otto-execute 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/dist/cdp-signer.d.ts +2 -0
  4. package/dist/cdp-signer.js +3 -0
  5. package/dist/cdp.d.ts +7 -0
  6. package/dist/cdp.js +8 -0
  7. package/dist/chain.d.ts +2 -0
  8. package/dist/chain.js +3 -0
  9. package/dist/cli.d.ts +17 -0
  10. package/dist/cli.js +400 -0
  11. package/dist/delegate.d.ts +117 -0
  12. package/dist/delegate.js +394 -0
  13. package/dist/eoa-signer.d.ts +94 -0
  14. package/dist/eoa-signer.js +289 -0
  15. package/dist/erc20.d.ts +2 -0
  16. package/dist/erc20.js +3 -0
  17. package/dist/index.d.ts +16 -0
  18. package/dist/index.js +19 -0
  19. package/dist/lifi-decode.d.ts +2 -0
  20. package/dist/lifi-decode.js +3 -0
  21. package/dist/mutations.d.ts +55 -0
  22. package/dist/mutations.js +363 -0
  23. package/dist/refusal.d.ts +2 -0
  24. package/dist/refusal.js +3 -0
  25. package/dist/vendor/otto-intel-mcp/VENDORED.json +52 -0
  26. package/dist/vendor/otto-intel-mcp/adapter/cdp-signer.d.ts +133 -0
  27. package/dist/vendor/otto-intel-mcp/adapter/cdp-signer.js +356 -0
  28. package/dist/vendor/otto-intel-mcp/adapter/chain.d.ts +36 -0
  29. package/dist/vendor/otto-intel-mcp/adapter/chain.js +65 -0
  30. package/dist/vendor/otto-intel-mcp/adapter/erc20.d.ts +39 -0
  31. package/dist/vendor/otto-intel-mcp/adapter/erc20.js +17 -0
  32. package/dist/vendor/otto-intel-mcp/adapter/lifi-decode.d.ts +52 -0
  33. package/dist/vendor/otto-intel-mcp/adapter/lifi-decode.js +149 -0
  34. package/dist/vendor/otto-intel-mcp/adapter/refusal.d.ts +21 -0
  35. package/dist/vendor/otto-intel-mcp/adapter/refusal.js +55 -0
  36. package/dist/vendor/otto-intel-mcp/adapter/sent-step.d.ts +15 -0
  37. package/dist/vendor/otto-intel-mcp/adapter/sent-step.js +6 -0
  38. package/dist/vendor/otto-intel-mcp/adapter/verify.d.ts +149 -0
  39. package/dist/vendor/otto-intel-mcp/adapter/verify.js +432 -0
  40. package/dist/vendor/otto-intel-mcp/adapter-cdp-index.d.ts +6 -0
  41. package/dist/vendor/otto-intel-mcp/adapter-cdp-index.js +7 -0
  42. package/dist/vendor/otto-intel-mcp/adapter-index.d.ts +15 -0
  43. package/dist/vendor/otto-intel-mcp/adapter-index.js +15 -0
  44. package/dist/vendor/otto-intel-mcp/artifact-id.d.ts +16 -0
  45. package/dist/vendor/otto-intel-mcp/artifact-id.js +60 -0
  46. package/dist/vendor/otto-intel-mcp/execution-config.d.ts +232 -0
  47. package/dist/vendor/otto-intel-mcp/execution-config.js +443 -0
  48. package/dist/vendor/otto-intel-mcp/execution-delegated-definition.d.ts +165 -0
  49. package/dist/vendor/otto-intel-mcp/execution-delegated-definition.js +116 -0
  50. package/dist/vendor/otto-intel-mcp/execution-delegation-admin-definition.d.ts +208 -0
  51. package/dist/vendor/otto-intel-mcp/execution-delegation-admin-definition.js +170 -0
  52. package/dist/vendor/otto-intel-mcp/execution-delegation-policy.d.ts +257 -0
  53. package/dist/vendor/otto-intel-mcp/execution-delegation-policy.js +279 -0
  54. package/dist/vendor/otto-intel-mcp/execution-errors.d.ts +9 -0
  55. package/dist/vendor/otto-intel-mcp/execution-errors.js +134 -0
  56. package/dist/vendor/otto-intel-mcp/execution-index.d.ts +17 -0
  57. package/dist/vendor/otto-intel-mcp/execution-index.js +16 -0
  58. package/dist/vendor/otto-intel-mcp/execution-intent.d.ts +14 -0
  59. package/dist/vendor/otto-intel-mcp/execution-intent.js +36 -0
  60. package/dist/vendor/otto-intel-mcp/execution-tool-definitions.d.ts +1103 -0
  61. package/dist/vendor/otto-intel-mcp/execution-tool-definitions.js +1051 -0
  62. package/dist/vendor/otto-intel-mcp/execution-types.d.ts +274 -0
  63. package/dist/vendor/otto-intel-mcp/execution-types.js +157 -0
  64. package/dist/verify.d.ts +2 -0
  65. package/dist/verify.js +3 -0
  66. package/dist/x402-table.d.ts +99 -0
  67. package/dist/x402-table.js +221 -0
  68. package/package.json +97 -0
@@ -0,0 +1,149 @@
1
+ /**
2
+ * lifi-decode.ts — the adapter's OWN decoder for what it is about to sign.
3
+ *
4
+ * Re-specified (not imported) from the reviewed layouts in `src/lib/otto-wallet/lifi-swap-action.ts`
5
+ * (GenericSwapV3 ERC20→ERC20: receiver@96 / minAmount@128, `LibSwap.SwapData` tuple) and the
6
+ * FeeCollector `collectTokenFees(token, (recipient, amount)[])` body. Spec §11 fences the dApp decoder
7
+ * as a live owner-op importer that must not move; spec §1 keeps the constructor's own assertions on
8
+ * the constructor's side. This file is the user-side view: if the two ever disagree, the artifact is
9
+ * refused, which is the correct outcome for a disagreement about calldata that moves money.
10
+ *
11
+ * Decoding runs on the ARG REGION with `decodeAbiParameters` after a separate selector check, so a
12
+ * selector/ABI mismatch cannot mask a correct-looking parameter decode. Every decode is re-encoded
13
+ * and compared to the input: trailing bytes or non-canonical encodings are refused, never ignored.
14
+ */
15
+ import { decodeAbiParameters, encodeAbiParameters, getAddress, parseAbiParameters, } from 'viem';
16
+ import { refuse } from './refusal.js';
17
+ /** LibSwap.SwapData — (callTo, approveTo, sendingAssetId, receivingAssetId, fromAmount, callData, requiresDeposit). */
18
+ const SWAP_DATA_TUPLE = '(address callTo, address approveTo, address sendingAssetId, address receivingAssetId, uint256 fromAmount, bytes callData, bool requiresDeposit)';
19
+ const GENERIC_SWAP_SINGLE_PARAMS = parseAbiParameters(`bytes32 _transactionId, string _integrator, string _referrer, address _receiver, uint256 _minAmount, ${SWAP_DATA_TUPLE} _swapData`);
20
+ const GENERIC_SWAP_MULTIPLE_PARAMS = parseAbiParameters(`bytes32 _transactionId, string _integrator, string _referrer, address _receiver, uint256 _minAmount, ${SWAP_DATA_TUPLE}[] _swapData`);
21
+ const COLLECT_TOKEN_FEES_PARAMS = parseAbiParameters('address token, (address recipient, uint256 amount)[] distributions');
22
+ /** swapTokensSingleV3ERC20ToERC20 / swapTokensMultipleV3ERC20ToERC20 — the only selectors a swap plan may call. */
23
+ export const GENERIC_SWAP_SELECTORS = Object.freeze({
24
+ single: '0x4666fc80',
25
+ multiple: '0x5fd9ae2e',
26
+ });
27
+ /** FeeCollector.collectTokenFees — the only calldata a fee-forwarding leg may carry. */
28
+ export const COLLECT_TOKEN_FEES_SELECTOR = '0x332d746b';
29
+ function selectorOf(data) {
30
+ return data.slice(0, 10).toLowerCase();
31
+ }
32
+ function argRegion(data) {
33
+ return `0x${data.slice(10)}`;
34
+ }
35
+ function normalizeLeg(leg) {
36
+ return Object.freeze({
37
+ callTo: getAddress(leg.callTo),
38
+ approveTo: getAddress(leg.approveTo),
39
+ sendingAssetId: getAddress(leg.sendingAssetId),
40
+ receivingAssetId: getAddress(leg.receivingAssetId),
41
+ fromAmount: leg.fromAmount,
42
+ callData: leg.callData,
43
+ requiresDeposit: leg.requiresDeposit,
44
+ });
45
+ }
46
+ export function decodeGenericSwap(data) {
47
+ if (!/^0x[0-9a-fA-F]*$/.test(data) || data.length < 10) {
48
+ refuse('SWAP_CALLDATA_INVALID', 'swap step calldata is not hex or has no selector');
49
+ }
50
+ const selector = selectorOf(data);
51
+ const args = argRegion(data);
52
+ const params = selector === GENERIC_SWAP_SELECTORS.single
53
+ ? GENERIC_SWAP_SINGLE_PARAMS
54
+ : selector === GENERIC_SWAP_SELECTORS.multiple
55
+ ? GENERIC_SWAP_MULTIPLE_PARAMS
56
+ : undefined;
57
+ if (!params) {
58
+ refuse('SWAP_CALLDATA_INVALID', `selector ${selector} is not an allowlisted GenericSwap ERC20→ERC20 function`);
59
+ }
60
+ let decoded;
61
+ try {
62
+ decoded = decodeAbiParameters(params, args);
63
+ if (encodeAbiParameters(params, decoded).toLowerCase() !== args.toLowerCase()) {
64
+ refuse('SWAP_CALLDATA_INVALID', 'swap calldata is non-canonical or carries trailing bytes');
65
+ }
66
+ }
67
+ catch (error) {
68
+ if (error instanceof Error && error.name === 'AdapterRefusal')
69
+ throw error;
70
+ refuse('SWAP_CALLDATA_INVALID', 'GenericSwap calldata failed to decode');
71
+ }
72
+ const [transactionId, integrator, referrer, receiver, minAmount, swapData] = decoded;
73
+ const legs = (Array.isArray(swapData) ? swapData : [swapData]).map(normalizeLeg);
74
+ if (legs.length === 0)
75
+ refuse('SWAP_CALLDATA_INVALID', 'GenericSwap carries no swap legs');
76
+ return Object.freeze({
77
+ selector,
78
+ transactionId,
79
+ integrator,
80
+ referrer,
81
+ receiver: getAddress(receiver),
82
+ minAmount,
83
+ legs: Object.freeze(legs),
84
+ });
85
+ }
86
+ export function decodeCollectTokenFees(callData) {
87
+ if (selectorOf(callData) !== COLLECT_TOKEN_FEES_SELECTOR) {
88
+ refuse('ATTRIBUTION_MISSING', 'fee-forwarding leg does not call collectTokenFees');
89
+ }
90
+ const args = argRegion(callData);
91
+ let decoded;
92
+ try {
93
+ decoded = decodeAbiParameters(COLLECT_TOKEN_FEES_PARAMS, args);
94
+ if (encodeAbiParameters(COLLECT_TOKEN_FEES_PARAMS, decoded).toLowerCase() !==
95
+ args.toLowerCase()) {
96
+ refuse('ATTRIBUTION_MISSING', 'fee calldata is non-canonical or carries trailing bytes');
97
+ }
98
+ }
99
+ catch (error) {
100
+ if (error instanceof Error && error.name === 'AdapterRefusal')
101
+ throw error;
102
+ refuse('ATTRIBUTION_MISSING', 'collectTokenFees calldata failed to decode');
103
+ }
104
+ const [token, distributions] = decoded;
105
+ if (distributions.length === 0 || distributions.length > 8) {
106
+ refuse('ATTRIBUTION_MISSING', 'fee calldata has an unexpected distribution count');
107
+ }
108
+ return Object.freeze({
109
+ token: getAddress(token),
110
+ distributions: Object.freeze(distributions.map((distribution) => Object.freeze({ recipient: getAddress(distribution.recipient), amount: distribution.amount }))),
111
+ });
112
+ }
113
+ /* ------------------------------------------------------------------ *
114
+ * Encoders — used ONLY by the mutation matrix (tests + the fence section) to
115
+ * derive inconsistent artifacts the verifier must refuse. Production paths never encode.
116
+ * ------------------------------------------------------------------ */
117
+ export function encodeGenericSwap(swap) {
118
+ const legs = swap.legs.map((leg) => ({ ...leg }));
119
+ if (swap.selector === GENERIC_SWAP_SELECTORS.single) {
120
+ if (legs.length !== 1)
121
+ throw new Error('single selector needs exactly one leg');
122
+ const body = encodeAbiParameters(GENERIC_SWAP_SINGLE_PARAMS, [
123
+ swap.transactionId,
124
+ swap.integrator,
125
+ swap.referrer,
126
+ swap.receiver,
127
+ swap.minAmount,
128
+ legs[0],
129
+ ]);
130
+ return `${swap.selector}${body.slice(2)}`;
131
+ }
132
+ const body = encodeAbiParameters(GENERIC_SWAP_MULTIPLE_PARAMS, [
133
+ swap.transactionId,
134
+ swap.integrator,
135
+ swap.referrer,
136
+ swap.receiver,
137
+ swap.minAmount,
138
+ legs,
139
+ ]);
140
+ return `${swap.selector}${body.slice(2)}`;
141
+ }
142
+ export function encodeCollectTokenFees(fees) {
143
+ const body = encodeAbiParameters(COLLECT_TOKEN_FEES_PARAMS, [
144
+ fees.token,
145
+ fees.distributions.map((distribution) => ({ ...distribution })),
146
+ ]);
147
+ return `${COLLECT_TOKEN_FEES_SELECTOR}${body.slice(2)}`;
148
+ }
149
+ //# sourceMappingURL=lifi-decode.js.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * refusal.ts — the adapter's refusal taxonomy.
3
+ *
4
+ * Every refusal names a defect in the artifact or in the request (spec §10). A refusal that cannot
5
+ * name one is not a refusal but a service fault, and is thrown as a plain Error so the ladder grades
6
+ * it INCONCLUSIVE rather than BLOCKED.
7
+ *
8
+ * `errorType` mirrors `code` so the CDP kit's ladder — which only grades a *structured* refusal as
9
+ * the fence biting — recognises adapter refusals without a second grading path.
10
+ */
11
+ export declare const ADAPTER_REFUSAL_CODES: readonly ["SCHEMA_INVALID", "UNSUPPORTED_OPERATION", "DIGEST_MISMATCH", "STALE_ARTIFACT", "ACCOUNT_BINDING_MISMATCH", "CAPABILITY_MISSING", "CHAIN_MISMATCH", "PLAN_SHAPE_INVALID", "APPROVAL_INVALID", "TARGET_NOT_ALLOWED", "SWAP_CALLDATA_INVALID", "RECEIVER_MISMATCH", "INTENT_MISMATCH", "MIN_OUTPUT_TOO_LOW", "ATTRIBUTION_MISSING", "ATTRIBUTION_MISMATCH", "FEE_CAP_EXCEEDED"];
12
+ export type AdapterRefusalCode = (typeof ADAPTER_REFUSAL_CODES)[number];
13
+ export declare class AdapterRefusal extends Error {
14
+ readonly code: AdapterRefusalCode;
15
+ /** Same value as `code`; lets `normalizeError` treat this as a structured refusal. */
16
+ readonly errorType: AdapterRefusalCode;
17
+ constructor(code: AdapterRefusalCode, message: string);
18
+ }
19
+ export declare function refuse(code: AdapterRefusalCode, message: string): never;
20
+ export declare function isAdapterRefusal(error: unknown): error is AdapterRefusal;
21
+ export declare function isAdapterRefusalCode(value: string): value is AdapterRefusalCode;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * refusal.ts — the adapter's refusal taxonomy.
3
+ *
4
+ * Every refusal names a defect in the artifact or in the request (spec §10). A refusal that cannot
5
+ * name one is not a refusal but a service fault, and is thrown as a plain Error so the ladder grades
6
+ * it INCONCLUSIVE rather than BLOCKED.
7
+ *
8
+ * `errorType` mirrors `code` so the CDP kit's ladder — which only grades a *structured* refusal as
9
+ * the fence biting — recognises adapter refusals without a second grading path.
10
+ */
11
+ export const ADAPTER_REFUSAL_CODES = [
12
+ // Envelope integrity (the constructor's own assertions, surfaced unchanged)
13
+ 'SCHEMA_INVALID',
14
+ 'UNSUPPORTED_OPERATION',
15
+ 'DIGEST_MISMATCH',
16
+ 'STALE_ARTIFACT',
17
+ 'ACCOUNT_BINDING_MISMATCH',
18
+ // Adapter contract (spec §9)
19
+ 'CAPABILITY_MISSING',
20
+ 'CHAIN_MISMATCH',
21
+ // Adapter-side plan policy (what the user's signer is willing to sign)
22
+ 'PLAN_SHAPE_INVALID',
23
+ 'APPROVAL_INVALID',
24
+ 'TARGET_NOT_ALLOWED',
25
+ 'SWAP_CALLDATA_INVALID',
26
+ 'RECEIVER_MISMATCH',
27
+ // Intent binding — the artifact must be the trade the USER asked for
28
+ 'INTENT_MISMATCH',
29
+ 'MIN_OUTPUT_TOO_LOW',
30
+ // Attribution — assert what you are about to sign, against the RULED constants
31
+ 'ATTRIBUTION_MISSING',
32
+ 'ATTRIBUTION_MISMATCH',
33
+ 'FEE_CAP_EXCEEDED',
34
+ ];
35
+ export class AdapterRefusal extends Error {
36
+ code;
37
+ /** Same value as `code`; lets `normalizeError` treat this as a structured refusal. */
38
+ errorType;
39
+ constructor(code, message) {
40
+ super(`[${code}] ${message}`);
41
+ this.code = code;
42
+ this.name = 'AdapterRefusal';
43
+ this.errorType = code;
44
+ }
45
+ }
46
+ export function refuse(code, message) {
47
+ throw new AdapterRefusal(code, message);
48
+ }
49
+ export function isAdapterRefusal(error) {
50
+ return error instanceof AdapterRefusal;
51
+ }
52
+ export function isAdapterRefusalCode(value) {
53
+ return ADAPTER_REFUSAL_CODES.includes(value);
54
+ }
55
+ //# sourceMappingURL=refusal.js.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * sent-step.ts — one submitted plan step as both signers report it: the step's index and kind, its
3
+ * target, the transaction hash, and the SEALED canonical receipt's block number and gas used.
4
+ */
5
+ import type { Address, Hex } from 'viem';
6
+ import type { VerifiedStep } from './verify.js';
7
+ export interface SentStep {
8
+ readonly index: number;
9
+ readonly kind: VerifiedStep['kind'];
10
+ readonly to: Address;
11
+ readonly transaction_hash: Hex;
12
+ readonly status: 'success';
13
+ readonly block_number: string;
14
+ readonly gas_used: string;
15
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * sent-step.ts — one submitted plan step as both signers report it: the step's index and kind, its
3
+ * target, the transaction hash, and the SEALED canonical receipt's block number and gas used.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=sent-step.js.map
@@ -0,0 +1,149 @@
1
+ /**
2
+ * verify.ts — the adapter core: what the user's signer checks BEFORE it signs anything.
3
+ *
4
+ * Model B (docs/0808_model_b_scope_and_verdict.md, spec docs/0816_step1_execution_mcp_spec_draft.md):
5
+ * Otto constructs; the user's own custody signs and submits; Otto's fee is attribution baked into
6
+ * the constructed payload. The constructor is prepare-only and asserts what it built. This module is
7
+ * the OTHER half of spec §8 — "the consuming adapter re-checks digest + expected signer before
8
+ * signing" — extended to a full adapter-side policy, because an artifact's own digests prove
9
+ * integrity relative to the artifact's own claims and nothing more: an inconsistent artifact with
10
+ * correctly recomputed digests is still inconsistent. The checks run in three layers:
11
+ *
12
+ * 1. INTEGRITY — the constructor's own assertions, unchanged (schema, payload digest, whole-envelope
13
+ * commitment + freshness, account binding).
14
+ * 2. INTENT — the artifact is the trade the USER asked for: the approved token and amount ARE the
15
+ * intent's, the deposit legs pull exactly that amount, the output token IS the intent's, and the
16
+ * on-chain minimum output is at least the caller's own floor (> 0). The caller owns the floor;
17
+ * it never comes from the artifact. This is the fence for the swap legs themselves: LI.FI's
18
+ * GenericSwapV3 reverts unless `_receiver` gets at least `_minAmount` of the output token, so an
19
+ * internal DEX leg is bounded on-chain by the receiver + minimum-output binds rather than by an
20
+ * allowlist of every DEX contract (which this adapter deliberately does not attempt to hold).
21
+ * 3. POLICY — capability contract, chain, plan shape, approvals only to the reviewed spender
22
+ * that IS the call target, `_receiver` == this account, and the fee leg decoded with the
23
+ * adapter's own decoder and matched against the RULED attribution constants (10 bps to Otto's
24
+ * recipient, only the reviewed FeeForwarder deployments, nothing to strangers, aggregate under
25
+ * the cap).
26
+ *
27
+ * P0 LIVENESS binds here exactly as it binds the constructor (spec §7.0): a valid artifact for the
28
+ * stated intent MUST pass. The test suite's first test is that property; the mutation matrix proves
29
+ * every refusal reddens. Every check that passes is recorded by id so the sitting's evidence shows
30
+ * what was verified, not just that "verification passed".
31
+ */
32
+ import { type Address, type Hex } from 'viem';
33
+ import { type AccountProfile, type ExecutionEnvelope } from '../execution-index.js';
34
+ import { type DecodedCollectTokenFees } from './lifi-decode.js';
35
+ export type SigningCapability = 'send_evm_transaction' | 'submit_evm_batch' | 'sign_eip712' | 'sign_hyperliquid_l1' | 'sign_x402_payment';
36
+ /** What the USER asked for. Owned by the caller; never read out of the artifact. */
37
+ export interface SwapIntent {
38
+ readonly fromToken: Address;
39
+ readonly toToken: Address;
40
+ /** Exact input amount in atomic units. */
41
+ readonly fromAmount: bigint;
42
+ /**
43
+ * The caller's OWN minimum acceptable output (atomic units), from a price source the caller
44
+ * trusts. Must be positive: a zero floor would let a swap leg deliver nothing.
45
+ */
46
+ readonly minAmountOut: bigint;
47
+ }
48
+ export interface AttributionPolicy {
49
+ /** The RULED fee config version the envelope must carry (spec §8: mechanism + version, never values). */
50
+ readonly configVersion: string;
51
+ /** The RULED Otto fee in basis points, asserted against the decoded fee leg. */
52
+ readonly feeBps: bigint;
53
+ readonly integrator: string;
54
+ readonly ottoRecipient: Address;
55
+ /** Recipients other than Otto's that a fee leg may pay (LI.FI's own platform share). Anything else is refused. */
56
+ readonly otherAllowedRecipients: readonly Address[];
57
+ /** Reviewed FeeForwarder deployments for the plan's chain (v1 + v2.0.0 today); a leg calling any other address is refused by name. */
58
+ readonly forwarders: readonly Address[];
59
+ /** Aggregate (Otto + LI.FI) fee ceiling in basis points; strictly above it is refused. */
60
+ readonly aggregateCapBps: bigint;
61
+ }
62
+ export interface AdapterPolicy {
63
+ readonly allowedCallTargets: readonly Address[];
64
+ readonly allowedApproveSpenders: readonly Address[];
65
+ readonly attribution: AttributionPolicy;
66
+ }
67
+ export interface VerifyExpectations {
68
+ readonly profile: AccountProfile;
69
+ readonly intent: SwapIntent;
70
+ readonly capabilities: readonly SigningCapability[];
71
+ readonly policy: AdapterPolicy;
72
+ readonly nowMs?: number;
73
+ /**
74
+ * The EXACT `otto_prepare_swap` input the caller sent (raw, as sent). When supplied, the artifact's
75
+ * `intent_digest` is recomputed with the constructor's own normalizer (which parses and checksums
76
+ * exactly as the constructor does) and must match — the artifact is then bound not only to the
77
+ * semantic intent fields but to the very request that produced it.
78
+ */
79
+ readonly prepareInput?: unknown;
80
+ }
81
+ export interface VerifiedStep {
82
+ readonly kind: 'approve_reset' | 'approve' | 'call';
83
+ readonly to: Address;
84
+ readonly value: bigint;
85
+ readonly data: Hex;
86
+ }
87
+ export interface VerifiedCheck {
88
+ readonly id: string;
89
+ readonly result: 'passed';
90
+ }
91
+ export interface VerifiedSwap {
92
+ readonly artifact: ExecutionEnvelope;
93
+ readonly steps: readonly [VerifiedStep, VerifiedStep, VerifiedStep];
94
+ readonly intent: SwapIntent;
95
+ readonly token: Address;
96
+ readonly outputToken: Address;
97
+ readonly spender: Address;
98
+ readonly gross: bigint;
99
+ readonly receiver: Address;
100
+ readonly minAmountOut: bigint;
101
+ readonly ottoFee: bigint;
102
+ readonly fees: DecodedCollectTokenFees;
103
+ readonly checks: readonly VerifiedCheck[];
104
+ }
105
+ /** The reviewed v1 policy for a same-chain LI.FI swap on `chainId`. */
106
+ export declare function defaultAdapterPolicy(chainId: number): AdapterPolicy;
107
+ export declare function verifySwapEnvelope(raw: unknown, expected: VerifyExpectations): VerifiedSwap;
108
+ /** The verifier's record of a plan at verification time. Signers bind to THIS, not to the plan's fields. */
109
+ export interface PlanIdentity {
110
+ readonly address: Address;
111
+ readonly chainId: number;
112
+ readonly capabilities: readonly SigningCapability[];
113
+ readonly validUntilMs: number;
114
+ readonly artifactId: string;
115
+ readonly artifactDigest: Hex;
116
+ readonly stepTargets: readonly [Address, Address, Address];
117
+ }
118
+ /** True iff every object reachable from `value` is frozen. */
119
+ export declare function isDeepFrozen(value: unknown): boolean;
120
+ /** True iff `plan` is an object `verifySwapEnvelope` itself returned (identity, not shape). */
121
+ export declare function isVerifierOutput(plan: unknown): boolean;
122
+ /** The verifier's own record of an intact verified plan (throws for anything else). */
123
+ export declare function verifiedPlanIdentity(plan: VerifiedSwap): PlanIdentity;
124
+ /** What a signer must present to be allowed to sign a verified plan. */
125
+ export interface SignerIdentity {
126
+ readonly address: Address;
127
+ readonly chainId: number;
128
+ readonly capabilities: readonly SigningCapability[];
129
+ }
130
+ /**
131
+ * The FULL signer-side gate, called at signer entry and again immediately before every signature or
132
+ * submission: provenance + frozen shape (`assertVerifiedPlanIntact`), then — against the verifier's
133
+ * RECORD of the plan, not the plan's fields — the bound account IS this signer, the chain matches,
134
+ * every required capability is provided, and the plan is still fresh at `nowMs` (the record's
135
+ * deadline AND the artifact's own commitment-bound deadline). A plan verified for another account,
136
+ * another chain, or that has since expired is refused here even though it was genuinely verified.
137
+ */
138
+ export declare function assertPlanSignableBy(plan: VerifiedSwap, signer: SignerIdentity, nowMs?: number): void;
139
+ /**
140
+ * Signer-side gate: a plan may be signed only if it IS the object `verifySwapEnvelope` returned
141
+ * (provenance, checked by identity), it is still the deep-frozen shape it was returned as — the
142
+ * artifact's nested objects included — and it still matches the verifier's own record of it. A thawed
143
+ * copy, a JSON round trip, a mutated clone, a fully frozen look-alike that imitates the shape, or a
144
+ * re-pointed artifact with a recomputed commitment are all refused, so the only way to sign
145
+ * different bytes is to verify different bytes.
146
+ */
147
+ export declare function assertVerifiedPlanIntact(plan: VerifiedSwap): void;
148
+ /** The check ids `verifySwapEnvelope` records on a passing artifact, in order. Tests pin this list. */
149
+ export declare const VERIFY_CHECK_IDS: readonly ["schema", "payload_digest", "commitment", "freshness", "account_binding", "capabilities", "chain", "plan_shape", "approvals", "swap_decode", "min_output", "fee_attribution"];