hookr-sdk 0.2.0 → 0.2.1
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/README.md +8 -2
- package/dist/reads.d.ts +9 -0
- package/dist/reads.js +13 -1
- package/dist/swap.d.ts +24 -12
- package/dist/swap.js +24 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,8 +99,11 @@ const swapCall = buildExactInputSwapCall({ key, currencyIn: market.quote, amount
|
|
|
99
99
|
A swap on a recapture pool needs more gas than an estimate reports, because the correction is
|
|
100
100
|
fail-open: an estimate converges on the cheapest swap that succeeds, which is the one that skipped
|
|
101
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
|
|
103
|
-
is; on the default root the call carries no `gas` and the wallet estimates
|
|
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).
|
|
104
107
|
|
|
105
108
|
## Roots
|
|
106
109
|
|
|
@@ -138,6 +141,9 @@ parity test in that repository keeps the package and the app in step.
|
|
|
138
141
|
|
|
139
142
|
## Changes
|
|
140
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.
|
|
141
147
|
- 0.2.0: names both live roots (`ADDRESSES.recaptureRoot`, `RECAPTURE_KERNEL_ID`, `ROOTS`); the
|
|
142
148
|
market builders take `root` and freeze the recapture correction fields (`RECAPTURE_CORRECTION`);
|
|
143
149
|
swap calls carry `gas: CORRECTION_SWAP_GAS_FLOOR` on a correcting root; `listMarkets` scans in
|
package/dist/reads.d.ts
CHANGED
|
@@ -98,6 +98,15 @@ export type PoolRules = Readonly<{
|
|
|
98
98
|
* by this package.
|
|
99
99
|
*/
|
|
100
100
|
export declare function readPoolRules(client: PublicClient, poolId: Hex): Promise<PoolRules>;
|
|
101
|
+
/**
|
|
102
|
+
* True when the pool's frozen rules name a correction executor, so the root's kernel dispatches a
|
|
103
|
+
* correction around every swap and the swap needs `CORRECTION_SWAP_GAS_FLOOR`. This is the pool's
|
|
104
|
+
* own record rather than the root's identity: a pool on a superseded recapture root keeps its
|
|
105
|
+
* executor and keeps correcting, which `isCorrectingRoot` (current root only) does not see. Pass
|
|
106
|
+
* the result as `correcting` to the swap builders. It is also true for a pool whose lane cannot
|
|
107
|
+
* run on ordinary gas (the first recapture root); the floor is then unused headroom, not a loss.
|
|
108
|
+
*/
|
|
109
|
+
export declare function poolCorrects(rules: PoolRules): boolean;
|
|
101
110
|
/** `HookrStackRegistryV1.KernelStatus`. */
|
|
102
111
|
export type RootStatus = "unset" | "active" | "retired";
|
|
103
112
|
/** One registered root (kernel) as the stack registry records it. */
|
package/dist/reads.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { decodeAbiParameters, getAbiItem, toEventSelector } from "viem";
|
|
13
13
|
import { hookrMarketCoordinatorV5Abi, hookrStackRegistryV2Abi } from "./abi.js";
|
|
14
|
-
import { ADDRESSES, MODULE_ID } from "./chain.js";
|
|
14
|
+
import { ADDRESSES, MODULE_ID, NATIVE_ADDRESS } from "./chain.js";
|
|
15
15
|
function marketOrigin(value) {
|
|
16
16
|
if (value === 1)
|
|
17
17
|
return "new-token";
|
|
@@ -153,6 +153,18 @@ export async function readPoolRules(client, poolId) {
|
|
|
153
153
|
}
|
|
154
154
|
return Object.freeze({ configured: true, limits: core.limits, nativeConfig });
|
|
155
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* True when the pool's frozen rules name a correction executor, so the root's kernel dispatches a
|
|
158
|
+
* correction around every swap and the swap needs `CORRECTION_SWAP_GAS_FLOOR`. This is the pool's
|
|
159
|
+
* own record rather than the root's identity: a pool on a superseded recapture root keeps its
|
|
160
|
+
* executor and keeps correcting, which `isCorrectingRoot` (current root only) does not see. Pass
|
|
161
|
+
* the result as `correcting` to the swap builders. It is also true for a pool whose lane cannot
|
|
162
|
+
* run on ordinary gas (the first recapture root); the floor is then unused headroom, not a loss.
|
|
163
|
+
*/
|
|
164
|
+
export function poolCorrects(rules) {
|
|
165
|
+
const executor = rules.limits?.correctionExecutor;
|
|
166
|
+
return executor !== undefined && executor.toLowerCase() !== NATIVE_ADDRESS.toLowerCase();
|
|
167
|
+
}
|
|
156
168
|
function rootStatus(value) {
|
|
157
169
|
if (value === 0)
|
|
158
170
|
return "unset";
|
package/dist/swap.d.ts
CHANGED
|
@@ -12,18 +12,26 @@ import { hookrKernelRouterV3Abi } from "./abi.js";
|
|
|
12
12
|
import type { PoolKey } from "./market.js";
|
|
13
13
|
/**
|
|
14
14
|
* The gas limit a swap on a correcting root must carry (the app's `CORRECTION_SWAP_GAS_FLOOR` in
|
|
15
|
-
* `src/lib/gas-headroom.ts`). The recapture root runs its correction
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
15
|
+
* `src/lib/gas-headroom.ts`). The recapture root runs its correction in both swap phases, once in
|
|
16
|
+
* `beforeSwap` and again in `afterSwap` (`HookrSwapKernelV5Wth.sol`, `_tryCorrection` at lines 214
|
|
17
|
+
* and 250), each inside a bounded call that fails open: a wallet's gas estimate covers the swap
|
|
18
|
+
* alone, so an estimated transaction succeeds with the correction skipped and nothing recaptured.
|
|
19
|
+
* The swap builders below put this floor on the call whenever `key.hooks` is the current recapture
|
|
20
|
+
* root, or whenever the caller passes `correcting: true`; pass it through to `writeContract` (viem
|
|
21
|
+
* sends `gas` as the limit) instead of estimating.
|
|
20
22
|
*/
|
|
21
23
|
export declare const CORRECTION_SWAP_GAS_FLOOR = 1100000n;
|
|
22
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* True when `hooks` is the current recapture root, which corrects in both swap phases. This is the
|
|
26
|
+
* root's identity, not the pool's: a pool opened on a superseded recapture root keeps the executor
|
|
27
|
+
* frozen into its rules and keeps correcting, and this returns false for it. Read that from the
|
|
28
|
+
* pool itself with `poolCorrects(await readPoolRules(client, poolId))` and pass the answer as
|
|
29
|
+
* `correcting` to the swap builders.
|
|
30
|
+
*/
|
|
23
31
|
export declare function isCorrectingRoot(hooks: Address): boolean;
|
|
24
|
-
/** The gas limit to send with a swap on `key`: the floor
|
|
25
|
-
* (let the wallet estimate). */
|
|
26
|
-
export declare function swapGasLimit(key: PoolKey): bigint | undefined;
|
|
32
|
+
/** The gas limit to send with a swap on `key`: the floor when the pool corrects (`correcting`,
|
|
33
|
+
* defaulting to `isCorrectingRoot(key.hooks)`), else `undefined` (let the wallet estimate). */
|
|
34
|
+
export declare function swapGasLimit(key: PoolKey, correcting?: boolean): bigint | undefined;
|
|
27
35
|
/** Router / block `MIN_SQRT_PRICE_LIMIT`: the full-fill limit for a `zeroForOne` swap. */
|
|
28
36
|
export declare const MIN_SQRT_PRICE_LIMIT = 4295128740n;
|
|
29
37
|
/** Router / block `MAX_SQRT_PRICE_LIMIT`: the full-fill limit for a `oneForZero` swap. */
|
|
@@ -45,13 +53,14 @@ export type RouterCall<F extends "exactInput" | "exactOutput"> = Readonly<{
|
|
|
45
53
|
functionName: F;
|
|
46
54
|
args: ContractFunctionArgs<typeof hookrKernelRouterV3Abi, "payable", F>;
|
|
47
55
|
value: bigint;
|
|
48
|
-
/** Set to `CORRECTION_SWAP_GAS_FLOOR` when the pool
|
|
56
|
+
/** Set to `CORRECTION_SWAP_GAS_FLOOR` when the pool corrects; absent otherwise. */
|
|
49
57
|
gas?: bigint;
|
|
50
58
|
}>;
|
|
51
59
|
/**
|
|
52
60
|
* `exactInput` through the Hookr router. `value` is `amountIn` when `currencyIn` is native ETH,
|
|
53
61
|
* else 0 (the router pulls the ERC-20 by `transferFrom`; approve it first). `gas` carries the
|
|
54
|
-
* correction floor when the pool
|
|
62
|
+
* correction floor when the pool corrects; send it as the gas limit. `correcting` defaults to
|
|
63
|
+
* `isCorrectingRoot(key.hooks)`; pass `poolCorrects(rules)` for a pool on a superseded root.
|
|
55
64
|
*/
|
|
56
65
|
export declare function buildExactInputSwapCall(input: {
|
|
57
66
|
key: PoolKey;
|
|
@@ -60,10 +69,12 @@ export declare function buildExactInputSwapCall(input: {
|
|
|
60
69
|
amountOutMinimum: bigint;
|
|
61
70
|
recipient: Address;
|
|
62
71
|
deadline: bigint;
|
|
72
|
+
correcting?: boolean;
|
|
63
73
|
}): RouterCall<"exactInput">;
|
|
64
74
|
/**
|
|
65
75
|
* `exactOutput` through the Hookr router. `value` is `amountInMaximum` when `currencyIn` is
|
|
66
|
-
* native ETH — the router refunds what the swap does not use.
|
|
76
|
+
* native ETH — the router refunds what the swap does not use. `correcting` works as on
|
|
77
|
+
* `buildExactInputSwapCall`.
|
|
67
78
|
*/
|
|
68
79
|
export declare function buildExactOutputSwapCall(input: {
|
|
69
80
|
key: PoolKey;
|
|
@@ -72,6 +83,7 @@ export declare function buildExactOutputSwapCall(input: {
|
|
|
72
83
|
amountInMaximum: bigint;
|
|
73
84
|
recipient: Address;
|
|
74
85
|
deadline: bigint;
|
|
86
|
+
correcting?: boolean;
|
|
75
87
|
}): RouterCall<"exactOutput">;
|
|
76
88
|
export type Quote = Readonly<{
|
|
77
89
|
amountIn: bigint;
|
package/dist/swap.js
CHANGED
|
@@ -2,21 +2,29 @@ import { hookrKernelQuoterV1Abi, hookrKernelRouterV3Abi } from "./abi.js";
|
|
|
2
2
|
import { ADDRESSES, NATIVE_ADDRESS } from "./chain.js";
|
|
3
3
|
/**
|
|
4
4
|
* The gas limit a swap on a correcting root must carry (the app's `CORRECTION_SWAP_GAS_FLOOR` in
|
|
5
|
-
* `src/lib/gas-headroom.ts`). The recapture root runs its correction
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* `src/lib/gas-headroom.ts`). The recapture root runs its correction in both swap phases, once in
|
|
6
|
+
* `beforeSwap` and again in `afterSwap` (`HookrSwapKernelV5Wth.sol`, `_tryCorrection` at lines 214
|
|
7
|
+
* and 250), each inside a bounded call that fails open: a wallet's gas estimate covers the swap
|
|
8
|
+
* alone, so an estimated transaction succeeds with the correction skipped and nothing recaptured.
|
|
9
|
+
* The swap builders below put this floor on the call whenever `key.hooks` is the current recapture
|
|
10
|
+
* root, or whenever the caller passes `correcting: true`; pass it through to `writeContract` (viem
|
|
11
|
+
* sends `gas` as the limit) instead of estimating.
|
|
10
12
|
*/
|
|
11
13
|
export const CORRECTION_SWAP_GAS_FLOOR = 1100000n;
|
|
12
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* True when `hooks` is the current recapture root, which corrects in both swap phases. This is the
|
|
16
|
+
* root's identity, not the pool's: a pool opened on a superseded recapture root keeps the executor
|
|
17
|
+
* frozen into its rules and keeps correcting, and this returns false for it. Read that from the
|
|
18
|
+
* pool itself with `poolCorrects(await readPoolRules(client, poolId))` and pass the answer as
|
|
19
|
+
* `correcting` to the swap builders.
|
|
20
|
+
*/
|
|
13
21
|
export function isCorrectingRoot(hooks) {
|
|
14
22
|
return hooks.toLowerCase() === ADDRESSES.recaptureRoot.toLowerCase();
|
|
15
23
|
}
|
|
16
|
-
/** The gas limit to send with a swap on `key`: the floor
|
|
17
|
-
* (let the wallet estimate). */
|
|
18
|
-
export function swapGasLimit(key) {
|
|
19
|
-
return isCorrectingRoot(key.hooks) ? CORRECTION_SWAP_GAS_FLOOR : undefined;
|
|
24
|
+
/** The gas limit to send with a swap on `key`: the floor when the pool corrects (`correcting`,
|
|
25
|
+
* defaulting to `isCorrectingRoot(key.hooks)`), else `undefined` (let the wallet estimate). */
|
|
26
|
+
export function swapGasLimit(key, correcting) {
|
|
27
|
+
return (correcting ?? isCorrectingRoot(key.hooks)) ? CORRECTION_SWAP_GAS_FLOOR : undefined;
|
|
20
28
|
}
|
|
21
29
|
/** Router / block `MIN_SQRT_PRICE_LIMIT`: the full-fill limit for a `zeroForOne` swap. */
|
|
22
30
|
export const MIN_SQRT_PRICE_LIMIT = 4295128740n;
|
|
@@ -45,12 +53,13 @@ export function swapDirection(key, currencyIn) {
|
|
|
45
53
|
/**
|
|
46
54
|
* `exactInput` through the Hookr router. `value` is `amountIn` when `currencyIn` is native ETH,
|
|
47
55
|
* else 0 (the router pulls the ERC-20 by `transferFrom`; approve it first). `gas` carries the
|
|
48
|
-
* correction floor when the pool
|
|
56
|
+
* correction floor when the pool corrects; send it as the gas limit. `correcting` defaults to
|
|
57
|
+
* `isCorrectingRoot(key.hooks)`; pass `poolCorrects(rules)` for a pool on a superseded root.
|
|
49
58
|
*/
|
|
50
59
|
export function buildExactInputSwapCall(input) {
|
|
51
60
|
const zeroForOne = swapDirection(input.key, input.currencyIn);
|
|
52
61
|
const native = input.currencyIn.toLowerCase() === NATIVE_ADDRESS.toLowerCase();
|
|
53
|
-
const gas = swapGasLimit(input.key);
|
|
62
|
+
const gas = swapGasLimit(input.key, input.correcting);
|
|
54
63
|
return Object.freeze({
|
|
55
64
|
address: ADDRESSES.router,
|
|
56
65
|
abi: hookrKernelRouterV3Abi,
|
|
@@ -73,12 +82,13 @@ export function buildExactInputSwapCall(input) {
|
|
|
73
82
|
}
|
|
74
83
|
/**
|
|
75
84
|
* `exactOutput` through the Hookr router. `value` is `amountInMaximum` when `currencyIn` is
|
|
76
|
-
* native ETH — the router refunds what the swap does not use.
|
|
85
|
+
* native ETH — the router refunds what the swap does not use. `correcting` works as on
|
|
86
|
+
* `buildExactInputSwapCall`.
|
|
77
87
|
*/
|
|
78
88
|
export function buildExactOutputSwapCall(input) {
|
|
79
89
|
const zeroForOne = swapDirection(input.key, input.currencyIn);
|
|
80
90
|
const native = input.currencyIn.toLowerCase() === NATIVE_ADDRESS.toLowerCase();
|
|
81
|
-
const gas = swapGasLimit(input.key);
|
|
91
|
+
const gas = swapGasLimit(input.key, input.correcting);
|
|
82
92
|
return Object.freeze({
|
|
83
93
|
address: ADDRESSES.router,
|
|
84
94
|
abi: hookrKernelRouterV3Abi,
|
package/package.json
CHANGED