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
package/CHANGELOG.md ADDED
@@ -0,0 +1,38 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0
4
+
5
+ Hookr 1. The package now builds on the `hookr-1` release on Robinhood Chain: one root, `HookrRoot`, whose pools each freeze their own Hook Blocks and, when they want it, arb recapture.
6
+
7
+ ### What is new
8
+
9
+ - `HOOKR_1`: every contract of the production release, fixed by CREATE3, and `HOOKR_1.deployment`, the release's deployment as its source verification records it. `CANARY_HOOKR_1_A` names the canary under its own release id. It is not for users.
10
+ - `readReleaseManifest(client, HOOKR_1)`: the manifest every builder takes. It reads the code at each address and refuses it unless it is the code the release deployed. `releaseManifest(HOOKR_1)` builds the same manifest with no reads.
11
+ - `ROBINHOOD_CHAIN`: the chain for viem, on any viem 2, with RobinScan as its explorer.
12
+ - Launch: `buildLaunch` and `buildLaunchAdvised` open one to eight pools of a new or existing token in one call. `buildLaunchFamily` adds a dev buy, supply weights and an opening price check. `launchFunding` lists exactly what a launch pulls.
13
+ - Hook Blocks: `RULE_PARAMS` has every setting with its range and default. `defaultRulesLaunch`, `checkRuleParams` and `rulesPoolTerms` check a pool against the contracts' own bounds before it is sent.
14
+ - Quote and swap: `buildQuote` and `buildSwap` for `HookrQuoter` and `HookrRouter`, `swapAllowance` and `buildApprovals` for ERC-20 input. The quoter also answers Uniswap's `quoteExactInputSingle` and `quoteExactOutputSingle`.
15
+ - Quotes: the 22-quote genesis catalog (`ROBINHOOD_QUOTE_CATALOG`), the 204 Robinhood stock tokens, and `classifyQuote`, `quoteWarnings` and `quoteAdmission`.
16
+ - Arb recapture: Hookr takes 25% of each profit (`RECAPTURE_PROTOCOL_BPS`), What The Hook up to 25% (`MAX_LANE_PARTNER_BPS`), and the rest goes as the pool froze it at launch. `recaptureSplit` works it out. `laneGasFloor` gives the gas a swap needs while a pool's lane is on.
17
+ - ABIs: the call ABIs for the root, router, quoter, launcher, HookrRules, HookrRecapture and the registry, and in `ARTIFACT_ABIS` the full ABIs of the registry, HookrRules, the treasury, the advisories, the liquidity vault, the family contracts and the owned-root contracts. Also the advisories, the registry's typed operations, the liquidity vault, referrals and reward proofs.
18
+ - `provenance.json`: the release's source commit and the hash of every file of the release SDK this package carries.
19
+
20
+ ### Breaking changes from 0.2.x
21
+
22
+ Of the 0.2.x exports only these carry over: `CHAIN_ID`, `RPC_URL`, `EXPLORER_URL`, `explorerAddressUrl`, `explorerTxUrl`, the `PoolKey` type, `DYNAMIC_FEE`, `MIN_SQRT_PRICE_LIMIT`, `MAX_SQRT_PRICE_LIMIT`, `DEFAULT_PROTOCOL_SHARE_BPS` (2,000), `MAX_PROTOCOL_SHARE_BPS` (5,000) and `MAX_GUARD_BLOCKS` (100,000). `EXPLORER_URL` is now RobinScan, `https://robin.etherscan.io`, where every contract's source is verified, so `explorerAddressUrl` and `explorerTxUrl` open RobinScan. `RootStatus` keeps its name with a new shape: the registry's `rootStatus(root)`, `{ advisory, verified }`. The builders return `{ chainId, to, data, value }` for `sendTransaction`, not `writeContract` arguments, and take the release manifest. Node 18.16 or newer. [MIGRATING.md](https://unpkg.com/hookr-sdk@1/MIGRATING.md) maps the exports in common use. Every other 0.2.x export is removed.
23
+
24
+ 0.2.x keeps working for pools on the earlier roots, `HookrModularHookV6` and `HookrModularHookV6WthV5`.
25
+
26
+ ## 0.2.1 (2026-09-22)
27
+
28
+ - The swap builders take `correcting` (default `isCorrectingRoot(key.hooks)`, the current recapture root), and `poolCorrects(rules)` reads from a pool's frozen rules whether it names a correction executor, so a pool on a superseded recapture root can carry the gas floor too.
29
+
30
+ A later 0.2.x change, `listMarkets` reading in windows of at most 5,000 blocks, was never published.
31
+
32
+ ## 0.2.0 (2026-09-21)
33
+
34
+ - Names both live roots (`ADDRESSES.recaptureRoot`, `RECAPTURE_KERNEL_ID`, `ROOTS`). The market builders take `root` and freeze the recapture correction fields (`RECAPTURE_CORRECTION`). Swap calls carry `gas: CORRECTION_SWAP_GAS_FLOOR` on a correcting root. `listMarkets` scans in windows. `listRoots` reads every registered root from the registry.
35
+
36
+ ## 0.1.0 (2026-09-10)
37
+
38
+ - First release, default root only.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hookr
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/MIGRATING.md ADDED
@@ -0,0 +1,89 @@
1
+ # Moving from 0.2.x to 1.0
2
+
3
+ 1.0 builds on Hookr 1, the `hookr-1` release. 0.2.x builds on the earlier roots. Both sets of pools live on Robinhood Chain, and each package only talks to its own.
4
+
5
+ ## Keep 0.2.x for the earlier roots
6
+
7
+ Pools on `HookrModularHookV6` (`0xb3cA29cF721380CEe8b8e4755F3865Ebc68Fe8cC`) and `HookrModularHookV6WthV5` (`0xb914f955294799de4b891bd2EA8AF628Fa1c68CC`) keep trading. 0.2.x stays on npm for them:
8
+
9
+ ```
10
+ npm install hookr-sdk@0.2
11
+ ```
12
+
13
+ An app that serves both sets of pools can install both under two names:
14
+
15
+ ```
16
+ npm install hookr-sdk hookr-sdk-v0@npm:hookr-sdk@0.2
17
+ ```
18
+
19
+ Pick by the pool's `PoolKey.hooks`: `HOOKR_1.contracts.HookrRoot` is 1.0's, the two roots above are 0.2.x's.
20
+
21
+ ## What changes
22
+
23
+ One root instead of two. Arb recapture is no longer a separate root: each pool turns it on or off at launch in its `RecaptureConfig`, on the same `HookrRoot`.
24
+
25
+ The builders return a call, `{ chainId, to, data, value }`, and take the release's manifest:
26
+
27
+ ```ts
28
+ // 0.2.x
29
+ const call = buildExactInputSwapCall({ key, currencyIn, amountIn, amountOutMinimum, recipient, deadline });
30
+ await walletClient.writeContract(call);
31
+
32
+ // 1.0
33
+ const manifest = await readReleaseManifest(client, HOOKR_1);
34
+ const call = buildSwap(manifest, { key, zeroForOne, amountSpecified: -amountIn, amountBound: amountOutMinimum, sqrtPriceLimitX96, recipient, deadline });
35
+ await walletClient.sendTransaction({ to: call.to, data: call.data, value: call.value });
36
+ ```
37
+
38
+ ## Export by export
39
+
40
+ | 0.2.x | 1.0 |
41
+ | --- | --- |
42
+ | `ADDRESSES.root`, `ADDRESSES.recaptureRoot`, `ROOTS` | `HOOKR_1.contracts.HookrRoot` |
43
+ | `ADDRESSES.router` | `HOOKR_1.contracts.HookrRouter` |
44
+ | `ADDRESSES.quoter` | `HOOKR_1.contracts.HookrQuoter` |
45
+ | `ADDRESSES.coordinator` | `HOOKR_1.contracts.HookrLauncher` |
46
+ | `ADDRESSES.nativeBlock` | `HOOKR_1.contracts.HookrRules` |
47
+ | `ADDRESSES.registry` | `HOOKR_1.contracts.HookrRegistry` |
48
+ | `KERNEL_ID`, `RECAPTURE_KERNEL_ID`, `MODULE_ID`, `RECAPTURE_CORRECTION`, `isRecaptureRoot` | none: one root, and arb recapture is each pool's `RecaptureConfig`. Pass `RECAPTURE_OFF`, or `recaptureDefaults()` read with `recaptureAbi` at the HookrRules address |
49
+ | `NATIVE_ADDRESS` | `ZERO` |
50
+ | `EXPLORER_URL`, `explorerAddressUrl`, `explorerTxUrl` | the same names, on RobinScan (`https://robin.etherscan.io`) |
51
+ | `DYNAMIC_FEE`, `MIN_SQRT_PRICE_LIMIT`, `MAX_SQRT_PRICE_LIMIT` | the same names and values |
52
+ | `fullFillLimit(zeroForOne)` | `MIN_SQRT_PRICE_LIMIT` for `zeroForOne`, `MAX_SQRT_PRICE_LIMIT` the other way |
53
+ | `swapDirection(key, currencyIn)` | `zeroForOne` is `currencyIn === key.currency0` |
54
+ | `subjectIsCurrency0(subject, quote)` | the lower address is `currency0`, as in every v4 `PoolKey` |
55
+ | `INT128_MAX`, `QUOTE_MIN_OUT_BOUND`, `EMPTY_MODULE_DATA` | none: `amountBound: 1n` on an exact-input quote, and a swap carries no module data |
56
+ | `MAX_TOTAL_FEE_PIPS`, `MIN_BASE_FEE_PIPS`, `baseFeeBounds` | `MAX_LP_FEE_PIPS` (600,000), and `baseLpFeePips` in `RULE_PARAMS.pool`, with its range |
57
+ | `RULES`, `PARAMS`, `RULE_ORDER`, `ruleFor`, `MAX_STACK_RULES`, `defaultBlock`, `defaultStack`, `validateStack`, `compileRuleBlocks` | `RULE_PARAMS`, `defaultRulesLaunch`, `defaultRuleParams`, `checkRuleParams`, `rulesPoolTerms` |
58
+ | `encodeNativeBlockConfig`, `decodeNativeBlockConfig` | `encodeRulesConfig`, `decodeRulesConfig` |
59
+ | `guardEndBlockFor` | `defaultRulesLaunch` sets `guardEndBlock` from the block number. `MAX_GUARD_BLOCKS` keeps its value |
60
+ | `MODULE_GAS`, `stackLimitsFor`, `correctionFor` | `rulesPoolTerms`, which returns the pool's caps and gas |
61
+ | `ZERO_BYTES32` | `zeroHash` from viem |
62
+ | `feeModel` | `rulesQuote`, `rulesSwapFees`, `recaptureSplit` |
63
+ | `poolKeyFor`, `poolIdFor` | a `PoolKey` with `fee: DYNAMIC_FEE` and `hooks: HOOKR_1.contracts.HookrRoot`, and `poolId(key)` |
64
+ | `buildNewTokenMarketCall` | `buildLaunch` with `token.existing` zero |
65
+ | `buildExistingTokenMarketCall` | `buildLaunch` with `token.existing` the token |
66
+ | `encodeMarketCall` | the `data` of the call `buildLaunch` returns |
67
+ | `buildExactInputSwapCall`, `buildExactOutputSwapCall` | `buildSwap`: a negative `amountSpecified` is exact input, a positive one exact output |
68
+ | `quoteExactInput` | `buildQuote`, sent as an `eth_call` from the payer |
69
+ | `CORRECTION_SWAP_GAS_FLOOR`, `swapGasLimit`, `isCorrectingRoot`, `poolCorrects` | `gasFloor` from `laneOf(id)` on `HookrRoot` (`laneRootAbi`), `laneGasFloor(gasCap)` |
70
+ | `readMarket`, `readPoolRules` | `poolConfig(id)` on `HookrRoot` (`rootAbi`), `config(id)` on the pool's HookrRules (`rulesAbi`), `laneOf(id)` (`laneRootAbi`) |
71
+ | `listMarkets`, `listRoots`, `MARKET_CREATED_TOPIC`, `MARKET_SCAN_FROM_BLOCK`, `MARKET_SCAN_CHUNK_BLOCKS`, `MARKET_SCAN_CONCURRENCY` | none: read `PoolOpened` (`rootAbi`) and `MemberLaunched` (`launcherAbi`) with your own log reader |
72
+ | `MAX_LOG_BLOCK_RANGE`, `logBlockRange`, `logBlockRanges`, `capLogSpan` | none: ask for at most 5,000 blocks a request |
73
+ | `claimableCall`, `claimCall`, `claimToCall` | `claimable`, `claim` and `claimTo` on `HookrRules` (`rulesAbi`) |
74
+ | `ReadCall`, `WriteCall`, `RouterCall`, `CoordinatorCall` | `Call`: `{ chainId, to, data, value }` |
75
+ | `builderLink`, `launchLink`, `encodeStack`, `decodeStack`, `decodeStackBaseFeePips`, `DEFAULT_ORIGIN`, `DEFAULT_BASE_FEE_PIPS` | none |
76
+ | `hookrKernelRouterV3Abi`, `hookrKernelQuoterV1Abi`, `hookrMarketCoordinatorV5Abi`, `hookrNativeMechanicsBlockV2Abi`, `hookrStackRegistryV2Abi` | `routerAbi`, `quoterAbi`, `launcherAbi`, `rulesAbi`, `registryAbi`, and the full ABIs in `ARTIFACT_ABIS` |
77
+ | every other 0.2.x export | removed |
78
+
79
+ `CHAIN_ID`, `RPC_URL`, `PoolKey`, `DYNAMIC_FEE`, `MIN_SQRT_PRICE_LIMIT`, `MAX_SQRT_PRICE_LIMIT`, `DEFAULT_PROTOCOL_SHARE_BPS`, `MAX_PROTOCOL_SHARE_BPS` and `MAX_GUARD_BLOCKS` keep their names and values. `EXPLORER_URL`, `explorerAddressUrl` and `explorerTxUrl` keep their names and open RobinScan, where 0.2.x opened Blockscout. `RootStatus` keeps its name with a new shape.
80
+
81
+ ## Fees and arb recapture
82
+
83
+ On the earlier recapture roots Hookr and What The Hook each took 10% of an arb recapture's profit. On Hookr 1 each takes 25%: Hookr's `RECAPTURE_PROTOCOL_BPS` is 2,500 and What The Hook keeps at most `MAX_LANE_PARTNER_BPS`, 2,500. The rest is the pool's, as it froze it at launch.
84
+
85
+ A swap on a Hookr 1 pool with arb recapture on carries the lane's gas floor, 6,802,619 at the lane's 3,000,000 gas cap, where 0.2.x put 1,100,000 on a correcting root. The swap's own gas comes on top, so estimate and add a sixth, or use a fixed limit of at least 7.5 million. See [Gas](https://www.npmjs.com/package/hookr-sdk#gas) in the README.
86
+
87
+ ## Requirements
88
+
89
+ Node 18.16 or newer, viem 2, ESM. `ROBINHOOD_CHAIN` works on any viem 2. viem's own `robinhood` chain needs viem 2.55 or newer.
package/README.md CHANGED
@@ -1,17 +1,16 @@
1
1
  # hookr-sdk
2
2
 
3
- Build a market on Hookr's live root hooks with a custom rule configuration, quote and swap
4
- through Hookr's router, read markets, and claim payouts, on Robinhood Chain (id 4663).
3
+ Build on Hookr 1, the Uniswap v4 hook on Robinhood Chain: launch tokens with Hook Blocks, open pools, quote, swap and claim.
5
4
 
6
- Two roots are live. A pool names exactly one of them in `PoolKey.hooks`:
5
+ The package carries the `hookr-1` release: its addresses, its deployment, its ABIs, the 22-quote catalog, every Hook Block's bounds and the builders hookr.fun itself uses. It holds no wallet and signs nothing. Each builder returns `{ chainId, to, data, value }` for your wallet to send.
7
6
 
8
- | Root | Export | What it runs |
9
- | --- | --- | --- |
10
- | `HookrModularHookV6` | `ADDRESSES.root`, `ROOTS.default` | the five native rules |
11
- | `HookrModularHookV6WthV5` | `ADDRESSES.recaptureRoot`, `ROOTS.recapture` | the same five rules plus the arbitrage-recapture lane |
12
-
13
- Earlier recapture roots still hold trading pools. Their pools read back like any other, so resolve
14
- a root from the pool's own `PoolKey.hooks` or from the registry rather than from a list.
7
+ - [Install](#install)
8
+ - [Quick start](#quick-start)
9
+ - [Addresses](#addresses)
10
+ - [Arb recapture](#arb-recapture)
11
+ - [Gas](#gas)
12
+ - [Quotes](#quotes)
13
+ - [What is in the package](#what-is-in-the-package)
15
14
 
16
15
  ## Install
17
16
 
@@ -19,135 +18,317 @@ a root from the pool's own `PoolKey.hooks` or from the registry rather than from
19
18
  npm install hookr-sdk viem
20
19
  ```
21
20
 
22
- ## RPC
21
+ ESM only, with TypeScript types. Node 18.16 or newer and viem 2. `ROBINHOOD_CHAIN` is the chain for viem, with RobinScan as its explorer. On viem 2.55 or newer, `robinhood` from `viem/chains` is the same chain with Blockscout as its explorer.
22
+
23
+ ## Quick start
24
+
25
+ ### Set up
23
26
 
24
- `RPC_URL` is the chain's public, keyless endpoint. It is fine for a few reads. Under load it rate
25
- limits, and a wide `eth_getLogs` can come back as an empty array instead of an error. `listMarkets`
26
- scans in windows of `MARKET_SCAN_CHUNK_BLOCKS` (3,000,000 blocks, the width the app's own scanners
27
- use; pass `chunkBlocks` to lower it) so no single answer is wide, but anything that must not miss
28
- data should still run on a provider endpoint you own:
27
+ Every builder takes the release's manifest: each contract it calls, at its address, with its runtime code hash. `readReleaseManifest` reads that code from chain and refuses it unless every contract runs the code the release deployed.
29
28
 
30
29
  ```ts
31
- import { http } from "viem";
32
- import { RPC_URL } from "hookr-sdk";
30
+ import "viem/window";
31
+ import { createPublicClient, createWalletClient, custom, http } from "viem";
32
+ import { HOOKR_1, ROBINHOOD_CHAIN, readReleaseManifest } from "hookr-sdk";
33
33
 
34
- const transport = http(process.env.HOOKR_RPC_URL ?? RPC_URL);
34
+ const client = createPublicClient({ chain: ROBINHOOD_CHAIN, transport: http() });
35
+ const wallet = createWalletClient({ chain: ROBINHOOD_CHAIN, transport: custom(window.ethereum!) });
36
+ const [account] = await wallet.getAddresses();
37
+
38
+ const manifest = await readReleaseManifest(client, HOOKR_1);
35
39
  ```
36
40
 
37
- ## List and validate rules
41
+ `releaseManifest(HOOKR_1)` builds the same manifest from the package alone, with no reads.
42
+
43
+ `http()` uses the chain's public node. It is fine for a few reads. Anything that scans logs or must not miss data should use a provider endpoint of its own.
44
+
45
+ ### Read a pool
46
+
47
+ A Hookr pool is a Uniswap v4 pool whose `PoolKey.hooks` is `HookrRoot`. Its fee is `DYNAMIC_FEE`: the hook sets the LP fee on every swap.
38
48
 
39
49
  ```ts
40
- import { RULES, PARAMS, defaultBlock, validateStack } from "hookr-sdk";
50
+ import { DYNAMIC_FEE, HOOKR_1, ZERO, laneRootAbi, poolId, rootAbi, rulesAbi, type PoolKey } from "hookr-sdk";
51
+
52
+ const key: PoolKey = {
53
+ currency0: ZERO, // native ETH sorts first
54
+ currency1: tokenAddress,
55
+ fee: DYNAMIC_FEE,
56
+ tickSpacing: 60,
57
+ hooks: HOOKR_1.contracts.HookrRoot,
58
+ };
59
+ const id = poolId(key);
60
+
61
+ const config = await client.readContract({ address: HOOKR_1.contracts.HookrRoot, abi: rootAbi, functionName: "poolConfig", args: [id] });
62
+ const blocks = await client.readContract({ address: config.rules, abi: rulesAbi, functionName: "config", args: [id] });
63
+ const [executor, codeHash, partnerBps, family, laneOn, gasCap, gasFloor] = await client.readContract({
64
+ address: HOOKR_1.contracts.HookrRoot,
65
+ abi: laneRootAbi,
66
+ functionName: "laneOf",
67
+ args: [id],
68
+ });
69
+ ```
70
+
71
+ `config` is the pool's `PoolConfig`: its quote, base LP fee and caps, and the HookrRules contract that holds its Hook Blocks. `blocks` is those Hook Blocks as frozen at launch: Anti-Snipe, the dynamic fee, Auto Burn, LP Rewards, the royalty and the protocol share. `laneOn` says whether arb recapture runs on the pool, and `gasFloor` is the least gas a swap must carry while it does. See [Gas](#gas).
41
72
 
42
- console.log(RULES.map((r) => r.key)); // ["snipe", "fee", "burn", "lp", "pot"]
73
+ ### Quote
43
74
 
44
- const stack = [defaultBlock("fee"), defaultBlock("lp")];
45
- const { ok, errors } = validateStack(stack);
75
+ `HookrQuoter` simulates the swap through the pool's own callbacks, so the quote is what the swap pays and gets, fees and Hook Blocks included. Send it as an `eth_call` from the real payer.
76
+
77
+ ```ts
78
+ import { decodeFunctionResult, parseEther } from "viem";
79
+ import { MIN_SQRT_PRICE_LIMIT, buildQuote, quoterAbi } from "hookr-sdk";
80
+
81
+ const swap = {
82
+ key,
83
+ zeroForOne: true, // ETH in, token out
84
+ amountSpecified: -parseEther("0.1"), // negative: exact input
85
+ amountBound: 1n, // the least out, set from the quote below
86
+ sqrtPriceLimitX96: MIN_SQRT_PRICE_LIMIT, // fill in full; MAX_SQRT_PRICE_LIMIT the other way
87
+ recipient: account,
88
+ deadline: BigInt(Math.floor(Date.now() / 1000) + 600), // at most an hour ahead
89
+ };
90
+
91
+ const quote = buildQuote(manifest, swap, account);
92
+ const { data } = await client.call({ account, to: quote.to, data: quote.data });
93
+ const receipt = decodeFunctionResult({ abi: quoterAbi, functionName: "quote", data: data! });
94
+ // receipt.outputAmount, receipt.quoteFee, receipt.subjectBurn, receipt.lpFeePips
46
95
  ```
47
96
 
48
- ## Build and send a create-market call
97
+ ### Swap
49
98
 
50
- A market opens on the default root unless `root: ROOTS.recapture` is passed. On the recapture
51
- root the builder also freezes the five correction fields of the stack (`RECAPTURE_CORRECTION`
52
- plus the creator), without which the pool would carry that root's name and never correct. The
53
- registry admits that lane on native-ETH-quoted pools only, so the builder throws on any other
54
- quote, and it needs `creator` (the launching wallet) to freeze as the correction creator.
99
+ `buildSwap` calls `HookrRouter.swap`. Native ETH in rides as the call's value. An ERC-20 in needs an allowance to the router first: `swapAllowance` says how much, `buildApprovals` builds the calls.
55
100
 
56
101
  ```ts
57
- import { createWalletClient, http } from "viem";
58
- import { CHAIN_ID, NATIVE_ADDRESS, ROOTS, buildExistingTokenMarketCall } from "hookr-sdk";
102
+ import { buildSwap } from "hookr-sdk";
59
103
 
60
- const call = buildExistingTokenMarketCall({
61
- subject: token, quote: usdcAddress, tickSpacing: 60, sqrtPriceX96,
62
- rules: { baseFeePips: 3_000, blocks: stack },
63
- protocolRecipient, protocolShareBps, caps, // read from the coordinator and native block first
64
- });
65
- const hash = await walletClient.writeContract(call);
66
-
67
- // The same market on the recapture root: native ETH quote, and the creator wallet.
68
- const recaptureCall = buildExistingTokenMarketCall({
69
- subject: token, quote: NATIVE_ADDRESS, tickSpacing: 60, sqrtPriceX96,
70
- rules: { baseFeePips: 3_000, blocks: stack },
71
- protocolRecipient, protocolShareBps, caps,
72
- root: ROOTS.recapture, creator: account.address,
73
- });
104
+ const minOut = (receipt.outputAmount * 995n) / 1000n; // 0.5% slippage
105
+ const swapCall = buildSwap(manifest, { ...swap, amountBound: minOut });
106
+
107
+ // With arb recapture on, the estimate includes the lane's gas floor, so it runs above 7.4 million.
108
+ const estimate = await client.estimateGas({ account, to: swapCall.to, data: swapCall.data, value: swapCall.value });
109
+ const hash = await wallet.sendTransaction({ account, to: swapCall.to, data: swapCall.data, value: swapCall.value, gas: estimate + estimate / 6n });
74
110
  ```
75
111
 
76
- `caps` comes from `nativeMechanicsBlock.validateStack(...)`; `protocolShareBps` from
77
- `marketCoordinator.protocolShareBps(creator)`. See `market.ts`'s module doc for what this
78
- package computes and what it takes as an already-resolved input.
112
+ When the estimate fails, the swap would revert as built. Check the quote, the allowance and the deadline before you try again.
79
113
 
80
- ## Read a market, quote, and swap
114
+ ### Launch a token with Hook Blocks
81
115
 
82
- `poolKeyFor` defaults `hooks` to the default root. Pass `hooks: ADDRESSES.recaptureRoot` for a
83
- pool on the recapture root, or use the `kernel` a `readMarket` row carries.
116
+ One launch creates the token and opens its pools, each with its own Hook Blocks, frozen when the pool opens. `defaultRulesLaunch` sets every block to its default. Change what you want, and `rulesPoolTerms` checks every value against the contracts' bounds and returns the pool's caps and gas.
84
117
 
85
118
  ```ts
86
- import { createPublicClient, http } from "viem";
87
- import { ADDRESSES, readMarket, poolKeyFor, quoteExactInput, buildExactInputSwapCall } from "hookr-sdk";
88
-
89
- const client = createPublicClient({ transport });
90
- const market = await readMarket(client, poolId);
91
- const key = poolKeyFor({
92
- subject: market.subject, quote: market.quote, tickSpacing: market.tickSpacing,
93
- hooks: market.kernel, // ADDRESSES.root or ADDRESSES.recaptureRoot
94
- });
95
- const { amountOut } = await quoteExactInput(client, { key, user, currencyIn: market.quote, amountIn });
96
- const swapCall = buildExactInputSwapCall({ key, currencyIn: market.quote, amountIn, amountOutMinimum, recipient: user, deadline });
119
+ import { zeroHash } from "viem";
120
+ import {
121
+ ARTIFACT_ABIS,
122
+ HOOKR_1,
123
+ RECAPTURE_OFF,
124
+ ZERO,
125
+ buildLaunch,
126
+ defaultRulesLaunch,
127
+ launchFeeAbi,
128
+ rulesAbi,
129
+ rulesPoolTerms,
130
+ type Admission,
131
+ } from "hookr-sdk";
132
+
133
+ const { HookrRegistry, HookrRoot, HookrRules, HookrLauncher } = HOOKR_1.contracts;
134
+ const blockNumber = await client.getBlockNumber();
135
+ const [open, admission, minProtocolShareBps, [launchFee]] = await Promise.all([
136
+ client.readContract({ address: HookrRegistry, abi: ARTIFACT_ABIS.HookrRegistry, functionName: "rootOpenFor", args: [HookrRoot, account] }),
137
+ client.readContract({ address: HookrRegistry, abi: ARTIFACT_ABIS.HookrRegistry, functionName: "admission", args: [HookrRoot, HookrRules] }),
138
+ client.readContract({ address: HookrRules, abi: rulesAbi, functionName: "minProtocolShareBps" }),
139
+ client.readContract({ address: HookrLauncher, abi: launchFeeAbi, functionName: "launchFee" }),
140
+ ]);
141
+ if (!open) throw new Error("The root takes no launch from this wallet now");
142
+
143
+ // Your opening price and range. ETH is currency0, so amount0Max is the ETH you seed.
144
+ const seed = { sqrtPriceX96, tickLower, tickUpper, liquidity, amount0Max, amount1Max };
145
+ const ctx = {
146
+ blockNumber,
147
+ minProtocolShareBps,
148
+ launchLiquidity: seed.liquidity,
149
+ launchSqrtPriceX96: seed.sqrtPriceX96,
150
+ quoteIsCurrency0: true,
151
+ liquidityOwner: HookrLauncher,
152
+ };
153
+
154
+ const settings = defaultRulesLaunch(ctx);
155
+ settings.rules.burnBps = 50; // Auto Burn, in basis points
156
+ settings.rules.lpBps = 300; // LP Rewards, in basis points
157
+ const terms = rulesPoolTerms(settings, ctx, admission as Admission);
158
+
159
+ const member = {
160
+ quote: ZERO,
161
+ tickSpacing: settings.tickSpacing,
162
+ ...seed,
163
+ config: {
164
+ subject: ZERO, // the launcher fills in the token
165
+ quote: ZERO,
166
+ rules: HookrRules,
167
+ advisory: ZERO,
168
+ liquidityOwner: HookrLauncher,
169
+ baseLpFeePips: settings.baseLpFeePips,
170
+ caps: terms.caps,
171
+ rulesGasLimit: terms.rulesGasLimit,
172
+ advisoryGasLimit: terms.advisoryGasLimit,
173
+ advisoryPhases: terms.advisoryPhases,
174
+ advisoryFailOpen: false,
175
+ policyId: zeroHash,
176
+ },
177
+ rules: settings.rules,
178
+ recapture: RECAPTURE_OFF,
179
+ };
180
+
181
+ const token = { existing: ZERO, name: "Hook", symbol: "HOOK", supply: 10n ** 27n, salt };
182
+ const deadline = BigInt(Math.floor(Date.now() / 1000) + 600);
183
+ const launchCall = buildLaunch(manifest, token, HookrRoot, [member], seed.amount0Max, deadline, launchFee);
184
+ await wallet.sendTransaction({ account, to: launchCall.to, data: launchCall.data, value: launchCall.value });
97
185
  ```
98
186
 
99
- A swap on a recapture pool needs more gas than an estimate reports, because the correction is
100
- fail-open: an estimate converges on the cheapest swap that succeeds, which is the one that skipped
101
- the correction. The swap builders put `gas: CORRECTION_SWAP_GAS_FLOOR` (1,100,000, the app's
102
- floor) on the call whenever the pool's root is the current recapture root, so pass the call to
103
- `writeContract` as it is; on the default root the call carries no `gas` and the wallet estimates
104
- as usual. A pool opened on a superseded recapture root keeps its executor and keeps correcting;
105
- read `poolCorrects(await readPoolRules(client, poolId))` and pass it as `correcting` to the swap
106
- builders to put the same floor on that call (since 0.2.1).
187
+ One launch opens one to eight pools of the same token, each on its own quote: pass more members. `buildLaunchAdvised` binds an advisory per pool, and `buildLaunchFamily` adds a dev buy, supply weights and an opening price check. `HookrLauncher.predictToken(creator, token)` gives the token's address before you send.
188
+
189
+ A member with arb recapture on takes the release's default `RecaptureConfig` in place of `RECAPTURE_OFF`, once the root's lane is open. Read it with `recaptureAbi` at the HookrRules address: `recaptureDefaults()` belongs to HookrRecapture, which HookrRules reaches for every call it does not handle itself.
190
+
191
+ ```ts
192
+ import { recaptureAbi } from "hookr-sdk";
193
+
194
+ const [recapture] = await client.readContract({ address: HookrRules, abi: recaptureAbi, functionName: "recaptureDefaults" });
195
+ const recaptureMember = { ...member, recapture };
196
+ ```
107
197
 
108
- ## Roots
198
+ ### Open pools for an existing token
109
199
 
110
- `ROOTS` names the two roots Hookr opens markets on today. The registry itself never retires a
111
- root, so `listRoots` shows every kernel it has registered, current or not, with its status and
112
- whether its profile is sealed (the coordinator opens markets on sealed profiles only):
200
+ The same launch, with the token named and nothing to mint. The launcher pulls the token side of each pool, so approve it first: `launchFunding` lists every allowance the launch needs.
113
201
 
114
202
  ```ts
115
- import { listRoots } from "hookr-sdk";
203
+ import { buildApprovals, launchFunding } from "hookr-sdk";
204
+
205
+ const existing = { existing: tokenAddress, name: "", symbol: "", supply: 0n, salt: zeroHash };
206
+ const funding = launchFunding(manifest, tokenAddress, true, [member], launchFee);
207
+ for (const allowance of funding.allowances)
208
+ for (const approve of buildApprovals(manifest, allowance, currentAllowance))
209
+ await wallet.sendTransaction({ account, to: approve.to, data: approve.data });
116
210
 
117
- for (const root of await listRoots(client)) {
118
- console.log(root.hook, root.status, root.sealed ? "sealed" : "unsealed");
119
- }
211
+ const openCall = buildLaunch(manifest, existing, HookrRoot, [member], seed.amount0Max, deadline, launchFee);
120
212
  ```
121
213
 
122
- Pools on any of those roots read, quote and swap through this package when their root's address is
123
- passed as `hooks`; only market creation is limited to `ROOTS`.
214
+ `HookrLauncher.memberKey(subject, quote, tickSpacing, root)` gives each pool's `PoolKey` and whether it is still free.
124
215
 
125
- ## Claim
216
+ ### Claim
217
+
218
+ Royalties, integrator fees and a trader's arb recapture rebate are held in `HookrRules`, per currency, until claimed.
126
219
 
127
220
  ```ts
128
- import { claimableCall, claimCall } from "hookr-sdk";
221
+ import { HOOKR_1, rulesAbi } from "hookr-sdk";
129
222
 
130
- const owed = await client.readContract(claimableCall(quoteAddress, account));
131
- if (owed > 0n) await walletClient.writeContract(claimCall(quoteAddress));
223
+ const owed = await client.readContract({ address: HOOKR_1.contracts.HookrRules, abi: rulesAbi, functionName: "claimable", args: [currency, account] });
224
+ if (owed > 0n)
225
+ await wallet.writeContract({ account, address: HOOKR_1.contracts.HookrRules, abi: rulesAbi, functionName: "claim", args: [currency] });
132
226
  ```
133
227
 
134
- ## Rule catalog
135
-
136
- `RULES` and `PARAMS` are this package's own machine-readable list of the five public rules and
137
- their bounds, and the same list is served live at https://hookr.fun/api/hooks/catalog together
138
- with the roots and contract addresses, the fee model, the composition limits and prefilled
139
- builder links for example configurations. Both come from the same source in the Hookr app, and a
140
- parity test in that repository keeps the package and the app in step.
141
-
142
- ## Changes
143
-
144
- - 0.2.1: the swap builders take `correcting` (default `isCorrectingRoot(key.hooks)`, the current
145
- recapture root), and `poolCorrects(rules)` reads from a pool's frozen rules whether it names a
146
- correction executor, so a pool on a superseded recapture root can carry the gas floor too.
147
- - 0.2.0: names both live roots (`ADDRESSES.recaptureRoot`, `RECAPTURE_KERNEL_ID`, `ROOTS`); the
148
- market builders take `root` and freeze the recapture correction fields (`RECAPTURE_CORRECTION`);
149
- swap calls carry `gas: CORRECTION_SWAP_GAS_FLOOR` on a correcting root; `listMarkets` scans in
150
- windows (`MARKET_SCAN_CHUNK_BLOCKS`, `chunkBlocks`); `listRoots` reads every registered root
151
- from the registry; documents the public RPC's limits. The README on npm for 0.1.0 had drifted
152
- from the repository.
153
- - 0.1.0: first release, default root only.
228
+ `claimTo` sends the claim to another address. `claimAsClaims` takes it as Uniswap v4 ERC-6909 claims.
229
+
230
+ ## Addresses
231
+
232
+ Robinhood Chain, chain id 4663. Every address is fixed by CREATE3 from the release deployer, the release id and the contract's name, so it is the same before and after deployment. `HOOKR_1.contracts` holds them all. `HOOKR_1.deployment` holds the deployment: the block the manifest starts from and its hash, each contract's runtime code hash, and the hash of the release's source verification on Blockscout. Each address below opens on RobinScan, where its source is verified.
233
+
234
+ | Contract | `hookr-1` | What it does |
235
+ | --- | --- | --- |
236
+ | HookrRoot | [`0x89c9FB50d1f03192230FFB1c279BB6E7d3Fe6aCc`](https://robin.etherscan.io/address/0x89c9FB50d1f03192230FFB1c279BB6E7d3Fe6aCc) | The hook each pool names in `PoolKey.hooks` |
237
+ | HookrRouter | [`0xC2Bc9a3fe6c4Ce8C2F7EB4655b0869b01D8c93C9`](https://robin.etherscan.io/address/0xC2Bc9a3fe6c4Ce8C2F7EB4655b0869b01D8c93C9) | Swaps through a Hookr pool |
238
+ | HookrQuoter | [`0x445D7891381Aa7F91F5048EdBC6a611ccBDe7865`](https://robin.etherscan.io/address/0x445D7891381Aa7F91F5048EdBC6a611ccBDe7865) | Quotes a swap with the pool's own callbacks |
239
+ | HookrLauncher | [`0x1cf2748A6670572425eAbf9Ab9e5BC4eb2eB8Ef4`](https://robin.etherscan.io/address/0x1cf2748A6670572425eAbf9Ab9e5BC4eb2eB8Ef4) | Opens a token's pools in one launch |
240
+ | HookrRules | [`0x4a71c270b1520F94064268102AebD744b0DE7942`](https://robin.etherscan.io/address/0x4a71c270b1520F94064268102AebD744b0DE7942) | Holds each pool's Hook Blocks and pays its fees |
241
+ | HookrRegistry | [`0x463c82beA1a52F4Cc05ca0741a24F0AD24bA4602`](https://robin.etherscan.io/address/0x463c82beA1a52F4Cc05ca0741a24F0AD24bA4602) | Admits roots, Hook Blocks, advisories and quotes, behind the owner's timelock |
242
+ | HookrTreasury | [`0x2242F7FC75606500503075f29ea8cDA684EfB4a9`](https://robin.etherscan.io/address/0x2242F7FC75606500503075f29ea8cDA684EfB4a9) | Holds Hookr's share and the integrator list |
243
+ | HookrForwarder | [`0xe7863CC0E2Fb783b44c279aB159bcD812c2ceA1c`](https://robin.etherscan.io/address/0xe7863CC0E2Fb783b44c279aB159bcD812c2ceA1c) | Runs a signed swap for a relayer |
244
+ | PoolManager | [`0x8366a39CC670B4001A1121B8F6A443A643e40951`](https://robin.etherscan.io/address/0x8366a39CC670B4001A1121B8F6A443A643e40951) | Uniswap v4's PoolManager, `POOL_MANAGER` |
245
+
246
+ The rest of the release:
247
+
248
+ | Contract | `hookr-1` |
249
+ | --- | --- |
250
+ | HookrRegistryChecks | [`0xB9F5c54E5Cc7ac6c7a96335E5A334Cf4eA496E98`](https://robin.etherscan.io/address/0xB9F5c54E5Cc7ac6c7a96335E5A334Cf4eA496E98) |
251
+ | HookrRegistryAdmin | [`0x675ac2102E8c69E2467F64656E3c235AF3901Ac1`](https://robin.etherscan.io/address/0x675ac2102E8c69E2467F64656E3c235AF3901Ac1) |
252
+ | HookrLaunchChecks | [`0x8567369a70100828611BB6F44ec051B48F10fb59`](https://robin.etherscan.io/address/0x8567369a70100828611BB6F44ec051B48F10fb59) |
253
+ | HookrTokenDeployer | [`0x1B23D6d7beBcB61E39317E9F0Bc02AEB91aFCcAe`](https://robin.etherscan.io/address/0x1B23D6d7beBcB61E39317E9F0Bc02AEB91aFCcAe) |
254
+ | HookrReferralRegistry | [`0xefD1DfBA80c06E72F793601706c3a1c71aab3057`](https://robin.etherscan.io/address/0xefD1DfBA80c06E72F793601706c3a1c71aab3057) |
255
+ | HookrProgramsAdmin | [`0x40B40D65543E70a9C757eda1A2208517a8BC7292`](https://robin.etherscan.io/address/0x40B40D65543E70a9C757eda1A2208517a8BC7292) |
256
+ | HookrPrograms | [`0x9fA204AC99176782Fd20615b2b2A516D1F8C328F`](https://robin.etherscan.io/address/0x9fA204AC99176782Fd20615b2b2A516D1F8C328F) |
257
+ | HookrMilestoneNFTFactory | [`0xa340F964F1E685c681dC3ABB5B0405E608914d00`](https://robin.etherscan.io/address/0xa340F964F1E685c681dC3ABB5B0405E608914d00) |
258
+ | HookrProgramValidator | [`0x33e0249083Be7Cd8bD2fe175E0671AcfD0516850`](https://robin.etherscan.io/address/0x33e0249083Be7Cd8bD2fe175E0671AcfD0516850) |
259
+ | HookrReferralDistributor | [`0x690539c53212899A9c6AEEE3b4B6737A5c4851d9`](https://robin.etherscan.io/address/0x690539c53212899A9c6AEEE3b4B6737A5c4851d9) |
260
+ | HookrLane | [`0x9A8a1006469BA196f8FEfc017a53505C83A060BB`](https://robin.etherscan.io/address/0x9A8a1006469BA196f8FEfc017a53505C83A060BB) |
261
+ | HookrRecapture | [`0xF83569E564d70daebc35950f66a73f2e2B915583`](https://robin.etherscan.io/address/0xF83569E564d70daebc35950f66a73f2e2B915583) |
262
+ | HookrFamilyRouter | [`0x854f3Fa7AC342B244DF0d9A8c8F597b051aAE559`](https://robin.etherscan.io/address/0x854f3Fa7AC342B244DF0d9A8c8F597b051aAE559) |
263
+ | HookrFamilyLock | [`0xfAFEcE64099C1E791C4B46189c277f00c0c7e00b`](https://robin.etherscan.io/address/0xfAFEcE64099C1E791C4B46189c277f00c0c7e00b) |
264
+ | HookrCompliance | [`0x9D205e8a68464761A9d84bdeCcEa0C3CB1e7B1EC`](https://robin.etherscan.io/address/0x9D205e8a68464761A9d84bdeCcEa0C3CB1e7B1EC) |
265
+ | HookrComplianceGuard | [`0x6CD70db1ac99344416a6fD7184e23FA8f09f313A`](https://robin.etherscan.io/address/0x6CD70db1ac99344416a6fD7184e23FA8f09f313A) |
266
+ | HookrAccountCalls | [`0x0579a95A7760070E2d6D34e5beCe571e5F1c4818`](https://robin.etherscan.io/address/0x0579a95A7760070E2d6D34e5beCe571e5F1c4818) |
267
+ | HookrPaymasterAdmin | [`0x1d81F4B131832f741392edf7B91b4CF099FbB008`](https://robin.etherscan.io/address/0x1d81F4B131832f741392edf7B91b4CF099FbB008) |
268
+ | HookrPaymaster | [`0x1c4682915092E742231ea038C4fcA61e96a83c99`](https://robin.etherscan.io/address/0x1c4682915092E742231ea038C4fcA61e96a83c99) |
269
+ | HookrRootFactory | [`0x21E438FaBE10770afb4407cF6b09d32369CBdCE4`](https://robin.etherscan.io/address/0x21E438FaBE10770afb4407cF6b09d32369CBdCE4) |
270
+ | HookrSessionAdvisory | [`0x78Bc6b7302Dda8632e661c8d74966bdBea1c66b1`](https://robin.etherscan.io/address/0x78Bc6b7302Dda8632e661c8d74966bdBea1c66b1) |
271
+ | HookrFeeAdvisory | [`0x3B6b3f00684987B831fcF9EB5f0d5B806afF7306`](https://robin.etherscan.io/address/0x3B6b3f00684987B831fcF9EB5f0d5B806afF7306) |
272
+ | HookrLiquidityVault | [`0xA408923EF811945Ef119Bc700B1950Dab65467Fc`](https://robin.etherscan.io/address/0xA408923EF811945Ef119Bc700B1950Dab65467Fc) |
273
+ | HookrOwnedProfiles | [`0xb46c318B6AEA2d6274f5566da414b09fDa6CC325`](https://robin.etherscan.io/address/0xb46c318B6AEA2d6274f5566da414b09fDa6CC325) |
274
+ | HookrOwnedRootsLens | [`0x6Bb5c9d21dD095F788cb8373d0143429ad277366`](https://robin.etherscan.io/address/0x6Bb5c9d21dD095F788cb8373d0143429ad277366) |
275
+ | HookrOwnedRootFactory | [`0xA6c2a401597301dFf57A59bC8F70a9622499f3ec`](https://robin.etherscan.io/address/0xA6c2a401597301dFf57A59bC8F70a9622499f3ec) |
276
+ | HookrLpBoost | [`0x52536F5F4E5BC7cEA2197c8F1BB49bf2B133E7f1`](https://robin.etherscan.io/address/0x52536F5F4E5BC7cEA2197c8F1BB49bf2B133E7f1) |
277
+
278
+ `CANARY_HOOKR_1_A` is the canary, release `canary-hookr-1-a`: the same contracts at their own addresses, deployed first to prove the release. Its root is `0x4C0904bfbdaEC6AA847C36BBf395E5f61325eacc`. It is not for users. Build on `HOOKR_1`.
279
+
280
+ ## Arb recapture
281
+
282
+ A pool with arb recapture on lets What The Hook's executor close the price gap between the pool and outside venues inside the trader's own swap, and pays the profit out:
283
+
284
+ | Who | Share of each profit |
285
+ | --- | --- |
286
+ | Hookr | 25% (`RECAPTURE_PROTOCOL_BPS`, 2,500) |
287
+ | What The Hook | up to 25% (`MAX_LANE_PARTNER_BPS`, 2,500), what its executor keeps |
288
+ | The pool | the rest: the trader's rebate (0 to 50% of it, 25% by default), the King of the Pool pot (0 to 50% of it, off by default) and the LPs |
289
+
290
+ The pool's split is frozen at launch. `recaptureSplit` and `recaptureProfit` work it out to the wei. The LPs' part is released over `releaseBlocks` L2 blocks: 1,200 to 864,000, 36,000 by default. The release counts at most 10 of them a second, so 36,000 blocks take at least an hour.
291
+
292
+ ## Gas
293
+
294
+ A swap on a pool with arb recapture on must carry the lane's gas floor, or it reverts `InsufficientLaneGas`. The floor is `2 × gasCap + gasCap / 63 + 755,000`: `laneGasFloor(gasCap)` here, `gasFloor` from `laneOf(id)` on chain. At the lane's 3,000,000 gas cap it is 6,802,619. The swap's own gas comes on top: in the release rehearsal, a lane swap through `HookrRouter` needed a gas limit of 7,419,835.
295
+
296
+ Estimate and add a sixth, as the [Swap](#swap) example does. The estimate already includes the floor, which is why it is high. If your wallet sets a fixed limit, use at least 7.5 million on such a pool. A wallet pays for the gas used, not the limit. A pool without arb recapture has no floor.
297
+
298
+ ## Quotes
299
+
300
+ A pool may quote in native ETH, any of the 22 tokens on the genesis catalog, any Robinhood stock token, and any other token the registry admits. `ROBINHOOD_QUOTE_CATALOG` is the catalog in the registry's order, each entry read from chain at block 81,225,166: address, symbol, decimals and runtime code hash. `classifyQuote` labels any address, `quoteWarnings` says what to tell a user, and `quoteAdmission` asks the registry whether a quote is admitted right now.
301
+
302
+ ## What is in the package
303
+
304
+ | Module | What it does |
305
+ | --- | --- |
306
+ | `releases` | `HOOKR_1` and the canary: addresses, deployment, the manifest, `ROBINHOOD_CHAIN`, explorer links and the lane gas floor |
307
+ | `wallet` | The launcher, router and quoter calls, each checked against its bounds |
308
+ | `launch` | Multi-pool launch, the dev buy and exactly what the launcher pulls |
309
+ | `params` | Every Hook Block setting with its range and default, and the checks that refuse a value outside them |
310
+ | `rules` | Encodes and checks a pool's Hook Blocks, and prices the Snipe tax, the dynamic fee and the arb recapture split |
311
+ | `quotes` | The quote catalog, quote classes and amounts in each quote's own decimals |
312
+ | `registry` | Typed registry operations and the admission checks |
313
+ | `advisories` | The managed fee and market-hours advisory configs |
314
+ | `abi` | The call ABIs for the root and its lane, the router, quoter, launcher, HookrRules, HookrRecapture, the registry, treasury, programs, referrals and forwarder |
315
+ | `generated` | `ARTIFACT_ABIS`, the full ABIs of the registry, HookrRules, the treasury, the root factory and pair root, the fee and session advisories, the liquidity vault, the family contracts, LP Boost and the owned-root contracts, and the constants the encoders use |
316
+ | `vault`, `referrals`, `proofs` | Liquidity vault and treasury calls, referral authorizations and reward proofs |
317
+ | `client` | `HookrClient`, which reads a Hookr service and checks the service serves the release it expects |
318
+
319
+ Everything but `releases` and `deployments` is the release SDK hookr.fun runs, copied byte for byte. `provenance.json` names the release's source commit and the hash of every file. Every contract's source is verified at its address on RobinScan and Sourcify.
320
+
321
+ `releaseManifest` and `readReleaseManifest` build the manifest the builders read. It is not a Hookr service's manifest: give `HookrClient` the release id and manifest hash the service publishes.
322
+
323
+ Before you send a call, check the wallet's chain, the payer, the token approvals, the deadline and the slippage yourself. A quote simulates the pool's accounting. It does not prove approvals, balances or gas. Treat token names and links as untrusted display text.
324
+
325
+ ## Links
326
+
327
+ - Docs: [hookr.fun/docs](https://hookr.fun/docs)
328
+ - Explorer: [RobinScan](https://robin.etherscan.io)
329
+ - Moving from 0.2.x: [MIGRATING.md](https://unpkg.com/hookr-sdk@1/MIGRATING.md), in the package
330
+ - Changes: [CHANGELOG.md](https://unpkg.com/hookr-sdk@1/CHANGELOG.md), in the package
331
+
332
+ ## License
333
+
334
+ MIT