@haven_ai/sdk 0.8.0-alpha.0 → 0.9.0-alpha.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 (39) hide show
  1. package/dist/base64-BZDPJ8M1.d.ts +1344 -0
  2. package/dist/base64-Cyxhsvqd.d.cts +1344 -0
  3. package/dist/{chunk-UXULZ3ZY.js → chunk-424S4QMG.js} +10 -5
  4. package/dist/chunk-424S4QMG.js.map +1 -0
  5. package/dist/{chunk-HX34HOW4.cjs → chunk-4Z6ATE44.cjs} +2 -2
  6. package/dist/chunk-4Z6ATE44.cjs.map +1 -0
  7. package/dist/chunk-7UTWSJC5.cjs +106 -0
  8. package/dist/chunk-7UTWSJC5.cjs.map +1 -0
  9. package/dist/{chunk-H4APV67M.js → chunk-J7N4LUZZ.js} +2 -2
  10. package/dist/chunk-J7N4LUZZ.js.map +1 -0
  11. package/dist/chunk-VRKWNJ7H.js +103 -0
  12. package/dist/chunk-VRKWNJ7H.js.map +1 -0
  13. package/dist/{chunk-WJFDXCYP.cjs → chunk-ZDKNPNI3.cjs} +41 -35
  14. package/dist/chunk-ZDKNPNI3.cjs.map +1 -0
  15. package/dist/edge.cjs +97 -89
  16. package/dist/edge.d.cts +4 -2
  17. package/dist/edge.d.ts +4 -2
  18. package/dist/edge.js +4 -4
  19. package/dist/index.cjs +1033 -490
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +103 -147
  22. package/dist/index.d.ts +103 -147
  23. package/dist/index.js +705 -189
  24. package/dist/index.js.map +1 -1
  25. package/dist/receipt-D4Roey3D.d.cts +130 -0
  26. package/dist/receipt-WkXHZGbu.d.ts +130 -0
  27. package/dist/test-support.cjs +71 -18
  28. package/dist/test-support.cjs.map +1 -1
  29. package/dist/test-support.d.cts +21 -1
  30. package/dist/test-support.d.ts +21 -1
  31. package/dist/test-support.js +53 -3
  32. package/dist/test-support.js.map +1 -1
  33. package/dist/{base64-znjJJQqu.d.cts → types-CrszUJ7Z.d.cts} +208 -1306
  34. package/dist/{base64-znjJJQqu.d.ts → types-CrszUJ7Z.d.ts} +208 -1306
  35. package/package.json +1 -1
  36. package/dist/chunk-H4APV67M.js.map +0 -1
  37. package/dist/chunk-HX34HOW4.cjs.map +0 -1
  38. package/dist/chunk-UXULZ3ZY.js.map +0 -1
  39. package/dist/chunk-WJFDXCYP.cjs.map +0 -1
@@ -0,0 +1,130 @@
1
+ import { aV as RawPaymentParties } from './types-CrszUJ7Z.cjs';
2
+
3
+ /**
4
+ * Verifiable payment receipts.
5
+ *
6
+ * A self-contained bundle for a settled Haven payment whose agent
7
+ * authorisation can be checked offline. What `verifyPaymentReceipt` proves is
8
+ * deliberately narrow: the `payment` block (amount, recipient) is
9
+ * Haven-asserted and is NOT bound by the signature, and `verified: true` never
10
+ * proves the payment settled on-chain — settlement stays an explorer check on
11
+ * `onChain.txHash` / `settlementTxHash`.
12
+ *
13
+ * What `verified: true` means, per scheme:
14
+ *
15
+ * - erc7710 (`authorization.signatureScheme: 'eip712_delegation'`): the bundle
16
+ * carries the settlement child's EIP-712 struct hash as `signHash`. The
17
+ * verifier rebuilds the digest the delegate actually signed —
18
+ * `keccak256(0x1901 ‖ domainSeparator(DelegationManager, chainId) ‖ signHash)`
19
+ * — from the DelegationManager address the SDK pins and the bundle's
20
+ * `onChain.chainId`, never from a value the receipt itself vouches for.
21
+ * `verified: true` means the delegate key signed that settlement delegation
22
+ * (`verifiedOver: 'delegation_digest'`).
23
+ * - direct payments and the eip3009 funding leg
24
+ * (`signatureScheme: 'eip712_userop'`) sign an ERC-4337 user operation the
25
+ * bundle does not carry: they return `not_verifiable_offline` rather than a
26
+ * false accusation.
27
+ * - retired-rail bundles (no scheme) carry a raw-signed `signHash`; the
28
+ * verifier recovers over it directly, then over the delegation digest when
29
+ * the chain allows rebuilding it.
30
+ *
31
+ * Anything that is not a signed bundle — including a `haven_list_receipts`
32
+ * history row, which carries no signature at all — returns
33
+ * `not_a_signed_receipt`. Verification never throws.
34
+ *
35
+ * #3723: the response `GET /payments/{id}/receipt` returns —
36
+ * `{ receipt, verification }` — is accepted AS-IS: when the top level carries
37
+ * no `authorization`, the `.receipt` object inside is verified instead (one
38
+ * level, no recursion). The wrapper's `verification` is never read — it is
39
+ * Haven's own self-check, and trusting it would defeat an offline verifier.
40
+ *
41
+ * This lives in the SDK so agents and users can verify receipts client-side.
42
+ */
43
+ declare const RECEIPT_VERSION = "haven-receipt-1";
44
+ interface PaymentReceipt {
45
+ version: typeof RECEIPT_VERSION;
46
+ paymentId: string;
47
+ payment: {
48
+ token: string;
49
+ tokenAddress: string;
50
+ amount: string;
51
+ amountSek: string | null;
52
+ recipient: string;
53
+ /** The payer's smart-account address. */
54
+ account: string;
55
+ /**
56
+ * #2960: one party vocabulary for "who paid", additive alongside `account`
57
+ * above (which is `parties.treasury_account` only). Optional: a server
58
+ * from before #2960 emits neither. Ignored by `verifyPaymentReceipt`,
59
+ * which reads only `authorization`.
60
+ */
61
+ parties?: RawPaymentParties;
62
+ chainId: number;
63
+ settledAt: string | null;
64
+ resourceUrl: string | null;
65
+ /**
66
+ * #3770: the paying agent's own evidence-only verdict on what the
67
+ * merchant DELIVERED (`ok` / `unusable` / `partial`, plus a bounded
68
+ * note). Additive and OPTIONAL: a server from before #3770 emits
69
+ * neither, and `null` means the agent has not reported. Ignored by
70
+ * `verifyPaymentReceipt`, which reads only `authorization` — the same
71
+ * rule `parties` follows. Evidence only: it never changes what the
72
+ * payment itself is, and `settled`/amounts are untouched by a report.
73
+ */
74
+ deliveryQuality?: {
75
+ quality: 'ok' | 'unusable' | 'partial';
76
+ note: string | null;
77
+ reportedAt: string | null;
78
+ } | null;
79
+ };
80
+ /** The agent's cryptographic authorisation — what makes the receipt verifiable. */
81
+ authorization: {
82
+ delegate: string;
83
+ signHash: string;
84
+ signature: string | null;
85
+ /**
86
+ * #3418: which digest the delegate signed — selects what offline
87
+ * verification rebuilds. `'eip712_delegation'`: the settlement
88
+ * delegation's EIP-712 digest (erc7710). `'eip712_userop'`: an ERC-4337
89
+ * user-operation digest the bundle does not carry (direct payments, the
90
+ * eip3009 funding leg) — not verifiable offline. Absent on retired-rail
91
+ * bundles and on backends older than #3418, whose `signHash` was signed
92
+ * raw. The value is only a selector: a lying one cannot make a forged
93
+ * signature verify, because recovery must still return `delegate`.
94
+ */
95
+ signatureScheme?: 'eip712_delegation' | 'eip712_userop';
96
+ };
97
+ onChain: {
98
+ txHash: string | null;
99
+ chainId: number;
100
+ };
101
+ }
102
+ type ReceiptVerification = {
103
+ verified: true;
104
+ recoveredSigner: string;
105
+ verifiedOver: 'sign_hash' | 'delegation_digest';
106
+ } | {
107
+ verified: false;
108
+ reason:
109
+ /** #3418: the input is not a haven-receipt-1 bundle (a haven_list_receipts row, null, undefined, a non-object). */
110
+ 'not_a_signed_receipt'
111
+ /** #3418: eip712_userop bundle; or a delegation bundle on a chain the SDK pins no DelegationManager for. */
112
+ | 'not_verifiable_offline' | 'missing_signature' | 'bad_signature' | 'signer_mismatch';
113
+ recoveredSigner?: string;
114
+ };
115
+ type RecoverFn = (hash: string, signature: string) => string;
116
+ /**
117
+ * Verify a receipt's agent authorisation offline: recover the signer and
118
+ * confirm it is the agent delegate, over whichever digest the bundle's scheme
119
+ * names (see the module doc for what that proves — and what it does not).
120
+ * Never throws: anything that is not a signed receipt — a
121
+ * `haven_list_receipts` history row, null, undefined, a non-object — returns
122
+ * `not_a_signed_receipt`. The `{ receipt, verification }` wrapper the receipt
123
+ * endpoint returns is accepted as-is: `.receipt` is verified, and the
124
+ * wrapper's `verification` — Haven's own self-check — is never read. Pure —
125
+ * `recover` is injectable but defaults to
126
+ * standard ECDSA recovery, so this runs anywhere (no Haven backend).
127
+ */
128
+ declare function verifyPaymentReceipt(receipt: unknown, recover?: RecoverFn): ReceiptVerification;
129
+
130
+ export { type PaymentReceipt as P, type ReceiptVerification as R, RECEIPT_VERSION as a, verifyPaymentReceipt as v };
@@ -0,0 +1,130 @@
1
+ import { aV as RawPaymentParties } from './types-CrszUJ7Z.js';
2
+
3
+ /**
4
+ * Verifiable payment receipts.
5
+ *
6
+ * A self-contained bundle for a settled Haven payment whose agent
7
+ * authorisation can be checked offline. What `verifyPaymentReceipt` proves is
8
+ * deliberately narrow: the `payment` block (amount, recipient) is
9
+ * Haven-asserted and is NOT bound by the signature, and `verified: true` never
10
+ * proves the payment settled on-chain — settlement stays an explorer check on
11
+ * `onChain.txHash` / `settlementTxHash`.
12
+ *
13
+ * What `verified: true` means, per scheme:
14
+ *
15
+ * - erc7710 (`authorization.signatureScheme: 'eip712_delegation'`): the bundle
16
+ * carries the settlement child's EIP-712 struct hash as `signHash`. The
17
+ * verifier rebuilds the digest the delegate actually signed —
18
+ * `keccak256(0x1901 ‖ domainSeparator(DelegationManager, chainId) ‖ signHash)`
19
+ * — from the DelegationManager address the SDK pins and the bundle's
20
+ * `onChain.chainId`, never from a value the receipt itself vouches for.
21
+ * `verified: true` means the delegate key signed that settlement delegation
22
+ * (`verifiedOver: 'delegation_digest'`).
23
+ * - direct payments and the eip3009 funding leg
24
+ * (`signatureScheme: 'eip712_userop'`) sign an ERC-4337 user operation the
25
+ * bundle does not carry: they return `not_verifiable_offline` rather than a
26
+ * false accusation.
27
+ * - retired-rail bundles (no scheme) carry a raw-signed `signHash`; the
28
+ * verifier recovers over it directly, then over the delegation digest when
29
+ * the chain allows rebuilding it.
30
+ *
31
+ * Anything that is not a signed bundle — including a `haven_list_receipts`
32
+ * history row, which carries no signature at all — returns
33
+ * `not_a_signed_receipt`. Verification never throws.
34
+ *
35
+ * #3723: the response `GET /payments/{id}/receipt` returns —
36
+ * `{ receipt, verification }` — is accepted AS-IS: when the top level carries
37
+ * no `authorization`, the `.receipt` object inside is verified instead (one
38
+ * level, no recursion). The wrapper's `verification` is never read — it is
39
+ * Haven's own self-check, and trusting it would defeat an offline verifier.
40
+ *
41
+ * This lives in the SDK so agents and users can verify receipts client-side.
42
+ */
43
+ declare const RECEIPT_VERSION = "haven-receipt-1";
44
+ interface PaymentReceipt {
45
+ version: typeof RECEIPT_VERSION;
46
+ paymentId: string;
47
+ payment: {
48
+ token: string;
49
+ tokenAddress: string;
50
+ amount: string;
51
+ amountSek: string | null;
52
+ recipient: string;
53
+ /** The payer's smart-account address. */
54
+ account: string;
55
+ /**
56
+ * #2960: one party vocabulary for "who paid", additive alongside `account`
57
+ * above (which is `parties.treasury_account` only). Optional: a server
58
+ * from before #2960 emits neither. Ignored by `verifyPaymentReceipt`,
59
+ * which reads only `authorization`.
60
+ */
61
+ parties?: RawPaymentParties;
62
+ chainId: number;
63
+ settledAt: string | null;
64
+ resourceUrl: string | null;
65
+ /**
66
+ * #3770: the paying agent's own evidence-only verdict on what the
67
+ * merchant DELIVERED (`ok` / `unusable` / `partial`, plus a bounded
68
+ * note). Additive and OPTIONAL: a server from before #3770 emits
69
+ * neither, and `null` means the agent has not reported. Ignored by
70
+ * `verifyPaymentReceipt`, which reads only `authorization` — the same
71
+ * rule `parties` follows. Evidence only: it never changes what the
72
+ * payment itself is, and `settled`/amounts are untouched by a report.
73
+ */
74
+ deliveryQuality?: {
75
+ quality: 'ok' | 'unusable' | 'partial';
76
+ note: string | null;
77
+ reportedAt: string | null;
78
+ } | null;
79
+ };
80
+ /** The agent's cryptographic authorisation — what makes the receipt verifiable. */
81
+ authorization: {
82
+ delegate: string;
83
+ signHash: string;
84
+ signature: string | null;
85
+ /**
86
+ * #3418: which digest the delegate signed — selects what offline
87
+ * verification rebuilds. `'eip712_delegation'`: the settlement
88
+ * delegation's EIP-712 digest (erc7710). `'eip712_userop'`: an ERC-4337
89
+ * user-operation digest the bundle does not carry (direct payments, the
90
+ * eip3009 funding leg) — not verifiable offline. Absent on retired-rail
91
+ * bundles and on backends older than #3418, whose `signHash` was signed
92
+ * raw. The value is only a selector: a lying one cannot make a forged
93
+ * signature verify, because recovery must still return `delegate`.
94
+ */
95
+ signatureScheme?: 'eip712_delegation' | 'eip712_userop';
96
+ };
97
+ onChain: {
98
+ txHash: string | null;
99
+ chainId: number;
100
+ };
101
+ }
102
+ type ReceiptVerification = {
103
+ verified: true;
104
+ recoveredSigner: string;
105
+ verifiedOver: 'sign_hash' | 'delegation_digest';
106
+ } | {
107
+ verified: false;
108
+ reason:
109
+ /** #3418: the input is not a haven-receipt-1 bundle (a haven_list_receipts row, null, undefined, a non-object). */
110
+ 'not_a_signed_receipt'
111
+ /** #3418: eip712_userop bundle; or a delegation bundle on a chain the SDK pins no DelegationManager for. */
112
+ | 'not_verifiable_offline' | 'missing_signature' | 'bad_signature' | 'signer_mismatch';
113
+ recoveredSigner?: string;
114
+ };
115
+ type RecoverFn = (hash: string, signature: string) => string;
116
+ /**
117
+ * Verify a receipt's agent authorisation offline: recover the signer and
118
+ * confirm it is the agent delegate, over whichever digest the bundle's scheme
119
+ * names (see the module doc for what that proves — and what it does not).
120
+ * Never throws: anything that is not a signed receipt — a
121
+ * `haven_list_receipts` history row, null, undefined, a non-object — returns
122
+ * `not_a_signed_receipt`. The `{ receipt, verification }` wrapper the receipt
123
+ * endpoint returns is accepted as-is: `.receipt` is verified, and the
124
+ * wrapper's `verification` — Haven's own self-check — is never read. Pure —
125
+ * `recover` is injectable but defaults to
126
+ * standard ECDSA recovery, so this runs anywhere (no Haven backend).
127
+ */
128
+ declare function verifyPaymentReceipt(receipt: unknown, recover?: RecoverFn): ReceiptVerification;
129
+
130
+ export { type PaymentReceipt as P, type ReceiptVerification as R, RECEIPT_VERSION as a, verifyPaymentReceipt as v };
@@ -1,13 +1,15 @@
1
1
  'use strict';
2
2
 
3
- var chunkHX34HOW4_cjs = require('./chunk-HX34HOW4.cjs');
3
+ var chunk7UTWSJC5_cjs = require('./chunk-7UTWSJC5.cjs');
4
+ var chunk4Z6ATE44_cjs = require('./chunk-4Z6ATE44.cjs');
4
5
  var viem = require('viem');
6
+ var ethers = require('ethers');
5
7
 
6
8
  var ZERO_BYTES32 = `0x${"00".repeat(32)}`;
7
9
  var ROOT_AUTHORITY = `0x${"ff".repeat(32)}`;
8
10
  var DEFAULT_DELEGATOR = "0x98989898989898989898989898989898989898De";
9
11
  var DELEGATION_ARRAY_PARAM = [
10
- { type: "tuple[]", components: chunkHX34HOW4_cjs.DELEGATION_TUPLE_COMPONENTS }
12
+ { type: "tuple[]", components: chunk4Z6ATE44_cjs.DELEGATION_TUPLE_COMPONENTS }
11
13
  ];
12
14
  var EXECUTE_ABI = [
13
15
  {
@@ -83,16 +85,16 @@ function buildBoundRedeemDelegationsCallData(options) {
83
85
  10000n
84
86
  );
85
87
  return viem.encodeFunctionData({
86
- abi: chunkHX34HOW4_cjs.REDEEM_DELEGATIONS_ABI,
88
+ abi: chunk4Z6ATE44_cjs.REDEEM_DELEGATIONS_ABI,
87
89
  functionName: "redeemDelegations",
88
- args: [[permissionContext], [chunkHX34HOW4_cjs.SINGLE_DEFAULT_MODE], [executionCallData]]
90
+ args: [[permissionContext], [chunk4Z6ATE44_cjs.SINGLE_DEFAULT_MODE], [executionCallData]]
89
91
  });
90
92
  }
91
93
  function buildEmptyPermissionContextRedemption(selfCallCallData) {
92
94
  return viem.encodeFunctionData({
93
- abi: chunkHX34HOW4_cjs.REDEEM_DELEGATIONS_ABI,
95
+ abi: chunk4Z6ATE44_cjs.REDEEM_DELEGATIONS_ABI,
94
96
  functionName: "redeemDelegations",
95
- args: [[buildEmptyPermissionContext()], [chunkHX34HOW4_cjs.SINGLE_DEFAULT_MODE], [selfCallCallData]]
97
+ args: [[buildEmptyPermissionContext()], [chunk4Z6ATE44_cjs.SINGLE_DEFAULT_MODE], [selfCallCallData]]
96
98
  });
97
99
  }
98
100
  function buildExecuteCallData(target, value, innerCallData) {
@@ -104,20 +106,20 @@ function buildExecuteCallData(target, value, innerCallData) {
104
106
  }
105
107
  function buildBoundDirectUserOp(options) {
106
108
  const chainId = options.chainId ?? 84532;
107
- const sender = options.sender ?? chunkHX34HOW4_cjs.deriveDelegateAccountAddress(options.delegate);
109
+ const sender = options.sender ?? chunk4Z6ATE44_cjs.deriveDelegateAccountAddress(options.delegate);
108
110
  const callData = options.callData ?? buildExecuteCallData(
109
- options.target ?? chunkHX34HOW4_cjs.DELEGATION_MANAGER,
111
+ options.target ?? chunk4Z6ATE44_cjs.DELEGATION_MANAGER,
110
112
  options.value ?? 0n,
111
113
  buildBoundRedeemDelegationsCallData({ delegate: sender, delegator: options.delegator })
112
114
  );
113
115
  const typedData = {
114
116
  domain: {
115
- name: chunkHX34HOW4_cjs.HYBRID_DELEGATOR_DOMAIN_NAME,
116
- version: chunkHX34HOW4_cjs.HYBRID_DELEGATOR_DOMAIN_VERSION,
117
+ name: chunk4Z6ATE44_cjs.HYBRID_DELEGATOR_DOMAIN_NAME,
118
+ version: chunk4Z6ATE44_cjs.HYBRID_DELEGATOR_DOMAIN_VERSION,
117
119
  chainId,
118
120
  verifyingContract: sender
119
121
  },
120
- types: { PackedUserOperation: chunkHX34HOW4_cjs.PACKED_USER_OPERATION_FIELDS.map((field) => ({ ...field })) },
122
+ types: { PackedUserOperation: chunk4Z6ATE44_cjs.PACKED_USER_OPERATION_FIELDS.map((field) => ({ ...field })) },
121
123
  primaryType: "PackedUserOperation",
122
124
  message: {
123
125
  sender,
@@ -128,10 +130,10 @@ function buildBoundDirectUserOp(options) {
128
130
  preVerificationGas: "0",
129
131
  gasFees: ZERO_BYTES32,
130
132
  paymasterAndData: "0x",
131
- entryPoint: chunkHX34HOW4_cjs.ENTRY_POINT_V07
133
+ entryPoint: chunk4Z6ATE44_cjs.ENTRY_POINT_V07
132
134
  }
133
135
  };
134
- const payloadHash = chunkHX34HOW4_cjs.packedUserOperationHash(typedData);
136
+ const payloadHash = chunk4Z6ATE44_cjs.packedUserOperationHash(typedData);
135
137
  return { typedData, payloadHash, sender };
136
138
  }
137
139
  function buildSelfCallCallData(sender) {
@@ -149,7 +151,7 @@ function rebuildDirectUserOpForSender(fixtureTypedData, newSender) {
149
151
  const originalCallData = fixtureTypedData.message.callData;
150
152
  const { args: executeArgs } = viem.decodeFunctionData({ abi: EXECUTE_ABI, data: originalCallData });
151
153
  const execution = executeArgs[0];
152
- const { args: redeemArgs } = viem.decodeFunctionData({ abi: chunkHX34HOW4_cjs.REDEEM_DELEGATIONS_ABI, data: execution.callData });
154
+ const { args: redeemArgs } = viem.decodeFunctionData({ abi: chunk4Z6ATE44_cjs.REDEEM_DELEGATIONS_ABI, data: execution.callData });
153
155
  const [permissionContexts, modes, executionCallDatas] = redeemArgs;
154
156
  const [delegations] = viem.decodeAbiParameters(DELEGATION_ARRAY_PARAM, permissionContexts[0]);
155
157
  const adjustedDelegations = delegations.map(
@@ -157,7 +159,7 @@ function rebuildDirectUserOpForSender(fixtureTypedData, newSender) {
157
159
  );
158
160
  const adjustedPermissionContext = viem.encodeAbiParameters(DELEGATION_ARRAY_PARAM, [adjustedDelegations]);
159
161
  const adjustedRedeemCallData = viem.encodeFunctionData({
160
- abi: chunkHX34HOW4_cjs.REDEEM_DELEGATIONS_ABI,
162
+ abi: chunk4Z6ATE44_cjs.REDEEM_DELEGATIONS_ABI,
161
163
  functionName: "redeemDelegations",
162
164
  args: [[adjustedPermissionContext], modes, executionCallDatas]
163
165
  });
@@ -171,13 +173,13 @@ function rebuildDirectUserOpForSender(fixtureTypedData, newSender) {
171
173
  domain: { ...fixtureTypedData.domain, verifyingContract: newSender },
172
174
  message: { ...fixtureTypedData.message, sender: newSender, callData: adjustedCallData }
173
175
  };
174
- const payloadHash = chunkHX34HOW4_cjs.packedUserOperationHash(typedData);
176
+ const payloadHash = chunk4Z6ATE44_cjs.packedUserOperationHash(typedData);
175
177
  return { typedData, payloadHash };
176
178
  }
177
179
  function buildFundingLegUserOp(options) {
178
- const sender = chunkHX34HOW4_cjs.deriveDelegateAccountAddress(options.delegate);
180
+ const sender = chunk4Z6ATE44_cjs.deriveDelegateAccountAddress(options.delegate);
179
181
  const callData = buildExecuteCallData(
180
- chunkHX34HOW4_cjs.DELEGATION_MANAGER,
182
+ chunk4Z6ATE44_cjs.DELEGATION_MANAGER,
181
183
  0n,
182
184
  buildBoundRedeemDelegationsCallData({
183
185
  delegate: sender,
@@ -196,8 +198,58 @@ function buildFundingLegUserOp(options) {
196
198
  });
197
199
  return { typedData, payloadHash, digest: viem.hashTypedData(typedData) };
198
200
  }
201
+ var RECEIPT_DELEGATE_KEY = `0x${"77".repeat(32)}`;
202
+ var OTHER_RECEIPT_KEY = `0x${"88".repeat(32)}`;
203
+ var EIP712_DOMAIN_TYPEHASH = viem.keccak256(
204
+ viem.toBytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
205
+ );
206
+ function delegationDigest(signHash, chainId) {
207
+ const domainSeparator = viem.keccak256(
208
+ viem.encodeAbiParameters(
209
+ [{ type: "bytes32" }, { type: "bytes32" }, { type: "bytes32" }, { type: "uint256" }, { type: "address" }],
210
+ [
211
+ EIP712_DOMAIN_TYPEHASH,
212
+ viem.keccak256(viem.toBytes("DelegationManager")),
213
+ viem.keccak256(viem.toBytes("1")),
214
+ BigInt(chainId),
215
+ chunk4Z6ATE44_cjs.DELEGATION_MANAGER
216
+ ]
217
+ )
218
+ );
219
+ return viem.keccak256(viem.concatHex(["0x1901", domainSeparator, signHash]));
220
+ }
221
+ function signedErc7710Receipt(options = {}) {
222
+ const chainId = options.chainId ?? 84532;
223
+ const signHash = options.signHash ?? `0x${"5e".repeat(32)}`;
224
+ const delegate = new ethers.Wallet(options.delegateKey ?? RECEIPT_DELEGATE_KEY);
225
+ const signature = delegate.signingKey.sign(delegationDigest(signHash, chainId)).serialized;
226
+ return {
227
+ version: chunk7UTWSJC5_cjs.RECEIPT_VERSION,
228
+ paymentId: options.paymentId ?? "pay_3723",
229
+ payment: {
230
+ token: "USDC",
231
+ tokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
232
+ amount: "0.50",
233
+ amountSek: "5.25",
234
+ recipient: "0x15179876c595922999C2d5DC7c23Cc7711fE799a",
235
+ account: "0x135a9215604711AC70d970e12Caa812c53537EF4",
236
+ chainId,
237
+ settledAt: "2026-10-07T10:00:00.000Z",
238
+ resourceUrl: "https://merchant.example/resource"
239
+ },
240
+ authorization: {
241
+ delegate: delegate.address,
242
+ signHash,
243
+ signature,
244
+ signatureScheme: "eip712_delegation"
245
+ },
246
+ onChain: { txHash: `0x${"cd".repeat(32)}`, chainId }
247
+ };
248
+ }
199
249
 
200
250
  exports.DEFAULT_DELEGATOR = DEFAULT_DELEGATOR;
251
+ exports.OTHER_RECEIPT_KEY = OTHER_RECEIPT_KEY;
252
+ exports.RECEIPT_DELEGATE_KEY = RECEIPT_DELEGATE_KEY;
201
253
  exports.buildBoundDirectUserOp = buildBoundDirectUserOp;
202
254
  exports.buildBoundRedeemDelegationsCallData = buildBoundRedeemDelegationsCallData;
203
255
  exports.buildChainPermissionContext = buildChainPermissionContext;
@@ -211,5 +263,6 @@ exports.buildSelfCallCallData = buildSelfCallCallData;
211
263
  exports.buildSingleExecutionCallData = buildSingleExecutionCallData;
212
264
  exports.buildTransferExecutionCallData = buildTransferExecutionCallData;
213
265
  exports.rebuildDirectUserOpForSender = rebuildDirectUserOpForSender;
266
+ exports.signedErc7710Receipt = signedErc7710Receipt;
214
267
  //# sourceMappingURL=test-support.cjs.map
215
268
  //# sourceMappingURL=test-support.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/test-support/direct-userop.ts"],"names":["DELEGATION_TUPLE_COMPONENTS","encodeAbiParameters","encodePacked","encodeFunctionData","REDEEM_DELEGATIONS_ABI","SINGLE_DEFAULT_MODE","deriveDelegateAccountAddress","DELEGATION_MANAGER","HYBRID_DELEGATOR_DOMAIN_NAME","HYBRID_DELEGATOR_DOMAIN_VERSION","PACKED_USER_OPERATION_FIELDS","ENTRY_POINT_V07","packedUserOperationHash","decodeFunctionData","decodeAbiParameters","hashTypedData"],"mappings":"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","file":"test-support.cjs","sourcesContent":["/**\n * #3272 — a real-shaped, BOUND direct-payment `PackedUserOperation` for\n * signer tests: `sender` is the counterfactual delegate account for a given\n * owner EOA, and `callData` is `execute(DelegationManager, 0,\n * redeemDelegations(...))` with a REAL redemption shape — one non-empty\n * `Delegation`, `delegate` = the signer's own account, `delegator` = a\n * distinct treasury address, `ExecutionMode.SingleDefault`, an\n * `encodePacked(target,value,callData)` execution — mirroring\n * `packages/backend/src/rails/delegation-rail.ts`'s `prepareRedemption`.\n * Replaces the toy 2-field / empty-callData / empty-arrays fixtures the\n * allowlist correctly refuses (including the B1 empty-permission-context\n * bypass, `buildEmptyPermissionContextRedemption` below, kept ONLY to\n * reproduce that exact refusal in a test).\n *\n * Moved here from `@haven_ai/signer` by #3283 so the SDK, the signer,\n * `@haven_ai/mcp` and `mcp-server` share ONE guard-valid builder. Published\n * as the `@haven_ai/sdk/test-support` subpath only because a sibling\n * package's tests cannot import this file by relative path (each package's\n * `tsc` `rootDir` is its own `src`). Test fixtures, not a signing API:\n * nothing here signs, and nothing the SDK or signer runs imports it.\n */\nimport {\n decodeAbiParameters,\n decodeFunctionData,\n encodeAbiParameters,\n encodeFunctionData,\n encodePacked,\n hashTypedData,\n type Address,\n type Hex,\n} from 'viem'\nimport {\n ENTRY_POINT_V07,\n HYBRID_DELEGATOR_DOMAIN_NAME,\n HYBRID_DELEGATOR_DOMAIN_VERSION,\n PACKED_USER_OPERATION_FIELDS,\n packedUserOperationHash,\n} from '../userop-binding.js'\nimport { DELEGATION_MANAGER } from '../settlement-child.js'\nimport { deriveDelegateAccountAddress } from '../delegate-account.js'\nimport { DELEGATION_TUPLE_COMPONENTS, REDEEM_DELEGATIONS_ABI, SINGLE_DEFAULT_MODE } from '../redemption-guard.js'\n\nconst ZERO_BYTES32 = `0x${'00'.repeat(32)}` as const\n\n/** `Delegation.authority` sentinel for a root (unchained) delegation — `@metamask/delegation-core`'s `ROOT_AUTHORITY`. */\nconst ROOT_AUTHORITY: Hex = `0x${'ff'.repeat(32)}`\n\n/** Stand-in treasury address — distinct from any derived signer account, matching the real fixture's `delegator`. */\nexport const DEFAULT_DELEGATOR: Address = '0x98989898989898989898989898989898989898De' as Address\n\nconst DELEGATION_ARRAY_PARAM = [\n { type: 'tuple[]', components: DELEGATION_TUPLE_COMPONENTS },\n] as const\n\nconst EXECUTE_ABI = [\n {\n type: 'function',\n name: 'execute',\n inputs: [\n {\n name: '_execution',\n type: 'tuple',\n components: [\n { name: 'target', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'callData', type: 'bytes' },\n ],\n },\n ],\n outputs: [],\n stateMutability: 'payable',\n },\n] as const\n\nconst TRANSFER_ABI = [\n {\n type: 'function',\n name: 'transfer',\n inputs: [\n { name: 'to', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n] as const\n\nexport interface DelegationOverrides {\n /** The redeemer this delegation authorises — normally the signer's own derived account. */\n delegate: Address\n /** Who granted it — must differ from `delegate` for a real (non-self) delegation. */\n delegator?: Address\n authority?: Hex\n caveats?: Array<{ enforcer: Address; terms: Hex; args: Hex }>\n salt?: bigint\n signature?: Hex\n}\n\n/** A single, well-formed `Delegation` tuple — the ONE-link chain Haven's backend redeems (`delegations: [[delegation]]`). */\nexport function buildDelegation(overrides: DelegationOverrides) {\n return {\n delegate: overrides.delegate,\n delegator: overrides.delegator ?? DEFAULT_DELEGATOR,\n authority: overrides.authority ?? ROOT_AUTHORITY,\n caveats: overrides.caveats ?? [\n // A real-shaped (if inert for test purposes) TimestampEnforcer term —\n // real budget delegations always carry at least one caveat.\n { enforcer: '0x1046bb45C8d673d4ea75321280DB34899413c069' as Address, terms: `0x${'00'.repeat(32)}` as Hex, args: '0x' as Hex },\n ],\n salt: overrides.salt ?? 1n,\n signature: overrides.signature ?? (`0x${'ab'.repeat(65)}` as Hex),\n }\n}\n\n/** `abi.encode(Delegation[])` for a ONE-delegation chain — a Haven-shaped permission context. */\nexport function buildPermissionContext(delegation: ReturnType<typeof buildDelegation>): Hex {\n return encodeAbiParameters(DELEGATION_ARRAY_PARAM, [[delegation]])\n}\n\n/** `abi.encode(Delegation[])` for a MULTI-link chain (leaf first) — never emitted by Haven. */\nexport function buildChainPermissionContext(chain: ReturnType<typeof buildDelegation>[]): Hex {\n return encodeAbiParameters(DELEGATION_ARRAY_PARAM, [chain])\n}\n\n/** `abi.encode(Delegation[])` for an EMPTY chain — the exact B1 bypass shape MetaMask's DelegationManager treats as self-authorised. */\nexport function buildEmptyPermissionContext(): Hex {\n return encodeAbiParameters(DELEGATION_ARRAY_PARAM, [[]])\n}\n\n/** `encodePacked(address,uint256,bytes)` — the single-execution calldata `ExecutionMode.SingleDefault` expects. */\nexport function buildSingleExecutionCallData(target: Address, value: bigint, innerCallData: Hex): Hex {\n return encodePacked(['address', 'uint256', 'bytes'], [target, value, innerCallData])\n}\n\n/** A real-shaped ERC-20 `transfer(to, amount)` execution — what a budget redemption actually spends. */\nexport function buildTransferExecutionCallData(token: Address, to: Address, amount: bigint): Hex {\n return buildSingleExecutionCallData(\n token,\n 0n,\n encodeFunctionData({ abi: TRANSFER_ABI, functionName: 'transfer', args: [to, amount] }),\n )\n}\n\nexport interface BoundRedeemDelegationsOptions {\n /** The redeemer — normally the signer's own derived account (matches the UserOp's `sender`). */\n delegate: Address\n delegator?: Address\n caveats?: DelegationOverrides['caveats']\n /** Override the single execution's calldata entirely (default: a real-shaped ERC-20 transfer). */\n executionCallData?: Hex\n}\n\n/** `redeemDelegations([permissionContext], [SingleDefault], [executionCallData])` — the REAL, bound shape. */\nexport function buildBoundRedeemDelegationsCallData(options: BoundRedeemDelegationsOptions): Hex {\n const delegation = buildDelegation({ delegate: options.delegate, delegator: options.delegator, caveats: options.caveats })\n const permissionContext = buildPermissionContext(delegation)\n const executionCallData =\n options.executionCallData ??\n buildTransferExecutionCallData(\n '0x036CbD53842c5426634e7929541eC2318f3dCF7e' as Address, // Base Sepolia USDC, matches the real captured fixture\n '0x98ffBf30459a98FD80fAce18f519967769641F76' as Address,\n 10000n,\n )\n return encodeFunctionData({\n abi: REDEEM_DELEGATIONS_ABI,\n functionName: 'redeemDelegations',\n args: [[permissionContext], [SINGLE_DEFAULT_MODE], [executionCallData]],\n })\n}\n\n/**\n * #3272 (B1 regression): `redeemDelegations([emptyPermissionContext],\n * [SingleDefault], [selfCallCallData])` — one permission context whose\n * `Delegation[]` decodes EMPTY, paired with a self-call execution. This is\n * the exact live bypass: MetaMask's DelegationManager treats an empty chain\n * as self-authorised and runs `selfCallCallData` AS the account. Exists only\n * so a test can assert this is refused, never to build a shape any code path\n * signs.\n */\nexport function buildEmptyPermissionContextRedemption(selfCallCallData: Hex): Hex {\n return encodeFunctionData({\n abi: REDEEM_DELEGATIONS_ABI,\n functionName: 'redeemDelegations',\n args: [[buildEmptyPermissionContext()], [SINGLE_DEFAULT_MODE], [selfCallCallData]],\n })\n}\n\n/** `execute((address,uint256,bytes))` — selector `0x5c1c6dcd`. */\nexport function buildExecuteCallData(target: Address, value: bigint, innerCallData: Hex): Hex {\n return encodeFunctionData({\n abi: EXECUTE_ABI,\n functionName: 'execute',\n args: [{ target, value, callData: innerCallData }],\n })\n}\n\nexport interface BoundDirectUserOpOptions {\n /** The delegate EOA (`signer.delegateAddress`) that owns the account `sender` derives from. */\n delegate: Address\n chainId?: number | bigint | string\n /** Override the execute() target — default DELEGATION_MANAGER (the bound shape). */\n target?: Address\n /** Override the execute() value — default 0n. */\n value?: bigint\n /** Override the full message.callData (bypasses target/value/redeemDelegations construction). */\n callData?: Hex\n /** Override sender/verifyingContract directly instead of deriving it from `delegate`. */\n sender?: Address\n /** Override the redemption's delegator (default: a distinct treasury address). */\n delegator?: Address\n}\n\nexport interface BoundDirectUserOp {\n typedData: {\n domain: { name: string; version: string; chainId: number | bigint | string; verifyingContract: Address }\n types: { PackedUserOperation: Array<{ name: string; type: string }> }\n primaryType: 'PackedUserOperation'\n message: Record<string, unknown>\n }\n payloadHash: Hex\n sender: Address\n}\n\n/**\n * A real-shaped, self-consistent (correct v0.7 hash) `PackedUserOperation`.\n * By default it is fully BOUND per #3272's allowlist: `sender` is the\n * counterfactual account for `delegate`, and `callData` redeems ONE real\n * delegation (delegate = `sender`, delegator = a distinct treasury address)\n * through the DelegationManager. Override `target` / `callData` / `sender` /\n * `delegator` to build the negative-test shapes the allowlist must refuse.\n */\nexport function buildBoundDirectUserOp(options: BoundDirectUserOpOptions): BoundDirectUserOp {\n const chainId = options.chainId ?? 84532\n const sender = options.sender ?? deriveDelegateAccountAddress(options.delegate)\n const callData =\n options.callData ??\n buildExecuteCallData(\n options.target ?? (DELEGATION_MANAGER as Address),\n options.value ?? 0n,\n buildBoundRedeemDelegationsCallData({ delegate: sender, delegator: options.delegator }),\n )\n const typedData = {\n domain: {\n name: HYBRID_DELEGATOR_DOMAIN_NAME,\n version: HYBRID_DELEGATOR_DOMAIN_VERSION,\n chainId,\n verifyingContract: sender,\n },\n types: { PackedUserOperation: PACKED_USER_OPERATION_FIELDS.map((field) => ({ ...field })) },\n primaryType: 'PackedUserOperation' as const,\n message: {\n sender,\n nonce: '0',\n initCode: '0x',\n callData,\n accountGasLimits: ZERO_BYTES32,\n preVerificationGas: '0',\n gasFees: ZERO_BYTES32,\n paymasterAndData: '0x',\n entryPoint: ENTRY_POINT_V07,\n },\n }\n const payloadHash = packedUserOperationHash(typedData)\n return { typedData, payloadHash, sender }\n}\n\n/** A well-formed `execute()` self-call — `target === sender` — for the (d)/self-call negative tests. */\nexport function buildSelfCallCallData(sender: Address): Hex {\n const TRANSFER_OWNERSHIP_ABI = [\n { type: 'function', name: 'transferOwnership', inputs: [{ name: 'newOwner', type: 'address' }], outputs: [], stateMutability: 'nonpayable' },\n ] as const\n const inner = encodeFunctionData({\n abi: TRANSFER_OWNERSHIP_ABI,\n functionName: 'transferOwnership',\n args: ['0x000000000000000000000000000000000000dEaD' as Address],\n })\n return buildExecuteCallData(sender, 0n, inner)\n}\n\n/**\n * Re-target a REAL captured direct-payment UserOp (for example\n * `__fixtures__/direct-payment-userop.json`) at `newSender`: the UserOp's\n * `sender` / `verifyingContract` and the redeemed delegation's `delegate`\n * become `newSender`; the delegator, caveats, mode and execution stay the\n * production bytes. The captured fixture is bound to a delegate whose key is\n * not in the repository, so a test signs this rebuilt copy with a test key\n * whose derived account is `newSender` — proving the guard accepts the actual\n * production shape, not only this file's synthetic one.\n */\nexport function rebuildDirectUserOpForSender(\n fixtureTypedData: {\n domain: Record<string, unknown>\n types: Record<string, unknown>\n primaryType: string\n message: Record<string, unknown>\n },\n newSender: Address,\n) {\n const originalCallData = fixtureTypedData.message.callData as Hex\n const { args: executeArgs } = decodeFunctionData({ abi: EXECUTE_ABI, data: originalCallData })\n const execution = executeArgs[0] as { target: Address; value: bigint; callData: Hex }\n const { args: redeemArgs } = decodeFunctionData({ abi: REDEEM_DELEGATIONS_ABI, data: execution.callData })\n const [permissionContexts, modes, executionCallDatas] = redeemArgs as unknown as [\n readonly Hex[],\n readonly Hex[],\n readonly Hex[],\n ]\n const [delegations] = decodeAbiParameters(DELEGATION_ARRAY_PARAM, permissionContexts[0])\n const adjustedDelegations = (delegations as unknown as Array<Record<string, unknown>>).map((d, i) =>\n i === 0 ? { ...d, delegate: newSender } : d,\n )\n const adjustedPermissionContext = encodeAbiParameters(DELEGATION_ARRAY_PARAM, [adjustedDelegations as never])\n const adjustedRedeemCallData = encodeFunctionData({\n abi: REDEEM_DELEGATIONS_ABI,\n functionName: 'redeemDelegations',\n args: [[adjustedPermissionContext], modes as Hex[], executionCallDatas as Hex[]],\n })\n const adjustedCallData = encodeFunctionData({\n abi: EXECUTE_ABI,\n functionName: 'execute',\n args: [{ target: execution.target, value: execution.value, callData: adjustedRedeemCallData }],\n })\n const typedData = {\n ...fixtureTypedData,\n domain: { ...fixtureTypedData.domain, verifyingContract: newSender },\n message: { ...fixtureTypedData.message, sender: newSender, callData: adjustedCallData },\n }\n const payloadHash = packedUserOperationHash(typedData as never) as Hex\n return { typedData, payloadHash }\n}\n\nexport interface FundingLegUserOpOptions {\n /** The delegate EOA (`signer.delegateAddress`): the account is derived from it AND it is the transfer's recipient. */\n delegate: Address\n /** The quoted token (the expected context's `asset`). */\n asset: Address\n /** The quoted atomic amount (the expected context's `amount`). */\n amount: bigint | string\n chainId?: number\n /** Override the transfer recipient (default: `delegate`) — for the recipient-pin negative test. */\n recipient?: Address\n /** Override the budget delegation's caveats (e.g. a multi-KB term, for relay-size tests). */\n caveats?: DelegationOverrides['caveats']\n}\n\n/**\n * #3281: an x402 EIP-3009 bridge FUNDING LEG exactly as the backend builds it\n * (`delegation-authorize.ts` → `prepareDelegationPayment(agent, token,\n * payTo = the delegate EOA, amountRaw)` → `prepareRedemption`): the\n * direct-payment shape, whose single execution is\n * `transfer(<delegate EOA>, <amount>)` on the quoted token. Returns the typed\n * data, its v0.7 UserOp hash (the expected context's `payloadHash`) and its\n * EIP-712 digest (the expected context's `typedDataHash`).\n */\nexport function buildFundingLegUserOp(options: FundingLegUserOpOptions) {\n const sender = deriveDelegateAccountAddress(options.delegate)\n const callData = buildExecuteCallData(\n DELEGATION_MANAGER as Address,\n 0n,\n buildBoundRedeemDelegationsCallData({\n delegate: sender,\n caveats: options.caveats,\n executionCallData: buildTransferExecutionCallData(\n options.asset,\n options.recipient ?? options.delegate,\n BigInt(options.amount),\n ),\n }),\n )\n const { typedData, payloadHash } = buildBoundDirectUserOp({\n delegate: options.delegate,\n chainId: options.chainId ?? 84532,\n callData,\n })\n return { typedData, payloadHash, digest: hashTypedData(typedData as never) }\n}\n"]}
1
+ {"version":3,"sources":["../src/test-support/direct-userop.ts","../src/test-support/signed-receipt.ts"],"names":["DELEGATION_TUPLE_COMPONENTS","encodeAbiParameters","encodePacked","encodeFunctionData","REDEEM_DELEGATIONS_ABI","SINGLE_DEFAULT_MODE","deriveDelegateAccountAddress","DELEGATION_MANAGER","HYBRID_DELEGATOR_DOMAIN_NAME","HYBRID_DELEGATOR_DOMAIN_VERSION","PACKED_USER_OPERATION_FIELDS","ENTRY_POINT_V07","packedUserOperationHash","decodeFunctionData","decodeAbiParameters","hashTypedData","keccak256","toBytes","concatHex","Wallet","RECEIPT_VERSION"],"mappings":"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","file":"test-support.cjs","sourcesContent":["/**\n * #3272 — a real-shaped, BOUND direct-payment `PackedUserOperation` for\n * signer tests: `sender` is the counterfactual delegate account for a given\n * owner EOA, and `callData` is `execute(DelegationManager, 0,\n * redeemDelegations(...))` with a REAL redemption shape — one non-empty\n * `Delegation`, `delegate` = the signer's own account, `delegator` = a\n * distinct treasury address, `ExecutionMode.SingleDefault`, an\n * `encodePacked(target,value,callData)` execution — mirroring\n * `packages/backend/src/rails/delegation-rail.ts`'s `prepareRedemption`.\n * Replaces the toy 2-field / empty-callData / empty-arrays fixtures the\n * allowlist correctly refuses (including the B1 empty-permission-context\n * bypass, `buildEmptyPermissionContextRedemption` below, kept ONLY to\n * reproduce that exact refusal in a test).\n *\n * Moved here from `@haven_ai/signer` by #3283 so the SDK, the signer,\n * `@haven_ai/mcp` and `mcp-server` share ONE guard-valid builder. Published\n * as the `@haven_ai/sdk/test-support` subpath only because a sibling\n * package's tests cannot import this file by relative path (each package's\n * `tsc` `rootDir` is its own `src`). Test fixtures, not a signing API:\n * nothing here signs, and nothing the SDK or signer runs imports it.\n */\nimport {\n decodeAbiParameters,\n decodeFunctionData,\n encodeAbiParameters,\n encodeFunctionData,\n encodePacked,\n hashTypedData,\n type Address,\n type Hex,\n} from 'viem'\nimport {\n ENTRY_POINT_V07,\n HYBRID_DELEGATOR_DOMAIN_NAME,\n HYBRID_DELEGATOR_DOMAIN_VERSION,\n PACKED_USER_OPERATION_FIELDS,\n packedUserOperationHash,\n} from '../userop-binding.js'\nimport { DELEGATION_MANAGER } from '../settlement-child.js'\nimport { deriveDelegateAccountAddress } from '../delegate-account.js'\nimport { DELEGATION_TUPLE_COMPONENTS, REDEEM_DELEGATIONS_ABI, SINGLE_DEFAULT_MODE } from '../redemption-guard.js'\n\nconst ZERO_BYTES32 = `0x${'00'.repeat(32)}` as const\n\n/** `Delegation.authority` sentinel for a root (unchained) delegation — `@metamask/delegation-core`'s `ROOT_AUTHORITY`. */\nconst ROOT_AUTHORITY: Hex = `0x${'ff'.repeat(32)}`\n\n/** Stand-in treasury address — distinct from any derived signer account, matching the real fixture's `delegator`. */\nexport const DEFAULT_DELEGATOR: Address = '0x98989898989898989898989898989898989898De' as Address\n\nconst DELEGATION_ARRAY_PARAM = [\n { type: 'tuple[]', components: DELEGATION_TUPLE_COMPONENTS },\n] as const\n\nconst EXECUTE_ABI = [\n {\n type: 'function',\n name: 'execute',\n inputs: [\n {\n name: '_execution',\n type: 'tuple',\n components: [\n { name: 'target', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'callData', type: 'bytes' },\n ],\n },\n ],\n outputs: [],\n stateMutability: 'payable',\n },\n] as const\n\nconst TRANSFER_ABI = [\n {\n type: 'function',\n name: 'transfer',\n inputs: [\n { name: 'to', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ type: 'bool' }],\n stateMutability: 'nonpayable',\n },\n] as const\n\nexport interface DelegationOverrides {\n /** The redeemer this delegation authorises — normally the signer's own derived account. */\n delegate: Address\n /** Who granted it — must differ from `delegate` for a real (non-self) delegation. */\n delegator?: Address\n authority?: Hex\n caveats?: Array<{ enforcer: Address; terms: Hex; args: Hex }>\n salt?: bigint\n signature?: Hex\n}\n\n/** A single, well-formed `Delegation` tuple — the ONE-link chain Haven's backend redeems (`delegations: [[delegation]]`). */\nexport function buildDelegation(overrides: DelegationOverrides) {\n return {\n delegate: overrides.delegate,\n delegator: overrides.delegator ?? DEFAULT_DELEGATOR,\n authority: overrides.authority ?? ROOT_AUTHORITY,\n caveats: overrides.caveats ?? [\n // A real-shaped (if inert for test purposes) TimestampEnforcer term —\n // real budget delegations always carry at least one caveat.\n { enforcer: '0x1046bb45C8d673d4ea75321280DB34899413c069' as Address, terms: `0x${'00'.repeat(32)}` as Hex, args: '0x' as Hex },\n ],\n salt: overrides.salt ?? 1n,\n signature: overrides.signature ?? (`0x${'ab'.repeat(65)}` as Hex),\n }\n}\n\n/** `abi.encode(Delegation[])` for a ONE-delegation chain — a Haven-shaped permission context. */\nexport function buildPermissionContext(delegation: ReturnType<typeof buildDelegation>): Hex {\n return encodeAbiParameters(DELEGATION_ARRAY_PARAM, [[delegation]])\n}\n\n/** `abi.encode(Delegation[])` for a MULTI-link chain (leaf first) — never emitted by Haven. */\nexport function buildChainPermissionContext(chain: ReturnType<typeof buildDelegation>[]): Hex {\n return encodeAbiParameters(DELEGATION_ARRAY_PARAM, [chain])\n}\n\n/** `abi.encode(Delegation[])` for an EMPTY chain — the exact B1 bypass shape MetaMask's DelegationManager treats as self-authorised. */\nexport function buildEmptyPermissionContext(): Hex {\n return encodeAbiParameters(DELEGATION_ARRAY_PARAM, [[]])\n}\n\n/** `encodePacked(address,uint256,bytes)` — the single-execution calldata `ExecutionMode.SingleDefault` expects. */\nexport function buildSingleExecutionCallData(target: Address, value: bigint, innerCallData: Hex): Hex {\n return encodePacked(['address', 'uint256', 'bytes'], [target, value, innerCallData])\n}\n\n/** A real-shaped ERC-20 `transfer(to, amount)` execution — what a budget redemption actually spends. */\nexport function buildTransferExecutionCallData(token: Address, to: Address, amount: bigint): Hex {\n return buildSingleExecutionCallData(\n token,\n 0n,\n encodeFunctionData({ abi: TRANSFER_ABI, functionName: 'transfer', args: [to, amount] }),\n )\n}\n\nexport interface BoundRedeemDelegationsOptions {\n /** The redeemer — normally the signer's own derived account (matches the UserOp's `sender`). */\n delegate: Address\n delegator?: Address\n caveats?: DelegationOverrides['caveats']\n /** Override the single execution's calldata entirely (default: a real-shaped ERC-20 transfer). */\n executionCallData?: Hex\n}\n\n/** `redeemDelegations([permissionContext], [SingleDefault], [executionCallData])` — the REAL, bound shape. */\nexport function buildBoundRedeemDelegationsCallData(options: BoundRedeemDelegationsOptions): Hex {\n const delegation = buildDelegation({ delegate: options.delegate, delegator: options.delegator, caveats: options.caveats })\n const permissionContext = buildPermissionContext(delegation)\n const executionCallData =\n options.executionCallData ??\n buildTransferExecutionCallData(\n '0x036CbD53842c5426634e7929541eC2318f3dCF7e' as Address, // Base Sepolia USDC, matches the real captured fixture\n '0x98ffBf30459a98FD80fAce18f519967769641F76' as Address,\n 10000n,\n )\n return encodeFunctionData({\n abi: REDEEM_DELEGATIONS_ABI,\n functionName: 'redeemDelegations',\n args: [[permissionContext], [SINGLE_DEFAULT_MODE], [executionCallData]],\n })\n}\n\n/**\n * #3272 (B1 regression): `redeemDelegations([emptyPermissionContext],\n * [SingleDefault], [selfCallCallData])` — one permission context whose\n * `Delegation[]` decodes EMPTY, paired with a self-call execution. This is\n * the exact live bypass: MetaMask's DelegationManager treats an empty chain\n * as self-authorised and runs `selfCallCallData` AS the account. Exists only\n * so a test can assert this is refused, never to build a shape any code path\n * signs.\n */\nexport function buildEmptyPermissionContextRedemption(selfCallCallData: Hex): Hex {\n return encodeFunctionData({\n abi: REDEEM_DELEGATIONS_ABI,\n functionName: 'redeemDelegations',\n args: [[buildEmptyPermissionContext()], [SINGLE_DEFAULT_MODE], [selfCallCallData]],\n })\n}\n\n/** `execute((address,uint256,bytes))` — selector `0x5c1c6dcd`. */\nexport function buildExecuteCallData(target: Address, value: bigint, innerCallData: Hex): Hex {\n return encodeFunctionData({\n abi: EXECUTE_ABI,\n functionName: 'execute',\n args: [{ target, value, callData: innerCallData }],\n })\n}\n\nexport interface BoundDirectUserOpOptions {\n /** The delegate EOA (`signer.delegateAddress`) that owns the account `sender` derives from. */\n delegate: Address\n chainId?: number | bigint | string\n /** Override the execute() target — default DELEGATION_MANAGER (the bound shape). */\n target?: Address\n /** Override the execute() value — default 0n. */\n value?: bigint\n /** Override the full message.callData (bypasses target/value/redeemDelegations construction). */\n callData?: Hex\n /** Override sender/verifyingContract directly instead of deriving it from `delegate`. */\n sender?: Address\n /** Override the redemption's delegator (default: a distinct treasury address). */\n delegator?: Address\n}\n\nexport interface BoundDirectUserOp {\n typedData: {\n domain: { name: string; version: string; chainId: number | bigint | string; verifyingContract: Address }\n types: { PackedUserOperation: Array<{ name: string; type: string }> }\n primaryType: 'PackedUserOperation'\n message: Record<string, unknown>\n }\n payloadHash: Hex\n sender: Address\n}\n\n/**\n * A real-shaped, self-consistent (correct v0.7 hash) `PackedUserOperation`.\n * By default it is fully BOUND per #3272's allowlist: `sender` is the\n * counterfactual account for `delegate`, and `callData` redeems ONE real\n * delegation (delegate = `sender`, delegator = a distinct treasury address)\n * through the DelegationManager. Override `target` / `callData` / `sender` /\n * `delegator` to build the negative-test shapes the allowlist must refuse.\n */\nexport function buildBoundDirectUserOp(options: BoundDirectUserOpOptions): BoundDirectUserOp {\n const chainId = options.chainId ?? 84532\n const sender = options.sender ?? deriveDelegateAccountAddress(options.delegate)\n const callData =\n options.callData ??\n buildExecuteCallData(\n options.target ?? (DELEGATION_MANAGER as Address),\n options.value ?? 0n,\n buildBoundRedeemDelegationsCallData({ delegate: sender, delegator: options.delegator }),\n )\n const typedData = {\n domain: {\n name: HYBRID_DELEGATOR_DOMAIN_NAME,\n version: HYBRID_DELEGATOR_DOMAIN_VERSION,\n chainId,\n verifyingContract: sender,\n },\n types: { PackedUserOperation: PACKED_USER_OPERATION_FIELDS.map((field) => ({ ...field })) },\n primaryType: 'PackedUserOperation' as const,\n message: {\n sender,\n nonce: '0',\n initCode: '0x',\n callData,\n accountGasLimits: ZERO_BYTES32,\n preVerificationGas: '0',\n gasFees: ZERO_BYTES32,\n paymasterAndData: '0x',\n entryPoint: ENTRY_POINT_V07,\n },\n }\n const payloadHash = packedUserOperationHash(typedData)\n return { typedData, payloadHash, sender }\n}\n\n/** A well-formed `execute()` self-call — `target === sender` — for the (d)/self-call negative tests. */\nexport function buildSelfCallCallData(sender: Address): Hex {\n const TRANSFER_OWNERSHIP_ABI = [\n { type: 'function', name: 'transferOwnership', inputs: [{ name: 'newOwner', type: 'address' }], outputs: [], stateMutability: 'nonpayable' },\n ] as const\n const inner = encodeFunctionData({\n abi: TRANSFER_OWNERSHIP_ABI,\n functionName: 'transferOwnership',\n args: ['0x000000000000000000000000000000000000dEaD' as Address],\n })\n return buildExecuteCallData(sender, 0n, inner)\n}\n\n/**\n * Re-target a REAL captured direct-payment UserOp (for example\n * `__fixtures__/direct-payment-userop.json`) at `newSender`: the UserOp's\n * `sender` / `verifyingContract` and the redeemed delegation's `delegate`\n * become `newSender`; the delegator, caveats, mode and execution stay the\n * production bytes. The captured fixture is bound to a delegate whose key is\n * not in the repository, so a test signs this rebuilt copy with a test key\n * whose derived account is `newSender` — proving the guard accepts the actual\n * production shape, not only this file's synthetic one.\n */\nexport function rebuildDirectUserOpForSender(\n fixtureTypedData: {\n domain: Record<string, unknown>\n types: Record<string, unknown>\n primaryType: string\n message: Record<string, unknown>\n },\n newSender: Address,\n) {\n const originalCallData = fixtureTypedData.message.callData as Hex\n const { args: executeArgs } = decodeFunctionData({ abi: EXECUTE_ABI, data: originalCallData })\n const execution = executeArgs[0] as { target: Address; value: bigint; callData: Hex }\n const { args: redeemArgs } = decodeFunctionData({ abi: REDEEM_DELEGATIONS_ABI, data: execution.callData })\n const [permissionContexts, modes, executionCallDatas] = redeemArgs as unknown as [\n readonly Hex[],\n readonly Hex[],\n readonly Hex[],\n ]\n const [delegations] = decodeAbiParameters(DELEGATION_ARRAY_PARAM, permissionContexts[0])\n const adjustedDelegations = (delegations as unknown as Array<Record<string, unknown>>).map((d, i) =>\n i === 0 ? { ...d, delegate: newSender } : d,\n )\n const adjustedPermissionContext = encodeAbiParameters(DELEGATION_ARRAY_PARAM, [adjustedDelegations as never])\n const adjustedRedeemCallData = encodeFunctionData({\n abi: REDEEM_DELEGATIONS_ABI,\n functionName: 'redeemDelegations',\n args: [[adjustedPermissionContext], modes as Hex[], executionCallDatas as Hex[]],\n })\n const adjustedCallData = encodeFunctionData({\n abi: EXECUTE_ABI,\n functionName: 'execute',\n args: [{ target: execution.target, value: execution.value, callData: adjustedRedeemCallData }],\n })\n const typedData = {\n ...fixtureTypedData,\n domain: { ...fixtureTypedData.domain, verifyingContract: newSender },\n message: { ...fixtureTypedData.message, sender: newSender, callData: adjustedCallData },\n }\n const payloadHash = packedUserOperationHash(typedData as never) as Hex\n return { typedData, payloadHash }\n}\n\nexport interface FundingLegUserOpOptions {\n /** The delegate EOA (`signer.delegateAddress`): the account is derived from it AND it is the transfer's recipient. */\n delegate: Address\n /** The quoted token (the expected context's `asset`). */\n asset: Address\n /** The quoted atomic amount (the expected context's `amount`). */\n amount: bigint | string\n chainId?: number\n /** Override the transfer recipient (default: `delegate`) — for the recipient-pin negative test. */\n recipient?: Address\n /** Override the budget delegation's caveats (e.g. a multi-KB term, for relay-size tests). */\n caveats?: DelegationOverrides['caveats']\n}\n\n/**\n * #3281: an x402 EIP-3009 bridge FUNDING LEG exactly as the backend builds it\n * (`delegation-authorize.ts` → `prepareDelegationPayment(agent, token,\n * payTo = the delegate EOA, amountRaw)` → `prepareRedemption`): the\n * direct-payment shape, whose single execution is\n * `transfer(<delegate EOA>, <amount>)` on the quoted token. Returns the typed\n * data, its v0.7 UserOp hash (the expected context's `payloadHash`) and its\n * EIP-712 digest (the expected context's `typedDataHash`).\n */\nexport function buildFundingLegUserOp(options: FundingLegUserOpOptions) {\n const sender = deriveDelegateAccountAddress(options.delegate)\n const callData = buildExecuteCallData(\n DELEGATION_MANAGER as Address,\n 0n,\n buildBoundRedeemDelegationsCallData({\n delegate: sender,\n caveats: options.caveats,\n executionCallData: buildTransferExecutionCallData(\n options.asset,\n options.recipient ?? options.delegate,\n BigInt(options.amount),\n ),\n }),\n )\n const { typedData, payloadHash } = buildBoundDirectUserOp({\n delegate: options.delegate,\n chainId: options.chainId ?? 84532,\n callData,\n })\n return { typedData, payloadHash, digest: hashTypedData(typedData as never) }\n}\n","/**\n * #3723 — a REAL signed erc7710 receipt bundle for handler-level tests: the\n * delegate key signs the DelegationManager EIP-712 digest rebuilt from the\n * bundle's own `signHash` + `onChain.chainId`, exactly the math\n * `verifyPaymentReceipt` performs. So `verifyPaymentReceipt(bundle)` returns\n * `{ verified: true, verifiedOver: 'delegation_digest' }` with the DEFAULT\n * ECDSA recovery — the first positive handler-level verify fixture on the\n * MCP runtimes (no stdio-originated payment is erc7710 live: `haven_send` is\n * direct and the stdio x402 path is the eip3009 bridge).\n *\n * Published on the `@haven_ai/sdk/test-support` subpath like the UserOp\n * builder: a sibling package's tests cannot import this file by relative\n * path. Test fixtures, not a signing API: nothing the SDK or signer runs\n * imports it.\n */\nimport { Wallet } from 'ethers'\nimport { concatHex, encodeAbiParameters, keccak256, toBytes, type Hex } from 'viem'\nimport { DELEGATION_MANAGER } from '../settlement-child.js'\nimport { RECEIPT_VERSION, type PaymentReceipt } from '../receipt.js'\n\n/** A fixed delegate key so fixtures are deterministic across runs. */\nexport const RECEIPT_DELEGATE_KEY = `0x${'77'.repeat(32)}` as const\n/** A distinct key, for signer_mismatch fixtures. */\nexport const OTHER_RECEIPT_KEY = `0x${'88'.repeat(32)}` as const\n\nconst EIP712_DOMAIN_TYPEHASH = keccak256(\n toBytes('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),\n)\n\n/** Same rebuild the verifier does — mirrored here so drift turns the positive test red. */\nfunction delegationDigest(signHash: string, chainId: number): Hex {\n const domainSeparator = keccak256(\n encodeAbiParameters(\n [{ type: 'bytes32' }, { type: 'bytes32' }, { type: 'bytes32' }, { type: 'uint256' }, { type: 'address' }],\n [\n EIP712_DOMAIN_TYPEHASH,\n keccak256(toBytes('DelegationManager')),\n keccak256(toBytes('1')),\n BigInt(chainId),\n DELEGATION_MANAGER as Hex,\n ],\n ),\n )\n return keccak256(concatHex(['0x1901', domainSeparator, signHash as Hex]))\n}\n\nexport interface SignedErc7710Options {\n /** Defaults to `RECEIPT_DELEGATE_KEY`; pass `OTHER_RECEIPT_KEY` for a forged bundle. */\n delegateKey?: string\n signHash?: string\n chainId?: number\n paymentId?: string\n}\n\n/**\n * A signed erc7710 bundle whose `authorization.signature` recovers to the\n * delegate over the delegation digest — `verifyPaymentReceipt` verifies it\n * offline with the default recovery.\n */\nexport function signedErc7710Receipt(options: SignedErc7710Options = {}): PaymentReceipt {\n const chainId = options.chainId ?? 84532 // Base Sepolia — a chain the SDK pins\n const signHash = options.signHash ?? (`0x${'5e'.repeat(32)}` as const)\n const delegate = new Wallet(options.delegateKey ?? RECEIPT_DELEGATE_KEY)\n const signature = delegate.signingKey.sign(delegationDigest(signHash, chainId)).serialized\n return {\n version: RECEIPT_VERSION,\n paymentId: options.paymentId ?? 'pay_3723',\n payment: {\n token: 'USDC',\n tokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n amount: '0.50',\n amountSek: '5.25',\n recipient: '0x15179876c595922999C2d5DC7c23Cc7711fE799a',\n account: '0x135a9215604711AC70d970e12Caa812c53537EF4',\n chainId,\n settledAt: '2026-10-07T10:00:00.000Z',\n resourceUrl: 'https://merchant.example/resource',\n },\n authorization: {\n delegate: delegate.address,\n signHash,\n signature,\n signatureScheme: 'eip712_delegation',\n },\n onChain: { txHash: `0x${'cd'.repeat(32)}`, chainId },\n }\n}\n"]}
@@ -1,4 +1,6 @@
1
1
  import { Address, Hex } from 'viem';
2
+ import { P as PaymentReceipt } from './receipt-D4Roey3D.cjs';
3
+ import './types-CrszUJ7Z.cjs';
2
4
 
3
5
  /**
4
6
  * #3272 — a real-shaped, BOUND direct-payment `PackedUserOperation` for
@@ -201,4 +203,22 @@ declare function buildFundingLegUserOp(options: FundingLegUserOpOptions): {
201
203
  digest: `0x${string}`;
202
204
  };
203
205
 
204
- export { type BoundDirectUserOp, type BoundDirectUserOpOptions, type BoundRedeemDelegationsOptions, DEFAULT_DELEGATOR, type DelegationOverrides, type FundingLegUserOpOptions, buildBoundDirectUserOp, buildBoundRedeemDelegationsCallData, buildChainPermissionContext, buildDelegation, buildEmptyPermissionContext, buildEmptyPermissionContextRedemption, buildExecuteCallData, buildFundingLegUserOp, buildPermissionContext, buildSelfCallCallData, buildSingleExecutionCallData, buildTransferExecutionCallData, rebuildDirectUserOpForSender };
206
+ /** A fixed delegate key so fixtures are deterministic across runs. */
207
+ declare const RECEIPT_DELEGATE_KEY: `0x${string}`;
208
+ /** A distinct key, for signer_mismatch fixtures. */
209
+ declare const OTHER_RECEIPT_KEY: `0x${string}`;
210
+ interface SignedErc7710Options {
211
+ /** Defaults to `RECEIPT_DELEGATE_KEY`; pass `OTHER_RECEIPT_KEY` for a forged bundle. */
212
+ delegateKey?: string;
213
+ signHash?: string;
214
+ chainId?: number;
215
+ paymentId?: string;
216
+ }
217
+ /**
218
+ * A signed erc7710 bundle whose `authorization.signature` recovers to the
219
+ * delegate over the delegation digest — `verifyPaymentReceipt` verifies it
220
+ * offline with the default recovery.
221
+ */
222
+ declare function signedErc7710Receipt(options?: SignedErc7710Options): PaymentReceipt;
223
+
224
+ export { type BoundDirectUserOp, type BoundDirectUserOpOptions, type BoundRedeemDelegationsOptions, DEFAULT_DELEGATOR, type DelegationOverrides, type FundingLegUserOpOptions, OTHER_RECEIPT_KEY, RECEIPT_DELEGATE_KEY, type SignedErc7710Options, buildBoundDirectUserOp, buildBoundRedeemDelegationsCallData, buildChainPermissionContext, buildDelegation, buildEmptyPermissionContext, buildEmptyPermissionContextRedemption, buildExecuteCallData, buildFundingLegUserOp, buildPermissionContext, buildSelfCallCallData, buildSingleExecutionCallData, buildTransferExecutionCallData, rebuildDirectUserOpForSender, signedErc7710Receipt };
@@ -1,4 +1,6 @@
1
1
  import { Address, Hex } from 'viem';
2
+ import { P as PaymentReceipt } from './receipt-WkXHZGbu.js';
3
+ import './types-CrszUJ7Z.js';
2
4
 
3
5
  /**
4
6
  * #3272 — a real-shaped, BOUND direct-payment `PackedUserOperation` for
@@ -201,4 +203,22 @@ declare function buildFundingLegUserOp(options: FundingLegUserOpOptions): {
201
203
  digest: `0x${string}`;
202
204
  };
203
205
 
204
- export { type BoundDirectUserOp, type BoundDirectUserOpOptions, type BoundRedeemDelegationsOptions, DEFAULT_DELEGATOR, type DelegationOverrides, type FundingLegUserOpOptions, buildBoundDirectUserOp, buildBoundRedeemDelegationsCallData, buildChainPermissionContext, buildDelegation, buildEmptyPermissionContext, buildEmptyPermissionContextRedemption, buildExecuteCallData, buildFundingLegUserOp, buildPermissionContext, buildSelfCallCallData, buildSingleExecutionCallData, buildTransferExecutionCallData, rebuildDirectUserOpForSender };
206
+ /** A fixed delegate key so fixtures are deterministic across runs. */
207
+ declare const RECEIPT_DELEGATE_KEY: `0x${string}`;
208
+ /** A distinct key, for signer_mismatch fixtures. */
209
+ declare const OTHER_RECEIPT_KEY: `0x${string}`;
210
+ interface SignedErc7710Options {
211
+ /** Defaults to `RECEIPT_DELEGATE_KEY`; pass `OTHER_RECEIPT_KEY` for a forged bundle. */
212
+ delegateKey?: string;
213
+ signHash?: string;
214
+ chainId?: number;
215
+ paymentId?: string;
216
+ }
217
+ /**
218
+ * A signed erc7710 bundle whose `authorization.signature` recovers to the
219
+ * delegate over the delegation digest — `verifyPaymentReceipt` verifies it
220
+ * offline with the default recovery.
221
+ */
222
+ declare function signedErc7710Receipt(options?: SignedErc7710Options): PaymentReceipt;
223
+
224
+ export { type BoundDirectUserOp, type BoundDirectUserOpOptions, type BoundRedeemDelegationsOptions, DEFAULT_DELEGATOR, type DelegationOverrides, type FundingLegUserOpOptions, OTHER_RECEIPT_KEY, RECEIPT_DELEGATE_KEY, type SignedErc7710Options, buildBoundDirectUserOp, buildBoundRedeemDelegationsCallData, buildChainPermissionContext, buildDelegation, buildEmptyPermissionContext, buildEmptyPermissionContextRedemption, buildExecuteCallData, buildFundingLegUserOp, buildPermissionContext, buildSelfCallCallData, buildSingleExecutionCallData, buildTransferExecutionCallData, rebuildDirectUserOpForSender, signedErc7710Receipt };