@payai/x402-evm 2.2.4 → 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 +412 -168
- 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 +477 -163
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/server/index.js +25 -3
- package/dist/cjs/exact/server/index.js.map +1 -1
- package/dist/cjs/exact/v1/client/index.d.ts +1 -1
- package/dist/cjs/exact/v1/client/index.js +18 -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 +11 -10
- 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 -109
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/permit2-DHAq6FTe.d.ts +517 -0
- package/dist/cjs/signer-DC81R8wQ.d.ts +161 -0
- package/dist/cjs/v1/index.d.ts +12 -2
- package/dist/cjs/v1/index.js +15 -11
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/chunk-LBIJBD7Q.mjs +425 -0
- package/dist/esm/chunk-LBIJBD7Q.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/{chunk-MVERYV34.mjs → chunk-XL6IFXCP.mjs} +96 -39
- package/dist/esm/chunk-XL6IFXCP.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 +407 -103
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/server/index.mjs +25 -3
- package/dist/esm/exact/server/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-BuAhWvNC.d.mts +517 -0
- package/dist/esm/signer-DC81R8wQ.d.mts +161 -0
- package/dist/esm/v1/index.d.mts +12 -2
- package/dist/esm/v1/index.mjs +6 -4
- package/package.json +1 -1
- package/dist/cjs/permit2-BYv82va2.d.ts +0 -103
- package/dist/cjs/signer-5OVDxViv.d.ts +0 -79
- package/dist/esm/chunk-MVERYV34.mjs.map +0 -1
- package/dist/esm/chunk-PFULIQAE.mjs.map +0 -1
- package/dist/esm/chunk-W556LH23.mjs +0 -229
- package/dist/esm/chunk-W556LH23.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,46 +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
|
-
};
|
|
280
|
-
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
285
|
+
// src/exact/client/scheme.ts
|
|
286
|
+
var import_viem6 = require("viem");
|
|
281
287
|
|
|
282
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
|
+
}
|
|
283
301
|
function getCrypto() {
|
|
284
302
|
const cryptoObj = globalThis.crypto;
|
|
285
303
|
if (!cryptoObj) {
|
|
@@ -288,20 +306,21 @@ function getCrypto() {
|
|
|
288
306
|
return cryptoObj;
|
|
289
307
|
}
|
|
290
308
|
function createNonce() {
|
|
291
|
-
return (0,
|
|
309
|
+
return (0, import_viem.toHex)(getCrypto().getRandomValues(new Uint8Array(32)));
|
|
292
310
|
}
|
|
293
311
|
function createPermit2Nonce() {
|
|
294
312
|
const randomBytes = getCrypto().getRandomValues(new Uint8Array(32));
|
|
295
|
-
return BigInt((0,
|
|
313
|
+
return BigInt((0, import_viem.toHex)(randomBytes)).toString();
|
|
296
314
|
}
|
|
297
315
|
|
|
298
316
|
// src/exact/client/eip3009.ts
|
|
317
|
+
var import_viem2 = require("viem");
|
|
299
318
|
async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
|
|
300
319
|
const nonce = createNonce();
|
|
301
320
|
const now = Math.floor(Date.now() / 1e3);
|
|
302
321
|
const authorization = {
|
|
303
322
|
from: signer.address,
|
|
304
|
-
to: (0,
|
|
323
|
+
to: (0, import_viem2.getAddress)(paymentRequirements.payTo),
|
|
305
324
|
value: paymentRequirements.amount,
|
|
306
325
|
validAfter: (now - 600).toString(),
|
|
307
326
|
validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),
|
|
@@ -318,7 +337,7 @@ async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
|
|
|
318
337
|
};
|
|
319
338
|
}
|
|
320
339
|
async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
321
|
-
const chainId =
|
|
340
|
+
const chainId = getEvmChainId(requirements.network);
|
|
322
341
|
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
323
342
|
throw new Error(
|
|
324
343
|
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
@@ -329,11 +348,11 @@ async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
|
329
348
|
name,
|
|
330
349
|
version,
|
|
331
350
|
chainId,
|
|
332
|
-
verifyingContract: (0,
|
|
351
|
+
verifyingContract: (0, import_viem2.getAddress)(requirements.asset)
|
|
333
352
|
};
|
|
334
353
|
const message = {
|
|
335
|
-
from: (0,
|
|
336
|
-
to: (0,
|
|
354
|
+
from: (0, import_viem2.getAddress)(authorization.from),
|
|
355
|
+
to: (0, import_viem2.getAddress)(authorization.to),
|
|
337
356
|
value: BigInt(authorization.value),
|
|
338
357
|
validAfter: BigInt(authorization.validAfter),
|
|
339
358
|
validBefore: BigInt(authorization.validBefore),
|
|
@@ -348,7 +367,7 @@ async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
|
348
367
|
}
|
|
349
368
|
|
|
350
369
|
// src/exact/client/permit2.ts
|
|
351
|
-
var
|
|
370
|
+
var import_viem3 = require("viem");
|
|
352
371
|
var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
353
372
|
async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
354
373
|
const now = Math.floor(Date.now() / 1e3);
|
|
@@ -358,16 +377,15 @@ async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
|
358
377
|
const permit2Authorization = {
|
|
359
378
|
from: signer.address,
|
|
360
379
|
permitted: {
|
|
361
|
-
token: (0,
|
|
380
|
+
token: (0, import_viem3.getAddress)(paymentRequirements.asset),
|
|
362
381
|
amount: paymentRequirements.amount
|
|
363
382
|
},
|
|
364
383
|
spender: x402ExactPermit2ProxyAddress,
|
|
365
384
|
nonce,
|
|
366
385
|
deadline,
|
|
367
386
|
witness: {
|
|
368
|
-
to: (0,
|
|
369
|
-
validAfter
|
|
370
|
-
extra: "0x"
|
|
387
|
+
to: (0, import_viem3.getAddress)(paymentRequirements.payTo),
|
|
388
|
+
validAfter
|
|
371
389
|
}
|
|
372
390
|
};
|
|
373
391
|
const signature = await signPermit2Authorization(
|
|
@@ -385,7 +403,7 @@ async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
|
385
403
|
};
|
|
386
404
|
}
|
|
387
405
|
async function signPermit2Authorization(signer, permit2Authorization, requirements) {
|
|
388
|
-
const chainId =
|
|
406
|
+
const chainId = getEvmChainId(requirements.network);
|
|
389
407
|
const domain = {
|
|
390
408
|
name: "Permit2",
|
|
391
409
|
chainId,
|
|
@@ -393,16 +411,15 @@ async function signPermit2Authorization(signer, permit2Authorization, requiremen
|
|
|
393
411
|
};
|
|
394
412
|
const message = {
|
|
395
413
|
permitted: {
|
|
396
|
-
token: (0,
|
|
414
|
+
token: (0, import_viem3.getAddress)(permit2Authorization.permitted.token),
|
|
397
415
|
amount: BigInt(permit2Authorization.permitted.amount)
|
|
398
416
|
},
|
|
399
|
-
spender: (0,
|
|
417
|
+
spender: (0, import_viem3.getAddress)(permit2Authorization.spender),
|
|
400
418
|
nonce: BigInt(permit2Authorization.nonce),
|
|
401
419
|
deadline: BigInt(permit2Authorization.deadline),
|
|
402
420
|
witness: {
|
|
403
|
-
to: (0,
|
|
404
|
-
validAfter: BigInt(permit2Authorization.witness.validAfter)
|
|
405
|
-
extra: permit2Authorization.witness.extra
|
|
421
|
+
to: (0, import_viem3.getAddress)(permit2Authorization.witness.to),
|
|
422
|
+
validAfter: BigInt(permit2Authorization.witness.validAfter)
|
|
406
423
|
}
|
|
407
424
|
};
|
|
408
425
|
return await signer.signTypedData({
|
|
@@ -412,47 +429,107 @@ async function signPermit2Authorization(signer, permit2Authorization, requiremen
|
|
|
412
429
|
message
|
|
413
430
|
});
|
|
414
431
|
}
|
|
415
|
-
var erc20ApproveAbi = [
|
|
416
|
-
{
|
|
417
|
-
type: "function",
|
|
418
|
-
name: "approve",
|
|
419
|
-
inputs: [
|
|
420
|
-
{ name: "spender", type: "address" },
|
|
421
|
-
{ name: "amount", type: "uint256" }
|
|
422
|
-
],
|
|
423
|
-
outputs: [{ type: "bool" }],
|
|
424
|
-
stateMutability: "nonpayable"
|
|
425
|
-
}
|
|
426
|
-
];
|
|
427
|
-
var erc20AllowanceAbi = [
|
|
428
|
-
{
|
|
429
|
-
type: "function",
|
|
430
|
-
name: "allowance",
|
|
431
|
-
inputs: [
|
|
432
|
-
{ name: "owner", type: "address" },
|
|
433
|
-
{ name: "spender", type: "address" }
|
|
434
|
-
],
|
|
435
|
-
outputs: [{ type: "uint256" }],
|
|
436
|
-
stateMutability: "view"
|
|
437
|
-
}
|
|
438
|
-
];
|
|
439
432
|
function createPermit2ApprovalTx(tokenAddress) {
|
|
440
|
-
const data = (0,
|
|
433
|
+
const data = (0, import_viem3.encodeFunctionData)({
|
|
441
434
|
abi: erc20ApproveAbi,
|
|
442
435
|
functionName: "approve",
|
|
443
436
|
args: [PERMIT2_ADDRESS, MAX_UINT256]
|
|
444
437
|
});
|
|
445
438
|
return {
|
|
446
|
-
to: (0,
|
|
439
|
+
to: (0, import_viem3.getAddress)(tokenAddress),
|
|
447
440
|
data
|
|
448
441
|
};
|
|
449
442
|
}
|
|
450
443
|
function getPermit2AllowanceReadParams(params) {
|
|
451
444
|
return {
|
|
452
|
-
address: (0,
|
|
445
|
+
address: (0, import_viem3.getAddress)(params.tokenAddress),
|
|
453
446
|
abi: erc20AllowanceAbi,
|
|
454
447
|
functionName: "allowance",
|
|
455
|
-
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
|
|
456
533
|
};
|
|
457
534
|
}
|
|
458
535
|
|
|
@@ -461,7 +538,9 @@ var ExactEvmScheme = class {
|
|
|
461
538
|
/**
|
|
462
539
|
* Creates a new ExactEvmClient instance.
|
|
463
540
|
*
|
|
464
|
-
* @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)`.
|
|
465
544
|
*/
|
|
466
545
|
constructor(signer) {
|
|
467
546
|
this.signer = signer;
|
|
@@ -471,22 +550,197 @@ var ExactEvmScheme = class {
|
|
|
471
550
|
* Creates a payment payload for the Exact scheme.
|
|
472
551
|
* Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.
|
|
473
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
|
+
*
|
|
474
557
|
* @param x402Version - The x402 protocol version
|
|
475
558
|
* @param paymentRequirements - The payment requirements
|
|
476
|
-
* @
|
|
559
|
+
* @param context - Optional context with server-declared extensions
|
|
560
|
+
* @returns Promise resolving to a payment payload result (with optional extensions)
|
|
477
561
|
*/
|
|
478
|
-
async createPaymentPayload(x402Version, paymentRequirements) {
|
|
562
|
+
async createPaymentPayload(x402Version, paymentRequirements, context) {
|
|
479
563
|
const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009";
|
|
480
564
|
if (assetTransferMethod === "permit2") {
|
|
481
|
-
|
|
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;
|
|
482
585
|
}
|
|
483
586
|
return createEIP3009Payload(this.signer, x402Version, paymentRequirements);
|
|
484
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
|
|
485
715
|
};
|
|
716
|
+
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
486
717
|
|
|
487
718
|
// src/signer.ts
|
|
488
|
-
function toClientEvmSigner(signer) {
|
|
489
|
-
|
|
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;
|
|
490
744
|
}
|
|
491
745
|
function toFacilitatorEvmSigner(client) {
|
|
492
746
|
return {
|