/** * v1.3 splitter selection, keyed by chain AND protocol route. * * From v1.3 a chain carries one splitter per protocol route, because the fee * split is immutable at construction and the two protocols need different * economics: * * merchant-aifp1 (100/0) — the agent pays the quoted gross amount, the * AiFinPay treasury receives 1%, the merchant receives 99%. * agent-x402 (0/0) — the provider receives 100% of the provider-defined * price and the AiFinPay fee is 0% for now. This route is NOT fee-on-top; * fee-on-top semantics arrive in a future contract version. * * Selection must use both chain and route, and must never fall back from one * route to the other. That is not a style preference. The splitters were * deployed with CREATE, so an address derives from deployer and nonce and the * same address recurs on other chains for the other route: * * 0x1Fe2021336596655Fac72bC7bC40F7FFFA501d55 * is OP's merchant-aifp1 AND Base's agent-x402 * 0xF03B3387415D557b6ab709D06E8aF0b4ABD6Eb74 * is Unichain's merchant-aifp1, Avalanche's agent-x402, AND the legacy * v1.2 splitter on Optimism * * An address on its own therefore says nothing about which economics apply. * Resolving by chain alone would settle at the wrong fee split, silently, * and the amounts would still look plausible in every log. * * The table itself is NOT in this file. It is generated into * splitterRoutes.generated.ts from registry/splitter-table.json, a byte-for-byte * copy of the canonical artifact in AiFinPay/evm-contract, where every * payment-critical field — splitter, owner, treasury, both bps values, the * runtime code hash — was read from the chain by verify-registry.mjs. Two * repositories hand-maintaining the same payout addresses is the failure this * split prevents; `npm run registry:check` fails CI if they disagree. * * What stays here is the part worth reading: the types, the errors, and the two * resolvers. Logic belongs in a reviewed file, not in a generated one. */ import type { Chain } from "viem/chains"; export { SPLITTER_ROUTES, SPLITTER_GOVERNANCE, SPLITTER_REGISTRY_SOURCE } from "./generated/splitterRoutes.generated.js"; /** Protocol routes. A route is a fee profile fixed at construction. */ export type SplitterRoute = "merchant-aifp1" | "agent-x402"; /** * Chains carrying v1.3 route splitters. * @deprecated "botchain" is deprecated. Use "robinhood" instead. */ export type SplitterRouteChain = "amoy" | "polygon" | "optimism" | "bnb" | "unichain" | "botchain" | "base" | "arbitrum" | "avalanche" | "xrplevm"; /** Key into SPLITTER_ROUTES. Both halves are required. */ export type SplitterRouteKey = `${SplitterRouteChain}:${SplitterRoute}`; export interface SplitterRouteDeployment { chain: SplitterRouteChain; route: SplitterRoute; chainId: number; viemChain: Chain; splitter: `0x${string}`; /** * The governance Safe, read from the contract's own owner(). It controls * pause/unpause, the treasury address and the stablecoin whitelist, so it is * carried here rather than assumed: every other field is only as trustworthy * as whoever can change it. */ owner: `0x${string}`; /** Owner and treasury are the same governance Safe on every chain. */ treasury: `0x${string}`; /** Immutable, baked into runtime code. 100 = 1%. */ treasuryBps: number; ipCreatorBps: number; /** keccak-256 of the deployed runtime bytecode, read from chain. */ runtimeCodeHash: `0x${string}`; /** * Deployed and verified is not the same as payable. A route is enabled * individually, and only after a successful mainnet paid end-to-end * settlement on that exact route with verified balance deltas. */ settlementEnabled: boolean; /** Testnet entries require an explicit opt-in; they never activate mainnet. */ testnet: boolean; /** * How many independent RPC providers agreed on every field above when the * registry was verified. A route verified from one provider can never be * enabled — BOT Chain and XRPL EVM have exactly one public provider each. */ rpcQuorum: number; /** * Stablecoins the splitter accepts, read live via whitelistedTokens() and * owner-mutable, so pinned separately from the runtime hash. null = not * accepted on this chain; a chain with both null settles native only. */ stablecoins: { USDC: `0x${string}` | null; USDT: `0x${string}` | null; }; /** Policy review window. Outside it, a route must not settle. */ validFrom: string; validUntil: string; defaultRpc: string; explorer: string; /** The date the fields above were last read from the chain. */ verifiedAt: string; } export declare class UnknownSplitterRouteError extends Error { constructor(chain: string, route: string); } export declare class SplitterRouteNotSettlingError extends Error { constructor(key: string, reason: string); } /** * Resolve a splitter by chain AND route. Throws on an unknown pair rather * than falling back, because the fallback is the bug: every route resolves to * a real, deployed, working contract with the wrong economics. */ export declare function resolveSplitterRoute(chain: SplitterRouteChain | string, route: SplitterRoute | string): SplitterRouteDeployment; /** * Resolve a route that is cleared to move money. Separate from * resolveSplitterRoute on purpose: reading the registry and being allowed to * settle are different questions, and conflating them is how a disabled route * ends up paying. */ export declare function resolveSettlingSplitterRoute(chain: SplitterRouteChain | string, route: SplitterRoute | string, now?: Date, options?: { allowTestnet?: boolean; }): SplitterRouteDeployment; //# sourceMappingURL=splitterRoutes.d.ts.map