tax rate, version and compose (#70)
resolves #67 Co-authored-by: johba <johba@harb.eth> Reviewed-on: https://codeberg.org/johba/harb/pulls/70
This commit is contained in:
parent
d8ca557eb6
commit
6cbb1781ce
40 changed files with 1243 additions and 213 deletions
6
kraiken-lib/.lintstagedrc.json
Normal file
6
kraiken-lib/.lintstagedrc.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"src/**/*.ts": [
|
||||
"eslint --fix",
|
||||
"prettier --write"
|
||||
]
|
||||
}
|
||||
5
kraiken-lib/.prettierignore
Normal file
5
kraiken-lib/.prettierignore
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Auto-generated files
|
||||
src/taxRates.ts
|
||||
|
||||
# Generated TypeScript definitions
|
||||
src/__generated__/
|
||||
|
|
@ -14,6 +14,8 @@ Shared TypeScript helpers used by the landing app, txnBot, and other services to
|
|||
- `src/queries/` - GraphQL operations that target the Ponder schema.
|
||||
- `src/__generated__/graphql.ts` - Codegen output consumed throughout the stack.
|
||||
- `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.
|
||||
|
||||
## GraphQL Code Generation
|
||||
- Schema source points to the Ponder GraphQL endpoint for the active environment.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import tsParser from "@typescript-eslint/parser";
|
|||
export default [
|
||||
{
|
||||
files: ["src/**/*.ts"],
|
||||
ignores: ["src/tests/**/*", "src/__generated__/**/*"],
|
||||
ignores: ["src/tests/**/*", "src/__generated__/**/*", "src/taxRates.ts"],
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: { project: "./tsconfig.json" }
|
||||
|
|
|
|||
|
|
@ -45,6 +45,11 @@
|
|||
"types": "./dist/abis.d.ts",
|
||||
"require": "./dist/abis.js",
|
||||
"import": "./dist/abis.js"
|
||||
},
|
||||
"./version": {
|
||||
"types": "./dist/version.d.ts",
|
||||
"require": "./dist/version.js",
|
||||
"import": "./dist/version.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
|
|
|
|||
|
|
@ -22,3 +22,5 @@ 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, isCompatibleVersion, getVersionMismatchError } from './version.js';
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
/**
|
||||
* AUTO-GENERATED FILE — DO NOT EDIT
|
||||
*
|
||||
* Generated by scripts/sync-tax-rates.mjs from onchain/src/Stake.sol.
|
||||
* Run `node scripts/sync-tax-rates.mjs` after modifying the contract TAX_RATES array.
|
||||
*/
|
||||
|
||||
export interface TaxRateOption {
|
||||
index: number;
|
||||
year: number;
|
||||
|
|
@ -18,22 +25,42 @@ export const TAX_RATE_OPTIONS: TaxRateOption[] = [
|
|||
{ index: 9, year: 50, daily: 0.13699, decimal: 0.5 },
|
||||
{ index: 10, year: 60, daily: 0.16438, decimal: 0.6 },
|
||||
{ index: 11, year: 80, daily: 0.21918, decimal: 0.8 },
|
||||
{ index: 12, year: 100, daily: 0.27397, decimal: 1.0 },
|
||||
{ index: 12, year: 100, daily: 0.27397, decimal: 1 },
|
||||
{ index: 13, year: 130, daily: 0.35616, decimal: 1.3 },
|
||||
{ index: 14, year: 180, daily: 0.49315, decimal: 1.8 },
|
||||
{ index: 15, year: 250, daily: 0.68493, decimal: 2.5 },
|
||||
{ index: 16, year: 320, daily: 0.87671, decimal: 3.2 },
|
||||
{ index: 17, year: 420, daily: 1.15068, decimal: 4.2 },
|
||||
{ index: 18, year: 540, daily: 1.47945, decimal: 5.4 },
|
||||
{ index: 19, year: 700, daily: 1.91781, decimal: 7.0 },
|
||||
{ index: 19, year: 700, daily: 1.91781, decimal: 7 },
|
||||
{ index: 20, year: 920, daily: 2.52055, decimal: 9.2 },
|
||||
{ index: 21, year: 1200, daily: 3.28767, decimal: 12.0 },
|
||||
{ index: 22, year: 1600, daily: 4.38356, decimal: 16.0 },
|
||||
{ index: 23, year: 2000, daily: 5.47945, decimal: 20.0 },
|
||||
{ index: 24, year: 2600, daily: 7.12329, decimal: 26.0 },
|
||||
{ index: 25, year: 3400, daily: 9.31507, decimal: 34.0 },
|
||||
{ index: 26, year: 4400, daily: 12.05479, decimal: 44.0 },
|
||||
{ index: 27, year: 5700, daily: 15.61644, decimal: 57.0 },
|
||||
{ index: 28, year: 7500, daily: 20.54795, decimal: 75.0 },
|
||||
{ index: 29, year: 9700, daily: 26.57534, decimal: 97.0 },
|
||||
{ index: 21, year: 1200, daily: 3.28767, decimal: 12 },
|
||||
{ index: 22, year: 1600, daily: 4.38356, decimal: 16 },
|
||||
{ index: 23, year: 2000, daily: 5.47945, decimal: 20 },
|
||||
{ index: 24, year: 2600, daily: 7.12329, decimal: 26 },
|
||||
{ index: 25, year: 3400, daily: 9.31507, decimal: 34 },
|
||||
{ index: 26, year: 4400, daily: 12.05479, decimal: 44 },
|
||||
{ index: 27, year: 5700, daily: 15.61644, decimal: 57 },
|
||||
{ index: 28, year: 7500, daily: 20.54795, decimal: 75 },
|
||||
{ index: 29, year: 9700, daily: 26.57534, decimal: 97 }
|
||||
];
|
||||
|
||||
/**
|
||||
* Checksum of the contract TAX_RATES array (first 16 chars of SHA-256).
|
||||
* Used for runtime validation to ensure kraiken-lib is in sync with deployed contracts.
|
||||
*
|
||||
* To validate at runtime:
|
||||
* 1. Read TAX_RATES array from the Stake contract
|
||||
* 2. Compute checksum: sha256(values.join(',')).slice(0, 16)
|
||||
* 3. Compare with TAX_RATES_CHECKSUM
|
||||
*
|
||||
* If mismatch: Run `node scripts/sync-tax-rates.mjs` and rebuild kraiken-lib.
|
||||
*/
|
||||
export const TAX_RATES_CHECKSUM = '1e37f2312ef082e9';
|
||||
|
||||
/**
|
||||
* Array of raw year values (matches contract uint256[] TAX_RATES exactly).
|
||||
* Used for runtime validation without needing to parse options.
|
||||
*/
|
||||
export const TAX_RATES_RAW = [1, 3, 5, 8, 12, 18, 24, 30, 40, 50, 60, 80, 100, 130, 180, 250, 320, 420, 540, 700, 920, 1200, 1600, 2000, 2600, 3400, 4400, 5700, 7500, 9700];
|
||||
|
||||
|
|
|
|||
|
|
@ -6,4 +6,20 @@ describe('taxRates', () => {
|
|||
expect(TAX_RATE_OPTIONS.length).toBeGreaterThan(0);
|
||||
expect(TAX_RATE_OPTIONS[0]).toEqual(expect.objectContaining({ index: 0, year: 1, decimal: 0.01 }));
|
||||
});
|
||||
|
||||
test('tax rate options have required fields', () => {
|
||||
TAX_RATE_OPTIONS.forEach((option, idx) => {
|
||||
expect(option.index).toBe(idx);
|
||||
expect(option.year).toBeGreaterThan(0);
|
||||
expect(option.daily).toBeGreaterThan(0);
|
||||
expect(option.decimal).toBeGreaterThan(0);
|
||||
expect(option.decimal).toBe(option.year / 100);
|
||||
});
|
||||
});
|
||||
|
||||
test('tax rates are in ascending order', () => {
|
||||
for (let i = 1; i < TAX_RATE_OPTIONS.length; i++) {
|
||||
expect(TAX_RATE_OPTIONS[i].year).toBeGreaterThan(TAX_RATE_OPTIONS[i - 1].year);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
66
kraiken-lib/src/version.ts
Normal file
66
kraiken-lib/src/version.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Protocol version compatibility tracking.
|
||||
*
|
||||
* The Kraiken contract exposes a VERSION constant that must be checked
|
||||
* at runtime by indexers and frontends to ensure data compatibility.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Current version this library is built for.
|
||||
* Should match the deployed Kraiken contract VERSION.
|
||||
*/
|
||||
export const KRAIKEN_LIB_VERSION = 1;
|
||||
|
||||
/**
|
||||
* List of Kraiken contract versions this library is compatible with.
|
||||
*
|
||||
* - Indexers MUST validate contract.VERSION is in this list at startup
|
||||
* - Frontends SHOULD validate indexer version matches KRAIKEN_LIB_VERSION
|
||||
*
|
||||
* Version History:
|
||||
* - v1: Initial deployment (30-tier TAX_RATES, index-based staking)
|
||||
*/
|
||||
export const COMPATIBLE_CONTRACT_VERSIONS = [1];
|
||||
|
||||
/**
|
||||
* Validates if a contract version is compatible with this library.
|
||||
*/
|
||||
export function isCompatibleVersion(contractVersion: number): boolean {
|
||||
return COMPATIBLE_CONTRACT_VERSIONS.includes(contractVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Error message generator for version mismatches.
|
||||
*/
|
||||
export function getVersionMismatchError(contractVersion: number, context: 'ponder' | 'frontend'): string {
|
||||
const compatibleVersions = COMPATIBLE_CONTRACT_VERSIONS.join(', ');
|
||||
const instructions =
|
||||
context === 'ponder'
|
||||
? [
|
||||
'1. Check if contract was upgraded',
|
||||
'2. Update COMPATIBLE_CONTRACT_VERSIONS in kraiken-lib/src/version.ts',
|
||||
'3. Run: ./scripts/build-kraiken-lib.sh',
|
||||
'4. Run: rm -rf services/ponder/.ponder/',
|
||||
'5. Restart Ponder for full re-index',
|
||||
]
|
||||
: [
|
||||
'1. Contact administrator - indexer may need updating',
|
||||
'2. Try refreshing the page',
|
||||
'3. Check if contract was recently upgraded',
|
||||
];
|
||||
|
||||
const lines = [
|
||||
'╔════════════════════════════════════════════════════════════╗',
|
||||
`║ ❌ CRITICAL: VERSION MISMATCH (${context})`.padEnd(61) + '║',
|
||||
'╠════════════════════════════════════════════════════════════╣',
|
||||
`║ Contract VERSION: ${contractVersion}`.padEnd(61) + '║',
|
||||
`║ Library VERSION: ${KRAIKEN_LIB_VERSION}`.padEnd(61) + '║',
|
||||
`║ Compatible versions: ${compatibleVersions}`.padEnd(61) + '║',
|
||||
'║'.padEnd(61) + '║',
|
||||
'║ 📋 Required Actions:'.padEnd(61) + '║',
|
||||
...instructions.map(line => `║ ${line}`.padEnd(61) + '║'),
|
||||
'╚════════════════════════════════════════════════════════════╝',
|
||||
];
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue