@x402/evm 2.3.1 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/exact/client/index.d.ts +2 -2
- package/dist/cjs/exact/client/index.js +412 -169
- package/dist/cjs/exact/client/index.js.map +1 -1
- package/dist/cjs/exact/facilitator/index.d.ts +18 -18
- package/dist/cjs/exact/facilitator/index.js +467 -157
- 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 +17 -18
- package/dist/cjs/exact/v1/client/index.js.map +1 -1
- package/dist/cjs/exact/v1/facilitator/index.d.ts +1 -1
- package/dist/cjs/exact/v1/facilitator/index.js +7 -8
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
- package/dist/cjs/index.d.ts +3 -390
- package/dist/cjs/index.js +363 -110
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/permit2-CQbXqCMC.d.ts +517 -0
- package/dist/cjs/signer-DC81R8wQ.d.ts +161 -0
- package/dist/cjs/v1/index.d.ts +11 -2
- package/dist/cjs/v1/index.js +14 -11
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/{chunk-RPL6OFJL.mjs → chunk-7KHQD5KT.mjs} +92 -37
- package/dist/esm/chunk-7KHQD5KT.mjs.map +1 -0
- package/dist/esm/chunk-GY6X5A3G.mjs +425 -0
- package/dist/esm/chunk-GY6X5A3G.mjs.map +1 -0
- package/dist/esm/{chunk-PFULIQAE.mjs → chunk-TKN5V2BV.mjs} +1 -1
- package/dist/esm/chunk-TKN5V2BV.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +2 -2
- package/dist/esm/exact/client/index.mjs +4 -3
- package/dist/esm/exact/facilitator/index.d.mts +18 -18
- package/dist/esm/exact/facilitator/index.mjs +401 -99
- 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 +2 -2
- package/dist/esm/exact/v1/facilitator/index.d.mts +1 -1
- package/dist/esm/exact/v1/facilitator/index.mjs +2 -2
- package/dist/esm/index.d.mts +3 -390
- package/dist/esm/index.mjs +29 -6
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/permit2-CGOcN7Et.d.mts +517 -0
- package/dist/esm/signer-DC81R8wQ.d.mts +161 -0
- package/dist/esm/v1/index.d.mts +11 -2
- package/dist/esm/v1/index.mjs +6 -4
- package/package.json +3 -2
- package/dist/cjs/permit2-BYv82va2.d.ts +0 -103
- package/dist/cjs/signer-5OVDxViv.d.ts +0 -79
- package/dist/esm/chunk-E2YMUI3X.mjs +0 -229
- package/dist/esm/chunk-E2YMUI3X.mjs.map +0 -1
- package/dist/esm/chunk-PFULIQAE.mjs.map +0 -1
- package/dist/esm/chunk-RPL6OFJL.mjs.map +0 -1
- package/dist/esm/permit2-BsAoJiWD.d.mts +0 -103
- package/dist/esm/signer-5OVDxViv.d.mts +0 -79
package/dist/cjs/index.js
CHANGED
|
@@ -38,8 +38,8 @@ __export(src_exports, {
|
|
|
38
38
|
});
|
|
39
39
|
module.exports = __toCommonJS(src_exports);
|
|
40
40
|
|
|
41
|
-
// src/exact/client/
|
|
42
|
-
var
|
|
41
|
+
// src/exact/client/scheme.ts
|
|
42
|
+
var import_extensions2 = require("@x402/extensions");
|
|
43
43
|
|
|
44
44
|
// src/constants.ts
|
|
45
45
|
var authorizationTypes = {
|
|
@@ -66,8 +66,7 @@ var permit2WitnessTypes = {
|
|
|
66
66
|
],
|
|
67
67
|
Witness: [
|
|
68
68
|
{ name: "to", type: "address" },
|
|
69
|
-
{ name: "validAfter", type: "uint256" }
|
|
70
|
-
{ name: "extra", type: "bytes" }
|
|
69
|
+
{ name: "validAfter", type: "uint256" }
|
|
71
70
|
]
|
|
72
71
|
};
|
|
73
72
|
var eip3009ABI = [
|
|
@@ -118,9 +117,58 @@ var eip3009ABI = [
|
|
|
118
117
|
type: "function"
|
|
119
118
|
}
|
|
120
119
|
];
|
|
120
|
+
var eip2612PermitTypes = {
|
|
121
|
+
Permit: [
|
|
122
|
+
{ name: "owner", type: "address" },
|
|
123
|
+
{ name: "spender", type: "address" },
|
|
124
|
+
{ name: "value", type: "uint256" },
|
|
125
|
+
{ name: "nonce", type: "uint256" },
|
|
126
|
+
{ name: "deadline", type: "uint256" }
|
|
127
|
+
]
|
|
128
|
+
};
|
|
129
|
+
var eip2612NoncesAbi = [
|
|
130
|
+
{
|
|
131
|
+
type: "function",
|
|
132
|
+
name: "nonces",
|
|
133
|
+
inputs: [{ name: "owner", type: "address" }],
|
|
134
|
+
outputs: [{ type: "uint256" }],
|
|
135
|
+
stateMutability: "view"
|
|
136
|
+
}
|
|
137
|
+
];
|
|
138
|
+
var erc20ApproveAbi = [
|
|
139
|
+
{
|
|
140
|
+
type: "function",
|
|
141
|
+
name: "approve",
|
|
142
|
+
inputs: [
|
|
143
|
+
{ name: "spender", type: "address" },
|
|
144
|
+
{ name: "amount", type: "uint256" }
|
|
145
|
+
],
|
|
146
|
+
outputs: [{ type: "bool" }],
|
|
147
|
+
stateMutability: "nonpayable"
|
|
148
|
+
}
|
|
149
|
+
];
|
|
150
|
+
var erc20AllowanceAbi = [
|
|
151
|
+
{
|
|
152
|
+
type: "function",
|
|
153
|
+
name: "allowance",
|
|
154
|
+
inputs: [
|
|
155
|
+
{ name: "owner", type: "address" },
|
|
156
|
+
{ name: "spender", type: "address" }
|
|
157
|
+
],
|
|
158
|
+
outputs: [{ type: "uint256" }],
|
|
159
|
+
stateMutability: "view"
|
|
160
|
+
}
|
|
161
|
+
];
|
|
162
|
+
var ERC20_APPROVE_GAS_LIMIT = 70000n;
|
|
163
|
+
var DEFAULT_MAX_FEE_PER_GAS = 1000000000n;
|
|
164
|
+
var DEFAULT_MAX_PRIORITY_FEE_PER_GAS = 100000000n;
|
|
121
165
|
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
122
|
-
var x402ExactPermit2ProxyAddress = "
|
|
123
|
-
var x402UptoPermit2ProxyAddress = "
|
|
166
|
+
var x402ExactPermit2ProxyAddress = "0x402085c248EeA27D92E8b30b2C58ed07f9E20001";
|
|
167
|
+
var x402UptoPermit2ProxyAddress = "0x402039b3d6E6BEC5A02c2C9fd937ac17A6940002";
|
|
168
|
+
var permit2WitnessABIComponents = [
|
|
169
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
170
|
+
{ name: "validAfter", type: "uint256", internalType: "uint256" }
|
|
171
|
+
];
|
|
124
172
|
var x402ExactPermit2ProxyABI = [
|
|
125
173
|
{
|
|
126
174
|
type: "function",
|
|
@@ -143,13 +191,6 @@ var x402ExactPermit2ProxyABI = [
|
|
|
143
191
|
outputs: [{ name: "", type: "string", internalType: "string" }],
|
|
144
192
|
stateMutability: "view"
|
|
145
193
|
},
|
|
146
|
-
{
|
|
147
|
-
type: "function",
|
|
148
|
-
name: "initialize",
|
|
149
|
-
inputs: [{ name: "_permit2", type: "address", internalType: "address" }],
|
|
150
|
-
outputs: [],
|
|
151
|
-
stateMutability: "nonpayable"
|
|
152
|
-
},
|
|
153
194
|
{
|
|
154
195
|
type: "function",
|
|
155
196
|
name: "settle",
|
|
@@ -176,12 +217,8 @@ var x402ExactPermit2ProxyABI = [
|
|
|
176
217
|
{
|
|
177
218
|
name: "witness",
|
|
178
219
|
type: "tuple",
|
|
179
|
-
internalType: "struct
|
|
180
|
-
components:
|
|
181
|
-
{ name: "to", type: "address", internalType: "address" },
|
|
182
|
-
{ name: "validAfter", type: "uint256", internalType: "uint256" },
|
|
183
|
-
{ name: "extra", type: "bytes", internalType: "bytes" }
|
|
184
|
-
]
|
|
220
|
+
internalType: "struct x402ExactPermit2Proxy.Witness",
|
|
221
|
+
components: permit2WitnessABIComponents
|
|
185
222
|
},
|
|
186
223
|
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
187
224
|
],
|
|
@@ -195,7 +232,7 @@ var x402ExactPermit2ProxyABI = [
|
|
|
195
232
|
{
|
|
196
233
|
name: "permit2612",
|
|
197
234
|
type: "tuple",
|
|
198
|
-
internalType: "struct
|
|
235
|
+
internalType: "struct x402ExactPermit2Proxy.EIP2612Permit",
|
|
199
236
|
components: [
|
|
200
237
|
{ name: "value", type: "uint256", internalType: "uint256" },
|
|
201
238
|
{ name: "deadline", type: "uint256", internalType: "uint256" },
|
|
@@ -226,12 +263,8 @@ var x402ExactPermit2ProxyABI = [
|
|
|
226
263
|
{
|
|
227
264
|
name: "witness",
|
|
228
265
|
type: "tuple",
|
|
229
|
-
internalType: "struct
|
|
230
|
-
components:
|
|
231
|
-
{ name: "to", type: "address", internalType: "address" },
|
|
232
|
-
{ name: "validAfter", type: "uint256", internalType: "uint256" },
|
|
233
|
-
{ name: "extra", type: "bytes", internalType: "bytes" }
|
|
234
|
-
]
|
|
266
|
+
internalType: "struct x402ExactPermit2Proxy.Witness",
|
|
267
|
+
components: permit2WitnessABIComponents
|
|
235
268
|
},
|
|
236
269
|
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
237
270
|
],
|
|
@@ -240,47 +273,31 @@ var x402ExactPermit2ProxyABI = [
|
|
|
240
273
|
},
|
|
241
274
|
{ type: "event", name: "Settled", inputs: [], anonymous: false },
|
|
242
275
|
{ type: "event", name: "SettledWithPermit", inputs: [], anonymous: false },
|
|
243
|
-
{ type: "error", name: "
|
|
276
|
+
{ type: "error", name: "InvalidAmount", inputs: [] },
|
|
244
277
|
{ type: "error", name: "InvalidDestination", inputs: [] },
|
|
245
278
|
{ type: "error", name: "InvalidOwner", inputs: [] },
|
|
246
279
|
{ type: "error", name: "InvalidPermit2Address", inputs: [] },
|
|
247
280
|
{ type: "error", name: "PaymentTooEarly", inputs: [] },
|
|
281
|
+
{ type: "error", name: "Permit2612AmountMismatch", inputs: [] },
|
|
248
282
|
{ type: "error", name: "ReentrancyGuardReentrantCall", inputs: [] }
|
|
249
283
|
];
|
|
250
284
|
|
|
251
|
-
// src/
|
|
252
|
-
var
|
|
253
|
-
|
|
254
|
-
// src/exact/v1/client/scheme.ts
|
|
255
|
-
var import_viem = require("viem");
|
|
256
|
-
|
|
257
|
-
// src/exact/v1/facilitator/scheme.ts
|
|
258
|
-
var import_viem2 = require("viem");
|
|
259
|
-
|
|
260
|
-
// src/v1/index.ts
|
|
261
|
-
var EVM_NETWORK_CHAIN_ID_MAP = {
|
|
262
|
-
ethereum: 1,
|
|
263
|
-
sepolia: 11155111,
|
|
264
|
-
abstract: 2741,
|
|
265
|
-
"abstract-testnet": 11124,
|
|
266
|
-
"base-sepolia": 84532,
|
|
267
|
-
base: 8453,
|
|
268
|
-
"avalanche-fuji": 43113,
|
|
269
|
-
avalanche: 43114,
|
|
270
|
-
iotex: 4689,
|
|
271
|
-
sei: 1329,
|
|
272
|
-
"sei-testnet": 1328,
|
|
273
|
-
polygon: 137,
|
|
274
|
-
"polygon-amoy": 80002,
|
|
275
|
-
peaq: 3338,
|
|
276
|
-
story: 1514,
|
|
277
|
-
educhain: 41923,
|
|
278
|
-
"skale-base-sepolia": 324705682,
|
|
279
|
-
megaeth: 4326
|
|
280
|
-
};
|
|
281
|
-
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
285
|
+
// src/exact/client/scheme.ts
|
|
286
|
+
var import_viem6 = require("viem");
|
|
282
287
|
|
|
283
288
|
// src/utils.ts
|
|
289
|
+
var import_viem = require("viem");
|
|
290
|
+
function getEvmChainId(network) {
|
|
291
|
+
if (network.startsWith("eip155:")) {
|
|
292
|
+
const idStr = network.split(":")[1];
|
|
293
|
+
const chainId = parseInt(idStr, 10);
|
|
294
|
+
if (isNaN(chainId)) {
|
|
295
|
+
throw new Error(`Invalid CAIP-2 chain ID: ${network}`);
|
|
296
|
+
}
|
|
297
|
+
return chainId;
|
|
298
|
+
}
|
|
299
|
+
throw new Error(`Unsupported network format: ${network} (expected eip155:CHAIN_ID)`);
|
|
300
|
+
}
|
|
284
301
|
function getCrypto() {
|
|
285
302
|
const cryptoObj = globalThis.crypto;
|
|
286
303
|
if (!cryptoObj) {
|
|
@@ -289,20 +306,21 @@ function getCrypto() {
|
|
|
289
306
|
return cryptoObj;
|
|
290
307
|
}
|
|
291
308
|
function createNonce() {
|
|
292
|
-
return (0,
|
|
309
|
+
return (0, import_viem.toHex)(getCrypto().getRandomValues(new Uint8Array(32)));
|
|
293
310
|
}
|
|
294
311
|
function createPermit2Nonce() {
|
|
295
312
|
const randomBytes = getCrypto().getRandomValues(new Uint8Array(32));
|
|
296
|
-
return BigInt((0,
|
|
313
|
+
return BigInt((0, import_viem.toHex)(randomBytes)).toString();
|
|
297
314
|
}
|
|
298
315
|
|
|
299
316
|
// src/exact/client/eip3009.ts
|
|
317
|
+
var import_viem2 = require("viem");
|
|
300
318
|
async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
|
|
301
319
|
const nonce = createNonce();
|
|
302
320
|
const now = Math.floor(Date.now() / 1e3);
|
|
303
321
|
const authorization = {
|
|
304
322
|
from: signer.address,
|
|
305
|
-
to: (0,
|
|
323
|
+
to: (0, import_viem2.getAddress)(paymentRequirements.payTo),
|
|
306
324
|
value: paymentRequirements.amount,
|
|
307
325
|
validAfter: (now - 600).toString(),
|
|
308
326
|
validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),
|
|
@@ -319,7 +337,7 @@ async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
|
|
|
319
337
|
};
|
|
320
338
|
}
|
|
321
339
|
async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
322
|
-
const chainId =
|
|
340
|
+
const chainId = getEvmChainId(requirements.network);
|
|
323
341
|
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
324
342
|
throw new Error(
|
|
325
343
|
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
@@ -330,11 +348,11 @@ async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
|
330
348
|
name,
|
|
331
349
|
version,
|
|
332
350
|
chainId,
|
|
333
|
-
verifyingContract: (0,
|
|
351
|
+
verifyingContract: (0, import_viem2.getAddress)(requirements.asset)
|
|
334
352
|
};
|
|
335
353
|
const message = {
|
|
336
|
-
from: (0,
|
|
337
|
-
to: (0,
|
|
354
|
+
from: (0, import_viem2.getAddress)(authorization.from),
|
|
355
|
+
to: (0, import_viem2.getAddress)(authorization.to),
|
|
338
356
|
value: BigInt(authorization.value),
|
|
339
357
|
validAfter: BigInt(authorization.validAfter),
|
|
340
358
|
validBefore: BigInt(authorization.validBefore),
|
|
@@ -349,7 +367,7 @@ async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
|
349
367
|
}
|
|
350
368
|
|
|
351
369
|
// src/exact/client/permit2.ts
|
|
352
|
-
var
|
|
370
|
+
var import_viem3 = require("viem");
|
|
353
371
|
var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
354
372
|
async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
355
373
|
const now = Math.floor(Date.now() / 1e3);
|
|
@@ -359,16 +377,15 @@ async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
|
359
377
|
const permit2Authorization = {
|
|
360
378
|
from: signer.address,
|
|
361
379
|
permitted: {
|
|
362
|
-
token: (0,
|
|
380
|
+
token: (0, import_viem3.getAddress)(paymentRequirements.asset),
|
|
363
381
|
amount: paymentRequirements.amount
|
|
364
382
|
},
|
|
365
383
|
spender: x402ExactPermit2ProxyAddress,
|
|
366
384
|
nonce,
|
|
367
385
|
deadline,
|
|
368
386
|
witness: {
|
|
369
|
-
to: (0,
|
|
370
|
-
validAfter
|
|
371
|
-
extra: "0x"
|
|
387
|
+
to: (0, import_viem3.getAddress)(paymentRequirements.payTo),
|
|
388
|
+
validAfter
|
|
372
389
|
}
|
|
373
390
|
};
|
|
374
391
|
const signature = await signPermit2Authorization(
|
|
@@ -386,7 +403,7 @@ async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
|
386
403
|
};
|
|
387
404
|
}
|
|
388
405
|
async function signPermit2Authorization(signer, permit2Authorization, requirements) {
|
|
389
|
-
const chainId =
|
|
406
|
+
const chainId = getEvmChainId(requirements.network);
|
|
390
407
|
const domain = {
|
|
391
408
|
name: "Permit2",
|
|
392
409
|
chainId,
|
|
@@ -394,16 +411,15 @@ async function signPermit2Authorization(signer, permit2Authorization, requiremen
|
|
|
394
411
|
};
|
|
395
412
|
const message = {
|
|
396
413
|
permitted: {
|
|
397
|
-
token: (0,
|
|
414
|
+
token: (0, import_viem3.getAddress)(permit2Authorization.permitted.token),
|
|
398
415
|
amount: BigInt(permit2Authorization.permitted.amount)
|
|
399
416
|
},
|
|
400
|
-
spender: (0,
|
|
417
|
+
spender: (0, import_viem3.getAddress)(permit2Authorization.spender),
|
|
401
418
|
nonce: BigInt(permit2Authorization.nonce),
|
|
402
419
|
deadline: BigInt(permit2Authorization.deadline),
|
|
403
420
|
witness: {
|
|
404
|
-
to: (0,
|
|
405
|
-
validAfter: BigInt(permit2Authorization.witness.validAfter)
|
|
406
|
-
extra: permit2Authorization.witness.extra
|
|
421
|
+
to: (0, import_viem3.getAddress)(permit2Authorization.witness.to),
|
|
422
|
+
validAfter: BigInt(permit2Authorization.witness.validAfter)
|
|
407
423
|
}
|
|
408
424
|
};
|
|
409
425
|
return await signer.signTypedData({
|
|
@@ -413,47 +429,107 @@ async function signPermit2Authorization(signer, permit2Authorization, requiremen
|
|
|
413
429
|
message
|
|
414
430
|
});
|
|
415
431
|
}
|
|
416
|
-
var erc20ApproveAbi = [
|
|
417
|
-
{
|
|
418
|
-
type: "function",
|
|
419
|
-
name: "approve",
|
|
420
|
-
inputs: [
|
|
421
|
-
{ name: "spender", type: "address" },
|
|
422
|
-
{ name: "amount", type: "uint256" }
|
|
423
|
-
],
|
|
424
|
-
outputs: [{ type: "bool" }],
|
|
425
|
-
stateMutability: "nonpayable"
|
|
426
|
-
}
|
|
427
|
-
];
|
|
428
|
-
var erc20AllowanceAbi = [
|
|
429
|
-
{
|
|
430
|
-
type: "function",
|
|
431
|
-
name: "allowance",
|
|
432
|
-
inputs: [
|
|
433
|
-
{ name: "owner", type: "address" },
|
|
434
|
-
{ name: "spender", type: "address" }
|
|
435
|
-
],
|
|
436
|
-
outputs: [{ type: "uint256" }],
|
|
437
|
-
stateMutability: "view"
|
|
438
|
-
}
|
|
439
|
-
];
|
|
440
432
|
function createPermit2ApprovalTx(tokenAddress) {
|
|
441
|
-
const data = (0,
|
|
433
|
+
const data = (0, import_viem3.encodeFunctionData)({
|
|
442
434
|
abi: erc20ApproveAbi,
|
|
443
435
|
functionName: "approve",
|
|
444
436
|
args: [PERMIT2_ADDRESS, MAX_UINT256]
|
|
445
437
|
});
|
|
446
438
|
return {
|
|
447
|
-
to: (0,
|
|
439
|
+
to: (0, import_viem3.getAddress)(tokenAddress),
|
|
448
440
|
data
|
|
449
441
|
};
|
|
450
442
|
}
|
|
451
443
|
function getPermit2AllowanceReadParams(params) {
|
|
452
444
|
return {
|
|
453
|
-
address: (0,
|
|
445
|
+
address: (0, import_viem3.getAddress)(params.tokenAddress),
|
|
454
446
|
abi: erc20AllowanceAbi,
|
|
455
447
|
functionName: "allowance",
|
|
456
|
-
args: [(0,
|
|
448
|
+
args: [(0, import_viem3.getAddress)(params.ownerAddress), PERMIT2_ADDRESS]
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// src/exact/client/eip2612.ts
|
|
453
|
+
var import_viem4 = require("viem");
|
|
454
|
+
async function signEip2612Permit(signer, tokenAddress, tokenName, tokenVersion, chainId, deadline, permittedAmount) {
|
|
455
|
+
const owner = signer.address;
|
|
456
|
+
const spender = (0, import_viem4.getAddress)(PERMIT2_ADDRESS);
|
|
457
|
+
const nonce = await signer.readContract({
|
|
458
|
+
address: tokenAddress,
|
|
459
|
+
abi: eip2612NoncesAbi,
|
|
460
|
+
functionName: "nonces",
|
|
461
|
+
args: [owner]
|
|
462
|
+
});
|
|
463
|
+
const domain = {
|
|
464
|
+
name: tokenName,
|
|
465
|
+
version: tokenVersion,
|
|
466
|
+
chainId,
|
|
467
|
+
verifyingContract: tokenAddress
|
|
468
|
+
};
|
|
469
|
+
const approvalAmount = BigInt(permittedAmount);
|
|
470
|
+
const message = {
|
|
471
|
+
owner,
|
|
472
|
+
spender,
|
|
473
|
+
value: approvalAmount,
|
|
474
|
+
nonce,
|
|
475
|
+
deadline: BigInt(deadline)
|
|
476
|
+
};
|
|
477
|
+
const signature = await signer.signTypedData({
|
|
478
|
+
domain,
|
|
479
|
+
types: eip2612PermitTypes,
|
|
480
|
+
primaryType: "Permit",
|
|
481
|
+
message
|
|
482
|
+
});
|
|
483
|
+
return {
|
|
484
|
+
from: owner,
|
|
485
|
+
asset: tokenAddress,
|
|
486
|
+
spender,
|
|
487
|
+
amount: approvalAmount.toString(),
|
|
488
|
+
nonce: nonce.toString(),
|
|
489
|
+
deadline,
|
|
490
|
+
signature,
|
|
491
|
+
version: "1"
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// src/exact/client/erc20approval.ts
|
|
496
|
+
var import_viem5 = require("viem");
|
|
497
|
+
var import_extensions = require("@x402/extensions");
|
|
498
|
+
async function signErc20ApprovalTransaction(signer, tokenAddress, chainId) {
|
|
499
|
+
const from = signer.address;
|
|
500
|
+
const spender = (0, import_viem5.getAddress)(PERMIT2_ADDRESS);
|
|
501
|
+
const data = (0, import_viem5.encodeFunctionData)({
|
|
502
|
+
abi: erc20ApproveAbi,
|
|
503
|
+
functionName: "approve",
|
|
504
|
+
args: [spender, import_viem5.maxUint256]
|
|
505
|
+
});
|
|
506
|
+
const nonce = await signer.getTransactionCount({ address: from });
|
|
507
|
+
let maxFeePerGas;
|
|
508
|
+
let maxPriorityFeePerGas;
|
|
509
|
+
try {
|
|
510
|
+
const fees = await signer.estimateFeesPerGas();
|
|
511
|
+
maxFeePerGas = fees.maxFeePerGas;
|
|
512
|
+
maxPriorityFeePerGas = fees.maxPriorityFeePerGas;
|
|
513
|
+
} catch {
|
|
514
|
+
maxFeePerGas = DEFAULT_MAX_FEE_PER_GAS;
|
|
515
|
+
maxPriorityFeePerGas = DEFAULT_MAX_PRIORITY_FEE_PER_GAS;
|
|
516
|
+
}
|
|
517
|
+
const signedTransaction = await signer.signTransaction({
|
|
518
|
+
to: tokenAddress,
|
|
519
|
+
data,
|
|
520
|
+
nonce,
|
|
521
|
+
gas: ERC20_APPROVE_GAS_LIMIT,
|
|
522
|
+
maxFeePerGas,
|
|
523
|
+
maxPriorityFeePerGas,
|
|
524
|
+
chainId
|
|
525
|
+
});
|
|
526
|
+
return {
|
|
527
|
+
from,
|
|
528
|
+
asset: tokenAddress,
|
|
529
|
+
spender,
|
|
530
|
+
amount: import_viem5.maxUint256.toString(),
|
|
531
|
+
signedTransaction,
|
|
532
|
+
version: import_extensions.ERC20_APPROVAL_GAS_SPONSORING_VERSION
|
|
457
533
|
};
|
|
458
534
|
}
|
|
459
535
|
|
|
@@ -462,7 +538,9 @@ var ExactEvmScheme = class {
|
|
|
462
538
|
/**
|
|
463
539
|
* Creates a new ExactEvmClient instance.
|
|
464
540
|
*
|
|
465
|
-
* @param signer - The EVM signer for client operations
|
|
541
|
+
* @param signer - The EVM signer for client operations.
|
|
542
|
+
* Must support `readContract` for EIP-2612 gas sponsoring.
|
|
543
|
+
* Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`.
|
|
466
544
|
*/
|
|
467
545
|
constructor(signer) {
|
|
468
546
|
this.signer = signer;
|
|
@@ -472,22 +550,197 @@ var ExactEvmScheme = class {
|
|
|
472
550
|
* Creates a payment payload for the Exact scheme.
|
|
473
551
|
* Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.
|
|
474
552
|
*
|
|
553
|
+
* For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the
|
|
554
|
+
* signer supports `readContract`, automatically signs an EIP-2612 permit
|
|
555
|
+
* when Permit2 allowance is insufficient.
|
|
556
|
+
*
|
|
475
557
|
* @param x402Version - The x402 protocol version
|
|
476
558
|
* @param paymentRequirements - The payment requirements
|
|
477
|
-
* @
|
|
559
|
+
* @param context - Optional context with server-declared extensions
|
|
560
|
+
* @returns Promise resolving to a payment payload result (with optional extensions)
|
|
478
561
|
*/
|
|
479
|
-
async createPaymentPayload(x402Version, paymentRequirements) {
|
|
562
|
+
async createPaymentPayload(x402Version, paymentRequirements, context) {
|
|
480
563
|
const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009";
|
|
481
564
|
if (assetTransferMethod === "permit2") {
|
|
482
|
-
|
|
565
|
+
const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements);
|
|
566
|
+
const eip2612Extensions = await this.trySignEip2612Permit(
|
|
567
|
+
paymentRequirements,
|
|
568
|
+
result,
|
|
569
|
+
context
|
|
570
|
+
);
|
|
571
|
+
if (eip2612Extensions) {
|
|
572
|
+
return {
|
|
573
|
+
...result,
|
|
574
|
+
extensions: eip2612Extensions
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
const erc20Extensions = await this.trySignErc20Approval(paymentRequirements, result, context);
|
|
578
|
+
if (erc20Extensions) {
|
|
579
|
+
return {
|
|
580
|
+
...result,
|
|
581
|
+
extensions: erc20Extensions
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
return result;
|
|
483
585
|
}
|
|
484
586
|
return createEIP3009Payload(this.signer, x402Version, paymentRequirements);
|
|
485
587
|
}
|
|
588
|
+
/**
|
|
589
|
+
* Attempts to sign an EIP-2612 permit for gasless Permit2 approval.
|
|
590
|
+
*
|
|
591
|
+
* Returns extension data if:
|
|
592
|
+
* 1. Server advertises eip2612GasSponsoring
|
|
593
|
+
* 2. Signer has readContract capability
|
|
594
|
+
* 3. Current Permit2 allowance is insufficient
|
|
595
|
+
*
|
|
596
|
+
* Returns undefined if the extension should not be used.
|
|
597
|
+
*
|
|
598
|
+
* @param requirements - The payment requirements from the server
|
|
599
|
+
* @param result - The payment payload result from the scheme
|
|
600
|
+
* @param context - Optional context containing server extensions and metadata
|
|
601
|
+
* @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable
|
|
602
|
+
*/
|
|
603
|
+
async trySignEip2612Permit(requirements, result, context) {
|
|
604
|
+
if (!context?.extensions?.[import_extensions2.EIP2612_GAS_SPONSORING.key]) {
|
|
605
|
+
return void 0;
|
|
606
|
+
}
|
|
607
|
+
const tokenName = requirements.extra?.name;
|
|
608
|
+
const tokenVersion = requirements.extra?.version;
|
|
609
|
+
if (!tokenName || !tokenVersion) {
|
|
610
|
+
return void 0;
|
|
611
|
+
}
|
|
612
|
+
const chainId = getEvmChainId(requirements.network);
|
|
613
|
+
const tokenAddress = (0, import_viem6.getAddress)(requirements.asset);
|
|
614
|
+
try {
|
|
615
|
+
const allowance = await this.signer.readContract({
|
|
616
|
+
address: tokenAddress,
|
|
617
|
+
abi: erc20AllowanceAbi,
|
|
618
|
+
functionName: "allowance",
|
|
619
|
+
args: [this.signer.address, PERMIT2_ADDRESS]
|
|
620
|
+
});
|
|
621
|
+
if (allowance >= BigInt(requirements.amount)) {
|
|
622
|
+
return void 0;
|
|
623
|
+
}
|
|
624
|
+
} catch {
|
|
625
|
+
}
|
|
626
|
+
const permit2Auth = result.payload?.permit2Authorization;
|
|
627
|
+
const deadline = permit2Auth?.deadline ?? Math.floor(Date.now() / 1e3 + requirements.maxTimeoutSeconds).toString();
|
|
628
|
+
const info = await signEip2612Permit(
|
|
629
|
+
this.signer,
|
|
630
|
+
tokenAddress,
|
|
631
|
+
tokenName,
|
|
632
|
+
tokenVersion,
|
|
633
|
+
chainId,
|
|
634
|
+
deadline,
|
|
635
|
+
requirements.amount
|
|
636
|
+
);
|
|
637
|
+
return {
|
|
638
|
+
[import_extensions2.EIP2612_GAS_SPONSORING.key]: { info }
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Attempts to sign an ERC-20 approval transaction for gasless Permit2 approval.
|
|
643
|
+
*
|
|
644
|
+
* This is the fallback path when the token does not support EIP-2612. The client
|
|
645
|
+
* signs (but does not broadcast) a raw `approve(Permit2, MaxUint256)` transaction.
|
|
646
|
+
* The facilitator broadcasts it atomically before settling.
|
|
647
|
+
*
|
|
648
|
+
* Returns extension data if:
|
|
649
|
+
* 1. Server advertises erc20ApprovalGasSponsoring
|
|
650
|
+
* 2. Signer has signTransaction + getTransactionCount capabilities
|
|
651
|
+
* 3. Current Permit2 allowance is insufficient
|
|
652
|
+
*
|
|
653
|
+
* Returns undefined if the extension should not be used.
|
|
654
|
+
*
|
|
655
|
+
* @param requirements - The payment requirements from the server
|
|
656
|
+
* @param _result - The payment payload result from the scheme (unused)
|
|
657
|
+
* @param context - Optional context containing server extensions and metadata
|
|
658
|
+
* @returns Extension data for ERC-20 approval gas sponsoring, or undefined if not applicable
|
|
659
|
+
*/
|
|
660
|
+
async trySignErc20Approval(requirements, _result, context) {
|
|
661
|
+
if (!context?.extensions?.[import_extensions2.ERC20_APPROVAL_GAS_SPONSORING.key]) {
|
|
662
|
+
return void 0;
|
|
663
|
+
}
|
|
664
|
+
if (!this.signer.signTransaction || !this.signer.getTransactionCount) {
|
|
665
|
+
return void 0;
|
|
666
|
+
}
|
|
667
|
+
const chainId = getEvmChainId(requirements.network);
|
|
668
|
+
const tokenAddress = (0, import_viem6.getAddress)(requirements.asset);
|
|
669
|
+
try {
|
|
670
|
+
const allowance = await this.signer.readContract({
|
|
671
|
+
address: tokenAddress,
|
|
672
|
+
abi: erc20AllowanceAbi,
|
|
673
|
+
functionName: "allowance",
|
|
674
|
+
args: [this.signer.address, PERMIT2_ADDRESS]
|
|
675
|
+
});
|
|
676
|
+
if (allowance >= BigInt(requirements.amount)) {
|
|
677
|
+
return void 0;
|
|
678
|
+
}
|
|
679
|
+
} catch {
|
|
680
|
+
}
|
|
681
|
+
const info = await signErc20ApprovalTransaction(this.signer, tokenAddress, chainId);
|
|
682
|
+
return {
|
|
683
|
+
[import_extensions2.ERC20_APPROVAL_GAS_SPONSORING.key]: { info }
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
// src/exact/v1/client/scheme.ts
|
|
689
|
+
var import_viem8 = require("viem");
|
|
690
|
+
|
|
691
|
+
// src/exact/v1/facilitator/scheme.ts
|
|
692
|
+
var import_viem7 = require("viem");
|
|
693
|
+
|
|
694
|
+
// src/v1/index.ts
|
|
695
|
+
var EVM_NETWORK_CHAIN_ID_MAP = {
|
|
696
|
+
ethereum: 1,
|
|
697
|
+
sepolia: 11155111,
|
|
698
|
+
abstract: 2741,
|
|
699
|
+
"abstract-testnet": 11124,
|
|
700
|
+
"base-sepolia": 84532,
|
|
701
|
+
base: 8453,
|
|
702
|
+
"avalanche-fuji": 43113,
|
|
703
|
+
avalanche: 43114,
|
|
704
|
+
iotex: 4689,
|
|
705
|
+
sei: 1329,
|
|
706
|
+
"sei-testnet": 1328,
|
|
707
|
+
polygon: 137,
|
|
708
|
+
"polygon-amoy": 80002,
|
|
709
|
+
peaq: 3338,
|
|
710
|
+
story: 1514,
|
|
711
|
+
educhain: 41923,
|
|
712
|
+
"skale-base-sepolia": 324705682,
|
|
713
|
+
megaeth: 4326,
|
|
714
|
+
monad: 143
|
|
486
715
|
};
|
|
716
|
+
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
487
717
|
|
|
488
718
|
// src/signer.ts
|
|
489
|
-
function toClientEvmSigner(signer) {
|
|
490
|
-
|
|
719
|
+
function toClientEvmSigner(signer, publicClient) {
|
|
720
|
+
const readContract = signer.readContract ?? publicClient?.readContract.bind(publicClient);
|
|
721
|
+
if (!readContract) {
|
|
722
|
+
throw new Error(
|
|
723
|
+
"toClientEvmSigner requires either a signer with readContract or a publicClient. Use createWalletClient(...).extend(publicActions) or pass a publicClient."
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
const result = {
|
|
727
|
+
address: signer.address,
|
|
728
|
+
signTypedData: (msg) => signer.signTypedData(msg),
|
|
729
|
+
readContract
|
|
730
|
+
};
|
|
731
|
+
const signTransaction = signer.signTransaction;
|
|
732
|
+
if (signTransaction) {
|
|
733
|
+
result.signTransaction = (args) => signTransaction(args);
|
|
734
|
+
}
|
|
735
|
+
const getTransactionCount = signer.getTransactionCount ?? publicClient?.getTransactionCount?.bind(publicClient);
|
|
736
|
+
if (getTransactionCount) {
|
|
737
|
+
result.getTransactionCount = (args) => getTransactionCount(args);
|
|
738
|
+
}
|
|
739
|
+
const estimateFeesPerGas = signer.estimateFeesPerGas ?? publicClient?.estimateFeesPerGas?.bind(publicClient);
|
|
740
|
+
if (estimateFeesPerGas) {
|
|
741
|
+
result.estimateFeesPerGas = () => estimateFeesPerGas();
|
|
742
|
+
}
|
|
743
|
+
return result;
|
|
491
744
|
}
|
|
492
745
|
function toFacilitatorEvmSigner(client) {
|
|
493
746
|
return {
|