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.
- package/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/MIGRATING.md +89 -0
- package/README.md +283 -96
- package/dist/core/abi.d.ts +10930 -0
- package/dist/core/abi.js +455 -0
- package/dist/core/advisories.d.ts +184 -0
- package/dist/core/advisories.js +291 -0
- package/dist/core/client.d.ts +55 -0
- package/dist/core/client.js +107 -0
- package/dist/core/generated.d.ts +14295 -0
- package/dist/core/generated.js +1058 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.js +17 -0
- package/dist/core/launch.d.ts +200 -0
- package/dist/core/launch.js +427 -0
- package/dist/core/pair.d.ts +64 -0
- package/dist/core/pair.js +136 -0
- package/dist/core/params.d.ts +415 -0
- package/dist/core/params.js +1235 -0
- package/dist/core/policies.d.ts +136 -0
- package/dist/core/policies.js +125 -0
- package/dist/core/proofs.d.ts +25 -0
- package/dist/core/proofs.js +118 -0
- package/dist/core/quotes.d.ts +185 -0
- package/dist/core/quotes.js +550 -0
- package/dist/core/referrals.d.ts +32 -0
- package/dist/core/referrals.js +36 -0
- package/dist/core/registry.d.ts +357 -0
- package/dist/core/registry.js +378 -0
- package/dist/core/rules.d.ts +675 -0
- package/dist/core/rules.js +1049 -0
- package/dist/core/schema.d.ts +358 -0
- package/dist/core/schema.js +105 -0
- package/dist/core/stocks.generated.d.ts +11 -0
- package/dist/core/stocks.generated.js +1228 -0
- package/dist/core/vault.d.ts +59 -0
- package/dist/core/vault.js +112 -0
- package/dist/core/wallet.d.ts +142 -0
- package/dist/core/wallet.js +304 -0
- package/dist/deployments.d.ts +8 -0
- package/dist/deployments.js +26 -0
- package/dist/index.d.ts +6 -15
- package/dist/index.js +6 -15
- package/dist/releases.d.ts +172 -0
- package/dist/releases.js +268 -0
- package/package.json +46 -10
- package/provenance.json +31 -0
- package/dist/abi.d.ts +0 -6404
- package/dist/abi.js +0 -8300
- package/dist/chain.d.ts +0 -87
- package/dist/chain.js +0 -86
- package/dist/claims.d.ts +0 -32
- package/dist/claims.js +0 -31
- package/dist/fees.d.ts +0 -59
- package/dist/fees.js +0 -142
- package/dist/links.d.ts +0 -48
- package/dist/links.js +0 -93
- package/dist/market.d.ts +0 -264
- package/dist/market.js +0 -310
- package/dist/reads.d.ts +0 -127
- package/dist/reads.js +0 -207
- package/dist/rules.d.ts +0 -84
- package/dist/rules.js +0 -296
- package/dist/swap.d.ts +0 -96
- package/dist/swap.js +0 -134
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
|
|
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
|
-
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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,129 +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
|
-
|
|
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
|
-
|
|
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
|
|
32
|
-
import {
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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
|
+
```
|
|
41
70
|
|
|
42
|
-
|
|
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).
|
|
43
72
|
|
|
44
|
-
|
|
45
|
-
|
|
73
|
+
### Quote
|
|
74
|
+
|
|
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
|
-
|
|
97
|
+
### Swap
|
|
49
98
|
|
|
50
|
-
|
|
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 {
|
|
58
|
-
import { CHAIN_ID, NATIVE_ADDRESS, ROOTS, buildExistingTokenMarketCall } from "hookr-sdk";
|
|
102
|
+
import { buildSwap } from "hookr-sdk";
|
|
59
103
|
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
});
|
|
65
|
-
const hash = await
|
|
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
|
-
|
|
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
|
-
|
|
114
|
+
### Launch a token with Hook Blocks
|
|
81
115
|
|
|
82
|
-
|
|
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 {
|
|
87
|
-
import {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
the
|
|
102
|
-
|
|
103
|
-
|
|
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
|
+
```
|
|
104
197
|
|
|
105
|
-
|
|
198
|
+
### Open pools for an existing token
|
|
106
199
|
|
|
107
|
-
|
|
108
|
-
root, so `listRoots` shows every kernel it has registered, current or not, with its status and
|
|
109
|
-
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.
|
|
110
201
|
|
|
111
202
|
```ts
|
|
112
|
-
import {
|
|
203
|
+
import { buildApprovals, launchFunding } from "hookr-sdk";
|
|
113
204
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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 });
|
|
210
|
+
|
|
211
|
+
const openCall = buildLaunch(manifest, existing, HookrRoot, [member], seed.amount0Max, deadline, launchFee);
|
|
117
212
|
```
|
|
118
213
|
|
|
119
|
-
|
|
120
|
-
|
|
214
|
+
`HookrLauncher.memberKey(subject, quote, tickSpacing, root)` gives each pool's `PoolKey` and whether it is still free.
|
|
215
|
+
|
|
216
|
+
### Claim
|
|
121
217
|
|
|
122
|
-
|
|
218
|
+
Royalties, integrator fees and a trader's arb recapture rebate are held in `HookrRules`, per currency, until claimed.
|
|
123
219
|
|
|
124
220
|
```ts
|
|
125
|
-
import {
|
|
221
|
+
import { HOOKR_1, rulesAbi } from "hookr-sdk";
|
|
126
222
|
|
|
127
|
-
const owed = await client.readContract(
|
|
128
|
-
if (owed > 0n)
|
|
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] });
|
|
129
226
|
```
|
|
130
227
|
|
|
131
|
-
|
|
228
|
+
`claimTo` sends the claim to another address. `claimAsClaims` takes it as Uniswap v4 ERC-6909 claims.
|
|
132
229
|
|
|
133
|
-
|
|
134
|
-
their bounds, and the same list is served live at https://hookr.fun/api/hooks/catalog together
|
|
135
|
-
with the roots and contract addresses, the fee model, the composition limits and prefilled
|
|
136
|
-
builder links for example configurations. Both come from the same source in the Hookr app, and a
|
|
137
|
-
parity test in that repository keeps the package and the app in step.
|
|
230
|
+
## Addresses
|
|
138
231
|
|
|
139
|
-
|
|
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.
|
|
140
233
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|