@x402/evm 2.5.0 → 2.7.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 (50) hide show
  1. package/README.md +25 -0
  2. package/dist/cjs/exact/client/index.d.ts +13 -6
  3. package/dist/cjs/exact/client/index.js +127 -28
  4. package/dist/cjs/exact/client/index.js.map +1 -1
  5. package/dist/cjs/exact/facilitator/index.d.ts +13 -1
  6. package/dist/cjs/exact/facilitator/index.js +990 -609
  7. package/dist/cjs/exact/facilitator/index.js.map +1 -1
  8. package/dist/cjs/exact/server/index.js +19 -4
  9. package/dist/cjs/exact/server/index.js.map +1 -1
  10. package/dist/cjs/exact/v1/client/index.d.ts +1 -1
  11. package/dist/cjs/exact/v1/client/index.js +11 -5
  12. package/dist/cjs/exact/v1/client/index.js.map +1 -1
  13. package/dist/cjs/exact/v1/facilitator/index.d.ts +16 -1
  14. package/dist/cjs/exact/v1/facilitator/index.js +415 -178
  15. package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
  16. package/dist/cjs/index.d.ts +2 -2
  17. package/dist/cjs/index.js +143 -30
  18. package/dist/cjs/index.js.map +1 -1
  19. package/dist/cjs/{permit2-CQbXqCMC.d.ts → permit2-U9Zolx3O.d.ts} +38 -5
  20. package/dist/{esm/signer-DC81R8wQ.d.mts → cjs/signer-D912R4mq.d.ts} +9 -3
  21. package/dist/cjs/v1/index.d.ts +1 -1
  22. package/dist/cjs/v1/index.js +6 -0
  23. package/dist/cjs/v1/index.js.map +1 -1
  24. package/dist/esm/chunk-GD4MKCN7.mjs +57 -0
  25. package/dist/esm/chunk-GD4MKCN7.mjs.map +1 -0
  26. package/dist/esm/{chunk-7KHQD5KT.mjs → chunk-IZEI7JTG.mjs} +517 -179
  27. package/dist/esm/chunk-IZEI7JTG.mjs.map +1 -0
  28. package/dist/esm/{chunk-GY6X5A3G.mjs → chunk-WJWNS4G4.mjs} +113 -20
  29. package/dist/esm/chunk-WJWNS4G4.mjs.map +1 -0
  30. package/dist/esm/exact/client/index.d.mts +13 -6
  31. package/dist/esm/exact/client/index.mjs +3 -2
  32. package/dist/esm/exact/facilitator/index.d.mts +13 -1
  33. package/dist/esm/exact/facilitator/index.mjs +500 -393
  34. package/dist/esm/exact/facilitator/index.mjs.map +1 -1
  35. package/dist/esm/exact/server/index.mjs +19 -4
  36. package/dist/esm/exact/server/index.mjs.map +1 -1
  37. package/dist/esm/exact/v1/client/index.d.mts +1 -1
  38. package/dist/esm/exact/v1/client/index.mjs +1 -1
  39. package/dist/esm/exact/v1/facilitator/index.d.mts +16 -1
  40. package/dist/esm/exact/v1/facilitator/index.mjs +1 -1
  41. package/dist/esm/index.d.mts +2 -2
  42. package/dist/esm/index.mjs +7 -9
  43. package/dist/esm/index.mjs.map +1 -1
  44. package/dist/esm/{permit2-CGOcN7Et.d.mts → permit2-Bbh3a8_h.d.mts} +38 -5
  45. package/dist/{cjs/signer-DC81R8wQ.d.ts → esm/signer-D912R4mq.d.mts} +9 -3
  46. package/dist/esm/v1/index.d.mts +1 -1
  47. package/dist/esm/v1/index.mjs +1 -1
  48. package/package.json +2 -3
  49. package/dist/esm/chunk-7KHQD5KT.mjs.map +0 -1
  50. package/dist/esm/chunk-GY6X5A3G.mjs.map +0 -1
package/README.md CHANGED
@@ -125,6 +125,30 @@ const client = new x402Client()
125
125
  .registerSchemeV1("base", new ExactEvmClientV1(signer));
126
126
  ```
127
127
 
128
+ ### Extension RPC Configuration (Optional)
129
+
130
+ `ExactEvmClient` only requires signer support for `address` + `signTypedData`.
131
+ Permit2 extension enrichment (EIP-2612 / ERC-20 approval gas sponsoring) can
132
+ optionally use explicit RPC config when signer read/fee helpers are unavailable.
133
+
134
+ No chain-default RPC fallback is applied by the SDK.
135
+
136
+ ```typescript
137
+ // Per-network explicit registration
138
+ const client = new x402Client()
139
+ .register("eip155:137", new ExactEvmClient(signer, { rpcUrl: polygonRpcUrl }))
140
+ .register("eip155:8453", new ExactEvmClient(signer, { rpcUrl: baseRpcUrl }));
141
+
142
+ // Wildcard registration with chain-id keyed config map
143
+ const wildcardClient = new x402Client().register(
144
+ "eip155:*",
145
+ new ExactEvmClient(signer, {
146
+ 137: { rpcUrl: polygonRpcUrl },
147
+ 8453: { rpcUrl: baseRpcUrl },
148
+ }),
149
+ );
150
+ ```
151
+
128
152
  ### 3. Using Config (Flexible)
129
153
 
130
154
  ```typescript
@@ -181,3 +205,4 @@ npm run format
181
205
  - `@x402/core` - Core protocol types and client
182
206
  - `@x402/fetch` - HTTP wrapper with automatic payment handling
183
207
  - `@x402/svm` - Solana/SVM implementation
208
+ - `@x402/stellar` - Stellar implementation
@@ -1,7 +1,8 @@
1
- export { E as ExactEvmScheme, a as Permit2AllowanceParams, c as createPermit2ApprovalTx, d as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-CQbXqCMC.js';
2
- import { SelectPaymentRequirements, PaymentPolicy, x402Client } from '@x402/core/client';
1
+ import { i as ExactEvmSchemeOptions } from '../../permit2-U9Zolx3O.js';
2
+ export { E as ExactEvmScheme, j as ExactEvmSchemeConfig, k as ExactEvmSchemeConfigByChainId, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-U9Zolx3O.js';
3
+ import { x402Client, SelectPaymentRequirements, PaymentPolicy } from '@x402/core/client';
3
4
  import { Network } from '@x402/core/types';
4
- import { C as ClientEvmSigner } from '../../signer-DC81R8wQ.js';
5
+ import { C as ClientEvmSigner } from '../../signer-D912R4mq.js';
5
6
 
6
7
  /**
7
8
  * Configuration options for registering EVM schemes to an x402Client
@@ -21,8 +22,14 @@ interface EvmClientConfig {
21
22
  */
22
23
  policies?: PaymentPolicy[];
23
24
  /**
24
- * Optional specific networks to register
25
- * If not provided, registers wildcard support (eip155:*)
25
+ * Optional Exact EVM client scheme options.
26
+ * Supports either a single config ({ rpcUrl }) or per-chain configs
27
+ * keyed by EVM chain ID ({ 8453: { rpcUrl: "..." } }).
28
+ */
29
+ schemeOptions?: ExactEvmSchemeOptions;
30
+ /**
31
+ * Optional specific networks to register.
32
+ * If not provided, registers wildcard support (eip155:*).
26
33
  */
27
34
  networks?: Network[];
28
35
  }
@@ -50,4 +57,4 @@ interface EvmClientConfig {
50
57
  */
51
58
  declare function registerExactEvmScheme(client: x402Client, config: EvmClientConfig): x402Client;
52
59
 
53
- export { type EvmClientConfig, registerExactEvmScheme };
60
+ export { type EvmClientConfig, ExactEvmSchemeOptions, registerExactEvmScheme };
@@ -28,9 +28,6 @@ __export(client_exports, {
28
28
  });
29
29
  module.exports = __toCommonJS(client_exports);
30
30
 
31
- // src/exact/client/scheme.ts
32
- var import_extensions2 = require("@x402/extensions");
33
-
34
31
  // src/constants.ts
35
32
  var authorizationTypes = {
36
33
  TransferWithAuthorization: [
@@ -108,7 +105,7 @@ var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
108
105
  var x402ExactPermit2ProxyAddress = "0x402085c248EeA27D92E8b30b2C58ed07f9E20001";
109
106
 
110
107
  // src/exact/client/scheme.ts
111
- var import_viem6 = require("viem");
108
+ var import_viem7 = require("viem");
112
109
 
113
110
  // src/utils.ts
114
111
  var import_viem = require("viem");
@@ -138,6 +135,11 @@ function createPermit2Nonce() {
138
135
  return BigInt((0, import_viem.toHex)(randomBytes)).toString();
139
136
  }
140
137
 
138
+ // src/exact/extensions.ts
139
+ var EIP2612_GAS_SPONSORING_KEY = "eip2612GasSponsoring";
140
+ var ERC20_APPROVAL_GAS_SPONSORING_KEY = "erc20ApprovalGasSponsoring";
141
+ var ERC20_APPROVAL_GAS_SPONSORING_VERSION = "1";
142
+
141
143
  // src/exact/client/eip3009.ts
142
144
  var import_viem2 = require("viem");
143
145
  async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
@@ -319,7 +321,6 @@ async function signEip2612Permit(signer, tokenAddress, tokenName, tokenVersion,
319
321
 
320
322
  // src/exact/client/erc20approval.ts
321
323
  var import_viem5 = require("viem");
322
- var import_extensions = require("@x402/extensions");
323
324
  async function signErc20ApprovalTransaction(signer, tokenAddress, chainId) {
324
325
  const from = signer.address;
325
326
  const spender = (0, import_viem5.getAddress)(PERMIT2_ADDRESS);
@@ -332,7 +333,10 @@ async function signErc20ApprovalTransaction(signer, tokenAddress, chainId) {
332
333
  let maxFeePerGas;
333
334
  let maxPriorityFeePerGas;
334
335
  try {
335
- const fees = await signer.estimateFeesPerGas();
336
+ const fees = await signer.estimateFeesPerGas?.();
337
+ if (!fees) {
338
+ throw new Error("no fee estimates available");
339
+ }
336
340
  maxFeePerGas = fees.maxFeePerGas;
337
341
  maxPriorityFeePerGas = fees.maxPriorityFeePerGas;
338
342
  } catch {
@@ -354,8 +358,65 @@ async function signErc20ApprovalTransaction(signer, tokenAddress, chainId) {
354
358
  spender,
355
359
  amount: import_viem5.maxUint256.toString(),
356
360
  signedTransaction,
357
- version: import_extensions.ERC20_APPROVAL_GAS_SPONSORING_VERSION
361
+ version: ERC20_APPROVAL_GAS_SPONSORING_VERSION
362
+ };
363
+ }
364
+
365
+ // src/exact/client/rpc.ts
366
+ var import_viem6 = require("viem");
367
+ var rpcClientCache = /* @__PURE__ */ new Map();
368
+ function isConfigByChainId(options) {
369
+ const keys = Object.keys(options);
370
+ return keys.length > 0 && keys.every((key) => /^\d+$/.test(key));
371
+ }
372
+ function getRpcClient(rpcUrl) {
373
+ const existing = rpcClientCache.get(rpcUrl);
374
+ if (existing) {
375
+ return existing;
376
+ }
377
+ const client = (0, import_viem6.createPublicClient)({
378
+ transport: (0, import_viem6.http)(rpcUrl)
379
+ });
380
+ rpcClientCache.set(rpcUrl, client);
381
+ return client;
382
+ }
383
+ function resolveRpcUrl(network, options) {
384
+ if (!options) {
385
+ return void 0;
386
+ }
387
+ if (isConfigByChainId(options)) {
388
+ const chainId = getEvmChainId(network);
389
+ const optionsByChainId = options;
390
+ return optionsByChainId[chainId]?.rpcUrl;
391
+ }
392
+ return options.rpcUrl;
393
+ }
394
+ function resolveExtensionRpcCapabilities(network, signer, options) {
395
+ const capabilities = {
396
+ signTransaction: signer.signTransaction,
397
+ readContract: signer.readContract,
398
+ getTransactionCount: signer.getTransactionCount,
399
+ estimateFeesPerGas: signer.estimateFeesPerGas
358
400
  };
401
+ const needsRpcBackfill = !capabilities.readContract || !capabilities.getTransactionCount || !capabilities.estimateFeesPerGas;
402
+ if (!needsRpcBackfill) {
403
+ return capabilities;
404
+ }
405
+ const rpcUrl = resolveRpcUrl(network, options);
406
+ if (!rpcUrl) {
407
+ return capabilities;
408
+ }
409
+ const rpcClient = getRpcClient(rpcUrl);
410
+ if (!capabilities.readContract) {
411
+ capabilities.readContract = (args) => rpcClient.readContract(args);
412
+ }
413
+ if (!capabilities.getTransactionCount) {
414
+ capabilities.getTransactionCount = async (args) => rpcClient.getTransactionCount({ address: args.address });
415
+ }
416
+ if (!capabilities.estimateFeesPerGas) {
417
+ capabilities.estimateFeesPerGas = async () => rpcClient.estimateFeesPerGas();
418
+ }
419
+ return capabilities;
359
420
  }
360
421
 
361
422
  // src/exact/client/scheme.ts
@@ -364,11 +425,14 @@ var ExactEvmScheme = class {
364
425
  * Creates a new ExactEvmClient instance.
365
426
  *
366
427
  * @param signer - The EVM signer for client operations.
367
- * Must support `readContract` for EIP-2612 gas sponsoring.
368
- * Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`.
428
+ * Base flow only requires `address` + `signTypedData`.
429
+ * Extension enrichment (EIP-2612 / ERC-20 approval sponsoring) additionally
430
+ * requires optional capabilities like `readContract` and tx signing helpers.
431
+ * @param options - Optional RPC configuration used to backfill extension capabilities.
369
432
  */
370
- constructor(signer) {
433
+ constructor(signer, options) {
371
434
  this.signer = signer;
435
+ this.options = options;
372
436
  this.scheme = "exact";
373
437
  }
374
438
  /**
@@ -426,7 +490,15 @@ var ExactEvmScheme = class {
426
490
  * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable
427
491
  */
428
492
  async trySignEip2612Permit(requirements, result, context) {
429
- if (!context?.extensions?.[import_extensions2.EIP2612_GAS_SPONSORING.key]) {
493
+ const capabilities = resolveExtensionRpcCapabilities(
494
+ requirements.network,
495
+ this.signer,
496
+ this.options
497
+ );
498
+ if (!capabilities.readContract) {
499
+ return void 0;
500
+ }
501
+ if (!context?.extensions?.[EIP2612_GAS_SPONSORING_KEY]) {
430
502
  return void 0;
431
503
  }
432
504
  const tokenName = requirements.extra?.name;
@@ -435,9 +507,9 @@ var ExactEvmScheme = class {
435
507
  return void 0;
436
508
  }
437
509
  const chainId = getEvmChainId(requirements.network);
438
- const tokenAddress = (0, import_viem6.getAddress)(requirements.asset);
510
+ const tokenAddress = (0, import_viem7.getAddress)(requirements.asset);
439
511
  try {
440
- const allowance = await this.signer.readContract({
512
+ const allowance = await capabilities.readContract({
441
513
  address: tokenAddress,
442
514
  abi: erc20AllowanceAbi,
443
515
  functionName: "allowance",
@@ -451,7 +523,11 @@ var ExactEvmScheme = class {
451
523
  const permit2Auth = result.payload?.permit2Authorization;
452
524
  const deadline = permit2Auth?.deadline ?? Math.floor(Date.now() / 1e3 + requirements.maxTimeoutSeconds).toString();
453
525
  const info = await signEip2612Permit(
454
- this.signer,
526
+ {
527
+ address: this.signer.address,
528
+ signTypedData: (msg) => this.signer.signTypedData(msg),
529
+ readContract: capabilities.readContract
530
+ },
455
531
  tokenAddress,
456
532
  tokenName,
457
533
  tokenVersion,
@@ -460,7 +536,7 @@ var ExactEvmScheme = class {
460
536
  requirements.amount
461
537
  );
462
538
  return {
463
- [import_extensions2.EIP2612_GAS_SPONSORING.key]: { info }
539
+ [EIP2612_GAS_SPONSORING_KEY]: { info }
464
540
  };
465
541
  }
466
542
  /**
@@ -483,16 +559,24 @@ var ExactEvmScheme = class {
483
559
  * @returns Extension data for ERC-20 approval gas sponsoring, or undefined if not applicable
484
560
  */
485
561
  async trySignErc20Approval(requirements, _result, context) {
486
- if (!context?.extensions?.[import_extensions2.ERC20_APPROVAL_GAS_SPONSORING.key]) {
562
+ const capabilities = resolveExtensionRpcCapabilities(
563
+ requirements.network,
564
+ this.signer,
565
+ this.options
566
+ );
567
+ if (!capabilities.readContract) {
568
+ return void 0;
569
+ }
570
+ if (!context?.extensions?.[ERC20_APPROVAL_GAS_SPONSORING_KEY]) {
487
571
  return void 0;
488
572
  }
489
- if (!this.signer.signTransaction || !this.signer.getTransactionCount) {
573
+ if (!capabilities.signTransaction || !capabilities.getTransactionCount) {
490
574
  return void 0;
491
575
  }
492
576
  const chainId = getEvmChainId(requirements.network);
493
- const tokenAddress = (0, import_viem6.getAddress)(requirements.asset);
577
+ const tokenAddress = (0, import_viem7.getAddress)(requirements.asset);
494
578
  try {
495
- const allowance = await this.signer.readContract({
579
+ const allowance = await capabilities.readContract({
496
580
  address: tokenAddress,
497
581
  abi: erc20AllowanceAbi,
498
582
  functionName: "allowance",
@@ -503,18 +587,33 @@ var ExactEvmScheme = class {
503
587
  }
504
588
  } catch {
505
589
  }
506
- const info = await signErc20ApprovalTransaction(this.signer, tokenAddress, chainId);
590
+ const info = await signErc20ApprovalTransaction(
591
+ {
592
+ address: this.signer.address,
593
+ signTransaction: capabilities.signTransaction,
594
+ getTransactionCount: capabilities.getTransactionCount,
595
+ estimateFeesPerGas: capabilities.estimateFeesPerGas
596
+ },
597
+ tokenAddress,
598
+ chainId
599
+ );
507
600
  return {
508
- [import_extensions2.ERC20_APPROVAL_GAS_SPONSORING.key]: { info }
601
+ [ERC20_APPROVAL_GAS_SPONSORING_KEY]: { info }
509
602
  };
510
603
  }
511
604
  };
512
605
 
513
606
  // src/exact/v1/client/scheme.ts
514
- var import_viem8 = require("viem");
607
+ var import_viem11 = require("viem");
515
608
 
516
609
  // src/exact/v1/facilitator/scheme.ts
517
- var import_viem7 = require("viem");
610
+ var import_viem10 = require("viem");
611
+
612
+ // src/exact/facilitator/eip3009-utils.ts
613
+ var import_viem9 = require("viem");
614
+
615
+ // src/multicall.ts
616
+ var import_viem8 = require("viem");
518
617
 
519
618
  // src/v1/index.ts
520
619
  var EVM_NETWORK_CHAIN_ID_MAP = {
@@ -571,7 +670,7 @@ var ExactEvmSchemeV1 = class {
571
670
  const now = Math.floor(Date.now() / 1e3);
572
671
  const authorization = {
573
672
  from: this.signer.address,
574
- to: (0, import_viem8.getAddress)(selectedV1.payTo),
673
+ to: (0, import_viem11.getAddress)(selectedV1.payTo),
575
674
  value: selectedV1.maxAmountRequired,
576
675
  validAfter: (now - 600).toString(),
577
676
  // 10 minutes before
@@ -609,11 +708,11 @@ var ExactEvmSchemeV1 = class {
609
708
  name,
610
709
  version,
611
710
  chainId,
612
- verifyingContract: (0, import_viem8.getAddress)(requirements.asset)
711
+ verifyingContract: (0, import_viem11.getAddress)(requirements.asset)
613
712
  };
614
713
  const message = {
615
- from: (0, import_viem8.getAddress)(authorization.from),
616
- to: (0, import_viem8.getAddress)(authorization.to),
714
+ from: (0, import_viem11.getAddress)(authorization.from),
715
+ to: (0, import_viem11.getAddress)(authorization.to),
617
716
  value: BigInt(authorization.value),
618
717
  validAfter: BigInt(authorization.validAfter),
619
718
  validBefore: BigInt(authorization.validBefore),
@@ -630,7 +729,7 @@ var ExactEvmSchemeV1 = class {
630
729
 
631
730
  // src/exact/client/register.ts
632
731
  function registerExactEvmScheme(client, config) {
633
- const evmScheme = new ExactEvmScheme(config.signer);
732
+ const evmScheme = new ExactEvmScheme(config.signer, config.schemeOptions);
634
733
  if (config.networks && config.networks.length > 0) {
635
734
  config.networks.forEach((network) => {
636
735
  client.register(network, evmScheme);