@bankofai/x402-evm 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -0
- package/dist/cjs/auth-capture/client/index.d.ts +44 -0
- package/dist/cjs/auth-capture/client/index.js +298 -0
- package/dist/cjs/auth-capture/client/index.js.map +1 -0
- package/dist/cjs/batch-settlement/client/file-storage.d.ts +47 -0
- package/dist/cjs/batch-settlement/client/file-storage.js +116 -0
- package/dist/cjs/batch-settlement/client/file-storage.js.map +1 -0
- package/dist/cjs/batch-settlement/client/index.d.ts +111 -0
- package/dist/cjs/batch-settlement/client/index.js +1565 -0
- package/dist/cjs/batch-settlement/client/index.js.map +1 -0
- package/dist/cjs/batch-settlement/facilitator/index.d.ts +72 -0
- package/dist/cjs/batch-settlement/facilitator/index.js +2102 -0
- package/dist/cjs/batch-settlement/facilitator/index.js.map +1 -0
- package/dist/cjs/batch-settlement/server/file-storage.d.ts +53 -0
- package/dist/cjs/batch-settlement/server/file-storage.js +181 -0
- package/dist/cjs/batch-settlement/server/file-storage.js.map +1 -0
- package/dist/cjs/batch-settlement/server/index.d.ts +491 -0
- package/dist/cjs/batch-settlement/server/index.js +1978 -0
- package/dist/cjs/batch-settlement/server/index.js.map +1 -0
- package/dist/cjs/batch-settlement/server/redis-storage.d.ts +87 -0
- package/dist/cjs/batch-settlement/server/redis-storage.js +181 -0
- package/dist/cjs/batch-settlement/server/redis-storage.js.map +1 -0
- package/dist/cjs/client/agent-wallet.d.ts +69 -0
- package/dist/cjs/client/agent-wallet.js +84 -0
- package/dist/cjs/client/agent-wallet.js.map +1 -0
- package/dist/cjs/exact/client/index.d.ts +63 -0
- package/dist/cjs/exact/client/index.js +739 -0
- package/dist/cjs/exact/client/index.js.map +1 -0
- package/dist/cjs/exact/facilitator/index.d.ts +141 -0
- package/dist/cjs/exact/facilitator/index.js +1989 -0
- package/dist/cjs/exact/facilitator/index.js.map +1 -0
- package/dist/cjs/exact/server/index.d.ts +118 -0
- package/dist/cjs/exact/server/index.js +326 -0
- package/dist/cjs/exact/server/index.js.map +1 -0
- package/dist/cjs/exact/v1/client/index.d.ts +38 -0
- package/dist/cjs/exact/v1/client/index.js +193 -0
- package/dist/cjs/exact/v1/client/index.js.map +1 -0
- package/dist/cjs/exact/v1/facilitator/index.d.ts +84 -0
- package/dist/cjs/exact/v1/facilitator/index.js +739 -0
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -0
- package/dist/cjs/facilitator/agent-wallet.d.ts +109 -0
- package/dist/cjs/facilitator/agent-wallet.js +105 -0
- package/dist/cjs/facilitator/agent-wallet.js.map +1 -0
- package/dist/cjs/index.d.ts +338 -0
- package/dist/cjs/index.js +2860 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/permit2-DK5A8alk.d.ts +729 -0
- package/dist/cjs/permit2-DhJRUcgY.d.ts +729 -0
- package/dist/cjs/rpc-DULZzRne.d.ts +13 -0
- package/dist/cjs/scheme-7ehldYoO.d.ts +307 -0
- package/dist/cjs/scheme-BjBJzHF7.d.ts +307 -0
- package/dist/cjs/scheme-DWgpkDgz.d.ts +47 -0
- package/dist/cjs/signer-BFelv8DL.d.ts +170 -0
- package/dist/cjs/storage-6W5MO46W.d.ts +50 -0
- package/dist/cjs/storage-CHNote8s.d.ts +81 -0
- package/dist/cjs/storage-DjCv5IPh.d.ts +81 -0
- package/dist/cjs/types-CKd3Xoi1.d.ts +180 -0
- package/dist/cjs/types-DIt9uAUy.d.ts +180 -0
- package/dist/cjs/upto/client/index.d.ts +34 -0
- package/dist/cjs/upto/client/index.js +509 -0
- package/dist/cjs/upto/client/index.js.map +1 -0
- package/dist/cjs/upto/facilitator/index.d.ts +54 -0
- package/dist/cjs/upto/facilitator/index.js +1313 -0
- package/dist/cjs/upto/facilitator/index.js.map +1 -0
- package/dist/cjs/upto/server/index.d.ts +69 -0
- package/dist/cjs/upto/server/index.js +296 -0
- package/dist/cjs/upto/server/index.js.map +1 -0
- package/dist/cjs/v1/index.d.ts +40 -0
- package/dist/cjs/v1/index.js +199 -0
- package/dist/cjs/v1/index.js.map +1 -0
- package/dist/esm/auth-capture/client/index.d.mts +44 -0
- package/dist/esm/auth-capture/client/index.mjs +8 -0
- package/dist/esm/auth-capture/client/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/client/file-storage.d.mts +47 -0
- package/dist/esm/batch-settlement/client/file-storage.mjs +63 -0
- package/dist/esm/batch-settlement/client/file-storage.mjs.map +1 -0
- package/dist/esm/batch-settlement/client/index.d.mts +111 -0
- package/dist/esm/batch-settlement/client/index.mjs +58 -0
- package/dist/esm/batch-settlement/client/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/facilitator/index.d.mts +72 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs +1252 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/file-storage.d.mts +53 -0
- package/dist/esm/batch-settlement/server/file-storage.mjs +128 -0
- package/dist/esm/batch-settlement/server/file-storage.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/index.d.mts +491 -0
- package/dist/esm/batch-settlement/server/index.mjs +1640 -0
- package/dist/esm/batch-settlement/server/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/redis-storage.d.mts +87 -0
- package/dist/esm/batch-settlement/server/redis-storage.mjs +156 -0
- package/dist/esm/batch-settlement/server/redis-storage.mjs.map +1 -0
- package/dist/esm/chunk-2EUQTNJO.mjs +38 -0
- package/dist/esm/chunk-2EUQTNJO.mjs.map +1 -0
- package/dist/esm/chunk-3WZF6722.mjs +36 -0
- package/dist/esm/chunk-3WZF6722.mjs.map +1 -0
- package/dist/esm/chunk-E4Z7PNXC.mjs +275 -0
- package/dist/esm/chunk-E4Z7PNXC.mjs.map +1 -0
- package/dist/esm/chunk-GQVMVP4N.mjs +911 -0
- package/dist/esm/chunk-GQVMVP4N.mjs.map +1 -0
- package/dist/esm/chunk-H2EYJIZL.mjs +489 -0
- package/dist/esm/chunk-H2EYJIZL.mjs.map +1 -0
- package/dist/esm/chunk-H3KPLYGI.mjs +152 -0
- package/dist/esm/chunk-H3KPLYGI.mjs.map +1 -0
- package/dist/esm/chunk-HYABYUBD.mjs +432 -0
- package/dist/esm/chunk-HYABYUBD.mjs.map +1 -0
- package/dist/esm/chunk-I2DVUHM5.mjs +123 -0
- package/dist/esm/chunk-I2DVUHM5.mjs.map +1 -0
- package/dist/esm/chunk-JK7SLLF7.mjs +34 -0
- package/dist/esm/chunk-JK7SLLF7.mjs.map +1 -0
- package/dist/esm/chunk-JNT7C46S.mjs +352 -0
- package/dist/esm/chunk-JNT7C46S.mjs.map +1 -0
- package/dist/esm/chunk-MACPBXCT.mjs +415 -0
- package/dist/esm/chunk-MACPBXCT.mjs.map +1 -0
- package/dist/esm/chunk-P3QOX3QZ.mjs +113 -0
- package/dist/esm/chunk-P3QOX3QZ.mjs.map +1 -0
- package/dist/esm/chunk-QVATVA3J.mjs +47 -0
- package/dist/esm/chunk-QVATVA3J.mjs.map +1 -0
- package/dist/esm/chunk-SHJFA25H.mjs +159 -0
- package/dist/esm/chunk-SHJFA25H.mjs.map +1 -0
- package/dist/esm/chunk-TW7Z65AO.mjs +34 -0
- package/dist/esm/chunk-TW7Z65AO.mjs.map +1 -0
- package/dist/esm/chunk-U4HCGTLU.mjs +35 -0
- package/dist/esm/chunk-U4HCGTLU.mjs.map +1 -0
- package/dist/esm/chunk-VS3RYAYE.mjs +80 -0
- package/dist/esm/chunk-VS3RYAYE.mjs.map +1 -0
- package/dist/esm/chunk-W6ON4LG2.mjs +39 -0
- package/dist/esm/chunk-W6ON4LG2.mjs.map +1 -0
- package/dist/esm/chunk-XG2JLZVJ.mjs +627 -0
- package/dist/esm/chunk-XG2JLZVJ.mjs.map +1 -0
- package/dist/esm/chunk-ZCJRY5LQ.mjs +162 -0
- package/dist/esm/chunk-ZCJRY5LQ.mjs.map +1 -0
- package/dist/esm/client/agent-wallet.d.mts +69 -0
- package/dist/esm/client/agent-wallet.mjs +36 -0
- package/dist/esm/client/agent-wallet.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +63 -0
- package/dist/esm/exact/client/index.mjs +25 -0
- package/dist/esm/exact/client/index.mjs.map +1 -0
- package/dist/esm/exact/facilitator/index.d.mts +141 -0
- package/dist/esm/exact/facilitator/index.mjs +694 -0
- package/dist/esm/exact/facilitator/index.mjs.map +1 -0
- package/dist/esm/exact/server/index.d.mts +118 -0
- package/dist/esm/exact/server/index.mjs +153 -0
- package/dist/esm/exact/server/index.mjs.map +1 -0
- package/dist/esm/exact/v1/client/index.d.mts +38 -0
- package/dist/esm/exact/v1/client/index.mjs +12 -0
- package/dist/esm/exact/v1/client/index.mjs.map +1 -0
- package/dist/esm/exact/v1/facilitator/index.d.mts +84 -0
- package/dist/esm/exact/v1/facilitator/index.mjs +12 -0
- package/dist/esm/exact/v1/facilitator/index.mjs.map +1 -0
- package/dist/esm/facilitator/agent-wallet.d.mts +109 -0
- package/dist/esm/facilitator/agent-wallet.mjs +74 -0
- package/dist/esm/facilitator/agent-wallet.mjs.map +1 -0
- package/dist/esm/index.d.mts +338 -0
- package/dist/esm/index.mjs +144 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/permit2-DhJRUcgY.d.mts +729 -0
- package/dist/esm/rpc-DULZzRne.d.mts +13 -0
- package/dist/esm/scheme-CkNhpXrG.d.mts +307 -0
- package/dist/esm/scheme-D8ZbykGV.d.mts +47 -0
- package/dist/esm/signer-BFelv8DL.d.mts +170 -0
- package/dist/esm/storage-6W5MO46W.d.mts +50 -0
- package/dist/esm/storage-BEzTEiUr.d.mts +81 -0
- package/dist/esm/types-DIt9uAUy.d.mts +180 -0
- package/dist/esm/upto/client/index.d.mts +34 -0
- package/dist/esm/upto/client/index.mjs +22 -0
- package/dist/esm/upto/client/index.mjs.map +1 -0
- package/dist/esm/upto/facilitator/index.d.mts +54 -0
- package/dist/esm/upto/facilitator/index.mjs +507 -0
- package/dist/esm/upto/facilitator/index.mjs.map +1 -0
- package/dist/esm/upto/server/index.d.mts +69 -0
- package/dist/esm/upto/server/index.mjs +124 -0
- package/dist/esm/upto/server/index.mjs.map +1 -0
- package/dist/esm/v1/index.d.mts +40 -0
- package/dist/esm/v1/index.mjs +18 -0
- package/dist/esm/v1/index.mjs.map +1 -0
- package/package.json +250 -0
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ErrEip3009InsufficientBalance,
|
|
3
|
+
ErrEip3009NonceAlreadyUsed,
|
|
4
|
+
ErrEip3009NotSupported,
|
|
5
|
+
ErrEip3009SimulationFailed,
|
|
6
|
+
ErrEip3009TokenNameMismatch,
|
|
7
|
+
ErrEip3009TokenVersionMismatch,
|
|
8
|
+
ErrFactoryNotAllowed,
|
|
9
|
+
ErrInvalidAuthorizationValue,
|
|
10
|
+
ErrInvalidScheme,
|
|
11
|
+
ErrInvalidSignature,
|
|
12
|
+
ErrMissingEip712Domain,
|
|
13
|
+
ErrNetworkMismatch,
|
|
14
|
+
ErrRecipientMismatch,
|
|
15
|
+
ErrTransactionFailed,
|
|
16
|
+
ErrUndeployedSmartWallet,
|
|
17
|
+
ErrValidAfterInFuture,
|
|
18
|
+
ErrValidBeforeExpired
|
|
19
|
+
} from "./chunk-P3QOX3QZ.mjs";
|
|
20
|
+
import {
|
|
21
|
+
resolveDataSuffix
|
|
22
|
+
} from "./chunk-JNT7C46S.mjs";
|
|
23
|
+
import {
|
|
24
|
+
authorizationTypes,
|
|
25
|
+
eip3009ABI
|
|
26
|
+
} from "./chunk-MACPBXCT.mjs";
|
|
27
|
+
import {
|
|
28
|
+
multicall
|
|
29
|
+
} from "./chunk-VS3RYAYE.mjs";
|
|
30
|
+
import {
|
|
31
|
+
createNonce
|
|
32
|
+
} from "./chunk-TW7Z65AO.mjs";
|
|
33
|
+
|
|
34
|
+
// src/exact/v1/client/scheme.ts
|
|
35
|
+
import { getAddress } from "viem";
|
|
36
|
+
var ExactEvmSchemeV1 = class {
|
|
37
|
+
/**
|
|
38
|
+
* Creates a new ExactEvmClientV1 instance.
|
|
39
|
+
*
|
|
40
|
+
* @param signer - The EVM signer for client operations
|
|
41
|
+
*/
|
|
42
|
+
constructor(signer) {
|
|
43
|
+
this.signer = signer;
|
|
44
|
+
this.scheme = "exact";
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates a payment payload for the Exact scheme (V1).
|
|
48
|
+
*
|
|
49
|
+
* @param x402Version - The x402 protocol version
|
|
50
|
+
* @param paymentRequirements - The payment requirements
|
|
51
|
+
* @returns Promise resolving to a payment payload
|
|
52
|
+
*/
|
|
53
|
+
async createPaymentPayload(x402Version, paymentRequirements) {
|
|
54
|
+
const selectedV1 = paymentRequirements;
|
|
55
|
+
const nonce = createNonce();
|
|
56
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
57
|
+
const authorization = {
|
|
58
|
+
from: this.signer.address,
|
|
59
|
+
to: getAddress(selectedV1.payTo),
|
|
60
|
+
value: selectedV1.maxAmountRequired,
|
|
61
|
+
validAfter: (now - 600).toString(),
|
|
62
|
+
// 10 minutes before
|
|
63
|
+
validBefore: (now + selectedV1.maxTimeoutSeconds).toString(),
|
|
64
|
+
nonce
|
|
65
|
+
};
|
|
66
|
+
const signature = await this.signAuthorization(authorization, selectedV1);
|
|
67
|
+
const payload = {
|
|
68
|
+
authorization,
|
|
69
|
+
signature
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
x402Version,
|
|
73
|
+
scheme: selectedV1.scheme,
|
|
74
|
+
network: selectedV1.network,
|
|
75
|
+
payload
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Sign the EIP-3009 authorization using EIP-712
|
|
80
|
+
*
|
|
81
|
+
* @param authorization - The authorization to sign
|
|
82
|
+
* @param requirements - The payment requirements
|
|
83
|
+
* @returns Promise resolving to the signature
|
|
84
|
+
*/
|
|
85
|
+
async signAuthorization(authorization, requirements) {
|
|
86
|
+
const chainId = getEvmChainIdV1(requirements.network);
|
|
87
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
const { name, version } = requirements.extra;
|
|
93
|
+
const domain = {
|
|
94
|
+
name,
|
|
95
|
+
version,
|
|
96
|
+
chainId,
|
|
97
|
+
verifyingContract: getAddress(requirements.asset)
|
|
98
|
+
};
|
|
99
|
+
const message = {
|
|
100
|
+
from: getAddress(authorization.from),
|
|
101
|
+
to: getAddress(authorization.to),
|
|
102
|
+
value: BigInt(authorization.value),
|
|
103
|
+
validAfter: BigInt(authorization.validAfter),
|
|
104
|
+
validBefore: BigInt(authorization.validBefore),
|
|
105
|
+
nonce: authorization.nonce
|
|
106
|
+
};
|
|
107
|
+
return await this.signer.signTypedData({
|
|
108
|
+
domain,
|
|
109
|
+
types: authorizationTypes,
|
|
110
|
+
primaryType: "TransferWithAuthorization",
|
|
111
|
+
message
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// src/exact/v1/facilitator/scheme.ts
|
|
117
|
+
import { getAddress as getAddress3, isAddressEqual, parseErc6492Signature as parseErc6492Signature2 } from "viem";
|
|
118
|
+
|
|
119
|
+
// src/exact/facilitator/eip3009-utils.ts
|
|
120
|
+
import { encodeFunctionData, getAddress as getAddress2, parseErc6492Signature, parseSignature } from "viem";
|
|
121
|
+
async function simulateEip3009Transfer(signer, erc20Address, payload, eip6492Deployment) {
|
|
122
|
+
const auth = payload.authorization;
|
|
123
|
+
const transferArgs = [
|
|
124
|
+
getAddress2(auth.from),
|
|
125
|
+
getAddress2(auth.to),
|
|
126
|
+
BigInt(auth.value),
|
|
127
|
+
BigInt(auth.validAfter),
|
|
128
|
+
BigInt(auth.validBefore),
|
|
129
|
+
auth.nonce
|
|
130
|
+
];
|
|
131
|
+
if (eip6492Deployment) {
|
|
132
|
+
const { signature: innerSignature } = parseErc6492Signature(payload.signature);
|
|
133
|
+
const transferCalldata = encodeFunctionData({
|
|
134
|
+
abi: eip3009ABI,
|
|
135
|
+
functionName: "transferWithAuthorization",
|
|
136
|
+
args: [...transferArgs, innerSignature]
|
|
137
|
+
});
|
|
138
|
+
try {
|
|
139
|
+
const results = await multicall(signer.readContract.bind(signer), [
|
|
140
|
+
{
|
|
141
|
+
address: getAddress2(eip6492Deployment.factoryAddress),
|
|
142
|
+
callData: eip6492Deployment.factoryCalldata
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
address: erc20Address,
|
|
146
|
+
callData: transferCalldata
|
|
147
|
+
}
|
|
148
|
+
]);
|
|
149
|
+
return results[1]?.status === "success";
|
|
150
|
+
} catch {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const sig = payload.signature;
|
|
155
|
+
const sigLength = sig.startsWith("0x") ? sig.length - 2 : sig.length;
|
|
156
|
+
const isECDSA = sigLength === 130;
|
|
157
|
+
try {
|
|
158
|
+
if (isECDSA) {
|
|
159
|
+
const parsedSig = parseSignature(sig);
|
|
160
|
+
await signer.readContract({
|
|
161
|
+
address: erc20Address,
|
|
162
|
+
abi: eip3009ABI,
|
|
163
|
+
functionName: "transferWithAuthorization",
|
|
164
|
+
args: [
|
|
165
|
+
...transferArgs,
|
|
166
|
+
parsedSig.v ?? parsedSig.yParity,
|
|
167
|
+
parsedSig.r,
|
|
168
|
+
parsedSig.s
|
|
169
|
+
]
|
|
170
|
+
});
|
|
171
|
+
} else {
|
|
172
|
+
await signer.readContract({
|
|
173
|
+
address: erc20Address,
|
|
174
|
+
abi: eip3009ABI,
|
|
175
|
+
functionName: "transferWithAuthorization",
|
|
176
|
+
args: [...transferArgs, sig]
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
return true;
|
|
180
|
+
} catch {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async function diagnoseEip3009SimulationFailure(signer, erc20Address, payload, requirements, amountRequired) {
|
|
185
|
+
const payer = payload.authorization.from;
|
|
186
|
+
const diagnosticCalls = [
|
|
187
|
+
{
|
|
188
|
+
address: erc20Address,
|
|
189
|
+
abi: eip3009ABI,
|
|
190
|
+
functionName: "balanceOf",
|
|
191
|
+
args: [payload.authorization.from]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
address: erc20Address,
|
|
195
|
+
abi: eip3009ABI,
|
|
196
|
+
functionName: "name"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
address: erc20Address,
|
|
200
|
+
abi: eip3009ABI,
|
|
201
|
+
functionName: "version"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
address: erc20Address,
|
|
205
|
+
abi: eip3009ABI,
|
|
206
|
+
functionName: "authorizationState",
|
|
207
|
+
args: [payload.authorization.from, payload.authorization.nonce]
|
|
208
|
+
}
|
|
209
|
+
];
|
|
210
|
+
try {
|
|
211
|
+
const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);
|
|
212
|
+
const [balanceResult, nameResult, versionResult, authStateResult] = results;
|
|
213
|
+
if (authStateResult.status === "failure") {
|
|
214
|
+
return { isValid: false, invalidReason: ErrEip3009NotSupported, payer };
|
|
215
|
+
}
|
|
216
|
+
if (authStateResult.status === "success" && authStateResult.result === true) {
|
|
217
|
+
return { isValid: false, invalidReason: ErrEip3009NonceAlreadyUsed, payer };
|
|
218
|
+
}
|
|
219
|
+
if (nameResult.status === "success" && requirements.extra?.name && nameResult.result !== requirements.extra.name) {
|
|
220
|
+
return { isValid: false, invalidReason: ErrEip3009TokenNameMismatch, payer };
|
|
221
|
+
}
|
|
222
|
+
if (versionResult.status === "success" && requirements.extra?.version && versionResult.result !== requirements.extra.version) {
|
|
223
|
+
return { isValid: false, invalidReason: ErrEip3009TokenVersionMismatch, payer };
|
|
224
|
+
}
|
|
225
|
+
if (balanceResult.status === "success") {
|
|
226
|
+
const balance = balanceResult.result;
|
|
227
|
+
if (balance < BigInt(amountRequired)) {
|
|
228
|
+
return {
|
|
229
|
+
isValid: false,
|
|
230
|
+
invalidReason: ErrEip3009InsufficientBalance,
|
|
231
|
+
payer
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} catch {
|
|
236
|
+
}
|
|
237
|
+
return { isValid: false, invalidReason: ErrEip3009SimulationFailed, payer };
|
|
238
|
+
}
|
|
239
|
+
function parseEip3009TransferError(error) {
|
|
240
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
241
|
+
if (/authorization.*(expired|valid before)/i.test(msg) || /AuthorizationExpired/i.test(msg)) {
|
|
242
|
+
return ErrValidBeforeExpired;
|
|
243
|
+
}
|
|
244
|
+
if (/authorization.*not.*valid|AuthorizationNotYetValid/i.test(msg)) {
|
|
245
|
+
return ErrValidAfterInFuture;
|
|
246
|
+
}
|
|
247
|
+
if (/authorization.*used|AuthorizationAlreadyUsed|AuthorizationUsedOrCanceled/i.test(msg)) {
|
|
248
|
+
return ErrEip3009NonceAlreadyUsed;
|
|
249
|
+
}
|
|
250
|
+
if (/transfer.*exceeds.*balance|insufficient.*balance|ERC20InsufficientBalance/i.test(msg)) {
|
|
251
|
+
return ErrEip3009InsufficientBalance;
|
|
252
|
+
}
|
|
253
|
+
if (/invalid.*signature|SignerMismatch|InvalidSignatureV|InvalidSignatureS/i.test(msg)) {
|
|
254
|
+
return ErrInvalidSignature;
|
|
255
|
+
}
|
|
256
|
+
return ErrTransactionFailed;
|
|
257
|
+
}
|
|
258
|
+
async function executeTransferWithAuthorization(signer, erc20Address, payload, dataSuffix) {
|
|
259
|
+
const { signature } = parseErc6492Signature(payload.signature);
|
|
260
|
+
const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
|
|
261
|
+
const isECDSA = signatureLength === 130;
|
|
262
|
+
const auth = payload.authorization;
|
|
263
|
+
const baseArgs = [
|
|
264
|
+
getAddress2(auth.from),
|
|
265
|
+
getAddress2(auth.to),
|
|
266
|
+
BigInt(auth.value),
|
|
267
|
+
BigInt(auth.validAfter),
|
|
268
|
+
BigInt(auth.validBefore),
|
|
269
|
+
auth.nonce
|
|
270
|
+
];
|
|
271
|
+
let signatureArgs;
|
|
272
|
+
if (isECDSA) {
|
|
273
|
+
const parsedSig = parseSignature(signature);
|
|
274
|
+
signatureArgs = [
|
|
275
|
+
parsedSig.v || parsedSig.yParity,
|
|
276
|
+
parsedSig.r,
|
|
277
|
+
parsedSig.s
|
|
278
|
+
];
|
|
279
|
+
} else {
|
|
280
|
+
signatureArgs = [signature];
|
|
281
|
+
}
|
|
282
|
+
return signer.writeContract({
|
|
283
|
+
address: erc20Address,
|
|
284
|
+
abi: eip3009ABI,
|
|
285
|
+
functionName: "transferWithAuthorization",
|
|
286
|
+
args: [...baseArgs, ...signatureArgs],
|
|
287
|
+
dataSuffix
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/exact/v1/facilitator/scheme.ts
|
|
292
|
+
var ExactEvmSchemeV12 = class {
|
|
293
|
+
/**
|
|
294
|
+
* Creates a new ExactEvmFacilitatorV1 instance.
|
|
295
|
+
*
|
|
296
|
+
* @param signer - The EVM signer for facilitator operations
|
|
297
|
+
* @param config - Optional configuration for the facilitator
|
|
298
|
+
*/
|
|
299
|
+
constructor(signer, config) {
|
|
300
|
+
this.signer = signer;
|
|
301
|
+
this.scheme = "exact";
|
|
302
|
+
this.caipFamily = "eip155:*";
|
|
303
|
+
this.config = {
|
|
304
|
+
eip6492AllowedFactories: config?.eip6492AllowedFactories ?? [],
|
|
305
|
+
simulateInSettle: config?.simulateInSettle ?? false
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Get mechanism-specific extra data for the supported kinds endpoint.
|
|
310
|
+
* For EVM, no extra data is needed.
|
|
311
|
+
*
|
|
312
|
+
* @param _ - The network identifier (unused for EVM)
|
|
313
|
+
* @returns undefined (EVM has no extra data)
|
|
314
|
+
*/
|
|
315
|
+
getExtra(_) {
|
|
316
|
+
return void 0;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Get signer addresses used by this facilitator.
|
|
320
|
+
* Returns all addresses this facilitator can use for signing/settling transactions.
|
|
321
|
+
*
|
|
322
|
+
* @param _ - The network identifier (unused for EVM, addresses are network-agnostic)
|
|
323
|
+
* @returns Array of facilitator wallet addresses
|
|
324
|
+
*/
|
|
325
|
+
getSigners(_) {
|
|
326
|
+
return [...this.signer.getAddresses()];
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Verifies a payment payload (V1).
|
|
330
|
+
*
|
|
331
|
+
* @param payload - The payment payload to verify
|
|
332
|
+
* @param requirements - The payment requirements
|
|
333
|
+
* @returns Promise resolving to verification response
|
|
334
|
+
*/
|
|
335
|
+
async verify(payload, requirements) {
|
|
336
|
+
return this._verify(payload, requirements);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Settles a payment by executing the transfer (V1).
|
|
340
|
+
*
|
|
341
|
+
* @param payload - The payment payload to settle
|
|
342
|
+
* @param requirements - The payment requirements
|
|
343
|
+
* @param context - Optional facilitator context for extension capabilities
|
|
344
|
+
* @returns Promise resolving to settlement response
|
|
345
|
+
*/
|
|
346
|
+
async settle(payload, requirements, context) {
|
|
347
|
+
const payloadV1 = payload;
|
|
348
|
+
const exactEvmPayload = payload.payload;
|
|
349
|
+
const valid = await this._verify(payload, requirements, {
|
|
350
|
+
simulate: this.config.simulateInSettle ?? false
|
|
351
|
+
});
|
|
352
|
+
if (!valid.isValid) {
|
|
353
|
+
return {
|
|
354
|
+
success: false,
|
|
355
|
+
network: payloadV1.network,
|
|
356
|
+
transaction: "",
|
|
357
|
+
errorReason: valid.invalidReason ?? ErrInvalidScheme,
|
|
358
|
+
payer: exactEvmPayload.authorization.from
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
try {
|
|
362
|
+
const { address: factoryAddress, data: factoryCalldata } = parseErc6492Signature2(
|
|
363
|
+
exactEvmPayload.signature
|
|
364
|
+
);
|
|
365
|
+
if (factoryAddress && factoryCalldata && !isAddressEqual(factoryAddress, "0x0000000000000000000000000000000000000000")) {
|
|
366
|
+
const payerAddress = exactEvmPayload.authorization.from;
|
|
367
|
+
const bytecode = await this.signer.getCode({ address: payerAddress });
|
|
368
|
+
if (!bytecode || bytecode === "0x") {
|
|
369
|
+
const normalizedFactory = factoryAddress.toLowerCase();
|
|
370
|
+
const isAllowed = (this.config.eip6492AllowedFactories ?? []).some(
|
|
371
|
+
(allowed) => allowed.toLowerCase() === normalizedFactory
|
|
372
|
+
);
|
|
373
|
+
if (!isAllowed) {
|
|
374
|
+
return {
|
|
375
|
+
success: false,
|
|
376
|
+
errorReason: ErrFactoryNotAllowed,
|
|
377
|
+
transaction: "",
|
|
378
|
+
network: payloadV1.network,
|
|
379
|
+
payer: exactEvmPayload.authorization.from
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
const deployTx = await this.signer.sendTransaction({
|
|
383
|
+
to: factoryAddress,
|
|
384
|
+
data: factoryCalldata
|
|
385
|
+
});
|
|
386
|
+
await this.signer.waitForTransactionReceipt({ hash: deployTx });
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
const dataSuffix = await resolveDataSuffix(context, {
|
|
390
|
+
paymentPayload: payload,
|
|
391
|
+
paymentRequirements: requirements
|
|
392
|
+
});
|
|
393
|
+
const tx = await executeTransferWithAuthorization(
|
|
394
|
+
this.signer,
|
|
395
|
+
getAddress3(requirements.asset),
|
|
396
|
+
exactEvmPayload,
|
|
397
|
+
dataSuffix
|
|
398
|
+
);
|
|
399
|
+
const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });
|
|
400
|
+
if (receipt.status !== "success") {
|
|
401
|
+
return {
|
|
402
|
+
success: false,
|
|
403
|
+
errorReason: ErrTransactionFailed,
|
|
404
|
+
transaction: tx,
|
|
405
|
+
network: payloadV1.network,
|
|
406
|
+
payer: exactEvmPayload.authorization.from
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
success: true,
|
|
411
|
+
transaction: tx,
|
|
412
|
+
network: payloadV1.network,
|
|
413
|
+
payer: exactEvmPayload.authorization.from
|
|
414
|
+
};
|
|
415
|
+
} catch (error) {
|
|
416
|
+
return {
|
|
417
|
+
success: false,
|
|
418
|
+
errorReason: error instanceof Error ? error.message : ErrTransactionFailed,
|
|
419
|
+
transaction: "",
|
|
420
|
+
network: payloadV1.network,
|
|
421
|
+
payer: exactEvmPayload.authorization.from
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Internal verify with optional simulation control.
|
|
427
|
+
*
|
|
428
|
+
* @param payload - The payment payload to verify
|
|
429
|
+
* @param requirements - The payment requirements
|
|
430
|
+
* @param options - Verification options (e.g. simulate)
|
|
431
|
+
* @returns Promise resolving to verification response
|
|
432
|
+
*/
|
|
433
|
+
async _verify(payload, requirements, options) {
|
|
434
|
+
const requirementsV1 = requirements;
|
|
435
|
+
const payloadV1 = payload;
|
|
436
|
+
const exactEvmPayload = payload.payload;
|
|
437
|
+
const payer = exactEvmPayload.authorization.from;
|
|
438
|
+
let eip6492Deployment;
|
|
439
|
+
if (payloadV1.scheme !== "exact" || requirements.scheme !== "exact") {
|
|
440
|
+
return {
|
|
441
|
+
isValid: false,
|
|
442
|
+
invalidReason: ErrInvalidScheme,
|
|
443
|
+
payer
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
let chainId;
|
|
447
|
+
try {
|
|
448
|
+
chainId = getEvmChainIdV1(payloadV1.network);
|
|
449
|
+
} catch {
|
|
450
|
+
return {
|
|
451
|
+
isValid: false,
|
|
452
|
+
invalidReason: ErrNetworkMismatch,
|
|
453
|
+
payer
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
457
|
+
return {
|
|
458
|
+
isValid: false,
|
|
459
|
+
invalidReason: ErrMissingEip712Domain,
|
|
460
|
+
payer
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
const { name, version } = requirements.extra;
|
|
464
|
+
const erc20Address = getAddress3(requirements.asset);
|
|
465
|
+
if (payloadV1.network !== requirements.network) {
|
|
466
|
+
return {
|
|
467
|
+
isValid: false,
|
|
468
|
+
invalidReason: ErrNetworkMismatch,
|
|
469
|
+
payer
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
const permitTypedData = {
|
|
473
|
+
types: authorizationTypes,
|
|
474
|
+
primaryType: "TransferWithAuthorization",
|
|
475
|
+
domain: {
|
|
476
|
+
name,
|
|
477
|
+
version,
|
|
478
|
+
chainId,
|
|
479
|
+
verifyingContract: erc20Address
|
|
480
|
+
},
|
|
481
|
+
message: {
|
|
482
|
+
from: exactEvmPayload.authorization.from,
|
|
483
|
+
to: exactEvmPayload.authorization.to,
|
|
484
|
+
value: BigInt(exactEvmPayload.authorization.value),
|
|
485
|
+
validAfter: BigInt(exactEvmPayload.authorization.validAfter),
|
|
486
|
+
validBefore: BigInt(exactEvmPayload.authorization.validBefore),
|
|
487
|
+
nonce: exactEvmPayload.authorization.nonce
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
let isValid = false;
|
|
491
|
+
try {
|
|
492
|
+
isValid = await this.signer.verifyTypedData({
|
|
493
|
+
address: payer,
|
|
494
|
+
...permitTypedData,
|
|
495
|
+
signature: exactEvmPayload.signature
|
|
496
|
+
});
|
|
497
|
+
} catch {
|
|
498
|
+
isValid = false;
|
|
499
|
+
}
|
|
500
|
+
const signature = exactEvmPayload.signature;
|
|
501
|
+
const sigLen = signature.startsWith("0x") ? signature.length - 2 : signature.length;
|
|
502
|
+
const erc6492Data = parseErc6492Signature2(signature);
|
|
503
|
+
const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !isAddressEqual(erc6492Data.address, "0x0000000000000000000000000000000000000000");
|
|
504
|
+
if (hasDeploymentInfo) {
|
|
505
|
+
eip6492Deployment = {
|
|
506
|
+
factoryAddress: erc6492Data.address,
|
|
507
|
+
factoryCalldata: erc6492Data.data
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
if (!isValid) {
|
|
511
|
+
const isSmartWallet = sigLen > 130;
|
|
512
|
+
if (!isSmartWallet) {
|
|
513
|
+
return {
|
|
514
|
+
isValid: false,
|
|
515
|
+
invalidReason: ErrInvalidSignature,
|
|
516
|
+
payer
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
const bytecode = await this.signer.getCode({ address: payer });
|
|
520
|
+
const isDeployed = bytecode && bytecode !== "0x";
|
|
521
|
+
if (!isDeployed && !hasDeploymentInfo) {
|
|
522
|
+
return {
|
|
523
|
+
isValid: false,
|
|
524
|
+
invalidReason: ErrUndeployedSmartWallet,
|
|
525
|
+
payer
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
if (getAddress3(exactEvmPayload.authorization.to) !== getAddress3(requirements.payTo)) {
|
|
530
|
+
return {
|
|
531
|
+
isValid: false,
|
|
532
|
+
invalidReason: ErrRecipientMismatch,
|
|
533
|
+
payer
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
537
|
+
if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) {
|
|
538
|
+
return {
|
|
539
|
+
isValid: false,
|
|
540
|
+
invalidReason: ErrValidBeforeExpired,
|
|
541
|
+
payer
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) {
|
|
545
|
+
return {
|
|
546
|
+
isValid: false,
|
|
547
|
+
invalidReason: ErrValidAfterInFuture,
|
|
548
|
+
payer
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
if (BigInt(exactEvmPayload.authorization.value) !== BigInt(requirementsV1.maxAmountRequired)) {
|
|
552
|
+
return {
|
|
553
|
+
isValid: false,
|
|
554
|
+
invalidReason: ErrInvalidAuthorizationValue,
|
|
555
|
+
payer
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
if (options?.simulate !== false) {
|
|
559
|
+
const simulationSucceeded = await simulateEip3009Transfer(
|
|
560
|
+
this.signer,
|
|
561
|
+
erc20Address,
|
|
562
|
+
exactEvmPayload,
|
|
563
|
+
eip6492Deployment
|
|
564
|
+
);
|
|
565
|
+
if (!simulationSucceeded) {
|
|
566
|
+
return diagnoseEip3009SimulationFailure(
|
|
567
|
+
this.signer,
|
|
568
|
+
erc20Address,
|
|
569
|
+
exactEvmPayload,
|
|
570
|
+
requirements,
|
|
571
|
+
requirementsV1.maxAmountRequired
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return {
|
|
576
|
+
isValid: true,
|
|
577
|
+
invalidReason: void 0,
|
|
578
|
+
payer
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
// src/v1/index.ts
|
|
584
|
+
var EVM_NETWORK_CHAIN_ID_MAP = {
|
|
585
|
+
ethereum: 1,
|
|
586
|
+
sepolia: 11155111,
|
|
587
|
+
abstract: 2741,
|
|
588
|
+
"abstract-testnet": 11124,
|
|
589
|
+
"base-sepolia": 84532,
|
|
590
|
+
base: 8453,
|
|
591
|
+
"avalanche-fuji": 43113,
|
|
592
|
+
avalanche: 43114,
|
|
593
|
+
iotex: 4689,
|
|
594
|
+
sei: 1329,
|
|
595
|
+
"sei-testnet": 1328,
|
|
596
|
+
polygon: 137,
|
|
597
|
+
"polygon-amoy": 80002,
|
|
598
|
+
peaq: 3338,
|
|
599
|
+
story: 1514,
|
|
600
|
+
educhain: 41923,
|
|
601
|
+
"skale-base-sepolia": 324705682,
|
|
602
|
+
megaeth: 4326,
|
|
603
|
+
monad: 143,
|
|
604
|
+
stable: 988,
|
|
605
|
+
"stable-testnet": 2201
|
|
606
|
+
};
|
|
607
|
+
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
608
|
+
function getEvmChainIdV1(network) {
|
|
609
|
+
const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];
|
|
610
|
+
if (!chainId) {
|
|
611
|
+
throw new Error(`Unsupported v1 network: ${network}`);
|
|
612
|
+
}
|
|
613
|
+
return chainId;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
export {
|
|
617
|
+
simulateEip3009Transfer,
|
|
618
|
+
diagnoseEip3009SimulationFailure,
|
|
619
|
+
parseEip3009TransferError,
|
|
620
|
+
executeTransferWithAuthorization,
|
|
621
|
+
ExactEvmSchemeV12 as ExactEvmSchemeV1,
|
|
622
|
+
EVM_NETWORK_CHAIN_ID_MAP,
|
|
623
|
+
NETWORKS,
|
|
624
|
+
getEvmChainIdV1,
|
|
625
|
+
ExactEvmSchemeV1 as ExactEvmSchemeV12
|
|
626
|
+
};
|
|
627
|
+
//# sourceMappingURL=chunk-XG2JLZVJ.mjs.map
|