hookr-sdk 0.2.0 → 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 +283 -96
  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 -127
  62. package/dist/reads.js +0 -207
  63. package/dist/rules.d.ts +0 -84
  64. package/dist/rules.js +0 -296
  65. package/dist/swap.d.ts +0 -96
  66. package/dist/swap.js +0 -134
@@ -0,0 +1,136 @@
1
+ import { type Hash } from "./schema.js";
2
+ export declare const SOURCE_POLICY_BODIES: {
3
+ readonly immediate: {
4
+ readonly mode: 0;
5
+ readonly activity: "authenticated-opt-in-actual-core-quote";
6
+ readonly rounding: "contract-fractional-carry";
7
+ readonly award: "fixed-rate-bounded-budget-wallet-cap";
8
+ readonly systemFlows: "excluded";
9
+ readonly schema: "hookr.source-policy.v1";
10
+ readonly history: "contiguous-finalized-receipts-pinned-runtime";
11
+ readonly identity: "chain-source-pool-config-participant";
12
+ readonly quantities: "raw-integer-per-currency";
13
+ readonly truth: "configured-RPC-and-named-attestor-reviewer";
14
+ readonly washResistance: "bounded-funded-campaign-not-Sybil-proof";
15
+ };
16
+ readonly dailySwap: {
17
+ readonly mode: 1;
18
+ readonly activity: "explicit-DailyActivityAccepted-plus-authenticated-receipt";
19
+ readonly rounding: "sum-raw-per-wallet-scope-day-then-normalize-floor";
20
+ readonly award: "fixed-UTC-day-budget-pro-rata-floor-wallet-caps-clip-no-redistribution";
21
+ readonly systemFlows: "excluded";
22
+ readonly schema: "hookr.source-policy.v1";
23
+ readonly history: "contiguous-finalized-receipts-pinned-runtime";
24
+ readonly identity: "chain-source-pool-config-participant";
25
+ readonly quantities: "raw-integer-per-currency";
26
+ readonly truth: "configured-RPC-and-named-attestor-reviewer";
27
+ readonly washResistance: "bounded-funded-campaign-not-Sybil-proof";
28
+ };
29
+ readonly dailyLPFees: {
30
+ readonly mode: 2;
31
+ readonly activity: "v4-integer-step-replay-LP-trade-fee-growth";
32
+ readonly ownership: "canonical-PositionManager-NFT-and-Launcher-family-actual-log-order";
33
+ readonly donations: "excluded-all";
34
+ readonly rounding: "sum-Q128-earned-per-owner-currency-day-then-floor-then-scope-normalize-floor";
35
+ readonly award: "fixed-UTC-day-budget-pro-rata-floor-wallet-caps-clip-no-redistribution";
36
+ readonly reconciliation: "end-block-pool-ticks-positions-owner-state";
37
+ readonly unsupportedCustody: "excluded-disclosed";
38
+ readonly selfPaidFees: "excluded-when-owner-is-router-payer-or-recipient-or-poolmanager-sender-or-transaction-origin";
39
+ readonly unattributedSwaps: "excluded-curated-router-and-unpaired-router-swaps";
40
+ readonly priceLimits: "v4-limit-bound-swaps-replayed-at-emitted-final-price";
41
+ readonly schema: "hookr.source-policy.v1";
42
+ readonly history: "contiguous-finalized-receipts-pinned-runtime";
43
+ readonly identity: "chain-source-pool-config-participant";
44
+ readonly quantities: "raw-integer-per-currency";
45
+ readonly truth: "configured-RPC-and-named-attestor-reviewer";
46
+ readonly washResistance: "bounded-funded-campaign-not-Sybil-proof";
47
+ };
48
+ readonly dailyReferral: {
49
+ readonly mode: 3;
50
+ readonly activity: "normalized-qualified-base-activity-not-awarded-points";
51
+ readonly binding: "authenticated-immutable-before-first-activity-Solidity-parent-clock";
52
+ readonly bases: readonly ["immediate", "dailySwap", "dailyLPFees"];
53
+ readonly award: "separate-fixed-daily-budget-weighted-per-payer-leaf-referrer-wallet-cap";
54
+ readonly donations: "excluded-all";
55
+ readonly lpBase: "dailyLPFees-self-paid-and-unattributed-swaps-excluded";
56
+ readonly rounding: "base-policy-activity-rounding-then-per-payer-budget-floor";
57
+ readonly schema: "hookr.source-policy.v1";
58
+ readonly history: "contiguous-finalized-receipts-pinned-runtime";
59
+ readonly identity: "chain-source-pool-config-participant";
60
+ readonly quantities: "raw-integer-per-currency";
61
+ readonly truth: "configured-RPC-and-named-attestor-reviewer";
62
+ readonly washResistance: "bounded-funded-campaign-not-Sybil-proof";
63
+ };
64
+ readonly commission: {
65
+ readonly activity: "actual-collected-protocol-or-creator-royalty-fee-lots";
66
+ readonly binding: "authenticated-immutable-before-first-activity-Solidity-parent-clock";
67
+ readonly payer: "unambiguous-known-router-fee-event-pair";
68
+ readonly payerCode: "EOA-or-reviewed-smart-wallet-runtime-including-EIP-7702-delegate";
69
+ readonly selfReferral: "referrer-originated-payer-swaps-excluded-related-wallet-evidence-not-Sybil-proof";
70
+ readonly collection: "refunds-to-router-payer-or-PoolManager-sender-unattributed-refunds-absorbed-first-by-lot-owners-non-owner-claims-skipped-then-FIFO-fee-lots-protocol-matches-Treasury-receipt";
71
+ readonly award: "immutable-bps-chronological-daily-budget-wallet-fee-cap";
72
+ readonly stacking: "each-fee-unit-once-within-operator-database-and-against-other-campaigns-onchain-proposals-review-required-across-operators";
73
+ readonly schema: "hookr.source-policy.v1";
74
+ readonly history: "contiguous-finalized-receipts-pinned-runtime";
75
+ readonly identity: "chain-source-pool-config-participant";
76
+ readonly quantities: "raw-integer-per-currency";
77
+ readonly truth: "configured-RPC-and-named-attestor-reviewer";
78
+ readonly washResistance: "bounded-funded-campaign-not-Sybil-proof";
79
+ };
80
+ };
81
+ export declare const SOURCE_POLICIES: {
82
+ readonly immediate: `0x${string}`;
83
+ readonly dailySwap: `0x${string}`;
84
+ readonly dailyLPFees: `0x${string}`;
85
+ readonly dailyReferral: `0x${string}`;
86
+ readonly commission: `0x${string}`;
87
+ };
88
+ export declare const LAUNCH_SEASON_POLICY_BODIES: {
89
+ readonly traders: {
90
+ readonly mode: 1;
91
+ readonly activity: "every-route-PoolManager-Swap-quote-leg";
92
+ readonly wash: "ATT-03-same-day-liquidity-rule-actor-and-effective-origin-dev-buy-per-formula";
93
+ readonly rounding: "sum-ETH-equivalent-wei-per-actor-over-the-ledger-period-floor";
94
+ readonly history: "finalized-eth_getLogs-spans-at-most-5000-blocks-plus-receipts-of-every-pool-transaction";
95
+ readonly identity: "chain-root-pool-actor";
96
+ readonly scope: "every-pool-a-pinned-root-opened-from-the-configured-launch-block";
97
+ readonly attribution: "router-payer-forwarder-intent-owner-dev-buy-buyer-userop-sender-universal-router-tx-sender-or-traced-listed-wallet-caller-lane-trader-as-caller-else-origin-flagged-trace-failures-fail-the-pass";
98
+ readonly unit: "ETH-equivalent-wei-at-the-swap-block-priced-before-it-by-chainlink-feeds-or-an-owner-pinned-reference-pool-TWAP-of-earlier-blocks-unpriced-weighs-zero";
99
+ readonly systemFlows: "arb-recapture-legs-executor-rules-treasury-launcher-vault-poolmanager-forwarder-and-owner-listed-wallets-excluded";
100
+ readonly receipts: "HookrPrograms-execution-receipts-ignored";
101
+ readonly payout: "ledger-UTC-days-paid-as-the-content-of-a-later-program-day-each-ledger-day-paid-once-per-kind-coverage-names-the-ledger-block-range";
102
+ readonly award: "fixed-UTC-day-budget-pro-rata-floor-wallet-caps-clip-no-redistribution";
103
+ readonly schema: "hookr.source-policy.v1";
104
+ readonly quantities: "raw-integer-per-currency";
105
+ readonly truth: "configured-RPC-and-named-attestor-reviewer";
106
+ readonly washResistance: "bounded-funded-campaign-not-Sybil-proof";
107
+ };
108
+ readonly lps: {
109
+ readonly mode: 2;
110
+ readonly activity: "v4-integer-step-replay-LP-trade-fee-growth-every-attributed-swap";
111
+ readonly ownership: "canonical-PositionManager-NFT-Launcher-family-and-HookrLiquidityVault-share-holders-actual-log-order";
112
+ readonly donations: "excluded-all";
113
+ readonly selfPaidFees: "excluded-when-owner-is-actor-origin-effective-origin-sender-payer-or-recipient";
114
+ readonly unattributedSwaps: "excluded-arb-recapture-executor-legs";
115
+ readonly rounding: "sum-Q128-earned-per-owner-currency-day-then-floor-then-each-currency-ETH-equivalent-at-day-close-by-feed-or-pinned-reference-TWAP-never-the-pool-price-unpriced-side-weighs-zero";
116
+ readonly history: "finalized-eth_getLogs-spans-at-most-5000-blocks-plus-receipts-of-every-pool-transaction";
117
+ readonly identity: "chain-root-pool-actor";
118
+ readonly scope: "every-pool-a-pinned-root-opened-from-the-configured-launch-block";
119
+ readonly attribution: "router-payer-forwarder-intent-owner-dev-buy-buyer-userop-sender-universal-router-tx-sender-or-traced-listed-wallet-caller-lane-trader-as-caller-else-origin-flagged-trace-failures-fail-the-pass";
120
+ readonly unit: "ETH-equivalent-wei-at-the-swap-block-priced-before-it-by-chainlink-feeds-or-an-owner-pinned-reference-pool-TWAP-of-earlier-blocks-unpriced-weighs-zero";
121
+ readonly systemFlows: "arb-recapture-legs-executor-rules-treasury-launcher-vault-poolmanager-forwarder-and-owner-listed-wallets-excluded";
122
+ readonly receipts: "HookrPrograms-execution-receipts-ignored";
123
+ readonly payout: "ledger-UTC-days-paid-as-the-content-of-a-later-program-day-each-ledger-day-paid-once-per-kind-coverage-names-the-ledger-block-range";
124
+ readonly award: "fixed-UTC-day-budget-pro-rata-floor-wallet-caps-clip-no-redistribution";
125
+ readonly schema: "hookr.source-policy.v1";
126
+ readonly quantities: "raw-integer-per-currency";
127
+ readonly truth: "configured-RPC-and-named-attestor-reviewer";
128
+ readonly washResistance: "bounded-funded-campaign-not-Sybil-proof";
129
+ };
130
+ };
131
+ export declare const LAUNCH_SEASON_POLICIES: {
132
+ readonly traders: `0x${string}`;
133
+ readonly lps: `0x${string}`;
134
+ };
135
+ export declare function policyForMode(mode: number): Hash;
136
+ export declare function requirePolicy(value: Hash, mode: number | "commission"): void;
@@ -0,0 +1,125 @@
1
+ import { assert } from "./schema.js";
2
+ import { digest } from "./proofs.js";
3
+ const common = {
4
+ schema: "hookr.source-policy.v1",
5
+ history: "contiguous-finalized-receipts-pinned-runtime",
6
+ identity: "chain-source-pool-config-participant",
7
+ quantities: "raw-integer-per-currency",
8
+ truth: "configured-RPC-and-named-attestor-reviewer",
9
+ washResistance: "bounded-funded-campaign-not-Sybil-proof",
10
+ };
11
+ export const SOURCE_POLICY_BODIES = {
12
+ immediate: {
13
+ ...common,
14
+ mode: 0,
15
+ activity: "authenticated-opt-in-actual-core-quote",
16
+ rounding: "contract-fractional-carry",
17
+ award: "fixed-rate-bounded-budget-wallet-cap",
18
+ systemFlows: "excluded",
19
+ },
20
+ dailySwap: {
21
+ ...common,
22
+ mode: 1,
23
+ activity: "explicit-DailyActivityAccepted-plus-authenticated-receipt",
24
+ rounding: "sum-raw-per-wallet-scope-day-then-normalize-floor",
25
+ award: "fixed-UTC-day-budget-pro-rata-floor-wallet-caps-clip-no-redistribution",
26
+ systemFlows: "excluded",
27
+ },
28
+ dailyLPFees: {
29
+ ...common,
30
+ mode: 2,
31
+ activity: "v4-integer-step-replay-LP-trade-fee-growth",
32
+ ownership: "canonical-PositionManager-NFT-and-Launcher-family-actual-log-order",
33
+ donations: "excluded-all",
34
+ rounding: "sum-Q128-earned-per-owner-currency-day-then-floor-then-scope-normalize-floor",
35
+ award: "fixed-UTC-day-budget-pro-rata-floor-wallet-caps-clip-no-redistribution",
36
+ reconciliation: "end-block-pool-ticks-positions-owner-state",
37
+ unsupportedCustody: "excluded-disclosed",
38
+ selfPaidFees: "excluded-when-owner-is-router-payer-or-recipient-or-poolmanager-sender-or-transaction-origin",
39
+ unattributedSwaps: "excluded-curated-router-and-unpaired-router-swaps",
40
+ priceLimits: "v4-limit-bound-swaps-replayed-at-emitted-final-price",
41
+ },
42
+ dailyReferral: {
43
+ ...common,
44
+ mode: 3,
45
+ activity: "normalized-qualified-base-activity-not-awarded-points",
46
+ binding: "authenticated-immutable-before-first-activity-Solidity-parent-clock",
47
+ bases: ["immediate", "dailySwap", "dailyLPFees"],
48
+ award: "separate-fixed-daily-budget-weighted-per-payer-leaf-referrer-wallet-cap",
49
+ donations: "excluded-all",
50
+ lpBase: "dailyLPFees-self-paid-and-unattributed-swaps-excluded",
51
+ rounding: "base-policy-activity-rounding-then-per-payer-budget-floor",
52
+ },
53
+ commission: {
54
+ ...common,
55
+ activity: "actual-collected-protocol-or-creator-royalty-fee-lots",
56
+ binding: "authenticated-immutable-before-first-activity-Solidity-parent-clock",
57
+ payer: "unambiguous-known-router-fee-event-pair",
58
+ payerCode: "EOA-or-reviewed-smart-wallet-runtime-including-EIP-7702-delegate",
59
+ selfReferral: "referrer-originated-payer-swaps-excluded-related-wallet-evidence-not-Sybil-proof",
60
+ collection: "refunds-to-router-payer-or-PoolManager-sender-unattributed-refunds-absorbed-first-by-lot-owners-non-owner-claims-skipped-then-FIFO-fee-lots-protocol-matches-Treasury-receipt",
61
+ award: "immutable-bps-chronological-daily-budget-wallet-fee-cap",
62
+ stacking: "each-fee-unit-once-within-operator-database-and-against-other-campaigns-onchain-proposals-review-required-across-operators",
63
+ },
64
+ };
65
+ export const SOURCE_POLICIES = {
66
+ immediate: digest(SOURCE_POLICY_BODIES.immediate),
67
+ dailySwap: digest(SOURCE_POLICY_BODIES.dailySwap),
68
+ dailyLPFees: digest(SOURCE_POLICY_BODIES.dailyLPFees),
69
+ dailyReferral: digest(SOURCE_POLICY_BODIES.dailyReferral),
70
+ commission: digest(SOURCE_POLICY_BODIES.commission),
71
+ };
72
+ /**
73
+ * Off-chain launch points ledger (service/src/points): activity counted from the Hookr 1 launch block on every pinned
74
+ * root's pools whatever the route, then paid through ordinary DailySwap (traders) or DailyLPFees (LPs) programs whose
75
+ * days carry earlier ledger periods. A program naming one of these hashes is allocated only by the ledger
76
+ * (`points-ledger allocate`), never from HookrPrograms receipts, so a swap opted into the season program by
77
+ * recordExecution is not counted twice.
78
+ */
79
+ const launchSeason = {
80
+ ...common,
81
+ history: "finalized-eth_getLogs-spans-at-most-5000-blocks-plus-receipts-of-every-pool-transaction",
82
+ identity: "chain-root-pool-actor",
83
+ scope: "every-pool-a-pinned-root-opened-from-the-configured-launch-block",
84
+ attribution: "router-payer-forwarder-intent-owner-dev-buy-buyer-userop-sender-universal-router-tx-sender-or-traced-listed-wallet-caller-lane-trader-as-caller-else-origin-flagged-trace-failures-fail-the-pass",
85
+ unit: "ETH-equivalent-wei-at-the-swap-block-priced-before-it-by-chainlink-feeds-or-an-owner-pinned-reference-pool-TWAP-of-earlier-blocks-unpriced-weighs-zero",
86
+ systemFlows: "arb-recapture-legs-executor-rules-treasury-launcher-vault-poolmanager-forwarder-and-owner-listed-wallets-excluded",
87
+ receipts: "HookrPrograms-execution-receipts-ignored",
88
+ payout: "ledger-UTC-days-paid-as-the-content-of-a-later-program-day-each-ledger-day-paid-once-per-kind-coverage-names-the-ledger-block-range",
89
+ award: "fixed-UTC-day-budget-pro-rata-floor-wallet-caps-clip-no-redistribution",
90
+ };
91
+ export const LAUNCH_SEASON_POLICY_BODIES = {
92
+ traders: {
93
+ ...launchSeason,
94
+ mode: 1,
95
+ activity: "every-route-PoolManager-Swap-quote-leg",
96
+ wash: "ATT-03-same-day-liquidity-rule-actor-and-effective-origin-dev-buy-per-formula",
97
+ rounding: "sum-ETH-equivalent-wei-per-actor-over-the-ledger-period-floor",
98
+ },
99
+ lps: {
100
+ ...launchSeason,
101
+ mode: 2,
102
+ activity: "v4-integer-step-replay-LP-trade-fee-growth-every-attributed-swap",
103
+ ownership: "canonical-PositionManager-NFT-Launcher-family-and-HookrLiquidityVault-share-holders-actual-log-order",
104
+ donations: "excluded-all",
105
+ selfPaidFees: "excluded-when-owner-is-actor-origin-effective-origin-sender-payer-or-recipient",
106
+ unattributedSwaps: "excluded-arb-recapture-executor-legs",
107
+ rounding: "sum-Q128-earned-per-owner-currency-day-then-floor-then-each-currency-ETH-equivalent-at-day-close-by-feed-or-pinned-reference-TWAP-never-the-pool-price-unpriced-side-weighs-zero",
108
+ },
109
+ };
110
+ export const LAUNCH_SEASON_POLICIES = {
111
+ traders: digest(LAUNCH_SEASON_POLICY_BODIES.traders),
112
+ lps: digest(LAUNCH_SEASON_POLICY_BODIES.lps),
113
+ };
114
+ export function policyForMode(mode) {
115
+ assert(Number.isInteger(mode) && mode >= 0 && mode <= 3, "Unsupported program mode");
116
+ return [
117
+ SOURCE_POLICIES.immediate,
118
+ SOURCE_POLICIES.dailySwap,
119
+ SOURCE_POLICIES.dailyLPFees,
120
+ SOURCE_POLICIES.dailyReferral,
121
+ ][mode];
122
+ }
123
+ export function requirePolicy(value, mode) {
124
+ assert(value === (mode === "commission" ? SOURCE_POLICIES.commission : policyForMode(mode)), "Unsupported source policy; use the published policy body and matching immutable hash");
125
+ }
@@ -0,0 +1,25 @@
1
+ import { type Address, type Hash } from "./schema.js";
2
+ export declare const digest: (value: unknown) => Hash;
3
+ export interface DayDomain {
4
+ chainId: string;
5
+ distributor: Address;
6
+ programId: string;
7
+ termsHash: Hash;
8
+ day: string;
9
+ epochStart: string;
10
+ epochEnd: string;
11
+ coverageHash: Hash;
12
+ }
13
+ export declare function dayLeaf(d: DayDomain, beneficiary: Address, weight: string): Hash;
14
+ export declare const pair: (a: Hash, b: Hash) => Hash;
15
+ export declare function merkle(leaves: Hash[]): {
16
+ root: Hash;
17
+ proofs: Hash[][];
18
+ };
19
+ export declare const verifyProof: (leaf: Hash, proof: Hash[], root: Hash) => boolean;
20
+ export interface FeeDomain extends Omit<DayDomain, "programId"> {
21
+ campaignId: string;
22
+ collectionsHash: Hash;
23
+ }
24
+ export declare function feeLeaf(d: FeeDomain, payer: Address, referrer: Address, firstActivityBlock: string, eligibleFees: string): Hash;
25
+ export declare function referralPointLeaf(d: DayDomain, payer: Address, referrer: Address, firstActivityBlock: string, weight: string): Hash;
@@ -0,0 +1,118 @@
1
+ import { encodeAbiParameters, keccak256, concatHex, stringToHex } from "viem";
2
+ import { assert, canonical, hash, uint, ZERO_HASH } from "./schema.js";
3
+ export const digest = (value) => keccak256(stringToHex(canonical(value)));
4
+ export function dayLeaf(d, beneficiary, weight) {
5
+ uint(weight, 128);
6
+ return keccak256(keccak256(encodeAbiParameters([
7
+ { type: "uint256" },
8
+ { type: "address" },
9
+ { type: "uint256" },
10
+ { type: "bytes32" },
11
+ { type: "uint256" },
12
+ { type: "uint64" },
13
+ { type: "uint64" },
14
+ { type: "bytes32" },
15
+ { type: "address" },
16
+ { type: "uint128" },
17
+ ], [
18
+ uint(d.chainId),
19
+ d.distributor,
20
+ uint(d.programId),
21
+ d.termsHash,
22
+ uint(d.day),
23
+ uint(d.epochStart, 64),
24
+ uint(d.epochEnd, 64),
25
+ d.coverageHash,
26
+ beneficiary,
27
+ uint(weight, 128),
28
+ ])));
29
+ }
30
+ export const pair = (a, b) => keccak256(concatHex(a.toLowerCase() < b.toLowerCase() ? [a, b] : [b, a]));
31
+ export function merkle(leaves) {
32
+ if (!leaves.length)
33
+ return { root: ZERO_HASH, proofs: [] };
34
+ const levels = [leaves.map(hash)];
35
+ assert(new Set(levels[0]).size === leaves.length, "Duplicate leaves");
36
+ while (levels.at(-1).length > 1) {
37
+ const prev = levels.at(-1);
38
+ const next = [];
39
+ for (let i = 0; i < prev.length; i += 2)
40
+ next.push(i + 1 < prev.length ? pair(prev[i], prev[i + 1]) : prev[i]);
41
+ levels.push(next);
42
+ }
43
+ assert(levels.length <= 33, "Merkle depth exceeded");
44
+ return {
45
+ root: levels.at(-1)[0],
46
+ proofs: leaves.map((_, i) => {
47
+ const proof = [];
48
+ for (const level of levels.slice(0, -1)) {
49
+ const other = i ^ 1;
50
+ if (other < level.length)
51
+ proof.push(level[other]);
52
+ i = Math.floor(i / 2);
53
+ }
54
+ return proof;
55
+ }),
56
+ };
57
+ }
58
+ export const verifyProof = (leaf, proof, root) => proof.reduce(pair, leaf) === root;
59
+ export function feeLeaf(d, payer, referrer, firstActivityBlock, eligibleFees) {
60
+ return keccak256(keccak256(encodeAbiParameters([
61
+ { type: "uint256" },
62
+ { type: "address" },
63
+ { type: "uint256" },
64
+ { type: "bytes32" },
65
+ { type: "uint256" },
66
+ { type: "uint64" },
67
+ { type: "uint64" },
68
+ { type: "bytes32" },
69
+ { type: "bytes32" },
70
+ { type: "address" },
71
+ { type: "address" },
72
+ { type: "uint64" },
73
+ { type: "uint128" },
74
+ ], [
75
+ uint(d.chainId),
76
+ d.distributor,
77
+ uint(d.campaignId),
78
+ d.termsHash,
79
+ uint(d.day),
80
+ uint(d.epochStart, 64),
81
+ uint(d.epochEnd, 64),
82
+ d.coverageHash,
83
+ d.collectionsHash,
84
+ payer,
85
+ referrer,
86
+ uint(firstActivityBlock, 64),
87
+ uint(eligibleFees, 128),
88
+ ])));
89
+ }
90
+ export function referralPointLeaf(d, payer, referrer, firstActivityBlock, weight) {
91
+ return keccak256(keccak256(encodeAbiParameters([
92
+ { type: "uint256" },
93
+ { type: "address" },
94
+ { type: "uint256" },
95
+ { type: "bytes32" },
96
+ { type: "uint256" },
97
+ { type: "uint64" },
98
+ { type: "uint64" },
99
+ { type: "bytes32" },
100
+ { type: "address" },
101
+ { type: "address" },
102
+ { type: "uint64" },
103
+ { type: "uint128" },
104
+ ], [
105
+ uint(d.chainId),
106
+ d.distributor,
107
+ uint(d.programId),
108
+ d.termsHash,
109
+ uint(d.day),
110
+ uint(d.epochStart, 64),
111
+ uint(d.epochEnd, 64),
112
+ d.coverageHash,
113
+ payer,
114
+ referrer,
115
+ uint(firstActivityBlock, 64),
116
+ uint(weight, 128),
117
+ ])));
118
+ }
@@ -0,0 +1,185 @@
1
+ import { type Hex } from "viem";
2
+ import { type Address, type Call, type DeploymentManifest, type Hash } from "./schema.js";
3
+ import { type StockToken } from "./stocks.generated.js";
4
+ import { type Swap } from "./wallet.js";
5
+ /**
6
+ * Quote assets: every asset a Hookr 1 market may quote in, the classes the app and the release tooling name them by,
7
+ * their decimals, and the ERC-20 funding a launch or trade needs.
8
+ *
9
+ * On chain the registry decides. HookrRoot.initializePool refuses a quote `isQuote` does not admit (UnqualifiedQuote);
10
+ * native ETH is always admitted, an ERC-20 through the reviewed catalog (SET_QUOTE), a whole class by runtime code hash
11
+ * (SET_QUOTE_CLASS, every Robinhood stock token) or, while open quotes are on (OPEN_QUOTES), any contract that is not an
12
+ * EIP-7702 delegated account, as the live launchpads accept. `curatedQuote` tells the first three from an open quote.
13
+ * Nothing here can admit a quote: `quoteAdmission` reads the registry at a block, and a class below is a label for
14
+ * guidance, never an admission.
15
+ *
16
+ * The classification follows the live app's v2-asset-class.ts: the curated catalog first (the only source that can
17
+ * name a stablecoin), then the ERC-1967 beacon slot (every Robinhood stock token is a BeaconProxy of one beacon), then
18
+ * fail closed to an unconfident "erc20".
19
+ */
20
+ /** ERC-1967 beacon slot: bytes32(uint256(keccak256("eip1967.proxy.beacon")) - 1). */
21
+ export declare const ERC1967_BEACON_SLOT: Hash;
22
+ /** ERC-1967 implementation slot: bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1). */
23
+ export declare const ERC1967_IMPLEMENTATION_SLOT: Hash;
24
+ /** The one beacon every Robinhood tokenized stock and ETF on chain 4663 proxies to (also its pause registry). */
25
+ export declare const ROBINHOOD_STOCK_BEACON: Address;
26
+ /** The runtime keccak256 every one of those proxies shares: OpenZeppelin BeaconProxy with that beacon immutable. */
27
+ export declare const ROBINHOOD_STOCK_PROXY_RUNTIME_KECCAK256: Hash;
28
+ /** Canonical Permit2: HookrForwarder pulls a gasless swap's ERC-20 input through it. */
29
+ export declare const PERMIT2: Address;
30
+ /**
31
+ * What a quote is, for guidance and labels. `native` is ETH (the zero address), `weth` wrapped ETH, `stable` the
32
+ * reviewed dollar token USDG, `hookr` the HOOKR token, `listed` every other token on the reviewed genesis catalog,
33
+ * `rwa` a Robinhood stock token, and `erc20` anything else.
34
+ */
35
+ export type QuoteClass = "native" | "weth" | "stable" | "hookr" | "listed" | "rwa" | "erc20";
36
+ /** How a classification was reached: rendered, so a reader knows what the answer rests on. */
37
+ export type QuoteSource = "native" | "catalog" | "beacon" | "unclassified";
38
+ export interface QuoteAsset {
39
+ address: Address;
40
+ /** Read from the token or the catalog; null when it could not be read. Never assumed. */
41
+ symbol: string | null;
42
+ /** Read from the token or the catalog; null when it could not be read. Never assumed to be 18. */
43
+ decimals: number | null;
44
+ class: QuoteClass;
45
+ source: QuoteSource;
46
+ /** False for an address neither the catalog nor the beacon identifies: its class is the fail-closed default. */
47
+ confident: boolean;
48
+ /** The stock token's onchain name, when the class is `rwa` and the scan list carries it. */
49
+ name?: string;
50
+ }
51
+ /** A reviewed catalog quote: exact onchain metadata and runtime, with the ERC-1967 implementation it proxies to. */
52
+ export interface CatalogQuote {
53
+ address: Address;
54
+ symbol: string;
55
+ name: string;
56
+ decimals: number;
57
+ class: Exclude<QuoteClass, "native" | "rwa" | "erc20">;
58
+ runtimeKeccak256: Hash;
59
+ /** The ERC-1967 implementation the proxy held when read, or null for a token that is not a proxy. */
60
+ implementation: Address | null;
61
+ }
62
+ /** The block the catalog below was read at (chain 4663, through Alchemy, 2026-10-06 00:54 UTC). */
63
+ export declare const ROBINHOOD_QUOTE_CATALOG_BLOCK = 81225166;
64
+ /**
65
+ * The genesis catalog the owner set on 2026-10-05: the 20 largest tokens on Robinhood Chain by market cap at
66
+ * ROBINHOOD_QUOTE_CATALOG_BLOCK that pass review (WETH and USDG among them) plus HOOKR and What The Hook's WTH, in the
67
+ * registry's queue order (the release template's `quoteAssets`).
68
+ * Every field was read from chain 4663 at ROBINHOOD_QUOTE_CATALOG_BLOCK, not copied from a document (USDG and
69
+ * syrupUSDG are 6 decimals). WETH, USDG and U are ERC-1967 proxies: a runtime hash alone does not review their upgrade
70
+ * authority.
71
+ */
72
+ export declare const ROBINHOOD_QUOTE_CATALOG: readonly CatalogQuote[];
73
+ /** Native ETH: the zero address in every pool key, 18 decimals, always admitted by the registry. */
74
+ export declare const NATIVE_QUOTE: QuoteAsset;
75
+ /** Display labels for each class. */
76
+ export declare const QUOTE_CLASS_LABELS: Readonly<Record<QuoteClass, string>>;
77
+ /** What a stock quote means for the pool, in the live classifier's words. */
78
+ export declare const STOCK_QUOTE_NOTE = "This token is a Robinhood tokenized stock: its proxy points at the shared beacon, so a pause there halts every pool holding it.";
79
+ /** Why an unclassified quote still warns. */
80
+ export declare const UNCLASSIFIED_QUOTE_NOTE = "This address is not on the verified list and does not point at the shared Robinhood stock beacon. It is treated as an ERC-20 you do not control: verify what it does on transfer before you use it.";
81
+ /** An upgradeable catalog quote. */
82
+ export declare const PROXY_QUOTE_NOTE = "This token is an upgradeable proxy: its issuer can change what it does, and every pool quoting it follows.";
83
+ /** A quote whose transfers move less or more than asked is refused by every Hookr transfer (exact settlement). */
84
+ export declare const EXACT_TRANSFER_NOTE = "Hookr settles exact amounts: a token that takes a fee on transfer, rebases or blocks addresses can make launches, trades and fee claims revert.";
85
+ /** The reviewed catalog entry for an address, or null. */
86
+ export declare function catalogQuote(target: string): CatalogQuote | null;
87
+ /** The scanned stock token at an address (its label), or null. A token absent here can still be a stock token. */
88
+ export declare function stockToken(target: string): StockToken | null;
89
+ /** A token's decimals as the contracts can use them: an integer from 0 to 36. Anything else throws. */
90
+ export declare function quoteDecimals(value: unknown): number;
91
+ /** Parses a decimal amount typed in quote units ("1.5") into raw units, refusing more places than the token has. */
92
+ export declare function parseQuoteAmount(text: string, decimals: number): bigint;
93
+ /** Formats a raw quote amount in its token's units. */
94
+ export declare function formatQuoteAmount(raw: bigint, decimals: number): string;
95
+ /** The address a 32-byte storage word holds, or null for an empty or malformed word. */
96
+ export declare function addressFromWord(word: unknown): Address | null;
97
+ /** The classification that needs no network: native ETH, the catalog and the scanned stock list. Null otherwise. */
98
+ export declare function classifyQuoteOffline(target: string): QuoteAsset | null;
99
+ /** The minimum a caller supplies to read the chain: a storage read and an eth_call. Mocked in tests. */
100
+ export interface QuoteReader {
101
+ getStorageAt(target: Address, slot: Hash): Promise<Hex | undefined>;
102
+ call(to: Address, data: Hex): Promise<Hex>;
103
+ }
104
+ /**
105
+ * The full classification: native, the catalog, then the ERC-1967 beacon slot, then an unconfident "erc20". Decimals
106
+ * and symbol are read from the token and are null when it does not answer (a quote without decimals cannot be priced
107
+ * or funded, so callers refuse it). A read that throws degrades to "erc20", never to a safer class.
108
+ */
109
+ export declare function classifyQuote(reader: QuoteReader, target: string): Promise<QuoteAsset>;
110
+ /**
111
+ * The warnings a quote carries before anyone launches or trades against it, in display order. `curated` is the
112
+ * registry's `curatedQuote` answer (`quoteAdmission`): false adds the open-quote note.
113
+ */
114
+ export declare function quoteWarnings(q: QuoteAsset, curated?: boolean | null): string[];
115
+ /** A read-only registry isQuote call for `asset` at the manifest's registry. */
116
+ export declare function buildIsQuote(m: DeploymentManifest, asset: Address): {
117
+ to: Address;
118
+ data: Hex;
119
+ };
120
+ /** Whether the registry admits `asset` as a new market's quote, by an eth_call the caller pins to a block. */
121
+ export declare function quoteAdmitted(ethCall: (to: Address, data: Hex) => Promise<Hex>, m: DeploymentManifest, asset: Address): Promise<boolean>;
122
+ /**
123
+ * What the registry says of a quote at the caller's block: `admitted`, whether a new pool may bind it (`isQuote`), and
124
+ * `curated`, whether it is native ETH, a catalog asset or a class member rather than admitted only by open quotes.
125
+ * `curated` is null when the registry does not answer `curatedQuote` (a release without quote classes, where every
126
+ * admitted quote is a catalog asset) or the read fails; a caller then labels the quote by its classification alone.
127
+ */
128
+ export declare function quoteAdmission(ethCall: (to: Address, data: Hex) => Promise<Hex>, m: DeploymentManifest, asset: Address): Promise<{
129
+ admitted: boolean;
130
+ curated: boolean | null;
131
+ }>;
132
+ /** The note an open quote carries: the registry admits it without any review. */
133
+ export declare const OPEN_QUOTE_NOTE = "The registry admits this token only because open quotes are on: nobody reviewed it. Check its address before you use it.";
134
+ /**
135
+ * Refuses a member quote the Launcher or the root would refuse before any pool opens, and one no amount could be read
136
+ * in: the subject itself, a quote repeated in one family, or an ERC-20 without known decimals. Registry admission is
137
+ * checked on chain (`quoteAdmitted`).
138
+ */
139
+ export declare function checkLaunchQuotes(subject: Address | null, quotes: readonly QuoteAsset[]): void;
140
+ /** An ERC-20 allowance an action needs: `spender` must be approved for `amount` of `token` from the signer. */
141
+ export interface Allowance {
142
+ token: Address;
143
+ spender: Address;
144
+ amount: bigint;
145
+ }
146
+ /** What a launch collects from its caller: native value and each ERC-20 the Launcher pulls, summed per token. */
147
+ export interface LaunchFunding {
148
+ native: bigint;
149
+ allowances: Allowance[];
150
+ }
151
+ /**
152
+ * The funding HookrLauncher.launch / launchAdvised / launchWithBuy / launchFamily collects from the caller: for every
153
+ * member, its quote side's maximum (amount1Max when the subject sorts first, else amount0Max) plus the dev buy's quoteIn
154
+ * on each buy's member (launchFamily takes up to one per member); for an existing subject, the subject side's maxima too
155
+ * (a new token is minted to the Launcher); and the launch fee in native value (r31, `launchFee`, read at the launch
156
+ * block). Native ETH is the call's value; each ERC-20 needs an allowance to the Launcher of the listed amount.
157
+ */
158
+ export declare function launchFunding(m: DeploymentManifest, subject: Address, existingSubject: boolean, members: readonly Record<string, unknown>[], launchFee: bigint, buys?: readonly {
159
+ member: number;
160
+ quoteIn: bigint;
161
+ }[]): LaunchFunding;
162
+ /**
163
+ * The ERC-20 allowance HookrRouter.swap needs: the input currency's exact amount for exact input, the bound for exact
164
+ * output, to the router. Null when the input is native ETH (sent as value). Through HookrForwarder (gasless) the
165
+ * allowance goes to Permit2 instead: `permit2Allowance`.
166
+ */
167
+ export declare function swapAllowance(m: DeploymentManifest, s: Swap): Allowance | null;
168
+ /** A gasless swap's ERC-20 input needs a Permit2 allowance; the intent's signature then authorizes each pull. */
169
+ export declare function permit2Allowance(token: Address, amount: bigint): Allowance;
170
+ /**
171
+ * The ERC-20 approve for an allowance. `current` is the signer's allowance now: a token that refuses to move a
172
+ * nonzero allowance to another nonzero value (USDT-style) is reset to zero first, so pass it and send the calls in
173
+ * order. Returns no call when the allowance already covers the amount.
174
+ */
175
+ export declare function buildApprovals(m: DeploymentManifest, a: Allowance, current?: bigint): Call[];
176
+ /**
177
+ * The Robinhood stock tokens as one reviewed quote class (SET_QUOTE_CLASS): the runtime keccak256 every proxy of the
178
+ * stock beacon shares, the beacon it embeds, and AAPL as the witness the registry checks the hash against.
179
+ */
180
+ export declare const ROBINHOOD_STOCK_QUOTE_CLASS: Readonly<{
181
+ label: "Robinhood stock tokens";
182
+ runtimeKeccak256: `0x${string}`;
183
+ beacon: `0x${string}`;
184
+ witness: Address;
185
+ }>;