@bankofai/x402-evm 2.6.0-beta.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 (65) hide show
  1. package/README.md +184 -0
  2. package/dist/cjs/exact/client/index.d.ts +53 -0
  3. package/dist/cjs/exact/client/index.js +661 -0
  4. package/dist/cjs/exact/client/index.js.map +1 -0
  5. package/dist/cjs/exact/facilitator/index.d.ts +121 -0
  6. package/dist/cjs/exact/facilitator/index.js +1458 -0
  7. package/dist/cjs/exact/facilitator/index.js.map +1 -0
  8. package/dist/cjs/exact/server/index.d.ts +125 -0
  9. package/dist/cjs/exact/server/index.js +229 -0
  10. package/dist/cjs/exact/server/index.js.map +1 -0
  11. package/dist/cjs/exact/v1/client/index.d.ts +37 -0
  12. package/dist/cjs/exact/v1/client/index.js +175 -0
  13. package/dist/cjs/exact/v1/client/index.js.map +1 -0
  14. package/dist/cjs/exact/v1/facilitator/index.d.ts +62 -0
  15. package/dist/cjs/exact/v1/facilitator/index.js +436 -0
  16. package/dist/cjs/exact/v1/facilitator/index.js.map +1 -0
  17. package/dist/cjs/exact_permit/client/index.d.ts +57 -0
  18. package/dist/cjs/exact_permit/client/index.js +223 -0
  19. package/dist/cjs/exact_permit/client/index.js.map +1 -0
  20. package/dist/cjs/exact_permit/facilitator/index.d.ts +82 -0
  21. package/dist/cjs/exact_permit/facilitator/index.js +437 -0
  22. package/dist/cjs/exact_permit/facilitator/index.js.map +1 -0
  23. package/dist/cjs/exact_permit/server/index.d.ts +71 -0
  24. package/dist/cjs/exact_permit/server/index.js +186 -0
  25. package/dist/cjs/exact_permit/server/index.js.map +1 -0
  26. package/dist/cjs/index.d.ts +76 -0
  27. package/dist/cjs/index.js +779 -0
  28. package/dist/cjs/index.js.map +1 -0
  29. package/dist/cjs/permit2-CpuKY2-F.d.ts +509 -0
  30. package/dist/cjs/permit2-D65OQ5yU.d.ts +517 -0
  31. package/dist/cjs/permit2-DvsTlAyj.d.ts +531 -0
  32. package/dist/cjs/signer-DC81R8wQ.d.ts +161 -0
  33. package/dist/cjs/v1/index.d.ts +39 -0
  34. package/dist/cjs/v1/index.js +181 -0
  35. package/dist/cjs/v1/index.js.map +1 -0
  36. package/dist/esm/chunk-4JGB4GDD.mjs +425 -0
  37. package/dist/esm/chunk-4JGB4GDD.mjs.map +1 -0
  38. package/dist/esm/chunk-TKN5V2BV.mjs +13 -0
  39. package/dist/esm/chunk-TKN5V2BV.mjs.map +1 -0
  40. package/dist/esm/chunk-UDKSVWSE.mjs +716 -0
  41. package/dist/esm/chunk-UDKSVWSE.mjs.map +1 -0
  42. package/dist/esm/exact/client/index.d.mts +53 -0
  43. package/dist/esm/exact/client/index.mjs +17 -0
  44. package/dist/esm/exact/client/index.mjs.map +1 -0
  45. package/dist/esm/exact/facilitator/index.d.mts +121 -0
  46. package/dist/esm/exact/facilitator/index.mjs +876 -0
  47. package/dist/esm/exact/facilitator/index.mjs.map +1 -0
  48. package/dist/esm/exact/server/index.d.mts +125 -0
  49. package/dist/esm/exact/server/index.mjs +201 -0
  50. package/dist/esm/exact/server/index.mjs.map +1 -0
  51. package/dist/esm/exact/v1/client/index.d.mts +37 -0
  52. package/dist/esm/exact/v1/client/index.mjs +7 -0
  53. package/dist/esm/exact/v1/client/index.mjs.map +1 -0
  54. package/dist/esm/exact/v1/facilitator/index.d.mts +62 -0
  55. package/dist/esm/exact/v1/facilitator/index.mjs +7 -0
  56. package/dist/esm/exact/v1/facilitator/index.mjs.map +1 -0
  57. package/dist/esm/index.d.mts +76 -0
  58. package/dist/esm/index.mjs +71 -0
  59. package/dist/esm/index.mjs.map +1 -0
  60. package/dist/esm/permit2-D7ni3g6s.d.mts +509 -0
  61. package/dist/esm/signer-DC81R8wQ.d.mts +161 -0
  62. package/dist/esm/v1/index.d.mts +39 -0
  63. package/dist/esm/v1/index.mjs +13 -0
  64. package/dist/esm/v1/index.mjs.map +1 -0
  65. package/package.json +128 -0
@@ -0,0 +1,1458 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/exact/facilitator/index.ts
21
+ var facilitator_exports = {};
22
+ __export(facilitator_exports, {
23
+ ExactEvmScheme: () => ExactEvmScheme,
24
+ registerExactEvmScheme: () => registerExactEvmScheme
25
+ });
26
+ module.exports = __toCommonJS(facilitator_exports);
27
+
28
+ // src/types.ts
29
+ function isPermit2Payload(payload) {
30
+ return "permit2Authorization" in payload;
31
+ }
32
+
33
+ // src/exact/facilitator/eip3009.ts
34
+ var import_viem2 = require("viem");
35
+
36
+ // src/constants.ts
37
+ var authorizationTypes = {
38
+ TransferWithAuthorization: [
39
+ { name: "from", type: "address" },
40
+ { name: "to", type: "address" },
41
+ { name: "value", type: "uint256" },
42
+ { name: "validAfter", type: "uint256" },
43
+ { name: "validBefore", type: "uint256" },
44
+ { name: "nonce", type: "bytes32" }
45
+ ]
46
+ };
47
+ var permit2WitnessTypes = {
48
+ PermitWitnessTransferFrom: [
49
+ { name: "permitted", type: "TokenPermissions" },
50
+ { name: "spender", type: "address" },
51
+ { name: "nonce", type: "uint256" },
52
+ { name: "deadline", type: "uint256" },
53
+ { name: "witness", type: "Witness" }
54
+ ],
55
+ TokenPermissions: [
56
+ { name: "token", type: "address" },
57
+ { name: "amount", type: "uint256" }
58
+ ],
59
+ Witness: [
60
+ { name: "to", type: "address" },
61
+ { name: "validAfter", type: "uint256" }
62
+ ]
63
+ };
64
+ var eip3009ABI = [
65
+ {
66
+ inputs: [
67
+ { name: "from", type: "address" },
68
+ { name: "to", type: "address" },
69
+ { name: "value", type: "uint256" },
70
+ { name: "validAfter", type: "uint256" },
71
+ { name: "validBefore", type: "uint256" },
72
+ { name: "nonce", type: "bytes32" },
73
+ { name: "v", type: "uint8" },
74
+ { name: "r", type: "bytes32" },
75
+ { name: "s", type: "bytes32" }
76
+ ],
77
+ name: "transferWithAuthorization",
78
+ outputs: [],
79
+ stateMutability: "nonpayable",
80
+ type: "function"
81
+ },
82
+ {
83
+ inputs: [
84
+ { name: "from", type: "address" },
85
+ { name: "to", type: "address" },
86
+ { name: "value", type: "uint256" },
87
+ { name: "validAfter", type: "uint256" },
88
+ { name: "validBefore", type: "uint256" },
89
+ { name: "nonce", type: "bytes32" },
90
+ { name: "signature", type: "bytes" }
91
+ ],
92
+ name: "transferWithAuthorization",
93
+ outputs: [],
94
+ stateMutability: "nonpayable",
95
+ type: "function"
96
+ },
97
+ {
98
+ inputs: [{ name: "account", type: "address" }],
99
+ name: "balanceOf",
100
+ outputs: [{ name: "", type: "uint256" }],
101
+ stateMutability: "view",
102
+ type: "function"
103
+ },
104
+ {
105
+ inputs: [],
106
+ name: "version",
107
+ outputs: [{ name: "", type: "string" }],
108
+ stateMutability: "view",
109
+ type: "function"
110
+ }
111
+ ];
112
+ var erc20ApproveAbi = [
113
+ {
114
+ type: "function",
115
+ name: "approve",
116
+ inputs: [
117
+ { name: "spender", type: "address" },
118
+ { name: "amount", type: "uint256" }
119
+ ],
120
+ outputs: [{ type: "bool" }],
121
+ stateMutability: "nonpayable"
122
+ }
123
+ ];
124
+ var erc20AllowanceAbi = [
125
+ {
126
+ type: "function",
127
+ name: "allowance",
128
+ inputs: [
129
+ { name: "owner", type: "address" },
130
+ { name: "spender", type: "address" }
131
+ ],
132
+ outputs: [{ type: "uint256" }],
133
+ stateMutability: "view"
134
+ }
135
+ ];
136
+ var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
137
+ var x402ExactPermit2ProxyAddress = "0xEe38Ec718255fe78e9D16aCC0e1183C731679b23";
138
+ var permit2WitnessABIComponents = [
139
+ { name: "to", type: "address", internalType: "address" },
140
+ { name: "validAfter", type: "uint256", internalType: "uint256" }
141
+ ];
142
+ var x402ExactPermit2ProxyABI = [
143
+ {
144
+ type: "function",
145
+ name: "PERMIT2",
146
+ inputs: [],
147
+ outputs: [{ name: "", type: "address", internalType: "contract ISignatureTransfer" }],
148
+ stateMutability: "view"
149
+ },
150
+ {
151
+ type: "function",
152
+ name: "WITNESS_TYPEHASH",
153
+ inputs: [],
154
+ outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
155
+ stateMutability: "view"
156
+ },
157
+ {
158
+ type: "function",
159
+ name: "WITNESS_TYPE_STRING",
160
+ inputs: [],
161
+ outputs: [{ name: "", type: "string", internalType: "string" }],
162
+ stateMutability: "view"
163
+ },
164
+ {
165
+ type: "function",
166
+ name: "settle",
167
+ inputs: [
168
+ {
169
+ name: "permit",
170
+ type: "tuple",
171
+ internalType: "struct ISignatureTransfer.PermitTransferFrom",
172
+ components: [
173
+ {
174
+ name: "permitted",
175
+ type: "tuple",
176
+ internalType: "struct ISignatureTransfer.TokenPermissions",
177
+ components: [
178
+ { name: "token", type: "address", internalType: "address" },
179
+ { name: "amount", type: "uint256", internalType: "uint256" }
180
+ ]
181
+ },
182
+ { name: "nonce", type: "uint256", internalType: "uint256" },
183
+ { name: "deadline", type: "uint256", internalType: "uint256" }
184
+ ]
185
+ },
186
+ { name: "owner", type: "address", internalType: "address" },
187
+ {
188
+ name: "witness",
189
+ type: "tuple",
190
+ internalType: "struct x402ExactPermit2Proxy.Witness",
191
+ components: permit2WitnessABIComponents
192
+ },
193
+ { name: "signature", type: "bytes", internalType: "bytes" }
194
+ ],
195
+ outputs: [],
196
+ stateMutability: "nonpayable"
197
+ },
198
+ {
199
+ type: "function",
200
+ name: "settleWithPermit",
201
+ inputs: [
202
+ {
203
+ name: "permit2612",
204
+ type: "tuple",
205
+ internalType: "struct x402ExactPermit2Proxy.EIP2612Permit",
206
+ components: [
207
+ { name: "value", type: "uint256", internalType: "uint256" },
208
+ { name: "deadline", type: "uint256", internalType: "uint256" },
209
+ { name: "r", type: "bytes32", internalType: "bytes32" },
210
+ { name: "s", type: "bytes32", internalType: "bytes32" },
211
+ { name: "v", type: "uint8", internalType: "uint8" }
212
+ ]
213
+ },
214
+ {
215
+ name: "permit",
216
+ type: "tuple",
217
+ internalType: "struct ISignatureTransfer.PermitTransferFrom",
218
+ components: [
219
+ {
220
+ name: "permitted",
221
+ type: "tuple",
222
+ internalType: "struct ISignatureTransfer.TokenPermissions",
223
+ components: [
224
+ { name: "token", type: "address", internalType: "address" },
225
+ { name: "amount", type: "uint256", internalType: "uint256" }
226
+ ]
227
+ },
228
+ { name: "nonce", type: "uint256", internalType: "uint256" },
229
+ { name: "deadline", type: "uint256", internalType: "uint256" }
230
+ ]
231
+ },
232
+ { name: "owner", type: "address", internalType: "address" },
233
+ {
234
+ name: "witness",
235
+ type: "tuple",
236
+ internalType: "struct x402ExactPermit2Proxy.Witness",
237
+ components: permit2WitnessABIComponents
238
+ },
239
+ { name: "signature", type: "bytes", internalType: "bytes" }
240
+ ],
241
+ outputs: [],
242
+ stateMutability: "nonpayable"
243
+ },
244
+ { type: "event", name: "Settled", inputs: [], anonymous: false },
245
+ { type: "event", name: "SettledWithPermit", inputs: [], anonymous: false },
246
+ { type: "error", name: "InvalidAmount", inputs: [] },
247
+ { type: "error", name: "InvalidDestination", inputs: [] },
248
+ { type: "error", name: "InvalidOwner", inputs: [] },
249
+ { type: "error", name: "InvalidPermit2Address", inputs: [] },
250
+ { type: "error", name: "PaymentTooEarly", inputs: [] },
251
+ { type: "error", name: "Permit2612AmountMismatch", inputs: [] },
252
+ { type: "error", name: "ReentrancyGuardReentrantCall", inputs: [] }
253
+ ];
254
+
255
+ // src/utils.ts
256
+ var import_viem = require("viem");
257
+ function getEvmChainId(network) {
258
+ if (network.startsWith("eip155:")) {
259
+ const idStr = network.split(":")[1];
260
+ const chainId = parseInt(idStr, 10);
261
+ if (isNaN(chainId)) {
262
+ throw new Error(`Invalid CAIP-2 chain ID: ${network}`);
263
+ }
264
+ return chainId;
265
+ }
266
+ throw new Error(`Unsupported network format: ${network} (expected eip155:CHAIN_ID)`);
267
+ }
268
+
269
+ // src/exact/facilitator/eip3009.ts
270
+ async function verifyEIP3009(signer, payload, requirements, eip3009Payload) {
271
+ const payer = eip3009Payload.authorization.from;
272
+ if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") {
273
+ return {
274
+ isValid: false,
275
+ invalidReason: "unsupported_scheme",
276
+ payer
277
+ };
278
+ }
279
+ if (!requirements.extra?.name || !requirements.extra?.version) {
280
+ return {
281
+ isValid: false,
282
+ invalidReason: "missing_eip712_domain",
283
+ payer
284
+ };
285
+ }
286
+ const { name, version } = requirements.extra;
287
+ const erc20Address = (0, import_viem2.getAddress)(requirements.asset);
288
+ if (payload.accepted.network !== requirements.network) {
289
+ return {
290
+ isValid: false,
291
+ invalidReason: "network_mismatch",
292
+ payer
293
+ };
294
+ }
295
+ const permitTypedData = {
296
+ types: authorizationTypes,
297
+ primaryType: "TransferWithAuthorization",
298
+ domain: {
299
+ name,
300
+ version,
301
+ chainId: getEvmChainId(requirements.network),
302
+ verifyingContract: erc20Address
303
+ },
304
+ message: {
305
+ from: eip3009Payload.authorization.from,
306
+ to: eip3009Payload.authorization.to,
307
+ value: BigInt(eip3009Payload.authorization.value),
308
+ validAfter: BigInt(eip3009Payload.authorization.validAfter),
309
+ validBefore: BigInt(eip3009Payload.authorization.validBefore),
310
+ nonce: eip3009Payload.authorization.nonce
311
+ }
312
+ };
313
+ try {
314
+ const recoveredAddress = await signer.verifyTypedData({
315
+ address: eip3009Payload.authorization.from,
316
+ ...permitTypedData,
317
+ signature: eip3009Payload.signature
318
+ });
319
+ if (!recoveredAddress) {
320
+ return {
321
+ isValid: false,
322
+ invalidReason: "invalid_exact_evm_payload_signature",
323
+ payer
324
+ };
325
+ }
326
+ } catch {
327
+ const signature = eip3009Payload.signature;
328
+ const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
329
+ const isSmartWallet = signatureLength > 130;
330
+ if (isSmartWallet) {
331
+ const payerAddress = eip3009Payload.authorization.from;
332
+ const bytecode = await signer.getCode({ address: payerAddress });
333
+ if (!bytecode || bytecode === "0x") {
334
+ const erc6492Data = (0, import_viem2.parseErc6492Signature)(signature);
335
+ const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem2.isAddressEqual)(erc6492Data.address, "0x0000000000000000000000000000000000000000");
336
+ if (!hasDeploymentInfo) {
337
+ return {
338
+ isValid: false,
339
+ invalidReason: "invalid_exact_evm_payload_undeployed_smart_wallet",
340
+ payer: payerAddress
341
+ };
342
+ }
343
+ } else {
344
+ return {
345
+ isValid: false,
346
+ invalidReason: "invalid_exact_evm_payload_signature",
347
+ payer
348
+ };
349
+ }
350
+ } else {
351
+ return {
352
+ isValid: false,
353
+ invalidReason: "invalid_exact_evm_payload_signature",
354
+ payer
355
+ };
356
+ }
357
+ }
358
+ if ((0, import_viem2.getAddress)(eip3009Payload.authorization.to) !== (0, import_viem2.getAddress)(requirements.payTo)) {
359
+ return {
360
+ isValid: false,
361
+ invalidReason: "invalid_exact_evm_payload_recipient_mismatch",
362
+ payer
363
+ };
364
+ }
365
+ const now = Math.floor(Date.now() / 1e3);
366
+ if (BigInt(eip3009Payload.authorization.validBefore) < BigInt(now + 6)) {
367
+ return {
368
+ isValid: false,
369
+ invalidReason: "invalid_exact_evm_payload_authorization_valid_before",
370
+ payer
371
+ };
372
+ }
373
+ if (BigInt(eip3009Payload.authorization.validAfter) > BigInt(now)) {
374
+ return {
375
+ isValid: false,
376
+ invalidReason: "invalid_exact_evm_payload_authorization_valid_after",
377
+ payer
378
+ };
379
+ }
380
+ try {
381
+ const balance = await signer.readContract({
382
+ address: erc20Address,
383
+ abi: eip3009ABI,
384
+ functionName: "balanceOf",
385
+ args: [eip3009Payload.authorization.from]
386
+ });
387
+ if (BigInt(balance) < BigInt(requirements.amount)) {
388
+ return {
389
+ isValid: false,
390
+ invalidReason: "insufficient_funds",
391
+ invalidMessage: `Insufficient funds to complete the payment. Required: ${requirements.amount} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,
392
+ payer
393
+ };
394
+ }
395
+ } catch {
396
+ }
397
+ if (BigInt(eip3009Payload.authorization.value) !== BigInt(requirements.amount)) {
398
+ return {
399
+ isValid: false,
400
+ invalidReason: "invalid_exact_evm_payload_authorization_value_mismatch",
401
+ payer
402
+ };
403
+ }
404
+ return {
405
+ isValid: true,
406
+ invalidReason: void 0,
407
+ payer
408
+ };
409
+ }
410
+ async function settleEIP3009(signer, payload, requirements, eip3009Payload, config) {
411
+ const payer = eip3009Payload.authorization.from;
412
+ const valid = await verifyEIP3009(signer, payload, requirements, eip3009Payload);
413
+ if (!valid.isValid) {
414
+ return {
415
+ success: false,
416
+ network: payload.accepted.network,
417
+ transaction: "",
418
+ errorReason: valid.invalidReason ?? "invalid_scheme",
419
+ payer
420
+ };
421
+ }
422
+ try {
423
+ const parseResult = (0, import_viem2.parseErc6492Signature)(eip3009Payload.signature);
424
+ const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;
425
+ if (config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem2.isAddressEqual)(factoryAddress, "0x0000000000000000000000000000000000000000")) {
426
+ const bytecode = await signer.getCode({ address: payer });
427
+ if (!bytecode || bytecode === "0x") {
428
+ const deployTx = await signer.sendTransaction({
429
+ to: factoryAddress,
430
+ data: factoryCalldata
431
+ });
432
+ await signer.waitForTransactionReceipt({ hash: deployTx });
433
+ }
434
+ }
435
+ const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
436
+ const isECDSA = signatureLength === 130;
437
+ let tx;
438
+ if (isECDSA) {
439
+ const parsedSig = (0, import_viem2.parseSignature)(signature);
440
+ tx = await signer.writeContract({
441
+ address: (0, import_viem2.getAddress)(requirements.asset),
442
+ abi: eip3009ABI,
443
+ functionName: "transferWithAuthorization",
444
+ args: [
445
+ (0, import_viem2.getAddress)(eip3009Payload.authorization.from),
446
+ (0, import_viem2.getAddress)(eip3009Payload.authorization.to),
447
+ BigInt(eip3009Payload.authorization.value),
448
+ BigInt(eip3009Payload.authorization.validAfter),
449
+ BigInt(eip3009Payload.authorization.validBefore),
450
+ eip3009Payload.authorization.nonce,
451
+ parsedSig.v || parsedSig.yParity,
452
+ parsedSig.r,
453
+ parsedSig.s
454
+ ]
455
+ });
456
+ } else {
457
+ tx = await signer.writeContract({
458
+ address: (0, import_viem2.getAddress)(requirements.asset),
459
+ abi: eip3009ABI,
460
+ functionName: "transferWithAuthorization",
461
+ args: [
462
+ (0, import_viem2.getAddress)(eip3009Payload.authorization.from),
463
+ (0, import_viem2.getAddress)(eip3009Payload.authorization.to),
464
+ BigInt(eip3009Payload.authorization.value),
465
+ BigInt(eip3009Payload.authorization.validAfter),
466
+ BigInt(eip3009Payload.authorization.validBefore),
467
+ eip3009Payload.authorization.nonce,
468
+ signature
469
+ ]
470
+ });
471
+ }
472
+ const receipt = await signer.waitForTransactionReceipt({ hash: tx });
473
+ if (receipt.status !== "success") {
474
+ return {
475
+ success: false,
476
+ errorReason: "invalid_transaction_state",
477
+ transaction: tx,
478
+ network: payload.accepted.network,
479
+ payer
480
+ };
481
+ }
482
+ return {
483
+ success: true,
484
+ transaction: tx,
485
+ network: payload.accepted.network,
486
+ payer
487
+ };
488
+ } catch {
489
+ return {
490
+ success: false,
491
+ errorReason: "transaction_failed",
492
+ transaction: "",
493
+ network: payload.accepted.network,
494
+ payer
495
+ };
496
+ }
497
+ }
498
+
499
+ // src/exact/facilitator/permit2.ts
500
+ var import_x402_extensions2 = require("@bankofai/x402-extensions");
501
+ var import_viem4 = require("viem");
502
+
503
+ // src/exact/facilitator/errors.ts
504
+ var ErrPermit2InvalidSignature = "invalid_permit2_signature";
505
+ var ErrPermit2InvalidAmount = "permit2_invalid_amount";
506
+ var ErrPermit2InvalidDestination = "permit2_invalid_destination";
507
+ var ErrPermit2InvalidOwner = "permit2_invalid_owner";
508
+ var ErrPermit2PaymentTooEarly = "permit2_payment_too_early";
509
+ var ErrPermit2InvalidNonce = "permit2_invalid_nonce";
510
+ var ErrPermit2612AmountMismatch = "permit2_2612_amount_mismatch";
511
+ var ErrErc20ApprovalInvalidFormat = "invalid_erc20_approval_extension_format";
512
+ var ErrErc20ApprovalFromMismatch = "erc20_approval_from_mismatch";
513
+ var ErrErc20ApprovalAssetMismatch = "erc20_approval_asset_mismatch";
514
+ var ErrErc20ApprovalSpenderNotPermit2 = "erc20_approval_spender_not_permit2";
515
+ var ErrErc20ApprovalTxWrongTarget = "erc20_approval_tx_wrong_target";
516
+ var ErrErc20ApprovalTxWrongSelector = "erc20_approval_tx_wrong_selector";
517
+ var ErrErc20ApprovalTxWrongSpender = "erc20_approval_tx_wrong_spender";
518
+ var ErrErc20ApprovalTxInvalidCalldata = "erc20_approval_tx_invalid_calldata";
519
+ var ErrErc20ApprovalTxSignerMismatch = "erc20_approval_tx_signer_mismatch";
520
+ var ErrErc20ApprovalTxInvalidSignature = "erc20_approval_tx_invalid_signature";
521
+ var ErrErc20ApprovalTxParseFailed = "erc20_approval_tx_parse_failed";
522
+
523
+ // src/exact/facilitator/erc20approval.ts
524
+ var import_viem3 = require("viem");
525
+ var import_x402_extensions = require("@bankofai/x402-extensions");
526
+ var APPROVE_SELECTOR = "0x095ea7b3";
527
+ async function validateErc20ApprovalForPayment(info, payer, tokenAddress) {
528
+ if (!(0, import_x402_extensions.validateErc20ApprovalGasSponsoringInfo)(info)) {
529
+ return {
530
+ isValid: false,
531
+ invalidReason: ErrErc20ApprovalInvalidFormat,
532
+ invalidMessage: "ERC-20 approval extension info failed schema validation"
533
+ };
534
+ }
535
+ if ((0, import_viem3.getAddress)(info.from) !== (0, import_viem3.getAddress)(payer)) {
536
+ return {
537
+ isValid: false,
538
+ invalidReason: ErrErc20ApprovalFromMismatch,
539
+ invalidMessage: `Expected from=${payer}, got ${info.from}`
540
+ };
541
+ }
542
+ if ((0, import_viem3.getAddress)(info.asset) !== tokenAddress) {
543
+ return {
544
+ isValid: false,
545
+ invalidReason: ErrErc20ApprovalAssetMismatch,
546
+ invalidMessage: `Expected asset=${tokenAddress}, got ${info.asset}`
547
+ };
548
+ }
549
+ if ((0, import_viem3.getAddress)(info.spender) !== (0, import_viem3.getAddress)(PERMIT2_ADDRESS)) {
550
+ return {
551
+ isValid: false,
552
+ invalidReason: ErrErc20ApprovalSpenderNotPermit2,
553
+ invalidMessage: `Expected spender=${PERMIT2_ADDRESS}, got ${info.spender}`
554
+ };
555
+ }
556
+ try {
557
+ const serializedTx = info.signedTransaction;
558
+ const tx = (0, import_viem3.parseTransaction)(serializedTx);
559
+ if (!tx.to || (0, import_viem3.getAddress)(tx.to) !== tokenAddress) {
560
+ return {
561
+ isValid: false,
562
+ invalidReason: ErrErc20ApprovalTxWrongTarget,
563
+ invalidMessage: `Transaction targets ${tx.to ?? "null"}, expected ${tokenAddress}`
564
+ };
565
+ }
566
+ const data = tx.data ?? "0x";
567
+ if (!data.startsWith(APPROVE_SELECTOR)) {
568
+ return {
569
+ isValid: false,
570
+ invalidReason: ErrErc20ApprovalTxWrongSelector,
571
+ invalidMessage: `Transaction calldata does not start with approve() selector ${APPROVE_SELECTOR}`
572
+ };
573
+ }
574
+ try {
575
+ const decoded = (0, import_viem3.decodeFunctionData)({
576
+ abi: erc20ApproveAbi,
577
+ data
578
+ });
579
+ const calldataSpender = (0, import_viem3.getAddress)(decoded.args[0]);
580
+ if (calldataSpender !== (0, import_viem3.getAddress)(PERMIT2_ADDRESS)) {
581
+ return {
582
+ isValid: false,
583
+ invalidReason: ErrErc20ApprovalTxWrongSpender,
584
+ invalidMessage: `approve() spender is ${calldataSpender}, expected Permit2 ${PERMIT2_ADDRESS}`
585
+ };
586
+ }
587
+ } catch {
588
+ return {
589
+ isValid: false,
590
+ invalidReason: ErrErc20ApprovalTxInvalidCalldata,
591
+ invalidMessage: "Failed to decode approve() calldata from the signed transaction"
592
+ };
593
+ }
594
+ try {
595
+ const recoveredAddress = await (0, import_viem3.recoverTransactionAddress)({
596
+ serializedTransaction: serializedTx
597
+ });
598
+ if ((0, import_viem3.getAddress)(recoveredAddress) !== (0, import_viem3.getAddress)(payer)) {
599
+ return {
600
+ isValid: false,
601
+ invalidReason: ErrErc20ApprovalTxSignerMismatch,
602
+ invalidMessage: `Transaction signed by ${recoveredAddress}, expected payer ${payer}`
603
+ };
604
+ }
605
+ } catch {
606
+ return {
607
+ isValid: false,
608
+ invalidReason: ErrErc20ApprovalTxInvalidSignature,
609
+ invalidMessage: "Failed to recover signer from the signed transaction"
610
+ };
611
+ }
612
+ } catch {
613
+ return {
614
+ isValid: false,
615
+ invalidReason: ErrErc20ApprovalTxParseFailed,
616
+ invalidMessage: "Failed to parse the signed transaction"
617
+ };
618
+ }
619
+ return { isValid: true };
620
+ }
621
+
622
+ // src/exact/facilitator/permit2.ts
623
+ async function verifyPermit2(signer, payload, requirements, permit2Payload, context) {
624
+ const payer = permit2Payload.permit2Authorization.from;
625
+ if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") {
626
+ return {
627
+ isValid: false,
628
+ invalidReason: "unsupported_scheme",
629
+ payer
630
+ };
631
+ }
632
+ if (payload.accepted.network !== requirements.network) {
633
+ return {
634
+ isValid: false,
635
+ invalidReason: "network_mismatch",
636
+ payer
637
+ };
638
+ }
639
+ const chainId = getEvmChainId(requirements.network);
640
+ const tokenAddress = (0, import_viem4.getAddress)(requirements.asset);
641
+ if ((0, import_viem4.getAddress)(permit2Payload.permit2Authorization.spender) !== (0, import_viem4.getAddress)(x402ExactPermit2ProxyAddress)) {
642
+ return {
643
+ isValid: false,
644
+ invalidReason: "invalid_permit2_spender",
645
+ payer
646
+ };
647
+ }
648
+ if ((0, import_viem4.getAddress)(permit2Payload.permit2Authorization.witness.to) !== (0, import_viem4.getAddress)(requirements.payTo)) {
649
+ return {
650
+ isValid: false,
651
+ invalidReason: "invalid_permit2_recipient_mismatch",
652
+ payer
653
+ };
654
+ }
655
+ const now = Math.floor(Date.now() / 1e3);
656
+ if (BigInt(permit2Payload.permit2Authorization.deadline) < BigInt(now + 6)) {
657
+ return {
658
+ isValid: false,
659
+ invalidReason: "permit2_deadline_expired",
660
+ payer
661
+ };
662
+ }
663
+ if (BigInt(permit2Payload.permit2Authorization.witness.validAfter) > BigInt(now)) {
664
+ return {
665
+ isValid: false,
666
+ invalidReason: "permit2_not_yet_valid",
667
+ payer
668
+ };
669
+ }
670
+ if (BigInt(permit2Payload.permit2Authorization.permitted.amount) !== BigInt(requirements.amount)) {
671
+ return {
672
+ isValid: false,
673
+ invalidReason: "permit2_amount_mismatch",
674
+ payer
675
+ };
676
+ }
677
+ if ((0, import_viem4.getAddress)(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) {
678
+ return {
679
+ isValid: false,
680
+ invalidReason: "permit2_token_mismatch",
681
+ payer
682
+ };
683
+ }
684
+ const permit2TypedData = {
685
+ types: permit2WitnessTypes,
686
+ primaryType: "PermitWitnessTransferFrom",
687
+ domain: {
688
+ name: "Permit2",
689
+ chainId,
690
+ verifyingContract: PERMIT2_ADDRESS
691
+ },
692
+ message: {
693
+ permitted: {
694
+ token: (0, import_viem4.getAddress)(permit2Payload.permit2Authorization.permitted.token),
695
+ amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
696
+ },
697
+ spender: (0, import_viem4.getAddress)(permit2Payload.permit2Authorization.spender),
698
+ nonce: BigInt(permit2Payload.permit2Authorization.nonce),
699
+ deadline: BigInt(permit2Payload.permit2Authorization.deadline),
700
+ witness: {
701
+ to: (0, import_viem4.getAddress)(permit2Payload.permit2Authorization.witness.to),
702
+ validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
703
+ }
704
+ }
705
+ };
706
+ try {
707
+ const isValid = await signer.verifyTypedData({
708
+ address: payer,
709
+ ...permit2TypedData,
710
+ signature: permit2Payload.signature
711
+ });
712
+ if (!isValid) {
713
+ return {
714
+ isValid: false,
715
+ invalidReason: "invalid_permit2_signature",
716
+ payer
717
+ };
718
+ }
719
+ } catch {
720
+ return {
721
+ isValid: false,
722
+ invalidReason: "invalid_permit2_signature",
723
+ payer
724
+ };
725
+ }
726
+ const allowanceResult = await _verifyPermit2Allowance(
727
+ signer,
728
+ payload,
729
+ requirements,
730
+ payer,
731
+ tokenAddress,
732
+ context
733
+ );
734
+ if (allowanceResult) {
735
+ return allowanceResult;
736
+ }
737
+ try {
738
+ const balance = await signer.readContract({
739
+ address: tokenAddress,
740
+ abi: eip3009ABI,
741
+ functionName: "balanceOf",
742
+ args: [payer]
743
+ });
744
+ if (balance < BigInt(requirements.amount)) {
745
+ return {
746
+ isValid: false,
747
+ invalidReason: "insufficient_funds",
748
+ invalidMessage: `Insufficient funds to complete the payment. Required: ${requirements.amount} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,
749
+ payer
750
+ };
751
+ }
752
+ } catch {
753
+ }
754
+ return {
755
+ isValid: true,
756
+ invalidReason: void 0,
757
+ payer
758
+ };
759
+ }
760
+ async function _verifyPermit2Allowance(signer, payload, requirements, payer, tokenAddress, context) {
761
+ try {
762
+ const allowance = await signer.readContract({
763
+ address: tokenAddress,
764
+ abi: erc20AllowanceAbi,
765
+ functionName: "allowance",
766
+ args: [payer, PERMIT2_ADDRESS]
767
+ });
768
+ if (allowance >= BigInt(requirements.amount)) {
769
+ return null;
770
+ }
771
+ const eip2612Info = (0, import_x402_extensions2.extractEip2612GasSponsoringInfo)(payload);
772
+ if (eip2612Info) {
773
+ const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);
774
+ if (!result.isValid) {
775
+ return { isValid: false, invalidReason: result.invalidReason, payer };
776
+ }
777
+ return null;
778
+ }
779
+ const erc20GasSponsorshipExtension = context?.getExtension(
780
+ import_x402_extensions2.ERC20_APPROVAL_GAS_SPONSORING.key
781
+ );
782
+ if (erc20GasSponsorshipExtension) {
783
+ const erc20Info = (0, import_x402_extensions2.extractErc20ApprovalGasSponsoringInfo)(payload);
784
+ if (erc20Info) {
785
+ const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);
786
+ if (!result.isValid) {
787
+ return { isValid: false, invalidReason: result.invalidReason, payer };
788
+ }
789
+ return null;
790
+ }
791
+ }
792
+ return { isValid: false, invalidReason: "permit2_allowance_required", payer };
793
+ } catch {
794
+ const eip2612Info = (0, import_x402_extensions2.extractEip2612GasSponsoringInfo)(payload);
795
+ if (eip2612Info) {
796
+ const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);
797
+ if (!result.isValid) {
798
+ return { isValid: false, invalidReason: result.invalidReason, payer };
799
+ }
800
+ }
801
+ return null;
802
+ }
803
+ }
804
+ async function settlePermit2(signer, payload, requirements, permit2Payload, context) {
805
+ const payer = permit2Payload.permit2Authorization.from;
806
+ const valid = await verifyPermit2(signer, payload, requirements, permit2Payload, context);
807
+ if (!valid.isValid) {
808
+ return {
809
+ success: false,
810
+ network: payload.accepted.network,
811
+ transaction: "",
812
+ errorReason: valid.invalidReason ?? "invalid_scheme",
813
+ payer
814
+ };
815
+ }
816
+ const eip2612Info = (0, import_x402_extensions2.extractEip2612GasSponsoringInfo)(payload);
817
+ if (eip2612Info) {
818
+ return _settlePermit2WithEIP2612(signer, payload, permit2Payload, eip2612Info);
819
+ }
820
+ const erc20Info = (0, import_x402_extensions2.extractErc20ApprovalGasSponsoringInfo)(payload);
821
+ if (erc20Info) {
822
+ const erc20GasSponsorshipExtension = context?.getExtension(
823
+ import_x402_extensions2.ERC20_APPROVAL_GAS_SPONSORING.key
824
+ );
825
+ if (erc20GasSponsorshipExtension?.signer) {
826
+ return _settlePermit2WithERC20Approval(
827
+ erc20GasSponsorshipExtension.signer,
828
+ payload,
829
+ permit2Payload,
830
+ erc20Info
831
+ );
832
+ }
833
+ }
834
+ return _settlePermit2Direct(signer, payload, permit2Payload);
835
+ }
836
+ async function _settlePermit2WithEIP2612(signer, payload, permit2Payload, eip2612Info) {
837
+ const payer = permit2Payload.permit2Authorization.from;
838
+ try {
839
+ const { v, r, s } = splitEip2612Signature(eip2612Info.signature);
840
+ const tx = await signer.writeContract({
841
+ address: x402ExactPermit2ProxyAddress,
842
+ abi: x402ExactPermit2ProxyABI,
843
+ functionName: "settleWithPermit",
844
+ args: [
845
+ {
846
+ value: BigInt(eip2612Info.amount),
847
+ deadline: BigInt(eip2612Info.deadline),
848
+ r,
849
+ s,
850
+ v
851
+ },
852
+ {
853
+ permitted: {
854
+ token: (0, import_viem4.getAddress)(permit2Payload.permit2Authorization.permitted.token),
855
+ amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
856
+ },
857
+ nonce: BigInt(permit2Payload.permit2Authorization.nonce),
858
+ deadline: BigInt(permit2Payload.permit2Authorization.deadline)
859
+ },
860
+ (0, import_viem4.getAddress)(payer),
861
+ {
862
+ to: (0, import_viem4.getAddress)(permit2Payload.permit2Authorization.witness.to),
863
+ validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
864
+ },
865
+ permit2Payload.signature
866
+ ]
867
+ });
868
+ return _waitAndReturn(signer, tx, payload, payer);
869
+ } catch (error) {
870
+ return _mapSettleError(error, payload, payer);
871
+ }
872
+ }
873
+ async function _settlePermit2WithERC20Approval(extensionSigner, payload, permit2Payload, erc20Info) {
874
+ const payer = permit2Payload.permit2Authorization.from;
875
+ try {
876
+ const approvalTxHash = await extensionSigner.sendRawTransaction({
877
+ serializedTransaction: erc20Info.signedTransaction
878
+ });
879
+ const approvalReceipt = await extensionSigner.waitForTransactionReceipt({
880
+ hash: approvalTxHash
881
+ });
882
+ if (approvalReceipt.status !== "success") {
883
+ return {
884
+ success: false,
885
+ errorReason: "erc20_approval_tx_failed",
886
+ transaction: approvalTxHash,
887
+ network: payload.accepted.network,
888
+ payer
889
+ };
890
+ }
891
+ const tx = await extensionSigner.writeContract({
892
+ address: x402ExactPermit2ProxyAddress,
893
+ abi: x402ExactPermit2ProxyABI,
894
+ functionName: "settle",
895
+ args: [
896
+ {
897
+ permitted: {
898
+ token: (0, import_viem4.getAddress)(permit2Payload.permit2Authorization.permitted.token),
899
+ amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
900
+ },
901
+ nonce: BigInt(permit2Payload.permit2Authorization.nonce),
902
+ deadline: BigInt(permit2Payload.permit2Authorization.deadline)
903
+ },
904
+ (0, import_viem4.getAddress)(payer),
905
+ {
906
+ to: (0, import_viem4.getAddress)(permit2Payload.permit2Authorization.witness.to),
907
+ validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
908
+ },
909
+ permit2Payload.signature
910
+ ]
911
+ });
912
+ return _waitAndReturn(extensionSigner, tx, payload, payer);
913
+ } catch (error) {
914
+ return _mapSettleError(error, payload, payer);
915
+ }
916
+ }
917
+ async function _settlePermit2Direct(signer, payload, permit2Payload) {
918
+ const payer = permit2Payload.permit2Authorization.from;
919
+ try {
920
+ const tx = await signer.writeContract({
921
+ address: x402ExactPermit2ProxyAddress,
922
+ abi: x402ExactPermit2ProxyABI,
923
+ functionName: "settle",
924
+ args: [
925
+ {
926
+ permitted: {
927
+ token: (0, import_viem4.getAddress)(permit2Payload.permit2Authorization.permitted.token),
928
+ amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
929
+ },
930
+ nonce: BigInt(permit2Payload.permit2Authorization.nonce),
931
+ deadline: BigInt(permit2Payload.permit2Authorization.deadline)
932
+ },
933
+ (0, import_viem4.getAddress)(payer),
934
+ {
935
+ to: (0, import_viem4.getAddress)(permit2Payload.permit2Authorization.witness.to),
936
+ validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
937
+ },
938
+ permit2Payload.signature
939
+ ]
940
+ });
941
+ return _waitAndReturn(signer, tx, payload, payer);
942
+ } catch (error) {
943
+ return _mapSettleError(error, payload, payer);
944
+ }
945
+ }
946
+ async function _waitAndReturn(signer, tx, payload, payer) {
947
+ const receipt = await signer.waitForTransactionReceipt({ hash: tx });
948
+ if (receipt.status !== "success") {
949
+ return {
950
+ success: false,
951
+ errorReason: "invalid_transaction_state",
952
+ transaction: tx,
953
+ network: payload.accepted.network,
954
+ payer
955
+ };
956
+ }
957
+ return {
958
+ success: true,
959
+ transaction: tx,
960
+ network: payload.accepted.network,
961
+ payer
962
+ };
963
+ }
964
+ function _mapSettleError(error, payload, payer) {
965
+ let errorReason = "transaction_failed";
966
+ if (error instanceof Error) {
967
+ const message = error.message;
968
+ if (message.includes("Permit2612AmountMismatch")) {
969
+ errorReason = ErrPermit2612AmountMismatch;
970
+ } else if (message.includes("InvalidAmount")) {
971
+ errorReason = ErrPermit2InvalidAmount;
972
+ } else if (message.includes("InvalidDestination")) {
973
+ errorReason = ErrPermit2InvalidDestination;
974
+ } else if (message.includes("InvalidOwner")) {
975
+ errorReason = ErrPermit2InvalidOwner;
976
+ } else if (message.includes("PaymentTooEarly")) {
977
+ errorReason = ErrPermit2PaymentTooEarly;
978
+ } else if (message.includes("InvalidSignature") || message.includes("SignatureExpired")) {
979
+ errorReason = ErrPermit2InvalidSignature;
980
+ } else if (message.includes("InvalidNonce")) {
981
+ errorReason = ErrPermit2InvalidNonce;
982
+ } else {
983
+ errorReason = `transaction_failed: ${message.slice(0, 500)}`;
984
+ }
985
+ }
986
+ return {
987
+ success: false,
988
+ errorReason,
989
+ transaction: "",
990
+ network: payload.accepted.network,
991
+ payer
992
+ };
993
+ }
994
+ function validateEip2612PermitForPayment(info, payer, tokenAddress) {
995
+ if (!(0, import_x402_extensions2.validateEip2612GasSponsoringInfo)(info)) {
996
+ return { isValid: false, invalidReason: "invalid_eip2612_extension_format" };
997
+ }
998
+ if ((0, import_viem4.getAddress)(info.from) !== (0, import_viem4.getAddress)(payer)) {
999
+ return { isValid: false, invalidReason: "eip2612_from_mismatch" };
1000
+ }
1001
+ if ((0, import_viem4.getAddress)(info.asset) !== tokenAddress) {
1002
+ return { isValid: false, invalidReason: "eip2612_asset_mismatch" };
1003
+ }
1004
+ if ((0, import_viem4.getAddress)(info.spender) !== (0, import_viem4.getAddress)(PERMIT2_ADDRESS)) {
1005
+ return { isValid: false, invalidReason: "eip2612_spender_not_permit2" };
1006
+ }
1007
+ const now = Math.floor(Date.now() / 1e3);
1008
+ if (BigInt(info.deadline) < BigInt(now + 6)) {
1009
+ return { isValid: false, invalidReason: "eip2612_deadline_expired" };
1010
+ }
1011
+ return { isValid: true };
1012
+ }
1013
+ function splitEip2612Signature(signature) {
1014
+ const sig = signature.startsWith("0x") ? signature.slice(2) : signature;
1015
+ if (sig.length !== 130) {
1016
+ throw new Error(
1017
+ `invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes`
1018
+ );
1019
+ }
1020
+ const r = `0x${sig.slice(0, 64)}`;
1021
+ const s = `0x${sig.slice(64, 128)}`;
1022
+ const v = parseInt(sig.slice(128, 130), 16);
1023
+ return { v, r, s };
1024
+ }
1025
+
1026
+ // src/exact/facilitator/scheme.ts
1027
+ var ExactEvmScheme = class {
1028
+ /**
1029
+ * Creates a new ExactEvmScheme facilitator instance.
1030
+ *
1031
+ * @param signer - The EVM signer for facilitator operations
1032
+ * @param config - Optional configuration
1033
+ */
1034
+ constructor(signer, config) {
1035
+ this.signer = signer;
1036
+ this.scheme = "exact";
1037
+ this.caipFamily = "eip155:*";
1038
+ this.config = {
1039
+ deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? false
1040
+ };
1041
+ }
1042
+ /**
1043
+ * Returns undefined — EVM has no mechanism-specific extra data.
1044
+ *
1045
+ * @param _ - The network identifier (unused)
1046
+ * @returns undefined
1047
+ */
1048
+ getExtra(_) {
1049
+ return void 0;
1050
+ }
1051
+ /**
1052
+ * Returns facilitator wallet addresses for the supported response.
1053
+ *
1054
+ * @param _ - The network identifier (unused, addresses are network-agnostic)
1055
+ * @returns Array of facilitator wallet addresses
1056
+ */
1057
+ getSigners(_) {
1058
+ return [...this.signer.getAddresses()];
1059
+ }
1060
+ /**
1061
+ * Verifies a payment payload. Routes to Permit2 or EIP-3009 based on payload type.
1062
+ *
1063
+ * @param payload - The payment payload to verify
1064
+ * @param requirements - The payment requirements
1065
+ * @param context - Optional facilitator context for extension capabilities
1066
+ * @returns Promise resolving to verification response
1067
+ */
1068
+ async verify(payload, requirements, context) {
1069
+ const rawPayload = payload.payload;
1070
+ if (isPermit2Payload(rawPayload)) {
1071
+ return verifyPermit2(this.signer, payload, requirements, rawPayload, context);
1072
+ }
1073
+ const eip3009Payload = rawPayload;
1074
+ return verifyEIP3009(this.signer, payload, requirements, eip3009Payload);
1075
+ }
1076
+ /**
1077
+ * Settles a payment. Routes to Permit2 or EIP-3009 based on payload type.
1078
+ *
1079
+ * @param payload - The payment payload to settle
1080
+ * @param requirements - The payment requirements
1081
+ * @param context - Optional facilitator context for extension capabilities
1082
+ * @returns Promise resolving to settlement response
1083
+ */
1084
+ async settle(payload, requirements, context) {
1085
+ const rawPayload = payload.payload;
1086
+ if (isPermit2Payload(rawPayload)) {
1087
+ return settlePermit2(this.signer, payload, requirements, rawPayload, context);
1088
+ }
1089
+ const eip3009Payload = rawPayload;
1090
+ return settleEIP3009(this.signer, payload, requirements, eip3009Payload, this.config);
1091
+ }
1092
+ };
1093
+
1094
+ // src/exact/v1/facilitator/scheme.ts
1095
+ var import_viem6 = require("viem");
1096
+
1097
+ // src/exact/v1/client/scheme.ts
1098
+ var import_viem5 = require("viem");
1099
+
1100
+ // src/v1/index.ts
1101
+ var EVM_NETWORK_CHAIN_ID_MAP = {
1102
+ ethereum: 1,
1103
+ sepolia: 11155111,
1104
+ abstract: 2741,
1105
+ "abstract-testnet": 11124,
1106
+ "base-sepolia": 84532,
1107
+ base: 8453,
1108
+ "avalanche-fuji": 43113,
1109
+ avalanche: 43114,
1110
+ iotex: 4689,
1111
+ sei: 1329,
1112
+ "sei-testnet": 1328,
1113
+ polygon: 137,
1114
+ "polygon-amoy": 80002,
1115
+ peaq: 3338,
1116
+ story: 1514,
1117
+ educhain: 41923,
1118
+ "skale-base-sepolia": 324705682,
1119
+ megaeth: 4326,
1120
+ monad: 143,
1121
+ bsc: 56,
1122
+ "bsc-testnet": 97
1123
+ };
1124
+ var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
1125
+ function getEvmChainIdV1(network) {
1126
+ const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];
1127
+ if (!chainId) {
1128
+ throw new Error(`Unsupported v1 network: ${network}`);
1129
+ }
1130
+ return chainId;
1131
+ }
1132
+
1133
+ // src/exact/v1/facilitator/scheme.ts
1134
+ var ExactEvmSchemeV12 = class {
1135
+ /**
1136
+ * Creates a new ExactEvmFacilitatorV1 instance.
1137
+ *
1138
+ * @param signer - The EVM signer for facilitator operations
1139
+ * @param config - Optional configuration for the facilitator
1140
+ */
1141
+ constructor(signer, config) {
1142
+ this.signer = signer;
1143
+ this.scheme = "exact";
1144
+ this.caipFamily = "eip155:*";
1145
+ this.config = {
1146
+ deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? false
1147
+ };
1148
+ }
1149
+ /**
1150
+ * Get mechanism-specific extra data for the supported kinds endpoint.
1151
+ * For EVM, no extra data is needed.
1152
+ *
1153
+ * @param _ - The network identifier (unused for EVM)
1154
+ * @returns undefined (EVM has no extra data)
1155
+ */
1156
+ getExtra(_) {
1157
+ return void 0;
1158
+ }
1159
+ /**
1160
+ * Get signer addresses used by this facilitator.
1161
+ * Returns all addresses this facilitator can use for signing/settling transactions.
1162
+ *
1163
+ * @param _ - The network identifier (unused for EVM, addresses are network-agnostic)
1164
+ * @returns Array of facilitator wallet addresses
1165
+ */
1166
+ getSigners(_) {
1167
+ return [...this.signer.getAddresses()];
1168
+ }
1169
+ /**
1170
+ * Verifies a payment payload (V1).
1171
+ *
1172
+ * @param payload - The payment payload to verify
1173
+ * @param requirements - The payment requirements
1174
+ * @returns Promise resolving to verification response
1175
+ */
1176
+ async verify(payload, requirements) {
1177
+ const requirementsV1 = requirements;
1178
+ const payloadV1 = payload;
1179
+ const exactEvmPayload = payload.payload;
1180
+ if (payloadV1.scheme !== "exact" || requirements.scheme !== "exact") {
1181
+ return {
1182
+ isValid: false,
1183
+ invalidReason: "unsupported_scheme",
1184
+ payer: exactEvmPayload.authorization.from
1185
+ };
1186
+ }
1187
+ let chainId;
1188
+ try {
1189
+ chainId = getEvmChainIdV1(payloadV1.network);
1190
+ } catch {
1191
+ return {
1192
+ isValid: false,
1193
+ invalidReason: `invalid_network`,
1194
+ payer: exactEvmPayload.authorization.from
1195
+ };
1196
+ }
1197
+ if (!requirements.extra?.name || !requirements.extra?.version) {
1198
+ return {
1199
+ isValid: false,
1200
+ invalidReason: "missing_eip712_domain",
1201
+ payer: exactEvmPayload.authorization.from
1202
+ };
1203
+ }
1204
+ const { name, version } = requirements.extra;
1205
+ const erc20Address = (0, import_viem6.getAddress)(requirements.asset);
1206
+ if (payloadV1.network !== requirements.network) {
1207
+ return {
1208
+ isValid: false,
1209
+ invalidReason: "network_mismatch",
1210
+ payer: exactEvmPayload.authorization.from
1211
+ };
1212
+ }
1213
+ const permitTypedData = {
1214
+ types: authorizationTypes,
1215
+ primaryType: "TransferWithAuthorization",
1216
+ domain: {
1217
+ name,
1218
+ version,
1219
+ chainId,
1220
+ verifyingContract: erc20Address
1221
+ },
1222
+ message: {
1223
+ from: exactEvmPayload.authorization.from,
1224
+ to: exactEvmPayload.authorization.to,
1225
+ value: BigInt(exactEvmPayload.authorization.value),
1226
+ validAfter: BigInt(exactEvmPayload.authorization.validAfter),
1227
+ validBefore: BigInt(exactEvmPayload.authorization.validBefore),
1228
+ nonce: exactEvmPayload.authorization.nonce
1229
+ }
1230
+ };
1231
+ try {
1232
+ const recoveredAddress = await this.signer.verifyTypedData({
1233
+ address: exactEvmPayload.authorization.from,
1234
+ ...permitTypedData,
1235
+ signature: exactEvmPayload.signature
1236
+ });
1237
+ if (!recoveredAddress) {
1238
+ return {
1239
+ isValid: false,
1240
+ invalidReason: "invalid_exact_evm_payload_signature",
1241
+ payer: exactEvmPayload.authorization.from
1242
+ };
1243
+ }
1244
+ } catch {
1245
+ const signature = exactEvmPayload.signature;
1246
+ const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
1247
+ const isSmartWallet = signatureLength > 130;
1248
+ if (isSmartWallet) {
1249
+ const payerAddress = exactEvmPayload.authorization.from;
1250
+ const bytecode = await this.signer.getCode({ address: payerAddress });
1251
+ if (!bytecode || bytecode === "0x") {
1252
+ const erc6492Data = (0, import_viem6.parseErc6492Signature)(signature);
1253
+ const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem6.isAddressEqual)(erc6492Data.address, "0x0000000000000000000000000000000000000000");
1254
+ if (!hasDeploymentInfo) {
1255
+ return {
1256
+ isValid: false,
1257
+ invalidReason: "invalid_exact_evm_payload_undeployed_smart_wallet",
1258
+ payer: payerAddress
1259
+ };
1260
+ }
1261
+ } else {
1262
+ return {
1263
+ isValid: false,
1264
+ invalidReason: "invalid_exact_evm_payload_signature",
1265
+ payer: exactEvmPayload.authorization.from
1266
+ };
1267
+ }
1268
+ } else {
1269
+ return {
1270
+ isValid: false,
1271
+ invalidReason: "invalid_exact_evm_payload_signature",
1272
+ payer: exactEvmPayload.authorization.from
1273
+ };
1274
+ }
1275
+ }
1276
+ if ((0, import_viem6.getAddress)(exactEvmPayload.authorization.to) !== (0, import_viem6.getAddress)(requirements.payTo)) {
1277
+ return {
1278
+ isValid: false,
1279
+ invalidReason: "invalid_exact_evm_payload_recipient_mismatch",
1280
+ payer: exactEvmPayload.authorization.from
1281
+ };
1282
+ }
1283
+ const now = Math.floor(Date.now() / 1e3);
1284
+ if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) {
1285
+ return {
1286
+ isValid: false,
1287
+ invalidReason: "invalid_exact_evm_payload_authorization_valid_before",
1288
+ payer: exactEvmPayload.authorization.from
1289
+ };
1290
+ }
1291
+ if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) {
1292
+ return {
1293
+ isValid: false,
1294
+ invalidReason: "invalid_exact_evm_payload_authorization_valid_after",
1295
+ payer: exactEvmPayload.authorization.from
1296
+ };
1297
+ }
1298
+ try {
1299
+ const balance = await this.signer.readContract({
1300
+ address: erc20Address,
1301
+ abi: eip3009ABI,
1302
+ functionName: "balanceOf",
1303
+ args: [exactEvmPayload.authorization.from]
1304
+ });
1305
+ if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {
1306
+ return {
1307
+ isValid: false,
1308
+ invalidReason: "insufficient_funds",
1309
+ invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,
1310
+ payer: exactEvmPayload.authorization.from
1311
+ };
1312
+ }
1313
+ } catch {
1314
+ }
1315
+ if (BigInt(exactEvmPayload.authorization.value) !== BigInt(requirementsV1.maxAmountRequired)) {
1316
+ return {
1317
+ isValid: false,
1318
+ invalidReason: "invalid_exact_evm_payload_authorization_value_mismatch",
1319
+ payer: exactEvmPayload.authorization.from
1320
+ };
1321
+ }
1322
+ return {
1323
+ isValid: true,
1324
+ invalidReason: void 0,
1325
+ payer: exactEvmPayload.authorization.from
1326
+ };
1327
+ }
1328
+ /**
1329
+ * Settles a payment by executing the transfer (V1).
1330
+ *
1331
+ * @param payload - The payment payload to settle
1332
+ * @param requirements - The payment requirements
1333
+ * @returns Promise resolving to settlement response
1334
+ */
1335
+ async settle(payload, requirements) {
1336
+ const payloadV1 = payload;
1337
+ const exactEvmPayload = payload.payload;
1338
+ const valid = await this.verify(payload, requirements);
1339
+ if (!valid.isValid) {
1340
+ return {
1341
+ success: false,
1342
+ network: payloadV1.network,
1343
+ transaction: "",
1344
+ errorReason: valid.invalidReason ?? "invalid_scheme",
1345
+ payer: exactEvmPayload.authorization.from
1346
+ };
1347
+ }
1348
+ try {
1349
+ const parseResult = (0, import_viem6.parseErc6492Signature)(exactEvmPayload.signature);
1350
+ const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;
1351
+ if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem6.isAddressEqual)(factoryAddress, "0x0000000000000000000000000000000000000000")) {
1352
+ const payerAddress = exactEvmPayload.authorization.from;
1353
+ const bytecode = await this.signer.getCode({ address: payerAddress });
1354
+ if (!bytecode || bytecode === "0x") {
1355
+ try {
1356
+ console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);
1357
+ const deployTx = await this.signer.sendTransaction({
1358
+ to: factoryAddress,
1359
+ data: factoryCalldata
1360
+ });
1361
+ await this.signer.waitForTransactionReceipt({ hash: deployTx });
1362
+ console.log(`Successfully deployed smart wallet for ${payerAddress}`);
1363
+ } catch (deployError) {
1364
+ console.error("Smart wallet deployment failed:", deployError);
1365
+ throw deployError;
1366
+ }
1367
+ } else {
1368
+ console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);
1369
+ }
1370
+ }
1371
+ const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
1372
+ const isECDSA = signatureLength === 130;
1373
+ let tx;
1374
+ if (isECDSA) {
1375
+ const parsedSig = (0, import_viem6.parseSignature)(signature);
1376
+ tx = await this.signer.writeContract({
1377
+ address: (0, import_viem6.getAddress)(requirements.asset),
1378
+ abi: eip3009ABI,
1379
+ functionName: "transferWithAuthorization",
1380
+ args: [
1381
+ (0, import_viem6.getAddress)(exactEvmPayload.authorization.from),
1382
+ (0, import_viem6.getAddress)(exactEvmPayload.authorization.to),
1383
+ BigInt(exactEvmPayload.authorization.value),
1384
+ BigInt(exactEvmPayload.authorization.validAfter),
1385
+ BigInt(exactEvmPayload.authorization.validBefore),
1386
+ exactEvmPayload.authorization.nonce,
1387
+ parsedSig.v || parsedSig.yParity,
1388
+ parsedSig.r,
1389
+ parsedSig.s
1390
+ ]
1391
+ });
1392
+ } else {
1393
+ tx = await this.signer.writeContract({
1394
+ address: (0, import_viem6.getAddress)(requirements.asset),
1395
+ abi: eip3009ABI,
1396
+ functionName: "transferWithAuthorization",
1397
+ args: [
1398
+ (0, import_viem6.getAddress)(exactEvmPayload.authorization.from),
1399
+ (0, import_viem6.getAddress)(exactEvmPayload.authorization.to),
1400
+ BigInt(exactEvmPayload.authorization.value),
1401
+ BigInt(exactEvmPayload.authorization.validAfter),
1402
+ BigInt(exactEvmPayload.authorization.validBefore),
1403
+ exactEvmPayload.authorization.nonce,
1404
+ signature
1405
+ ]
1406
+ });
1407
+ }
1408
+ const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });
1409
+ if (receipt.status !== "success") {
1410
+ return {
1411
+ success: false,
1412
+ errorReason: "invalid_transaction_state",
1413
+ transaction: tx,
1414
+ network: payloadV1.network,
1415
+ payer: exactEvmPayload.authorization.from
1416
+ };
1417
+ }
1418
+ return {
1419
+ success: true,
1420
+ transaction: tx,
1421
+ network: payloadV1.network,
1422
+ payer: exactEvmPayload.authorization.from
1423
+ };
1424
+ } catch (error) {
1425
+ console.error("Failed to settle transaction:", error);
1426
+ return {
1427
+ success: false,
1428
+ errorReason: "transaction_failed",
1429
+ transaction: "",
1430
+ network: payloadV1.network,
1431
+ payer: exactEvmPayload.authorization.from
1432
+ };
1433
+ }
1434
+ }
1435
+ };
1436
+
1437
+ // src/exact/facilitator/register.ts
1438
+ function registerExactEvmScheme(facilitator, config) {
1439
+ facilitator.register(
1440
+ config.networks,
1441
+ new ExactEvmScheme(config.signer, {
1442
+ deployERC4337WithEIP6492: config.deployERC4337WithEIP6492
1443
+ })
1444
+ );
1445
+ facilitator.registerV1(
1446
+ NETWORKS,
1447
+ new ExactEvmSchemeV12(config.signer, {
1448
+ deployERC4337WithEIP6492: config.deployERC4337WithEIP6492
1449
+ })
1450
+ );
1451
+ return facilitator;
1452
+ }
1453
+ // Annotate the CommonJS export names for ESM import in node:
1454
+ 0 && (module.exports = {
1455
+ ExactEvmScheme,
1456
+ registerExactEvmScheme
1457
+ });
1458
+ //# sourceMappingURL=index.js.map