@x402/evm 2.6.0 → 2.8.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 (46) hide show
  1. package/README.md +29 -4
  2. package/dist/cjs/exact/client/index.d.ts +12 -5
  3. package/dist/cjs/exact/client/index.js +127 -28
  4. package/dist/cjs/exact/client/index.js.map +1 -1
  5. package/dist/cjs/exact/facilitator/index.d.ts +13 -1
  6. package/dist/cjs/exact/facilitator/index.js +987 -606
  7. package/dist/cjs/exact/facilitator/index.js.map +1 -1
  8. package/dist/cjs/exact/v1/client/index.d.ts +1 -1
  9. package/dist/cjs/exact/v1/client/index.js +11 -5
  10. package/dist/cjs/exact/v1/client/index.js.map +1 -1
  11. package/dist/cjs/exact/v1/facilitator/index.d.ts +16 -1
  12. package/dist/cjs/exact/v1/facilitator/index.js +414 -177
  13. package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
  14. package/dist/cjs/index.d.ts +2 -2
  15. package/dist/cjs/index.js +143 -30
  16. package/dist/cjs/index.js.map +1 -1
  17. package/dist/cjs/{permit2-DHAq6FTe.d.ts → permit2-U9Zolx3O.d.ts} +38 -5
  18. package/dist/{esm/signer-DC81R8wQ.d.mts → cjs/signer-D912R4mq.d.ts} +9 -3
  19. package/dist/cjs/v1/index.d.ts +1 -1
  20. package/dist/cjs/v1/index.js +6 -0
  21. package/dist/cjs/v1/index.js.map +1 -1
  22. package/dist/esm/chunk-GD4MKCN7.mjs +57 -0
  23. package/dist/esm/chunk-GD4MKCN7.mjs.map +1 -0
  24. package/dist/esm/{chunk-XL6IFXCP.mjs → chunk-IZEI7JTG.mjs} +516 -178
  25. package/dist/esm/chunk-IZEI7JTG.mjs.map +1 -0
  26. package/dist/esm/{chunk-LBIJBD7Q.mjs → chunk-WJWNS4G4.mjs} +113 -20
  27. package/dist/esm/chunk-WJWNS4G4.mjs.map +1 -0
  28. package/dist/esm/exact/client/index.d.mts +12 -5
  29. package/dist/esm/exact/client/index.mjs +3 -2
  30. package/dist/esm/exact/facilitator/index.d.mts +13 -1
  31. package/dist/esm/exact/facilitator/index.mjs +498 -391
  32. package/dist/esm/exact/facilitator/index.mjs.map +1 -1
  33. package/dist/esm/exact/v1/client/index.d.mts +1 -1
  34. package/dist/esm/exact/v1/client/index.mjs +1 -1
  35. package/dist/esm/exact/v1/facilitator/index.d.mts +16 -1
  36. package/dist/esm/exact/v1/facilitator/index.mjs +1 -1
  37. package/dist/esm/index.d.mts +2 -2
  38. package/dist/esm/index.mjs +7 -9
  39. package/dist/esm/index.mjs.map +1 -1
  40. package/dist/esm/{permit2-BuAhWvNC.d.mts → permit2-Bbh3a8_h.d.mts} +38 -5
  41. package/dist/{cjs/signer-DC81R8wQ.d.ts → esm/signer-D912R4mq.d.mts} +9 -3
  42. package/dist/esm/v1/index.d.mts +1 -1
  43. package/dist/esm/v1/index.mjs +1 -1
  44. package/package.json +2 -3
  45. package/dist/esm/chunk-LBIJBD7Q.mjs.map +0 -1
  46. package/dist/esm/chunk-XL6IFXCP.mjs.map +0 -1
@@ -75,6 +75,23 @@ var eip3009ABI = [
75
75
  outputs: [{ name: "", type: "string" }],
76
76
  stateMutability: "view",
77
77
  type: "function"
78
+ },
79
+ {
80
+ inputs: [],
81
+ name: "name",
82
+ outputs: [{ name: "", type: "string" }],
83
+ stateMutability: "view",
84
+ type: "function"
85
+ },
86
+ {
87
+ inputs: [
88
+ { name: "authorizer", type: "address" },
89
+ { name: "nonce", type: "bytes32" }
90
+ ],
91
+ name: "authorizationState",
92
+ outputs: [{ name: "", type: "bool" }],
93
+ stateMutability: "view",
94
+ type: "function"
78
95
  }
79
96
  ];
80
97
  var eip2612PermitTypes = {
@@ -352,7 +369,306 @@ var ExactEvmSchemeV1 = class {
352
369
  };
353
370
 
354
371
  // src/exact/v1/facilitator/scheme.ts
355
- import { getAddress as getAddress2, isAddressEqual, parseErc6492Signature, parseSignature } from "viem";
372
+ import { getAddress as getAddress3, isAddressEqual, parseErc6492Signature as parseErc6492Signature2 } from "viem";
373
+
374
+ // src/exact/facilitator/errors.ts
375
+ var ErrInvalidScheme = "invalid_exact_evm_scheme";
376
+ var ErrNetworkMismatch = "invalid_exact_evm_network_mismatch";
377
+ var ErrMissingEip712Domain = "invalid_exact_evm_missing_eip712_domain";
378
+ var ErrRecipientMismatch = "invalid_exact_evm_recipient_mismatch";
379
+ var ErrInvalidSignature = "invalid_exact_evm_signature";
380
+ var ErrValidBeforeExpired = "invalid_exact_evm_payload_authorization_valid_before";
381
+ var ErrValidAfterInFuture = "invalid_exact_evm_payload_authorization_valid_after";
382
+ var ErrInvalidAuthorizationValue = "invalid_exact_evm_authorization_value";
383
+ var ErrUndeployedSmartWallet = "invalid_exact_evm_payload_undeployed_smart_wallet";
384
+ var ErrTransactionFailed = "invalid_exact_evm_transaction_failed";
385
+ var ErrEip3009TokenNameMismatch = "invalid_exact_evm_token_name_mismatch";
386
+ var ErrEip3009TokenVersionMismatch = "invalid_exact_evm_token_version_mismatch";
387
+ var ErrEip3009NotSupported = "invalid_exact_evm_eip3009_not_supported";
388
+ var ErrEip3009NonceAlreadyUsed = "invalid_exact_evm_nonce_already_used";
389
+ var ErrEip3009InsufficientBalance = "invalid_exact_evm_insufficient_balance";
390
+ var ErrEip3009SimulationFailed = "invalid_exact_evm_transaction_simulation_failed";
391
+ var ErrPermit2InvalidSpender = "invalid_permit2_spender";
392
+ var ErrPermit2RecipientMismatch = "invalid_permit2_recipient_mismatch";
393
+ var ErrPermit2DeadlineExpired = "permit2_deadline_expired";
394
+ var ErrPermit2NotYetValid = "permit2_not_yet_valid";
395
+ var ErrPermit2AmountMismatch = "permit2_amount_mismatch";
396
+ var ErrPermit2TokenMismatch = "permit2_token_mismatch";
397
+ var ErrPermit2InvalidSignature = "invalid_permit2_signature";
398
+ var ErrPermit2AllowanceRequired = "permit2_allowance_required";
399
+ var ErrPermit2SimulationFailed = "permit2_simulation_failed";
400
+ var ErrPermit2InsufficientBalance = "permit2_insufficient_balance";
401
+ var ErrPermit2ProxyNotDeployed = "permit2_proxy_not_deployed";
402
+ var ErrPermit2InvalidAmount = "permit2_invalid_amount";
403
+ var ErrPermit2InvalidDestination = "permit2_invalid_destination";
404
+ var ErrPermit2InvalidOwner = "permit2_invalid_owner";
405
+ var ErrPermit2PaymentTooEarly = "permit2_payment_too_early";
406
+ var ErrPermit2InvalidNonce = "permit2_invalid_nonce";
407
+ var ErrPermit2612AmountMismatch = "permit2_2612_amount_mismatch";
408
+ var ErrErc20ApprovalInsufficientEthForGas = "erc20_approval_insufficient_eth_for_gas";
409
+ var ErrErc20ApprovalInvalidFormat = "invalid_erc20_approval_extension_format";
410
+ var ErrErc20ApprovalFromMismatch = "erc20_approval_from_mismatch";
411
+ var ErrErc20ApprovalAssetMismatch = "erc20_approval_asset_mismatch";
412
+ var ErrErc20ApprovalSpenderNotPermit2 = "erc20_approval_spender_not_permit2";
413
+ var ErrErc20ApprovalTxWrongTarget = "erc20_approval_tx_wrong_target";
414
+ var ErrErc20ApprovalTxWrongSelector = "erc20_approval_tx_wrong_selector";
415
+ var ErrErc20ApprovalTxWrongSpender = "erc20_approval_tx_wrong_spender";
416
+ var ErrErc20ApprovalTxInvalidCalldata = "erc20_approval_tx_invalid_calldata";
417
+ var ErrErc20ApprovalTxSignerMismatch = "erc20_approval_tx_signer_mismatch";
418
+ var ErrErc20ApprovalTxInvalidSignature = "erc20_approval_tx_invalid_signature";
419
+ var ErrErc20ApprovalTxParseFailed = "erc20_approval_tx_parse_failed";
420
+ var ErrErc20ApprovalTxFailed = "erc20_approval_tx_failed";
421
+ var ErrInvalidEip2612ExtensionFormat = "invalid_eip2612_extension_format";
422
+ var ErrEip2612FromMismatch = "eip2612_from_mismatch";
423
+ var ErrEip2612AssetMismatch = "eip2612_asset_mismatch";
424
+ var ErrEip2612SpenderNotPermit2 = "eip2612_spender_not_permit2";
425
+ var ErrEip2612DeadlineExpired = "eip2612_deadline_expired";
426
+ var ErrUnsupportedPayloadType = "unsupported_payload_type";
427
+ var ErrInvalidTransactionState = "invalid_transaction_state";
428
+
429
+ // src/exact/facilitator/eip3009-utils.ts
430
+ import { encodeFunctionData as encodeFunctionData2, getAddress as getAddress2, parseErc6492Signature, parseSignature } from "viem";
431
+
432
+ // src/multicall.ts
433
+ import { encodeFunctionData, decodeFunctionResult } from "viem";
434
+ var MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
435
+ var multicall3GetEthBalanceAbi = [
436
+ {
437
+ name: "getEthBalance",
438
+ inputs: [{ name: "addr", type: "address" }],
439
+ outputs: [{ name: "balance", type: "uint256" }],
440
+ stateMutability: "view",
441
+ type: "function"
442
+ }
443
+ ];
444
+ var multicall3ABI = [
445
+ {
446
+ inputs: [
447
+ { name: "requireSuccess", type: "bool" },
448
+ {
449
+ name: "calls",
450
+ type: "tuple[]",
451
+ components: [
452
+ { name: "target", type: "address" },
453
+ { name: "callData", type: "bytes" }
454
+ ]
455
+ }
456
+ ],
457
+ name: "tryAggregate",
458
+ outputs: [
459
+ {
460
+ name: "returnData",
461
+ type: "tuple[]",
462
+ components: [
463
+ { name: "success", type: "bool" },
464
+ { name: "returnData", type: "bytes" }
465
+ ]
466
+ }
467
+ ],
468
+ stateMutability: "payable",
469
+ type: "function"
470
+ }
471
+ ];
472
+ async function multicall(readContract, calls) {
473
+ const aggregateCalls = calls.map((call) => {
474
+ if ("callData" in call) {
475
+ return { target: call.address, callData: call.callData };
476
+ }
477
+ const callData = encodeFunctionData({
478
+ abi: call.abi,
479
+ functionName: call.functionName,
480
+ args: call.args
481
+ });
482
+ return { target: call.address, callData };
483
+ });
484
+ const rawResults = await readContract({
485
+ address: MULTICALL3_ADDRESS,
486
+ abi: multicall3ABI,
487
+ functionName: "tryAggregate",
488
+ args: [false, aggregateCalls]
489
+ });
490
+ return rawResults.map((raw, i) => {
491
+ if (!raw.success) {
492
+ return {
493
+ status: "failure",
494
+ error: new Error(`multicall: call reverted (returnData: ${raw.returnData})`)
495
+ };
496
+ }
497
+ const call = calls[i];
498
+ if ("callData" in call) {
499
+ return { status: "success", result: void 0 };
500
+ }
501
+ try {
502
+ const decoded = decodeFunctionResult({
503
+ abi: call.abi,
504
+ functionName: call.functionName,
505
+ data: raw.returnData
506
+ });
507
+ return { status: "success", result: decoded };
508
+ } catch (err) {
509
+ return {
510
+ status: "failure",
511
+ error: err instanceof Error ? err : new Error(String(err))
512
+ };
513
+ }
514
+ });
515
+ }
516
+
517
+ // src/exact/facilitator/eip3009-utils.ts
518
+ async function simulateEip3009Transfer(signer, erc20Address, payload, eip6492Deployment) {
519
+ const auth = payload.authorization;
520
+ const transferArgs = [
521
+ getAddress2(auth.from),
522
+ getAddress2(auth.to),
523
+ BigInt(auth.value),
524
+ BigInt(auth.validAfter),
525
+ BigInt(auth.validBefore),
526
+ auth.nonce
527
+ ];
528
+ if (eip6492Deployment) {
529
+ const { signature: innerSignature } = parseErc6492Signature(payload.signature);
530
+ const transferCalldata = encodeFunctionData2({
531
+ abi: eip3009ABI,
532
+ functionName: "transferWithAuthorization",
533
+ args: [...transferArgs, innerSignature]
534
+ });
535
+ try {
536
+ const results = await multicall(signer.readContract.bind(signer), [
537
+ {
538
+ address: getAddress2(eip6492Deployment.factoryAddress),
539
+ callData: eip6492Deployment.factoryCalldata
540
+ },
541
+ {
542
+ address: erc20Address,
543
+ callData: transferCalldata
544
+ }
545
+ ]);
546
+ return results[1]?.status === "success";
547
+ } catch {
548
+ return false;
549
+ }
550
+ }
551
+ const sig = payload.signature;
552
+ const sigLength = sig.startsWith("0x") ? sig.length - 2 : sig.length;
553
+ const isECDSA = sigLength === 130;
554
+ try {
555
+ if (isECDSA) {
556
+ const parsedSig = parseSignature(sig);
557
+ await signer.readContract({
558
+ address: erc20Address,
559
+ abi: eip3009ABI,
560
+ functionName: "transferWithAuthorization",
561
+ args: [
562
+ ...transferArgs,
563
+ parsedSig.v ?? parsedSig.yParity,
564
+ parsedSig.r,
565
+ parsedSig.s
566
+ ]
567
+ });
568
+ } else {
569
+ await signer.readContract({
570
+ address: erc20Address,
571
+ abi: eip3009ABI,
572
+ functionName: "transferWithAuthorization",
573
+ args: [...transferArgs, sig]
574
+ });
575
+ }
576
+ return true;
577
+ } catch {
578
+ return false;
579
+ }
580
+ }
581
+ async function diagnoseEip3009SimulationFailure(signer, erc20Address, payload, requirements, amountRequired) {
582
+ const payer = payload.authorization.from;
583
+ const diagnosticCalls = [
584
+ {
585
+ address: erc20Address,
586
+ abi: eip3009ABI,
587
+ functionName: "balanceOf",
588
+ args: [payload.authorization.from]
589
+ },
590
+ {
591
+ address: erc20Address,
592
+ abi: eip3009ABI,
593
+ functionName: "name"
594
+ },
595
+ {
596
+ address: erc20Address,
597
+ abi: eip3009ABI,
598
+ functionName: "version"
599
+ },
600
+ {
601
+ address: erc20Address,
602
+ abi: eip3009ABI,
603
+ functionName: "authorizationState",
604
+ args: [payload.authorization.from, payload.authorization.nonce]
605
+ }
606
+ ];
607
+ try {
608
+ const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);
609
+ const [balanceResult, nameResult, versionResult, authStateResult] = results;
610
+ if (authStateResult.status === "failure") {
611
+ return { isValid: false, invalidReason: ErrEip3009NotSupported, payer };
612
+ }
613
+ if (authStateResult.status === "success" && authStateResult.result === true) {
614
+ return { isValid: false, invalidReason: ErrEip3009NonceAlreadyUsed, payer };
615
+ }
616
+ if (nameResult.status === "success" && requirements.extra?.name && nameResult.result !== requirements.extra.name) {
617
+ return { isValid: false, invalidReason: ErrEip3009TokenNameMismatch, payer };
618
+ }
619
+ if (versionResult.status === "success" && requirements.extra?.version && versionResult.result !== requirements.extra.version) {
620
+ return { isValid: false, invalidReason: ErrEip3009TokenVersionMismatch, payer };
621
+ }
622
+ if (balanceResult.status === "success") {
623
+ const balance = balanceResult.result;
624
+ if (balance < BigInt(amountRequired)) {
625
+ return {
626
+ isValid: false,
627
+ invalidReason: ErrEip3009InsufficientBalance,
628
+ payer
629
+ };
630
+ }
631
+ }
632
+ } catch {
633
+ }
634
+ return { isValid: false, invalidReason: ErrEip3009SimulationFailed, payer };
635
+ }
636
+ async function executeTransferWithAuthorization(signer, erc20Address, payload) {
637
+ const { signature } = parseErc6492Signature(payload.signature);
638
+ const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
639
+ const isECDSA = signatureLength === 130;
640
+ const auth = payload.authorization;
641
+ const baseArgs = [
642
+ getAddress2(auth.from),
643
+ getAddress2(auth.to),
644
+ BigInt(auth.value),
645
+ BigInt(auth.validAfter),
646
+ BigInt(auth.validBefore),
647
+ auth.nonce
648
+ ];
649
+ if (isECDSA) {
650
+ const parsedSig = parseSignature(signature);
651
+ return signer.writeContract({
652
+ address: erc20Address,
653
+ abi: eip3009ABI,
654
+ functionName: "transferWithAuthorization",
655
+ args: [
656
+ ...baseArgs,
657
+ parsedSig.v || parsedSig.yParity,
658
+ parsedSig.r,
659
+ parsedSig.s
660
+ ]
661
+ });
662
+ }
663
+ return signer.writeContract({
664
+ address: erc20Address,
665
+ abi: eip3009ABI,
666
+ functionName: "transferWithAuthorization",
667
+ args: [...baseArgs, signature]
668
+ });
669
+ }
670
+
671
+ // src/exact/v1/facilitator/scheme.ts
356
672
  var ExactEvmSchemeV12 = class {
357
673
  /**
358
674
  * Creates a new ExactEvmFacilitatorV1 instance.
@@ -365,7 +681,8 @@ var ExactEvmSchemeV12 = class {
365
681
  this.scheme = "exact";
366
682
  this.caipFamily = "eip155:*";
367
683
  this.config = {
368
- deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? false
684
+ deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? false,
685
+ simulateInSettle: config?.simulateInSettle ?? false
369
686
  };
370
687
  }
371
688
  /**
@@ -396,14 +713,95 @@ var ExactEvmSchemeV12 = class {
396
713
  * @returns Promise resolving to verification response
397
714
  */
398
715
  async verify(payload, requirements) {
716
+ return this._verify(payload, requirements);
717
+ }
718
+ /**
719
+ * Settles a payment by executing the transfer (V1).
720
+ *
721
+ * @param payload - The payment payload to settle
722
+ * @param requirements - The payment requirements
723
+ * @returns Promise resolving to settlement response
724
+ */
725
+ async settle(payload, requirements) {
726
+ const payloadV1 = payload;
727
+ const exactEvmPayload = payload.payload;
728
+ const valid = await this._verify(payload, requirements, {
729
+ simulate: this.config.simulateInSettle ?? false
730
+ });
731
+ if (!valid.isValid) {
732
+ return {
733
+ success: false,
734
+ network: payloadV1.network,
735
+ transaction: "",
736
+ errorReason: valid.invalidReason ?? ErrInvalidScheme,
737
+ payer: exactEvmPayload.authorization.from
738
+ };
739
+ }
740
+ try {
741
+ const { address: factoryAddress, data: factoryCalldata } = parseErc6492Signature2(
742
+ exactEvmPayload.signature
743
+ );
744
+ if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !isAddressEqual(factoryAddress, "0x0000000000000000000000000000000000000000")) {
745
+ const payerAddress = exactEvmPayload.authorization.from;
746
+ const bytecode = await this.signer.getCode({ address: payerAddress });
747
+ if (!bytecode || bytecode === "0x") {
748
+ const deployTx = await this.signer.sendTransaction({
749
+ to: factoryAddress,
750
+ data: factoryCalldata
751
+ });
752
+ await this.signer.waitForTransactionReceipt({ hash: deployTx });
753
+ }
754
+ }
755
+ const tx = await executeTransferWithAuthorization(
756
+ this.signer,
757
+ getAddress3(requirements.asset),
758
+ exactEvmPayload
759
+ );
760
+ const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });
761
+ if (receipt.status !== "success") {
762
+ return {
763
+ success: false,
764
+ errorReason: ErrTransactionFailed,
765
+ transaction: tx,
766
+ network: payloadV1.network,
767
+ payer: exactEvmPayload.authorization.from
768
+ };
769
+ }
770
+ return {
771
+ success: true,
772
+ transaction: tx,
773
+ network: payloadV1.network,
774
+ payer: exactEvmPayload.authorization.from
775
+ };
776
+ } catch (error) {
777
+ return {
778
+ success: false,
779
+ errorReason: error instanceof Error ? error.message : ErrTransactionFailed,
780
+ transaction: "",
781
+ network: payloadV1.network,
782
+ payer: exactEvmPayload.authorization.from
783
+ };
784
+ }
785
+ }
786
+ /**
787
+ * Internal verify with optional simulation control.
788
+ *
789
+ * @param payload - The payment payload to verify
790
+ * @param requirements - The payment requirements
791
+ * @param options - Verification options (e.g. simulate)
792
+ * @returns Promise resolving to verification response
793
+ */
794
+ async _verify(payload, requirements, options) {
399
795
  const requirementsV1 = requirements;
400
796
  const payloadV1 = payload;
401
797
  const exactEvmPayload = payload.payload;
798
+ const payer = exactEvmPayload.authorization.from;
799
+ let eip6492Deployment;
402
800
  if (payloadV1.scheme !== "exact" || requirements.scheme !== "exact") {
403
801
  return {
404
802
  isValid: false,
405
- invalidReason: "unsupported_scheme",
406
- payer: exactEvmPayload.authorization.from
803
+ invalidReason: ErrInvalidScheme,
804
+ payer
407
805
  };
408
806
  }
409
807
  let chainId;
@@ -412,24 +810,24 @@ var ExactEvmSchemeV12 = class {
412
810
  } catch {
413
811
  return {
414
812
  isValid: false,
415
- invalidReason: `invalid_network`,
416
- payer: exactEvmPayload.authorization.from
813
+ invalidReason: ErrNetworkMismatch,
814
+ payer
417
815
  };
418
816
  }
419
817
  if (!requirements.extra?.name || !requirements.extra?.version) {
420
818
  return {
421
819
  isValid: false,
422
- invalidReason: "missing_eip712_domain",
423
- payer: exactEvmPayload.authorization.from
820
+ invalidReason: ErrMissingEip712Domain,
821
+ payer
424
822
  };
425
823
  }
426
824
  const { name, version } = requirements.extra;
427
- const erc20Address = getAddress2(requirements.asset);
825
+ const erc20Address = getAddress3(requirements.asset);
428
826
  if (payloadV1.network !== requirements.network) {
429
827
  return {
430
828
  isValid: false,
431
- invalidReason: "network_mismatch",
432
- payer: exactEvmPayload.authorization.from
829
+ invalidReason: ErrNetworkMismatch,
830
+ payer
433
831
  };
434
832
  }
435
833
  const permitTypedData = {
@@ -450,210 +848,97 @@ var ExactEvmSchemeV12 = class {
450
848
  nonce: exactEvmPayload.authorization.nonce
451
849
  }
452
850
  };
851
+ let isValid = false;
453
852
  try {
454
- const recoveredAddress = await this.signer.verifyTypedData({
455
- address: exactEvmPayload.authorization.from,
853
+ isValid = await this.signer.verifyTypedData({
854
+ address: payer,
456
855
  ...permitTypedData,
457
856
  signature: exactEvmPayload.signature
458
857
  });
459
- if (!recoveredAddress) {
858
+ } catch {
859
+ isValid = false;
860
+ }
861
+ const signature = exactEvmPayload.signature;
862
+ const sigLen = signature.startsWith("0x") ? signature.length - 2 : signature.length;
863
+ const erc6492Data = parseErc6492Signature2(signature);
864
+ const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !isAddressEqual(erc6492Data.address, "0x0000000000000000000000000000000000000000");
865
+ if (hasDeploymentInfo) {
866
+ eip6492Deployment = {
867
+ factoryAddress: erc6492Data.address,
868
+ factoryCalldata: erc6492Data.data
869
+ };
870
+ }
871
+ if (!isValid) {
872
+ const isSmartWallet = sigLen > 130;
873
+ if (!isSmartWallet) {
460
874
  return {
461
875
  isValid: false,
462
- invalidReason: "invalid_exact_evm_payload_signature",
463
- payer: exactEvmPayload.authorization.from
876
+ invalidReason: ErrInvalidSignature,
877
+ payer
464
878
  };
465
879
  }
466
- } catch {
467
- const signature = exactEvmPayload.signature;
468
- const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
469
- const isSmartWallet = signatureLength > 130;
470
- if (isSmartWallet) {
471
- const payerAddress = exactEvmPayload.authorization.from;
472
- const bytecode = await this.signer.getCode({ address: payerAddress });
473
- if (!bytecode || bytecode === "0x") {
474
- const erc6492Data = parseErc6492Signature(signature);
475
- const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !isAddressEqual(erc6492Data.address, "0x0000000000000000000000000000000000000000");
476
- if (!hasDeploymentInfo) {
477
- return {
478
- isValid: false,
479
- invalidReason: "invalid_exact_evm_payload_undeployed_smart_wallet",
480
- payer: payerAddress
481
- };
482
- }
483
- } else {
484
- return {
485
- isValid: false,
486
- invalidReason: "invalid_exact_evm_payload_signature",
487
- payer: exactEvmPayload.authorization.from
488
- };
489
- }
490
- } else {
880
+ const bytecode = await this.signer.getCode({ address: payer });
881
+ const isDeployed = bytecode && bytecode !== "0x";
882
+ if (!isDeployed && !hasDeploymentInfo) {
491
883
  return {
492
884
  isValid: false,
493
- invalidReason: "invalid_exact_evm_payload_signature",
494
- payer: exactEvmPayload.authorization.from
885
+ invalidReason: ErrUndeployedSmartWallet,
886
+ payer
495
887
  };
496
888
  }
497
889
  }
498
- if (getAddress2(exactEvmPayload.authorization.to) !== getAddress2(requirements.payTo)) {
890
+ if (getAddress3(exactEvmPayload.authorization.to) !== getAddress3(requirements.payTo)) {
499
891
  return {
500
892
  isValid: false,
501
- invalidReason: "invalid_exact_evm_payload_recipient_mismatch",
502
- payer: exactEvmPayload.authorization.from
893
+ invalidReason: ErrRecipientMismatch,
894
+ payer
503
895
  };
504
896
  }
505
897
  const now = Math.floor(Date.now() / 1e3);
506
898
  if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) {
507
899
  return {
508
900
  isValid: false,
509
- invalidReason: "invalid_exact_evm_payload_authorization_valid_before",
510
- payer: exactEvmPayload.authorization.from
901
+ invalidReason: ErrValidBeforeExpired,
902
+ payer
511
903
  };
512
904
  }
513
905
  if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) {
514
906
  return {
515
907
  isValid: false,
516
- invalidReason: "invalid_exact_evm_payload_authorization_valid_after",
517
- payer: exactEvmPayload.authorization.from
908
+ invalidReason: ErrValidAfterInFuture,
909
+ payer
518
910
  };
519
911
  }
520
- try {
521
- const balance = await this.signer.readContract({
522
- address: erc20Address,
523
- abi: eip3009ABI,
524
- functionName: "balanceOf",
525
- args: [exactEvmPayload.authorization.from]
526
- });
527
- if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {
528
- return {
529
- isValid: false,
530
- invalidReason: "insufficient_funds",
531
- 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.`,
532
- payer: exactEvmPayload.authorization.from
533
- };
534
- }
535
- } catch {
536
- }
537
912
  if (BigInt(exactEvmPayload.authorization.value) !== BigInt(requirementsV1.maxAmountRequired)) {
538
913
  return {
539
914
  isValid: false,
540
- invalidReason: "invalid_exact_evm_payload_authorization_value_mismatch",
541
- payer: exactEvmPayload.authorization.from
915
+ invalidReason: ErrInvalidAuthorizationValue,
916
+ payer
542
917
  };
543
918
  }
919
+ if (options?.simulate !== false) {
920
+ const simulationSucceeded = await simulateEip3009Transfer(
921
+ this.signer,
922
+ erc20Address,
923
+ exactEvmPayload,
924
+ eip6492Deployment
925
+ );
926
+ if (!simulationSucceeded) {
927
+ return diagnoseEip3009SimulationFailure(
928
+ this.signer,
929
+ erc20Address,
930
+ exactEvmPayload,
931
+ requirements,
932
+ requirementsV1.maxAmountRequired
933
+ );
934
+ }
935
+ }
544
936
  return {
545
937
  isValid: true,
546
938
  invalidReason: void 0,
547
- payer: exactEvmPayload.authorization.from
939
+ payer
548
940
  };
549
941
  }
550
- /**
551
- * Settles a payment by executing the transfer (V1).
552
- *
553
- * @param payload - The payment payload to settle
554
- * @param requirements - The payment requirements
555
- * @returns Promise resolving to settlement response
556
- */
557
- async settle(payload, requirements) {
558
- const payloadV1 = payload;
559
- const exactEvmPayload = payload.payload;
560
- const valid = await this.verify(payload, requirements);
561
- if (!valid.isValid) {
562
- return {
563
- success: false,
564
- network: payloadV1.network,
565
- transaction: "",
566
- errorReason: valid.invalidReason ?? "invalid_scheme",
567
- payer: exactEvmPayload.authorization.from
568
- };
569
- }
570
- try {
571
- const parseResult = parseErc6492Signature(exactEvmPayload.signature);
572
- const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;
573
- if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !isAddressEqual(factoryAddress, "0x0000000000000000000000000000000000000000")) {
574
- const payerAddress = exactEvmPayload.authorization.from;
575
- const bytecode = await this.signer.getCode({ address: payerAddress });
576
- if (!bytecode || bytecode === "0x") {
577
- try {
578
- console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);
579
- const deployTx = await this.signer.sendTransaction({
580
- to: factoryAddress,
581
- data: factoryCalldata
582
- });
583
- await this.signer.waitForTransactionReceipt({ hash: deployTx });
584
- console.log(`Successfully deployed smart wallet for ${payerAddress}`);
585
- } catch (deployError) {
586
- console.error("Smart wallet deployment failed:", deployError);
587
- throw deployError;
588
- }
589
- } else {
590
- console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);
591
- }
592
- }
593
- const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
594
- const isECDSA = signatureLength === 130;
595
- let tx;
596
- if (isECDSA) {
597
- const parsedSig = parseSignature(signature);
598
- tx = await this.signer.writeContract({
599
- address: getAddress2(requirements.asset),
600
- abi: eip3009ABI,
601
- functionName: "transferWithAuthorization",
602
- args: [
603
- getAddress2(exactEvmPayload.authorization.from),
604
- getAddress2(exactEvmPayload.authorization.to),
605
- BigInt(exactEvmPayload.authorization.value),
606
- BigInt(exactEvmPayload.authorization.validAfter),
607
- BigInt(exactEvmPayload.authorization.validBefore),
608
- exactEvmPayload.authorization.nonce,
609
- parsedSig.v || parsedSig.yParity,
610
- parsedSig.r,
611
- parsedSig.s
612
- ]
613
- });
614
- } else {
615
- tx = await this.signer.writeContract({
616
- address: getAddress2(requirements.asset),
617
- abi: eip3009ABI,
618
- functionName: "transferWithAuthorization",
619
- args: [
620
- getAddress2(exactEvmPayload.authorization.from),
621
- getAddress2(exactEvmPayload.authorization.to),
622
- BigInt(exactEvmPayload.authorization.value),
623
- BigInt(exactEvmPayload.authorization.validAfter),
624
- BigInt(exactEvmPayload.authorization.validBefore),
625
- exactEvmPayload.authorization.nonce,
626
- signature
627
- ]
628
- });
629
- }
630
- const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });
631
- if (receipt.status !== "success") {
632
- return {
633
- success: false,
634
- errorReason: "invalid_transaction_state",
635
- transaction: tx,
636
- network: payloadV1.network,
637
- payer: exactEvmPayload.authorization.from
638
- };
639
- }
640
- return {
641
- success: true,
642
- transaction: tx,
643
- network: payloadV1.network,
644
- payer: exactEvmPayload.authorization.from
645
- };
646
- } catch (error) {
647
- console.error("Failed to settle transaction:", error);
648
- return {
649
- success: false,
650
- errorReason: "transaction_failed",
651
- transaction: "",
652
- network: payloadV1.network,
653
- payer: exactEvmPayload.authorization.from
654
- };
655
- }
656
- }
657
942
  };
658
943
 
659
944
  // src/v1/index.ts
@@ -705,10 +990,63 @@ export {
705
990
  getEvmChainId,
706
991
  createNonce,
707
992
  createPermit2Nonce,
993
+ ErrInvalidScheme,
994
+ ErrNetworkMismatch,
995
+ ErrMissingEip712Domain,
996
+ ErrRecipientMismatch,
997
+ ErrInvalidSignature,
998
+ ErrValidBeforeExpired,
999
+ ErrValidAfterInFuture,
1000
+ ErrInvalidAuthorizationValue,
1001
+ ErrUndeployedSmartWallet,
1002
+ ErrTransactionFailed,
1003
+ ErrPermit2InvalidSpender,
1004
+ ErrPermit2RecipientMismatch,
1005
+ ErrPermit2DeadlineExpired,
1006
+ ErrPermit2NotYetValid,
1007
+ ErrPermit2AmountMismatch,
1008
+ ErrPermit2TokenMismatch,
1009
+ ErrPermit2InvalidSignature,
1010
+ ErrPermit2AllowanceRequired,
1011
+ ErrPermit2SimulationFailed,
1012
+ ErrPermit2InsufficientBalance,
1013
+ ErrPermit2ProxyNotDeployed,
1014
+ ErrPermit2InvalidAmount,
1015
+ ErrPermit2InvalidDestination,
1016
+ ErrPermit2InvalidOwner,
1017
+ ErrPermit2PaymentTooEarly,
1018
+ ErrPermit2InvalidNonce,
1019
+ ErrPermit2612AmountMismatch,
1020
+ ErrErc20ApprovalInsufficientEthForGas,
1021
+ ErrErc20ApprovalInvalidFormat,
1022
+ ErrErc20ApprovalFromMismatch,
1023
+ ErrErc20ApprovalAssetMismatch,
1024
+ ErrErc20ApprovalSpenderNotPermit2,
1025
+ ErrErc20ApprovalTxWrongTarget,
1026
+ ErrErc20ApprovalTxWrongSelector,
1027
+ ErrErc20ApprovalTxWrongSpender,
1028
+ ErrErc20ApprovalTxInvalidCalldata,
1029
+ ErrErc20ApprovalTxSignerMismatch,
1030
+ ErrErc20ApprovalTxInvalidSignature,
1031
+ ErrErc20ApprovalTxParseFailed,
1032
+ ErrErc20ApprovalTxFailed,
1033
+ ErrInvalidEip2612ExtensionFormat,
1034
+ ErrEip2612FromMismatch,
1035
+ ErrEip2612AssetMismatch,
1036
+ ErrEip2612SpenderNotPermit2,
1037
+ ErrEip2612DeadlineExpired,
1038
+ ErrUnsupportedPayloadType,
1039
+ ErrInvalidTransactionState,
1040
+ MULTICALL3_ADDRESS,
1041
+ multicall3GetEthBalanceAbi,
1042
+ multicall,
1043
+ simulateEip3009Transfer,
1044
+ diagnoseEip3009SimulationFailure,
1045
+ executeTransferWithAuthorization,
708
1046
  ExactEvmSchemeV12 as ExactEvmSchemeV1,
709
1047
  EVM_NETWORK_CHAIN_ID_MAP,
710
1048
  NETWORKS,
711
1049
  getEvmChainIdV1,
712
1050
  ExactEvmSchemeV1 as ExactEvmSchemeV12
713
1051
  };
714
- //# sourceMappingURL=chunk-XL6IFXCP.mjs.map
1052
+ //# sourceMappingURL=chunk-IZEI7JTG.mjs.map