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,140 @@
1
+ /** Guarded LP collection is record v3 in the existing sponsored claim and gas ledger. */
2
+ import { z } from 'zod';
3
+ import { hybridYieldCommitment } from './hybrid-yield-markets.js';
4
+ import { SPONSORED_OPERATION_SCHEMA, SPONSORED_AUTHORITY_SCHEMA, SPONSORED_ACTIVATION_SCHEMA, sponsoredDigest, sponsoredChainTerms, sponsoredActivationSupports } from './execution-sponsored-definition.js';
5
+ import { SPONSORED_CDP_NETWORKS } from './execution-sponsored-transport.js';
6
+ import { LP_USEROP_REVIEW_RECORD_SCHEMA } from './lp-userop-definition.js';
7
+ import { LP_USEROP_ENVELOPE_SCHEMA, LP_USEROP_SUBMIT_EVIDENCE_SCHEMA, assertLpUserOpEnvelope, lpUserOpRecordedCalls } from './lp-userop.js';
8
+ import { LP_USEROP_SETTLEMENT_SCHEMA } from './lp-userop-settlement.js';
9
+ import { commitment as protocolCommitment } from './vendor/lp-v3/lp-v3-contract.js';
10
+ const time = z.number().int().positive().safe();
11
+ export const LP_USEROP_CONTEXT_SCHEMA = z.object({ kind: z.literal('lp-collect-userop'),
12
+ account: SPONSORED_AUTHORITY_SCHEMA.shape.account, chainId: z.literal(8453),
13
+ envelope: LP_USEROP_ENVELOPE_SCHEMA, review: LP_USEROP_REVIEW_RECORD_SCHEMA,
14
+ authority: SPONSORED_AUTHORITY_SCHEMA, activation: SPONSORED_ACTIVATION_SCHEMA,
15
+ reviewedAtMs: time, validUntilMs: time,
16
+ }).strict();
17
+ export const LP_USEROP_OPERATION_SCHEMA = SPONSORED_OPERATION_SCHEMA.extend({ version: z.literal(3),
18
+ context: LP_USEROP_CONTEXT_SCHEMA, submitEvidence: LP_USEROP_SUBMIT_EVIDENCE_SCHEMA.optional(),
19
+ settlement: LP_USEROP_SETTLEMENT_SCHEMA.optional(),
20
+ }).strict();
21
+ export function lpUserOpReviewCommitment(operationId, context, gasReview) {
22
+ if (gasReview)
23
+ return sponsoredDigest({ domain: 'otto-account-gas-review-v1', operationId, context, gasReview });
24
+ return sponsoredDigest({ domain: 'otto-sponsored-lp-collect-review-v1', operationId, context });
25
+ }
26
+ function invalid() { throw new Error('SPONSOR_LP_JOURNAL_INVALID'); }
27
+ export function assertLpUserOpContext(context, fresh = false, nowMs = Date.now()) {
28
+ const envelope = assertLpUserOpEnvelope(context.envelope), terms = envelope.terms;
29
+ const chain = sponsoredChainTerms(context.activation, context.chainId), profile = chain.nativeYieldUserOpProfile;
30
+ if (context.account !== terms.account || context.chainId !== terms.chainId ||
31
+ context.authority.account !== context.account || context.authority.userId !== terms.userId ||
32
+ context.authority.activationDigest !== sponsoredDigest(context.activation) ||
33
+ context.authority.policyRulesDigest !== context.activation.policyRulesDigest ||
34
+ context.reviewedAtMs !== envelope.preparedAtMs || context.validUntilMs !== envelope.validUntilMs ||
35
+ context.validUntilMs > context.activation.expiresAtMs || context.validUntilMs > Date.parse(context.authority.grantExpiresAt) ||
36
+ hybridYieldCommitment(context.review.input) !== hybridYieldCommitment(envelope.input) ||
37
+ hybridYieldCommitment(context.review.terms) !== hybridYieldCommitment(terms) ||
38
+ !sponsoredActivationSupports(context.activation, 'lp-collect-userop') ||
39
+ terms.sponsoredActivationId !== context.activation.id || terms.sponsoredActivationDigest !== sponsoredDigest(context.activation) ||
40
+ terms.projectId !== context.activation.projectId || terms.policyId !== context.activation.policyId ||
41
+ terms.policyRulesDigest !== context.activation.policyRulesDigest ||
42
+ terms.providerEnforcementEvidenceDigest !== context.activation.providerEnforcementEvidenceDigest ||
43
+ context.activation.lpUserOpPolicyRelation?.lpActivationCommitment !== terms.lpActivationCommitment ||
44
+ context.activation.lpUserOpPolicyRelation?.compiledFullPolicyDigest !== terms.policyRulesDigest ||
45
+ !profile || terms.implementation !== profile.implementation || terms.implementationCodeHash !== profile.implementationCodeHash ||
46
+ terms.delegateBatchAbi !== profile.delegateBatchAbi || terms.delegateBatchReviewDigest !== profile.delegateBatchReviewDigest ||
47
+ terms.entryPointVersion !== profile.entryPointVersion || terms.delegate !== chain.delegate || terms.delegateCodeHash !== chain.delegateCodeHash ||
48
+ terms.entryPoint !== chain.entryPoint || terms.entryPointCodeHash !== chain.entryPointCodeHash ||
49
+ terms.paymaster !== chain.paymaster || terms.paymasterCodeHash !== chain.paymasterCodeHash ||
50
+ terms.sponsorshipPolicyId !== chain.sponsorshipPolicyId || terms.maxGasCostWei !== chain.maxGasCostWei ||
51
+ terms.maxUserGasCostWei !== chain.maxUserGasCostWei || terms.maxTotalGasCostWei !== chain.maxTotalGasCostWei)
52
+ invalid();
53
+ if (fresh && (context.activation.mode !== 'enabled' || context.activation.approvedAtMs > nowMs ||
54
+ nowMs < context.reviewedAtMs || nowMs >= context.validUntilMs))
55
+ throw new Error('SPONSOR_REVIEW_EXPIRED');
56
+ }
57
+ export function validateLpUserOpOperation(raw) {
58
+ const op = LP_USEROP_OPERATION_SCHEMA.parse(raw), context = op.context;
59
+ assertLpUserOpContext(context);
60
+ const { envelope } = context, { terms } = envelope;
61
+ if (op.userId !== context.authority.userId || op.reviewCommitment !== lpUserOpReviewCommitment(op.operationId, context, op.gasReview) ||
62
+ (op.state === 'review') !== !op.reviewConsumed || op.updatedAtMs < op.createdAtMs ||
63
+ context.reviewedAtMs !== op.createdAtMs || context.validUntilMs <= context.reviewedAtMs)
64
+ invalid();
65
+ if (op.request) {
66
+ const expectedBody = JSON.stringify({ network: SPONSORED_CDP_NETWORKS[context.chainId],
67
+ calls: lpUserOpRecordedCalls(envelope), useCdpPaymaster: false,
68
+ ...(op.gasReview?.payer === 'account' ? {} : { paymasterAlias: `pimlico:${context.chainId}`,
69
+ paymasterContext: { sponsorshipPolicyId: terms.sponsorshipPolicyId } }) });
70
+ if (op.request.userId !== op.userId || op.request.account !== context.account || op.request.chainId !== context.chainId ||
71
+ op.request.idempotencyKey !== op.operationId.slice(3) ||
72
+ op.request.path !== `/platform/v2/embedded-wallet-api/end-users/${op.userId}/evm/smart-accounts/${context.account.toLowerCase()}/send` ||
73
+ op.request.body !== expectedBody)
74
+ invalid();
75
+ }
76
+ if (op.handoffAttempted && !op.request)
77
+ invalid();
78
+ if (op.state === 'review' && (op.request || op.handoffAttempted || op.submitEvidence || op.userOpHash || op.transactionHash))
79
+ invalid();
80
+ if ((op.userOpHash || op.transactionHash || op.receipt) && !op.handoffAttempted)
81
+ invalid();
82
+ if (op.userOpHash && !op.submitEvidence)
83
+ invalid();
84
+ if (op.transactionHash && !op.userOpHash)
85
+ invalid();
86
+ if (op.submitEvidence) {
87
+ const { baseline, check, verifiedAtMs } = op.submitEvidence;
88
+ const { checkCommitment, ...checkCore } = check;
89
+ if (checkCommitment !== protocolCommitment(checkCore) || verifiedAtMs > op.updatedAtMs ||
90
+ verifiedAtMs < envelope.preparedAtMs || verifiedAtMs >= context.validUntilMs ||
91
+ check.checkedAt !== Math.floor(verifiedAtMs / 1000) || check.planCommitment !== envelope.plan.planCommitment ||
92
+ check.intentCommitment !== terms.intentCommitment || check.policyCommitment !== envelope.plan.policyCommitment ||
93
+ check.baselineCommitment !== protocolCommitment(baseline) || baseline.account !== context.account.toLowerCase() ||
94
+ BigInt(baseline.blockNumber) < BigInt(envelope.baseline.blockNumber) || baseline.position.approved !== terms.initialNftApproval)
95
+ invalid();
96
+ }
97
+ if (op.receipt && (op.receipt.userOpHash.toLowerCase() !== op.userOpHash?.toLowerCase() ||
98
+ op.receipt.transactionHash.toLowerCase() !== op.transactionHash?.toLowerCase() || op.receipt.chainId !== context.chainId ||
99
+ op.receipt.account !== context.account || op.receipt.paymaster !== (op.gasReview?.payer === 'account' ? '0x0000000000000000000000000000000000000000' : terms.paymaster) ||
100
+ (op.gasReview?.payer !== 'account' && BigInt(op.receipt.actualGasCostWei) > BigInt(terms.maxGasCostWei))))
101
+ invalid();
102
+ if (op.gasCapBreach && (op.gasReview?.payer === 'account' || !op.handoffAttempted || op.state !== 'submitted' || op.receipt || op.settlement ||
103
+ op.failureCode !== 'SPONSOR_GAS_CAP_EXCEEDED' || op.gasCapBreach.userOpHash.toLowerCase() !== op.userOpHash?.toLowerCase() ||
104
+ op.gasCapBreach.transactionHash.toLowerCase() !== op.transactionHash?.toLowerCase() ||
105
+ op.gasCapBreach.chainId !== context.chainId || op.gasCapBreach.account !== context.account ||
106
+ op.gasCapBreach.paymaster !== terms.paymaster || BigInt(op.gasCapBreach.actualGasCostWei) <= BigInt(terms.maxGasCostWei)))
107
+ invalid();
108
+ const result = op.settlement;
109
+ if (result) {
110
+ if (!result.releaseClaim)
111
+ return invalid();
112
+ const receipt = op.receipt;
113
+ if (!receipt || !op.submitEvidence || result.userOpHash !== op.userOpHash || result.transactionHash !== op.transactionHash ||
114
+ result.blockHash !== receipt.blockHash || result.blockNumber !== receipt.blockNumber || result.userOpNonce !== receipt.nonce ||
115
+ result.owner !== context.account || result.chainId !== context.chainId || result.pool !== envelope.input.pool ||
116
+ result.tokenId !== envelope.input.tokenId || result.planCommitment !== envelope.plan.planCommitment ||
117
+ result.baselineCommitment !== op.submitEvidence.check.baselineCommitment ||
118
+ result.actualGasCostWei !== receipt.actualGasCostWei || result.actualGasUsed !== receipt.actualGasUsed ||
119
+ result.paymaster !== receipt.paymaster || result.finality.policyCommitment !== protocolCommitment(envelope.finalityPolicy) ||
120
+ result.finality.observedAtMs < op.submitEvidence.verifiedAtMs ||
121
+ BigInt(result.finality.finalizedBlockNumber) < BigInt(result.blockNumber) ||
122
+ BigInt(result.finality.confirmations) !== BigInt(result.finality.finalizedBlockNumber) - BigInt(result.blockNumber) + 1n ||
123
+ BigInt(result.finality.confirmations) < BigInt(envelope.finalityPolicy.minFinalizedConfirmations))
124
+ invalid();
125
+ if (result.status === 'completed') {
126
+ if (op.state !== 'completed' || receipt.status !== 'success' || result.collectedRaw.some((amount, i) => BigInt(amount) > BigInt(envelope.input.amountMax[i]) || BigInt(amount) < BigInt(envelope.input.amountMin[i])))
127
+ invalid();
128
+ }
129
+ else if (op.state !== 'failed' || receipt.status !== 'reverted' || result.collectedRaw.some(amount => amount !== '0'))
130
+ invalid();
131
+ }
132
+ if (op.state === 'completed' && result?.status !== 'completed')
133
+ invalid();
134
+ if (op.state === 'failed' && op.handoffAttempted && result?.status !== 'reverted')
135
+ invalid();
136
+ if (op.state === 'submitted' && !op.userOpHash)
137
+ invalid();
138
+ return op;
139
+ }
140
+ //# sourceMappingURL=lp-userop-operation.js.map
@@ -0,0 +1,14 @@
1
+ /** Header authorization precedes every input parse and optional LP runtime access. */
2
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
3
+ import type { ExecutionToolRuntime } from './execution-tools.js';
4
+ import { type LpUserOpAvailabilityResult } from './lp-userop-mcp-definition.js';
5
+ export interface LpUserOpBinding {
6
+ availability(): Promise<LpUserOpAvailabilityResult>;
7
+ reviewGas(input: unknown): Promise<unknown>;
8
+ prepare(input: unknown): Promise<unknown>;
9
+ submit(input: unknown): Promise<unknown>;
10
+ read(input: unknown): Promise<unknown>;
11
+ reconcile(input: unknown): Promise<unknown>;
12
+ }
13
+ export declare function unavailableLpUserOpBinding(reason?: NonNullable<LpUserOpAvailabilityResult['reason']>): LpUserOpBinding;
14
+ export declare function callLpUserOp(runtime: ExecutionToolRuntime, raw: unknown, headers: Readonly<Record<string, string | string[] | undefined>> | undefined): Promise<CallToolResult>;
@@ -0,0 +1,70 @@
1
+ import { accountGasFailure } from './execution-account-gas-view.js';
2
+ import { LpUserOpPreHandoffRefusal } from './lp-userop-account.js';
3
+ import { ZodError } from 'zod';
4
+ import { assertDelegationCaller, callerFromHeaders } from './execution-delegation.js';
5
+ import { ExecutionRefusal, isExecutionRefusal } from './execution-errors.js';
6
+ import { SponsoredAccountRefusal } from './execution-sponsored-runtime.js';
7
+ import { lpUserOpAvailability } from './lp-userop-index.js';
8
+ import { LP_USEROP_ACTION_INPUT, LP_USEROP_TOOL_RESULT, LP_USEROP_AVAILABILITY_RESULT } from './lp-userop-mcp-definition.js';
9
+ export function unavailableLpUserOpBinding(reason = 'SPONSOR_ACTIVATION_UNCONFIGURED') {
10
+ const refuse = async () => { throw new SponsoredAccountRefusal(reason); };
11
+ return Object.freeze({ availability: async () => LP_USEROP_AVAILABILITY_RESULT.parse({ ...lpUserOpAvailability(),
12
+ executionEnabled: false, recoveryAvailable: false, reason }),
13
+ reviewGas: refuse, prepare: refuse, submit: refuse, read: refuse, reconcile: refuse });
14
+ }
15
+ function success(raw) {
16
+ const output = LP_USEROP_TOOL_RESULT.parse(raw);
17
+ return { content: [{ type: 'text', text: JSON.stringify(output) }], structuredContent: output };
18
+ }
19
+ // Factory refusals occur before the service can start this invocation. Arbitrary errors remain unknown.
20
+ const BEFORE_HANDOFF_REFUSALS = new Set(['SPONSOR_ACTIVATION_UNCONFIGURED', 'SPONSOR_ACTIVATION_UNAVAILABLE',
21
+ 'SPONSOR_CAPABILITY_UNAVAILABLE', 'SPONSOR_RECOVERY_ONLY', 'SPONSOR_RUNTIME_UNAVAILABLE',
22
+ 'SPONSOR_JOURNAL_UNAVAILABLE', 'SPONSOR_CAP_UNAVAILABLE', 'SPONSOR_CHAIN_UNAVAILABLE']);
23
+ export async function callLpUserOp(runtime, raw, headers) {
24
+ let submitId, invoked = false;
25
+ try {
26
+ if (!runtime.delegation)
27
+ throw new ExecutionRefusal('DELEGATION_UNAUTHORIZED', 'Protected account caller is not authorized');
28
+ assertDelegationCaller(runtime.delegation, callerFromHeaders(headers));
29
+ const input = LP_USEROP_ACTION_INPUT.parse(raw), binding = runtime.lpUserOp ?? unavailableLpUserOpBinding();
30
+ if (input.action === 'availability')
31
+ return success(LP_USEROP_AVAILABILITY_RESULT.parse(await binding.availability()));
32
+ const { action, ...body } = input;
33
+ if (action === 'submit')
34
+ submitId = input.operationId;
35
+ invoked = true;
36
+ const result = LP_USEROP_TOOL_RESULT.parse(await binding[action](body));
37
+ if (!('state' in result) || !('operationId' in result))
38
+ throw new Error('mismatched operation');
39
+ if (action === 'prepare') {
40
+ if (result.state !== 'review' || result.account.toLowerCase() !== input.input.account ||
41
+ result.chainId !== input.input.chainId || result.pool !== input.input.pool || result.tokenId !== input.input.tokenId ||
42
+ JSON.stringify(result.collection.maximum) !== JSON.stringify(input.input.amountMax) ||
43
+ JSON.stringify(result.collection.minimum) !== JSON.stringify(input.input.amountMin))
44
+ throw new Error('mismatched preparation');
45
+ }
46
+ else if (result.operationId !== input.operationId)
47
+ throw new Error('mismatched operation');
48
+ if (input.action === 'reviewGas' && (result.state !== 'review' || result.reviewConsumed || result.gas.reviewRequired !== true || !result.gas.paymentReview ||
49
+ result.reviewCommitment === input.reviewCommitment || (input.preference !== 'auto' && result.gas.payer !== input.preference)))
50
+ throw new Error('mismatched gas review');
51
+ if (action === 'submit' && (!result.reviewConsumed || result.envelopeCommitment !== input.envelopeCommitment ||
52
+ result.reviewCommitment !== input.reviewCommitment))
53
+ throw new Error('mismatched consumed review');
54
+ return success(result);
55
+ }
56
+ catch (error) {
57
+ const knownRefusal = error instanceof LpUserOpPreHandoffRefusal ||
58
+ (error instanceof SponsoredAccountRefusal && BEFORE_HANDOFF_REFUSALS.has(error.code));
59
+ if (submitId && invoked && !knownRefusal)
60
+ return success({ schemaVersion: '1', kind: 'lp-collect-userop', status: 'outcome-unknown', operationId: submitId,
61
+ requiresReconciliation: true, replacementPermitted: false,
62
+ attention: 'The outcome of the original submission is unknown. Read or reconcile this operation; do not submit a replacement.' });
63
+ const denied = isExecutionRefusal(error) && error.code === 'DELEGATION_UNAUTHORIZED' && !invoked;
64
+ const code = denied ? 'DELEGATION_UNAUTHORIZED' : error instanceof ZodError && !invoked
65
+ ? 'LP_USEROP_REQUEST_INVALID' : accountGasFailure(error) ?? 'LP_USEROP_REQUEST_REFUSED';
66
+ return { isError: true, content: [{ type: 'text', text: JSON.stringify({ status: 'refused', code,
67
+ message: denied ? 'The protected account caller is not authorized.' : 'The LP collection action is unavailable or refused. Read current availability and the original operation before continuing.' }) }] };
68
+ }
69
+ }
70
+ //# sourceMappingURL=lp-userop-registration.js.map
@@ -0,0 +1,89 @@
1
+ /** Canonical EntryPoint transaction and isolated LP accounting proof. Never sends or retries. */
2
+ import { type Hex } from 'viem';
3
+ import { z } from 'zod';
4
+ import { type LpUserOpEnvelope, type LpUserOpRuntime, type LpUserOpSubmitEvidence } from './lp-userop.js';
5
+ export declare const LP_USEROP_SETTLEMENT_SCHEMA: z.ZodUnion<readonly [z.ZodObject<{
6
+ status: z.ZodEnum<{
7
+ unknown: "unknown";
8
+ held: "held";
9
+ }>;
10
+ reason: z.ZodString;
11
+ userOpHash: z.ZodString;
12
+ transactionHash: z.ZodString;
13
+ releaseClaim: z.ZodLiteral<false>;
14
+ retrySafe: z.ZodLiteral<false>;
15
+ }, z.core.$strict>, z.ZodObject<{
16
+ userOpHash: z.ZodString;
17
+ transactionHash: z.ZodString;
18
+ blockHash: z.ZodString;
19
+ blockNumber: z.ZodString;
20
+ userOpNonce: z.ZodString;
21
+ owner: z.ZodString;
22
+ chainId: z.ZodLiteral<8453>;
23
+ pool: z.ZodString;
24
+ tokenId: z.ZodString;
25
+ planCommitment: z.ZodString;
26
+ baselineCommitment: z.ZodString;
27
+ accountingCommitment: z.ZodString;
28
+ collectedRaw: z.ZodTuple<[z.ZodString, z.ZodString], null>;
29
+ liquidityDelta: z.ZodLiteral<"0">;
30
+ ownerBalancesAtBlock: z.ZodTuple<[z.ZodString, z.ZodString], null>;
31
+ nftTokenApprovalCleared: z.ZodLiteral<true>;
32
+ erc20AllowancesCleared: z.ZodLiteral<true>;
33
+ actualGasCostWei: z.ZodString;
34
+ actualGasUsed: z.ZodString;
35
+ paymaster: z.ZodString;
36
+ profitClassification: z.ZodLiteral<"UNKNOWN">;
37
+ distributableProfitRaw: z.ZodNull;
38
+ releaseClaim: z.ZodLiteral<true>;
39
+ retrySafe: z.ZodLiteral<false>;
40
+ finality: z.ZodObject<{
41
+ policyCommitment: z.ZodString;
42
+ observedAtMs: z.ZodNumber;
43
+ finalizedBlockNumber: z.ZodString;
44
+ finalizedBlockHash: z.ZodString;
45
+ confirmations: z.ZodString;
46
+ }, z.core.$strict>;
47
+ status: z.ZodLiteral<"completed">;
48
+ protocolActionVerified: z.ZodLiteral<true>;
49
+ }, z.core.$strict>, z.ZodObject<{
50
+ userOpHash: z.ZodString;
51
+ transactionHash: z.ZodString;
52
+ blockHash: z.ZodString;
53
+ blockNumber: z.ZodString;
54
+ userOpNonce: z.ZodString;
55
+ owner: z.ZodString;
56
+ chainId: z.ZodLiteral<8453>;
57
+ pool: z.ZodString;
58
+ tokenId: z.ZodString;
59
+ planCommitment: z.ZodString;
60
+ baselineCommitment: z.ZodString;
61
+ accountingCommitment: z.ZodString;
62
+ collectedRaw: z.ZodTuple<[z.ZodString, z.ZodString], null>;
63
+ liquidityDelta: z.ZodLiteral<"0">;
64
+ ownerBalancesAtBlock: z.ZodTuple<[z.ZodString, z.ZodString], null>;
65
+ nftTokenApprovalCleared: z.ZodLiteral<true>;
66
+ erc20AllowancesCleared: z.ZodLiteral<true>;
67
+ actualGasCostWei: z.ZodString;
68
+ actualGasUsed: z.ZodString;
69
+ paymaster: z.ZodString;
70
+ profitClassification: z.ZodLiteral<"UNKNOWN">;
71
+ distributableProfitRaw: z.ZodNull;
72
+ releaseClaim: z.ZodLiteral<true>;
73
+ retrySafe: z.ZodLiteral<false>;
74
+ finality: z.ZodObject<{
75
+ policyCommitment: z.ZodString;
76
+ observedAtMs: z.ZodNumber;
77
+ finalizedBlockNumber: z.ZodString;
78
+ finalizedBlockHash: z.ZodString;
79
+ confirmations: z.ZodString;
80
+ }, z.core.$strict>;
81
+ status: z.ZodLiteral<"reverted">;
82
+ protocolActionVerified: z.ZodLiteral<false>;
83
+ }, z.core.$strict>]>;
84
+ export type LpUserOpSettlement = z.infer<typeof LP_USEROP_SETTLEMENT_SCHEMA>;
85
+ export interface LpUserOpReceiptBinding {
86
+ readonly userOpHash: Hex;
87
+ readonly transactionHash: Hex;
88
+ }
89
+ export declare function readLpUserOpSettlement(rawEnvelope: LpUserOpEnvelope, binding: LpUserOpReceiptBinding, runtime: LpUserOpRuntime, rawSubmitEvidence: LpUserOpSubmitEvidence, payer?: 'sponsor' | 'account'): Promise<LpUserOpSettlement>;
@@ -0,0 +1,184 @@
1
+ /** Canonical EntryPoint transaction and isolated LP accounting proof. Never sends or retries. */
2
+ import { decodeEventLog, decodeFunctionData, encodeFunctionData, keccak256, parseAbi, recoverTransactionAddress, serializeTransaction } from 'viem';
3
+ import { getUserOperationHash } from 'viem/account-abstraction';
4
+ import { z } from 'zod';
5
+ import { freezeHybridValue } from './hybrid-yield-markets.js';
6
+ import { readConfirmedSponsoredReceipt, SponsoredReceiptUnconfirmedError } from './execution-sponsored-receipt.js';
7
+ import { sponsoredOperationLogs } from './execution-sponsored-settlement.js';
8
+ import { commitment as protocolCommitment } from './vendor/lp-v3/lp-v3-contract.js';
9
+ import { lpV3CollectProtocolEvidenceSchema } from './vendor/lp-v3/lp-v3-collect-protocol-contract.js';
10
+ import { assertLpUserOpEnvelope, assertLpUserOpAccountState, boundedLpUserOpRead, lpUserOpBatchData, lpUserOpNow, lpUserOpProtocol, lpUserOpProtocolClient, requireLpUserOp, LP_USEROP_SUBMIT_EVIDENCE_SCHEMA, LpUserOpError } from './lp-userop.js';
11
+ const EP_ABI = parseAbi([
12
+ 'function handleOps((address sender,uint256 nonce,bytes initCode,bytes callData,uint256 callGasLimit,uint256 verificationGasLimit,uint256 preVerificationGas,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,bytes paymasterAndData,bytes signature)[] ops,address beneficiary)',
13
+ 'event UserOperationEvent(bytes32 indexed userOpHash,address indexed sender,address indexed paymaster,uint256 nonce,bool success,uint256 actualGasCost,uint256 actualGasUsed)',
14
+ 'event BeforeExecution()',
15
+ ]);
16
+ const hash = z.string().regex(/^0x[0-9a-fA-F]{64}$/), uint = z.string().regex(/^(0|[1-9][0-9]*)$/);
17
+ const held = z.object({ status: z.enum(['held', 'unknown']), reason: z.string(), userOpHash: hash, transactionHash: hash,
18
+ releaseClaim: z.literal(false), retrySafe: z.literal(false) }).strict();
19
+ const accounted = z.object({
20
+ userOpHash: hash, transactionHash: hash, blockHash: hash, blockNumber: uint, userOpNonce: uint,
21
+ owner: z.string(), chainId: z.literal(8453), pool: z.string(), tokenId: uint, planCommitment: hash,
22
+ baselineCommitment: hash, accountingCommitment: hash, collectedRaw: z.tuple([uint, uint]), liquidityDelta: z.literal('0'),
23
+ ownerBalancesAtBlock: z.tuple([uint, uint]), nftTokenApprovalCleared: z.literal(true), erc20AllowancesCleared: z.literal(true),
24
+ actualGasCostWei: uint, actualGasUsed: uint, paymaster: z.string(),
25
+ profitClassification: z.literal('UNKNOWN'), distributableProfitRaw: z.null(),
26
+ releaseClaim: z.literal(true), retrySafe: z.literal(false),
27
+ finality: z.object({ policyCommitment: hash, observedAtMs: z.number().int().positive().safe(),
28
+ finalizedBlockNumber: uint, finalizedBlockHash: hash, confirmations: uint }).strict(),
29
+ });
30
+ export const LP_USEROP_SETTLEMENT_SCHEMA = z.union([held,
31
+ accounted.extend({ status: z.literal('completed'), protocolActionVerified: z.literal(true) }).strict(),
32
+ accounted.extend({ status: z.literal('reverted'), protocolActionVerified: z.literal(false) }).strict(),
33
+ ]);
34
+ const same = (a, b) => typeof a === 'string' && a.toLowerCase() === b.toLowerCase();
35
+ async function proveTransaction(runtime, envelope, binding, receipt, nonce, payer) {
36
+ const tx = await runtime.client.getTransaction({ hash: binding.transactionHash }), terms = envelope.terms;
37
+ requireLpUserOp(tx.type === 'eip1559' && tx.chainId === terms.chainId && same(tx.hash, binding.transactionHash) &&
38
+ same(tx.to, terms.entryPoint) && tx.value === 0n && same(tx.blockHash, receipt.blockHash) && tx.blockNumber === receipt.blockNumber &&
39
+ tx.transactionIndex === receipt.transactionIndex && same(tx.from, receipt.from) && same(receipt.to, terms.entryPoint) &&
40
+ Number.isSafeInteger(tx.nonce) && tx.nonce >= 0 && tx.gas > 0n && tx.maxFeePerGas > 0n &&
41
+ tx.maxPriorityFeePerGas >= 0n && tx.maxPriorityFeePerGas <= tx.maxFeePerGas &&
42
+ (tx.yParity === 0 || tx.yParity === 1) && BigInt(tx.r) > 0n &&
43
+ BigInt(tx.r) < 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n &&
44
+ BigInt(tx.s) > 0n && BigInt(tx.s) <= 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0n, 'LP_USEROP_TRANSACTION_BINDING');
45
+ const serialized = serializeTransaction({ type: 'eip1559', chainId: tx.chainId, nonce: tx.nonce, gas: tx.gas,
46
+ maxFeePerGas: tx.maxFeePerGas, maxPriorityFeePerGas: tx.maxPriorityFeePerGas, to: tx.to, value: tx.value,
47
+ data: tx.input, accessList: tx.accessList }, { r: tx.r, s: tx.s, yParity: tx.yParity });
48
+ requireLpUserOp(same(keccak256(serialized), binding.transactionHash) &&
49
+ same(await recoverTransactionAddress({ serializedTransaction: serialized }), tx.from), 'LP_USEROP_TRANSACTION_SIGNATURE');
50
+ const decoded = decodeFunctionData({ abi: EP_ABI, data: tx.input });
51
+ requireLpUserOp(decoded.functionName === 'handleOps' && decoded.args[0].length > 0 && decoded.args[0].length <= 256 &&
52
+ encodeFunctionData({ abi: EP_ABI, functionName: 'handleOps', args: decoded.args }) === tx.input, 'LP_USEROP_UNSUPPORTED_BUNDLE');
53
+ const operations = decoded.args[0].map(operation => ({ operation, hash: getUserOperationHash({ chainId: terms.chainId,
54
+ entryPointAddress: terms.entryPoint, entryPointVersion: '0.6', userOperation: operation }) }));
55
+ const matching = operations.filter(operation => same(operation.hash, binding.userOpHash));
56
+ requireLpUserOp(matching.length === 1 && operations.filter(({ operation }) => same(operation.sender, terms.account)).length === 1, 'LP_USEROP_HASH');
57
+ const operation = matching[0].operation;
58
+ requireLpUserOp(same(operation.sender, terms.account) && operation.nonce.toString() === nonce &&
59
+ operation.initCode === '0x' && same(operation.callData, lpUserOpBatchData(envelope)) &&
60
+ (payer === 'account' ? operation.paymasterAndData === '0x' :
61
+ operation.paymasterAndData.length >= 42 && same(operation.paymasterAndData.slice(0, 42), terms.paymaster)) &&
62
+ operation.callGasLimit > 0n && operation.verificationGasLimit > 0n && operation.preVerificationGas > 0n &&
63
+ operation.maxFeePerGas > 0n && operation.maxPriorityFeePerGas <= operation.maxFeePerGas, 'LP_USEROP_CALLDATA');
64
+ const events = [];
65
+ let beforeExecution = -1;
66
+ for (const log of receipt.logs) {
67
+ if (!same(log.address, terms.entryPoint))
68
+ continue;
69
+ let event;
70
+ try {
71
+ event = decodeEventLog({ abi: EP_ABI, data: log.data, topics: log.topics, strict: true });
72
+ }
73
+ catch {
74
+ continue;
75
+ }
76
+ if (event.eventName === 'BeforeExecution') {
77
+ requireLpUserOp(beforeExecution === -1 && events.length === 0, 'LP_USEROP_BUNDLE_BOUNDARY');
78
+ beforeExecution = log.logIndex;
79
+ }
80
+ else if (event.eventName === 'UserOperationEvent') {
81
+ requireLpUserOp(beforeExecution >= 0, 'LP_USEROP_BUNDLE_BOUNDARY');
82
+ events.push({ hash: event.args.userOpHash, sender: event.args.sender, nonce: event.args.nonce, index: log.logIndex });
83
+ }
84
+ }
85
+ requireLpUserOp(events.length === operations.length && events.every((event, i) => same(event.hash, operations[i].hash) &&
86
+ same(event.sender, operations[i].operation.sender) && event.nonce === operations[i].operation.nonce), 'LP_USEROP_BUNDLE_EVENTS');
87
+ const eventIndex = events.findIndex(event => same(event.hash, binding.userOpHash));
88
+ requireLpUserOp(eventIndex >= 0, 'LP_USEROP_BUNDLE_EVENTS');
89
+ return { windowStartLogIndex: eventIndex === 0 ? beforeExecution : events[eventIndex - 1].index,
90
+ userOpEventLogIndex: events[eventIndex].index };
91
+ }
92
+ export async function readLpUserOpSettlement(rawEnvelope, binding, runtime, rawSubmitEvidence, payer = 'sponsor') {
93
+ const retain = (reason, status = 'held') => ({ status, reason, ...binding, releaseClaim: false, retrySafe: false });
94
+ try {
95
+ return await boundedLpUserOpRead(runtime, async () => {
96
+ const envelope = assertLpUserOpEnvelope(rawEnvelope), submit = LP_USEROP_SUBMIT_EVIDENCE_SCHEMA.parse(rawSubmitEvidence);
97
+ const { plan, input, terms, finalityPolicy: policy } = envelope, protocol = lpUserOpProtocol(runtime, envelope);
98
+ requireLpUserOp(submit.verifiedAtMs >= envelope.preparedAtMs && submit.verifiedAtMs < envelope.validUntilMs &&
99
+ submit.check.checkedAt === Math.floor(submit.verifiedAtMs / 1000), 'LP_USEROP_SUBMIT_BASELINE');
100
+ const checked = protocol.validatePrepared(plan, input, submit.baseline, { now: () => submit.check.checkedAt });
101
+ requireLpUserOp(protocolCommitment(checked) === protocolCommitment(submit.check), 'LP_USEROP_SUBMIT_CHECK');
102
+ // Seal the finalized boundary before reading either transaction or historical account state.
103
+ const [finalized, latest] = await Promise.all([runtime.client.getBlock({ blockTag: 'finalized' }), runtime.client.getBlock({ blockTag: 'latest' })]);
104
+ const observedAtMs = lpUserOpNow(runtime), now = Math.floor(observedAtMs / 1000);
105
+ requireLpUserOp(finalized.number !== null && finalized.hash && latest.number !== null && latest.hash &&
106
+ finalized.number <= latest.number && finalized.timestamp <= latest.timestamp &&
107
+ Number(latest.timestamp) <= now && now - Number(latest.timestamp) <= policy.maxHeadAgeSeconds &&
108
+ now - Number(finalized.timestamp) <= policy.maxFinalizedLagSeconds, 'LP_USEROP_FINALITY_STALE');
109
+ const confirmed = await readConfirmedSponsoredReceipt({ ...binding, chainId: terms.chainId, account: terms.account,
110
+ payer, entryPoint: terms.entryPoint, paymaster: payer === 'account' ? '0x0000000000000000000000000000000000000000' : terms.paymaster, maxGasCostWei: BigInt(terms.maxGasCostWei) }, runtime.client);
111
+ const receipt = await runtime.client.getTransactionReceipt({ hash: binding.transactionHash });
112
+ requireLpUserOp(receipt.transactionHash === confirmed.transactionHash && receipt.blockHash === confirmed.blockHash &&
113
+ receipt.blockNumber.toString() === confirmed.blockNumber && receipt.type === 'eip1559' &&
114
+ Number.isSafeInteger(receipt.transactionIndex) && receipt.transactionIndex >= 0 &&
115
+ receipt.gasUsed > 0n && receipt.effectiveGasPrice > 0n && receipt.cumulativeGasUsed >= receipt.gasUsed &&
116
+ receipt.logs.length > 0 && receipt.logs.length <= 4096 && receipt.logs.every((log, i) => !log.removed &&
117
+ log.transactionHash === receipt.transactionHash && log.transactionIndex === receipt.transactionIndex && log.blockHash === receipt.blockHash &&
118
+ log.blockNumber === receipt.blockNumber && Number.isSafeInteger(log.logIndex) && log.logIndex >= 0 &&
119
+ (i === 0 || log.logIndex === receipt.logs[i - 1].logIndex + 1)), 'LP_USEROP_RECEIPT_BINDING');
120
+ const confirmations = finalized.number - receipt.blockNumber + 1n;
121
+ requireLpUserOp(confirmations >= BigInt(policy.minFinalizedConfirmations), 'LP_USEROP_NOT_FINALIZED');
122
+ const block = await runtime.client.getBlock({ blockNumber: receipt.blockNumber });
123
+ requireLpUserOp(block.number === receipt.blockNumber && block.hash === receipt.blockHash &&
124
+ receipt.blockNumber > BigInt(submit.baseline.blockNumber) && block.timestamp <= finalized.timestamp &&
125
+ Number(block.timestamp) > submit.baseline.blockTimestamp &&
126
+ (confirmed.status === 'reverted' || Number(block.timestamp) <= input.deadline) && same(typeof block.transactions[receipt.transactionIndex] === 'string'
127
+ ? block.transactions[receipt.transactionIndex] : undefined, binding.transactionHash), 'LP_USEROP_BLOCK_BINDING');
128
+ const bounds = await proveTransaction(runtime, envelope, binding, receipt, confirmed.nonce, payer);
129
+ const historical = await protocol.collectProtocolEvidence(input, { client: lpUserOpProtocolClient(runtime.client),
130
+ nowSeconds: () => Math.floor(lpUserOpNow(runtime) / 1000), maxBlockAgeSeconds: policy.maxHeadAgeSeconds,
131
+ maxReadDurationSeconds: policy.maxReadDurationSeconds,
132
+ historicalAnchor: { number: submit.baseline.blockNumber, hash: submit.baseline.blockHash, timestamp: submit.baseline.blockTimestamp } });
133
+ // The new historical read has a CURRENT observation time. All chain fields must match the original
134
+ // submission baseline exactly; the persisted check continues to bind its original observation time.
135
+ const { observedAt: _newReadTime, ...historicalState } = historical;
136
+ const { observedAt: _originalReadTime, ...originalState } = submit.baseline;
137
+ requireLpUserOp(protocolCommitment(historicalState) === protocolCommitment(originalState), 'LP_USEROP_BASELINE_CHANGED');
138
+ await assertLpUserOpAccountState(runtime, terms, BigInt(submit.baseline.blockNumber), submit.baseline.blockHash);
139
+ await assertLpUserOpAccountState(runtime, terms, receipt.blockNumber, receipt.blockHash);
140
+ const post = await protocol.collectProtocolEvidence(input, { client: lpUserOpProtocolClient(runtime.client), nowSeconds: () => Math.floor(lpUserOpNow(runtime) / 1000),
141
+ maxBlockAgeSeconds: policy.maxHeadAgeSeconds, maxReadDurationSeconds: policy.maxReadDurationSeconds,
142
+ historicalAnchor: { number: receipt.blockNumber.toString(), hash: receipt.blockHash, timestamp: Number(block.timestamp) } });
143
+ const logs = sponsoredOperationLogs(receipt, terms.entryPoint, binding.userOpHash);
144
+ const evidence = lpV3CollectProtocolEvidenceSchema.parse({ schemaVersion: 3, planCommitment: plan.planCommitment,
145
+ status: confirmed.status, binding: { ...binding, ...bounds, chainId: terms.chainId, account: terms.account.toLowerCase(),
146
+ entryPoint: terms.entryPoint.toLowerCase(), blockNumber: receipt.blockNumber.toString(), blockHash: receipt.blockHash,
147
+ blockTimestamp: Number(block.timestamp), transactionIndex: receipt.transactionIndex, userOpNonce: confirmed.nonce },
148
+ logs: logs.map(log => ({ address: log.address.toLowerCase(), topics: log.topics, data: log.data, logIndex: log.logIndex,
149
+ transactionHash: log.transactionHash, transactionIndex: log.transactionIndex, blockHash: log.blockHash,
150
+ blockNumber: log.blockNumber.toString(), removed: false })), post });
151
+ const accounting = protocol.reconcileCollectProtocol({ plan, independentIntent: input, baseline: submit.baseline, check: submit.check, evidence }, { now: () => Math.floor(lpUserOpNow(runtime) / 1000) });
152
+ if (accounting.status !== 'PROTOCOL_ACCOUNTED')
153
+ return retain(`LP_USEROP_PROTOCOL_${accounting.reason}`);
154
+ requireLpUserOp(accounting.outcome === (confirmed.status === 'success' ? 'collected' : 'reverted') &&
155
+ same(accounting.userOpHash, binding.userOpHash) && same(accounting.transactionHash, binding.transactionHash), 'LP_USEROP_ACCOUNTING_BINDING');
156
+ const [finalizedAnchor, receiptAnchor, baselineAnchor, latestAnchor, chainId] = await Promise.all([
157
+ runtime.client.getBlock({ blockNumber: finalized.number }), runtime.client.getBlock({ blockNumber: receipt.blockNumber }),
158
+ runtime.client.getBlock({ blockNumber: BigInt(submit.baseline.blockNumber) }), runtime.client.getBlock({ blockNumber: latest.number }),
159
+ runtime.client.getChainId(),
160
+ ]);
161
+ requireLpUserOp(chainId === terms.chainId && finalizedAnchor.hash === finalized.hash && receiptAnchor.hash === receipt.blockHash &&
162
+ baselineAnchor.hash === submit.baseline.blockHash && latestAnchor.hash === latest.hash &&
163
+ Math.floor(lpUserOpNow(runtime) / 1000) - Number(latest.timestamp) <= policy.maxHeadAgeSeconds, 'LP_USEROP_REORG');
164
+ return freezeHybridValue(LP_USEROP_SETTLEMENT_SCHEMA.parse({
165
+ ...binding, blockHash: receipt.blockHash, blockNumber: receipt.blockNumber.toString(), userOpNonce: confirmed.nonce,
166
+ owner: terms.account, chainId: terms.chainId, pool: input.pool, tokenId: input.tokenId, planCommitment: plan.planCommitment,
167
+ baselineCommitment: accounting.baselineCommitment, accountingCommitment: accounting.accountingCommitment,
168
+ collectedRaw: accounting.collectedRaw, liquidityDelta: '0', ownerBalancesAtBlock: accounting.ownerBalancesAtBlock,
169
+ nftTokenApprovalCleared: true, erc20AllowancesCleared: true, actualGasCostWei: confirmed.actualGasCostWei,
170
+ actualGasUsed: confirmed.actualGasUsed, paymaster: confirmed.paymaster, profitClassification: 'UNKNOWN', distributableProfitRaw: null,
171
+ releaseClaim: true, retrySafe: false, finality: { policyCommitment: protocolCommitment(policy), observedAtMs,
172
+ finalizedBlockNumber: finalized.number.toString(), finalizedBlockHash: finalized.hash, confirmations: confirmations.toString() },
173
+ status: confirmed.status === 'success' ? 'completed' : 'reverted', protocolActionVerified: confirmed.status === 'success',
174
+ }));
175
+ });
176
+ }
177
+ catch (error) {
178
+ // The shared sponsor circuit needs the exact proven breach, including after Stop and expiry.
179
+ if (error instanceof SponsoredReceiptUnconfirmedError && error.code === 'SPONSOR_GAS_CAP_EXCEEDED')
180
+ throw error;
181
+ return retain(error instanceof LpUserOpError ? error.code : 'LP_USEROP_EVIDENCE_UNAVAILABLE', 'unknown');
182
+ }
183
+ }
184
+ //# sourceMappingURL=lp-userop-settlement.js.map