@dexterai/x402 1.9.4 → 2.0.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.
@@ -511,4 +511,3 @@ function findAdapter(adapters, network) {
511
511
  isKnownUSDC,
512
512
  isSolanaWallet
513
513
  });
514
- //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,5 @@
1
- import { C as ChainAdapter } from '../types-CfKflCZO.cjs';
2
- export { A as AdapterConfig, B as BalanceInfo, G as GenericWallet, S as SignedTransaction, W as WalletSet } from '../types-CfKflCZO.cjs';
3
- import { b as SolanaAdapter, d as EvmAdapter } from '../solana-BcOfK6Eq.cjs';
4
- export { A as ARBITRUM_ONE, k as AVALANCHE, B as BASE_MAINNET, j as BASE_SEPOLIA, n as ETHEREUM_MAINNET, E as EvmWallet, O as OPTIMISM, P as POLYGON, l as SKALE_BASE, m as SKALE_BASE_SEPOLIA, e as SOLANA_DEVNET, S as SOLANA_MAINNET, f as SOLANA_TESTNET, g as SolanaWallet, U as USDC_ADDRESSES, a as createEvmAdapter, c as createSolanaAdapter, h as isEvmWallet, i as isSolanaWallet } from '../solana-BcOfK6Eq.cjs';
1
+ import { e as SolanaAdapter, f as EvmAdapter, C as ChainAdapter } from '../types-DWhpiOBD.cjs';
2
+ export { m as ARBITRUM_ONE, n as AVALANCHE, A as AdapterConfig, B as BASE_MAINNET, l as BASE_SEPOLIA, d as BalanceInfo, q as ETHEREUM_MAINNET, E as EvmWallet, G as GenericWallet, O as OPTIMISM, P as POLYGON, o as SKALE_BASE, p as SKALE_BASE_SEPOLIA, h as SOLANA_DEVNET, b as SOLANA_MAINNET, j as SOLANA_TESTNET, g as SignedTransaction, S as SolanaWallet, U as USDC_ADDRESSES, W as WalletSet, a as createEvmAdapter, c as createSolanaAdapter, k as isEvmWallet, i as isSolanaWallet } from '../types-DWhpiOBD.cjs';
5
3
  import '../types-CjLMR7qs.cjs';
6
4
 
7
5
  /**
@@ -1,7 +1,5 @@
1
- import { C as ChainAdapter } from '../types-BIHhO2-I.js';
2
- export { A as AdapterConfig, B as BalanceInfo, G as GenericWallet, S as SignedTransaction, W as WalletSet } from '../types-BIHhO2-I.js';
3
- import { b as SolanaAdapter, d as EvmAdapter } from '../solana-Cxr5byPa.js';
4
- export { A as ARBITRUM_ONE, k as AVALANCHE, B as BASE_MAINNET, j as BASE_SEPOLIA, n as ETHEREUM_MAINNET, E as EvmWallet, O as OPTIMISM, P as POLYGON, l as SKALE_BASE, m as SKALE_BASE_SEPOLIA, e as SOLANA_DEVNET, S as SOLANA_MAINNET, f as SOLANA_TESTNET, g as SolanaWallet, U as USDC_ADDRESSES, a as createEvmAdapter, c as createSolanaAdapter, h as isEvmWallet, i as isSolanaWallet } from '../solana-Cxr5byPa.js';
1
+ import { e as SolanaAdapter, f as EvmAdapter, C as ChainAdapter } from '../types-D1TGACsL.js';
2
+ export { m as ARBITRUM_ONE, n as AVALANCHE, A as AdapterConfig, B as BASE_MAINNET, l as BASE_SEPOLIA, d as BalanceInfo, q as ETHEREUM_MAINNET, E as EvmWallet, G as GenericWallet, O as OPTIMISM, P as POLYGON, o as SKALE_BASE, p as SKALE_BASE_SEPOLIA, h as SOLANA_DEVNET, b as SOLANA_MAINNET, j as SOLANA_TESTNET, g as SignedTransaction, S as SolanaWallet, U as USDC_ADDRESSES, W as WalletSet, a as createEvmAdapter, c as createSolanaAdapter, k as isEvmWallet, i as isSolanaWallet } from '../types-D1TGACsL.js';
5
3
  import '../types-CjLMR7qs.js';
6
4
 
7
5
  /**
@@ -466,4 +466,3 @@ export {
466
466
  isKnownUSDC,
467
467
  isSolanaWallet
468
468
  };
469
- //# sourceMappingURL=index.js.map
@@ -191,6 +191,7 @@ __export(client_exports, {
191
191
  SOLANA_MAINNET: () => SOLANA_MAINNET,
192
192
  USDC_MINT: () => USDC_MINT,
193
193
  X402Error: () => X402Error,
194
+ createBudgetAccount: () => createBudgetAccount,
194
195
  createEvmAdapter: () => createEvmAdapter,
195
196
  createEvmKeypairWallet: () => createEvmKeypairWallet,
196
197
  createKeypairWallet: () => createKeypairWallet,
@@ -202,6 +203,7 @@ __export(client_exports, {
202
203
  getSponsoredRecommendations: () => getSponsoredRecommendations,
203
204
  isEvmKeypairWallet: () => isEvmKeypairWallet,
204
205
  isKeypairWallet: () => isKeypairWallet,
206
+ searchAPIs: () => searchAPIs,
205
207
  wrapFetch: () => wrapFetch
206
208
  });
207
209
  module.exports = __toCommonJS(client_exports);
@@ -662,10 +664,33 @@ function createX402Client(config) {
662
664
  fetch: customFetch = globalThis.fetch,
663
665
  verbose = false,
664
666
  accessPass: accessPassConfig,
665
- onPaymentRequired
667
+ onPaymentRequired,
668
+ maxRetries = 0,
669
+ retryDelayMs = 500
666
670
  } = config;
667
671
  const log = verbose ? console.log.bind(console, "[x402]") : () => {
668
672
  };
673
+ async function fetchWithRetry(input, init) {
674
+ let lastError;
675
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
676
+ try {
677
+ const response = await customFetch(input, init);
678
+ if (response.status >= 502 && response.status <= 504 && attempt < maxRetries) {
679
+ log(`Retry ${attempt + 1}/${maxRetries}: server returned ${response.status}`);
680
+ await new Promise((r) => setTimeout(r, retryDelayMs * Math.pow(2, attempt)));
681
+ continue;
682
+ }
683
+ return response;
684
+ } catch (err) {
685
+ lastError = err;
686
+ if (attempt < maxRetries) {
687
+ log(`Retry ${attempt + 1}/${maxRetries}: ${err instanceof Error ? err.message : "network error"}`);
688
+ await new Promise((r) => setTimeout(r, retryDelayMs * Math.pow(2, attempt)));
689
+ }
690
+ }
691
+ }
692
+ throw lastError;
693
+ }
669
694
  const passCache = /* @__PURE__ */ new Map();
670
695
  function getCachedPass(url) {
671
696
  try {
@@ -865,7 +890,7 @@ function createX402Client(config) {
865
890
  }
866
891
  }
867
892
  }
868
- const response = await customFetch(input, init);
893
+ const response = await fetchWithRetry(input, init);
869
894
  if (response.status !== 402) {
870
895
  return response;
871
896
  }
@@ -1000,7 +1025,7 @@ function createX402Client(config) {
1000
1025
  };
1001
1026
  const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
1002
1027
  log("Retrying request with payment...");
1003
- const retryResponse = await customFetch(input, {
1028
+ const retryResponse = await fetchWithRetry(input, {
1004
1029
  ...init,
1005
1030
  headers: {
1006
1031
  ...init?.headers || {},
@@ -1144,7 +1169,8 @@ function wrapFetch(fetchImpl, options) {
1144
1169
  rpcUrls,
1145
1170
  maxAmountAtomic,
1146
1171
  verbose,
1147
- accessPass
1172
+ accessPass,
1173
+ onPaymentRequired
1148
1174
  } = options;
1149
1175
  if (!walletPrivateKey && !evmPrivateKey) {
1150
1176
  throw new Error("At least one wallet private key is required (walletPrivateKey or evmPrivateKey)");
@@ -1177,7 +1203,8 @@ function wrapFetch(fetchImpl, options) {
1177
1203
  maxAmountAtomic,
1178
1204
  fetch: fetchImpl,
1179
1205
  verbose,
1180
- accessPass
1206
+ accessPass,
1207
+ onPaymentRequired
1181
1208
  };
1182
1209
  const client = createX402Client(clientConfig);
1183
1210
  const clientFetch = client.fetch.bind(client);
@@ -1190,6 +1217,164 @@ function wrapFetch(fetchImpl, options) {
1190
1217
  return clientFetch;
1191
1218
  }
1192
1219
 
1220
+ // src/client/discovery.ts
1221
+ var DEFAULT_MARKETPLACE = "https://x402.dexter.cash/api/facilitator/marketplace/resources";
1222
+ async function searchAPIs(options = {}) {
1223
+ const {
1224
+ query,
1225
+ category,
1226
+ network,
1227
+ maxPrice,
1228
+ verifiedOnly,
1229
+ sort = "marketplace",
1230
+ limit = 20,
1231
+ marketplaceUrl = DEFAULT_MARKETPLACE
1232
+ } = options;
1233
+ const params = new URLSearchParams();
1234
+ if (query) params.set("search", query);
1235
+ if (category) params.set("category", category);
1236
+ if (network) params.set("network", network);
1237
+ if (maxPrice !== void 0) params.set("maxPrice", String(maxPrice));
1238
+ if (verifiedOnly) params.set("verified", "true");
1239
+ params.set("sort", sort);
1240
+ params.set("order", "desc");
1241
+ params.set("limit", String(Math.min(limit, 50)));
1242
+ const url = `${marketplaceUrl}?${params.toString()}`;
1243
+ const response = await fetch(url, {
1244
+ headers: { "Accept": "application/json" },
1245
+ signal: AbortSignal.timeout(15e3)
1246
+ });
1247
+ if (!response.ok) {
1248
+ throw new Error(`Marketplace search failed: ${response.status}`);
1249
+ }
1250
+ const data = await response.json();
1251
+ if (!data.resources) return [];
1252
+ return data.resources.map((r) => ({
1253
+ name: r.displayName || r.resourceUrl,
1254
+ url: r.resourceUrl,
1255
+ method: r.method || "GET",
1256
+ price: r.priceLabel || (r.priceUsdc ? `$${r.priceUsdc.toFixed(4)}` : "free"),
1257
+ priceUsdc: r.priceUsdc ?? null,
1258
+ network: r.priceNetwork ?? null,
1259
+ description: r.description || "",
1260
+ category: r.category || "uncategorized",
1261
+ qualityScore: r.qualityScore ?? null,
1262
+ verified: r.verificationStatus === "pass",
1263
+ totalCalls: r.totalSettlements || 0,
1264
+ totalVolume: r.totalVolumeUsdc ? `$${r.totalVolumeUsdc.toLocaleString("en-US", { minimumFractionDigits: 2 })}` : null,
1265
+ seller: r.seller?.displayName ?? null,
1266
+ sellerReputation: r.reputationScore ?? null,
1267
+ authRequired: r.authRequired || false,
1268
+ lastActive: r.lastSettlementAt ?? null
1269
+ }));
1270
+ }
1271
+
1272
+ // src/client/budget-account.ts
1273
+ function createBudgetAccount(config) {
1274
+ const { budget, allowedDomains, onPaymentRequired: userOnPayment, ...fetchOptions } = config;
1275
+ const totalBudget = parseFloat(budget.total);
1276
+ const perRequestMax = budget.perRequest ? parseFloat(budget.perRequest) : Infinity;
1277
+ const perHourMax = budget.perHour ? parseFloat(budget.perHour) : Infinity;
1278
+ if (isNaN(totalBudget) || totalBudget <= 0) {
1279
+ throw new Error("budget.total must be a positive number");
1280
+ }
1281
+ let ledger = [];
1282
+ let pendingAmount = 0;
1283
+ function getSpent() {
1284
+ return ledger.reduce((sum, r) => sum + r.amount, 0);
1285
+ }
1286
+ function getHourlySpend() {
1287
+ const cutoff = Date.now() - 36e5;
1288
+ return ledger.filter((r) => r.timestamp >= cutoff).reduce((sum, r) => sum + r.amount, 0);
1289
+ }
1290
+ const innerFetch = wrapFetch(fetch, {
1291
+ ...fetchOptions,
1292
+ onPaymentRequired: async (accept) => {
1293
+ const decimals = accept.extra?.decimals ?? 6;
1294
+ const amountUsd = Number(accept.amount) / Math.pow(10, decimals);
1295
+ if (amountUsd > perRequestMax) {
1296
+ throw new X402Error(
1297
+ "amount_exceeds_max",
1298
+ `$${amountUsd.toFixed(4)} exceeds per-request limit of $${perRequestMax.toFixed(2)}`
1299
+ );
1300
+ }
1301
+ const spent = getSpent();
1302
+ if (spent + amountUsd > totalBudget) {
1303
+ throw new X402Error(
1304
+ "amount_exceeds_max",
1305
+ `Budget exceeded. Spent $${spent.toFixed(2)} of $${totalBudget.toFixed(2)}, payment: $${amountUsd.toFixed(4)}`
1306
+ );
1307
+ }
1308
+ const hourly = getHourlySpend();
1309
+ if (hourly + amountUsd > perHourMax) {
1310
+ throw new X402Error(
1311
+ "amount_exceeds_max",
1312
+ `Hourly limit ($${perHourMax.toFixed(2)}) exceeded. Spent $${hourly.toFixed(2)} this hour`
1313
+ );
1314
+ }
1315
+ pendingAmount = amountUsd;
1316
+ if (userOnPayment) return userOnPayment(accept);
1317
+ return true;
1318
+ }
1319
+ });
1320
+ const budgetFetch = (async (input, init) => {
1321
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
1322
+ let domain = "unknown";
1323
+ try {
1324
+ domain = new URL(url).hostname;
1325
+ } catch {
1326
+ }
1327
+ if (allowedDomains) {
1328
+ if (!allowedDomains.some((d) => domain === d || domain.endsWith(`.${d}`))) {
1329
+ throw new X402Error("payment_rejected", `Domain "${domain}" not in allowed domains`);
1330
+ }
1331
+ }
1332
+ pendingAmount = 0;
1333
+ const response = await innerFetch(input, init);
1334
+ if (pendingAmount > 0) {
1335
+ let network = "unknown";
1336
+ const paymentHeader = response.headers.get("PAYMENT-RESPONSE");
1337
+ if (paymentHeader) {
1338
+ try {
1339
+ const decoded = JSON.parse(atob(paymentHeader));
1340
+ network = decoded.network || network;
1341
+ } catch {
1342
+ }
1343
+ }
1344
+ ledger.push({ amount: pendingAmount, domain, network, timestamp: Date.now() });
1345
+ pendingAmount = 0;
1346
+ }
1347
+ return response;
1348
+ });
1349
+ return {
1350
+ fetch: budgetFetch,
1351
+ get spent() {
1352
+ return `$${getSpent().toFixed(2)}`;
1353
+ },
1354
+ get remaining() {
1355
+ return `$${(totalBudget - getSpent()).toFixed(2)}`;
1356
+ },
1357
+ get payments() {
1358
+ return ledger.length;
1359
+ },
1360
+ get spentAmount() {
1361
+ return getSpent();
1362
+ },
1363
+ get remainingAmount() {
1364
+ return totalBudget - getSpent();
1365
+ },
1366
+ get ledger() {
1367
+ return ledger;
1368
+ },
1369
+ get hourlySpend() {
1370
+ return getHourlySpend();
1371
+ },
1372
+ reset() {
1373
+ ledger = [];
1374
+ }
1375
+ };
1376
+ }
1377
+
1193
1378
  // src/client/sponsored-access.ts
1194
1379
  function getSponsoredAccessInfo(response) {
1195
1380
  const receipt = getPaymentReceipt(response);
@@ -1219,6 +1404,7 @@ async function fireImpressionBeacon(response) {
1219
1404
  SOLANA_MAINNET,
1220
1405
  USDC_MINT,
1221
1406
  X402Error,
1407
+ createBudgetAccount,
1222
1408
  createEvmAdapter,
1223
1409
  createEvmKeypairWallet,
1224
1410
  createKeypairWallet,
@@ -1230,6 +1416,6 @@ async function fireImpressionBeacon(response) {
1230
1416
  getSponsoredRecommendations,
1231
1417
  isEvmKeypairWallet,
1232
1418
  isKeypairWallet,
1419
+ searchAPIs,
1233
1420
  wrapFetch
1234
1421
  });
1235
- //# sourceMappingURL=index.cjs.map
@@ -1,32 +1,11 @@
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-Br6YPA-m.cjs';
2
- import { A as AccessPassClientConfig } from '../types-CjLMR7qs.cjs';
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-BgEDLg_H.cjs';
2
+ import { A as AccessPassClientConfig, P as PaymentAccept } from '../types-CjLMR7qs.cjs';
3
3
  export { b as AccessPassInfo, a as AccessPassTier, D as DEXTER_FACILITATOR_URL, U as USDC_MINT, X as X402Error } from '../types-CjLMR7qs.cjs';
4
- import { Transaction, VersionedTransaction, Keypair } from '@solana/web3.js';
5
- import { E as EvmWallet } from '../solana-BcOfK6Eq.cjs';
6
- export { B as BASE_MAINNET, S as SOLANA_MAINNET, a as createEvmAdapter, c as createSolanaAdapter } from '../solana-BcOfK6Eq.cjs';
7
- export { C as ChainAdapter, W as WalletSet } from '../types-CfKflCZO.cjs';
4
+ import { Keypair } from '@solana/web3.js';
5
+ import { S as SolanaWallet, E as EvmWallet } from '../types-DWhpiOBD.cjs';
6
+ export { B as BASE_MAINNET, C as ChainAdapter, b as SOLANA_MAINNET, W as WalletSet, a as createEvmAdapter, c as createSolanaAdapter } from '../types-DWhpiOBD.cjs';
8
7
  export { SponsoredAccessSettlementInfo, SponsoredRecommendation } from '@dexterai/x402-ads-types';
9
8
 
10
- /**
11
- * Simple Fetch Wrapper for Node.js
12
- *
13
- * The easiest way to make x402 payments from Node.js scripts.
14
- * Just provide a private key and it handles everything automatically.
15
- *
16
- * @example
17
- * ```typescript
18
- * import { wrapFetch } from '@dexterai/x402/client';
19
- *
20
- * const x402Fetch = wrapFetch(fetch, {
21
- * walletPrivateKey: process.env.SOLANA_PRIVATE_KEY!,
22
- * });
23
- *
24
- * // Make a paid request - payment happens automatically
25
- * const response = await x402Fetch('https://api.example.com/protected');
26
- * const data = await response.json();
27
- * ```
28
- */
29
-
30
9
  /**
31
10
  * Options for wrapFetch
32
11
  */
@@ -81,6 +60,11 @@ interface WrapFetchOptions {
81
60
  * ```
82
61
  */
83
62
  accessPass?: AccessPassClientConfig;
63
+ /**
64
+ * Called before signing a payment. Return true to proceed, false to reject.
65
+ * Used internally by Budget Accounts — can also be set directly.
66
+ */
67
+ onPaymentRequired?: (requirements: PaymentAccept) => boolean | Promise<boolean>;
84
68
  }
85
69
  /**
86
70
  * Wrap fetch with automatic x402 payment handling
@@ -138,15 +122,9 @@ declare function wrapFetch(fetchImpl: typeof globalThis.fetch, options: WrapFetc
138
122
  /** Symbol key for the underlying Keypair — prevents accidental exposure via console.log or JSON.stringify */
139
123
  declare const KEYPAIR_SYMBOL: unique symbol;
140
124
  /**
141
- * Keypair wallet interface (compatible with SDK's SolanaWallet)
125
+ * Keypair wallet interface extends SolanaWallet with safe Keypair access.
142
126
  */
143
- interface KeypairWallet {
144
- /** Public key with toBase58() method */
145
- publicKey: {
146
- toBase58(): string;
147
- };
148
- /** Sign a transaction */
149
- signTransaction<T extends Transaction | VersionedTransaction>(tx: T): Promise<T>;
127
+ interface KeypairWallet extends SolanaWallet {
150
128
  /**
151
129
  * Get the underlying Keypair. Accessed via Symbol to prevent accidental
152
130
  * exposure through console.log, JSON.stringify, or Object.keys.
@@ -259,4 +237,190 @@ declare function createEvmKeypairWallet(privateKey: string): Promise<EvmWallet>;
259
237
  */
260
238
  declare function isEvmKeypairWallet(wallet: unknown): wallet is EvmWallet;
261
239
 
262
- export { AccessPassClientConfig, KEYPAIR_SYMBOL, type KeypairWallet, type WrapFetchOptions, createEvmKeypairWallet, createKeypairWallet, isEvmKeypairWallet, isKeypairWallet, wrapFetch };
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
+ /**
342
+ * Budget Account — Autonomous Agent Spending Controls
343
+ *
344
+ * Wraps the x402 client with a spending limit, per-request cap,
345
+ * per-hour rate limit, and optional domain allowlist. Tracks cumulative
346
+ * spend and exposes remaining budget. When the budget is exhausted,
347
+ * requests throw instead of paying.
348
+ *
349
+ * @example
350
+ * ```typescript
351
+ * import { createBudgetAccount } from '@dexterai/x402/client';
352
+ *
353
+ * const agent = createBudgetAccount({
354
+ * walletPrivateKey: process.env.SOLANA_PRIVATE_KEY,
355
+ * budget: {
356
+ * total: '50.00', // $50 total budget
357
+ * perRequest: '1.00', // max $1 per request
358
+ * perHour: '10.00', // max $10/hour
359
+ * },
360
+ * allowedDomains: ['api.example.com', 'data.example.com'],
361
+ * });
362
+ *
363
+ * const response = await agent.fetch('https://api.example.com/data');
364
+ * console.log(agent.spent); // '$0.05'
365
+ * console.log(agent.remaining); // '$49.95'
366
+ * console.log(agent.payments); // 1
367
+ * ```
368
+ */
369
+
370
+ /** Budget configuration */
371
+ interface BudgetConfig {
372
+ /** Total spending limit in USD (e.g., '50.00') */
373
+ total: string;
374
+ /** Maximum amount per single request in USD (e.g., '1.00'). Optional. */
375
+ perRequest?: string;
376
+ /** Maximum spend per hour in USD (e.g., '10.00'). Optional. */
377
+ perHour?: string;
378
+ }
379
+ /** Budget Account configuration — extends WrapFetchOptions with spending controls */
380
+ interface BudgetAccountConfig extends WrapFetchOptions {
381
+ /** Spending limits */
382
+ budget: BudgetConfig;
383
+ /** Restrict payments to these domains only. If omitted, all domains allowed. */
384
+ allowedDomains?: string[];
385
+ }
386
+ /** A payment record in the spend ledger */
387
+ interface PaymentRecord {
388
+ /** Amount paid in USD */
389
+ amount: number;
390
+ /** Domain that was paid */
391
+ domain: string;
392
+ /** CAIP-2 network used */
393
+ network: string;
394
+ /** Timestamp (ms) */
395
+ timestamp: number;
396
+ }
397
+ /** Budget Account — fetch with spending controls */
398
+ interface BudgetAccount {
399
+ /** Payment-aware fetch with budget enforcement */
400
+ fetch: typeof globalThis.fetch;
401
+ /** Total amount spent (formatted, e.g., '$12.34') */
402
+ readonly spent: string;
403
+ /** Remaining budget (formatted, e.g., '$37.66') */
404
+ readonly remaining: string;
405
+ /** Number of payments made */
406
+ readonly payments: number;
407
+ /** Total spent as a raw number */
408
+ readonly spentAmount: number;
409
+ /** Remaining budget as a raw number */
410
+ readonly remainingAmount: number;
411
+ /** Full payment history */
412
+ readonly ledger: readonly PaymentRecord[];
413
+ /** Spend in the last hour */
414
+ readonly hourlySpend: number;
415
+ /** Reset the budget (clears all spend history) */
416
+ reset: () => void;
417
+ }
418
+ /**
419
+ * Create a budget-controlled fetch wrapper for autonomous agents.
420
+ *
421
+ * Enforces total spend limit, per-request cap, hourly rate limit,
422
+ * and domain allowlist. Every payment is tracked in an in-memory ledger.
423
+ */
424
+ declare function createBudgetAccount(config: BudgetAccountConfig): BudgetAccount;
425
+
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 };