hookr-sdk 0.2.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/LICENSE +21 -0
  3. package/MIGRATING.md +89 -0
  4. package/README.md +286 -105
  5. package/dist/core/abi.d.ts +10930 -0
  6. package/dist/core/abi.js +455 -0
  7. package/dist/core/advisories.d.ts +184 -0
  8. package/dist/core/advisories.js +291 -0
  9. package/dist/core/client.d.ts +55 -0
  10. package/dist/core/client.js +107 -0
  11. package/dist/core/generated.d.ts +14295 -0
  12. package/dist/core/generated.js +1058 -0
  13. package/dist/core/index.d.ts +17 -0
  14. package/dist/core/index.js +17 -0
  15. package/dist/core/launch.d.ts +200 -0
  16. package/dist/core/launch.js +427 -0
  17. package/dist/core/pair.d.ts +64 -0
  18. package/dist/core/pair.js +136 -0
  19. package/dist/core/params.d.ts +415 -0
  20. package/dist/core/params.js +1235 -0
  21. package/dist/core/policies.d.ts +136 -0
  22. package/dist/core/policies.js +125 -0
  23. package/dist/core/proofs.d.ts +25 -0
  24. package/dist/core/proofs.js +118 -0
  25. package/dist/core/quotes.d.ts +185 -0
  26. package/dist/core/quotes.js +550 -0
  27. package/dist/core/referrals.d.ts +32 -0
  28. package/dist/core/referrals.js +36 -0
  29. package/dist/core/registry.d.ts +357 -0
  30. package/dist/core/registry.js +378 -0
  31. package/dist/core/rules.d.ts +675 -0
  32. package/dist/core/rules.js +1049 -0
  33. package/dist/core/schema.d.ts +358 -0
  34. package/dist/core/schema.js +105 -0
  35. package/dist/core/stocks.generated.d.ts +11 -0
  36. package/dist/core/stocks.generated.js +1228 -0
  37. package/dist/core/vault.d.ts +59 -0
  38. package/dist/core/vault.js +112 -0
  39. package/dist/core/wallet.d.ts +142 -0
  40. package/dist/core/wallet.js +304 -0
  41. package/dist/deployments.d.ts +8 -0
  42. package/dist/deployments.js +26 -0
  43. package/dist/index.d.ts +6 -15
  44. package/dist/index.js +6 -15
  45. package/dist/releases.d.ts +172 -0
  46. package/dist/releases.js +268 -0
  47. package/package.json +46 -10
  48. package/provenance.json +31 -0
  49. package/dist/abi.d.ts +0 -6404
  50. package/dist/abi.js +0 -8300
  51. package/dist/chain.d.ts +0 -87
  52. package/dist/chain.js +0 -86
  53. package/dist/claims.d.ts +0 -32
  54. package/dist/claims.js +0 -31
  55. package/dist/fees.d.ts +0 -59
  56. package/dist/fees.js +0 -142
  57. package/dist/links.d.ts +0 -48
  58. package/dist/links.js +0 -93
  59. package/dist/market.d.ts +0 -264
  60. package/dist/market.js +0 -310
  61. package/dist/reads.d.ts +0 -136
  62. package/dist/reads.js +0 -219
  63. package/dist/rules.d.ts +0 -84
  64. package/dist/rules.js +0 -296
  65. package/dist/swap.d.ts +0 -108
  66. package/dist/swap.js +0 -144
@@ -0,0 +1,59 @@
1
+ import { type Address, type Call, type DeploymentManifest, type Hash } from "./schema.js";
2
+ import { type PoolKey } from "./wallet.js";
3
+ /** HookrLiquidityVault.DepositParams. The vault charges exactly what the pool requires, never more than desired. */
4
+ export interface VaultDeposit {
5
+ key: PoolKey;
6
+ tickLower: number;
7
+ tickUpper: number;
8
+ amount0Desired: bigint;
9
+ amount1Desired: bigint;
10
+ amount0Min: bigint;
11
+ amount1Min: bigint;
12
+ recipient: Address;
13
+ deadline: bigint;
14
+ }
15
+ /** HookrLiquidityVault.WithdrawParams. Minimums bound the principal returned, excluding fees. */
16
+ export interface VaultWithdraw {
17
+ key: PoolKey;
18
+ tickLower: number;
19
+ tickUpper: number;
20
+ liquidity: bigint;
21
+ amount0Min: bigint;
22
+ amount1Min: bigint;
23
+ recipient: Address;
24
+ deadline: bigint;
25
+ }
26
+ /** Uniswap v4 PoolId of any pool key (static or dynamic fee): the vault serves every v4 pool. */
27
+ export declare function v4PoolId(key: PoolKey): Hash;
28
+ /** HookrLiquidityVault.rangeId: the ERC-6909 share id of (pool, tickLower, tickUpper). */
29
+ export declare function vaultRangeId(poolId: Hash, tickLower: number, tickUpper: number): bigint;
30
+ /**
31
+ * Deposits into a range and mints shares equal to the liquidity added. A native currency0 is paid as the call
32
+ * value (`amount0Desired`); the vault refunds what the pool did not take. ERC-20 amounts need an approval of the
33
+ * vault first.
34
+ */
35
+ export declare function buildVaultDeposit(m: DeploymentManifest, p: VaultDeposit, now?: bigint): Call;
36
+ /** Burns the caller's shares and pays the principal plus the caller's realised fees in the range. */
37
+ export declare function buildVaultWithdraw(m: DeploymentManifest, p: VaultWithdraw, now?: bigint): Call;
38
+ /** Realises the range's fees and pays the caller's fees to `to`. Principal is untouched. */
39
+ export declare function buildVaultClaim(m: DeploymentManifest, key: PoolKey, tickLower: number, tickUpper: number, to: Address): Call;
40
+ /** Realises the range's accrued fees into its per-share accumulators. Permissionless. */
41
+ export declare function buildVaultPoke(m: DeploymentManifest, key: PoolKey, tickLower: number, tickUpper: number): Call;
42
+ /** Pays the vault's skimmed fees in `currency` to its immutable protocol recipient. Permissionless. */
43
+ export declare function buildVaultCollectProtocolFees(m: DeploymentManifest, currency: Address): Call;
44
+ /** Pulls the treasury's claim from an admitted source (a pinned HookrRules or HookrLiquidityVault). Permissionless. */
45
+ export declare function buildTreasuryCollect(m: DeploymentManifest, from: Address, currency: Address): Call;
46
+ /** Pulls the treasury's claim from an admitted source straight to the treasury target. */
47
+ export declare function buildTreasuryCollectTo(m: DeploymentManifest, from: Address, currency: Address): Call;
48
+ /**
49
+ * Moves the treasury's HookrRules claim to the treasury target as PoolManager ERC-6909 claims of `currency`; the
50
+ * exit for a quote that stops delivering exact amounts. Only the treasury owner or the current target may send it.
51
+ */
52
+ export declare function buildTreasuryCollectAsClaims(m: DeploymentManifest, rules: Address, currency: Address): Call;
53
+ /** Retries deferred protocol funds, or forwards an unassigned balance, to the treasury target. */
54
+ export declare function buildTreasuryForward(m: DeploymentManifest, currency: Address): Call;
55
+ /**
56
+ * Pays the caller's whole HookrRules claim (royalty, refund or advisory fee) to `to` as PoolManager ERC-6909 claims.
57
+ * Moves no token; `to` redeems through any PoolManager unlock.
58
+ */
59
+ export declare function buildRulesClaimAsClaims(m: DeploymentManifest, rules: Address, currency: Address, to: Address): Call;
@@ -0,0 +1,112 @@
1
+ import { encodeAbiParameters, keccak256 } from "viem";
2
+ import { ARTIFACT_ABIS } from "./generated.js";
3
+ import { address, assert, hash, uint, ZERO, } from "./schema.js";
4
+ import { buildCall, buildCallTo, contract, pinned } from "./wallet.js";
5
+ const vaultAbi = ARTIFACT_ABIS.HookrLiquidityVault;
6
+ const MAX_AMOUNT = (1n << 127n) - 1n;
7
+ /** Uniswap v4 PoolId of any pool key (static or dynamic fee): the vault serves every v4 pool. */
8
+ export function v4PoolId(key) {
9
+ const c0 = address(key.currency0, true);
10
+ const c1 = address(key.currency1);
11
+ assert(BigInt(c0) < BigInt(c1), "Unsorted pool currencies");
12
+ assert(Number.isInteger(key.fee) && key.fee >= 0 && key.fee <= 0x800000, "Invalid pool fee");
13
+ assert(Number.isInteger(key.tickSpacing) && key.tickSpacing > 0 && key.tickSpacing <= 32767, "Invalid tick spacing");
14
+ return keccak256(encodeAbiParameters([{ type: "address" }, { type: "address" }, { type: "uint24" }, { type: "int24" }, { type: "address" }], [c0, c1, key.fee, key.tickSpacing, address(key.hooks, true)]));
15
+ }
16
+ /** HookrLiquidityVault.rangeId: the ERC-6909 share id of (pool, tickLower, tickUpper). */
17
+ export function vaultRangeId(poolId, tickLower, tickUpper) {
18
+ checkRange(tickLower, tickUpper);
19
+ return BigInt(keccak256(encodeAbiParameters([{ type: "bytes32" }, { type: "int24" }, { type: "int24" }], [hash(poolId), tickLower, tickUpper])));
20
+ }
21
+ function checkRange(tickLower, tickUpper) {
22
+ assert(Number.isInteger(tickLower) && Number.isInteger(tickUpper) && tickLower >= -887272 && tickUpper <= 887272, "Tick out of range");
23
+ assert(tickLower < tickUpper, "Invalid range");
24
+ }
25
+ /** The vault refuses the zero address, itself and the PoolManager as recipient. */
26
+ function recipient(m, to) {
27
+ const r = address(to);
28
+ assert(r !== contract(m, "liquidityVault"), "Vault cannot receive");
29
+ assert(!m.contracts.some((c) => c.role === "poolManager" && c.address === r), "PoolManager cannot receive");
30
+ return r;
31
+ }
32
+ function deadline(value, now) {
33
+ assert(uint(value) >= now, "Deadline passed");
34
+ return value;
35
+ }
36
+ /**
37
+ * Deposits into a range and mints shares equal to the liquidity added. A native currency0 is paid as the call
38
+ * value (`amount0Desired`); the vault refunds what the pool did not take. ERC-20 amounts need an approval of the
39
+ * vault first.
40
+ */
41
+ export function buildVaultDeposit(m, p, now = BigInt(Math.floor(Date.now() / 1000))) {
42
+ v4PoolId(p.key);
43
+ checkRange(p.tickLower, p.tickUpper);
44
+ for (const v of [p.amount0Desired, p.amount1Desired])
45
+ assert(uint(v) <= MAX_AMOUNT, "Amount above int128");
46
+ assert(p.amount0Desired > 0n || p.amount1Desired > 0n, "Empty deposit");
47
+ assert(uint(p.amount0Min) <= p.amount0Desired && uint(p.amount1Min) <= p.amount1Desired, "Minimum above desired");
48
+ const params = { ...p, recipient: recipient(m, p.recipient), deadline: deadline(p.deadline, now) };
49
+ const value = address(p.key.currency0, true) === ZERO ? p.amount0Desired : 0n;
50
+ return buildCall(m, "liquidityVault", vaultAbi, "deposit", [params], value);
51
+ }
52
+ /** Burns the caller's shares and pays the principal plus the caller's realised fees in the range. */
53
+ export function buildVaultWithdraw(m, p, now = BigInt(Math.floor(Date.now() / 1000))) {
54
+ v4PoolId(p.key);
55
+ checkRange(p.tickLower, p.tickUpper);
56
+ assert(uint(p.liquidity, 128) > 0n, "Empty withdrawal");
57
+ uint(p.amount0Min);
58
+ uint(p.amount1Min);
59
+ const params = { ...p, recipient: recipient(m, p.recipient), deadline: deadline(p.deadline, now) };
60
+ return buildCall(m, "liquidityVault", vaultAbi, "withdraw", [params]);
61
+ }
62
+ /** Realises the range's fees and pays the caller's fees to `to`. Principal is untouched. */
63
+ export function buildVaultClaim(m, key, tickLower, tickUpper, to) {
64
+ v4PoolId(key);
65
+ checkRange(tickLower, tickUpper);
66
+ return buildCall(m, "liquidityVault", vaultAbi, "claim", [key, tickLower, tickUpper, recipient(m, to)]);
67
+ }
68
+ /** Realises the range's accrued fees into its per-share accumulators. Permissionless. */
69
+ export function buildVaultPoke(m, key, tickLower, tickUpper) {
70
+ v4PoolId(key);
71
+ checkRange(tickLower, tickUpper);
72
+ return buildCall(m, "liquidityVault", vaultAbi, "poke", [key, tickLower, tickUpper]);
73
+ }
74
+ /** Pays the vault's skimmed fees in `currency` to its immutable protocol recipient. Permissionless. */
75
+ export function buildVaultCollectProtocolFees(m, currency) {
76
+ return buildCall(m, "liquidityVault", vaultAbi, "collectProtocolFees", [address(currency, true)]);
77
+ }
78
+ const treasuryAbi = ARTIFACT_ABIS.HookrTreasury;
79
+ function source(m, s) {
80
+ const a = address(s);
81
+ assert(m.contracts.some((c) => (c.role === "rules" || c.role === "liquidityVault") && c.address === a), "Unqualified treasury source");
82
+ return a;
83
+ }
84
+ /** Pulls the treasury's claim from an admitted source (a pinned HookrRules or HookrLiquidityVault). Permissionless. */
85
+ export function buildTreasuryCollect(m, from, currency) {
86
+ return buildCall(m, "treasury", treasuryAbi, "collect", [source(m, from), address(currency, true)]);
87
+ }
88
+ /** Pulls the treasury's claim from an admitted source straight to the treasury target. */
89
+ export function buildTreasuryCollectTo(m, from, currency) {
90
+ return buildCall(m, "treasury", treasuryAbi, "collectTo", [source(m, from), address(currency, true)]);
91
+ }
92
+ /**
93
+ * Moves the treasury's HookrRules claim to the treasury target as PoolManager ERC-6909 claims of `currency`; the
94
+ * exit for a quote that stops delivering exact amounts. Only the treasury owner or the current target may send it.
95
+ */
96
+ export function buildTreasuryCollectAsClaims(m, rules, currency) {
97
+ return buildCall(m, "treasury", treasuryAbi, "collectAsClaims", [pinned(m, "rules", rules), address(currency, true)]);
98
+ }
99
+ /** Retries deferred protocol funds, or forwards an unassigned balance, to the treasury target. */
100
+ export function buildTreasuryForward(m, currency) {
101
+ return buildCall(m, "treasury", treasuryAbi, "forwardBalance", [address(currency, true)]);
102
+ }
103
+ /**
104
+ * Pays the caller's whole HookrRules claim (royalty, refund or advisory fee) to `to` as PoolManager ERC-6909 claims.
105
+ * Moves no token; `to` redeems through any PoolManager unlock.
106
+ */
107
+ export function buildRulesClaimAsClaims(m, rules, currency, to) {
108
+ const r = pinned(m, "rules", rules);
109
+ const recipient = address(to);
110
+ assert(recipient !== r && !m.contracts.some((c) => c.role === "poolManager" && c.address === recipient), "Invalid claim recipient");
111
+ return buildCallTo(m, r, ARTIFACT_ABIS.HookrRules, "claimAsClaims", [address(currency, true), recipient]);
112
+ }
@@ -0,0 +1,142 @@
1
+ import { type Abi, type Hex } from "viem";
2
+ import { type Address, type Call, type ContractRole, type DeploymentManifest, type Hash } from "./schema.js";
3
+ export interface PoolKey {
4
+ currency0: Address;
5
+ currency1: Address;
6
+ fee: number;
7
+ tickSpacing: number;
8
+ hooks: Address;
9
+ }
10
+ export interface Swap {
11
+ key: PoolKey;
12
+ zeroForOne: boolean;
13
+ amountSpecified: bigint;
14
+ amountBound: bigint;
15
+ sqrtPriceLimitX96: bigint;
16
+ recipient: Address;
17
+ deadline: bigint;
18
+ }
19
+ export declare function poolId(key: PoolKey): Hash;
20
+ export declare function contract(m: DeploymentManifest, role: ContractRole): Address;
21
+ /** Returns `target` when the manifest pins it under `role` (roles such as `root` and `rules` may repeat). */
22
+ export declare function pinned(m: DeploymentManifest, role: ContractRole, target: Address): Address;
23
+ export declare function buildCall(m: DeploymentManifest, role: ContractRole, abi: Abi, name: string, args: readonly unknown[], value?: bigint): Call;
24
+ /** buildCall for an explicit pinned address; callers check the pin (`pinned`). */
25
+ export declare function buildCallTo(m: DeploymentManifest, to: Address, abi: Abi, name: string, args: readonly unknown[], value?: bigint): Call;
26
+ export declare function buildSwap(m: DeploymentManifest, s: Swap, programIds?: bigint[], now?: bigint): Call;
27
+ export declare function buildQuote(m: DeploymentManifest, s: Swap, payer: Address, now?: bigint): Call;
28
+ export declare function buildLaunch(m: DeploymentManifest, token: {
29
+ existing: Address;
30
+ name: string;
31
+ symbol: string;
32
+ supply: bigint;
33
+ salt: Hash;
34
+ }, root: Address, members: readonly Record<string, unknown>[], nativeBudget: bigint, deadline: bigint, launchFee: bigint): Call;
35
+ /**
36
+ * launch, where member i binds its admitted advisory with the exact bytes `advisoryConfigs[i]` (for example
37
+ * `encodeFeeAdvisoryConfig` or `encodeSessionSchedule`). A member without an advisory passes "0x".
38
+ */
39
+ export declare function buildLaunchAdvised(m: DeploymentManifest, token: {
40
+ existing: Address;
41
+ name: string;
42
+ symbol: string;
43
+ supply: bigint;
44
+ salt: Hash;
45
+ }, root: Address, members: readonly Record<string, unknown>[], advisoryConfigs: readonly Hash[], nativeBudget: bigint, deadline: bigint, launchFee: bigint): Call;
46
+ /** HookrLaunchChecks.MAX_LAUNCH_FEE: the most a launch fee can be, 0.01 of the native currency. */
47
+ export declare const MAX_LAUNCH_FEE: bigint;
48
+ /**
49
+ * The launch fee a launch's native value carries on top of its native budgets (r31, IHookrLaunchFee): HookrLauncher
50
+ * refuses any other value (InvalidFunding). Read it at the launch block (`encodeLaunchFeeCall`, `decodeLaunchFee`);
51
+ * it is zero at genesis and changes only by the registry owner's timelocked proposal, at most MAX_LAUNCH_FEE.
52
+ */
53
+ export declare function checkLaunchFee(launchFee: bigint): bigint;
54
+ /** HookrLauncher.launchFee() (IHookrLaunchFee, served by the launcher's fallback): the fee now and a pending change. */
55
+ export interface LaunchFee {
56
+ fee: bigint;
57
+ treasury: Address;
58
+ pendingFee: bigint;
59
+ pendingTreasury: Address;
60
+ readyAt: bigint;
61
+ }
62
+ /** The eth_call data that reads the launch fee from the launcher (`decodeLaunchFee` reads the answer). */
63
+ export declare function encodeLaunchFeeCall(): Hex;
64
+ /** Decodes launchFee()'s five words, refusing a fee above MAX_LAUNCH_FEE. */
65
+ export declare function decodeLaunchFee(data: Hex): LaunchFee;
66
+ /** Refuses advisory configs launchAdvised and launchWithBuy would refuse: one per member, "0x" without an advisory. */
67
+ export declare function checkAdvisoryConfigs(members: readonly Record<string, unknown>[], advisoryConfigs: readonly Hash[]): void;
68
+ /**
69
+ * Refuses a launch the Launcher would refuse before any pool opens: an unqualified root, a family of 0 or more than 8,
70
+ * a malformed token, an expired deadline, an empty member, or a native budget other than the native members' maxima.
71
+ */
72
+ /**
73
+ * HookrLauncher.Member.recapture that launches a member without the recapture lane. Any config with `on` set makes the
74
+ * member's pool freeze the root's open lane at initialization, and the launch reverts while the root has none.
75
+ */
76
+ export declare const RECAPTURE_OFF: Readonly<{
77
+ on: false;
78
+ traderBps: 0;
79
+ lpBps: 0;
80
+ period: 0;
81
+ maxPrizeBps: 0;
82
+ potReleaseBps: 0;
83
+ minBuyQuote: 0n;
84
+ releaseBlocks: 0;
85
+ }>;
86
+ /**
87
+ * HookrRecapture's release period bounds and default (RecaptureConfig.releaseBlocks), in L2 blocks: Robinhood Chain's
88
+ * own block number (ArbSys.arbBlockNumber), about 10 a second, so about 2 minutes, 24 hours and, by default, an hour.
89
+ * The release also counts at most `l2PerSecond` L2 blocks per second of block time. A member with recapture on and a
90
+ * period outside the bounds is refused at bind (InvalidConfig).
91
+ */
92
+ export declare const RECAPTURE_RELEASE_BLOCKS: Readonly<{
93
+ min: number;
94
+ default: number;
95
+ max: number;
96
+ l2PerSecond: number;
97
+ }>;
98
+ export declare function checkLaunch(m: DeploymentManifest, token: {
99
+ existing: Address;
100
+ name: string;
101
+ symbol: string;
102
+ supply: bigint;
103
+ salt: Hash;
104
+ }, root: Address, members: readonly Record<string, unknown>[], nativeBudget: bigint, deadline: bigint): void;
105
+ export declare function buildWithdraw(m: DeploymentManifest, family: Hash, member: number, liquidity: bigint, min0: bigint, min1: bigint, to: Address, deadline: bigint): Call;
106
+ /**
107
+ * Starts a two-step family transfer; `to` must then send buildFamilyAccept. The zero address cancels.
108
+ * `claims` is the current owner's own fee form on acceptance: bits (2i, 2i+1) pay member i's currency0/currency1
109
+ * fees to the current owner as PoolManager ERC-6909 claims instead of tokens. Only the current owner chooses it.
110
+ */
111
+ export declare function buildFamilyTransfer(m: DeploymentManifest, family: Hash, to: Address, claims?: number): Call;
112
+ /** Completes a pending family transfer; accrued fees go to the old owner in the form it chose. */
113
+ export declare function buildFamilyAccept(m: DeploymentManifest, family: Hash): Call;
114
+ /** withdraw, delivering currency0 (bit 0) and/or currency1 (bit 1) as PoolManager ERC-6909 claims. */
115
+ export declare function buildWithdrawWithClaims(m: DeploymentManifest, family: Hash, member: number, liquidity: bigint, min0: bigint, min1: bigint, to: Address, claims: number, deadline: bigint): Call;
116
+ /**
117
+ * Burns the sender's own ERC-6909 claim and pays `to` exactly `amount`. The sender must first approve the
118
+ * Launcher on the PoolManager (approve or setOperator). A fee-bearing currency is refused (exact delivery).
119
+ */
120
+ export declare function buildRedeem(m: DeploymentManifest, currency: Address, amount: bigint, to: Address): Call;
121
+ /** Moves the Launcher's whole idle (mistakenly sent) balance of `currency` to `to`. Reverts on zero. */
122
+ export declare function buildSweep(m: DeploymentManifest, currency: Address, to: Address): Call;
123
+ /**
124
+ * The sorted PoolKey the Launcher uses for a member (HookrLauncher.memberKey without the availability read).
125
+ * Read the contract's memberKey (or PoolManager slot0) for this key before signing a launch: an initialized key
126
+ * blocks the launch whatever its creator or role order.
127
+ */
128
+ export declare function launcherMemberKey(subject: Address, quote: Address, tickSpacing: number, root: Address): PoolKey;
129
+ export declare function buildDayClaim(m: DeploymentManifest, id: bigint, day: bigint, beneficiary: Address, weight: bigint, proof: Hash[]): Call;
130
+ export declare function buildAddLiquidity(m: DeploymentManifest, family: Hash, member: number, liquidity: bigint, max0: bigint, max1: bigint, deadline: bigint, nativeValue: bigint): Call;
131
+ export declare function buildPredictToken(m: DeploymentManifest, creator: Address, token: {
132
+ existing: Address;
133
+ name: string;
134
+ symbol: string;
135
+ supply: bigint;
136
+ salt: Hash;
137
+ }): Call;
138
+ export declare function buildReferralDayClaim(m: DeploymentManifest, id: bigint, day: bigint, payer: Address, referrer: Address, firstActivityBlock: bigint, weight: bigint, proof: Hash[]): Call;
139
+ export declare function buildCommissionCredit(m: DeploymentManifest, id: bigint, day: bigint, payer: Address, referrer: Address, firstActivityBlock: bigint, eligibleFees: bigint, proof: Hash[]): Call;
140
+ export declare function buildCommissionClaim(m: DeploymentManifest, currency: Address, beneficiary: Address, to: Address, amount?: bigint): Call;
141
+ export declare function buildCashClaim(m: DeploymentManifest, id: bigint, beneficiary: Address, to: Address, amount?: bigint): Call;
142
+ export declare function buildNFTClaim(m: DeploymentManifest, id: bigint, beneficiary: Address, milestone: bigint, to: Address): Call;
@@ -0,0 +1,304 @@
1
+ import { decodeFunctionResult, encodeFunctionData, encodeAbiParameters, keccak256 } from "viem";
2
+ import { address, assert, deployment, uint, hash, ZERO, } from "./schema.js";
3
+ import { launcherAbi, launchFeeAbi, routerAbi, quoterAbi, programsAbi, commissionsAbi } from "./abi.js";
4
+ import { RELEASE_CONSTANTS } from "./generated.js";
5
+ export function poolId(key) {
6
+ address(key.currency0, true);
7
+ address(key.currency1);
8
+ address(key.hooks);
9
+ assert(BigInt(key.currency0) < BigInt(key.currency1), "Unsorted pool currencies");
10
+ assert(key.fee === 0x800000, "Expected dynamic pool");
11
+ assert(Number.isInteger(key.tickSpacing) && key.tickSpacing > 0 && key.tickSpacing <= 32767, "Invalid tick spacing");
12
+ return keccak256(encodeAbiParameters([{ type: "address" }, { type: "address" }, { type: "uint24" }, { type: "int24" }, { type: "address" }], [key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks]));
13
+ }
14
+ export function contract(m, role) {
15
+ const pins = m.contracts.filter((c) => c.role === role);
16
+ assert(pins.length === 1, `Ambiguous/missing ${role}`);
17
+ return pins[0].address;
18
+ }
19
+ /** Returns `target` when the manifest pins it under `role` (roles such as `root` and `rules` may repeat). */
20
+ export function pinned(m, role, target) {
21
+ const a = address(target);
22
+ assert(m.contracts.some((c) => c.role === role && c.address === a), `Unpinned ${role}`);
23
+ return a;
24
+ }
25
+ export function buildCall(m, role, abi, name, args, value = 0n) {
26
+ return buildCallTo(m, contract(m, role), abi, name, args, value);
27
+ }
28
+ /** buildCall for an explicit pinned address; callers check the pin (`pinned`). */
29
+ export function buildCallTo(m, to, abi, name, args, value = 0n) {
30
+ deployment(m);
31
+ uint(value);
32
+ assert(uint(m.chainId) <= BigInt(Number.MAX_SAFE_INTEGER), "Chain overflow");
33
+ return {
34
+ chainId: Number(m.chainId),
35
+ to,
36
+ data: encodeFunctionData({ abi, functionName: name, args }),
37
+ value,
38
+ };
39
+ }
40
+ function checkSwap(m, s, now) {
41
+ poolId(s.key);
42
+ assert(m.contracts.some((c) => c.role === "root" && c.address.toLowerCase() === s.key.hooks.toLowerCase()), "Unqualified root");
43
+ address(s.recipient);
44
+ assert(s.amountSpecified !== 0n && s.amountSpecified > -(1n << 127n) && s.amountSpecified < 1n << 127n, "Bad amount");
45
+ assert(uint(s.amountBound, 128) > 0n, "Missing amount bound");
46
+ assert(uint(s.sqrtPriceLimitX96, 160) > 0n, "Missing price bound");
47
+ assert(s.deadline > now && s.deadline <= now + 3600n, "Deadline outside one-hour window");
48
+ }
49
+ export function buildSwap(m, s, programIds = [], now = BigInt(Math.floor(Date.now() / 1000))) {
50
+ checkSwap(m, s, now);
51
+ assert(programIds.length <= 8 && new Set(programIds.map(String)).size === programIds.length, "Invalid program set");
52
+ programIds.forEach((x) => assert(uint(x) > 0n, "Invalid program"));
53
+ const input = s.zeroForOne ? s.key.currency0 : s.key.currency1;
54
+ const value = input === ZERO ? (s.amountSpecified < 0n ? -s.amountSpecified : s.amountBound) : 0n;
55
+ return buildCall(m, "router", routerAbi, "swap", [s, programIds.length ? contract(m, "programs") : ZERO, programIds], value);
56
+ }
57
+ export function buildQuote(m, s, payer, now = BigInt(Math.floor(Date.now() / 1000))) {
58
+ checkSwap(m, s, now);
59
+ address(payer);
60
+ return buildCall(m, "quoter", quoterAbi, "quote", [s, payer]);
61
+ }
62
+ export function buildLaunch(m, token, root, members, nativeBudget, deadline, launchFee) {
63
+ checkLaunch(m, token, root, members, nativeBudget, deadline);
64
+ return buildCall(m, "launcher", launcherAbi, "launch", [token, root, members, deadline], nativeBudget + checkLaunchFee(launchFee));
65
+ }
66
+ /**
67
+ * launch, where member i binds its admitted advisory with the exact bytes `advisoryConfigs[i]` (for example
68
+ * `encodeFeeAdvisoryConfig` or `encodeSessionSchedule`). A member without an advisory passes "0x".
69
+ */
70
+ export function buildLaunchAdvised(m, token, root, members, advisoryConfigs, nativeBudget, deadline, launchFee) {
71
+ checkLaunch(m, token, root, members, nativeBudget, deadline);
72
+ checkAdvisoryConfigs(members, advisoryConfigs);
73
+ return buildCall(m, "launcher", launcherAbi, "launchAdvised", [token, root, members, advisoryConfigs, deadline], nativeBudget + checkLaunchFee(launchFee));
74
+ }
75
+ /** HookrLaunchChecks.MAX_LAUNCH_FEE: the most a launch fee can be, 0.01 of the native currency. */
76
+ export const MAX_LAUNCH_FEE = BigInt(RELEASE_CONSTANTS.LAUNCH_MAX_LAUNCH_FEE);
77
+ /**
78
+ * The launch fee a launch's native value carries on top of its native budgets (r31, IHookrLaunchFee): HookrLauncher
79
+ * refuses any other value (InvalidFunding). Read it at the launch block (`encodeLaunchFeeCall`, `decodeLaunchFee`);
80
+ * it is zero at genesis and changes only by the registry owner's timelocked proposal, at most MAX_LAUNCH_FEE.
81
+ */
82
+ export function checkLaunchFee(launchFee) {
83
+ assert(typeof launchFee === "bigint" && launchFee >= 0n && launchFee <= MAX_LAUNCH_FEE, "Launch fee outside 0 to 0.01 ether");
84
+ return launchFee;
85
+ }
86
+ /** The eth_call data that reads the launch fee from the launcher (`decodeLaunchFee` reads the answer). */
87
+ export function encodeLaunchFeeCall() {
88
+ return encodeFunctionData({ abi: launchFeeAbi, functionName: "launchFee" });
89
+ }
90
+ /** Decodes launchFee()'s five words, refusing a fee above MAX_LAUNCH_FEE. */
91
+ export function decodeLaunchFee(data) {
92
+ const [fee, treasury, pendingFee, pendingTreasury, readyAt] = decodeFunctionResult({
93
+ abi: launchFeeAbi,
94
+ functionName: "launchFee",
95
+ data,
96
+ });
97
+ checkLaunchFee(fee);
98
+ return {
99
+ fee,
100
+ treasury: address(treasury, true),
101
+ pendingFee,
102
+ pendingTreasury: address(pendingTreasury, true),
103
+ readyAt,
104
+ };
105
+ }
106
+ /** Refuses advisory configs launchAdvised and launchWithBuy would refuse: one per member, "0x" without an advisory. */
107
+ export function checkAdvisoryConfigs(members, advisoryConfigs) {
108
+ assert(advisoryConfigs.length === members.length, "One advisory config per member");
109
+ members.forEach((member, i) => {
110
+ assert(/^0x([\da-fA-F]{2})*$/.test(advisoryConfigs[i]), "Invalid advisory config bytes");
111
+ const advisory = member.config?.advisory;
112
+ assert(advisoryConfigs[i] === "0x" || (typeof advisory === "string" && address(advisory, true) !== ZERO), "Advisory config without an advisory");
113
+ assert(advisoryConfigs[i].length <= 2 + 2 * 4096, "Advisory config above 4096 bytes");
114
+ });
115
+ }
116
+ /**
117
+ * Refuses a launch the Launcher would refuse before any pool opens: an unqualified root, a family of 0 or more than 8,
118
+ * a malformed token, an expired deadline, an empty member, or a native budget other than the native members' maxima.
119
+ */
120
+ /**
121
+ * HookrLauncher.Member.recapture that launches a member without the recapture lane. Any config with `on` set makes the
122
+ * member's pool freeze the root's open lane at initialization, and the launch reverts while the root has none.
123
+ */
124
+ export const RECAPTURE_OFF = Object.freeze({
125
+ on: false,
126
+ traderBps: 0,
127
+ lpBps: 0,
128
+ period: 0,
129
+ maxPrizeBps: 0,
130
+ potReleaseBps: 0,
131
+ minBuyQuote: 0n,
132
+ releaseBlocks: 0,
133
+ });
134
+ /**
135
+ * HookrRecapture's release period bounds and default (RecaptureConfig.releaseBlocks), in L2 blocks: Robinhood Chain's
136
+ * own block number (ArbSys.arbBlockNumber), about 10 a second, so about 2 minutes, 24 hours and, by default, an hour.
137
+ * The release also counts at most `l2PerSecond` L2 blocks per second of block time. A member with recapture on and a
138
+ * period outside the bounds is refused at bind (InvalidConfig).
139
+ */
140
+ export const RECAPTURE_RELEASE_BLOCKS = Object.freeze({
141
+ min: Number(RELEASE_CONSTANTS.RECAPTURE_MIN_RELEASE_BLOCKS),
142
+ default: Number(RELEASE_CONSTANTS.RECAPTURE_DEFAULT_RELEASE_BLOCKS),
143
+ max: Number(RELEASE_CONSTANTS.RECAPTURE_MAX_RELEASE_BLOCKS),
144
+ l2PerSecond: Number(RELEASE_CONSTANTS.RECAPTURE_L2_PER_SECOND),
145
+ });
146
+ export function checkLaunch(m, token, root, members, nativeBudget, deadline) {
147
+ assert(m.contracts.some((c) => c.role === "root" && c.address.toLowerCase() === address(root)), "Unqualified root");
148
+ assert(members.length > 0 && members.length <= 8, "Invalid family size");
149
+ assert(token.existing === ZERO ? uint(token.supply) > 0n : token.supply === 0n && BigInt(token.salt) === 0n, "Invalid token supply");
150
+ address(token.existing, true);
151
+ assert(deadline > BigInt(Math.floor(Date.now() / 1000)), "Expired launch");
152
+ let expected = 0n;
153
+ for (const member of members) {
154
+ const q = address(member.quote, true);
155
+ if (q === ZERO)
156
+ expected += uint(member.amount0Max);
157
+ assert(uint(member.liquidity, 128) > 0n, "Empty liquidity");
158
+ const recapture = member.recapture;
159
+ assert(recapture !== null && typeof recapture === "object" && typeof recapture.on === "boolean", "Each launch member names its RecaptureConfig: RECAPTURE_OFF, or the Rules' recaptureDefaults() while the root's lane is open");
160
+ if (recapture.on) {
161
+ const period = Number(recapture.releaseBlocks);
162
+ assert(Number.isInteger(period) && period >= RECAPTURE_RELEASE_BLOCKS.min && period <= RECAPTURE_RELEASE_BLOCKS.max, "Recapture releaseBlocks outside 1,200 to 864,000 L2 blocks");
163
+ }
164
+ }
165
+ assert(nativeBudget === expected, "Native family budget must match native member maxima");
166
+ }
167
+ export function buildWithdraw(m, family, member, liquidity, min0, min1, to, deadline) {
168
+ assert(Number.isInteger(member) && member >= 0 && member < 8, "Invalid member");
169
+ uint(liquidity, 128);
170
+ uint(min0);
171
+ uint(min1);
172
+ address(to);
173
+ return buildCall(m, "launcher", launcherAbi, "withdraw", [family, member, liquidity, min0, min1, to, deadline]);
174
+ }
175
+ function claimsMask(claims, bits) {
176
+ assert(Number.isInteger(claims) && claims >= 0 && claims < 1 << bits, "Invalid claims mask");
177
+ return claims;
178
+ }
179
+ /**
180
+ * Starts a two-step family transfer; `to` must then send buildFamilyAccept. The zero address cancels.
181
+ * `claims` is the current owner's own fee form on acceptance: bits (2i, 2i+1) pay member i's currency0/currency1
182
+ * fees to the current owner as PoolManager ERC-6909 claims instead of tokens. Only the current owner chooses it.
183
+ */
184
+ export function buildFamilyTransfer(m, family, to, claims = 0) {
185
+ return buildCall(m, "launcher", launcherAbi, "transferFamily", [family, address(to, true), claimsMask(claims, 16)]);
186
+ }
187
+ /** Completes a pending family transfer; accrued fees go to the old owner in the form it chose. */
188
+ export function buildFamilyAccept(m, family) {
189
+ return buildCall(m, "launcher", launcherAbi, "acceptFamily", [family]);
190
+ }
191
+ /** withdraw, delivering currency0 (bit 0) and/or currency1 (bit 1) as PoolManager ERC-6909 claims. */
192
+ export function buildWithdrawWithClaims(m, family, member, liquidity, min0, min1, to, claims, deadline) {
193
+ assert(Number.isInteger(member) && member >= 0 && member < 8, "Invalid member");
194
+ uint(liquidity, 128);
195
+ uint(min0);
196
+ uint(min1);
197
+ uint(deadline);
198
+ return buildCall(m, "launcher", launcherAbi, "withdrawWithClaims", [
199
+ family,
200
+ member,
201
+ liquidity,
202
+ min0,
203
+ min1,
204
+ address(to),
205
+ claimsMask(claims, 2),
206
+ deadline,
207
+ ]);
208
+ }
209
+ /**
210
+ * Burns the sender's own ERC-6909 claim and pays `to` exactly `amount`. The sender must first approve the
211
+ * Launcher on the PoolManager (approve or setOperator). A fee-bearing currency is refused (exact delivery).
212
+ */
213
+ export function buildRedeem(m, currency, amount, to) {
214
+ assert(uint(amount) > 0n, "Empty redemption");
215
+ return buildCall(m, "launcher", launcherAbi, "redeem", [address(currency, true), amount, address(to)]);
216
+ }
217
+ /** Moves the Launcher's whole idle (mistakenly sent) balance of `currency` to `to`. Reverts on zero. */
218
+ export function buildSweep(m, currency, to) {
219
+ return buildCall(m, "launcher", launcherAbi, "sweep", [address(currency, true), address(to)]);
220
+ }
221
+ /**
222
+ * The sorted PoolKey the Launcher uses for a member (HookrLauncher.memberKey without the availability read).
223
+ * Read the contract's memberKey (or PoolManager slot0) for this key before signing a launch: an initialized key
224
+ * blocks the launch whatever its creator or role order.
225
+ */
226
+ export function launcherMemberKey(subject, quote, tickSpacing, root) {
227
+ const s = address(subject);
228
+ const q = address(quote, true);
229
+ assert(s !== q, "Subject equals quote");
230
+ const subjectFirst = BigInt(s) < BigInt(q);
231
+ const key = {
232
+ currency0: subjectFirst ? s : q,
233
+ currency1: subjectFirst ? q : s,
234
+ fee: 0x800000,
235
+ tickSpacing,
236
+ hooks: address(root),
237
+ };
238
+ poolId(key);
239
+ return key;
240
+ }
241
+ export function buildDayClaim(m, id, day, beneficiary, weight, proof) {
242
+ assert(proof.length <= 32, "Proof too long");
243
+ uint(weight, 128);
244
+ return buildCall(m, "programs", programsAbi, "claimDay", [id, day, address(beneficiary), weight, proof]);
245
+ }
246
+ export function buildAddLiquidity(m, family, member, liquidity, max0, max1, deadline, nativeValue) {
247
+ uint(liquidity, 128);
248
+ uint(max0, 128);
249
+ uint(max1, 128);
250
+ assert(nativeValue === 0n || nativeValue === max0, "Native funding must match currency0 bound");
251
+ return buildCall(m, "launcher", launcherAbi, "addLiquidity", [family, member, liquidity, max0, max1, deadline], nativeValue);
252
+ }
253
+ export function buildPredictToken(m, creator, token) {
254
+ address(creator);
255
+ address(token.existing, true);
256
+ hash(token.salt);
257
+ uint(token.supply);
258
+ return buildCall(m, "launcher", launcherAbi, "predictToken", [creator, token]);
259
+ }
260
+ export function buildReferralDayClaim(m, id, day, payer, referrer, firstActivityBlock, weight, proof) {
261
+ assert(proof.length <= 32, "Proof too long");
262
+ uint(firstActivityBlock, 64);
263
+ uint(weight, 128);
264
+ return buildCall(m, "programs", programsAbi, "claimReferralDay", [
265
+ id,
266
+ day,
267
+ address(payer),
268
+ address(referrer),
269
+ firstActivityBlock,
270
+ weight,
271
+ proof,
272
+ ]);
273
+ }
274
+ export function buildCommissionCredit(m, id, day, payer, referrer, firstActivityBlock, eligibleFees, proof) {
275
+ assert(proof.length <= 32, "Proof too long");
276
+ uint(firstActivityBlock, 64);
277
+ uint(eligibleFees, 128);
278
+ return buildCall(m, "commissions", commissionsAbi, "creditDay", [
279
+ id,
280
+ day,
281
+ address(payer),
282
+ address(referrer),
283
+ firstActivityBlock,
284
+ eligibleFees,
285
+ proof,
286
+ ]);
287
+ }
288
+ export function buildCommissionClaim(m, currency, beneficiary, to, amount = 0n) {
289
+ uint(amount);
290
+ return buildCall(m, "commissions", commissionsAbi, "claim", [
291
+ address(currency, true),
292
+ address(beneficiary),
293
+ address(to),
294
+ amount,
295
+ ]);
296
+ }
297
+ export function buildCashClaim(m, id, beneficiary, to, amount = 0n) {
298
+ uint(amount);
299
+ return buildCall(m, "programs", programsAbi, "claimCash", [id, address(beneficiary), address(to), amount]);
300
+ }
301
+ export function buildNFTClaim(m, id, beneficiary, milestone, to) {
302
+ uint(milestone);
303
+ return buildCall(m, "programs", programsAbi, "claimNFT", [id, address(beneficiary), milestone, address(to)]);
304
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Each release's deployment as its verified app manifest records it: the start block and that block's hash, every
3
+ * manifest role's runtime code hash, and the hash of the release's source verification on Blockscout.
4
+ * `scripts/release-deployment.mjs` writes this file from that manifest. A release stays null until every contract of
5
+ * it is deployed and its source verified.
6
+ */
7
+ import type { HookrReleaseId, ReleaseDeployment } from "./releases.js";
8
+ export declare const DEPLOYMENTS: Readonly<Record<HookrReleaseId, ReleaseDeployment | null>>;
@@ -0,0 +1,26 @@
1
+ export const DEPLOYMENTS = {
2
+ "hookr-1": {
3
+ startBlock: "82536327",
4
+ parentHash: "0xe77f49e3ad06e4d93c91a233449a290cfa3ad392b9ea980d822b8bbc0ba8e3b7",
5
+ runtimeHashes: {
6
+ poolManager: "0xbd3881180b547f5fe817545743cfb4343e96b1bc6640dcd70c106b0066e95626",
7
+ registry: "0xc16e7681583d8d9af8e8c54962f7e890b967687dee4cf32dbd676d4d547d2359",
8
+ root: "0xd336de325837e60a74cea11d87b5ebd1cc8961911f611f38de0508d23b6e779f",
9
+ rules: "0x4b6d50b40981b8082f3ee5a7ebf57e48489f71c94c2a3b94032a1d1a382b515b",
10
+ router: "0x855177b2017e7b73a79cb0c7b3027044beb5e726fbdc0fd2937229e32ecd7e0b",
11
+ quoter: "0x1623e56a309a31e3626b854cd87623d62e39f743e2943d1f36ba13d677cef67a",
12
+ launcher: "0x96b8c338c38a072ceef8b947ad93d3d7a46d2d7c70189d2b4ee92efb2a5e1d5d",
13
+ treasury: "0x95d1784c555685e9ccbc0ba9f6d1e6facea864fd1de77ebbc98862dcf2c13454",
14
+ programs: "0xedd6b1c99617bd0bb5cb1e6d1088144c579fe5ca0e21d3e4254ade8f4249a19f",
15
+ referrals: "0xc576e1b1254a8d1e0100f541d3f6d4fbe27029aa8a7eb55607db697543fd6894",
16
+ commissions: "0x66b72c0818a51f1f22b8d7e2c053e02606dc170754917d6fbd815fc42701ba9d",
17
+ forwarder: "0x3242bd3dea1be9c1ffd17b23475f2d1d11fb5ee9cdbe8328b309b7adb8427043",
18
+ rootFactory: "0xed0774e92af31e9799c7b91b764c4508d33fee4323a564801713714897183849",
19
+ feeAdvisory: "0x9b3c56e0749889dd01ab6c1a5247c1fb2f47bf92da5d08737f6570ed48fead74",
20
+ sessionAdvisory: "0x0e33fd89175de3909a2a51a4d93c0bd359b17dd9396dd49faeea0d49370d6e18",
21
+ liquidityVault: "0x6632211514f82b2f0fe6d9016cbdc5a7e2c688bc576a75d4ab1384fcc0344827",
22
+ },
23
+ evidenceHash: "0xd11146db666e226b65fc27ff225a777c076ab91fbf68f31ee27c3a6a4d30a85d",
24
+ },
25
+ "canary-hookr-1-a": null,
26
+ };