@x402/evm 2.4.0 → 2.5.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 (48) hide show
  1. package/dist/cjs/exact/client/index.d.ts +2 -2
  2. package/dist/cjs/exact/client/index.js +284 -192
  3. package/dist/cjs/exact/client/index.js.map +1 -1
  4. package/dist/cjs/exact/facilitator/index.d.ts +18 -18
  5. package/dist/cjs/exact/facilitator/index.js +454 -234
  6. package/dist/cjs/exact/facilitator/index.js.map +1 -1
  7. package/dist/cjs/exact/v1/client/index.d.ts +1 -1
  8. package/dist/cjs/exact/v1/client/index.js +17 -18
  9. package/dist/cjs/exact/v1/client/index.js.map +1 -1
  10. package/dist/cjs/exact/v1/facilitator/index.d.ts +1 -1
  11. package/dist/cjs/exact/v1/facilitator/index.js +7 -8
  12. package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
  13. package/dist/cjs/index.d.ts +3 -390
  14. package/dist/cjs/index.js +225 -132
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/permit2-CQbXqCMC.d.ts +517 -0
  17. package/dist/cjs/{signer-3KGwtdNT.d.ts → signer-DC81R8wQ.d.ts} +37 -0
  18. package/dist/cjs/v1/index.d.ts +11 -2
  19. package/dist/cjs/v1/index.js +14 -11
  20. package/dist/cjs/v1/index.js.map +1 -1
  21. package/dist/esm/{chunk-GSU4DHTC.mjs → chunk-7KHQD5KT.mjs} +72 -37
  22. package/dist/esm/chunk-7KHQD5KT.mjs.map +1 -0
  23. package/dist/esm/{chunk-CJHYX7BQ.mjs → chunk-GY6X5A3G.mjs} +119 -56
  24. package/dist/esm/chunk-GY6X5A3G.mjs.map +1 -0
  25. package/dist/esm/{chunk-PFULIQAE.mjs → chunk-TKN5V2BV.mjs} +1 -1
  26. package/dist/esm/chunk-TKN5V2BV.mjs.map +1 -0
  27. package/dist/esm/exact/client/index.d.mts +2 -2
  28. package/dist/esm/exact/client/index.mjs +4 -3
  29. package/dist/esm/exact/facilitator/index.d.mts +18 -18
  30. package/dist/esm/exact/facilitator/index.mjs +385 -176
  31. package/dist/esm/exact/facilitator/index.mjs.map +1 -1
  32. package/dist/esm/exact/v1/client/index.d.mts +1 -1
  33. package/dist/esm/exact/v1/client/index.mjs +2 -2
  34. package/dist/esm/exact/v1/facilitator/index.d.mts +1 -1
  35. package/dist/esm/exact/v1/facilitator/index.mjs +2 -2
  36. package/dist/esm/index.d.mts +3 -390
  37. package/dist/esm/index.mjs +18 -5
  38. package/dist/esm/index.mjs.map +1 -1
  39. package/dist/esm/permit2-CGOcN7Et.d.mts +517 -0
  40. package/dist/esm/{signer-3KGwtdNT.d.mts → signer-DC81R8wQ.d.mts} +37 -0
  41. package/dist/esm/v1/index.d.mts +11 -2
  42. package/dist/esm/v1/index.mjs +6 -4
  43. package/package.json +3 -3
  44. package/dist/cjs/permit2-CzKPU5By.d.ts +0 -130
  45. package/dist/esm/chunk-CJHYX7BQ.mjs.map +0 -1
  46. package/dist/esm/chunk-GSU4DHTC.mjs.map +0 -1
  47. package/dist/esm/chunk-PFULIQAE.mjs.map +0 -1
  48. package/dist/esm/permit2-C2FkNEHT.d.mts +0 -130
@@ -1,16 +1,19 @@
1
1
  import {
2
2
  isPermit2Payload
3
- } from "../../chunk-PFULIQAE.mjs";
3
+ } from "../../chunk-TKN5V2BV.mjs";
4
4
  import {
5
- ExactEvmSchemeV12 as ExactEvmSchemeV1,
5
+ ExactEvmSchemeV1,
6
6
  NETWORKS,
7
7
  PERMIT2_ADDRESS,
8
8
  authorizationTypes,
9
9
  eip3009ABI,
10
+ erc20AllowanceAbi,
11
+ erc20ApproveAbi,
12
+ getEvmChainId,
10
13
  permit2WitnessTypes,
11
14
  x402ExactPermit2ProxyABI,
12
15
  x402ExactPermit2ProxyAddress
13
- } from "../../chunk-GSU4DHTC.mjs";
16
+ } from "../../chunk-7KHQD5KT.mjs";
14
17
 
15
18
  // src/exact/facilitator/eip3009.ts
16
19
  import { getAddress, isAddressEqual, parseErc6492Signature, parseSignature } from "viem";
@@ -45,7 +48,7 @@ async function verifyEIP3009(signer, payload, requirements, eip3009Payload) {
45
48
  domain: {
46
49
  name,
47
50
  version,
48
- chainId: parseInt(requirements.network.split(":")[1]),
51
+ chainId: getEvmChainId(requirements.network),
49
52
  verifyingContract: erc20Address
50
53
  },
51
54
  message: {
@@ -246,22 +249,140 @@ async function settleEIP3009(signer, payload, requirements, eip3009Payload, conf
246
249
  // src/exact/facilitator/permit2.ts
247
250
  import {
248
251
  extractEip2612GasSponsoringInfo,
249
- validateEip2612GasSponsoringInfo
252
+ validateEip2612GasSponsoringInfo,
253
+ extractErc20ApprovalGasSponsoringInfo,
254
+ ERC20_APPROVAL_GAS_SPONSORING
250
255
  } from "@x402/extensions";
251
- import { getAddress as getAddress2 } from "viem";
252
- var erc20AllowanceABI = [
253
- {
254
- type: "function",
255
- name: "allowance",
256
- inputs: [
257
- { name: "owner", type: "address" },
258
- { name: "spender", type: "address" }
259
- ],
260
- outputs: [{ type: "uint256" }],
261
- stateMutability: "view"
262
- }
263
- ];
264
- async function verifyPermit2(signer, payload, requirements, permit2Payload) {
256
+ import { getAddress as getAddress3 } from "viem";
257
+
258
+ // src/exact/facilitator/errors.ts
259
+ var ErrPermit2InvalidSignature = "invalid_permit2_signature";
260
+ var ErrPermit2InvalidAmount = "permit2_invalid_amount";
261
+ var ErrPermit2InvalidDestination = "permit2_invalid_destination";
262
+ var ErrPermit2InvalidOwner = "permit2_invalid_owner";
263
+ var ErrPermit2PaymentTooEarly = "permit2_payment_too_early";
264
+ var ErrPermit2InvalidNonce = "permit2_invalid_nonce";
265
+ var ErrPermit2612AmountMismatch = "permit2_2612_amount_mismatch";
266
+ var ErrErc20ApprovalInvalidFormat = "invalid_erc20_approval_extension_format";
267
+ var ErrErc20ApprovalFromMismatch = "erc20_approval_from_mismatch";
268
+ var ErrErc20ApprovalAssetMismatch = "erc20_approval_asset_mismatch";
269
+ var ErrErc20ApprovalSpenderNotPermit2 = "erc20_approval_spender_not_permit2";
270
+ var ErrErc20ApprovalTxWrongTarget = "erc20_approval_tx_wrong_target";
271
+ var ErrErc20ApprovalTxWrongSelector = "erc20_approval_tx_wrong_selector";
272
+ var ErrErc20ApprovalTxWrongSpender = "erc20_approval_tx_wrong_spender";
273
+ var ErrErc20ApprovalTxInvalidCalldata = "erc20_approval_tx_invalid_calldata";
274
+ var ErrErc20ApprovalTxSignerMismatch = "erc20_approval_tx_signer_mismatch";
275
+ var ErrErc20ApprovalTxInvalidSignature = "erc20_approval_tx_invalid_signature";
276
+ var ErrErc20ApprovalTxParseFailed = "erc20_approval_tx_parse_failed";
277
+
278
+ // src/exact/facilitator/erc20approval.ts
279
+ import {
280
+ getAddress as getAddress2,
281
+ parseTransaction,
282
+ decodeFunctionData,
283
+ recoverTransactionAddress
284
+ } from "viem";
285
+ import {
286
+ validateErc20ApprovalGasSponsoringInfo
287
+ } from "@x402/extensions";
288
+ var APPROVE_SELECTOR = "0x095ea7b3";
289
+ async function validateErc20ApprovalForPayment(info, payer, tokenAddress) {
290
+ if (!validateErc20ApprovalGasSponsoringInfo(info)) {
291
+ return {
292
+ isValid: false,
293
+ invalidReason: ErrErc20ApprovalInvalidFormat,
294
+ invalidMessage: "ERC-20 approval extension info failed schema validation"
295
+ };
296
+ }
297
+ if (getAddress2(info.from) !== getAddress2(payer)) {
298
+ return {
299
+ isValid: false,
300
+ invalidReason: ErrErc20ApprovalFromMismatch,
301
+ invalidMessage: `Expected from=${payer}, got ${info.from}`
302
+ };
303
+ }
304
+ if (getAddress2(info.asset) !== tokenAddress) {
305
+ return {
306
+ isValid: false,
307
+ invalidReason: ErrErc20ApprovalAssetMismatch,
308
+ invalidMessage: `Expected asset=${tokenAddress}, got ${info.asset}`
309
+ };
310
+ }
311
+ if (getAddress2(info.spender) !== getAddress2(PERMIT2_ADDRESS)) {
312
+ return {
313
+ isValid: false,
314
+ invalidReason: ErrErc20ApprovalSpenderNotPermit2,
315
+ invalidMessage: `Expected spender=${PERMIT2_ADDRESS}, got ${info.spender}`
316
+ };
317
+ }
318
+ try {
319
+ const serializedTx = info.signedTransaction;
320
+ const tx = parseTransaction(serializedTx);
321
+ if (!tx.to || getAddress2(tx.to) !== tokenAddress) {
322
+ return {
323
+ isValid: false,
324
+ invalidReason: ErrErc20ApprovalTxWrongTarget,
325
+ invalidMessage: `Transaction targets ${tx.to ?? "null"}, expected ${tokenAddress}`
326
+ };
327
+ }
328
+ const data = tx.data ?? "0x";
329
+ if (!data.startsWith(APPROVE_SELECTOR)) {
330
+ return {
331
+ isValid: false,
332
+ invalidReason: ErrErc20ApprovalTxWrongSelector,
333
+ invalidMessage: `Transaction calldata does not start with approve() selector ${APPROVE_SELECTOR}`
334
+ };
335
+ }
336
+ try {
337
+ const decoded = decodeFunctionData({
338
+ abi: erc20ApproveAbi,
339
+ data
340
+ });
341
+ const calldataSpender = getAddress2(decoded.args[0]);
342
+ if (calldataSpender !== getAddress2(PERMIT2_ADDRESS)) {
343
+ return {
344
+ isValid: false,
345
+ invalidReason: ErrErc20ApprovalTxWrongSpender,
346
+ invalidMessage: `approve() spender is ${calldataSpender}, expected Permit2 ${PERMIT2_ADDRESS}`
347
+ };
348
+ }
349
+ } catch {
350
+ return {
351
+ isValid: false,
352
+ invalidReason: ErrErc20ApprovalTxInvalidCalldata,
353
+ invalidMessage: "Failed to decode approve() calldata from the signed transaction"
354
+ };
355
+ }
356
+ try {
357
+ const recoveredAddress = await recoverTransactionAddress({
358
+ serializedTransaction: serializedTx
359
+ });
360
+ if (getAddress2(recoveredAddress) !== getAddress2(payer)) {
361
+ return {
362
+ isValid: false,
363
+ invalidReason: ErrErc20ApprovalTxSignerMismatch,
364
+ invalidMessage: `Transaction signed by ${recoveredAddress}, expected payer ${payer}`
365
+ };
366
+ }
367
+ } catch {
368
+ return {
369
+ isValid: false,
370
+ invalidReason: ErrErc20ApprovalTxInvalidSignature,
371
+ invalidMessage: "Failed to recover signer from the signed transaction"
372
+ };
373
+ }
374
+ } catch {
375
+ return {
376
+ isValid: false,
377
+ invalidReason: ErrErc20ApprovalTxParseFailed,
378
+ invalidMessage: "Failed to parse the signed transaction"
379
+ };
380
+ }
381
+ return { isValid: true };
382
+ }
383
+
384
+ // src/exact/facilitator/permit2.ts
385
+ async function verifyPermit2(signer, payload, requirements, permit2Payload, context) {
265
386
  const payer = permit2Payload.permit2Authorization.from;
266
387
  if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") {
267
388
  return {
@@ -277,16 +398,16 @@ async function verifyPermit2(signer, payload, requirements, permit2Payload) {
277
398
  payer
278
399
  };
279
400
  }
280
- const chainId = parseInt(requirements.network.split(":")[1]);
281
- const tokenAddress = getAddress2(requirements.asset);
282
- if (getAddress2(permit2Payload.permit2Authorization.spender) !== getAddress2(x402ExactPermit2ProxyAddress)) {
401
+ const chainId = getEvmChainId(requirements.network);
402
+ const tokenAddress = getAddress3(requirements.asset);
403
+ if (getAddress3(permit2Payload.permit2Authorization.spender) !== getAddress3(x402ExactPermit2ProxyAddress)) {
283
404
  return {
284
405
  isValid: false,
285
406
  invalidReason: "invalid_permit2_spender",
286
407
  payer
287
408
  };
288
409
  }
289
- if (getAddress2(permit2Payload.permit2Authorization.witness.to) !== getAddress2(requirements.payTo)) {
410
+ if (getAddress3(permit2Payload.permit2Authorization.witness.to) !== getAddress3(requirements.payTo)) {
290
411
  return {
291
412
  isValid: false,
292
413
  invalidReason: "invalid_permit2_recipient_mismatch",
@@ -315,7 +436,7 @@ async function verifyPermit2(signer, payload, requirements, permit2Payload) {
315
436
  payer
316
437
  };
317
438
  }
318
- if (getAddress2(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) {
439
+ if (getAddress3(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) {
319
440
  return {
320
441
  isValid: false,
321
442
  invalidReason: "permit2_token_mismatch",
@@ -332,16 +453,15 @@ async function verifyPermit2(signer, payload, requirements, permit2Payload) {
332
453
  },
333
454
  message: {
334
455
  permitted: {
335
- token: getAddress2(permit2Payload.permit2Authorization.permitted.token),
456
+ token: getAddress3(permit2Payload.permit2Authorization.permitted.token),
336
457
  amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
337
458
  },
338
- spender: getAddress2(permit2Payload.permit2Authorization.spender),
459
+ spender: getAddress3(permit2Payload.permit2Authorization.spender),
339
460
  nonce: BigInt(permit2Payload.permit2Authorization.nonce),
340
461
  deadline: BigInt(permit2Payload.permit2Authorization.deadline),
341
462
  witness: {
342
- to: getAddress2(permit2Payload.permit2Authorization.witness.to),
343
- validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),
344
- extra: permit2Payload.permit2Authorization.witness.extra
463
+ to: getAddress3(permit2Payload.permit2Authorization.witness.to),
464
+ validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
345
465
  }
346
466
  }
347
467
  };
@@ -365,44 +485,16 @@ async function verifyPermit2(signer, payload, requirements, permit2Payload) {
365
485
  payer
366
486
  };
367
487
  }
368
- try {
369
- const allowance = await signer.readContract({
370
- address: tokenAddress,
371
- abi: erc20AllowanceABI,
372
- functionName: "allowance",
373
- args: [payer, PERMIT2_ADDRESS]
374
- });
375
- if (allowance < BigInt(requirements.amount)) {
376
- const eip2612Info = extractEip2612GasSponsoringInfo(payload);
377
- if (eip2612Info) {
378
- const validationResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);
379
- if (!validationResult.isValid) {
380
- return {
381
- isValid: false,
382
- invalidReason: validationResult.invalidReason,
383
- payer
384
- };
385
- }
386
- } else {
387
- return {
388
- isValid: false,
389
- invalidReason: "permit2_allowance_required",
390
- payer
391
- };
392
- }
393
- }
394
- } catch {
395
- const eip2612Info = extractEip2612GasSponsoringInfo(payload);
396
- if (eip2612Info) {
397
- const validationResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);
398
- if (!validationResult.isValid) {
399
- return {
400
- isValid: false,
401
- invalidReason: validationResult.invalidReason,
402
- payer
403
- };
404
- }
405
- }
488
+ const allowanceResult = await _verifyPermit2Allowance(
489
+ signer,
490
+ payload,
491
+ requirements,
492
+ payer,
493
+ tokenAddress,
494
+ context
495
+ );
496
+ if (allowanceResult) {
497
+ return allowanceResult;
406
498
  }
407
499
  try {
408
500
  const balance = await signer.readContract({
@@ -427,9 +519,53 @@ async function verifyPermit2(signer, payload, requirements, permit2Payload) {
427
519
  payer
428
520
  };
429
521
  }
430
- async function settlePermit2(signer, payload, requirements, permit2Payload) {
522
+ async function _verifyPermit2Allowance(signer, payload, requirements, payer, tokenAddress, context) {
523
+ try {
524
+ const allowance = await signer.readContract({
525
+ address: tokenAddress,
526
+ abi: erc20AllowanceAbi,
527
+ functionName: "allowance",
528
+ args: [payer, PERMIT2_ADDRESS]
529
+ });
530
+ if (allowance >= BigInt(requirements.amount)) {
531
+ return null;
532
+ }
533
+ const eip2612Info = extractEip2612GasSponsoringInfo(payload);
534
+ if (eip2612Info) {
535
+ const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);
536
+ if (!result.isValid) {
537
+ return { isValid: false, invalidReason: result.invalidReason, payer };
538
+ }
539
+ return null;
540
+ }
541
+ const erc20GasSponsorshipExtension = context?.getExtension(
542
+ ERC20_APPROVAL_GAS_SPONSORING.key
543
+ );
544
+ if (erc20GasSponsorshipExtension) {
545
+ const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);
546
+ if (erc20Info) {
547
+ const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);
548
+ if (!result.isValid) {
549
+ return { isValid: false, invalidReason: result.invalidReason, payer };
550
+ }
551
+ return null;
552
+ }
553
+ }
554
+ return { isValid: false, invalidReason: "permit2_allowance_required", payer };
555
+ } catch {
556
+ const eip2612Info = extractEip2612GasSponsoringInfo(payload);
557
+ if (eip2612Info) {
558
+ const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);
559
+ if (!result.isValid) {
560
+ return { isValid: false, invalidReason: result.invalidReason, payer };
561
+ }
562
+ }
563
+ return null;
564
+ }
565
+ }
566
+ async function settlePermit2(signer, payload, requirements, permit2Payload, context) {
431
567
  const payer = permit2Payload.permit2Authorization.from;
432
- const valid = await verifyPermit2(signer, payload, requirements, permit2Payload);
568
+ const valid = await verifyPermit2(signer, payload, requirements, permit2Payload, context);
433
569
  if (!valid.isValid) {
434
570
  return {
435
571
  success: false,
@@ -439,120 +575,195 @@ async function settlePermit2(signer, payload, requirements, permit2Payload) {
439
575
  payer
440
576
  };
441
577
  }
578
+ const eip2612Info = extractEip2612GasSponsoringInfo(payload);
579
+ if (eip2612Info) {
580
+ return _settlePermit2WithEIP2612(signer, payload, permit2Payload, eip2612Info);
581
+ }
582
+ const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);
583
+ if (erc20Info) {
584
+ const erc20GasSponsorshipExtension = context?.getExtension(
585
+ ERC20_APPROVAL_GAS_SPONSORING.key
586
+ );
587
+ if (erc20GasSponsorshipExtension?.signer) {
588
+ return _settlePermit2WithERC20Approval(
589
+ erc20GasSponsorshipExtension.signer,
590
+ payload,
591
+ permit2Payload,
592
+ erc20Info
593
+ );
594
+ }
595
+ }
596
+ return _settlePermit2Direct(signer, payload, permit2Payload);
597
+ }
598
+ async function _settlePermit2WithEIP2612(signer, payload, permit2Payload, eip2612Info) {
599
+ const payer = permit2Payload.permit2Authorization.from;
442
600
  try {
443
- const eip2612Info = extractEip2612GasSponsoringInfo(payload);
444
- let tx;
445
- if (eip2612Info) {
446
- const { v, r, s } = splitEip2612Signature(eip2612Info.signature);
447
- tx = await signer.writeContract({
448
- address: x402ExactPermit2ProxyAddress,
449
- abi: x402ExactPermit2ProxyABI,
450
- functionName: "settleWithPermit",
451
- args: [
452
- {
453
- value: BigInt(eip2612Info.amount),
454
- deadline: BigInt(eip2612Info.deadline),
455
- r,
456
- s,
457
- v
458
- },
459
- {
460
- permitted: {
461
- token: getAddress2(permit2Payload.permit2Authorization.permitted.token),
462
- amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
463
- },
464
- nonce: BigInt(permit2Payload.permit2Authorization.nonce),
465
- deadline: BigInt(permit2Payload.permit2Authorization.deadline)
466
- },
467
- getAddress2(payer),
468
- {
469
- to: getAddress2(permit2Payload.permit2Authorization.witness.to),
470
- validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),
471
- extra: permit2Payload.permit2Authorization.witness.extra
472
- },
473
- permit2Payload.signature
474
- ]
475
- });
476
- } else {
477
- tx = await signer.writeContract({
478
- address: x402ExactPermit2ProxyAddress,
479
- abi: x402ExactPermit2ProxyABI,
480
- functionName: "settle",
481
- args: [
482
- {
483
- permitted: {
484
- token: getAddress2(permit2Payload.permit2Authorization.permitted.token),
485
- amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
486
- },
487
- nonce: BigInt(permit2Payload.permit2Authorization.nonce),
488
- deadline: BigInt(permit2Payload.permit2Authorization.deadline)
489
- },
490
- getAddress2(payer),
491
- {
492
- to: getAddress2(permit2Payload.permit2Authorization.witness.to),
493
- validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),
494
- extra: permit2Payload.permit2Authorization.witness.extra
601
+ const { v, r, s } = splitEip2612Signature(eip2612Info.signature);
602
+ const tx = await signer.writeContract({
603
+ address: x402ExactPermit2ProxyAddress,
604
+ abi: x402ExactPermit2ProxyABI,
605
+ functionName: "settleWithPermit",
606
+ args: [
607
+ {
608
+ value: BigInt(eip2612Info.amount),
609
+ deadline: BigInt(eip2612Info.deadline),
610
+ r,
611
+ s,
612
+ v
613
+ },
614
+ {
615
+ permitted: {
616
+ token: getAddress3(permit2Payload.permit2Authorization.permitted.token),
617
+ amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
495
618
  },
496
- permit2Payload.signature
497
- ]
498
- });
499
- }
500
- const receipt = await signer.waitForTransactionReceipt({ hash: tx });
501
- if (receipt.status !== "success") {
619
+ nonce: BigInt(permit2Payload.permit2Authorization.nonce),
620
+ deadline: BigInt(permit2Payload.permit2Authorization.deadline)
621
+ },
622
+ getAddress3(payer),
623
+ {
624
+ to: getAddress3(permit2Payload.permit2Authorization.witness.to),
625
+ validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
626
+ },
627
+ permit2Payload.signature
628
+ ]
629
+ });
630
+ return _waitAndReturn(signer, tx, payload, payer);
631
+ } catch (error) {
632
+ return _mapSettleError(error, payload, payer);
633
+ }
634
+ }
635
+ async function _settlePermit2WithERC20Approval(extensionSigner, payload, permit2Payload, erc20Info) {
636
+ const payer = permit2Payload.permit2Authorization.from;
637
+ try {
638
+ const approvalTxHash = await extensionSigner.sendRawTransaction({
639
+ serializedTransaction: erc20Info.signedTransaction
640
+ });
641
+ const approvalReceipt = await extensionSigner.waitForTransactionReceipt({
642
+ hash: approvalTxHash
643
+ });
644
+ if (approvalReceipt.status !== "success") {
502
645
  return {
503
646
  success: false,
504
- errorReason: "invalid_transaction_state",
505
- transaction: tx,
647
+ errorReason: "erc20_approval_tx_failed",
648
+ transaction: approvalTxHash,
506
649
  network: payload.accepted.network,
507
650
  payer
508
651
  };
509
652
  }
510
- return {
511
- success: true,
512
- transaction: tx,
513
- network: payload.accepted.network,
514
- payer
515
- };
653
+ const tx = await extensionSigner.writeContract({
654
+ address: x402ExactPermit2ProxyAddress,
655
+ abi: x402ExactPermit2ProxyABI,
656
+ functionName: "settle",
657
+ args: [
658
+ {
659
+ permitted: {
660
+ token: getAddress3(permit2Payload.permit2Authorization.permitted.token),
661
+ amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
662
+ },
663
+ nonce: BigInt(permit2Payload.permit2Authorization.nonce),
664
+ deadline: BigInt(permit2Payload.permit2Authorization.deadline)
665
+ },
666
+ getAddress3(payer),
667
+ {
668
+ to: getAddress3(permit2Payload.permit2Authorization.witness.to),
669
+ validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
670
+ },
671
+ permit2Payload.signature
672
+ ]
673
+ });
674
+ return _waitAndReturn(extensionSigner, tx, payload, payer);
516
675
  } catch (error) {
517
- let errorReason = "transaction_failed";
518
- if (error instanceof Error) {
519
- const message = error.message;
520
- if (message.includes("AmountExceedsPermitted")) {
521
- errorReason = "permit2_amount_exceeds_permitted";
522
- } else if (message.includes("InvalidDestination")) {
523
- errorReason = "permit2_invalid_destination";
524
- } else if (message.includes("InvalidOwner")) {
525
- errorReason = "permit2_invalid_owner";
526
- } else if (message.includes("PaymentTooEarly")) {
527
- errorReason = "permit2_payment_too_early";
528
- } else if (message.includes("InvalidSignature") || message.includes("SignatureExpired")) {
529
- errorReason = "permit2_invalid_signature";
530
- } else if (message.includes("InvalidNonce")) {
531
- errorReason = "permit2_invalid_nonce";
532
- } else {
533
- errorReason = `transaction_failed: ${message.slice(0, 500)}`;
534
- }
535
- }
676
+ return _mapSettleError(error, payload, payer);
677
+ }
678
+ }
679
+ async function _settlePermit2Direct(signer, payload, permit2Payload) {
680
+ const payer = permit2Payload.permit2Authorization.from;
681
+ try {
682
+ const tx = await signer.writeContract({
683
+ address: x402ExactPermit2ProxyAddress,
684
+ abi: x402ExactPermit2ProxyABI,
685
+ functionName: "settle",
686
+ args: [
687
+ {
688
+ permitted: {
689
+ token: getAddress3(permit2Payload.permit2Authorization.permitted.token),
690
+ amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
691
+ },
692
+ nonce: BigInt(permit2Payload.permit2Authorization.nonce),
693
+ deadline: BigInt(permit2Payload.permit2Authorization.deadline)
694
+ },
695
+ getAddress3(payer),
696
+ {
697
+ to: getAddress3(permit2Payload.permit2Authorization.witness.to),
698
+ validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
699
+ },
700
+ permit2Payload.signature
701
+ ]
702
+ });
703
+ return _waitAndReturn(signer, tx, payload, payer);
704
+ } catch (error) {
705
+ return _mapSettleError(error, payload, payer);
706
+ }
707
+ }
708
+ async function _waitAndReturn(signer, tx, payload, payer) {
709
+ const receipt = await signer.waitForTransactionReceipt({ hash: tx });
710
+ if (receipt.status !== "success") {
536
711
  return {
537
712
  success: false,
538
- errorReason,
539
- transaction: "",
713
+ errorReason: "invalid_transaction_state",
714
+ transaction: tx,
540
715
  network: payload.accepted.network,
541
716
  payer
542
717
  };
543
718
  }
719
+ return {
720
+ success: true,
721
+ transaction: tx,
722
+ network: payload.accepted.network,
723
+ payer
724
+ };
725
+ }
726
+ function _mapSettleError(error, payload, payer) {
727
+ let errorReason = "transaction_failed";
728
+ if (error instanceof Error) {
729
+ const message = error.message;
730
+ if (message.includes("Permit2612AmountMismatch")) {
731
+ errorReason = ErrPermit2612AmountMismatch;
732
+ } else if (message.includes("InvalidAmount")) {
733
+ errorReason = ErrPermit2InvalidAmount;
734
+ } else if (message.includes("InvalidDestination")) {
735
+ errorReason = ErrPermit2InvalidDestination;
736
+ } else if (message.includes("InvalidOwner")) {
737
+ errorReason = ErrPermit2InvalidOwner;
738
+ } else if (message.includes("PaymentTooEarly")) {
739
+ errorReason = ErrPermit2PaymentTooEarly;
740
+ } else if (message.includes("InvalidSignature") || message.includes("SignatureExpired")) {
741
+ errorReason = ErrPermit2InvalidSignature;
742
+ } else if (message.includes("InvalidNonce")) {
743
+ errorReason = ErrPermit2InvalidNonce;
744
+ } else {
745
+ errorReason = `transaction_failed: ${message.slice(0, 500)}`;
746
+ }
747
+ }
748
+ return {
749
+ success: false,
750
+ errorReason,
751
+ transaction: "",
752
+ network: payload.accepted.network,
753
+ payer
754
+ };
544
755
  }
545
756
  function validateEip2612PermitForPayment(info, payer, tokenAddress) {
546
757
  if (!validateEip2612GasSponsoringInfo(info)) {
547
758
  return { isValid: false, invalidReason: "invalid_eip2612_extension_format" };
548
759
  }
549
- if (getAddress2(info.from) !== getAddress2(payer)) {
760
+ if (getAddress3(info.from) !== getAddress3(payer)) {
550
761
  return { isValid: false, invalidReason: "eip2612_from_mismatch" };
551
762
  }
552
- if (getAddress2(info.asset) !== tokenAddress) {
763
+ if (getAddress3(info.asset) !== tokenAddress) {
553
764
  return { isValid: false, invalidReason: "eip2612_asset_mismatch" };
554
765
  }
555
- if (getAddress2(info.spender) !== getAddress2(PERMIT2_ADDRESS)) {
766
+ if (getAddress3(info.spender) !== getAddress3(PERMIT2_ADDRESS)) {
556
767
  return { isValid: false, invalidReason: "eip2612_spender_not_permit2" };
557
768
  }
558
769
  const now = Math.floor(Date.now() / 1e3);
@@ -577,10 +788,10 @@ function splitEip2612Signature(signature) {
577
788
  // src/exact/facilitator/scheme.ts
578
789
  var ExactEvmScheme = class {
579
790
  /**
580
- * Creates a new ExactEvmFacilitator instance.
791
+ * Creates a new ExactEvmScheme facilitator instance.
581
792
  *
582
793
  * @param signer - The EVM signer for facilitator operations
583
- * @param config - Optional configuration for the facilitator
794
+ * @param config - Optional configuration
584
795
  */
585
796
  constructor(signer, config) {
586
797
  this.signer = signer;
@@ -591,53 +802,51 @@ var ExactEvmScheme = class {
591
802
  };
592
803
  }
593
804
  /**
594
- * Get mechanism-specific extra data for the supported kinds endpoint.
595
- * For EVM, no extra data is needed.
805
+ * Returns undefined — EVM has no mechanism-specific extra data.
596
806
  *
597
- * @param _ - The network identifier (unused for EVM)
598
- * @returns undefined (EVM has no extra data)
807
+ * @param _ - The network identifier (unused)
808
+ * @returns undefined
599
809
  */
600
810
  getExtra(_) {
601
811
  return void 0;
602
812
  }
603
813
  /**
604
- * Get signer addresses used by this facilitator.
605
- * Returns all addresses this facilitator can use for signing/settling transactions.
814
+ * Returns facilitator wallet addresses for the supported response.
606
815
  *
607
- * @param _ - The network identifier (unused for EVM, addresses are network-agnostic)
816
+ * @param _ - The network identifier (unused, addresses are network-agnostic)
608
817
  * @returns Array of facilitator wallet addresses
609
818
  */
610
819
  getSigners(_) {
611
820
  return [...this.signer.getAddresses()];
612
821
  }
613
822
  /**
614
- * Verifies a payment payload.
615
- * Routes to the appropriate verification logic based on payload type.
823
+ * Verifies a payment payload. Routes to Permit2 or EIP-3009 based on payload type.
616
824
  *
617
825
  * @param payload - The payment payload to verify
618
826
  * @param requirements - The payment requirements
827
+ * @param context - Optional facilitator context for extension capabilities
619
828
  * @returns Promise resolving to verification response
620
829
  */
621
- async verify(payload, requirements) {
830
+ async verify(payload, requirements, context) {
622
831
  const rawPayload = payload.payload;
623
832
  if (isPermit2Payload(rawPayload)) {
624
- return verifyPermit2(this.signer, payload, requirements, rawPayload);
833
+ return verifyPermit2(this.signer, payload, requirements, rawPayload, context);
625
834
  }
626
835
  const eip3009Payload = rawPayload;
627
836
  return verifyEIP3009(this.signer, payload, requirements, eip3009Payload);
628
837
  }
629
838
  /**
630
- * Settles a payment by executing the transfer.
631
- * Routes to the appropriate settlement logic based on payload type.
839
+ * Settles a payment. Routes to Permit2 or EIP-3009 based on payload type.
632
840
  *
633
841
  * @param payload - The payment payload to settle
634
842
  * @param requirements - The payment requirements
843
+ * @param context - Optional facilitator context for extension capabilities
635
844
  * @returns Promise resolving to settlement response
636
845
  */
637
- async settle(payload, requirements) {
846
+ async settle(payload, requirements, context) {
638
847
  const rawPayload = payload.payload;
639
848
  if (isPermit2Payload(rawPayload)) {
640
- return settlePermit2(this.signer, payload, requirements, rawPayload);
849
+ return settlePermit2(this.signer, payload, requirements, rawPayload, context);
641
850
  }
642
851
  const eip3009Payload = rawPayload;
643
852
  return settleEIP3009(this.signer, payload, requirements, eip3009Payload, this.config);