@springmint/x402-payment 1.0.1 → 1.0.3

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.
@@ -1,5 +1,5 @@
1
- export const id = 743;
2
- export const ids = [743];
1
+ export const id = 618;
2
+ export const ids = [618];
3
3
  export const modules = {
4
4
 
5
5
  /***/ 1491:
@@ -37689,7 +37689,7 @@ function randomBytes(bytesLength = 32) {
37689
37689
 
37690
37690
  /***/ }),
37691
37691
 
37692
- /***/ 3743:
37692
+ /***/ 8618:
37693
37693
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
37694
37694
 
37695
37695
 
@@ -37703,14 +37703,14 @@ __webpack_require__.d(__webpack_exports__, {
37703
37703
  ExactPermitTronClientMechanism: () => (/* reexport */ ExactPermitTronClientMechanism),
37704
37704
  ExactTronClientMechanism: () => (/* reexport */ ExactTronClientMechanism),
37705
37705
  o6: () => (/* reexport */ InsufficientAllowanceError),
37706
- uF: () => (/* reexport */ KIND_MAP),
37707
- N3: () => (/* reexport */ PAYMENT_PERMIT_TYPES),
37708
37706
  Px: () => (/* reexport */ config_PAYMENT_REQUIRED_HEADER),
37709
37707
  g7: () => (/* reexport */ config_PAYMENT_SIGNATURE_HEADER),
37708
+ gG: () => (/* reexport */ PERMIT402_TYPES),
37709
+ uz: () => (/* reexport */ PTYPE_MAP),
37710
37710
  fL: () => (/* reexport */ PermitValidationError),
37711
+ dz: () => (/* reexport */ setting_SCHEMES),
37711
37712
  e$: () => (/* reexport */ SignatureCreationError),
37712
37713
  SufficientBalancePolicy: () => (/* reexport */ SufficientBalancePolicy),
37713
- P5: () => (/* reexport */ TRON_RPC_URLS),
37714
37714
  KT: () => (/* reexport */ TRON_ZERO_ADDRESS),
37715
37715
  qR: () => (/* reexport */ TronAddressConverter),
37716
37716
  TronClientSigner: () => (/* reexport */ TronClientSigner),
@@ -37720,12 +37720,12 @@ __webpack_require__.d(__webpack_exports__, {
37720
37720
  hV: () => (/* reexport */ encoding_decodePaymentPayload),
37721
37721
  Py: () => (/* reexport */ encoding_encodePaymentPayload),
37722
37722
  TH: () => (/* reexport */ getChainId),
37723
- kv: () => (/* reexport */ getPaymentPermitAddress),
37724
- Ff: () => (/* reexport */ resolveRpcUrl),
37723
+ e5: () => (/* reexport */ getPermit402Address),
37724
+ AB: () => (/* reexport */ resolveRpcUrls),
37725
37725
  ld: () => (/* reexport */ toEvmHex)
37726
37726
  });
37727
37727
 
37728
- // UNUSED EXPORTS: AllowanceError, CHAIN_IDS, CheapestTokenSelectionStrategy, ConfigurationError, DefaultTokenSelectionStrategy, EIP712_DOMAIN_TYPE, ERC20_ABI, EVM_RPC_URLS, Facilitator, FacilitatorFetchError, FacilitatorSettleError, FacilitatorVerifyError, JSON_CONTENT_TYPE, NETWORKS, PAYMENT_ONLY, PAYMENT_PERMIT_ADDRESSES, PAYMENT_PERMIT_PRIMARY_TYPE, ResourceConfig, ResponseError, SCHEME_EXACT, SignatureError, TRANSFER_AUTH_EIP712_TYPES, TRANSFER_AUTH_PRIMARY_TYPE, ValidationError, X402Error, X402Middleware, X402Server, ZERO_ADDRESS_HEX, buildEip712Domain, buildEip712Message, bytesToHex, createNonce, createValidityWindow, decodeBase64, decodeBase64ToBytes, decodeJSON, encodeBase64, encodeJSON, findByAddress, getNetworkTokens, getToken, getZeroAddress, hexToBytes, isEvmNetwork, isTronNetwork, paymentIdToBytes, registerToken, toBase58, x402_protected
37728
+ // UNUSED EXPORTS: AllowanceError, CHAIN_IDS, CheapestTokenSelectionStrategy, ConfigurationError, DefaultTokenSelectionStrategy, EIP712_DOMAIN_TYPE, ERC20_ABI, EVM_RPC_URLS, FACILITATOR_ENDPOINTS, Facilitator, FacilitatorFetchError, FacilitatorSettleError, FacilitatorVerifyError, JSON_CONTENT_TYPE, NETWORKS, PAYMENT_ONLY, PERMIT402_ADDRESSES, PERMIT402_PRIMARY_TYPE, ResourceConfig, ResponseError, SignatureError, TRANSFER_AUTH_EIP712_TYPES, TRANSFER_AUTH_PRIMARY_TYPE, TRON_RPC_URLS, ValidationError, X402Error, X402Middleware, X402Server, ZERO_ADDRESS_HEX, buildEip712Domain, buildEip712Message, bytesToHex, createNonce, createValidityWindow, decodeBase64, decodeBase64ToBytes, decodeJSON, encodeBase64, encodeJSON, findByAddress, getNetworkTokens, getToken, getZeroAddress, hexToBytes, isEvmNetwork, isTronNetwork, paymentIdToBytes, registerToken, resolveRpcUrl, toBase58, x402_protected
37729
37729
 
37730
37730
  // NAMESPACE OBJECT: ./node_modules/tronweb/lib/esm/utils/bytes.js
37731
37731
  var bytes_namespaceObject = {};
@@ -38388,11 +38388,6 @@ class X402Client {
38388
38388
  *
38389
38389
  * Policies are applied in order after mechanism filtering and before token selection.
38390
38390
  */
38391
-
38392
- function policies_getDecimals(req) {
38393
- const token = findByAddress(req.network, req.asset);
38394
- return token?.decimals ?? 6;
38395
- }
38396
38391
  /**
38397
38392
  * Policy that filters out requirements with insufficient balance.
38398
38393
  *
@@ -38431,31 +38426,16 @@ class SufficientBalancePolicy {
38431
38426
  try {
38432
38427
  balance = await signer.checkBalance(req.asset, req.network);
38433
38428
  }
38434
- catch {
38435
- // Signer cannot query this network; keep the requirement.
38436
- affordable.push(req);
38437
- continue;
38429
+ catch (error) {
38430
+ throw new Error(`Failed to query balance via RPC for ${req.scheme} on ${req.network}: ${error instanceof Error ? error.message : String(error)}`);
38438
38431
  }
38439
38432
  let needed = BigInt(req.amount);
38440
38433
  if (req.extra?.fee?.feeAmount) {
38441
38434
  needed += BigInt(req.extra.fee.feeAmount);
38442
38435
  }
38443
- const decimals = policies_getDecimals(req);
38444
- const token = findByAddress(req.network, req.asset);
38445
- const symbol = token?.symbol ?? req.asset.slice(0, 8);
38446
- const divisor = 10 ** decimals;
38447
- const hBalance = (Number(balance) / divisor).toFixed(decimals);
38448
- const hNeeded = (Number(needed) / divisor).toFixed(decimals);
38449
38436
  if (balance >= needed) {
38450
- console.log(`[x402] ${symbol} on ${req.network}: balance=${hBalance} >= needed=${hNeeded} (OK)`);
38451
38437
  affordable.push(req);
38452
38438
  }
38453
- else {
38454
- console.log(`[x402] ${symbol} on ${req.network}: balance=${hBalance} < needed=${hNeeded} (skipped)`);
38455
- }
38456
- }
38457
- if (affordable.length === 0) {
38458
- console.error("[x402] All payment requirements filtered: insufficient balance");
38459
38439
  }
38460
38440
  return affordable;
38461
38441
  }
@@ -38587,8 +38567,8 @@ function paymentIdToBytes(paymentId) {
38587
38567
  * ABI and EIP-712 type definitions for x402 protocol
38588
38568
  * Shared across all mechanisms
38589
38569
  */
38590
- /** EIP-712 Primary Type for Permit402 (matches contract Permit402Details) */
38591
- const PAYMENT_PERMIT_PRIMARY_TYPE = "Permit402Details";
38570
+ /** EIP-712 Primary Type for Permit402 */
38571
+ const PERMIT402_PRIMARY_TYPE = "Permit402Details";
38592
38572
  /**
38593
38573
  * EIP-712 Domain Type
38594
38574
  * Based on contract: keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)")
@@ -38601,9 +38581,9 @@ const EIP712_DOMAIN_TYPE = [
38601
38581
  ];
38602
38582
  /**
38603
38583
  * EIP-712 type definitions for Permit402
38604
- * Matches IPermit402.sol and PermitHash.sol - struct has meta, buyer, payment, fee (no caller)
38584
+ * Based on PermitHash.sol from the contract
38605
38585
  */
38606
- const PAYMENT_PERMIT_TYPES = {
38586
+ const PERMIT402_TYPES = {
38607
38587
  PermitMeta: [
38608
38588
  { name: "ptype", type: "uint8" },
38609
38589
  { name: "paymentId", type: "bytes16" },
@@ -38627,8 +38607,8 @@ const PAYMENT_PERMIT_TYPES = {
38627
38607
  { name: "fee", type: "Fee" },
38628
38608
  ],
38629
38609
  };
38630
- /** Kind mapping for EIP-712 (string to numeric) */
38631
- const KIND_MAP = {
38610
+ /** Ptype mapping for EIP-712 (string to numeric) */
38611
+ const PTYPE_MAP = {
38632
38612
  PAYMENT_ONLY: 0,
38633
38613
  };
38634
38614
  /** ERC20 ABI for allowance/approve calls */
@@ -38683,18 +38663,18 @@ const NETWORKS = {
38683
38663
  BSC_MAINNET: "eip155:56",
38684
38664
  BSC_TESTNET: "eip155:97",
38685
38665
  };
38686
- /** PaymentPermit contract addresses */
38687
- const PAYMENT_PERMIT_ADDRESSES = {
38688
- "tron:mainnet": "TT8rEWbCoNX7vpEUauxb7rWJsTgs8vDLAn",
38689
- "tron:shasta": "TR2XninQ3jsvRRLGTifFyUHTBysffooUjt",
38690
- "tron:nile": "TFxDcGvS7zfQrS1YzcCMp673ta2NHHzsiH",
38691
- "eip155:97": "0x84084692ea4E1BeEE56668b80D13902426fc3917",
38692
- "eip155:56": "0x84084692ea4E1BeEE56668b80D13902426fc3917",
38666
+ /** Permit402 contract addresses */
38667
+ const PERMIT402_ADDRESSES = {
38668
+ "tron:mainnet": "TK5kfgbNK5B5sFWSbtDs2HyCaSUuEzfN2B",
38669
+ "tron:shasta": "TSNfGRDkyyDY4dHsWzQ6rWWG63p9iczz1k",
38670
+ "tron:nile": "TRK2rYmbyFZKcPTDREEF36rEsLfDWZXnjA",
38671
+ "eip155:97": "",
38672
+ "eip155:56": "0x105a6f4613a1d1c17ef35d4d5f053fa2e659a958",
38693
38673
  };
38694
38674
  /** Default RPC URLs for EVM networks */
38695
38675
  const EVM_RPC_URLS = {
38696
- "eip155:97": "https://data-seed-prebsc-2-s2.bnbchain.org:8545",
38697
- "eip155:56": "https://bsc-dataseed.binance.org",
38676
+ "eip155:97": ["https://data-seed-prebsc-2-s2.bnbchain.org:8545", "https://bsc-testnet-rpc.publicnode.com"],
38677
+ "eip155:56": ["https://bsc-dataseed.binance.org", "https://rpc-bsc.48.club"],
38698
38678
  // 'eip155:1': 'https://eth.llamarpc.com',
38699
38679
  };
38700
38680
  /** Default TronGrid hosts for TRON networks */
@@ -38703,12 +38683,38 @@ const TRON_RPC_URLS = {
38703
38683
  "tron:shasta": "https://api.shasta.trongrid.io",
38704
38684
  "tron:nile": "https://nile.trongrid.io",
38705
38685
  };
38686
+ /** Normalize any RPC URL input into a de-duplicated array */
38687
+ function normalizeRpcUrls(input) {
38688
+ if (!input)
38689
+ return [];
38690
+ const values = Array.isArray(input) ? input : [input];
38691
+ const unique = [];
38692
+ for (const value of values) {
38693
+ const url = value.trim();
38694
+ if (!url)
38695
+ continue;
38696
+ if (!unique.includes(url)) {
38697
+ unique.push(url);
38698
+ }
38699
+ }
38700
+ return unique;
38701
+ }
38702
+ /**
38703
+ * Resolve all available RPC URLs for a network.
38704
+ * Priority: caller overrides first, built-in defaults second.
38705
+ */
38706
+ function resolveRpcUrls(network, overrides) {
38707
+ const customUrls = normalizeRpcUrls(overrides?.[network]);
38708
+ const defaultUrl = EVM_RPC_URLS[network] ?? TRON_RPC_URLS[network];
38709
+ const defaultUrls = normalizeRpcUrls(defaultUrl);
38710
+ return [...customUrls, ...defaultUrls.filter((url) => !customUrls.includes(url))];
38711
+ }
38706
38712
  /**
38707
38713
  * Resolve a network identifier to an RPC URL.
38708
38714
  * Returns the URL from the built-in map, or undefined if not configured.
38709
38715
  */
38710
38716
  function resolveRpcUrl(network) {
38711
- return EVM_RPC_URLS[network] ?? TRON_RPC_URLS[network];
38717
+ return resolveRpcUrls(network)[0];
38712
38718
  }
38713
38719
  /** Zero address for TRON */
38714
38720
  const TRON_ZERO_ADDRESS = "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb";
@@ -38733,10 +38739,10 @@ function getChainId(network) {
38733
38739
  return chainId;
38734
38740
  }
38735
38741
  /**
38736
- * Get PaymentPermit contract address for network
38742
+ * Get Permit402 contract address for network
38737
38743
  */
38738
- function getPaymentPermitAddress(network) {
38739
- const addr = PAYMENT_PERMIT_ADDRESSES[network];
38744
+ function getPermit402Address(network) {
38745
+ const addr = PERMIT402_ADDRESSES[network];
38740
38746
  if (addr)
38741
38747
  return addr;
38742
38748
  // EVM fallback: zero address (not yet deployed)
@@ -38770,6 +38776,17 @@ const config_PAYMENT_SIGNATURE_HEADER = "PAYMENT-SIGNATURE";
38770
38776
  const config_PAYMENT_REQUIRED_HEADER = "PAYMENT-REQUIRED";
38771
38777
  const config_JSON_CONTENT_TYPE = "application/json";
38772
38778
  //# sourceMappingURL=config.js.map
38779
+ ;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/setting.js
38780
+ // facilitator configure
38781
+ const FACILITATOR_ENDPOINTS = {
38782
+ popular: "https://www.cppay.finance/api/x402/facilitator",
38783
+ };
38784
+ // sheme exact
38785
+ const setting_SCHEMES = {
38786
+ erc3009: "transfer_auth",
38787
+ permit402: "permit402",
38788
+ };
38789
+ //# sourceMappingURL=setting.js.map
38773
38790
  ;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/address.js
38774
38791
  /**
38775
38792
  * Address conversion utilities for x402 protocol
@@ -38875,7 +38892,7 @@ function toEvmHex(addr) {
38875
38892
  return base58ToEvmHex(addr);
38876
38893
  }
38877
38894
  // Invalid format, return zero address
38878
- console.warn(`[toEvmHex] Invalid address format: ${addr}, returning zero address`);
38895
+ // Invalid format, return zero address
38879
38896
  return ZERO_ADDRESS_HEX;
38880
38897
  }
38881
38898
  /**
@@ -38890,7 +38907,7 @@ function base58ToEvmHex(addr) {
38890
38907
  for (const char of addr) {
38891
38908
  const value = alphabetMap[char];
38892
38909
  if (value === undefined) {
38893
- console.warn(`[toEvmHex] Invalid Base58 character: ${char} in address: ${addr}`);
38910
+ // Invalid Base58 character
38894
38911
  return ZERO_ADDRESS_HEX;
38895
38912
  }
38896
38913
  num = num * BigInt(58) + BigInt(value);
@@ -39005,12 +39022,6 @@ class X402FetchClient {
39005
39022
  }
39006
39023
  }
39007
39024
  //# sourceMappingURL=client.js.map
39008
- ;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/setting.js
39009
- // facilitator configure
39010
- const FACILITATOR_ENDPOINTS = {
39011
- popular: "https://www.cppay.finance/api/x402/facilitator",
39012
- };
39013
- //# sourceMappingURL=setting.js.map
39014
39025
  ;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/server/facilitator.js
39015
39026
  var _a;
39016
39027
 
@@ -39028,7 +39039,7 @@ class Facilitator {
39028
39039
  }
39029
39040
  async #request(url, init) {
39030
39041
  try {
39031
- const fullUrl = new URL(url, this.endpoint);
39042
+ const fullUrl = new URL(`${this.endpoint}${url}`);
39032
39043
  const response = await fetch(fullUrl, {
39033
39044
  ...init,
39034
39045
  headers: { ...init?.headers, [_a.apikey_header]: this.apikey },
@@ -39046,10 +39057,23 @@ class Facilitator {
39046
39057
  }
39047
39058
  }
39048
39059
  async feeQuote(accepts, context) {
39049
- return await this.#request("/fee/quote", {
39060
+ const response = await this.#request("/fee/quote", {
39050
39061
  method: "POST",
39051
- body: JSON.stringify({ accepts, paymentPermitContext: context }),
39062
+ body: JSON.stringify({ accepts, permit402Context: context }),
39052
39063
  });
39064
+ if (response == null) {
39065
+ return [];
39066
+ }
39067
+ if (Array.isArray(response)) {
39068
+ return response;
39069
+ }
39070
+ if (Array.isArray(response.quotes)) {
39071
+ return response.quotes;
39072
+ }
39073
+ if (Array.isArray(response.data)) {
39074
+ return response.data;
39075
+ }
39076
+ throw new FacilitatorFetchError('Request "/fee/quote" failed, invalid response format');
39053
39077
  }
39054
39078
  async supported() {
39055
39079
  return await this.#request("/supported", { method: "GET" });
@@ -39075,6 +39099,7 @@ var external_node_crypto_ = __webpack_require__(7598);
39075
39099
  var external_node_crypto_namespaceObject = /*#__PURE__*/__webpack_require__.t(external_node_crypto_, 2);
39076
39100
  ;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/server/x402Server.js
39077
39101
 
39102
+
39078
39103
  const x402Server_PAYMENT_ONLY = "PAYMENT_ONLY";
39079
39104
  class x402Server_ResourceConfig {
39080
39105
  scheme;
@@ -39150,13 +39175,16 @@ class X402Server {
39150
39175
  if (!this.facilitator) {
39151
39176
  throw new Error("Facilitator is not set");
39152
39177
  }
39153
- const permitReqs = requirementsList.filter((r) => r.scheme !== "transfer_auth");
39154
- const exactReqs = requirementsList.filter((r) => r.scheme === "transfer_auth");
39178
+ const permitReqs = requirementsList.filter((r) => r.scheme !== SCHEMES.erc3009);
39179
+ const exactReqs = requirementsList.filter((r) => r.scheme === SCHEMES.erc3009);
39155
39180
  const supported = [...exactReqs];
39156
39181
  if (permitReqs.length === 0) {
39157
39182
  return supported;
39158
39183
  }
39159
39184
  const feeQuotes = await this.facilitator.feeQuote(permitReqs);
39185
+ if (!Array.isArray(feeQuotes)) {
39186
+ throw new Error("Facilitator feeQuote returned invalid response");
39187
+ }
39160
39188
  const quoteMap = new Map();
39161
39189
  for (const quote of feeQuotes) {
39162
39190
  quoteMap.set(`${quote.scheme}|${quote.network}|${quote.asset}`.toLowerCase(), quote);
@@ -39172,7 +39200,6 @@ class X402Server {
39172
39200
  facilitatorId: this.facilitator.facilitatorId,
39173
39201
  feeTo: feeQuote.fee.feeTo,
39174
39202
  feeAmount: feeQuote.fee.feeAmount,
39175
- caller: feeQuote.fee.feeTo,
39176
39203
  };
39177
39204
  supported.push(req);
39178
39205
  }
@@ -39189,9 +39216,9 @@ class X402Server {
39189
39216
  resource: resourceInfo,
39190
39217
  accepts: requirements,
39191
39218
  extensions: {
39192
- paymentPermitContext: {
39219
+ permit402Context: {
39193
39220
  meta: {
39194
- kind: x402Server_PAYMENT_ONLY,
39221
+ ptype: x402Server_PAYMENT_ONLY,
39195
39222
  paymentId: paymentId ?? this.generatePaymentId(),
39196
39223
  nonce: nonce ?? this.generateNonce(),
39197
39224
  validAfter: validAfter ?? now,
@@ -39210,7 +39237,7 @@ class X402Server {
39210
39237
  }
39211
39238
  const mechanism = this.findMechanism(requirements.network, requirements.scheme);
39212
39239
  if (mechanism?.verifySignature) {
39213
- const isValid = await mechanism.verifySignature(payload.payload.paymentPermit, payload.payload.signature, requirements.network);
39240
+ const isValid = await mechanism.verifySignature(payload.payload.permit402, payload.payload.signature, requirements.network);
39214
39241
  if (!isValid) {
39215
39242
  return { isValid: false, invalidReason: "invalid_signature_server" };
39216
39243
  }
@@ -39243,7 +39270,7 @@ class X402Server {
39243
39270
  return networkMechanisms[scheme] ?? null;
39244
39271
  }
39245
39272
  validatePayloadMatchesRequirements(payload, requirements) {
39246
- const permit = payload.payload.paymentPermit;
39273
+ const permit = payload.payload.permit402;
39247
39274
  if (permit.payment.payToken.toLowerCase() !== requirements.asset.toLowerCase()) {
39248
39275
  return false;
39249
39276
  }
@@ -39492,13 +39519,13 @@ function x402_protected(server, prices, schemes, network, pay_to, options) {
39492
39519
  //# sourceMappingURL=index.js.map
39493
39520
  ;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/mechanisms/exact.js
39494
39521
  /**
39495
- * ExactPermitTronClientMechanism - TRON client mechanism for "payment_permit" payment scheme
39522
+ * ExactPermitTronClientMechanism - TRON client mechanism for "permit402" payment scheme
39496
39523
  *
39497
- * Uses TIP-712 (TRON's EIP-712 implementation) for signing PaymentPermit.
39524
+ * Uses TIP-712 (TRON's EIP-712 implementation) for signing Permit402.
39498
39525
  */
39499
39526
 
39500
39527
  /**
39501
- * TRON client mechanism for "payment_permit" payment scheme
39528
+ * TRON client mechanism for "permit402" payment scheme
39502
39529
  */
39503
39530
  class ExactPermitTronClientMechanism {
39504
39531
  signer;
@@ -39510,25 +39537,24 @@ class ExactPermitTronClientMechanism {
39510
39537
  return this.signer;
39511
39538
  }
39512
39539
  scheme() {
39513
- return "payment_permit";
39540
+ return setting_SCHEMES.permit402;
39514
39541
  }
39515
39542
  async createPaymentPayload(requirements, resource, extensions) {
39516
- const context = extensions?.paymentPermitContext;
39543
+ const context = extensions?.permit402Context;
39517
39544
  if (!context) {
39518
- throw new PermitValidationError("missing_context", "paymentPermitContext is required");
39545
+ throw new PermitValidationError("missing_context", "permit402Context is required");
39519
39546
  }
39520
39547
  const buyerAddress = this.signer.getAddress();
39521
- const zeroAddress = TRON_ZERO_ADDRESS; // Use TRON zero address for consistency with Python
39548
+ const zeroAddress = TRON_ZERO_ADDRESS;
39522
39549
  const permit = {
39523
39550
  meta: {
39524
- kind: context.meta.kind,
39551
+ ptype: context.meta.ptype,
39525
39552
  paymentId: context.meta.paymentId,
39526
39553
  nonce: context.meta.nonce,
39527
39554
  validAfter: context.meta.validAfter,
39528
39555
  validBefore: context.meta.validBefore,
39529
39556
  },
39530
39557
  buyer: buyerAddress,
39531
- caller: requirements.extra?.fee?.caller || zeroAddress,
39532
39558
  payment: {
39533
39559
  payToken: requirements.asset,
39534
39560
  payAmount: requirements.amount,
@@ -39542,19 +39568,18 @@ class ExactPermitTronClientMechanism {
39542
39568
  // Ensure allowance
39543
39569
  const totalAmount = BigInt(permit.payment.payAmount) + BigInt(permit.fee.feeAmount);
39544
39570
  await this.signer.ensureAllowance(permit.payment.payToken, totalAmount, requirements.network);
39545
- // Build EIP-712 domain - must match contract (name: "Permit402")
39546
- const permitAddress = getPaymentPermitAddress(requirements.network);
39571
+ // Build EIP-712 domain (no version field per contract spec)
39572
+ const permitAddress = getPermit402Address(requirements.network);
39547
39573
  const domain = {
39548
39574
  name: "Permit402",
39549
39575
  chainId: getChainId(requirements.network),
39550
39576
  verifyingContract: this.addressConverter.toEvmFormat(permitAddress),
39551
39577
  };
39552
- // Convert permit to EIP-712 format matching Permit402Details (meta, buyer, payment, fee - no caller)
39553
- const ptype = KIND_MAP[permit.meta.kind] ?? 0;
39578
+ // Convert permit to EIP-712 compatible format
39554
39579
  const permitForSigning = {
39555
39580
  meta: {
39556
- ptype,
39557
- paymentId: permit.meta.paymentId.startsWith("0x") ? permit.meta.paymentId : `0x${permit.meta.paymentId}`,
39581
+ ptype: PTYPE_MAP[permit.meta.ptype],
39582
+ paymentId: permit.meta.paymentId,
39558
39583
  nonce: BigInt(permit.meta.nonce),
39559
39584
  validAfter: BigInt(permit.meta.validAfter),
39560
39585
  validBefore: BigInt(permit.meta.validBefore),
@@ -39570,29 +39595,14 @@ class ExactPermitTronClientMechanism {
39570
39595
  feeAmount: BigInt(permit.fee.feeAmount),
39571
39596
  },
39572
39597
  };
39573
- // Debug: log exact message being signed
39574
- console.log("[SIGN] Domain:", JSON.stringify(domain));
39575
- console.log("[SIGN] Message:", JSON.stringify(permitForSigning, (key, value) => {
39576
- if (value instanceof Uint8Array) {
39577
- return ("0x" +
39578
- Array.from(value)
39579
- .map((b) => b.toString(16).padStart(2, "0"))
39580
- .join(""));
39581
- }
39582
- if (typeof value === "bigint") {
39583
- return value.toString();
39584
- }
39585
- return value;
39586
- }));
39587
- const signature = await this.signer.signTypedData(domain, PAYMENT_PERMIT_TYPES, permitForSigning);
39588
- console.log("[SIGN] Signature:", signature);
39598
+ const signature = await this.signer.signTypedData(domain, PERMIT402_TYPES, permitForSigning);
39589
39599
  return {
39590
39600
  x402Version: 2,
39591
39601
  resource: { url: resource },
39592
39602
  accepted: requirements,
39593
39603
  payload: {
39594
39604
  signature,
39595
- paymentPermit: permit,
39605
+ permit402: permit,
39596
39606
  },
39597
39607
  extensions: {},
39598
39608
  };
@@ -39601,11 +39611,11 @@ class ExactPermitTronClientMechanism {
39601
39611
  //# sourceMappingURL=exact.js.map
39602
39612
  ;// CONCATENATED MODULE: ./node_modules/@springmint/x402/dist/mechanisms/exactEvm.js
39603
39613
  /**
39604
- * ExactPermitEvmClientMechanism - EVM client mechanism for "payment_permit" payment scheme
39614
+ * ExactPermitEvmClientMechanism - EVM client mechanism for "permit402" payment scheme
39605
39615
  */
39606
39616
 
39607
39617
  /**
39608
- * EVM client mechanism for "payment_permit" payment scheme
39618
+ * EVM client mechanism for "permit402" payment scheme
39609
39619
  */
39610
39620
  class ExactPermitEvmClientMechanism {
39611
39621
  signer;
@@ -39617,25 +39627,24 @@ class ExactPermitEvmClientMechanism {
39617
39627
  return this.signer;
39618
39628
  }
39619
39629
  scheme() {
39620
- return "payment_permit";
39630
+ return setting_SCHEMES.permit402;
39621
39631
  }
39622
39632
  async createPaymentPayload(requirements, resource, extensions) {
39623
- const context = extensions?.paymentPermitContext;
39633
+ const context = extensions?.permit402Context;
39624
39634
  if (!context) {
39625
- throw new PermitValidationError("missing_context", "paymentPermitContext is required");
39635
+ throw new PermitValidationError("missing_context", "permit402Context is required");
39626
39636
  }
39627
39637
  const buyerAddress = this.signer.getAddress();
39628
39638
  const zeroAddress = EVM_ZERO_ADDRESS;
39629
39639
  const permit = {
39630
39640
  meta: {
39631
- kind: context.meta.kind,
39641
+ ptype: context.meta.ptype,
39632
39642
  paymentId: context.meta.paymentId,
39633
39643
  nonce: context.meta.nonce,
39634
39644
  validAfter: context.meta.validAfter,
39635
39645
  validBefore: context.meta.validBefore,
39636
39646
  },
39637
39647
  buyer: buyerAddress,
39638
- caller: requirements.extra?.fee?.caller || zeroAddress,
39639
39648
  payment: {
39640
39649
  payToken: requirements.asset,
39641
39650
  payAmount: requirements.amount,
@@ -39649,22 +39658,22 @@ class ExactPermitEvmClientMechanism {
39649
39658
  // Ensure allowance
39650
39659
  const totalAmount = BigInt(permit.payment.payAmount) + BigInt(permit.fee.feeAmount);
39651
39660
  await this.signer.ensureAllowance(permit.payment.payToken, totalAmount, requirements.network);
39652
- // Build EIP-712 domain - must match contract EIP712.sol (name: "Permit402")
39653
- const permitAddress = getPaymentPermitAddress(requirements.network);
39661
+ // Build EIP-712 domain
39662
+ const permitAddress = getPermit402Address(requirements.network);
39654
39663
  const domain = {
39655
39664
  name: "Permit402",
39656
39665
  chainId: getChainId(requirements.network),
39657
39666
  verifyingContract: this.addressConverter.toEvmFormat(permitAddress),
39658
39667
  };
39659
39668
  // Convert permit to EIP-712 format matching Permit402Details (meta, buyer, payment, fee - no caller)
39660
- const ptype = KIND_MAP[permit.meta.kind] ?? 0;
39661
- const paymentIdBytes = permit.meta.paymentId.startsWith("0x")
39662
- ? permit.meta.paymentId
39663
- : `0x${permit.meta.paymentId}`;
39669
+ // const ptype = KIND_MAP[permit.meta.kind] ?? 0;
39670
+ // const paymentIdBytes = permit.meta.paymentId.startsWith("0x")
39671
+ // ? permit.meta.paymentId
39672
+ // : `0x${permit.meta.paymentId}`;
39664
39673
  const permitForSigning = {
39665
39674
  meta: {
39666
- ptype,
39667
- paymentId: paymentIdBytes,
39675
+ ptype: PTYPE_MAP[permit.meta.ptype],
39676
+ paymentId: permit.meta.paymentId,
39668
39677
  nonce: BigInt(permit.meta.nonce),
39669
39678
  validAfter: BigInt(permit.meta.validAfter),
39670
39679
  validBefore: BigInt(permit.meta.validBefore),
@@ -39680,14 +39689,14 @@ class ExactPermitEvmClientMechanism {
39680
39689
  feeAmount: BigInt(permit.fee.feeAmount),
39681
39690
  },
39682
39691
  };
39683
- const signature = await this.signer.signTypedData(domain, PAYMENT_PERMIT_TYPES, permitForSigning);
39692
+ const signature = await this.signer.signTypedData(domain, PERMIT402_TYPES, permitForSigning);
39684
39693
  return {
39685
39694
  x402Version: 2,
39686
39695
  resource: { url: resource },
39687
39696
  accepted: requirements,
39688
39697
  payload: {
39689
39698
  signature,
39690
- paymentPermit: permit,
39699
+ permit402: permit,
39691
39700
  },
39692
39701
  extensions: {},
39693
39702
  };
@@ -39699,15 +39708,13 @@ class ExactPermitEvmClientMechanism {
39699
39708
  * Shared types and helpers for transfer_auth mechanism.
39700
39709
  *
39701
39710
  * transfer_auth uses ERC-3009 TransferWithAuthorization for direct token transfers
39702
- * without going through a PaymentPermit contract.
39711
+ * without going through a Permit402 contract.
39703
39712
  */
39704
- /** Scheme name */
39705
- const SCHEME_EXACT = "transfer_auth";
39706
39713
  /** Default validity period (1 hour) */
39707
39714
  const DEFAULT_VALIDITY_SECONDS = 3600;
39708
39715
  /**
39709
39716
  * EIP-712 type definitions for TransferWithAuthorization
39710
- * Note: domain includes "version" field (unlike PaymentPermit)
39717
+ * Note: domain includes "version" field (unlike Permit402)
39711
39718
  */
39712
39719
  const TRANSFER_AUTH_EIP712_TYPES = {
39713
39720
  TransferWithAuthorization: [
@@ -39787,7 +39794,7 @@ class ExactTronClientMechanism {
39787
39794
  return this.signer;
39788
39795
  }
39789
39796
  scheme() {
39790
- return SCHEME_EXACT;
39797
+ return setting_SCHEMES.erc3009;
39791
39798
  }
39792
39799
  async createPaymentPayload(requirements, resource) {
39793
39800
  const converter = this.addressConverter;
@@ -39817,7 +39824,7 @@ class ExactTronClientMechanism {
39817
39824
  accepted: requirements,
39818
39825
  payload: {
39819
39826
  signature,
39820
- paymentPermit: undefined,
39827
+ permit402: undefined,
39821
39828
  },
39822
39829
  extensions: {
39823
39830
  transferAuthorization: authorization,
@@ -39849,7 +39856,7 @@ class ExactEvmClientMechanism {
39849
39856
  return this.signer;
39850
39857
  }
39851
39858
  scheme() {
39852
- return SCHEME_EXACT;
39859
+ return setting_SCHEMES.erc3009;
39853
39860
  }
39854
39861
  async createPaymentPayload(requirements, resource) {
39855
39862
  const converter = this.addressConverter;
@@ -39879,7 +39886,7 @@ class ExactEvmClientMechanism {
39879
39886
  accepted: requirements,
39880
39887
  payload: {
39881
39888
  signature,
39882
- paymentPermit: undefined,
39889
+ permit402: undefined,
39883
39890
  },
39884
39891
  extensions: {
39885
39892
  transferAuthorization: authorization,
@@ -39892,7 +39899,7 @@ class ExactEvmClientMechanism {
39892
39899
  /**
39893
39900
  * x402 Client Mechanisms
39894
39901
  */
39895
- // payment_permit scheme
39902
+ // permit402 scheme
39896
39903
 
39897
39904
 
39898
39905
  // exact scheme
@@ -75010,37 +75017,73 @@ class TronClientSigner {
75010
75017
  privateKey;
75011
75018
  address; // Base58 format
75012
75019
  tronWebInstances = new Map();
75013
- constructor(privateKey) {
75020
+ rpcUrl;
75021
+ rpcUrls;
75022
+ rpcByNetwork;
75023
+ constructor(privateKey, options) {
75014
75024
  const cleanKey = privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey;
75015
75025
  this.privateKey = cleanKey;
75026
+ this.rpcUrl = options?.rpcUrl;
75027
+ this.rpcUrls = options?.rpcUrls;
75028
+ this.rpcByNetwork = options?.rpcByNetwork;
75016
75029
  // Derive address using a temporary TronWeb instance (pure crypto, no network needed)
75017
- const tw = this.createTronWeb("https://nile.trongrid.io");
75030
+ const tw = this.getDefaultTronWeb();
75018
75031
  this.address = tw.address.fromPrivateKey(cleanKey);
75019
75032
  }
75020
75033
  /**
75021
75034
  * Get or create a TronWeb instance for the given network.
75022
75035
  */
75023
75036
  getTronWeb(network) {
75024
- const host = network ? TRON_RPC_URLS[network] : undefined;
75025
- const key = host ?? "__default__";
75026
- let tw = this.tronWebInstances.get(key);
75027
- if (!tw) {
75028
- if (!host) {
75029
- throw new errors_UnsupportedNetworkError(`No RPC URL configured for network: ${network}`);
75030
- }
75031
- tw = this.createTronWeb(host);
75032
- this.tronWebInstances.set(key, tw);
75037
+ const host = this.getRpcCandidates(network)[0];
75038
+ if (!host) {
75039
+ throw new errors_UnsupportedNetworkError(`No RPC URL configured for network: ${network}`);
75033
75040
  }
75034
- return tw;
75041
+ return this.getOrCreateTronWeb(host);
75035
75042
  }
75036
75043
  getDefaultTronWeb() {
75037
- let tw = this.tronWebInstances.get("__default__");
75044
+ const host = this.getRpcCandidates("tron:nile")[0] ?? "https://nile.trongrid.io";
75045
+ return this.getOrCreateTronWeb(host);
75046
+ }
75047
+ getOrCreateTronWeb(host) {
75048
+ let tw = this.tronWebInstances.get(host);
75038
75049
  if (!tw) {
75039
- tw = this.createTronWeb("https://nile.trongrid.io");
75040
- this.tronWebInstances.set("__default__", tw);
75050
+ tw = this.createTronWeb(host);
75051
+ this.tronWebInstances.set(host, tw);
75041
75052
  }
75042
75053
  return tw;
75043
75054
  }
75055
+ getRpcCandidates(network) {
75056
+ if (!network) {
75057
+ const global = this.rpcUrls?.length ? this.rpcUrls : this.rpcUrl ? [this.rpcUrl] : [];
75058
+ const deduped = global.filter((url, index) => global.indexOf(url) === index);
75059
+ return deduped.length > 0 ? deduped : ["https://nile.trongrid.io"];
75060
+ }
75061
+ const perNetwork = this.rpcByNetwork?.[network];
75062
+ const perNetworkList = Array.isArray(perNetwork) ? perNetwork : perNetwork ? [perNetwork] : [];
75063
+ const globalList = this.rpcUrls?.length ? this.rpcUrls : this.rpcUrl ? [this.rpcUrl] : [];
75064
+ const overrides = {
75065
+ ...(this.rpcByNetwork ?? {}),
75066
+ [network]: [...perNetworkList, ...globalList],
75067
+ };
75068
+ return resolveRpcUrls(network, overrides);
75069
+ }
75070
+ async executeWithRpcFallback(network, action) {
75071
+ const candidates = this.getRpcCandidates(network);
75072
+ if (candidates.length === 0) {
75073
+ throw new errors_UnsupportedNetworkError(`No RPC URL configured for network: ${network}`);
75074
+ }
75075
+ let lastError;
75076
+ for (const host of candidates) {
75077
+ const tw = this.getOrCreateTronWeb(host);
75078
+ try {
75079
+ return await action(tw);
75080
+ }
75081
+ catch (error) {
75082
+ lastError = error;
75083
+ }
75084
+ }
75085
+ throw new Error(`All RPC endpoints failed for ${network}: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
75086
+ }
75044
75087
  createTronWeb(fullHost) {
75045
75088
  const apiKey = typeof process !== "undefined" ? process.env?.TRON_GRID_API_KEY : undefined;
75046
75089
  const headers = apiKey ? { "TRON-PRO-API-KEY": apiKey } : undefined;
@@ -75080,25 +75123,20 @@ class TronClientSigner {
75080
75123
  return signFn.call(tw.trx, typedDomain, types, message, this.privateKey);
75081
75124
  }
75082
75125
  async checkBalance(token, network) {
75083
- try {
75084
- const ownerHex = toEvmHex(this.address);
75085
- const tw = this.getTronWeb(network);
75126
+ const ownerHex = toEvmHex(this.address);
75127
+ return this.executeWithRpcFallback(network, async (tw) => {
75086
75128
  const result = await tw.transactionBuilder.triggerConstantContract(token, "balanceOf(address)", {}, [{ type: "address", value: ownerHex }], this.address);
75087
75129
  if (result.result?.result && result.constant_result?.length) {
75088
75130
  return BigInt("0x" + result.constant_result[0]);
75089
75131
  }
75090
- }
75091
- catch (error) {
75092
- console.error(`[TronClientSigner] Failed to check balance: ${error}`);
75093
- }
75094
- return BigInt(0);
75132
+ throw new Error(`checkBalance failed for ${token} on ${network}: no result from RPC`);
75133
+ });
75095
75134
  }
75096
75135
  async checkAllowance(token, _amount, network) {
75097
- const spender = getPaymentPermitAddress(network);
75098
- try {
75099
- const ownerHex = toEvmHex(this.address);
75100
- const spenderHex = toEvmHex(spender);
75101
- const tw = this.getTronWeb(network);
75136
+ const spender = getPermit402Address(network);
75137
+ const ownerHex = toEvmHex(this.address);
75138
+ const spenderHex = toEvmHex(spender);
75139
+ return this.executeWithRpcFallback(network, async (tw) => {
75102
75140
  const result = await tw.transactionBuilder.triggerConstantContract(token, ERC20_ALLOWANCE_SELECTOR, {}, [
75103
75141
  { type: "address", value: ownerHex },
75104
75142
  { type: "address", value: spenderHex },
@@ -75106,11 +75144,8 @@ class TronClientSigner {
75106
75144
  if (result.result?.result && result.constant_result?.length) {
75107
75145
  return BigInt("0x" + result.constant_result[0]);
75108
75146
  }
75109
- }
75110
- catch (error) {
75111
- console.error(`[TronClientSigner] Failed to check allowance: ${error}`);
75112
- }
75113
- return BigInt(0);
75147
+ throw new Error(`checkAllowance failed for ${token} on ${network}: no result from RPC`);
75148
+ });
75114
75149
  }
75115
75150
  async ensureAllowance(token, amount, network, mode = "auto") {
75116
75151
  if (mode === "skip") {
@@ -75118,57 +75153,58 @@ class TronClientSigner {
75118
75153
  }
75119
75154
  const currentAllowance = await this.checkAllowance(token, amount, network);
75120
75155
  if (currentAllowance >= amount) {
75121
- console.log(`[ALLOWANCE] Sufficient allowance: ${currentAllowance} >= ${amount}`);
75122
75156
  return true;
75123
75157
  }
75124
75158
  if (mode === "interactive") {
75125
75159
  throw new InsufficientAllowanceError("Interactive approval not implemented - use wallet UI");
75126
75160
  }
75127
75161
  // Auto mode: send approve transaction
75128
- console.log(`[ALLOWANCE] Insufficient allowance: ${currentAllowance} < ${amount}, sending approve...`);
75129
- const spender = getPaymentPermitAddress(network);
75162
+ const spender = getPermit402Address(network);
75130
75163
  const spenderHex = toEvmHex(spender);
75131
75164
  // Use maxUint160 (2^160 - 1) to avoid repeated approvals
75132
75165
  const maxUint160 = BigInt(2) ** BigInt(160) - BigInt(1);
75133
75166
  try {
75134
- // Build approve transaction
75135
- const tw = this.getTronWeb(network);
75136
- const tx = await tw.transactionBuilder.triggerSmartContract(token, ERC20_APPROVE_SELECTOR, {
75137
- feeLimit: 100_000_000,
75138
- callValue: 0,
75139
- }, [
75140
- { type: "address", value: spenderHex },
75141
- { type: "uint256", value: maxUint160.toString() },
75142
- ], this.address);
75143
- if (!tx.result?.result) {
75144
- throw new InsufficientAllowanceError("Failed to build approve transaction");
75145
- }
75146
- // Sign transaction
75147
- const signedTx = await tw.trx.sign(tx.transaction, this.privateKey);
75148
- // Broadcast transaction
75149
- const broadcast = await tw.trx.sendRawTransaction(signedTx);
75150
- if (!broadcast.result) {
75151
- throw new InsufficientAllowanceError(`Failed to broadcast approve transaction: ${JSON.stringify(broadcast)}`);
75152
- }
75153
- console.log(`[ALLOWANCE] Approve transaction sent: ${broadcast.txid}`);
75154
- // Wait for confirmation (poll for ~30 seconds)
75155
- const txid = broadcast.txid;
75156
- for (let i = 0; i < 10; i++) {
75157
- await new Promise((resolve) => setTimeout(resolve, 3000));
75158
- try {
75159
- const info = await tw.trx.getTransactionInfo(txid);
75160
- if (info && info.blockNumber) {
75161
- const success = info.receipt?.result === "SUCCESS";
75162
- console.log(`[ALLOWANCE] Approve confirmed: ${success ? "SUCCESS" : "FAILED"}`);
75163
- return success;
75164
- }
75167
+ return await this.executeWithRpcFallback(network, async (tw) => {
75168
+ // Build approve transaction
75169
+ const tx = await tw.transactionBuilder.triggerSmartContract(token, ERC20_APPROVE_SELECTOR, {
75170
+ feeLimit: 100_000_000,
75171
+ callValue: 0,
75172
+ }, [
75173
+ { type: "address", value: spenderHex },
75174
+ { type: "uint256", value: maxUint160.toString() },
75175
+ ], this.address);
75176
+ if (!tx.result?.result) {
75177
+ throw new InsufficientAllowanceError("Failed to build approve transaction");
75165
75178
  }
75166
- catch {
75167
- // Not confirmed yet, continue polling
75179
+ // Sign transaction
75180
+ const signedTx = await tw.trx.sign(tx.transaction, this.privateKey);
75181
+ // Broadcast transaction
75182
+ const broadcast = await tw.trx.sendRawTransaction(signedTx);
75183
+ if (!broadcast.result) {
75184
+ throw new InsufficientAllowanceError(`Failed to broadcast approve transaction: ${JSON.stringify(broadcast)}`);
75168
75185
  }
75169
- }
75170
- console.log("[ALLOWANCE] Approve transaction not confirmed within timeout, assuming success");
75171
- return true;
75186
+ // Wait for confirmation (poll for ~30 seconds)
75187
+ const txid = broadcast.txid;
75188
+ for (let i = 0; i < 10; i++) {
75189
+ await new Promise((resolve) => setTimeout(resolve, 3000));
75190
+ try {
75191
+ const info = await tw.trx.getTransactionInfo(txid);
75192
+ if (info && info.blockNumber) {
75193
+ if (info.receipt?.result === "SUCCESS") {
75194
+ return true;
75195
+ }
75196
+ throw new InsufficientAllowanceError(`Approve transaction failed on-chain for tx ${txid}: ${info.receipt?.result ?? "UNKNOWN"}`);
75197
+ }
75198
+ }
75199
+ catch (error) {
75200
+ if (error instanceof InsufficientAllowanceError) {
75201
+ throw error;
75202
+ }
75203
+ // Not confirmed yet, continue polling
75204
+ }
75205
+ }
75206
+ throw new InsufficientAllowanceError(`Approve transaction not confirmed within timeout: ${txid}`);
75207
+ });
75172
75208
  }
75173
75209
  catch (error) {
75174
75210
  if (error instanceof InsufficientAllowanceError)
@@ -90471,6 +90507,167 @@ function createPublicClient(parameters) {
90471
90507
  return client.extend(publicActions);
90472
90508
  }
90473
90509
  //# sourceMappingURL=createPublicClient.js.map
90510
+ ;// CONCATENATED MODULE: ./node_modules/viem/_esm/clients/transports/fallback.js
90511
+
90512
+
90513
+
90514
+
90515
+ function fallback(transports_, config = {}) {
90516
+ const { key = 'fallback', name = 'Fallback', rank = false, shouldThrow: shouldThrow_ = shouldThrow, retryCount, retryDelay, } = config;
90517
+ return (({ chain, pollingInterval = 4_000, timeout, ...rest }) => {
90518
+ let transports = transports_;
90519
+ let onResponse = () => { };
90520
+ const transport = createTransport({
90521
+ key,
90522
+ name,
90523
+ async request({ method, params }) {
90524
+ let includes;
90525
+ const fetch = async (i = 0) => {
90526
+ const transport = transports[i]({
90527
+ ...rest,
90528
+ chain,
90529
+ retryCount: 0,
90530
+ timeout,
90531
+ });
90532
+ try {
90533
+ const response = await transport.request({
90534
+ method,
90535
+ params,
90536
+ });
90537
+ onResponse({
90538
+ method,
90539
+ params: params,
90540
+ response,
90541
+ transport,
90542
+ status: 'success',
90543
+ });
90544
+ return response;
90545
+ }
90546
+ catch (err) {
90547
+ onResponse({
90548
+ error: err,
90549
+ method,
90550
+ params: params,
90551
+ transport,
90552
+ status: 'error',
90553
+ });
90554
+ if (shouldThrow_(err))
90555
+ throw err;
90556
+ // If we've reached the end of the fallbacks, throw the error.
90557
+ if (i === transports.length - 1)
90558
+ throw err;
90559
+ // Check if at least one other transport includes the method
90560
+ includes ??= transports.slice(i + 1).some((transport) => {
90561
+ const { include, exclude } = transport({ chain }).config.methods || {};
90562
+ if (include)
90563
+ return include.includes(method);
90564
+ if (exclude)
90565
+ return !exclude.includes(method);
90566
+ return true;
90567
+ });
90568
+ if (!includes)
90569
+ throw err;
90570
+ // Otherwise, try the next fallback.
90571
+ return fetch(i + 1);
90572
+ }
90573
+ };
90574
+ return fetch();
90575
+ },
90576
+ retryCount,
90577
+ retryDelay,
90578
+ type: 'fallback',
90579
+ }, {
90580
+ onResponse: (fn) => (onResponse = fn),
90581
+ transports: transports.map((fn) => fn({ chain, retryCount: 0 })),
90582
+ });
90583
+ if (rank) {
90584
+ const rankOptions = (typeof rank === 'object' ? rank : {});
90585
+ rankTransports({
90586
+ chain,
90587
+ interval: rankOptions.interval ?? pollingInterval,
90588
+ onTransports: (transports_) => (transports = transports_),
90589
+ ping: rankOptions.ping,
90590
+ sampleCount: rankOptions.sampleCount,
90591
+ timeout: rankOptions.timeout,
90592
+ transports,
90593
+ weights: rankOptions.weights,
90594
+ });
90595
+ }
90596
+ return transport;
90597
+ });
90598
+ }
90599
+ function shouldThrow(error) {
90600
+ if ('code' in error && typeof error.code === 'number') {
90601
+ if (error.code === TransactionRejectedRpcError.code ||
90602
+ error.code === UserRejectedRequestError.code ||
90603
+ error.code === WalletConnectSessionSettlementError.code ||
90604
+ errors_node/* ExecutionRevertedError */.A7.nodeMessage.test(error.message) ||
90605
+ error.code === 5000 // CAIP UserRejectedRequestError
90606
+ )
90607
+ return true;
90608
+ }
90609
+ return false;
90610
+ }
90611
+ /** @internal */
90612
+ function rankTransports({ chain, interval = 4_000, onTransports, ping, sampleCount = 10, timeout = 1_000, transports, weights = {}, }) {
90613
+ const { stability: stabilityWeight = 0.7, latency: latencyWeight = 0.3 } = weights;
90614
+ const samples = [];
90615
+ const rankTransports_ = async () => {
90616
+ // 1. Take a sample from each Transport.
90617
+ const sample = await Promise.all(transports.map(async (transport) => {
90618
+ const transport_ = transport({ chain, retryCount: 0, timeout });
90619
+ const start = Date.now();
90620
+ let end;
90621
+ let success;
90622
+ try {
90623
+ await (ping
90624
+ ? ping({ transport: transport_ })
90625
+ : transport_.request({ method: 'net_listening' }));
90626
+ success = 1;
90627
+ }
90628
+ catch {
90629
+ success = 0;
90630
+ }
90631
+ finally {
90632
+ end = Date.now();
90633
+ }
90634
+ const latency = end - start;
90635
+ return { latency, success };
90636
+ }));
90637
+ // 2. Store the sample. If we have more than `sampleCount` samples, remove
90638
+ // the oldest sample.
90639
+ samples.push(sample);
90640
+ if (samples.length > sampleCount)
90641
+ samples.shift();
90642
+ // 3. Calculate the max latency from samples.
90643
+ const maxLatency = Math.max(...samples.map((sample) => Math.max(...sample.map(({ latency }) => latency))));
90644
+ // 4. Calculate the score for each Transport.
90645
+ const scores = transports
90646
+ .map((_, i) => {
90647
+ const latencies = samples.map((sample) => sample[i].latency);
90648
+ const meanLatency = latencies.reduce((acc, latency) => acc + latency, 0) /
90649
+ latencies.length;
90650
+ const latencyScore = 1 - meanLatency / maxLatency;
90651
+ const successes = samples.map((sample) => sample[i].success);
90652
+ const stabilityScore = successes.reduce((acc, success) => acc + success, 0) /
90653
+ successes.length;
90654
+ if (stabilityScore === 0)
90655
+ return [0, i];
90656
+ return [
90657
+ latencyWeight * latencyScore + stabilityWeight * stabilityScore,
90658
+ i,
90659
+ ];
90660
+ })
90661
+ .sort((a, b) => b[0] - a[0]);
90662
+ // 5. Sort the Transports by score.
90663
+ onTransports(scores.map(([, i]) => transports[i]));
90664
+ // 6. Wait, and then rank again.
90665
+ await wait(interval);
90666
+ rankTransports_();
90667
+ };
90668
+ rankTransports_();
90669
+ }
90670
+ //# sourceMappingURL=fallback.js.map
90474
90671
  ;// CONCATENATED MODULE: ./node_modules/viem/_esm/accounts/toAccount.js
90475
90672
  // TODO(v3): Rename to `toLocalAccount` + add `source` property to define source (privateKey, mnemonic, hdKey, etc).
90476
90673
 
@@ -91189,9 +91386,15 @@ class EvmClientSigner {
91189
91386
  walletClient;
91190
91387
  publicClients = new Map();
91191
91388
  account;
91192
- constructor(privateKey) {
91389
+ rpcUrl;
91390
+ rpcUrls;
91391
+ rpcByNetwork;
91392
+ constructor(privateKey, options) {
91193
91393
  const hexKey = privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`;
91194
91394
  this.account = privateKeyToAccount(hexKey);
91395
+ this.rpcUrl = options?.rpcUrl;
91396
+ this.rpcUrls = options?.rpcUrls;
91397
+ this.rpcByNetwork = options?.rpcByNetwork;
91195
91398
  this.walletClient = createWalletClient({
91196
91399
  account: this.account,
91197
91400
  chain: mainnet,
@@ -91210,7 +91413,6 @@ class EvmClientSigner {
91210
91413
  });
91211
91414
  }
91212
91415
  async signTypedData(domain, types, message) {
91213
- // TODO: Add explicit primaryType to ClientSigner interface
91214
91416
  const primaryType = types.Permit402Details ? "Permit402Details" : Object.keys(types).pop();
91215
91417
  if (!primaryType) {
91216
91418
  throw new Error("No primary type found in types definition");
@@ -91225,35 +91427,23 @@ class EvmClientSigner {
91225
91427
  async checkBalance(token, network) {
91226
91428
  const chainId = this.parseNetworkToChainId(network);
91227
91429
  const client = this.getPublicClient(chainId, network);
91228
- try {
91229
- return await client.readContract({
91230
- address: token,
91231
- abi: evmSigner_ERC20_ABI,
91232
- functionName: "balanceOf",
91233
- args: [this.account.address],
91234
- });
91235
- }
91236
- catch (error) {
91237
- console.error(`[EvmClientSigner] checkBalance failed for ${token} on ${network}:`, error);
91238
- return 0n;
91239
- }
91430
+ return await client.readContract({
91431
+ address: token,
91432
+ abi: evmSigner_ERC20_ABI,
91433
+ functionName: "balanceOf",
91434
+ args: [this.account.address],
91435
+ });
91240
91436
  }
91241
91437
  async checkAllowance(token, _amount, network) {
91242
91438
  const chainId = this.parseNetworkToChainId(network);
91243
91439
  const client = this.getPublicClient(chainId, network);
91244
- const spender = getPaymentPermitAddress(network);
91245
- try {
91246
- return await client.readContract({
91247
- address: token,
91248
- abi: evmSigner_ERC20_ABI,
91249
- functionName: "allowance",
91250
- args: [this.account.address, spender],
91251
- });
91252
- }
91253
- catch (error) {
91254
- console.error(`[EvmClientSigner] checkAllowance failed for ${token} on ${network}:`, error);
91255
- return 0n;
91256
- }
91440
+ const spender = getPermit402Address(network);
91441
+ return await client.readContract({
91442
+ address: token,
91443
+ abi: evmSigner_ERC20_ABI,
91444
+ functionName: "allowance",
91445
+ args: [this.account.address, spender],
91446
+ });
91257
91447
  }
91258
91448
  async ensureAllowance(token, amount, network, mode = "auto") {
91259
91449
  if (mode === "skip")
@@ -91266,14 +91456,14 @@ class EvmClientSigner {
91266
91456
  }
91267
91457
  const chainId = this.parseNetworkToChainId(network);
91268
91458
  const client = this.getPublicClient(chainId, network);
91269
- const spender = getPaymentPermitAddress(network);
91459
+ const spender = getPermit402Address(network);
91270
91460
  const chain = this.getChain(chainId);
91271
91461
  try {
91272
- const rpcUrl = resolveRpcUrl(network);
91462
+ const transport = this.createTransport(network);
91273
91463
  const walletClient = createWalletClient({
91274
91464
  account: this.account,
91275
91465
  chain: chain,
91276
- transport: http_http(rpcUrl),
91466
+ transport,
91277
91467
  });
91278
91468
  const hash = await walletClient.writeContract({
91279
91469
  address: token,
@@ -91282,29 +91472,44 @@ class EvmClientSigner {
91282
91472
  args: [spender, BigInt(2) ** BigInt(256) - BigInt(1)],
91283
91473
  });
91284
91474
  const receipt = await client.waitForTransactionReceipt({ hash });
91285
- const success = receipt.status === "success";
91286
- if (success) {
91287
- console.info(`[EvmClientSigner] ERC20 approval confirmed for ${token}, tx: ${hash}`);
91288
- }
91289
- return success;
91475
+ return receipt.status === "success";
91290
91476
  }
91291
91477
  catch (error) {
91292
- console.error(`[EvmClientSigner] ERC20 approval failed for ${token}:`, error);
91293
91478
  throw new InsufficientAllowanceError(`ERC20 approval transaction failed for ${token}: ${error instanceof Error ? error.message : String(error)}`);
91294
91479
  }
91295
91480
  }
91296
91481
  getPublicClient(chainId, network) {
91297
91482
  let client = this.publicClients.get(chainId);
91298
91483
  if (!client) {
91299
- const rpcUrl = resolveRpcUrl(network);
91484
+ const transport = this.createTransport(network);
91300
91485
  client = createPublicClient({
91301
91486
  chain: this.getChain(chainId),
91302
- transport: http_http(rpcUrl),
91487
+ transport,
91303
91488
  });
91304
91489
  this.publicClients.set(chainId, client);
91305
91490
  }
91306
91491
  return client;
91307
91492
  }
91493
+ createTransport(network) {
91494
+ const candidates = this.getRpcCandidates(network);
91495
+ if (candidates.length === 0) {
91496
+ throw new errors_UnsupportedNetworkError(`No RPC URL configured for network: ${network}`);
91497
+ }
91498
+ if (candidates.length === 1) {
91499
+ return http_http(candidates[0]);
91500
+ }
91501
+ return fallback(candidates.map((url) => http_http(url)), { rank: false, retryCount: 1 });
91502
+ }
91503
+ getRpcCandidates(network) {
91504
+ const perNetwork = this.rpcByNetwork?.[network];
91505
+ const perNetworkList = Array.isArray(perNetwork) ? perNetwork : perNetwork ? [perNetwork] : [];
91506
+ const globalList = this.rpcUrls?.length ? this.rpcUrls : this.rpcUrl ? [this.rpcUrl] : [];
91507
+ const overrides = {
91508
+ ...(this.rpcByNetwork ?? {}),
91509
+ [network]: [...perNetworkList, ...globalList],
91510
+ };
91511
+ return resolveRpcUrls(network, overrides);
91512
+ }
91308
91513
  getChain(chainId) {
91309
91514
  const chains = {
91310
91515
  1: mainnet,
@@ -91345,6 +91550,7 @@ class EvmClientSigner {
91345
91550
 
91346
91551
 
91347
91552
 
91553
+
91348
91554
  // HTTP Client
91349
91555
 
91350
91556
  // Server helpers