@dexterai/x402 2.1.0 → 3.0.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.
@@ -1,9 +1,10 @@
1
- export { P as PaymentReceipt, a as X402Client, X as X402ClientConfig, c as createX402Client, f as fireImpressionBeacon, g as getPaymentReceipt, d as getSponsoredAccessInfo, b as getSponsoredRecommendations } from '../sponsored-access-Lxa11w_X.js';
1
+ export { P as PaymentReceipt, a as X402Client, X as X402ClientConfig, c as createX402Client, f as fireImpressionBeacon, g as getPaymentReceipt, d as getSponsoredAccessInfo, b as getSponsoredRecommendations } from '../sponsored-access-BVoucsEW.js';
2
2
  import { A as AccessPassClientConfig, P as PaymentAccept } from '../types-_iT11DL0.js';
3
3
  export { b as AccessPassInfo, a as AccessPassTier, D as DEXTER_FACILITATOR_URL, U as USDC_MINT, X as X402Error } from '../types-_iT11DL0.js';
4
4
  import { Keypair } from '@solana/web3.js';
5
- import { S as SolanaWallet, E as EvmWallet } from '../types-YQlJI5E3.js';
6
- export { B as BASE_MAINNET, C as ChainAdapter, b as SOLANA_MAINNET, W as WalletSet, a as createEvmAdapter, c as createSolanaAdapter } from '../types-YQlJI5E3.js';
5
+ import { S as SolanaWallet, E as EvmWallet } from '../types-DBS0XOsH.js';
6
+ export { B as BASE_MAINNET, C as ChainAdapter, b as SOLANA_MAINNET, W as WalletSet, a as createEvmAdapter, c as createSolanaAdapter } from '../types-DBS0XOsH.js';
7
+ export { FormattedResource as CapabilityAPI, CapabilitySearchOptions, CapabilitySearchResult, NoMatchReason, capabilitySearch } from '@dexterai/x402-core';
7
8
  export { SponsoredAccessSettlementInfo, SponsoredRecommendation } from '@dexterai/x402-ads-types';
8
9
 
9
10
  /**
@@ -237,107 +238,6 @@ declare function createEvmKeypairWallet(privateKey: string): Promise<EvmWallet>;
237
238
  */
238
239
  declare function isEvmKeypairWallet(wallet: unknown): wallet is EvmWallet;
239
240
 
240
- /**
241
- * API Discovery — Find x402 Paid APIs
242
- *
243
- * Search the Dexter marketplace for x402-enabled APIs. Discover endpoints
244
- * by category, price range, network, and quality score — then pay for them
245
- * with the same SDK.
246
- *
247
- * @example
248
- * ```typescript
249
- * import { searchAPIs } from '@dexterai/x402/client';
250
- *
251
- * const results = await searchAPIs({ query: 'sentiment analysis', maxPrice: 0.10 });
252
- * for (const api of results) {
253
- * console.log(`${api.name}: ${api.price} — ${api.description}`);
254
- * }
255
- *
256
- * // Then call one with wrapFetch:
257
- * const response = await x402Fetch(results[0].url);
258
- * ```
259
- */
260
- /**
261
- * Search options for discovering x402 APIs
262
- */
263
- interface SearchAPIsOptions {
264
- /** Search query (e.g., 'sentiment analysis', 'token price', 'image generation') */
265
- query?: string;
266
- /** Filter by category (e.g., 'defi', 'ai', 'data', 'social') */
267
- category?: string;
268
- /** Filter by payment network (e.g., 'solana', 'base', 'polygon') */
269
- network?: string;
270
- /** Maximum price per call in USDC */
271
- maxPrice?: number;
272
- /** Only return verified endpoints (quality score 75+) */
273
- verifiedOnly?: boolean;
274
- /** Sort order */
275
- sort?: 'marketplace' | 'relevance' | 'quality_score' | 'settlements' | 'volume' | 'recent';
276
- /** Maximum results to return (default 20, max 50) */
277
- limit?: number;
278
- /** Marketplace API URL (default: Dexter marketplace) */
279
- marketplaceUrl?: string;
280
- }
281
- /**
282
- * A discovered x402 API endpoint
283
- */
284
- interface DiscoveredAPI {
285
- /** API name */
286
- name: string;
287
- /** Full resource URL — pass directly to wrapFetch or createX402Client.fetch */
288
- url: string;
289
- /** HTTP method */
290
- method: string;
291
- /** Price per call (formatted, e.g., '$0.05') */
292
- price: string;
293
- /** Price per call in USDC (raw number, null if free) */
294
- priceUsdc: number | null;
295
- /** Payment network */
296
- network: string | null;
297
- /** Human-readable description */
298
- description: string;
299
- /** Category (e.g., 'defi', 'ai', 'data') */
300
- category: string;
301
- /** Quality score (0-100, null if unscored) */
302
- qualityScore: number | null;
303
- /** Whether the endpoint has been verified */
304
- verified: boolean;
305
- /** Total number of settlements (calls) */
306
- totalCalls: number;
307
- /** Total volume in USDC (formatted, e.g., '$1,234.56') */
308
- totalVolume: string | null;
309
- /** Seller name */
310
- seller: string | null;
311
- /** Seller reputation score */
312
- sellerReputation: number | null;
313
- /** Whether authentication is required beyond payment */
314
- authRequired: boolean;
315
- /** Last time someone called this API */
316
- lastActive: string | null;
317
- }
318
- /**
319
- * Search the Dexter marketplace for x402 paid APIs.
320
- *
321
- * Returns a list of discovered endpoints that can be called directly
322
- * with `wrapFetch` or `createX402Client.fetch`.
323
- *
324
- * @example Find AI APIs under $0.10
325
- * ```typescript
326
- * const apis = await searchAPIs({ query: 'ai', maxPrice: 0.10 });
327
- * ```
328
- *
329
- * @example Browse all verified DeFi tools
330
- * ```typescript
331
- * const apis = await searchAPIs({ category: 'defi', verifiedOnly: true });
332
- * ```
333
- *
334
- * @example Find cheapest APIs on Solana
335
- * ```typescript
336
- * const apis = await searchAPIs({ network: 'solana', sort: 'quality_score' });
337
- * ```
338
- */
339
- declare function searchAPIs(options?: SearchAPIsOptions): Promise<DiscoveredAPI[]>;
340
-
341
241
  /**
342
242
  * Budget Account — Autonomous Agent Spending Controls
343
243
  *
@@ -423,4 +323,4 @@ interface BudgetAccount {
423
323
  */
424
324
  declare function createBudgetAccount(config: BudgetAccountConfig): BudgetAccount;
425
325
 
426
- export { AccessPassClientConfig, type BudgetAccount, type BudgetAccountConfig, type BudgetConfig, type DiscoveredAPI, KEYPAIR_SYMBOL, type KeypairWallet, type PaymentRecord, type SearchAPIsOptions, type WrapFetchOptions, createBudgetAccount, createEvmKeypairWallet, createKeypairWallet, isEvmKeypairWallet, isKeypairWallet, searchAPIs, wrapFetch };
326
+ export { AccessPassClientConfig, type BudgetAccount, type BudgetAccountConfig, type BudgetConfig, KEYPAIR_SYMBOL, type KeypairWallet, type PaymentRecord, type WrapFetchOptions, createBudgetAccount, createEvmKeypairWallet, createKeypairWallet, isEvmKeypairWallet, isKeypairWallet, wrapFetch };
@@ -785,21 +785,51 @@ var EvmAdapter = class {
785
785
  });
786
786
  const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
787
787
  const currentAllowance = await this.readAllowance(url, asset, wallet.address, PERMIT2_ADDRESS);
788
+ let approvalExtension;
788
789
  if (currentAllowance < BigInt(amount)) {
789
- if (!wallet.sendTransaction) {
790
+ const approveData = this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256);
791
+ if (wallet.signTransaction) {
792
+ this.log(`Signing Permit2 approval for relay (current allowance: ${currentAllowance})`);
793
+ const chainId2 = this.getChainId(accept.network);
794
+ const gasPrice = await this.readGasPrice(url);
795
+ const nonce2 = await this.readNonce(url, wallet.address);
796
+ const signedTx = await wallet.signTransaction({
797
+ to: asset,
798
+ data: approveData,
799
+ chainId: chainId2,
800
+ gas: 50000n,
801
+ // standard ERC-20 approve
802
+ gasPrice,
803
+ nonce: nonce2
804
+ });
805
+ approvalExtension = {
806
+ erc20ApprovalGasSponsoring: {
807
+ info: {
808
+ from: wallet.address,
809
+ asset,
810
+ spender: PERMIT2_ADDRESS,
811
+ amount: MAX_UINT256.toString(),
812
+ signedTransaction: signedTx,
813
+ version: "1"
814
+ }
815
+ }
816
+ };
817
+ this.log("Permit2 approval signed for facilitator relay");
818
+ } else if (wallet.sendTransaction) {
819
+ this.log(`Approving Permit2 directly (current allowance: ${currentAllowance})`);
820
+ const approveTxHash = await wallet.sendTransaction({
821
+ to: asset,
822
+ data: approveData,
823
+ value: 0n
824
+ });
825
+ this.log(`Permit2 approval tx sent: ${approveTxHash}`);
826
+ await this.waitForReceipt(url, approveTxHash);
827
+ this.log("Permit2 approval confirmed");
828
+ } else {
790
829
  throw new Error(
791
- "Permit2 payments require a wallet that supports sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
830
+ "Permit2 payments require a wallet that supports signTransaction or sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
792
831
  );
793
832
  }
794
- this.log(`Approving Permit2 for ${asset} (current allowance: ${currentAllowance})`);
795
- const approveTxHash = await wallet.sendTransaction({
796
- to: asset,
797
- data: this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256),
798
- value: 0n
799
- });
800
- this.log(`Permit2 approval tx sent: ${approveTxHash}`);
801
- await this.waitForReceipt(url, approveTxHash);
802
- this.log("Permit2 approval confirmed");
803
833
  } else {
804
834
  this.log("Sufficient Permit2 allowance, skipping approval");
805
835
  }
@@ -854,7 +884,8 @@ var EvmAdapter = class {
854
884
  };
855
885
  return {
856
886
  serialized: JSON.stringify(payload),
857
- signature
887
+ signature,
888
+ extensions: approvalExtension
858
889
  };
859
890
  }
860
891
  /**
@@ -923,6 +954,43 @@ var EvmAdapter = class {
923
954
  }
924
955
  throw new Error(`Approval transaction receipt timeout after ${timeoutMs}ms: ${txHash}`);
925
956
  }
957
+ /**
958
+ * Read gas price via eth_gasPrice RPC call.
959
+ */
960
+ async readGasPrice(rpcUrl) {
961
+ try {
962
+ const response = await fetch(rpcUrl, {
963
+ method: "POST",
964
+ headers: { "Content-Type": "application/json" },
965
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_gasPrice", params: [] })
966
+ });
967
+ const result = await response.json();
968
+ return result.result ? BigInt(result.result) : 50000000n;
969
+ } catch {
970
+ return 50000000n;
971
+ }
972
+ }
973
+ /**
974
+ * Read transaction count (nonce) via eth_getTransactionCount RPC call.
975
+ */
976
+ async readNonce(rpcUrl, address) {
977
+ try {
978
+ const response = await fetch(rpcUrl, {
979
+ method: "POST",
980
+ headers: { "Content-Type": "application/json" },
981
+ body: JSON.stringify({
982
+ jsonrpc: "2.0",
983
+ id: 1,
984
+ method: "eth_getTransactionCount",
985
+ params: [address, "latest"]
986
+ })
987
+ });
988
+ const result = await response.json();
989
+ return result.result ? parseInt(result.result, 16) : 0;
990
+ } catch {
991
+ return 0;
992
+ }
993
+ }
926
994
  /**
927
995
  * Calculate how much to approve based on the facilitator's approval strategy.
928
996
  * Buffered approvals reduce the number of on-chain approval txs for micropayments.
@@ -1184,6 +1252,9 @@ function createX402Client(config) {
1184
1252
  accepted: accept,
1185
1253
  payload
1186
1254
  };
1255
+ if (signedTx.extensions) {
1256
+ paymentSignature.extensions = signedTx.extensions;
1257
+ }
1187
1258
  const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
1188
1259
  const passResponse = await customFetch(passUrl, {
1189
1260
  ...init,
@@ -1362,6 +1433,9 @@ function createX402Client(config) {
1362
1433
  accepted: accept,
1363
1434
  payload
1364
1435
  };
1436
+ if (signedTx.extensions) {
1437
+ paymentSignature.extensions = signedTx.extensions;
1438
+ }
1365
1439
  const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
1366
1440
  log("Retrying request with payment...");
1367
1441
  const retryResponse = await fetchWithRetry(input, {
@@ -1490,7 +1564,16 @@ async function createEvmKeypairWallet(privateKey) {
1490
1564
  const account = privateKeyToAccount(normalizedKey);
1491
1565
  return {
1492
1566
  address: account.address,
1493
- signTypedData: (params) => account.signTypedData(params)
1567
+ signTypedData: (params) => account.signTypedData(params),
1568
+ signTransaction: (params) => account.signTransaction({
1569
+ to: params.to,
1570
+ data: params.data,
1571
+ chainId: params.chainId,
1572
+ gas: params.gas,
1573
+ gasPrice: params.gasPrice,
1574
+ nonce: params.nonce,
1575
+ type: "legacy"
1576
+ })
1494
1577
  };
1495
1578
  }
1496
1579
  function isEvmKeypairWallet(wallet) {
@@ -1557,56 +1640,7 @@ function wrapFetch(fetchImpl, options) {
1557
1640
  }
1558
1641
 
1559
1642
  // src/client/discovery.ts
1560
- var DEFAULT_MARKETPLACE = "https://x402.dexter.cash/api/facilitator/marketplace/resources";
1561
- async function searchAPIs(options = {}) {
1562
- const {
1563
- query,
1564
- category,
1565
- network,
1566
- maxPrice,
1567
- verifiedOnly,
1568
- sort = "marketplace",
1569
- limit = 20,
1570
- marketplaceUrl = DEFAULT_MARKETPLACE
1571
- } = options;
1572
- const params = new URLSearchParams();
1573
- if (query) params.set("search", query);
1574
- if (category) params.set("category", category);
1575
- if (network) params.set("network", network);
1576
- if (maxPrice !== void 0) params.set("maxPrice", String(maxPrice));
1577
- if (verifiedOnly) params.set("verified", "true");
1578
- params.set("sort", sort);
1579
- params.set("order", "desc");
1580
- params.set("limit", String(Math.min(limit, 50)));
1581
- const url = `${marketplaceUrl}?${params.toString()}`;
1582
- const response = await fetch(url, {
1583
- headers: { "Accept": "application/json" },
1584
- signal: AbortSignal.timeout(15e3)
1585
- });
1586
- if (!response.ok) {
1587
- throw new Error(`Marketplace search failed: ${response.status}`);
1588
- }
1589
- const data = await response.json();
1590
- if (!data.resources) return [];
1591
- return data.resources.map((r) => ({
1592
- name: r.displayName || r.resourceUrl,
1593
- url: r.resourceUrl,
1594
- method: r.method || "GET",
1595
- price: r.priceLabel || (r.priceUsdc ? `$${r.priceUsdc.toFixed(4)}` : "free"),
1596
- priceUsdc: r.priceUsdc ?? null,
1597
- network: r.priceNetwork ?? null,
1598
- description: r.description || "",
1599
- category: r.category || "uncategorized",
1600
- qualityScore: r.qualityScore ?? null,
1601
- verified: r.verificationStatus === "pass",
1602
- totalCalls: r.totalSettlements || 0,
1603
- totalVolume: r.totalVolumeUsdc ? `$${r.totalVolumeUsdc.toLocaleString("en-US", { minimumFractionDigits: 2 })}` : null,
1604
- seller: r.seller?.displayName ?? null,
1605
- sellerReputation: r.reputationScore ?? null,
1606
- authRequired: r.authRequired || false,
1607
- lastActive: r.lastSettlementAt ?? null
1608
- }));
1609
- }
1643
+ import { capabilitySearch } from "@dexterai/x402-core";
1610
1644
 
1611
1645
  // src/client/budget-account.ts
1612
1646
  function createBudgetAccount(config) {
@@ -1742,6 +1776,7 @@ export {
1742
1776
  SOLANA_MAINNET,
1743
1777
  USDC_MINT,
1744
1778
  X402Error,
1779
+ capabilitySearch,
1745
1780
  createBudgetAccount,
1746
1781
  createEvmAdapter,
1747
1782
  createEvmKeypairWallet,
@@ -1754,6 +1789,5 @@ export {
1754
1789
  getSponsoredRecommendations,
1755
1790
  isEvmKeypairWallet,
1756
1791
  isKeypairWallet,
1757
- searchAPIs,
1758
1792
  wrapFetch
1759
1793
  };
@@ -655,21 +655,51 @@ var EvmAdapter = class {
655
655
  });
656
656
  const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
657
657
  const currentAllowance = await this.readAllowance(url, asset, wallet.address, PERMIT2_ADDRESS);
658
+ let approvalExtension;
658
659
  if (currentAllowance < BigInt(amount)) {
659
- if (!wallet.sendTransaction) {
660
+ const approveData = this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256);
661
+ if (wallet.signTransaction) {
662
+ this.log(`Signing Permit2 approval for relay (current allowance: ${currentAllowance})`);
663
+ const chainId2 = this.getChainId(accept.network);
664
+ const gasPrice = await this.readGasPrice(url);
665
+ const nonce2 = await this.readNonce(url, wallet.address);
666
+ const signedTx = await wallet.signTransaction({
667
+ to: asset,
668
+ data: approveData,
669
+ chainId: chainId2,
670
+ gas: 50000n,
671
+ // standard ERC-20 approve
672
+ gasPrice,
673
+ nonce: nonce2
674
+ });
675
+ approvalExtension = {
676
+ erc20ApprovalGasSponsoring: {
677
+ info: {
678
+ from: wallet.address,
679
+ asset,
680
+ spender: PERMIT2_ADDRESS,
681
+ amount: MAX_UINT256.toString(),
682
+ signedTransaction: signedTx,
683
+ version: "1"
684
+ }
685
+ }
686
+ };
687
+ this.log("Permit2 approval signed for facilitator relay");
688
+ } else if (wallet.sendTransaction) {
689
+ this.log(`Approving Permit2 directly (current allowance: ${currentAllowance})`);
690
+ const approveTxHash = await wallet.sendTransaction({
691
+ to: asset,
692
+ data: approveData,
693
+ value: 0n
694
+ });
695
+ this.log(`Permit2 approval tx sent: ${approveTxHash}`);
696
+ await this.waitForReceipt(url, approveTxHash);
697
+ this.log("Permit2 approval confirmed");
698
+ } else {
660
699
  throw new Error(
661
- "Permit2 payments require a wallet that supports sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
700
+ "Permit2 payments require a wallet that supports signTransaction or sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
662
701
  );
663
702
  }
664
- this.log(`Approving Permit2 for ${asset} (current allowance: ${currentAllowance})`);
665
- const approveTxHash = await wallet.sendTransaction({
666
- to: asset,
667
- data: this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256),
668
- value: 0n
669
- });
670
- this.log(`Permit2 approval tx sent: ${approveTxHash}`);
671
- await this.waitForReceipt(url, approveTxHash);
672
- this.log("Permit2 approval confirmed");
673
703
  } else {
674
704
  this.log("Sufficient Permit2 allowance, skipping approval");
675
705
  }
@@ -724,7 +754,8 @@ var EvmAdapter = class {
724
754
  };
725
755
  return {
726
756
  serialized: JSON.stringify(payload),
727
- signature
757
+ signature,
758
+ extensions: approvalExtension
728
759
  };
729
760
  }
730
761
  /**
@@ -793,6 +824,43 @@ var EvmAdapter = class {
793
824
  }
794
825
  throw new Error(`Approval transaction receipt timeout after ${timeoutMs}ms: ${txHash}`);
795
826
  }
827
+ /**
828
+ * Read gas price via eth_gasPrice RPC call.
829
+ */
830
+ async readGasPrice(rpcUrl) {
831
+ try {
832
+ const response = await fetch(rpcUrl, {
833
+ method: "POST",
834
+ headers: { "Content-Type": "application/json" },
835
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_gasPrice", params: [] })
836
+ });
837
+ const result = await response.json();
838
+ return result.result ? BigInt(result.result) : 50000000n;
839
+ } catch {
840
+ return 50000000n;
841
+ }
842
+ }
843
+ /**
844
+ * Read transaction count (nonce) via eth_getTransactionCount RPC call.
845
+ */
846
+ async readNonce(rpcUrl, address) {
847
+ try {
848
+ const response = await fetch(rpcUrl, {
849
+ method: "POST",
850
+ headers: { "Content-Type": "application/json" },
851
+ body: JSON.stringify({
852
+ jsonrpc: "2.0",
853
+ id: 1,
854
+ method: "eth_getTransactionCount",
855
+ params: [address, "latest"]
856
+ })
857
+ });
858
+ const result = await response.json();
859
+ return result.result ? parseInt(result.result, 16) : 0;
860
+ } catch {
861
+ return 0;
862
+ }
863
+ }
796
864
  /**
797
865
  * Calculate how much to approve based on the facilitator's approval strategy.
798
866
  * Buffered approvals reduce the number of on-chain approval txs for micropayments.
@@ -1054,6 +1122,9 @@ function createX402Client(config) {
1054
1122
  accepted: accept,
1055
1123
  payload
1056
1124
  };
1125
+ if (signedTx.extensions) {
1126
+ paymentSignature.extensions = signedTx.extensions;
1127
+ }
1057
1128
  const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
1058
1129
  const passResponse = await customFetch(passUrl, {
1059
1130
  ...init,
@@ -1232,6 +1303,9 @@ function createX402Client(config) {
1232
1303
  accepted: accept,
1233
1304
  payload
1234
1305
  };
1306
+ if (signedTx.extensions) {
1307
+ paymentSignature.extensions = signedTx.extensions;
1308
+ }
1235
1309
  const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
1236
1310
  log("Retrying request with payment...");
1237
1311
  const retryResponse = await fetchWithRetry(input, {
@@ -1,6 +1,6 @@
1
- import { a as X402Client } from '../sponsored-access-DAVzu4x6.cjs';
2
- export { f as fireImpressionBeacon, b as getSponsoredRecommendations } from '../sponsored-access-DAVzu4x6.cjs';
3
- import { W as WalletSet, d as BalanceInfo } from '../types-D1u7iu8n.cjs';
1
+ import { a as X402Client } from '../sponsored-access-CE7WpV5b.cjs';
2
+ export { f as fireImpressionBeacon, b as getSponsoredRecommendations } from '../sponsored-access-CE7WpV5b.cjs';
3
+ import { W as WalletSet, d as BalanceInfo } from '../types-C_aQh02s.cjs';
4
4
  import { SponsoredRecommendation } from '@dexterai/x402-ads-types';
5
5
  export { SponsoredRecommendation } from '@dexterai/x402-ads-types';
6
6
  import { a as AccessPassTier } from '../types-_iT11DL0.cjs';
@@ -1,6 +1,6 @@
1
- import { a as X402Client } from '../sponsored-access-Lxa11w_X.js';
2
- export { f as fireImpressionBeacon, b as getSponsoredRecommendations } from '../sponsored-access-Lxa11w_X.js';
3
- import { W as WalletSet, d as BalanceInfo } from '../types-YQlJI5E3.js';
1
+ import { a as X402Client } from '../sponsored-access-BVoucsEW.js';
2
+ export { f as fireImpressionBeacon, b as getSponsoredRecommendations } from '../sponsored-access-BVoucsEW.js';
3
+ import { W as WalletSet, d as BalanceInfo } from '../types-DBS0XOsH.js';
4
4
  import { SponsoredRecommendation } from '@dexterai/x402-ads-types';
5
5
  export { SponsoredRecommendation } from '@dexterai/x402-ads-types';
6
6
  import { a as AccessPassTier } from '../types-_iT11DL0.js';
@@ -628,21 +628,51 @@ var EvmAdapter = class {
628
628
  });
629
629
  const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
630
630
  const currentAllowance = await this.readAllowance(url, asset, wallet.address, PERMIT2_ADDRESS);
631
+ let approvalExtension;
631
632
  if (currentAllowance < BigInt(amount)) {
632
- if (!wallet.sendTransaction) {
633
+ const approveData = this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256);
634
+ if (wallet.signTransaction) {
635
+ this.log(`Signing Permit2 approval for relay (current allowance: ${currentAllowance})`);
636
+ const chainId2 = this.getChainId(accept.network);
637
+ const gasPrice = await this.readGasPrice(url);
638
+ const nonce2 = await this.readNonce(url, wallet.address);
639
+ const signedTx = await wallet.signTransaction({
640
+ to: asset,
641
+ data: approveData,
642
+ chainId: chainId2,
643
+ gas: 50000n,
644
+ // standard ERC-20 approve
645
+ gasPrice,
646
+ nonce: nonce2
647
+ });
648
+ approvalExtension = {
649
+ erc20ApprovalGasSponsoring: {
650
+ info: {
651
+ from: wallet.address,
652
+ asset,
653
+ spender: PERMIT2_ADDRESS,
654
+ amount: MAX_UINT256.toString(),
655
+ signedTransaction: signedTx,
656
+ version: "1"
657
+ }
658
+ }
659
+ };
660
+ this.log("Permit2 approval signed for facilitator relay");
661
+ } else if (wallet.sendTransaction) {
662
+ this.log(`Approving Permit2 directly (current allowance: ${currentAllowance})`);
663
+ const approveTxHash = await wallet.sendTransaction({
664
+ to: asset,
665
+ data: approveData,
666
+ value: 0n
667
+ });
668
+ this.log(`Permit2 approval tx sent: ${approveTxHash}`);
669
+ await this.waitForReceipt(url, approveTxHash);
670
+ this.log("Permit2 approval confirmed");
671
+ } else {
633
672
  throw new Error(
634
- "Permit2 payments require a wallet that supports sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
673
+ "Permit2 payments require a wallet that supports signTransaction or sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support."
635
674
  );
636
675
  }
637
- this.log(`Approving Permit2 for ${asset} (current allowance: ${currentAllowance})`);
638
- const approveTxHash = await wallet.sendTransaction({
639
- to: asset,
640
- data: this.encodeApprove(PERMIT2_ADDRESS, MAX_UINT256),
641
- value: 0n
642
- });
643
- this.log(`Permit2 approval tx sent: ${approveTxHash}`);
644
- await this.waitForReceipt(url, approveTxHash);
645
- this.log("Permit2 approval confirmed");
646
676
  } else {
647
677
  this.log("Sufficient Permit2 allowance, skipping approval");
648
678
  }
@@ -697,7 +727,8 @@ var EvmAdapter = class {
697
727
  };
698
728
  return {
699
729
  serialized: JSON.stringify(payload),
700
- signature
730
+ signature,
731
+ extensions: approvalExtension
701
732
  };
702
733
  }
703
734
  /**
@@ -766,6 +797,43 @@ var EvmAdapter = class {
766
797
  }
767
798
  throw new Error(`Approval transaction receipt timeout after ${timeoutMs}ms: ${txHash}`);
768
799
  }
800
+ /**
801
+ * Read gas price via eth_gasPrice RPC call.
802
+ */
803
+ async readGasPrice(rpcUrl) {
804
+ try {
805
+ const response = await fetch(rpcUrl, {
806
+ method: "POST",
807
+ headers: { "Content-Type": "application/json" },
808
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_gasPrice", params: [] })
809
+ });
810
+ const result = await response.json();
811
+ return result.result ? BigInt(result.result) : 50000000n;
812
+ } catch {
813
+ return 50000000n;
814
+ }
815
+ }
816
+ /**
817
+ * Read transaction count (nonce) via eth_getTransactionCount RPC call.
818
+ */
819
+ async readNonce(rpcUrl, address) {
820
+ try {
821
+ const response = await fetch(rpcUrl, {
822
+ method: "POST",
823
+ headers: { "Content-Type": "application/json" },
824
+ body: JSON.stringify({
825
+ jsonrpc: "2.0",
826
+ id: 1,
827
+ method: "eth_getTransactionCount",
828
+ params: [address, "latest"]
829
+ })
830
+ });
831
+ const result = await response.json();
832
+ return result.result ? parseInt(result.result, 16) : 0;
833
+ } catch {
834
+ return 0;
835
+ }
836
+ }
769
837
  /**
770
838
  * Calculate how much to approve based on the facilitator's approval strategy.
771
839
  * Buffered approvals reduce the number of on-chain approval txs for micropayments.
@@ -1027,6 +1095,9 @@ function createX402Client(config) {
1027
1095
  accepted: accept,
1028
1096
  payload
1029
1097
  };
1098
+ if (signedTx.extensions) {
1099
+ paymentSignature.extensions = signedTx.extensions;
1100
+ }
1030
1101
  const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
1031
1102
  const passResponse = await customFetch(passUrl, {
1032
1103
  ...init,
@@ -1205,6 +1276,9 @@ function createX402Client(config) {
1205
1276
  accepted: accept,
1206
1277
  payload
1207
1278
  };
1279
+ if (signedTx.extensions) {
1280
+ paymentSignature.extensions = signedTx.extensions;
1281
+ }
1208
1282
  const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
1209
1283
  log("Retrying request with payment...");
1210
1284
  const retryResponse = await fetchWithRetry(input, {
@@ -1,4 +1,4 @@
1
- import { C as ChainAdapter, W as WalletSet } from './types-YQlJI5E3.js';
1
+ import { C as ChainAdapter, W as WalletSet } from './types-DBS0XOsH.js';
2
2
  import { A as AccessPassClientConfig, P as PaymentAccept } from './types-_iT11DL0.js';
3
3
  import { SponsoredRecommendation, SponsoredAccessSettlementInfo } from '@dexterai/x402-ads-types';
4
4
 
@@ -1,4 +1,4 @@
1
- import { C as ChainAdapter, W as WalletSet } from './types-D1u7iu8n.cjs';
1
+ import { C as ChainAdapter, W as WalletSet } from './types-C_aQh02s.cjs';
2
2
  import { A as AccessPassClientConfig, P as PaymentAccept } from './types-_iT11DL0.cjs';
3
3
  import { SponsoredRecommendation, SponsoredAccessSettlementInfo } from '@dexterai/x402-ads-types';
4
4