refactor: migrate kraiken-lib to explicit subpath imports (BREAKING CHANGE) (#89)

Removes the barrel export pattern in favor of explicit subpath imports
for better tree-shaking and clearer dependencies.

## Breaking Changes
- Removed `src/helpers.ts` barrel export
- Removed `./helpers` from package.json exports
- Root `kraiken-lib` import now raises build errors
- Consumers MUST use explicit subpaths:
  - `kraiken-lib/abis` - Contract ABIs
  - `kraiken-lib/staking` - Staking helpers
  - `kraiken-lib/snatch` - Snatch selection
  - `kraiken-lib/ids` - Position ID utilities
  - `kraiken-lib/subgraph` - Byte conversion utilities
  - `kraiken-lib/taxRates` - Tax rate constants
  - `kraiken-lib/version` - Version validation

## Changes
- kraiken-lib:
  - Bumped version to 1.0.0 (breaking change)
  - Updated src/index.ts to raise build errors
  - Added backward-compatible ABI aliases (KraikenAbi, StakeAbi)
  - Updated all test files to use .js extensions and new imports
  - Updated documentation (README, AGENTS.md)

- Consumer updates:
  - services/ponder: Updated ponder.config.ts to use kraiken-lib/abis
  - web-app: Updated all imports to use subpaths
    - composables/usePositions.ts: kraiken-lib/subgraph
    - contracts/harb.ts: kraiken-lib/abis
    - contracts/stake.ts: kraiken-lib/abis

## Migration Guide
```typescript
// OLD
import { getSnatchList } from 'kraiken-lib/helpers';
import { KraikenAbi } from 'kraiken-lib';

// NEW
import { getSnatchList } from 'kraiken-lib/snatch';
import { KraikenAbi } from 'kraiken-lib/abis';
```

Fixes #86

Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/89
This commit is contained in:
johba 2025-11-20 18:54:53 +01:00
parent 1c6f118f6b
commit a555a2fdd1
18 changed files with 74 additions and 74 deletions

View file

@ -8,11 +8,10 @@ Shared TypeScript helpers used by the landing app, txnBot, and other services to
- Centralise staking math (tax calculations, snatch selection, share conversions) for reuse across clients.
## Key Modules
- `src/kraiken.ts` - Token-facing helpers and supply utilities.
- `src/stake.ts` - Staking math, Harberger tax helpers, snatch scoring.
- `src/chains.ts` - Chain constants and deployment metadata.
- `src/queries/` - GraphQL operations that target the Ponder schema.
- `src/__generated__/graphql.ts` - Codegen output consumed throughout the stack.
- `src/staking.ts` - Harberger staking helpers for delinquency checks and snatch math.
- `src/snatch.ts` - Snatch selection engine and supporting types.
- `src/ids.ts` - Position ID encoding helpers.
- `src/subgraph.ts` - Byte utilities shared between the GraphQL layer and clients.
- `src/abis.ts` - Contract ABIs imported directly from `onchain/out/` forge artifacts. Single source of truth for all ABI consumers.
- `src/taxRates.ts` - Generated from `onchain/src/Stake.sol` by `scripts/sync-tax-rates.mjs`; never edit by hand.
- `src/version.ts` - Version validation system tracking `KRAIKEN_LIB_VERSION` and `COMPATIBLE_CONTRACT_VERSIONS` for runtime dependency checking.
@ -29,13 +28,18 @@ Shared TypeScript helpers used by the landing app, txnBot, and other services to
- `npm test` - Execute Jest suite for helper coverage.
## Integration Notes
- Landing app consumes helpers for UI projections and staking copy.
- txnBot relies on the same helpers to evaluate profitability and tax windows.
- Landing app consumes `kraiken-lib/abis`, `kraiken-lib/staking`, and `kraiken-lib/subgraph` for ABI resolution and ID conversion.
- txnBot relies on `kraiken-lib/staking` and `kraiken-lib/ids` to evaluate profitability and tax windows.
- Ponder imports `kraiken-lib/abis` for indexing, and `kraiken-lib/version` for cross-service version checks.
- When the Ponder schema changes, rerun `npm run compile` and commit regenerated types to prevent drift.
## Import Guidance
- The legacy `helpers.ts` barrel has been removed. Always import from the narrow subpaths (e.g. `kraiken-lib/abis`, `kraiken-lib/staking`, `kraiken-lib/snatch`, `kraiken-lib/subgraph`).
- Avoid importing `kraiken-lib` directly; the root module no longer re-exports the helper surface and exists only to raise build-time errors for bundle imports.
## ES Module Architecture
- **Module Type**: This package is built as ES modules (`"type": "module"` in package.json). All consumers must support ES modules.
- **Import Extensions**: All relative imports in TypeScript source files MUST include `.js` extensions (e.g., `from "./helpers.js"`). This is required for ES module resolution even though the source files are `.ts`.
- **Import Extensions**: All relative imports in TypeScript source files MUST include `.js` extensions (e.g., `from "./staking.js"`). This is required for ES module resolution even though the source files are `.ts`.
- **JSON Imports**: JSON files (like ABI artifacts) must use import assertions: `import Foo from './path.json' assert { type: 'json' }`.
- **TypeScript Config**: `tsconfig.json` must specify:
- `"module": "esnext"` - Generate ES module syntax

View file

@ -16,7 +16,7 @@ yarn add kraiken-lib
then
```
import { bytesToUint256LittleEndian, uint256ToBytesLittleEndian } from "kraiken-lib";
import { bytesToUint256LittleEndian, uint256ToBytesLittleEndian } from "kraiken-lib/subgraph";
uint256ToBytesLittleEndian(3n);
```
@ -24,7 +24,7 @@ uint256ToBytesLittleEndian(3n);
## get Snatch List
```
import { getSnatchList } from "kraiken-lib";
import { getSnatchList } from "kraiken-lib/snatch";
const positionIds = getSnatchList(positions, neededShares, maxTaxRateDecimal, stakeTotalSupply);
```

View file

@ -1,6 +1,6 @@
{
"name": "kraiken-lib",
"version": "0.2.0",
"version": "1.0.0",
"description": "helper functions and snatch selection",
"type": "module",
"main": "dist/index.js",
@ -11,11 +11,6 @@
"require": "./dist/index.js",
"import": "./dist/index.js"
},
"./helpers": {
"types": "./dist/helpers.d.ts",
"require": "./dist/helpers.js",
"import": "./dist/helpers.js"
},
"./ids": {
"types": "./dist/ids.d.ts",
"require": "./dist/ids.js",

View file

@ -23,3 +23,9 @@ export const ABIS = {
Kraiken: KRAIKEN_ABI,
Stake: STAKE_ABI,
} as const;
// Backward-compatible aliases
// eslint-disable-next-line @typescript-eslint/naming-convention
export const KraikenAbi = KRAIKEN_ABI;
// eslint-disable-next-line @typescript-eslint/naming-convention
export const StakeAbi = STAKE_ABI;

View file

@ -1,4 +0,0 @@
export * from './staking.js';
export * from './snatch.js';
export * from './ids.js';
export * from './taxRates.js';

View file

@ -1,32 +1,5 @@
export { bytesToUint256LittleEndian, uint256ToBytesLittleEndian } from './subgraph.js';
// Backward compatible aliases
export { bytesToUint256LittleEndian as bytesToUint256, uint256ToBytesLittleEndian as uint256ToBytes } from './subgraph.js';
export { TAX_RATE_OPTIONS, type TaxRateOption } from './taxRates.js';
export { calculateSnatchShortfall, isPositionDelinquent } from './staking.js';
export {
minimumTaxRate,
selectSnatchPositions,
getSnatchList,
type SnatchablePosition,
type SnatchSelectionOptions,
type SnatchSelectionResult,
} from './snatch.js';
export { decodePositionId } from './ids.js';
export { KRAIKEN_ABI, STAKE_ABI, ABIS } from './abis.js';
// Backward compatible aliases
export { KRAIKEN_ABI as KraikenAbi, STAKE_ABI as StakeAbi } from './abis.js';
export {
KRAIKEN_LIB_VERSION,
COMPATIBLE_CONTRACT_VERSIONS,
STACK_META_ID,
isCompatibleVersion,
getVersionMismatchError,
} from './version.js';
/**
* kraiken-lib no longer exposes a bundled helper surface.
* Import from explicit subpaths such as `kraiken-lib/staking`.
*/
export {};

View file

@ -1,5 +1,5 @@
import { describe, expect, test } from '@jest/globals';
import { bytesToUint256LittleEndian, uint256ToBytesLittleEndian } from '../subgraph';
import { bytesToUint256LittleEndian, uint256ToBytesLittleEndian } from '../subgraph.js';
describe('BigInt Conversion Functions', () => {
test('converts uint256 to bytes and back (little endian)', async () => {

View file

@ -1,6 +1,6 @@
import { describe, expect, test } from '@jest/globals';
import { decodePositionId } from '../ids';
import { uint256ToBytesLittleEndian } from '../subgraph';
import { decodePositionId } from '../ids.js';
import { uint256ToBytesLittleEndian } from '../subgraph.js';
describe('ids', () => {
test('decodePositionId works across representations', () => {

View file

@ -1,6 +1,7 @@
import { describe, expect, test } from '@jest/globals';
import { getSnatchList, minimumTaxRate, selectSnatchPositions, type SnatchablePosition } from '../snatch';
import type { Positions } from '../__generated__/graphql';
import { getSnatchList, minimumTaxRate, selectSnatchPositions, type SnatchablePosition } from '../snatch.js';
import { uint256ToBytesLittleEndian } from '../subgraph.js';
import type { Positions as GraphPosition } from '../__generated__/graphql.js';
describe('snatch', () => {
test('minimumTaxRate finds the lowest tax', () => {
@ -44,17 +45,17 @@ describe('snatch', () => {
test('getSnatchList converts subgraph positions', () => {
const stakeTotalSupply = 1_000_000n * 10n ** 18n;
const positions: Positions[] = [
const positions = [
{
__typename: 'positions',
id: '0x01',
id: uint256ToBytesLittleEndian(1n),
owner: '0xowner1',
share: 0.0001,
creationTime: '0',
lastTaxTime: '0',
taxRate: 0.02,
status: 'Active',
createdAt: '0',
createdAt: 0,
kraikenDeposit: '0',
payout: '0',
snatched: 0,
@ -64,14 +65,14 @@ describe('snatch', () => {
},
{
__typename: 'positions',
id: '0x02',
id: uint256ToBytesLittleEndian(2n),
owner: '0xowner2',
share: 0.0002,
creationTime: '0',
lastTaxTime: '0',
taxRate: 0.01,
status: 'Active',
createdAt: '0',
createdAt: 0,
kraikenDeposit: '0',
payout: '0',
snatched: 0,
@ -79,7 +80,7 @@ describe('snatch', () => {
taxPaid: '0',
totalSupplyInit: '0',
},
];
] as unknown as GraphPosition[];
const result = getSnatchList(positions, 10n ** 18n, 0.05, stakeTotalSupply);

View file

@ -1,5 +1,5 @@
import { describe, expect, test } from '@jest/globals';
import { calculateSnatchShortfall, isPositionDelinquent } from '../staking';
import { calculateSnatchShortfall, isPositionDelinquent } from '../staking.js';
describe('staking', () => {
test('calculateSnatchShortfall returns zero when within cap', () => {

View file

@ -1,5 +1,5 @@
import { describe, expect, test } from '@jest/globals';
import { TAX_RATE_OPTIONS } from '../taxRates';
import { TAX_RATE_OPTIONS } from '../taxRates.js';
describe('taxRates', () => {
test('tax rate options exported for consumers', () => {