hookr-sdk 0.1.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/dist/swap.js ADDED
@@ -0,0 +1,111 @@
1
+ import { hookrKernelQuoterV1Abi, hookrKernelRouterV3Abi } from "./abi.js";
2
+ import { ADDRESSES, NATIVE_ADDRESS } from "./chain.js";
3
+ /** Router / block `MIN_SQRT_PRICE_LIMIT`: the full-fill limit for a `zeroForOne` swap. */
4
+ export const MIN_SQRT_PRICE_LIMIT = 4295128740n;
5
+ /** Router / block `MAX_SQRT_PRICE_LIMIT`: the full-fill limit for a `oneForZero` swap. */
6
+ export const MAX_SQRT_PRICE_LIMIT = 1461446703485210103287273052203988822378723970341n;
7
+ /** `type(int128).max`: the router's and the quoter's ceiling on every amount and bound. */
8
+ export const INT128_MAX = (1n << 127n) - 1n;
9
+ /** The bound an exact-input quote carries: the smallest value the quoter admits. */
10
+ export const QUOTE_MIN_OUT_BOUND = 1n;
11
+ /** The router's `moduleData` for a plain swap: the native block reads none. */
12
+ export const EMPTY_MODULE_DATA = "0x";
13
+ /** The full-fill `sqrtPriceLimitX96`: `MIN` when selling currency0, `MAX` otherwise. Any pool
14
+ * with an input cut rejects every other limit on an exact-input buy. */
15
+ export function fullFillLimit(zeroForOne) {
16
+ return zeroForOne ? MIN_SQRT_PRICE_LIMIT : MAX_SQRT_PRICE_LIMIT;
17
+ }
18
+ /** `zeroForOne = currencyIn == key.currency0`. Throws when `currencyIn` is not in the pool. */
19
+ export function swapDirection(key, currencyIn) {
20
+ const same = (a, b) => a.toLowerCase() === b.toLowerCase();
21
+ if (same(currencyIn, key.currency0))
22
+ return true;
23
+ if (same(currencyIn, key.currency1))
24
+ return false;
25
+ throw new Error("That currency is not in this pool.");
26
+ }
27
+ /**
28
+ * `exactInput` through the Hookr router. `value` is `amountIn` when `currencyIn` is native ETH,
29
+ * else 0 (the router pulls the ERC-20 by `transferFrom`; approve it first).
30
+ */
31
+ export function buildExactInputSwapCall(input) {
32
+ const zeroForOne = swapDirection(input.key, input.currencyIn);
33
+ const native = input.currencyIn.toLowerCase() === NATIVE_ADDRESS.toLowerCase();
34
+ return Object.freeze({
35
+ address: ADDRESSES.router,
36
+ abi: hookrKernelRouterV3Abi,
37
+ functionName: "exactInput",
38
+ args: [
39
+ {
40
+ key: input.key,
41
+ zeroForOne,
42
+ amountIn: input.amountIn,
43
+ amountOutMinimum: input.amountOutMinimum,
44
+ sqrtPriceLimitX96: fullFillLimit(zeroForOne),
45
+ recipient: input.recipient,
46
+ deadline: input.deadline,
47
+ },
48
+ EMPTY_MODULE_DATA,
49
+ ],
50
+ value: native ? input.amountIn : 0n,
51
+ });
52
+ }
53
+ /**
54
+ * `exactOutput` through the Hookr router. `value` is `amountInMaximum` when `currencyIn` is
55
+ * native ETH — the router refunds what the swap does not use.
56
+ */
57
+ export function buildExactOutputSwapCall(input) {
58
+ const zeroForOne = swapDirection(input.key, input.currencyIn);
59
+ const native = input.currencyIn.toLowerCase() === NATIVE_ADDRESS.toLowerCase();
60
+ return Object.freeze({
61
+ address: ADDRESSES.router,
62
+ abi: hookrKernelRouterV3Abi,
63
+ functionName: "exactOutput",
64
+ args: [
65
+ {
66
+ key: input.key,
67
+ zeroForOne,
68
+ amountOut: input.amountOut,
69
+ amountInMaximum: input.amountInMaximum,
70
+ sqrtPriceLimitX96: fullFillLimit(zeroForOne),
71
+ recipient: input.recipient,
72
+ deadline: input.deadline,
73
+ },
74
+ EMPTY_MODULE_DATA,
75
+ ],
76
+ value: native ? input.amountInMaximum : 0n,
77
+ });
78
+ }
79
+ /**
80
+ * Quote through `kernelQuoter.quote`. Run as a simulated call from `account` rather than an
81
+ * ordinary read: the function is declared `nonpayable` (it runs the full module loop, including
82
+ * the pot leg, which is recipient-specific), which is also why the app's own equivalent
83
+ * (`quoteV2` in `src/lib/v2-swap.ts`) calls `simulateContract` rather than `readContract` — the
84
+ * same `eth_call` either way, just the viem entry point whose types match a nonpayable function.
85
+ * `amountSpecified` is negative for an exact-input quote, bound at 1 wei/unit — the least the
86
+ * quoter admits; pass `amountBound` to override it (an exact-output quote wants `INT128_MAX` or
87
+ * your own maximum).
88
+ */
89
+ export async function quoteExactInput(client, input) {
90
+ const zeroForOne = swapDirection(input.key, input.currencyIn);
91
+ const { result } = await client.simulateContract({
92
+ address: ADDRESSES.quoter,
93
+ abi: hookrKernelQuoterV1Abi,
94
+ functionName: "quote",
95
+ account: input.user,
96
+ args: [
97
+ {
98
+ key: input.key,
99
+ payer: input.user,
100
+ recipient: input.user,
101
+ zeroForOne,
102
+ amountSpecified: -input.amountIn,
103
+ amountBound: input.amountBound ?? QUOTE_MIN_OUT_BOUND,
104
+ sqrtPriceLimitX96: fullFillLimit(zeroForOne),
105
+ },
106
+ EMPTY_MODULE_DATA,
107
+ ],
108
+ });
109
+ const [amountIn, amountOut] = result;
110
+ return Object.freeze({ amountIn, amountOut });
111
+ }
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "hookr-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Build a market on Hookr's live root hook, quote and swap through its router, read markets, and claim payouts.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/Hookr-fun/hookr"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "main": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
23
+ "peerDependencies": {
24
+ "viem": "^2"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc -p tsconfig.json"
28
+ }
29
+ }