@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.
Files changed (55) hide show
  1. package/dist/cjs/exact/client/index.d.ts +2 -2
  2. package/dist/cjs/exact/client/index.js +412 -168
  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 +477 -163
  6. package/dist/cjs/exact/facilitator/index.js.map +1 -1
  7. package/dist/cjs/exact/server/index.js +25 -3
  8. package/dist/cjs/exact/server/index.js.map +1 -1
  9. package/dist/cjs/exact/v1/client/index.d.ts +1 -1
  10. package/dist/cjs/exact/v1/client/index.js +18 -18
  11. package/dist/cjs/exact/v1/client/index.js.map +1 -1
  12. package/dist/cjs/exact/v1/facilitator/index.d.ts +1 -1
  13. package/dist/cjs/exact/v1/facilitator/index.js +11 -10
  14. package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
  15. package/dist/cjs/index.d.ts +3 -390
  16. package/dist/cjs/index.js +363 -109
  17. package/dist/cjs/index.js.map +1 -1
  18. package/dist/cjs/permit2-DHAq6FTe.d.ts +517 -0
  19. package/dist/cjs/signer-DC81R8wQ.d.ts +161 -0
  20. package/dist/cjs/v1/index.d.ts +12 -2
  21. package/dist/cjs/v1/index.js +15 -11
  22. package/dist/cjs/v1/index.js.map +1 -1
  23. package/dist/esm/chunk-LBIJBD7Q.mjs +425 -0
  24. package/dist/esm/chunk-LBIJBD7Q.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/{chunk-MVERYV34.mjs → chunk-XL6IFXCP.mjs} +96 -39
  28. package/dist/esm/chunk-XL6IFXCP.mjs.map +1 -0
  29. package/dist/esm/exact/client/index.d.mts +2 -2
  30. package/dist/esm/exact/client/index.mjs +4 -3
  31. package/dist/esm/exact/facilitator/index.d.mts +18 -18
  32. package/dist/esm/exact/facilitator/index.mjs +407 -103
  33. package/dist/esm/exact/facilitator/index.mjs.map +1 -1
  34. package/dist/esm/exact/server/index.mjs +25 -3
  35. package/dist/esm/exact/server/index.mjs.map +1 -1
  36. package/dist/esm/exact/v1/client/index.d.mts +1 -1
  37. package/dist/esm/exact/v1/client/index.mjs +2 -2
  38. package/dist/esm/exact/v1/facilitator/index.d.mts +1 -1
  39. package/dist/esm/exact/v1/facilitator/index.mjs +2 -2
  40. package/dist/esm/index.d.mts +3 -390
  41. package/dist/esm/index.mjs +29 -6
  42. package/dist/esm/index.mjs.map +1 -1
  43. package/dist/esm/permit2-BuAhWvNC.d.mts +517 -0
  44. package/dist/esm/signer-DC81R8wQ.d.mts +161 -0
  45. package/dist/esm/v1/index.d.mts +12 -2
  46. package/dist/esm/v1/index.mjs +6 -4
  47. package/package.json +1 -1
  48. package/dist/cjs/permit2-BYv82va2.d.ts +0 -103
  49. package/dist/cjs/signer-5OVDxViv.d.ts +0 -79
  50. package/dist/esm/chunk-MVERYV34.mjs.map +0 -1
  51. package/dist/esm/chunk-PFULIQAE.mjs.map +0 -1
  52. package/dist/esm/chunk-W556LH23.mjs +0 -229
  53. package/dist/esm/chunk-W556LH23.mjs.map +0 -1
  54. package/dist/esm/permit2-BsAoJiWD.d.mts +0 -103
  55. 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,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: "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
- };
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, import_viem3.toHex)(getCrypto().getRandomValues(new Uint8Array(32)));
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, import_viem3.toHex)(randomBytes)).toString();
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, import_viem4.getAddress)(paymentRequirements.payTo),
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 = parseInt(requirements.network.split(":")[1]);
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, import_viem4.getAddress)(requirements.asset)
351
+ verifyingContract: (0, import_viem2.getAddress)(requirements.asset)
333
352
  };
334
353
  const message = {
335
- from: (0, import_viem4.getAddress)(authorization.from),
336
- to: (0, import_viem4.getAddress)(authorization.to),
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 import_viem5 = require("viem");
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, import_viem5.getAddress)(paymentRequirements.asset),
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, import_viem5.getAddress)(paymentRequirements.payTo),
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 = parseInt(requirements.network.split(":")[1]);
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, import_viem5.getAddress)(permit2Authorization.permitted.token),
414
+ token: (0, import_viem3.getAddress)(permit2Authorization.permitted.token),
397
415
  amount: BigInt(permit2Authorization.permitted.amount)
398
416
  },
399
- spender: (0, import_viem5.getAddress)(permit2Authorization.spender),
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, import_viem5.getAddress)(permit2Authorization.witness.to),
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, import_viem5.encodeFunctionData)({
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, import_viem5.getAddress)(tokenAddress),
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, import_viem5.getAddress)(params.tokenAddress),
445
+ address: (0, import_viem3.getAddress)(params.tokenAddress),
453
446
  abi: erc20AllowanceAbi,
454
447
  functionName: "allowance",
455
- 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
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
- * @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)
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
- 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;
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
- 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;
490
744
  }
491
745
  function toFacilitatorEvmSigner(client) {
492
746
  return {