otto-intel-mcp 0.1.2 → 0.1.4

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 (239) hide show
  1. package/README.md +76 -18
  2. package/dist/account-userop-policy-definition.d.ts +14 -0
  3. package/dist/account-userop-policy-definition.js +12 -0
  4. package/dist/account-userop-policy-relation.d.ts +371 -0
  5. package/dist/account-userop-policy-relation.js +87 -0
  6. package/dist/adapter/cdp-signer.d.ts +76 -9
  7. package/dist/adapter/cdp-signer.js +274 -33
  8. package/dist/adapter/evm-call-failure.d.ts +29 -0
  9. package/dist/adapter/evm-call-failure.js +109 -0
  10. package/dist/adapter/refusal.d.ts +1 -1
  11. package/dist/adapter/refusal.js +13 -0
  12. package/dist/adapter/route-simulator.d.ts +91 -0
  13. package/dist/adapter/route-simulator.js +143 -0
  14. package/dist/adapter-cdp-index.d.ts +1 -1
  15. package/dist/executable-equities.d.ts +55 -0
  16. package/dist/executable-equities.js +116 -0
  17. package/dist/executable-yield-markets.d.ts +261 -0
  18. package/dist/executable-yield-markets.js +154 -0
  19. package/dist/execution-account-gas-quote.d.ts +141 -0
  20. package/dist/execution-account-gas-quote.js +443 -0
  21. package/dist/execution-account-gas-review.d.ts +123 -0
  22. package/dist/execution-account-gas-review.js +104 -0
  23. package/dist/execution-account-gas-runtime.d.ts +33 -0
  24. package/dist/execution-account-gas-runtime.js +131 -0
  25. package/dist/execution-account-gas-view.d.ts +936 -0
  26. package/dist/execution-account-gas-view.js +56 -0
  27. package/dist/execution-config.d.ts +3 -0
  28. package/dist/execution-config.js +4 -0
  29. package/dist/execution-delegated-definition.d.ts +7 -6
  30. package/dist/execution-delegated-definition.js +13 -2
  31. package/dist/execution-delegation-admin-definition.d.ts +127 -5
  32. package/dist/execution-delegation-admin-definition.js +155 -5
  33. package/dist/execution-delegation-admin.d.ts +48 -2
  34. package/dist/execution-delegation-admin.js +422 -12
  35. package/dist/execution-delegation-cap-store.d.ts +386 -0
  36. package/dist/execution-delegation-cap-store.js +1150 -0
  37. package/dist/execution-delegation-exit-definition.d.ts +309 -0
  38. package/dist/execution-delegation-exit-definition.js +204 -0
  39. package/dist/execution-delegation-exit-store.d.ts +114 -0
  40. package/dist/execution-delegation-exit-store.js +671 -0
  41. package/dist/execution-delegation-exit.d.ts +4 -0
  42. package/dist/execution-delegation-exit.js +614 -0
  43. package/dist/execution-delegation-finality.d.ts +22 -0
  44. package/dist/execution-delegation-finality.js +90 -0
  45. package/dist/execution-delegation-operation-store.d.ts +129 -0
  46. package/dist/execution-delegation-operation-store.js +1107 -0
  47. package/dist/execution-delegation-operations-definition.d.ts +282 -0
  48. package/dist/execution-delegation-operations-definition.js +117 -0
  49. package/dist/execution-delegation-operations.d.ts +6 -0
  50. package/dist/execution-delegation-operations.js +282 -0
  51. package/dist/execution-delegation-policy.d.ts +154 -8
  52. package/dist/execution-delegation-policy.js +273 -40
  53. package/dist/execution-delegation.d.ts +51 -0
  54. package/dist/execution-delegation.js +441 -31
  55. package/dist/execution-errors.d.ts +1 -1
  56. package/dist/execution-errors.js +122 -0
  57. package/dist/execution-index.d.ts +7 -2
  58. package/dist/execution-index.js +7 -2
  59. package/dist/execution-journal-schema.d.ts +96 -0
  60. package/dist/execution-journal-schema.js +368 -0
  61. package/dist/execution-journal-tables.d.ts +14 -0
  62. package/dist/execution-journal-tables.js +227 -0
  63. package/dist/execution-policy-compatibility.d.ts +34 -0
  64. package/dist/execution-policy-compatibility.js +76 -0
  65. package/dist/execution-registration.d.ts +54 -2
  66. package/dist/execution-registration.js +151 -5
  67. package/dist/execution-sponsored-account-profile.d.ts +32 -0
  68. package/dist/execution-sponsored-account-profile.js +59 -0
  69. package/dist/execution-sponsored-account.d.ts +1519 -0
  70. package/dist/execution-sponsored-account.js +222 -0
  71. package/dist/execution-sponsored-definition.d.ts +1713 -0
  72. package/dist/execution-sponsored-definition.js +185 -0
  73. package/dist/execution-sponsored-gas-policy.d.ts +27 -0
  74. package/dist/execution-sponsored-gas-policy.js +110 -0
  75. package/dist/execution-sponsored-hosted.d.ts +3 -0
  76. package/dist/execution-sponsored-hosted.js +71 -0
  77. package/dist/execution-sponsored-index.d.ts +1322 -0
  78. package/dist/execution-sponsored-index.js +102 -0
  79. package/dist/execution-sponsored-mcp-definition.d.ts +1662 -0
  80. package/dist/execution-sponsored-mcp-definition.js +94 -0
  81. package/dist/execution-sponsored-receipt.d.ts +47 -0
  82. package/dist/execution-sponsored-receipt.js +74 -0
  83. package/dist/execution-sponsored-registration.d.ts +14 -0
  84. package/dist/execution-sponsored-registration.js +77 -0
  85. package/dist/execution-sponsored-runtime.d.ts +84 -0
  86. package/dist/execution-sponsored-runtime.js +149 -0
  87. package/dist/execution-sponsored-settlement.d.ts +15 -0
  88. package/dist/execution-sponsored-settlement.js +88 -0
  89. package/dist/execution-sponsored-store.d.ts +67 -0
  90. package/dist/execution-sponsored-store.js +517 -0
  91. package/dist/execution-sponsored-transport.d.ts +90 -0
  92. package/dist/execution-sponsored-transport.js +180 -0
  93. package/dist/execution-tool-definitions.d.ts +21 -21
  94. package/dist/execution-tool-definitions.js +0 -7
  95. package/dist/execution-tools.d.ts +53 -1
  96. package/dist/execution-tools.js +171 -13
  97. package/dist/execution-worker-guard.d.ts +28 -0
  98. package/dist/execution-worker-guard.js +124 -0
  99. package/dist/hybrid-yield-index.d.ts +10 -0
  100. package/dist/hybrid-yield-index.js +11 -0
  101. package/dist/hybrid-yield-markets.d.ts +96 -0
  102. package/dist/hybrid-yield-markets.js +124 -0
  103. package/dist/hybrid-yield.d.ts +411 -0
  104. package/dist/hybrid-yield.js +155 -0
  105. package/dist/hyperliquid-order-builder.js +4 -0
  106. package/dist/lifi-execution-client.d.ts +6 -0
  107. package/dist/lifi-execution-client.js +3 -0
  108. package/dist/lp-userop-account.d.ts +461 -0
  109. package/dist/lp-userop-account.js +417 -0
  110. package/dist/lp-userop-authority.d.ts +49 -0
  111. package/dist/lp-userop-authority.js +211 -0
  112. package/dist/lp-userop-definition.d.ts +233 -0
  113. package/dist/lp-userop-definition.js +85 -0
  114. package/dist/lp-userop-hosted.d.ts +3 -0
  115. package/dist/lp-userop-hosted.js +73 -0
  116. package/dist/lp-userop-index.d.ts +1569 -0
  117. package/dist/lp-userop-index.js +112 -0
  118. package/dist/lp-userop-mcp-definition.d.ts +1220 -0
  119. package/dist/lp-userop-mcp-definition.js +46 -0
  120. package/dist/lp-userop-operation.d.ts +1230 -0
  121. package/dist/lp-userop-operation.js +140 -0
  122. package/dist/lp-userop-registration.d.ts +14 -0
  123. package/dist/lp-userop-registration.js +70 -0
  124. package/dist/lp-userop-settlement.d.ts +89 -0
  125. package/dist/lp-userop-settlement.js +184 -0
  126. package/dist/lp-userop.d.ts +643 -0
  127. package/dist/lp-userop.js +343 -0
  128. package/dist/native-yield-account-definition.d.ts +1192 -0
  129. package/dist/native-yield-account-definition.js +232 -0
  130. package/dist/native-yield-account-gas.d.ts +58 -0
  131. package/dist/native-yield-account-gas.js +228 -0
  132. package/dist/native-yield-account-index.d.ts +23 -0
  133. package/dist/native-yield-account-index.js +28 -0
  134. package/dist/native-yield-account-policy.d.ts +168 -0
  135. package/dist/native-yield-account-policy.js +525 -0
  136. package/dist/native-yield-account-rpc.d.ts +8 -0
  137. package/dist/native-yield-account-rpc.js +128 -0
  138. package/dist/native-yield-account-runtime.d.ts +71 -0
  139. package/dist/native-yield-account-runtime.js +125 -0
  140. package/dist/native-yield-account-store.d.ts +40 -0
  141. package/dist/native-yield-account-store.js +307 -0
  142. package/dist/native-yield-account.d.ts +662 -0
  143. package/dist/native-yield-account.js +371 -0
  144. package/dist/native-yield-consent-store.d.ts +20 -0
  145. package/dist/native-yield-consent-store.js +317 -0
  146. package/dist/native-yield-definition.d.ts +288 -0
  147. package/dist/native-yield-definition.js +105 -0
  148. package/dist/native-yield-reader.d.ts +4 -0
  149. package/dist/native-yield-reader.js +137 -0
  150. package/dist/native-yield-settlement.d.ts +48 -0
  151. package/dist/native-yield-settlement.js +167 -0
  152. package/dist/native-yield-simulation.d.ts +18 -0
  153. package/dist/native-yield-simulation.js +45 -0
  154. package/dist/native-yield-userop-account.d.ts +675 -0
  155. package/dist/native-yield-userop-account.js +357 -0
  156. package/dist/native-yield-userop-authority.d.ts +214 -0
  157. package/dist/native-yield-userop-authority.js +296 -0
  158. package/dist/native-yield-userop-definition.d.ts +331 -0
  159. package/dist/native-yield-userop-definition.js +105 -0
  160. package/dist/native-yield-userop-hosted.d.ts +3 -0
  161. package/dist/native-yield-userop-hosted.js +71 -0
  162. package/dist/native-yield-userop-index.d.ts +1522 -0
  163. package/dist/native-yield-userop-index.js +142 -0
  164. package/dist/native-yield-userop-mcp-definition.d.ts +1356 -0
  165. package/dist/native-yield-userop-mcp-definition.js +50 -0
  166. package/dist/native-yield-userop-operation.d.ts +845 -0
  167. package/dist/native-yield-userop-operation.js +127 -0
  168. package/dist/native-yield-userop-policy.d.ts +23 -0
  169. package/dist/native-yield-userop-policy.js +25 -0
  170. package/dist/native-yield-userop-registration.d.ts +17 -0
  171. package/dist/native-yield-userop-registration.js +76 -0
  172. package/dist/native-yield-userop-settlement.d.ts +8 -0
  173. package/dist/native-yield-userop-settlement.js +79 -0
  174. package/dist/native-yield-userop-simulation.d.ts +18 -0
  175. package/dist/native-yield-userop-simulation.js +34 -0
  176. package/dist/native-yield-userop.d.ts +35 -0
  177. package/dist/native-yield-userop.js +156 -0
  178. package/dist/native-yield-verify.d.ts +30 -0
  179. package/dist/native-yield-verify.js +141 -0
  180. package/dist/native-yield.d.ts +17 -0
  181. package/dist/native-yield.js +119 -0
  182. package/dist/stdio-main.js +0 -0
  183. package/dist/stock-buy-definition.d.ts +338 -0
  184. package/dist/stock-buy-definition.js +127 -0
  185. package/dist/stock-buy-oracle.d.ts +8 -0
  186. package/dist/stock-buy-oracle.js +22 -0
  187. package/dist/stock-buy.d.ts +17 -0
  188. package/dist/stock-buy.js +164 -0
  189. package/dist/tool-definitions.d.ts +3 -1
  190. package/dist/tool-definitions.js +55 -2
  191. package/dist/vendor/lp-v3/lp-v3-atomic-contract.d.ts +445 -0
  192. package/dist/vendor/lp-v3/lp-v3-atomic-contract.js +90 -0
  193. package/dist/vendor/lp-v3/lp-v3-atomic-evidence.d.ts +14 -0
  194. package/dist/vendor/lp-v3/lp-v3-atomic-evidence.js +82 -0
  195. package/dist/vendor/lp-v3/lp-v3-atomic-index.d.ts +80 -0
  196. package/dist/vendor/lp-v3/lp-v3-atomic-index.js +19 -0
  197. package/dist/vendor/lp-v3/lp-v3-atomic-plan.d.ts +43 -0
  198. package/dist/vendor/lp-v3/lp-v3-atomic-plan.js +112 -0
  199. package/dist/vendor/lp-v3/lp-v3-atomic-read-contract.d.ts +312 -0
  200. package/dist/vendor/lp-v3/lp-v3-atomic-read-contract.js +41 -0
  201. package/dist/vendor/lp-v3/lp-v3-atomic-read-index.d.ts +3 -0
  202. package/dist/vendor/lp-v3/lp-v3-atomic-read-index.js +3 -0
  203. package/dist/vendor/lp-v3/lp-v3-atomic-read-rpc.d.ts +49 -0
  204. package/dist/vendor/lp-v3/lp-v3-atomic-read-rpc.js +88 -0
  205. package/dist/vendor/lp-v3/lp-v3-atomic-read.d.ts +17 -0
  206. package/dist/vendor/lp-v3/lp-v3-atomic-read.js +232 -0
  207. package/dist/vendor/lp-v3/lp-v3-atomic-settlement.d.ts +105 -0
  208. package/dist/vendor/lp-v3/lp-v3-atomic-settlement.js +162 -0
  209. package/dist/vendor/lp-v3/lp-v3-collect-protocol-contract.d.ts +606 -0
  210. package/dist/vendor/lp-v3/lp-v3-collect-protocol-contract.js +59 -0
  211. package/dist/vendor/lp-v3/lp-v3-collect-protocol-index.d.ts +168 -0
  212. package/dist/vendor/lp-v3/lp-v3-collect-protocol-index.js +23 -0
  213. package/dist/vendor/lp-v3/lp-v3-collect-protocol-observation.d.ts +32 -0
  214. package/dist/vendor/lp-v3/lp-v3-collect-protocol-observation.js +228 -0
  215. package/dist/vendor/lp-v3/lp-v3-collect-protocol-plan.d.ts +11 -0
  216. package/dist/vendor/lp-v3/lp-v3-collect-protocol-plan.js +91 -0
  217. package/dist/vendor/lp-v3/lp-v3-collect-protocol-reconcile.d.ts +9 -0
  218. package/dist/vendor/lp-v3/lp-v3-collect-protocol-reconcile.js +124 -0
  219. package/dist/vendor/lp-v3/lp-v3-contract.d.ts +538 -0
  220. package/dist/vendor/lp-v3/lp-v3-contract.js +137 -0
  221. package/dist/vendor/lp-v3/lp-v3-evidence.d.ts +25 -0
  222. package/dist/vendor/lp-v3/lp-v3-evidence.js +168 -0
  223. package/dist/vendor/lp-v3/lp-v3-plan.d.ts +22 -0
  224. package/dist/vendor/lp-v3/lp-v3-plan.js +135 -0
  225. package/dist/vendor/lp-v3/types.d.ts +131 -0
  226. package/dist/vendor/lp-v3/types.js +6 -0
  227. package/dist/vendor/lp-v3/v4-math.d.ts +18 -0
  228. package/dist/vendor/lp-v3/v4-math.js +90 -0
  229. package/dist/yield-deposit-definition.d.ts +374 -0
  230. package/dist/yield-deposit-definition.js +123 -0
  231. package/dist/yield-deposit.d.ts +16 -0
  232. package/dist/yield-deposit.js +149 -0
  233. package/dist/yield-route-semantics.d.ts +27 -0
  234. package/dist/yield-route-semantics.js +71 -0
  235. package/dist/yield-withdraw-definition.d.ts +357 -0
  236. package/dist/yield-withdraw-definition.js +90 -0
  237. package/dist/yield-withdraw.d.ts +11 -0
  238. package/dist/yield-withdraw.js +122 -0
  239. package/package.json +239 -7
@@ -0,0 +1,137 @@
1
+ import { bytesToHex, keccak256, parseAbi, stringToHex } from 'viem';
2
+ import { z } from 'zod';
3
+ /** Public runtime bytecode digests, represented as bytes for portable package
4
+ * declarations. Runtime values and exact z.literal checks remain unchanged.
5
+ * These are public chain facts, never credentials or configurable policy.
6
+ */
7
+ function publicCodeHash(bytes) {
8
+ if (bytes.length !== 32 || bytes.some(byte => !Number.isInteger(byte) || byte < 0 || byte > 255))
9
+ throw new Error('LP_INVALID_PUBLIC_CODE_HASH');
10
+ return bytesToHex(Uint8Array.from(bytes));
11
+ }
12
+ // Canonical Base deployment and runtime code read at block 51211952, 2026-09-12.
13
+ // Proxy upgrades deliberately fail closed until separately reviewed and repinned.
14
+ export const LP_V3_BASE = Object.freeze({
15
+ chainId: 8453,
16
+ factory: '0x33128a8fc17869897dce68ed026d694621f6fdfd',
17
+ manager: '0x03a520b32c04bf3beef7beb72e919cf822ed34f1',
18
+ token0: '0x4200000000000000000000000000000000000006', // WETH, 18 decimals
19
+ token1: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', // native USDC, 6 decimals
20
+ factoryCodeHash: publicCodeHash([
21
+ 0x95, 0x70, 0x7a, 0x4a, 0xc7, 0x1f, 0x20, 0x18, 0x1a, 0x63, 0xef, 0x7d, 0x18, 0x0e, 0x3c, 0x62,
22
+ 0x5b, 0xe5, 0xd2, 0x0f, 0xc8, 0xf6, 0xf9, 0x80, 0xbe, 0xfa, 0x96, 0x6b, 0xad, 0x56, 0x81, 0x32,
23
+ ]),
24
+ managerCodeHash: publicCodeHash([
25
+ 0x91, 0x77, 0xa1, 0x17, 0x68, 0x99, 0x6e, 0x8f, 0x95, 0x1e, 0x0f, 0x00, 0x13, 0xd7, 0x16, 0x51,
26
+ 0x34, 0x17, 0x8b, 0x15, 0xb2, 0x1f, 0xb9, 0x91, 0x61, 0x08, 0xf9, 0x95, 0xe6, 0xc5, 0x64, 0xbf,
27
+ ]),
28
+ token0CodeHash: publicCodeHash([
29
+ 0x8a, 0x3a, 0x1f, 0x6a, 0x9f, 0x9d, 0xce, 0x63, 0x31, 0x17, 0xad, 0xee, 0x5b, 0x45, 0x82, 0x45,
30
+ 0x83, 0x5a, 0x86, 0x45, 0xa8, 0xc8, 0x72, 0x6a, 0x26, 0x38, 0x2a, 0x46, 0x22, 0x50, 0x8b, 0x1c,
31
+ ]),
32
+ token1CodeHash: publicCodeHash([
33
+ 0xa6, 0x70, 0x5a, 0x10, 0xbb, 0x75, 0x6b, 0x5d, 0xea, 0x14, 0x45, 0x91, 0x11, 0x8b, 0xe7, 0x7d,
34
+ 0x7a, 0xf0, 0xc3, 0xee, 0xe3, 0xbf, 0x2d, 0xfe, 0x25, 0x83, 0xdc, 0xb0, 0x36, 0x4f, 0xef, 0xab,
35
+ ]),
36
+ usdcImplementationSlot: keccak256(stringToHex('org.zeppelinos.proxy.implementation')),
37
+ usdcImplementation: '0x2ce6311ddae708829bc0784c967b7d77d19fd779',
38
+ usdcImplementationCodeHash: publicCodeHash([
39
+ 0x11, 0xb7, 0x5a, 0x23, 0x79, 0x97, 0xab, 0x83, 0x28, 0xf6, 0x5b, 0x2d, 0x5a, 0x55, 0xc1, 0x0f,
40
+ 0x03, 0x46, 0xd0, 0xa1, 0x75, 0x74, 0x1e, 0xd4, 0x2d, 0xdf, 0x4f, 0x2c, 0x66, 0xb9, 0xe8, 0x73,
41
+ ]),
42
+ });
43
+ export const lpAddress = z.string().regex(/^0x[0-9a-f]{40}$/).refine(v => !/^0x0{40}$/.test(v));
44
+ export const lpHash = z.string().regex(/^0x[0-9a-f]{64}$/).refine(v => !/^0x0{64}$/.test(v));
45
+ export const lpUint = (bits = 256) => z.string().regex(/^(0|[1-9][0-9]{0,77})$/).refine(v => BigInt(v) < 1n << BigInt(bits));
46
+ const uint = lpUint(), uint128 = lpUint(128);
47
+ const tick = z.number().int().min(-887272).max(887272);
48
+ const pair = z.tuple([uint, uint]);
49
+ const common = {
50
+ schemaVersion: z.literal(1), protocol: z.literal('uniswap-v3'), chainId: z.literal(8453),
51
+ // Unique authenticated operation ID. The execution owner's durable journal enforces replay exclusion.
52
+ operationId: z.string().regex(/^[a-zA-Z0-9_-]{16,96}$/),
53
+ account: lpAddress, recipient: lpAddress,
54
+ manager: z.literal(LP_V3_BASE.manager), factory: z.literal(LP_V3_BASE.factory), pool: lpAddress,
55
+ token0: z.literal(LP_V3_BASE.token0), token1: z.literal(LP_V3_BASE.token1),
56
+ fee: z.union([z.literal(100), z.literal(500), z.literal(3000), z.literal(10000)]),
57
+ tickLower: tick, tickUpper: tick,
58
+ deadline: z.number().int().positive().safe(),
59
+ };
60
+ export const lpV3IntentSchema = z.discriminatedUnion('action', [
61
+ z.object({ ...common, action: z.literal('mint'), amountDesired: pair, amountMin: pair }).strict(),
62
+ z.object({ ...common, action: z.literal('increase'), tokenId: uint, amountDesired: pair, amountMin: pair }).strict(),
63
+ z.object({ ...common, action: z.literal('decrease'), tokenId: uint, liquidity: uint128, amountMin: pair }).strict(),
64
+ // collect has no onchain deadline/minimum. The sender must check deadline before signing;
65
+ // output floors are settlement postconditions, not an atomic slippage guarantee.
66
+ z.object({ ...common, action: z.literal('collect'), tokenId: uint, amountMax: z.tuple([uint128, uint128]), amountMin: pair }).strict(),
67
+ ]);
68
+ export const lpV3PositionSchema = z.object({
69
+ tokenId: uint, owner: lpAddress, token0: lpAddress, token1: lpAddress,
70
+ fee: z.number().int(), tickLower: tick, tickUpper: tick, liquidity: uint128,
71
+ tokensOwed: z.tuple([uint128, uint128]),
72
+ }).strict();
73
+ export const lpV3ChainEvidenceSchema = z.object({
74
+ schemaVersion: z.literal(1), chainId: z.literal(8453),
75
+ blockNumber: uint, blockHash: lpHash, blockTimestamp: z.number().int().positive().safe(),
76
+ observedAt: z.number().int().positive().safe(), canonical: z.literal(true),
77
+ account: lpAddress, accountCode: z.literal('0x'), balances: pair, allowances: pair,
78
+ manager: z.literal(LP_V3_BASE.manager), managerFactory: z.literal(LP_V3_BASE.factory),
79
+ factory: z.literal(LP_V3_BASE.factory), factoryPool: lpAddress,
80
+ factoryCodeHash: z.literal(LP_V3_BASE.factoryCodeHash), managerCodeHash: z.literal(LP_V3_BASE.managerCodeHash),
81
+ token0CodeHash: z.literal(LP_V3_BASE.token0CodeHash), token1CodeHash: z.literal(LP_V3_BASE.token1CodeHash),
82
+ usdcImplementation: z.literal(LP_V3_BASE.usdcImplementation),
83
+ usdcImplementationCodeHash: z.literal(LP_V3_BASE.usdcImplementationCodeHash),
84
+ usdcPaused: z.literal(false), accountBlacklisted: z.literal(false), managerBlacklisted: z.literal(false),
85
+ pool: lpAddress, poolFactory: z.literal(LP_V3_BASE.factory),
86
+ token0: z.literal(LP_V3_BASE.token0), token1: z.literal(LP_V3_BASE.token1),
87
+ fee: z.number().int(), tickSpacing: z.number().int().positive(),
88
+ tick, sqrtPriceX96: lpUint(160), unlocked: z.literal(true),
89
+ position: lpV3PositionSchema.nullable(),
90
+ }).strict();
91
+ export const lpV3CallSchema = z.object({
92
+ step: z.enum(['approve', 'mutation', 'cleanup']), tokenIndex: z.union([z.literal(0), z.literal(1)]).nullable(),
93
+ chainId: z.literal(8453), from: lpAddress, to: lpAddress, value: z.literal('0'),
94
+ data: z.string().regex(/^0x[0-9a-f]+$/),
95
+ }).strict();
96
+ export const lpV3SigningSupportSchema = z.enum(['HOST_GATES_REQUIRED', 'BLOCKED_ATOMIC_NFT_OWNER_GUARD', 'BLOCKED_ATOMIC_COLLECTION_GUARD']);
97
+ export const lpV3PreparedPlanSchema = z.object({
98
+ schemaVersion: z.literal(1), kind: z.literal('lp-v3'), intent: lpV3IntentSchema,
99
+ signingSupport: lpV3SigningSupportSchema,
100
+ intentCommitment: lpHash, calls: z.array(lpV3CallSchema).min(1).max(5),
101
+ // Economic state read at preparation; verification independently refreshes it.
102
+ preparedBlock: z.object({ number: uint, hash: lpHash }).strict(),
103
+ planCommitment: lpHash,
104
+ }).strict();
105
+ export const LP_V3_NPM_ABI = parseAbi([
106
+ 'function mint((address token0,address token1,uint24 fee,int24 tickLower,int24 tickUpper,uint256 amount0Desired,uint256 amount1Desired,uint256 amount0Min,uint256 amount1Min,address recipient,uint256 deadline) params) payable returns (uint256 tokenId,uint128 liquidity,uint256 amount0,uint256 amount1)',
107
+ 'function increaseLiquidity((uint256 tokenId,uint256 amount0Desired,uint256 amount1Desired,uint256 amount0Min,uint256 amount1Min,uint256 deadline) params) payable returns (uint128 liquidity,uint256 amount0,uint256 amount1)',
108
+ 'function decreaseLiquidity((uint256 tokenId,uint128 liquidity,uint256 amount0Min,uint256 amount1Min,uint256 deadline) params) payable returns (uint256 amount0,uint256 amount1)',
109
+ 'function collect((uint256 tokenId,address recipient,uint128 amount0Max,uint128 amount1Max) params) payable returns (uint256 amount0,uint256 amount1)',
110
+ 'event IncreaseLiquidity(uint256 indexed tokenId,uint128 liquidity,uint256 amount0,uint256 amount1)',
111
+ 'event DecreaseLiquidity(uint256 indexed tokenId,uint128 liquidity,uint256 amount0,uint256 amount1)',
112
+ 'event Collect(uint256 indexed tokenId,address recipient,uint256 amount0,uint256 amount1)',
113
+ 'event Transfer(address indexed from,address indexed to,uint256 indexed tokenId)',
114
+ ]);
115
+ export const LP_V3_ERC20_ABI = parseAbi([
116
+ 'function approve(address spender,uint256 amount) returns (bool)',
117
+ 'event Transfer(address indexed from,address indexed to,uint256 value)',
118
+ ]);
119
+ export function canonicalJson(value) {
120
+ if (Array.isArray(value))
121
+ return `[${value.map(canonicalJson).join(',')}]`;
122
+ if (value !== null && typeof value === 'object')
123
+ return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(',')}}`;
124
+ const encoded = JSON.stringify(value);
125
+ if (encoded === undefined)
126
+ throw new Error('LP_UNSERIALIZABLE_VALUE');
127
+ return encoded;
128
+ }
129
+ export const commitment = (value) => keccak256(stringToHex(canonicalJson(value)));
130
+ export function deepFreeze(value) {
131
+ if (value && typeof value === 'object') {
132
+ Object.values(value).forEach(deepFreeze);
133
+ Object.freeze(value);
134
+ }
135
+ return value;
136
+ }
137
+ //# sourceMappingURL=lp-v3-contract.js.map
@@ -0,0 +1,25 @@
1
+ import { type LpV3ChainEvidence, type LpV3Intent } from './lp-v3-contract.js';
2
+ export interface LpV3ReadRequest {
3
+ method: 'eth_chainId' | 'eth_getBlockByNumber' | 'eth_getCode' | 'eth_getStorageAt' | 'eth_call';
4
+ params?: readonly unknown[];
5
+ }
6
+ /** Trusted host dependency, never a caller-supplied evidence/API object. */
7
+ export interface LpV3ReadClient {
8
+ request(request: LpV3ReadRequest): Promise<unknown>;
9
+ }
10
+ export interface LpV3EvidenceOptions {
11
+ client?: LpV3ReadClient;
12
+ /** Trusted host clock, in integer Unix seconds. */
13
+ nowSeconds?: () => number;
14
+ /** May tighten the default 60 seconds; hard maximum 60 seconds. */
15
+ maxBlockAgeSeconds?: number;
16
+ }
17
+ export declare class LpV3EvidenceError extends Error {
18
+ readonly code: string;
19
+ constructor(code: string);
20
+ }
21
+ /** Read-only Base evidence. EIP-1898 binds every state read to one canonical hash.
22
+ * Unsupported hash-based RPC reads fail closed; there is no latest-state fallback.
23
+ * This is a point-in-time RPC observation, not finality or permission to execute.
24
+ */
25
+ export declare function collectLpV3ChainEvidence(input: LpV3Intent, options?: LpV3EvidenceOptions): Promise<LpV3ChainEvidence>;
@@ -0,0 +1,168 @@
1
+ import { createPublicClient, decodeFunctionResult, encodeFunctionData, http, keccak256, parseAbi } from 'viem';
2
+ import { base } from 'viem/chains';
3
+ import { LP_V3_BASE, lpV3ChainEvidenceSchema, lpV3IntentSchema, lpV3PositionSchema } from './lp-v3-contract.js';
4
+ import { MAX_TICK, MIN_TICK, sqrtPriceAtTick } from './v4-math.js';
5
+ const READ_ABI = parseAbi([
6
+ 'function factory() view returns (address)', 'function WETH9() view returns (address)',
7
+ 'function getPool(address token0,address token1,uint24 fee) view returns (address)',
8
+ 'function feeAmountTickSpacing(uint24 fee) view returns (int24)',
9
+ 'function token0() view returns (address)', 'function token1() view returns (address)',
10
+ 'function fee() view returns (uint24)', 'function tickSpacing() view returns (int24)',
11
+ 'function slot0() view returns (uint160 sqrtPriceX96,int24 tick,uint16 observationIndex,uint16 observationCardinality,uint16 observationCardinalityNext,uint8 feeProtocol,bool unlocked)',
12
+ 'function balanceOf(address owner) view returns (uint256)',
13
+ 'function allowance(address owner,address spender) view returns (uint256)',
14
+ 'function decimals() view returns (uint8)', 'function paused() view returns (bool)',
15
+ 'function isBlacklisted(address account) view returns (bool)',
16
+ 'function ownerOf(uint256 tokenId) view returns (address)',
17
+ 'function positions(uint256 tokenId) view returns (uint96 nonce,address operator,address token0,address token1,uint24 fee,int24 tickLower,int24 tickUpper,uint128 liquidity,uint256 feeGrowthInside0LastX128,uint256 feeGrowthInside1LastX128,uint128 tokensOwed0,uint128 tokensOwed1)',
18
+ ]);
19
+ export class LpV3EvidenceError extends Error {
20
+ code;
21
+ constructor(code) {
22
+ super(code);
23
+ this.code = code;
24
+ this.name = 'LpV3EvidenceError';
25
+ }
26
+ }
27
+ function requireState(condition, code) {
28
+ if (!condition)
29
+ throw new LpV3EvidenceError(code);
30
+ }
31
+ function address(value) {
32
+ requireState(typeof value === 'string' && /^0x[0-9a-fA-F]{40}$/.test(value) && !/^0x0{40}$/.test(value), 'LP_V3_INVALID_ADDRESS');
33
+ return value.toLowerCase();
34
+ }
35
+ function hex(value) {
36
+ requireState(typeof value === 'string' && /^0x(?:[0-9a-fA-F]{2})*$/.test(value), 'LP_V3_INVALID_RPC_DATA');
37
+ return value.toLowerCase();
38
+ }
39
+ function quantity(value) {
40
+ requireState(typeof value === 'string' && /^0x(?:0|[1-9a-fA-F][0-9a-fA-F]*)$/.test(value), 'LP_V3_INVALID_RPC_QUANTITY');
41
+ return BigInt(value);
42
+ }
43
+ function uint(value, bits = 256) {
44
+ requireState(typeof value === 'bigint' && value >= 0n && value < 1n << BigInt(bits), 'LP_V3_INVALID_CONTRACT_UINT');
45
+ return value;
46
+ }
47
+ function integer(value, minimum, maximum) {
48
+ requireState(typeof value === 'number' && Number.isSafeInteger(value) && value >= minimum && value <= maximum, 'LP_V3_INVALID_CONTRACT_INTEGER');
49
+ return value;
50
+ }
51
+ function tuple(value, length) {
52
+ requireState(Array.isArray(value) && value.length === length, 'LP_V3_INVALID_CONTRACT_TUPLE');
53
+ return value;
54
+ }
55
+ function block(value) {
56
+ requireState(value !== null && typeof value === 'object', 'LP_V3_BLOCK_UNAVAILABLE');
57
+ const raw = value, number = quantity(raw.number), timestamp = quantity(raw.timestamp), hash = hex(raw.hash);
58
+ requireState(hash.length === 66 && !/^0x0{64}$/.test(hash) && timestamp > 0n && timestamp <= BigInt(Number.MAX_SAFE_INTEGER), 'LP_V3_INVALID_BLOCK');
59
+ return { number, hash, timestamp: Number(timestamp) };
60
+ }
61
+ /** Read-only Base evidence. EIP-1898 binds every state read to one canonical hash.
62
+ * Unsupported hash-based RPC reads fail closed; there is no latest-state fallback.
63
+ * This is a point-in-time RPC observation, not finality or permission to execute.
64
+ */
65
+ export async function collectLpV3ChainEvidence(input, options = {}) {
66
+ try {
67
+ const parsed = lpV3IntentSchema.safeParse(input);
68
+ requireState(parsed.success, 'LP_V3_INVALID_INTENT');
69
+ const intent = parsed.data, pins = LP_V3_BASE;
70
+ const maxAge = options.maxBlockAgeSeconds ?? 60;
71
+ requireState(Number.isSafeInteger(maxAge) && maxAge > 0 && maxAge <= 60, 'LP_V3_INVALID_FRESHNESS_LIMIT');
72
+ const now = options.nowSeconds ?? (() => Math.floor(Date.now() / 1000));
73
+ const clock = () => integer(now(), 1, Number.MAX_SAFE_INTEGER);
74
+ const startedAt = clock();
75
+ const publicClient = options.client ? null : createPublicClient({ chain: base, transport: http('https://mainnet.base.org', { timeout: 15_000, retryCount: 1 }) });
76
+ // The constrained raw interface preserves EIP-1898 for all three state methods.
77
+ const request = publicClient?.request;
78
+ // Bound concurrency on the default public endpoint. A failed read also
79
+ // rejects its queued successors; no incomplete evidence can be returned.
80
+ let pending = Promise.resolve();
81
+ const client = options.client ?? { request: args => (pending = pending.then(() => request(args))) };
82
+ const chain = async () => requireState(quantity(await client.request({ method: 'eth_chainId' })) === BigInt(pins.chainId), 'LP_V3_RPC_CHAIN_MISMATCH');
83
+ await chain();
84
+ const anchor = block(await client.request({ method: 'eth_getBlockByNumber', params: ['latest', false] }));
85
+ const fresh = (time) => requireState(anchor.timestamp <= time && time - anchor.timestamp <= maxAge, 'LP_V3_STALE_OR_FUTURE_BLOCK');
86
+ fresh(clock());
87
+ const reference = Object.freeze({ blockHash: anchor.hash, requireCanonical: true });
88
+ const read = async (target, functionName, args) => {
89
+ const data = encodeFunctionData({ abi: READ_ABI, functionName, args });
90
+ const result = hex(await client.request({ method: 'eth_call', params: [{ to: target, data }, reference] }));
91
+ return decodeFunctionResult({ abi: READ_ABI, functionName, data: result });
92
+ };
93
+ const getCode = async (target) => hex(await client.request({ method: 'eth_getCode', params: [target, reference] }));
94
+ const [factoryPoolRaw, factorySpacingRaw, managerFactoryRaw, managerWethRaw, accountCode, implementationStorage] = await Promise.all([
95
+ read(pins.factory, 'getPool', [pins.token0, pins.token1, intent.fee]),
96
+ read(pins.factory, 'feeAmountTickSpacing', [intent.fee]),
97
+ read(pins.manager, 'factory'), read(pins.manager, 'WETH9'), getCode(intent.account),
98
+ client.request({ method: 'eth_getStorageAt', params: [pins.token1, pins.usdcImplementationSlot, reference] }),
99
+ ]);
100
+ const factoryPool = address(factoryPoolRaw), managerFactory = address(managerFactoryRaw);
101
+ requireState(factoryPool === intent.pool && managerFactory === pins.factory && address(managerWethRaw) === pins.token0, 'LP_V3_DEPLOYMENT_IDENTITY_MISMATCH');
102
+ requireState(accountCode === '0x', 'LP_V3_EOA_REQUIRED');
103
+ const storage = hex(implementationStorage);
104
+ requireState(/^0x0{24}[0-9a-f]{40}$/.test(storage), 'LP_V3_INVALID_USDC_IMPLEMENTATION_SLOT');
105
+ const usdcImplementation = address(`0x${storage.slice(-40)}`);
106
+ requireState(usdcImplementation === pins.usdcImplementation, 'LP_V3_USDC_IMPLEMENTATION_CHANGED');
107
+ const tickSpacing = integer(factorySpacingRaw, 1, 16_383);
108
+ requireState(intent.tickLower < intent.tickUpper && intent.tickLower % tickSpacing === 0 && intent.tickUpper % tickSpacing === 0, 'LP_V3_INVALID_INTENT_TICKS');
109
+ const [poolFactoryRaw, token0Raw, token1Raw, feeRaw, spacingRaw, rawSlot, balancesRaw, allowancesRaw, paused, accountBlacklisted, managerBlacklisted, decimals, codes, positionRaw] = await Promise.all([
110
+ read(factoryPool, 'factory'), read(factoryPool, 'token0'), read(factoryPool, 'token1'),
111
+ read(factoryPool, 'fee'), read(factoryPool, 'tickSpacing'), read(factoryPool, 'slot0'),
112
+ Promise.all([pins.token0, pins.token1].map(token => read(token, 'balanceOf', [intent.account]))),
113
+ Promise.all([pins.token0, pins.token1].map(token => read(token, 'allowance', [intent.account, pins.manager]))),
114
+ read(pins.token1, 'paused'), read(pins.token1, 'isBlacklisted', [intent.account]), read(pins.token1, 'isBlacklisted', [pins.manager]),
115
+ Promise.all([pins.token0, pins.token1].map(token => read(token, 'decimals'))),
116
+ Promise.all([pins.factory, pins.manager, pins.token0, pins.token1, usdcImplementation, factoryPool].map(getCode)),
117
+ intent.action === 'mint' ? null : Promise.all([read(pins.manager, 'ownerOf', [BigInt(intent.tokenId)]), read(pins.manager, 'positions', [BigInt(intent.tokenId)])]),
118
+ ]);
119
+ const poolFactory = address(poolFactoryRaw), token0 = address(token0Raw), token1 = address(token1Raw);
120
+ const fee = integer(feeRaw, 0, 999_999);
121
+ requireState(poolFactory === pins.factory && token0 === pins.token0 && token1 === pins.token1 && fee === intent.fee && spacingRaw === tickSpacing, 'LP_V3_POOL_IDENTITY_MISMATCH');
122
+ requireState(paused === false && accountBlacklisted === false && managerBlacklisted === false, 'LP_V3_USDC_TRANSFER_RESTRICTED');
123
+ requireState(decimals[0] === 18 && decimals[1] === 6, 'LP_V3_TOKEN_DECIMALS_MISMATCH');
124
+ const slot = tuple(rawSlot, 7), sqrt = uint(slot[0], 160), tick = integer(slot[1], MIN_TICK, MAX_TICK - 1);
125
+ requireState(slot[6] === true && sqrt >= sqrtPriceAtTick(MIN_TICK) && sqrt < sqrtPriceAtTick(MAX_TICK), 'LP_V3_UNINITIALIZED_OR_LOCKED_POOL');
126
+ // Exact downward tick crossings legitimately leave slot0.tick one below the ratio's tick.
127
+ requireState(sqrt >= sqrtPriceAtTick(tick) && sqrt <= sqrtPriceAtTick(tick + 1), 'LP_V3_INCONSISTENT_POOL_PRICE');
128
+ const balances = balancesRaw.map(value => uint(value).toString()), allowances = allowancesRaw.map(value => uint(value).toString());
129
+ let position = null;
130
+ if (intent.action !== 'mint') {
131
+ requireState(positionRaw !== null, 'LP_V3_POSITION_UNAVAILABLE');
132
+ const data = tuple(positionRaw[1], 12);
133
+ position = lpV3PositionSchema.parse({
134
+ tokenId: intent.tokenId, owner: address(positionRaw[0]), token0: address(data[2]), token1: address(data[3]),
135
+ fee: integer(data[4], 0, 999_999), tickLower: integer(data[5], MIN_TICK, MAX_TICK), tickUpper: integer(data[6], MIN_TICK, MAX_TICK),
136
+ liquidity: uint(data[7], 128).toString(), tokensOwed: [uint(data[10], 128).toString(), uint(data[11], 128).toString()],
137
+ });
138
+ requireState(position.owner === intent.account, 'LP_V3_NFT_OWNER_MISMATCH');
139
+ requireState(position.token0 === token0 && position.token1 === token1 && position.fee === fee && position.tickLower === intent.tickLower && position.tickUpper === intent.tickUpper, 'LP_V3_NFT_POSITION_MISMATCH');
140
+ }
141
+ requireState(codes.every(code => code !== '0x'), 'LP_V3_CONTRACT_CODE_UNAVAILABLE');
142
+ // Re-read the canonical number mapping even though each state call required canonicality.
143
+ const canonicalBlock = block(await client.request({ method: 'eth_getBlockByNumber', params: [`0x${anchor.number.toString(16)}`, false] }));
144
+ await chain();
145
+ requireState(canonicalBlock.number === anchor.number && canonicalBlock.hash === anchor.hash && canonicalBlock.timestamp === anchor.timestamp, 'LP_V3_BLOCK_REORG');
146
+ const observedAt = clock();
147
+ requireState(observedAt >= startedAt, 'LP_V3_CLOCK_MOVED_BACKWARDS');
148
+ fresh(observedAt);
149
+ const hashes = codes.slice(0, 5).map(code => keccak256(code));
150
+ const expectedHashes = [pins.factoryCodeHash, pins.managerCodeHash, pins.token0CodeHash, pins.token1CodeHash, pins.usdcImplementationCodeHash];
151
+ requireState(hashes.every((hash, index) => hash === expectedHashes[index]), 'LP_V3_RUNTIME_CODE_CHANGED');
152
+ return lpV3ChainEvidenceSchema.parse({
153
+ schemaVersion: 1, chainId: pins.chainId, blockNumber: anchor.number.toString(), blockHash: anchor.hash,
154
+ blockTimestamp: anchor.timestamp, observedAt, canonical: true, account: intent.account, accountCode, balances, allowances,
155
+ manager: pins.manager, managerFactory, factory: pins.factory, factoryPool,
156
+ factoryCodeHash: hashes[0], managerCodeHash: hashes[1], token0CodeHash: hashes[2], token1CodeHash: hashes[3],
157
+ usdcImplementation, usdcImplementationCodeHash: hashes[4], usdcPaused: paused, accountBlacklisted, managerBlacklisted,
158
+ pool: factoryPool, poolFactory, token0, token1, fee, tickSpacing, tick, sqrtPriceX96: sqrt.toString(), unlocked: slot[6], position,
159
+ });
160
+ }
161
+ catch (error) {
162
+ // RPC messages can contain endpoint credentials. Never include the underlying error.
163
+ if (error instanceof LpV3EvidenceError)
164
+ throw error;
165
+ throw new LpV3EvidenceError('LP_V3_REQUIRED_CHAIN_STATE_UNAVAILABLE');
166
+ }
167
+ }
168
+ //# sourceMappingURL=lp-v3-evidence.js.map
@@ -0,0 +1,22 @@
1
+ import { type LpV3ChainEvidence, type LpV3Intent, type LpV3PreparedPlan } from './lp-v3-contract.js';
2
+ declare const verifiedLpBrand: unique symbol;
3
+ export interface VerifiedLpV3Plan {
4
+ readonly [verifiedLpBrand]: true;
5
+ readonly plan: LpV3PreparedPlan;
6
+ readonly evidence: LpV3ChainEvidence;
7
+ readonly verifiedAt: number;
8
+ }
9
+ /** Clock injection is a trusted host/test option, never an HTTP request field. */
10
+ export interface LpV3VerifyOptions {
11
+ now?: () => number;
12
+ }
13
+ export declare function requireVerifiedLpV3Plan(value: VerifiedLpV3Plan): void;
14
+ export declare function checkLpV3Context(intent: LpV3Intent, evidence: LpV3ChainEvidence, now: number): void;
15
+ /** Preparation grants no wallet authority. Inputs are parsed and copied before use. */
16
+ export declare function prepareLpV3Plan(input: unknown, chainEvidence: unknown, options?: LpV3VerifyOptions): LpV3PreparedPlan;
17
+ /** independentIntent and freshEvidence MUST originate in the authenticated host.
18
+ * Deserialized client-supplied plans cannot confer either intent or chain authority.
19
+ * The host also enforces durable operation-ID admission, gas budgets and nonce claims.
20
+ */
21
+ export declare function verifyLpV3Plan(input: unknown, independentIntent: unknown, freshEvidence: unknown, options?: LpV3VerifyOptions): VerifiedLpV3Plan;
22
+ export {};
@@ -0,0 +1,135 @@
1
+ import { encodeFunctionData } from 'viem';
2
+ import { LP_V3_BASE, LP_V3_ERC20_ABI, LP_V3_NPM_ABI, canonicalJson, commitment, deepFreeze, lpV3ChainEvidenceSchema, lpV3IntentSchema, lpV3PreparedPlanSchema, } from './lp-v3-contract.js';
3
+ import { sqrtPriceAtTick } from './v4-math.js';
4
+ const verified = new WeakSet();
5
+ export function requireVerifiedLpV3Plan(value) {
6
+ if (!value || !verified.has(value))
7
+ throw new Error('LP_UNVERIFIED_PLAN');
8
+ }
9
+ export function checkLpV3Context(intent, evidence, now) {
10
+ if (!Number.isSafeInteger(now) || now <= 0)
11
+ throw new Error('LP_INVALID_CLOCK');
12
+ if (intent.account !== intent.recipient || evidence.account !== intent.account)
13
+ throw new Error('LP_OWNER_RECIPIENT_MISMATCH');
14
+ if (evidence.observedAt > now || now - evidence.observedAt > 30 || evidence.blockTimestamp > evidence.observedAt || now - evidence.blockTimestamp > 60)
15
+ throw new Error('LP_STALE_CHAIN_EVIDENCE');
16
+ if (intent.deadline <= now || intent.deadline > now + 300)
17
+ throw new Error('LP_DEADLINE_OUT_OF_BOUNDS');
18
+ if (intent.pool !== evidence.pool || evidence.factoryPool !== intent.pool || intent.fee !== evidence.fee)
19
+ throw new Error('LP_POOL_MISMATCH');
20
+ const spacing = { 100: 1, 500: 10, 3000: 60, 10000: 200 }[intent.fee];
21
+ if (evidence.tickSpacing !== spacing || intent.tickLower % spacing || intent.tickUpper % spacing || intent.tickLower >= intent.tickUpper)
22
+ throw new Error('LP_INVALID_RANGE');
23
+ const sqrt = BigInt(evidence.sqrtPriceX96);
24
+ if (evidence.tick >= 887272 || sqrt < sqrtPriceAtTick(-887272) || sqrt >= sqrtPriceAtTick(887272) || sqrt < sqrtPriceAtTick(evidence.tick) || sqrt > sqrtPriceAtTick(evidence.tick + 1))
25
+ throw new Error('LP_INVALID_POOL_PRICE');
26
+ // Every supported operation starts with no standing ERC20 authority to the NPM.
27
+ // Recovery of a partially submitted sequence belongs to the durable execution journal.
28
+ if (evidence.allowances.some(v => v !== '0'))
29
+ throw new Error('LP_EXISTING_ALLOWANCE_REQUIRES_RECOVERY');
30
+ if (intent.action === 'mint') {
31
+ if (evidence.position !== null)
32
+ throw new Error('LP_UNEXPECTED_POSITION');
33
+ }
34
+ else {
35
+ const p = evidence.position;
36
+ if (intent.tokenId === '0' || !p || p.tokenId !== intent.tokenId || p.owner !== intent.account || p.token0 !== intent.token0 || p.token1 !== intent.token1 || p.fee !== intent.fee || p.tickLower !== intent.tickLower || p.tickUpper !== intent.tickUpper)
37
+ throw new Error('LP_NFT_IDENTITY_MISMATCH');
38
+ }
39
+ if (intent.action === 'mint' || intent.action === 'increase') {
40
+ if (intent.amountDesired.every(v => v === '0'))
41
+ throw new Error('LP_EMPTY_DEPOSIT');
42
+ for (const i of [0, 1]) {
43
+ const desired = BigInt(intent.amountDesired[i]), min = BigInt(intent.amountMin[i]);
44
+ if (desired > BigInt(evidence.balances[i]))
45
+ throw new Error('LP_INSUFFICIENT_BALANCE');
46
+ // Positive desired inputs require a positive onchain amount floor. A one-sided
47
+ // operation is expressed by setting BOTH desired and minimum of the other side to 0.
48
+ if (min > desired || (desired > 0n && min === 0n))
49
+ throw new Error('LP_INVALID_INPUT_FLOOR');
50
+ }
51
+ }
52
+ else if (intent.action === 'decrease') {
53
+ if (intent.liquidity === '0' || BigInt(intent.liquidity) > BigInt(evidence.position.liquidity) || intent.amountMin.every(v => v === '0'))
54
+ throw new Error('LP_INVALID_DECREASE');
55
+ }
56
+ else {
57
+ if (intent.amountMax.every(v => v === '0') || intent.amountMin.every(v => v === '0'))
58
+ throw new Error('LP_EMPTY_COLLECTION');
59
+ if (intent.amountMin.some((v, i) => BigInt(v) > BigInt(intent.amountMax[i])))
60
+ throw new Error('LP_INVALID_COLLECTION_FLOOR');
61
+ }
62
+ }
63
+ function deriveCalls(intent) {
64
+ const calls = [];
65
+ const add = (step, to, data, tokenIndex = null) => calls.push({ step, tokenIndex, chainId: 8453, from: intent.account, to, value: '0', data });
66
+ const addApproval = (i, amount, step) => add(step, i === 0 ? intent.token0 : intent.token1, encodeFunctionData({ abi: LP_V3_ERC20_ABI, functionName: 'approve', args: [LP_V3_BASE.manager, amount] }), i);
67
+ if (intent.action === 'mint' || intent.action === 'increase') {
68
+ for (const i of [0, 1])
69
+ if (intent.amountDesired[i] !== '0')
70
+ addApproval(i, BigInt(intent.amountDesired[i]), 'approve');
71
+ const amounts = { amount0Desired: BigInt(intent.amountDesired[0]), amount1Desired: BigInt(intent.amountDesired[1]), amount0Min: BigInt(intent.amountMin[0]), amount1Min: BigInt(intent.amountMin[1]), deadline: BigInt(intent.deadline) };
72
+ const data = intent.action === 'mint'
73
+ ? encodeFunctionData({ abi: LP_V3_NPM_ABI, functionName: 'mint', args: [{ ...amounts, token0: LP_V3_BASE.token0, token1: LP_V3_BASE.token1, fee: intent.fee, tickLower: intent.tickLower, tickUpper: intent.tickUpper, recipient: intent.recipient }] })
74
+ : encodeFunctionData({ abi: LP_V3_NPM_ABI, functionName: 'increaseLiquidity', args: [{ ...amounts, tokenId: BigInt(intent.tokenId) }] });
75
+ add('mutation', intent.manager, data);
76
+ // Always revoke the exact allowance after partial fills; never retain a remainder.
77
+ for (const i of [0, 1])
78
+ if (intent.amountDesired[i] !== '0')
79
+ addApproval(i, 0n, 'cleanup');
80
+ }
81
+ else if (intent.action === 'decrease') {
82
+ add('mutation', intent.manager, encodeFunctionData({ abi: LP_V3_NPM_ABI, functionName: 'decreaseLiquidity', args: [{ tokenId: BigInt(intent.tokenId), liquidity: BigInt(intent.liquidity), amount0Min: BigInt(intent.amountMin[0]), amount1Min: BigInt(intent.amountMin[1]), deadline: BigInt(intent.deadline) }] }));
83
+ }
84
+ else {
85
+ add('mutation', intent.manager, encodeFunctionData({ abi: LP_V3_NPM_ABI, functionName: 'collect', args: [{ tokenId: BigInt(intent.tokenId), recipient: intent.account, amount0Max: BigInt(intent.amountMax[0]), amount1Max: BigInt(intent.amountMax[1]) }] }));
86
+ }
87
+ return calls;
88
+ }
89
+ function signingSupport(intent) {
90
+ if (intent.action === 'increase')
91
+ return 'BLOCKED_ATOMIC_NFT_OWNER_GUARD';
92
+ if (intent.action === 'collect')
93
+ return 'BLOCKED_ATOMIC_COLLECTION_GUARD';
94
+ return 'HOST_GATES_REQUIRED';
95
+ }
96
+ /** Preparation grants no wallet authority. Inputs are parsed and copied before use. */
97
+ export function prepareLpV3Plan(input, chainEvidence, options = {}) {
98
+ const intent = lpV3IntentSchema.parse(input), evidence = lpV3ChainEvidenceSchema.parse(chainEvidence);
99
+ const now = (options.now ?? (() => Math.floor(Date.now() / 1000)))();
100
+ checkLpV3Context(intent, evidence, now);
101
+ const body = { schemaVersion: 1, kind: 'lp-v3', intent, signingSupport: signingSupport(intent), intentCommitment: commitment(intent), calls: deriveCalls(intent), preparedBlock: { number: evidence.blockNumber, hash: evidence.blockHash } };
102
+ return deepFreeze({ ...body, planCommitment: commitment(body) });
103
+ }
104
+ /** independentIntent and freshEvidence MUST originate in the authenticated host.
105
+ * Deserialized client-supplied plans cannot confer either intent or chain authority.
106
+ * The host also enforces durable operation-ID admission, gas budgets and nonce claims.
107
+ */
108
+ export function verifyLpV3Plan(input, independentIntent, freshEvidence, options = {}) {
109
+ const plan = lpV3PreparedPlanSchema.parse(input), intent = lpV3IntentSchema.parse(independentIntent), evidence = lpV3ChainEvidenceSchema.parse(freshEvidence);
110
+ const now = (options.now ?? (() => Math.floor(Date.now() / 1000)))();
111
+ checkLpV3Context(intent, evidence, now);
112
+ // An NFT operator can transfer an existing NFT after the read, and NPM increase
113
+ // is permissionless: it would still spend into that now-foreign NFT. Collection
114
+ // similarly cannot atomically enforce this contract's deadline/output floors.
115
+ // Neither action can acquire the verified runtime brand through this entry.
116
+ if (intent.action === 'increase')
117
+ throw new Error('LP_ATOMIC_NFT_OWNER_GUARD_REQUIRED');
118
+ if (intent.action === 'collect')
119
+ throw new Error('LP_ATOMIC_COLLECTION_GUARD_REQUIRED');
120
+ if (plan.signingSupport !== signingSupport(intent))
121
+ throw new Error('LP_SIGNING_SUPPORT_MISMATCH');
122
+ if (canonicalJson(plan.intent) !== canonicalJson(intent) || plan.intentCommitment !== commitment(intent))
123
+ throw new Error('LP_INDEPENDENT_INTENT_MISMATCH');
124
+ if (canonicalJson(plan.calls) !== canonicalJson(deriveCalls(intent)))
125
+ throw new Error('LP_CALL_SEQUENCE_MISMATCH');
126
+ const { planCommitment, ...body } = plan;
127
+ if (planCommitment !== commitment(body))
128
+ throw new Error('LP_PLAN_COMMITMENT_MISMATCH');
129
+ if (BigInt(plan.preparedBlock.number) > BigInt(evidence.blockNumber) || (plan.preparedBlock.number === evidence.blockNumber && plan.preparedBlock.hash !== evidence.blockHash))
130
+ throw new Error('LP_PREPARATION_BLOCK_MISMATCH');
131
+ const result = deepFreeze({ plan, evidence, verifiedAt: now });
132
+ verified.add(result);
133
+ return result;
134
+ }
135
+ //# sourceMappingURL=lp-v3-plan.js.map
@@ -0,0 +1,131 @@
1
+ export type Hex = `0x${string}`;
2
+ export type Pair<T> = [T, T];
3
+ export interface PositionRef {
4
+ chainId: 4663;
5
+ positionManager: Hex;
6
+ tokenId: string;
7
+ expectedOwner?: Hex;
8
+ }
9
+ export interface PoolKey {
10
+ currency0: Hex;
11
+ currency1: Hex;
12
+ fee: number;
13
+ tickSpacing: number;
14
+ hooks: Hex;
15
+ }
16
+ export interface TokenInfo {
17
+ address: Hex;
18
+ symbol: string;
19
+ decimals: number;
20
+ paused: boolean | null;
21
+ oraclePaused: boolean | null;
22
+ multiplier: string | null;
23
+ }
24
+ export interface PositionSnapshot {
25
+ schemaVersion: 1;
26
+ snapshotId: string;
27
+ ref: PositionRef;
28
+ /** Absent on legacy snapshots means uniswap-v4. */
29
+ protocol?: 'uniswap-v3' | 'uniswap-v4';
30
+ observedAt: string;
31
+ block: {
32
+ number: string;
33
+ hash: Hex;
34
+ timestamp: string;
35
+ finality: 'latest' | 'safe' | 'finalized';
36
+ };
37
+ status: 'READY' | 'CLOSED' | 'UNSUPPORTED' | 'UNAVAILABLE';
38
+ owner: Hex | null;
39
+ pool: {
40
+ id: Hex;
41
+ address?: Hex;
42
+ key: PoolKey;
43
+ sqrtPriceX96: string;
44
+ tick: number;
45
+ lowerTick: number;
46
+ upperTick: number;
47
+ activeLiquidity: string;
48
+ } | null;
49
+ tokens: Pair<TokenInfo> | null;
50
+ liquidity: string | null;
51
+ principalRaw: Pair<string> | null;
52
+ feesOwedRaw: Pair<string> | null;
53
+ /** V3 stored collectable balances can contain withdrawn principal; never label these fees without history. */
54
+ tokensOwedRaw?: Pair<string> | null;
55
+ feeGrowthInsideX128: Pair<string> | null;
56
+ feeGrowthInsideLastX128: Pair<string> | null;
57
+ marksUsd: Pair<number | null>;
58
+ markSource: string;
59
+ warnings: string[];
60
+ }
61
+ export interface TrackingBaseline {
62
+ snapshot: PositionSnapshot;
63
+ establishedAt: string;
64
+ basis: 'since-tracking-start';
65
+ }
66
+ export interface WatchPolicy {
67
+ version: 1;
68
+ stopLossUsd: number | null;
69
+ takeProfitReviewUsd: number | null;
70
+ trailingDrawdownUsd: number | null;
71
+ rangeWarningFraction: number;
72
+ maxSnapshotAgeSeconds: number;
73
+ maxQuoteAgeSeconds: number;
74
+ maxRebalancePaybackHours: number;
75
+ minSwitchImprovementUsd: number;
76
+ }
77
+ export interface ExitQuote {
78
+ snapshotId: string;
79
+ quotedAt: string;
80
+ expiresAt: string;
81
+ settlementAsset: string;
82
+ netProceedsUsd: number;
83
+ completeExit: boolean;
84
+ source: 'simulated-sequential-exit';
85
+ }
86
+ export interface Opportunity {
87
+ id: string;
88
+ kind: 'rebalance' | 'rotate';
89
+ qualified: boolean;
90
+ sameChain: boolean;
91
+ costUsd: number | null;
92
+ conservativeIncrementalFeesUsdPerDay: number | null;
93
+ horizonHours: number;
94
+ exposureChange: string;
95
+ evidence: string[];
96
+ }
97
+ export interface Assessment {
98
+ schemaVersion: 1;
99
+ snapshotId: string;
100
+ policyVersion: 1;
101
+ assessedAt: string;
102
+ action: 'HOLD' | 'REVIEW' | 'REBALANCE_CANDIDATE' | 'EXIT_CANDIDATE' | 'ROTATE_CANDIDATE' | 'DATA_UNAVAILABLE';
103
+ reasons: string[];
104
+ metrics: {
105
+ principalValueUsd: number | null;
106
+ uncollectedFeesUsd: number | null;
107
+ positionValueUsd: number | null;
108
+ trackingMarkedPnlUsd: number | null;
109
+ trackingNetExitPnlUsd: number | null;
110
+ holdPrincipalValueUsd: number | null;
111
+ inventoryShortfallVsHoldUsd: number | null;
112
+ inventoryShortfallVsHoldPct: number | null;
113
+ ghoBenchmarkPnlUsd: number | null;
114
+ inRange: boolean | null;
115
+ boundaryDistanceFraction: number | null;
116
+ };
117
+ accountingCoverage: 'since-tracking-start' | 'snapshot-only' | 'gap';
118
+ requiresSignature: true;
119
+ alternatives: Array<{
120
+ id: string;
121
+ qualified: boolean;
122
+ reasons: string[];
123
+ paybackHours: number | null;
124
+ improvementUsd: number | null;
125
+ }>;
126
+ }
127
+ export declare const DEFAULT_POLICY: WatchPolicy;
128
+ export interface PositionReader {
129
+ read(ref: PositionRef): Promise<PositionSnapshot>;
130
+ isCanonical?(snapshot: PositionSnapshot): Promise<boolean | null>;
131
+ }
@@ -0,0 +1,6 @@
1
+ export const DEFAULT_POLICY = {
2
+ version: 1, stopLossUsd: 900, takeProfitReviewUsd: 450, trailingDrawdownUsd: null,
3
+ rangeWarningFraction: 0.2, maxSnapshotAgeSeconds: 120, maxQuoteAgeSeconds: 120,
4
+ maxRebalancePaybackHours: 48, minSwitchImprovementUsd: 10,
5
+ };
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,18 @@
1
+ import type { Hex, Pair, PoolKey } from './types.js';
2
+ export declare const Q96: bigint;
3
+ export declare const Q128: bigint;
4
+ export declare const UINT256_MOD: bigint;
5
+ export declare const MIN_TICK = -887272;
6
+ export declare const MAX_TICK = 887272;
7
+ export declare function sqrtPriceAtTick(tick: number): bigint;
8
+ export declare function unpackPositionInfo(info: bigint): {
9
+ lowerTick: number;
10
+ upperTick: number;
11
+ poolIdPrefix: Hex;
12
+ hasSubscriber: boolean;
13
+ };
14
+ export declare function poolId(key: PoolKey): Hex;
15
+ export declare function feesOwed(liquidity: bigint, current: Pair<bigint>, checkpoint: Pair<bigint>): Pair<bigint>;
16
+ export declare function principalAmounts(liquidity: bigint, sqrtPriceX96: bigint, lowerTick: number, upperTick: number): Pair<bigint>;
17
+ /** Human units of currency1 per one currency0. Display marks only, never raw accounting. */
18
+ export declare function humanPriceRatio(sqrtPriceX96: bigint, decimals0: number, decimals1: number): number;