@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.
Files changed (51) hide show
  1. package/dist/cjs/exact/client/index.d.ts +2 -2
  2. package/dist/cjs/exact/client/index.js +412 -169
  3. package/dist/cjs/exact/client/index.js.map +1 -1
  4. package/dist/cjs/exact/facilitator/index.d.ts +18 -18
  5. package/dist/cjs/exact/facilitator/index.js +467 -157
  6. package/dist/cjs/exact/facilitator/index.js.map +1 -1
  7. package/dist/cjs/exact/v1/client/index.d.ts +1 -1
  8. package/dist/cjs/exact/v1/client/index.js +17 -18
  9. package/dist/cjs/exact/v1/client/index.js.map +1 -1
  10. package/dist/cjs/exact/v1/facilitator/index.d.ts +1 -1
  11. package/dist/cjs/exact/v1/facilitator/index.js +7 -8
  12. package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
  13. package/dist/cjs/index.d.ts +3 -390
  14. package/dist/cjs/index.js +363 -110
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/permit2-CQbXqCMC.d.ts +517 -0
  17. package/dist/cjs/signer-DC81R8wQ.d.ts +161 -0
  18. package/dist/cjs/v1/index.d.ts +11 -2
  19. package/dist/cjs/v1/index.js +14 -11
  20. package/dist/cjs/v1/index.js.map +1 -1
  21. package/dist/esm/{chunk-RPL6OFJL.mjs → chunk-7KHQD5KT.mjs} +92 -37
  22. package/dist/esm/chunk-7KHQD5KT.mjs.map +1 -0
  23. package/dist/esm/chunk-GY6X5A3G.mjs +425 -0
  24. package/dist/esm/chunk-GY6X5A3G.mjs.map +1 -0
  25. package/dist/esm/{chunk-PFULIQAE.mjs → chunk-TKN5V2BV.mjs} +1 -1
  26. package/dist/esm/chunk-TKN5V2BV.mjs.map +1 -0
  27. package/dist/esm/exact/client/index.d.mts +2 -2
  28. package/dist/esm/exact/client/index.mjs +4 -3
  29. package/dist/esm/exact/facilitator/index.d.mts +18 -18
  30. package/dist/esm/exact/facilitator/index.mjs +401 -99
  31. package/dist/esm/exact/facilitator/index.mjs.map +1 -1
  32. package/dist/esm/exact/v1/client/index.d.mts +1 -1
  33. package/dist/esm/exact/v1/client/index.mjs +2 -2
  34. package/dist/esm/exact/v1/facilitator/index.d.mts +1 -1
  35. package/dist/esm/exact/v1/facilitator/index.mjs +2 -2
  36. package/dist/esm/index.d.mts +3 -390
  37. package/dist/esm/index.mjs +29 -6
  38. package/dist/esm/index.mjs.map +1 -1
  39. package/dist/esm/permit2-CGOcN7Et.d.mts +517 -0
  40. package/dist/esm/signer-DC81R8wQ.d.mts +161 -0
  41. package/dist/esm/v1/index.d.mts +11 -2
  42. package/dist/esm/v1/index.mjs +6 -4
  43. package/package.json +3 -2
  44. package/dist/cjs/permit2-BYv82va2.d.ts +0 -103
  45. package/dist/cjs/signer-5OVDxViv.d.ts +0 -79
  46. package/dist/esm/chunk-E2YMUI3X.mjs +0 -229
  47. package/dist/esm/chunk-E2YMUI3X.mjs.map +0 -1
  48. package/dist/esm/chunk-PFULIQAE.mjs.map +0 -1
  49. package/dist/esm/chunk-RPL6OFJL.mjs.map +0 -1
  50. package/dist/esm/permit2-BsAoJiWD.d.mts +0 -103
  51. 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/eip3009.ts
42
- var import_viem4 = require("viem");
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 = "0x4020615294c913F045dc10f0a5cdEbd86c280001";
123
- var x402UptoPermit2ProxyAddress = "0x4020633461b2895a48930Ff97eE8fCdE8E520002";
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 x402BasePermit2Proxy.Witness",
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 x402BasePermit2Proxy.EIP2612Permit",
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 x402BasePermit2Proxy.Witness",
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: "AlreadyInitialized", inputs: [] },
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/utils.ts
252
- var import_viem3 = require("viem");
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, import_viem3.toHex)(getCrypto().getRandomValues(new Uint8Array(32)));
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, import_viem3.toHex)(randomBytes)).toString();
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, import_viem4.getAddress)(paymentRequirements.payTo),
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 = parseInt(requirements.network.split(":")[1]);
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, import_viem4.getAddress)(requirements.asset)
351
+ verifyingContract: (0, import_viem2.getAddress)(requirements.asset)
334
352
  };
335
353
  const message = {
336
- from: (0, import_viem4.getAddress)(authorization.from),
337
- to: (0, import_viem4.getAddress)(authorization.to),
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 import_viem5 = require("viem");
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, import_viem5.getAddress)(paymentRequirements.asset),
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, import_viem5.getAddress)(paymentRequirements.payTo),
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 = parseInt(requirements.network.split(":")[1]);
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, import_viem5.getAddress)(permit2Authorization.permitted.token),
414
+ token: (0, import_viem3.getAddress)(permit2Authorization.permitted.token),
398
415
  amount: BigInt(permit2Authorization.permitted.amount)
399
416
  },
400
- spender: (0, import_viem5.getAddress)(permit2Authorization.spender),
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, import_viem5.getAddress)(permit2Authorization.witness.to),
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, import_viem5.encodeFunctionData)({
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, import_viem5.getAddress)(tokenAddress),
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, import_viem5.getAddress)(params.tokenAddress),
445
+ address: (0, import_viem3.getAddress)(params.tokenAddress),
454
446
  abi: erc20AllowanceAbi,
455
447
  functionName: "allowance",
456
- args: [(0, import_viem5.getAddress)(params.ownerAddress), PERMIT2_ADDRESS]
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
- * @returns Promise resolving to a payment payload result
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
- return createPermit2Payload(this.signer, x402Version, paymentRequirements);
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
- return signer;
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 {