@x402/evm 2.6.0 → 2.7.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.
- package/README.md +24 -0
- package/dist/cjs/exact/client/index.d.ts +12 -5
- package/dist/cjs/exact/client/index.js +127 -28
- package/dist/cjs/exact/client/index.js.map +1 -1
- package/dist/cjs/exact/facilitator/index.d.ts +13 -1
- package/dist/cjs/exact/facilitator/index.js +987 -606
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/v1/client/index.d.ts +1 -1
- package/dist/cjs/exact/v1/client/index.js +11 -5
- package/dist/cjs/exact/v1/client/index.js.map +1 -1
- package/dist/cjs/exact/v1/facilitator/index.d.ts +16 -1
- package/dist/cjs/exact/v1/facilitator/index.js +414 -177
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +143 -30
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/{permit2-DHAq6FTe.d.ts → permit2-U9Zolx3O.d.ts} +38 -5
- package/dist/{esm/signer-DC81R8wQ.d.mts → cjs/signer-D912R4mq.d.ts} +9 -3
- package/dist/cjs/v1/index.d.ts +1 -1
- package/dist/cjs/v1/index.js +6 -0
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/chunk-GD4MKCN7.mjs +57 -0
- package/dist/esm/chunk-GD4MKCN7.mjs.map +1 -0
- package/dist/esm/{chunk-XL6IFXCP.mjs → chunk-IZEI7JTG.mjs} +516 -178
- package/dist/esm/chunk-IZEI7JTG.mjs.map +1 -0
- package/dist/esm/{chunk-LBIJBD7Q.mjs → chunk-WJWNS4G4.mjs} +113 -20
- package/dist/esm/chunk-WJWNS4G4.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +12 -5
- package/dist/esm/exact/client/index.mjs +3 -2
- package/dist/esm/exact/facilitator/index.d.mts +13 -1
- package/dist/esm/exact/facilitator/index.mjs +498 -391
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/v1/client/index.d.mts +1 -1
- package/dist/esm/exact/v1/client/index.mjs +1 -1
- package/dist/esm/exact/v1/facilitator/index.d.mts +16 -1
- package/dist/esm/exact/v1/facilitator/index.mjs +1 -1
- package/dist/esm/index.d.mts +2 -2
- package/dist/esm/index.mjs +7 -9
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/{permit2-BuAhWvNC.d.mts → permit2-Bbh3a8_h.d.mts} +38 -5
- package/dist/{cjs/signer-DC81R8wQ.d.ts → esm/signer-D912R4mq.d.mts} +9 -3
- package/dist/esm/v1/index.d.mts +1 -1
- package/dist/esm/v1/index.mjs +1 -1
- package/package.json +2 -3
- package/dist/esm/chunk-LBIJBD7Q.mjs.map +0 -1
- 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
|
|
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:
|
|
406
|
-
payer
|
|
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:
|
|
416
|
-
payer
|
|
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:
|
|
423
|
-
payer
|
|
820
|
+
invalidReason: ErrMissingEip712Domain,
|
|
821
|
+
payer
|
|
424
822
|
};
|
|
425
823
|
}
|
|
426
824
|
const { name, version } = requirements.extra;
|
|
427
|
-
const erc20Address =
|
|
825
|
+
const erc20Address = getAddress3(requirements.asset);
|
|
428
826
|
if (payloadV1.network !== requirements.network) {
|
|
429
827
|
return {
|
|
430
828
|
isValid: false,
|
|
431
|
-
invalidReason:
|
|
432
|
-
payer
|
|
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
|
-
|
|
455
|
-
address:
|
|
853
|
+
isValid = await this.signer.verifyTypedData({
|
|
854
|
+
address: payer,
|
|
456
855
|
...permitTypedData,
|
|
457
856
|
signature: exactEvmPayload.signature
|
|
458
857
|
});
|
|
459
|
-
|
|
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:
|
|
463
|
-
payer
|
|
876
|
+
invalidReason: ErrInvalidSignature,
|
|
877
|
+
payer
|
|
464
878
|
};
|
|
465
879
|
}
|
|
466
|
-
|
|
467
|
-
const
|
|
468
|
-
|
|
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:
|
|
494
|
-
payer
|
|
885
|
+
invalidReason: ErrUndeployedSmartWallet,
|
|
886
|
+
payer
|
|
495
887
|
};
|
|
496
888
|
}
|
|
497
889
|
}
|
|
498
|
-
if (
|
|
890
|
+
if (getAddress3(exactEvmPayload.authorization.to) !== getAddress3(requirements.payTo)) {
|
|
499
891
|
return {
|
|
500
892
|
isValid: false,
|
|
501
|
-
invalidReason:
|
|
502
|
-
payer
|
|
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:
|
|
510
|
-
payer
|
|
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:
|
|
517
|
-
payer
|
|
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:
|
|
541
|
-
payer
|
|
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
|
|
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-
|
|
1052
|
+
//# sourceMappingURL=chunk-IZEI7JTG.mjs.map
|