@x402/evm 2.2.0 → 2.3.1
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/dist/cjs/exact/client/index.d.ts +2 -2
- package/dist/cjs/exact/client/index.js +265 -119
- package/dist/cjs/exact/client/index.js.map +1 -1
- package/dist/cjs/exact/facilitator/index.d.ts +3 -0
- package/dist/cjs/exact/facilitator/index.js +692 -281
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/server/index.js +8 -1
- package/dist/cjs/exact/server/index.js.map +1 -1
- package/dist/cjs/exact/v1/client/index.js +44 -17
- package/dist/cjs/exact/v1/client/index.js.map +1 -1
- package/dist/cjs/exact/v1/facilitator/index.js +60 -26
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
- package/dist/cjs/index.d.ts +458 -31
- package/dist/cjs/index.js +439 -63
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/permit2-BYv82va2.d.ts +103 -0
- package/dist/cjs/v1/index.d.ts +22 -1
- package/dist/cjs/v1/index.js +34 -29
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/chunk-E2YMUI3X.mjs +229 -0
- package/dist/esm/chunk-E2YMUI3X.mjs.map +1 -0
- package/dist/esm/chunk-PFULIQAE.mjs +13 -0
- package/dist/esm/chunk-PFULIQAE.mjs.map +1 -0
- package/dist/esm/chunk-RPL6OFJL.mjs +659 -0
- package/dist/esm/chunk-RPL6OFJL.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +2 -2
- package/dist/esm/exact/client/index.mjs +10 -30
- package/dist/esm/exact/client/index.mjs.map +1 -1
- package/dist/esm/exact/facilitator/index.d.mts +3 -0
- package/dist/esm/exact/facilitator/index.mjs +491 -241
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/server/index.mjs +8 -1
- package/dist/esm/exact/server/index.mjs.map +1 -1
- package/dist/esm/exact/v1/client/index.mjs +1 -2
- package/dist/esm/exact/v1/facilitator/index.mjs +2 -3
- package/dist/esm/index.d.mts +458 -31
- package/dist/esm/index.mjs +31 -4
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/permit2-BsAoJiWD.d.mts +103 -0
- package/dist/esm/v1/index.d.mts +22 -1
- package/dist/esm/v1/index.mjs +4 -6
- package/package.json +2 -2
- package/dist/esm/chunk-FOUXRQAV.mjs +0 -88
- package/dist/esm/chunk-FOUXRQAV.mjs.map +0 -1
- package/dist/esm/chunk-JYZWCLMP.mjs +0 -305
- package/dist/esm/chunk-JYZWCLMP.mjs.map +0 -1
- package/dist/esm/chunk-PSA4YVU2.mjs +0 -92
- package/dist/esm/chunk-PSA4YVU2.mjs.map +0 -1
- package/dist/esm/chunk-QLXM7BIB.mjs +0 -23
- package/dist/esm/chunk-QLXM7BIB.mjs.map +0 -1
- package/dist/esm/chunk-ZYXTTU74.mjs +0 -88
- package/dist/esm/chunk-ZYXTTU74.mjs.map +0 -1
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
// src/exact/v1/client/scheme.ts
|
|
2
|
+
import { getAddress } from "viem";
|
|
3
|
+
|
|
4
|
+
// src/constants.ts
|
|
5
|
+
var authorizationTypes = {
|
|
6
|
+
TransferWithAuthorization: [
|
|
7
|
+
{ name: "from", type: "address" },
|
|
8
|
+
{ name: "to", type: "address" },
|
|
9
|
+
{ name: "value", type: "uint256" },
|
|
10
|
+
{ name: "validAfter", type: "uint256" },
|
|
11
|
+
{ name: "validBefore", type: "uint256" },
|
|
12
|
+
{ name: "nonce", type: "bytes32" }
|
|
13
|
+
]
|
|
14
|
+
};
|
|
15
|
+
var permit2WitnessTypes = {
|
|
16
|
+
PermitWitnessTransferFrom: [
|
|
17
|
+
{ name: "permitted", type: "TokenPermissions" },
|
|
18
|
+
{ name: "spender", type: "address" },
|
|
19
|
+
{ name: "nonce", type: "uint256" },
|
|
20
|
+
{ name: "deadline", type: "uint256" },
|
|
21
|
+
{ name: "witness", type: "Witness" }
|
|
22
|
+
],
|
|
23
|
+
TokenPermissions: [
|
|
24
|
+
{ name: "token", type: "address" },
|
|
25
|
+
{ name: "amount", type: "uint256" }
|
|
26
|
+
],
|
|
27
|
+
Witness: [
|
|
28
|
+
{ name: "to", type: "address" },
|
|
29
|
+
{ name: "validAfter", type: "uint256" },
|
|
30
|
+
{ name: "extra", type: "bytes" }
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
var eip3009ABI = [
|
|
34
|
+
{
|
|
35
|
+
inputs: [
|
|
36
|
+
{ name: "from", type: "address" },
|
|
37
|
+
{ name: "to", type: "address" },
|
|
38
|
+
{ name: "value", type: "uint256" },
|
|
39
|
+
{ name: "validAfter", type: "uint256" },
|
|
40
|
+
{ name: "validBefore", type: "uint256" },
|
|
41
|
+
{ name: "nonce", type: "bytes32" },
|
|
42
|
+
{ name: "v", type: "uint8" },
|
|
43
|
+
{ name: "r", type: "bytes32" },
|
|
44
|
+
{ name: "s", type: "bytes32" }
|
|
45
|
+
],
|
|
46
|
+
name: "transferWithAuthorization",
|
|
47
|
+
outputs: [],
|
|
48
|
+
stateMutability: "nonpayable",
|
|
49
|
+
type: "function"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
inputs: [
|
|
53
|
+
{ name: "from", type: "address" },
|
|
54
|
+
{ name: "to", type: "address" },
|
|
55
|
+
{ name: "value", type: "uint256" },
|
|
56
|
+
{ name: "validAfter", type: "uint256" },
|
|
57
|
+
{ name: "validBefore", type: "uint256" },
|
|
58
|
+
{ name: "nonce", type: "bytes32" },
|
|
59
|
+
{ name: "signature", type: "bytes" }
|
|
60
|
+
],
|
|
61
|
+
name: "transferWithAuthorization",
|
|
62
|
+
outputs: [],
|
|
63
|
+
stateMutability: "nonpayable",
|
|
64
|
+
type: "function"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
inputs: [{ name: "account", type: "address" }],
|
|
68
|
+
name: "balanceOf",
|
|
69
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
70
|
+
stateMutability: "view",
|
|
71
|
+
type: "function"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
inputs: [],
|
|
75
|
+
name: "version",
|
|
76
|
+
outputs: [{ name: "", type: "string" }],
|
|
77
|
+
stateMutability: "view",
|
|
78
|
+
type: "function"
|
|
79
|
+
}
|
|
80
|
+
];
|
|
81
|
+
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
82
|
+
var x402ExactPermit2ProxyAddress = "0x4020615294c913F045dc10f0a5cdEbd86c280001";
|
|
83
|
+
var x402UptoPermit2ProxyAddress = "0x4020633461b2895a48930Ff97eE8fCdE8E520002";
|
|
84
|
+
var x402ExactPermit2ProxyABI = [
|
|
85
|
+
{
|
|
86
|
+
type: "function",
|
|
87
|
+
name: "PERMIT2",
|
|
88
|
+
inputs: [],
|
|
89
|
+
outputs: [{ name: "", type: "address", internalType: "contract ISignatureTransfer" }],
|
|
90
|
+
stateMutability: "view"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: "function",
|
|
94
|
+
name: "WITNESS_TYPEHASH",
|
|
95
|
+
inputs: [],
|
|
96
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
97
|
+
stateMutability: "view"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: "function",
|
|
101
|
+
name: "WITNESS_TYPE_STRING",
|
|
102
|
+
inputs: [],
|
|
103
|
+
outputs: [{ name: "", type: "string", internalType: "string" }],
|
|
104
|
+
stateMutability: "view"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
type: "function",
|
|
108
|
+
name: "initialize",
|
|
109
|
+
inputs: [{ name: "_permit2", type: "address", internalType: "address" }],
|
|
110
|
+
outputs: [],
|
|
111
|
+
stateMutability: "nonpayable"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: "function",
|
|
115
|
+
name: "settle",
|
|
116
|
+
inputs: [
|
|
117
|
+
{
|
|
118
|
+
name: "permit",
|
|
119
|
+
type: "tuple",
|
|
120
|
+
internalType: "struct ISignatureTransfer.PermitTransferFrom",
|
|
121
|
+
components: [
|
|
122
|
+
{
|
|
123
|
+
name: "permitted",
|
|
124
|
+
type: "tuple",
|
|
125
|
+
internalType: "struct ISignatureTransfer.TokenPermissions",
|
|
126
|
+
components: [
|
|
127
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
128
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
{ name: "nonce", type: "uint256", internalType: "uint256" },
|
|
132
|
+
{ name: "deadline", type: "uint256", internalType: "uint256" }
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
{ name: "owner", type: "address", internalType: "address" },
|
|
136
|
+
{
|
|
137
|
+
name: "witness",
|
|
138
|
+
type: "tuple",
|
|
139
|
+
internalType: "struct x402BasePermit2Proxy.Witness",
|
|
140
|
+
components: [
|
|
141
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
142
|
+
{ name: "validAfter", type: "uint256", internalType: "uint256" },
|
|
143
|
+
{ name: "extra", type: "bytes", internalType: "bytes" }
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
147
|
+
],
|
|
148
|
+
outputs: [],
|
|
149
|
+
stateMutability: "nonpayable"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
type: "function",
|
|
153
|
+
name: "settleWithPermit",
|
|
154
|
+
inputs: [
|
|
155
|
+
{
|
|
156
|
+
name: "permit2612",
|
|
157
|
+
type: "tuple",
|
|
158
|
+
internalType: "struct x402BasePermit2Proxy.EIP2612Permit",
|
|
159
|
+
components: [
|
|
160
|
+
{ name: "value", type: "uint256", internalType: "uint256" },
|
|
161
|
+
{ name: "deadline", type: "uint256", internalType: "uint256" },
|
|
162
|
+
{ name: "r", type: "bytes32", internalType: "bytes32" },
|
|
163
|
+
{ name: "s", type: "bytes32", internalType: "bytes32" },
|
|
164
|
+
{ name: "v", type: "uint8", internalType: "uint8" }
|
|
165
|
+
]
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "permit",
|
|
169
|
+
type: "tuple",
|
|
170
|
+
internalType: "struct ISignatureTransfer.PermitTransferFrom",
|
|
171
|
+
components: [
|
|
172
|
+
{
|
|
173
|
+
name: "permitted",
|
|
174
|
+
type: "tuple",
|
|
175
|
+
internalType: "struct ISignatureTransfer.TokenPermissions",
|
|
176
|
+
components: [
|
|
177
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
178
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
{ name: "nonce", type: "uint256", internalType: "uint256" },
|
|
182
|
+
{ name: "deadline", type: "uint256", internalType: "uint256" }
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
{ name: "owner", type: "address", internalType: "address" },
|
|
186
|
+
{
|
|
187
|
+
name: "witness",
|
|
188
|
+
type: "tuple",
|
|
189
|
+
internalType: "struct x402BasePermit2Proxy.Witness",
|
|
190
|
+
components: [
|
|
191
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
192
|
+
{ name: "validAfter", type: "uint256", internalType: "uint256" },
|
|
193
|
+
{ name: "extra", type: "bytes", internalType: "bytes" }
|
|
194
|
+
]
|
|
195
|
+
},
|
|
196
|
+
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
197
|
+
],
|
|
198
|
+
outputs: [],
|
|
199
|
+
stateMutability: "nonpayable"
|
|
200
|
+
},
|
|
201
|
+
{ type: "event", name: "Settled", inputs: [], anonymous: false },
|
|
202
|
+
{ type: "event", name: "SettledWithPermit", inputs: [], anonymous: false },
|
|
203
|
+
{ type: "error", name: "AlreadyInitialized", inputs: [] },
|
|
204
|
+
{ type: "error", name: "InvalidDestination", inputs: [] },
|
|
205
|
+
{ type: "error", name: "InvalidOwner", inputs: [] },
|
|
206
|
+
{ type: "error", name: "InvalidPermit2Address", inputs: [] },
|
|
207
|
+
{ type: "error", name: "PaymentTooEarly", inputs: [] },
|
|
208
|
+
{ type: "error", name: "ReentrancyGuardReentrantCall", inputs: [] }
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
// src/utils.ts
|
|
212
|
+
import { toHex } from "viem";
|
|
213
|
+
function getEvmChainId(network) {
|
|
214
|
+
const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];
|
|
215
|
+
if (!chainId) {
|
|
216
|
+
throw new Error(`Unsupported network: ${network}`);
|
|
217
|
+
}
|
|
218
|
+
return chainId;
|
|
219
|
+
}
|
|
220
|
+
function getCrypto() {
|
|
221
|
+
const cryptoObj = globalThis.crypto;
|
|
222
|
+
if (!cryptoObj) {
|
|
223
|
+
throw new Error("Crypto API not available");
|
|
224
|
+
}
|
|
225
|
+
return cryptoObj;
|
|
226
|
+
}
|
|
227
|
+
function createNonce() {
|
|
228
|
+
return toHex(getCrypto().getRandomValues(new Uint8Array(32)));
|
|
229
|
+
}
|
|
230
|
+
function createPermit2Nonce() {
|
|
231
|
+
const randomBytes = getCrypto().getRandomValues(new Uint8Array(32));
|
|
232
|
+
return BigInt(toHex(randomBytes)).toString();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/exact/v1/client/scheme.ts
|
|
236
|
+
var ExactEvmSchemeV1 = class {
|
|
237
|
+
/**
|
|
238
|
+
* Creates a new ExactEvmClientV1 instance.
|
|
239
|
+
*
|
|
240
|
+
* @param signer - The EVM signer for client operations
|
|
241
|
+
*/
|
|
242
|
+
constructor(signer) {
|
|
243
|
+
this.signer = signer;
|
|
244
|
+
this.scheme = "exact";
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Creates a payment payload for the Exact scheme (V1).
|
|
248
|
+
*
|
|
249
|
+
* @param x402Version - The x402 protocol version
|
|
250
|
+
* @param paymentRequirements - The payment requirements
|
|
251
|
+
* @returns Promise resolving to a payment payload
|
|
252
|
+
*/
|
|
253
|
+
async createPaymentPayload(x402Version, paymentRequirements) {
|
|
254
|
+
const selectedV1 = paymentRequirements;
|
|
255
|
+
const nonce = createNonce();
|
|
256
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
257
|
+
const authorization = {
|
|
258
|
+
from: this.signer.address,
|
|
259
|
+
to: getAddress(selectedV1.payTo),
|
|
260
|
+
value: selectedV1.maxAmountRequired,
|
|
261
|
+
validAfter: (now - 600).toString(),
|
|
262
|
+
// 10 minutes before
|
|
263
|
+
validBefore: (now + selectedV1.maxTimeoutSeconds).toString(),
|
|
264
|
+
nonce
|
|
265
|
+
};
|
|
266
|
+
const signature = await this.signAuthorization(authorization, selectedV1);
|
|
267
|
+
const payload = {
|
|
268
|
+
authorization,
|
|
269
|
+
signature
|
|
270
|
+
};
|
|
271
|
+
return {
|
|
272
|
+
x402Version,
|
|
273
|
+
scheme: selectedV1.scheme,
|
|
274
|
+
network: selectedV1.network,
|
|
275
|
+
payload
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Sign the EIP-3009 authorization using EIP-712
|
|
280
|
+
*
|
|
281
|
+
* @param authorization - The authorization to sign
|
|
282
|
+
* @param requirements - The payment requirements
|
|
283
|
+
* @returns Promise resolving to the signature
|
|
284
|
+
*/
|
|
285
|
+
async signAuthorization(authorization, requirements) {
|
|
286
|
+
const chainId = getEvmChainId(requirements.network);
|
|
287
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
288
|
+
throw new Error(
|
|
289
|
+
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
const { name, version } = requirements.extra;
|
|
293
|
+
const domain = {
|
|
294
|
+
name,
|
|
295
|
+
version,
|
|
296
|
+
chainId,
|
|
297
|
+
verifyingContract: getAddress(requirements.asset)
|
|
298
|
+
};
|
|
299
|
+
const message = {
|
|
300
|
+
from: getAddress(authorization.from),
|
|
301
|
+
to: getAddress(authorization.to),
|
|
302
|
+
value: BigInt(authorization.value),
|
|
303
|
+
validAfter: BigInt(authorization.validAfter),
|
|
304
|
+
validBefore: BigInt(authorization.validBefore),
|
|
305
|
+
nonce: authorization.nonce
|
|
306
|
+
};
|
|
307
|
+
return await this.signer.signTypedData({
|
|
308
|
+
domain,
|
|
309
|
+
types: authorizationTypes,
|
|
310
|
+
primaryType: "TransferWithAuthorization",
|
|
311
|
+
message
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
// src/exact/v1/facilitator/scheme.ts
|
|
317
|
+
import { getAddress as getAddress2, isAddressEqual, parseErc6492Signature, parseSignature } from "viem";
|
|
318
|
+
var ExactEvmSchemeV12 = class {
|
|
319
|
+
/**
|
|
320
|
+
* Creates a new ExactEvmFacilitatorV1 instance.
|
|
321
|
+
*
|
|
322
|
+
* @param signer - The EVM signer for facilitator operations
|
|
323
|
+
* @param config - Optional configuration for the facilitator
|
|
324
|
+
*/
|
|
325
|
+
constructor(signer, config) {
|
|
326
|
+
this.signer = signer;
|
|
327
|
+
this.scheme = "exact";
|
|
328
|
+
this.caipFamily = "eip155:*";
|
|
329
|
+
this.config = {
|
|
330
|
+
deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? false
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Get mechanism-specific extra data for the supported kinds endpoint.
|
|
335
|
+
* For EVM, no extra data is needed.
|
|
336
|
+
*
|
|
337
|
+
* @param _ - The network identifier (unused for EVM)
|
|
338
|
+
* @returns undefined (EVM has no extra data)
|
|
339
|
+
*/
|
|
340
|
+
getExtra(_) {
|
|
341
|
+
return void 0;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Get signer addresses used by this facilitator.
|
|
345
|
+
* Returns all addresses this facilitator can use for signing/settling transactions.
|
|
346
|
+
*
|
|
347
|
+
* @param _ - The network identifier (unused for EVM, addresses are network-agnostic)
|
|
348
|
+
* @returns Array of facilitator wallet addresses
|
|
349
|
+
*/
|
|
350
|
+
getSigners(_) {
|
|
351
|
+
return [...this.signer.getAddresses()];
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Verifies a payment payload (V1).
|
|
355
|
+
*
|
|
356
|
+
* @param payload - The payment payload to verify
|
|
357
|
+
* @param requirements - The payment requirements
|
|
358
|
+
* @returns Promise resolving to verification response
|
|
359
|
+
*/
|
|
360
|
+
async verify(payload, requirements) {
|
|
361
|
+
const requirementsV1 = requirements;
|
|
362
|
+
const payloadV1 = payload;
|
|
363
|
+
const exactEvmPayload = payload.payload;
|
|
364
|
+
if (payloadV1.scheme !== "exact" || requirements.scheme !== "exact") {
|
|
365
|
+
return {
|
|
366
|
+
isValid: false,
|
|
367
|
+
invalidReason: "unsupported_scheme",
|
|
368
|
+
payer: exactEvmPayload.authorization.from
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
let chainId;
|
|
372
|
+
try {
|
|
373
|
+
chainId = getEvmChainId(payloadV1.network);
|
|
374
|
+
} catch {
|
|
375
|
+
return {
|
|
376
|
+
isValid: false,
|
|
377
|
+
invalidReason: `invalid_network`,
|
|
378
|
+
payer: exactEvmPayload.authorization.from
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
382
|
+
return {
|
|
383
|
+
isValid: false,
|
|
384
|
+
invalidReason: "missing_eip712_domain",
|
|
385
|
+
payer: exactEvmPayload.authorization.from
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
const { name, version } = requirements.extra;
|
|
389
|
+
const erc20Address = getAddress2(requirements.asset);
|
|
390
|
+
if (payloadV1.network !== requirements.network) {
|
|
391
|
+
return {
|
|
392
|
+
isValid: false,
|
|
393
|
+
invalidReason: "network_mismatch",
|
|
394
|
+
payer: exactEvmPayload.authorization.from
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
const permitTypedData = {
|
|
398
|
+
types: authorizationTypes,
|
|
399
|
+
primaryType: "TransferWithAuthorization",
|
|
400
|
+
domain: {
|
|
401
|
+
name,
|
|
402
|
+
version,
|
|
403
|
+
chainId,
|
|
404
|
+
verifyingContract: erc20Address
|
|
405
|
+
},
|
|
406
|
+
message: {
|
|
407
|
+
from: exactEvmPayload.authorization.from,
|
|
408
|
+
to: exactEvmPayload.authorization.to,
|
|
409
|
+
value: BigInt(exactEvmPayload.authorization.value),
|
|
410
|
+
validAfter: BigInt(exactEvmPayload.authorization.validAfter),
|
|
411
|
+
validBefore: BigInt(exactEvmPayload.authorization.validBefore),
|
|
412
|
+
nonce: exactEvmPayload.authorization.nonce
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
try {
|
|
416
|
+
const recoveredAddress = await this.signer.verifyTypedData({
|
|
417
|
+
address: exactEvmPayload.authorization.from,
|
|
418
|
+
...permitTypedData,
|
|
419
|
+
signature: exactEvmPayload.signature
|
|
420
|
+
});
|
|
421
|
+
if (!recoveredAddress) {
|
|
422
|
+
return {
|
|
423
|
+
isValid: false,
|
|
424
|
+
invalidReason: "invalid_exact_evm_payload_signature",
|
|
425
|
+
payer: exactEvmPayload.authorization.from
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
} catch {
|
|
429
|
+
const signature = exactEvmPayload.signature;
|
|
430
|
+
const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
|
|
431
|
+
const isSmartWallet = signatureLength > 130;
|
|
432
|
+
if (isSmartWallet) {
|
|
433
|
+
const payerAddress = exactEvmPayload.authorization.from;
|
|
434
|
+
const bytecode = await this.signer.getCode({ address: payerAddress });
|
|
435
|
+
if (!bytecode || bytecode === "0x") {
|
|
436
|
+
const erc6492Data = parseErc6492Signature(signature);
|
|
437
|
+
const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !isAddressEqual(erc6492Data.address, "0x0000000000000000000000000000000000000000");
|
|
438
|
+
if (!hasDeploymentInfo) {
|
|
439
|
+
return {
|
|
440
|
+
isValid: false,
|
|
441
|
+
invalidReason: "invalid_exact_evm_payload_undeployed_smart_wallet",
|
|
442
|
+
payer: payerAddress
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
} else {
|
|
446
|
+
return {
|
|
447
|
+
isValid: false,
|
|
448
|
+
invalidReason: "invalid_exact_evm_payload_signature",
|
|
449
|
+
payer: exactEvmPayload.authorization.from
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
} else {
|
|
453
|
+
return {
|
|
454
|
+
isValid: false,
|
|
455
|
+
invalidReason: "invalid_exact_evm_payload_signature",
|
|
456
|
+
payer: exactEvmPayload.authorization.from
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (getAddress2(exactEvmPayload.authorization.to) !== getAddress2(requirements.payTo)) {
|
|
461
|
+
return {
|
|
462
|
+
isValid: false,
|
|
463
|
+
invalidReason: "invalid_exact_evm_payload_recipient_mismatch",
|
|
464
|
+
payer: exactEvmPayload.authorization.from
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
468
|
+
if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) {
|
|
469
|
+
return {
|
|
470
|
+
isValid: false,
|
|
471
|
+
invalidReason: "invalid_exact_evm_payload_authorization_valid_before",
|
|
472
|
+
payer: exactEvmPayload.authorization.from
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) {
|
|
476
|
+
return {
|
|
477
|
+
isValid: false,
|
|
478
|
+
invalidReason: "invalid_exact_evm_payload_authorization_valid_after",
|
|
479
|
+
payer: exactEvmPayload.authorization.from
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
try {
|
|
483
|
+
const balance = await this.signer.readContract({
|
|
484
|
+
address: erc20Address,
|
|
485
|
+
abi: eip3009ABI,
|
|
486
|
+
functionName: "balanceOf",
|
|
487
|
+
args: [exactEvmPayload.authorization.from]
|
|
488
|
+
});
|
|
489
|
+
if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {
|
|
490
|
+
return {
|
|
491
|
+
isValid: false,
|
|
492
|
+
invalidReason: "insufficient_funds",
|
|
493
|
+
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.`,
|
|
494
|
+
payer: exactEvmPayload.authorization.from
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
} catch {
|
|
498
|
+
}
|
|
499
|
+
if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) {
|
|
500
|
+
return {
|
|
501
|
+
isValid: false,
|
|
502
|
+
invalidReason: "invalid_exact_evm_payload_authorization_value",
|
|
503
|
+
payer: exactEvmPayload.authorization.from
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
return {
|
|
507
|
+
isValid: true,
|
|
508
|
+
invalidReason: void 0,
|
|
509
|
+
payer: exactEvmPayload.authorization.from
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Settles a payment by executing the transfer (V1).
|
|
514
|
+
*
|
|
515
|
+
* @param payload - The payment payload to settle
|
|
516
|
+
* @param requirements - The payment requirements
|
|
517
|
+
* @returns Promise resolving to settlement response
|
|
518
|
+
*/
|
|
519
|
+
async settle(payload, requirements) {
|
|
520
|
+
const payloadV1 = payload;
|
|
521
|
+
const exactEvmPayload = payload.payload;
|
|
522
|
+
const valid = await this.verify(payload, requirements);
|
|
523
|
+
if (!valid.isValid) {
|
|
524
|
+
return {
|
|
525
|
+
success: false,
|
|
526
|
+
network: payloadV1.network,
|
|
527
|
+
transaction: "",
|
|
528
|
+
errorReason: valid.invalidReason ?? "invalid_scheme",
|
|
529
|
+
payer: exactEvmPayload.authorization.from
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
try {
|
|
533
|
+
const parseResult = parseErc6492Signature(exactEvmPayload.signature);
|
|
534
|
+
const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;
|
|
535
|
+
if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !isAddressEqual(factoryAddress, "0x0000000000000000000000000000000000000000")) {
|
|
536
|
+
const payerAddress = exactEvmPayload.authorization.from;
|
|
537
|
+
const bytecode = await this.signer.getCode({ address: payerAddress });
|
|
538
|
+
if (!bytecode || bytecode === "0x") {
|
|
539
|
+
try {
|
|
540
|
+
console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);
|
|
541
|
+
const deployTx = await this.signer.sendTransaction({
|
|
542
|
+
to: factoryAddress,
|
|
543
|
+
data: factoryCalldata
|
|
544
|
+
});
|
|
545
|
+
await this.signer.waitForTransactionReceipt({ hash: deployTx });
|
|
546
|
+
console.log(`Successfully deployed smart wallet for ${payerAddress}`);
|
|
547
|
+
} catch (deployError) {
|
|
548
|
+
console.error("Smart wallet deployment failed:", deployError);
|
|
549
|
+
throw deployError;
|
|
550
|
+
}
|
|
551
|
+
} else {
|
|
552
|
+
console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
|
|
556
|
+
const isECDSA = signatureLength === 130;
|
|
557
|
+
let tx;
|
|
558
|
+
if (isECDSA) {
|
|
559
|
+
const parsedSig = parseSignature(signature);
|
|
560
|
+
tx = await this.signer.writeContract({
|
|
561
|
+
address: getAddress2(requirements.asset),
|
|
562
|
+
abi: eip3009ABI,
|
|
563
|
+
functionName: "transferWithAuthorization",
|
|
564
|
+
args: [
|
|
565
|
+
getAddress2(exactEvmPayload.authorization.from),
|
|
566
|
+
getAddress2(exactEvmPayload.authorization.to),
|
|
567
|
+
BigInt(exactEvmPayload.authorization.value),
|
|
568
|
+
BigInt(exactEvmPayload.authorization.validAfter),
|
|
569
|
+
BigInt(exactEvmPayload.authorization.validBefore),
|
|
570
|
+
exactEvmPayload.authorization.nonce,
|
|
571
|
+
parsedSig.v || parsedSig.yParity,
|
|
572
|
+
parsedSig.r,
|
|
573
|
+
parsedSig.s
|
|
574
|
+
]
|
|
575
|
+
});
|
|
576
|
+
} else {
|
|
577
|
+
tx = await this.signer.writeContract({
|
|
578
|
+
address: getAddress2(requirements.asset),
|
|
579
|
+
abi: eip3009ABI,
|
|
580
|
+
functionName: "transferWithAuthorization",
|
|
581
|
+
args: [
|
|
582
|
+
getAddress2(exactEvmPayload.authorization.from),
|
|
583
|
+
getAddress2(exactEvmPayload.authorization.to),
|
|
584
|
+
BigInt(exactEvmPayload.authorization.value),
|
|
585
|
+
BigInt(exactEvmPayload.authorization.validAfter),
|
|
586
|
+
BigInt(exactEvmPayload.authorization.validBefore),
|
|
587
|
+
exactEvmPayload.authorization.nonce,
|
|
588
|
+
signature
|
|
589
|
+
]
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });
|
|
593
|
+
if (receipt.status !== "success") {
|
|
594
|
+
return {
|
|
595
|
+
success: false,
|
|
596
|
+
errorReason: "invalid_transaction_state",
|
|
597
|
+
transaction: tx,
|
|
598
|
+
network: payloadV1.network,
|
|
599
|
+
payer: exactEvmPayload.authorization.from
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
return {
|
|
603
|
+
success: true,
|
|
604
|
+
transaction: tx,
|
|
605
|
+
network: payloadV1.network,
|
|
606
|
+
payer: exactEvmPayload.authorization.from
|
|
607
|
+
};
|
|
608
|
+
} catch (error) {
|
|
609
|
+
console.error("Failed to settle transaction:", error);
|
|
610
|
+
return {
|
|
611
|
+
success: false,
|
|
612
|
+
errorReason: "transaction_failed",
|
|
613
|
+
transaction: "",
|
|
614
|
+
network: payloadV1.network,
|
|
615
|
+
payer: exactEvmPayload.authorization.from
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
// src/v1/index.ts
|
|
622
|
+
var EVM_NETWORK_CHAIN_ID_MAP = {
|
|
623
|
+
ethereum: 1,
|
|
624
|
+
sepolia: 11155111,
|
|
625
|
+
abstract: 2741,
|
|
626
|
+
"abstract-testnet": 11124,
|
|
627
|
+
"base-sepolia": 84532,
|
|
628
|
+
base: 8453,
|
|
629
|
+
"avalanche-fuji": 43113,
|
|
630
|
+
avalanche: 43114,
|
|
631
|
+
iotex: 4689,
|
|
632
|
+
sei: 1329,
|
|
633
|
+
"sei-testnet": 1328,
|
|
634
|
+
polygon: 137,
|
|
635
|
+
"polygon-amoy": 80002,
|
|
636
|
+
peaq: 3338,
|
|
637
|
+
story: 1514,
|
|
638
|
+
educhain: 41923,
|
|
639
|
+
"skale-base-sepolia": 324705682,
|
|
640
|
+
megaeth: 4326
|
|
641
|
+
};
|
|
642
|
+
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
643
|
+
|
|
644
|
+
export {
|
|
645
|
+
authorizationTypes,
|
|
646
|
+
permit2WitnessTypes,
|
|
647
|
+
eip3009ABI,
|
|
648
|
+
PERMIT2_ADDRESS,
|
|
649
|
+
x402ExactPermit2ProxyAddress,
|
|
650
|
+
x402UptoPermit2ProxyAddress,
|
|
651
|
+
x402ExactPermit2ProxyABI,
|
|
652
|
+
ExactEvmSchemeV1,
|
|
653
|
+
ExactEvmSchemeV12,
|
|
654
|
+
EVM_NETWORK_CHAIN_ID_MAP,
|
|
655
|
+
NETWORKS,
|
|
656
|
+
createNonce,
|
|
657
|
+
createPermit2Nonce
|
|
658
|
+
};
|
|
659
|
+
//# sourceMappingURL=chunk-RPL6OFJL.mjs.map
|