feat: add ABI validation helpers for Ponder (#29)
resolves https://codeberg.org/johba/harb/issues/23 Co-authored-by: openhands <openhands@all-hands.dev> Reviewed-on: https://codeberg.org/johba/harb/pulls/29
This commit is contained in:
parent
0eaf91be13
commit
76d84341de
17 changed files with 2105 additions and 49 deletions
1
CLAUDE.md
Symbolic link
1
CLAUDE.md
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
AGENTS.md
|
||||
15
kraiken-lib/package-lock.json
generated
15
kraiken-lib/package-lock.json
generated
|
|
@ -19,6 +19,7 @@
|
|||
"@graphql-codegen/typescript-operations": "^4.2.0",
|
||||
"@graphql-typed-document-node/core": "^3.2.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^24.6.0",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.2",
|
||||
"typescript": "^5.4.3"
|
||||
|
|
@ -2887,13 +2888,13 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz",
|
||||
"integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==",
|
||||
"version": "24.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.6.0.tgz",
|
||||
"integrity": "sha512-F1CBxgqwOMc4GKJ7eY22hWhBVQuMYTtqI8L0FcszYcpYX0fzfDGpez22Xau8Mgm7O9fI+zA/TYIdq3tGWfweBA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
"undici-types": "~7.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/stack-utils": {
|
||||
|
|
@ -7904,9 +7905,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"version": "7.13.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.13.0.tgz",
|
||||
"integrity": "sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
"@graphql-codegen/typescript-operations": "^4.2.0",
|
||||
"@graphql-typed-document-node/core": "^3.2.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^24.6.0",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.2",
|
||||
"typescript": "^5.4.3"
|
||||
|
|
|
|||
25
kraiken-lib/src/abis.ts
Normal file
25
kraiken-lib/src/abis.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Contract ABIs extracted from forge build artifacts
|
||||
*
|
||||
* These ABIs are the single source of truth, generated from onchain/out/
|
||||
* To update: run `forge build` in onchain/ directory
|
||||
*/
|
||||
|
||||
const KraikenForgeOutput = require('../../onchain/out/Kraiken.sol/Kraiken.json');
|
||||
const StakeForgeOutput = require('../../onchain/out/Stake.sol/Stake.json');
|
||||
|
||||
/**
|
||||
* Kraiken ERC20 token contract ABI
|
||||
*/
|
||||
export const KraikenAbi = KraikenForgeOutput.abi;
|
||||
|
||||
/**
|
||||
* Stake (Harberger tax staking) contract ABI
|
||||
*/
|
||||
export const StakeAbi = StakeForgeOutput.abi;
|
||||
|
||||
// Re-export for convenience
|
||||
export const ABIS = {
|
||||
Kraiken: KraikenAbi,
|
||||
Stake: StakeAbi,
|
||||
} as const;
|
||||
|
|
@ -22,3 +22,5 @@ export {
|
|||
getSnatchList,
|
||||
isPositionDelinquent,
|
||||
} from "./helpers";
|
||||
|
||||
export { KraikenAbi, StakeAbi, ABIS } from "./abis";
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@
|
|||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"skipLibCheck": true,
|
||||
"types": []
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
|
|
|||
|
|
@ -1432,12 +1432,12 @@
|
|||
resolved "https://registry.npmjs.org/@types/json-stable-stringify/-/json-stable-stringify-1.0.36.tgz"
|
||||
integrity sha512-b7bq23s4fgBB76n34m2b3RBf6M369B0Z9uRR8aHTMd8kZISRkmDEpPD8hhpYvDFzr3bJCPES96cm3Q6qRNDbQw==
|
||||
|
||||
"@types/node@*", "@types/node@>=13":
|
||||
version "20.12.2"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz"
|
||||
integrity sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==
|
||||
"@types/node@*", "@types/node@^24.6.0", "@types/node@>=13":
|
||||
version "24.6.0"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-24.6.0.tgz"
|
||||
integrity sha512-F1CBxgqwOMc4GKJ7eY22hWhBVQuMYTtqI8L0FcszYcpYX0fzfDGpez22Xau8Mgm7O9fI+zA/TYIdq3tGWfweBA==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
undici-types "~7.13.0"
|
||||
|
||||
"@types/stack-utils@^2.0.0":
|
||||
version "2.0.3"
|
||||
|
|
@ -2387,6 +2387,11 @@ fs.realpath@^1.0.0:
|
|||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@^2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
|
||||
|
|
@ -4257,10 +4262,10 @@ unc-path-regex@^0.1.2:
|
|||
resolved "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz"
|
||||
integrity sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==
|
||||
|
||||
undici-types@~5.26.4:
|
||||
version "5.26.5"
|
||||
resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz"
|
||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||
undici-types@~7.13.0:
|
||||
version "7.13.0"
|
||||
resolved "https://registry.npmjs.org/undici-types/-/undici-types-7.13.0.tgz"
|
||||
integrity sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==
|
||||
|
||||
unixify@^1.0.0:
|
||||
version "1.0.0"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
- Tooling: Foundry (`forge build`, `forge test`, `forge fmt`, `forge snapshot`), Anvil for local chain, Base Sepolia deployment script (`forge script ...BaseSepoliaDeploy`).
|
||||
- Repo structure highlights: `src/` (core contracts), `test/helpers/` (Uniswap/Kraiken bases), `lib/uni-v3-lib` (math + JS setup), `script/` (deploy), `out/` (artifacts), config via `foundry.toml` & `remappings.txt`.
|
||||
- Setup steps: clone repo, init/update submodules, install `lib/uni-v3-lib` dependencies (yarn), ensure Foundry installed.
|
||||
- **ABI Architecture**: Contract ABIs are exported via `kraiken-lib/src/abis.ts`, which imports directly from `onchain/out/` (forge build artifacts). All consumers (ponder, web-app) import from kraiken-lib for type-safe, single-source-of-truth ABIs. Run `forge build` in `onchain/` to update ABIs across the stack.
|
||||
|
||||
## Strategy & Mechanics
|
||||
- Outstanding supply excludes liquidity position balances; enforce 20% staking cap (~20k positions).
|
||||
|
|
|
|||
1
onchain/CLAUDE.md
Symbolic link
1
onchain/CLAUDE.md
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
AGENTS.md
|
||||
1
services/ponder/CLAUDE.md
Symbolic link
1
services/ponder/CLAUDE.md
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
AGENTS.md
|
||||
2006
services/ponder/package-lock.json
generated
2006
services/ponder/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -7,17 +7,19 @@
|
|||
"dev": "ponder dev",
|
||||
"start": "ponder start",
|
||||
"codegen": "ponder codegen",
|
||||
"build": "tsc"
|
||||
"build": "ponder codegen"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ponder/core": "^0.7.17",
|
||||
"hono": "^4.5.0",
|
||||
"ponder": "^0.13.1",
|
||||
"kraiken-lib": "file:../../kraiken-lib",
|
||||
"ponder": "^0.13.6",
|
||||
"viem": "^2.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.30",
|
||||
"esbuild": "^0.25.10",
|
||||
"typescript": "^5.4.3"
|
||||
"typescript": "^5.9.2"
|
||||
},
|
||||
"overrides": {
|
||||
"esbuild": "^0.25.10",
|
||||
|
|
|
|||
6
services/ponder/ponder-env.d.ts
vendored
6
services/ponder/ponder-env.d.ts
vendored
|
|
@ -9,6 +9,12 @@ declare module "ponder:schema" {
|
|||
export * from "./ponder.schema.ts";
|
||||
}
|
||||
|
||||
declare module "*.json" {
|
||||
import type { Abi } from 'viem'
|
||||
const value: { abi: Abi }
|
||||
export default value
|
||||
}
|
||||
|
||||
// This file enables type checking and editor autocomplete for this Ponder project.
|
||||
// After upgrading, you may find that changes have been made to this file.
|
||||
// If this happens, please commit the changes. Do not manually edit this file.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,20 @@
|
|||
import { createConfig } from "ponder";
|
||||
import type { Abi } from "viem";
|
||||
import KraikenAbi from "./abis/Kraiken.json";
|
||||
import StakeAbi from "./abis/Stake.json";
|
||||
import { KraikenAbi, StakeAbi } from "kraiken-lib";
|
||||
|
||||
// Network configurations keyed by canonical environment name
|
||||
const networks = {
|
||||
type NetworkConfig = {
|
||||
chainId: number;
|
||||
rpc: string;
|
||||
disableCache?: boolean;
|
||||
contracts: {
|
||||
kraiken: string;
|
||||
stake: string;
|
||||
startBlock: number;
|
||||
};
|
||||
};
|
||||
|
||||
const networks: Record<string, NetworkConfig> = {
|
||||
BASE_SEPOLIA_LOCAL_FORK: {
|
||||
chainId: 31337,
|
||||
rpc: process.env.PONDER_RPC_URL_BASE_SEPOLIA_LOCAL_FORK || "http://127.0.0.1:8545",
|
||||
|
|
@ -33,7 +43,7 @@ const networks = {
|
|||
startBlock: 26038614,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
};
|
||||
|
||||
// Select network based on environment variable
|
||||
const NETWORK = (process.env.PONDER_NETWORK as keyof typeof networks) || "BASE_SEPOLIA_LOCAL_FORK";
|
||||
|
|
@ -57,18 +67,18 @@ export default createConfig({
|
|||
[NETWORK]: {
|
||||
id: selectedNetwork.chainId,
|
||||
rpc: selectedNetwork.rpc,
|
||||
disableCache: selectedNetwork.disableCache,
|
||||
disableCache: selectedNetwork.disableCache ?? false,
|
||||
},
|
||||
},
|
||||
contracts: {
|
||||
Kraiken: {
|
||||
abi: KraikenAbi.abi as Abi,
|
||||
abi: KraikenAbi satisfies Abi,
|
||||
chain: NETWORK,
|
||||
address: selectedNetwork.contracts.kraiken as `0x${string}`,
|
||||
startBlock: selectedNetwork.contracts.startBlock,
|
||||
},
|
||||
Stake: {
|
||||
abi: StakeAbi.abi as Abi,
|
||||
abi: StakeAbi satisfies Abi,
|
||||
chain: NETWORK,
|
||||
address: selectedNetwork.contracts.stake as `0x${string}`,
|
||||
startBlock: selectedNetwork.contracts.startBlock,
|
||||
|
|
|
|||
19
services/ponder/src/helpers/abi.ts
Normal file
19
services/ponder/src/helpers/abi.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import type { Abi } from 'viem'
|
||||
|
||||
/**
|
||||
* Helper function to ensure an imported ABI matches the viem Abi type at compile time
|
||||
* @param abi The ABI to validate
|
||||
* @returns The validated ABI
|
||||
*/
|
||||
export function validateAbi<T extends Abi>(abi: T): T {
|
||||
return abi
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to ensure an imported contract ABI matches the viem Abi type at compile time
|
||||
* @param contract The contract with an abi property to validate
|
||||
* @returns The validated contract ABI
|
||||
*/
|
||||
export function validateContractAbi<T extends { abi: Abi }>(contract: T): T['abi'] {
|
||||
return contract.abi
|
||||
}
|
||||
|
|
@ -10,8 +10,7 @@ import {
|
|||
type WaitForTransactionReceiptParameters,
|
||||
getChainId
|
||||
} from "@wagmi/core";
|
||||
// import { HarbContract } from "@/contracts/harb";
|
||||
import HarbJson from "@/assets/contracts/harb.json";
|
||||
import { KraikenAbi } from "kraiken-lib";
|
||||
import { type Abi, type Address } from "viem";
|
||||
import { StakeContract } from "@/contracts/stake";
|
||||
import {getChain} from "@/config"
|
||||
|
|
@ -36,13 +35,13 @@ export let HarbContract = getHarbJson();
|
|||
|
||||
function getHarbJson(){
|
||||
console.log("getHarbJson");
|
||||
|
||||
|
||||
const chainId = getChainId(config as any);
|
||||
console.log("chainId", chainId);
|
||||
|
||||
|
||||
const chain = getChain(chainId)
|
||||
|
||||
return {abi: HarbJson, contractAddress: chain?.harb} as Contract;
|
||||
|
||||
return {abi: KraikenAbi as Abi, contractAddress: chain?.harb} as Contract;
|
||||
}
|
||||
|
||||
export function setHarbContract(){
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { ref } from "vue";
|
||||
import { config } from "@/wagmi";
|
||||
import { readContract, writeContract, getChainId } from "@wagmi/core";
|
||||
import StakeJson from "@/assets/contracts/stake.json";
|
||||
import { StakeAbi } from "kraiken-lib";
|
||||
import { type Abi, type Address } from "viem";
|
||||
import {getChain} from "@/config"
|
||||
import logger from "@/utils/logger";
|
||||
|
|
@ -25,8 +25,8 @@ function getStakeJson(){
|
|||
console.log("chainId", chainId);
|
||||
|
||||
const chain = getChain(chainId)
|
||||
|
||||
return {abi: StakeJson, contractAddress: chain?.stake} as Contract;
|
||||
|
||||
return {abi: StakeAbi as Abi, contractAddress: chain?.stake} as Contract;
|
||||
}
|
||||
|
||||
export function setStakeContract(){
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue