@routstr/sdk 0.3.3 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/client/index.d.mts +9 -5
  2. package/dist/client/index.d.ts +9 -5
  3. package/dist/client/index.js +107 -136
  4. package/dist/client/index.js.map +1 -1
  5. package/dist/client/index.mjs +107 -136
  6. package/dist/client/index.mjs.map +1 -1
  7. package/dist/discovery/index.d.mts +8 -2
  8. package/dist/discovery/index.d.ts +8 -2
  9. package/dist/discovery/index.js +27 -16
  10. package/dist/discovery/index.js.map +1 -1
  11. package/dist/discovery/index.mjs +27 -16
  12. package/dist/discovery/index.mjs.map +1 -1
  13. package/dist/index.d.mts +10 -8
  14. package/dist/index.d.ts +10 -8
  15. package/dist/index.js +179 -193
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +178 -194
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/{interfaces-C5fLD3jB.d.mts → interfaces-Bp0Ngmqv.d.mts} +1 -1
  20. package/dist/{interfaces-BxDEka72.d.ts → interfaces-CIfd_phZ.d.ts} +1 -1
  21. package/dist/{interfaces-BWJJTCXO.d.mts → interfaces-Cxi8R4TT.d.mts} +1 -1
  22. package/dist/{interfaces-B62Rw-dd.d.ts → interfaces-D2FDCLyP.d.ts} +1 -1
  23. package/dist/storage/index.d.mts +9 -7
  24. package/dist/storage/index.d.ts +9 -7
  25. package/dist/storage/index.js +52 -37
  26. package/dist/storage/index.js.map +1 -1
  27. package/dist/storage/index.mjs +52 -37
  28. package/dist/storage/index.mjs.map +1 -1
  29. package/dist/{store-h7m23ffq.d.ts → store-BD5zF9Hp.d.ts} +4 -4
  30. package/dist/{store-DGeLPv9E.d.mts → store-CBSyK2qg.d.mts} +4 -4
  31. package/dist/{types-BYj_8c5c.d.mts → types-DPQM6tIG.d.mts} +10 -1
  32. package/dist/{types-BYj_8c5c.d.ts → types-DPQM6tIG.d.ts} +10 -1
  33. package/dist/wallet/index.d.mts +8 -6
  34. package/dist/wallet/index.d.ts +8 -6
  35. package/dist/wallet/index.js +80 -57
  36. package/dist/wallet/index.js.map +1 -1
  37. package/dist/wallet/index.mjs +80 -57
  38. package/dist/wallet/index.mjs.map +1 -1
  39. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8,6 +8,30 @@ var vanilla = require('zustand/vanilla');
8
8
  var stream = require('stream');
9
9
  var string_decoder = require('string_decoder');
10
10
 
11
+ // core/types.ts
12
+ function makeConsoleLogger(prefix) {
13
+ const fmt = (args) => prefix ? [prefix, ...args] : args;
14
+ return {
15
+ log: (...args) => console.log(...fmt(args)),
16
+ warn: (...args) => console.warn(...fmt(args)),
17
+ error: (...args) => console.error(...fmt(args)),
18
+ debug: (...args) => console.log(...fmt(args)),
19
+ child: (p) => makeConsoleLogger(prefix ? `${prefix}:${p}` : p)
20
+ };
21
+ }
22
+ var consoleLogger = makeConsoleLogger();
23
+ var noopLogger = {
24
+ log: () => {
25
+ },
26
+ warn: () => {
27
+ },
28
+ error: () => {
29
+ },
30
+ debug: () => {
31
+ },
32
+ child: () => noopLogger
33
+ };
34
+
11
35
  // core/errors.ts
12
36
  var InsufficientBalanceError = class extends Error {
13
37
  constructor(required, available, maxMintBalance = 0, maxMintUrl = "", customMessage) {
@@ -104,11 +128,13 @@ var ModelManager = class _ModelManager {
104
128
  this.cacheTTL = config.cacheTTL || 210 * 60 * 1e3;
105
129
  this.includeProviderUrls = config.includeProviderUrls || [];
106
130
  this.excludeProviderUrls = config.excludeProviderUrls || [];
131
+ this.logger = (config.logger ?? consoleLogger).child("ModelManager");
107
132
  }
108
133
  cacheTTL;
109
134
  providerDirectoryUrl;
110
135
  includeProviderUrls;
111
136
  excludeProviderUrls;
137
+ logger;
112
138
  /**
113
139
  * Get the list of bootstrapped provider base URLs
114
140
  * @returns Array of provider base URLs
@@ -154,7 +180,7 @@ var ModelManager = class _ModelManager {
154
180
  return filtered;
155
181
  }
156
182
  } catch (e) {
157
- console.warn("Nostr bootstrap failed, falling back to HTTP:", e);
183
+ this.logger.warn("Nostr bootstrap failed, falling back to HTTP:", e);
158
184
  }
159
185
  return this.bootstrapFromHttp(torMode, forceRefresh);
160
186
  }
@@ -230,10 +256,7 @@ var ModelManager = class _ModelManager {
230
256
  }
231
257
  }
232
258
  } catch {
233
- console.warn(
234
- "[NostrBootstrap] Failed to parse Nostr event content:",
235
- event.id
236
- );
259
+ this.logger.warn("NostrBootstrap: failed to parse event content:", event.id);
237
260
  }
238
261
  }
239
262
  }
@@ -287,7 +310,7 @@ var ModelManager = class _ModelManager {
287
310
  }
288
311
  return list;
289
312
  } catch (e) {
290
- console.error("Failed to bootstrap providers", e);
313
+ this.logger.error("Failed to bootstrap providers", e);
291
314
  throw new ProviderBootstrapError([], `Provider bootstrap failed: ${e}`);
292
315
  }
293
316
  }
@@ -353,9 +376,9 @@ var ModelManager = class _ModelManager {
353
376
  return { success: true, base, list };
354
377
  } catch (error) {
355
378
  if (this.isProviderDownError(error)) {
356
- console.warn(`Provider ${base} is down right now.`);
379
+ this.logger.warn(`Provider ${base} is down right now.`);
357
380
  } else {
358
- console.warn(`Failed to fetch models from ${base}:`, error);
381
+ this.logger.warn(`Failed to fetch models from ${base}:`, error);
359
382
  }
360
383
  this.adapter.setProviderLastUpdate(base, Date.now());
361
384
  return { success: false, base };
@@ -512,10 +535,7 @@ var ModelManager = class _ModelManager {
512
535
  this.adapter.setRoutstr21ModelsLastUpdate(Date.now());
513
536
  return models;
514
537
  } catch {
515
- console.warn(
516
- "[Routstr21Models] Failed to parse Nostr event content:",
517
- event.id
518
- );
538
+ this.logger.warn("Routstr21Models: failed to parse Nostr event content:", event.id);
519
539
  return cachedModels.length > 0 ? cachedModels : [];
520
540
  }
521
541
  }
@@ -526,8 +546,10 @@ var MintDiscovery = class {
526
546
  constructor(adapter, config = {}) {
527
547
  this.adapter = adapter;
528
548
  this.cacheTTL = config.cacheTTL || 21 * 60 * 1e3;
549
+ this.logger = (config.logger ?? consoleLogger).child("MintDiscovery");
529
550
  }
530
551
  cacheTTL;
552
+ logger;
531
553
  /**
532
554
  * Fetch mints from all providers via their /v1/info endpoints
533
555
  * Caches mints and full provider info for later access
@@ -578,9 +600,9 @@ var MintDiscovery = class {
578
600
  } catch (error) {
579
601
  this.adapter.setProviderLastUpdate(base, Date.now());
580
602
  if (this.isProviderDownError(error)) {
581
- console.warn(`Provider ${base} is down right now.`);
603
+ this.logger.warn(`Provider ${base} is down right now.`);
582
604
  } else {
583
- console.warn(`Failed to fetch mints from ${base}:`, error);
605
+ this.logger.warn(`Failed to fetch mints from ${base}:`, error);
584
606
  }
585
607
  return { success: false, base, mints: [], info: null };
586
608
  }
@@ -594,14 +616,14 @@ var MintDiscovery = class {
594
616
  infoFromAllProviders[base] = info;
595
617
  }
596
618
  } else {
597
- console.error("Mint discovery error:", result.reason);
619
+ this.logger.error("Mint discovery error:", result.reason);
598
620
  }
599
621
  }
600
622
  try {
601
623
  this.adapter.setCachedMints(mintsFromAllProviders);
602
624
  this.adapter.setCachedProviderInfo(infoFromAllProviders);
603
625
  } catch (error) {
604
- console.error("Error caching mint discovery results:", error);
626
+ this.logger.error("Error caching mint discovery results:", error);
605
627
  }
606
628
  return {
607
629
  mintsFromProviders: mintsFromAllProviders,
@@ -740,14 +762,16 @@ function selectMintWithBalance(balances, units, amount, excludeMints = []) {
740
762
  return { selectedMintUrl: null, selectedMintBalance: 0 };
741
763
  }
742
764
  var CashuSpender = class {
743
- constructor(walletAdapter, storageAdapter, _providerRegistry, balanceManager) {
765
+ constructor(walletAdapter, storageAdapter, _providerRegistry, balanceManager, logger) {
744
766
  this.walletAdapter = walletAdapter;
745
767
  this.storageAdapter = storageAdapter;
746
768
  this._providerRegistry = _providerRegistry;
747
769
  this.balanceManager = balanceManager;
770
+ this.logger = (logger ?? consoleLogger).child("CashuSpender");
748
771
  }
749
772
  _isBusy = false;
750
773
  debugLevel = "WARN";
774
+ logger;
751
775
  async receiveToken(token) {
752
776
  try {
753
777
  const result = await this.walletAdapter.receiveToken(token);
@@ -843,13 +867,13 @@ var CashuSpender = class {
843
867
  if (levelPriority[level] >= levelPriority[this.debugLevel]) {
844
868
  switch (level) {
845
869
  case "DEBUG":
846
- console.log(...args);
870
+ this.logger.log(...args);
847
871
  break;
848
872
  case "WARN":
849
- console.warn(...args);
873
+ this.logger.warn(...args);
850
874
  break;
851
875
  case "ERROR":
852
- console.error(...args);
876
+ this.logger.error(...args);
853
877
  break;
854
878
  }
855
879
  }
@@ -1197,19 +1221,50 @@ var CashuSpender = class {
1197
1221
  apiKeyEntry.baseUrl
1198
1222
  );
1199
1223
  if (apiKeyEntryFull && this.balanceManager) {
1224
+ try {
1225
+ const balanceResult = await this.balanceManager.getTokenBalance(
1226
+ apiKeyEntryFull.key,
1227
+ apiKeyEntry.baseUrl
1228
+ );
1229
+ if (balanceResult.isInvalidApiKey) {
1230
+ this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
1231
+ results.push({
1232
+ baseUrl: apiKeyEntry.baseUrl,
1233
+ success: true
1234
+ });
1235
+ continue;
1236
+ }
1237
+ if (balanceResult.amount >= 0) {
1238
+ const balanceSat = balanceResult.unit === "msat" ? Math.floor(balanceResult.amount / 1e3) : balanceResult.amount;
1239
+ this.storageAdapter.updateApiKeyBalance(
1240
+ apiKeyEntry.baseUrl,
1241
+ balanceSat
1242
+ );
1243
+ }
1244
+ } catch {
1245
+ }
1246
+ const refreshedEntry = this.storageAdapter.getApiKey(
1247
+ apiKeyEntry.baseUrl
1248
+ );
1249
+ if (!refreshedEntry) continue;
1200
1250
  const refundResult = await this.balanceManager.refundApiKey({
1201
1251
  mintUrl,
1202
1252
  baseUrl: apiKeyEntry.baseUrl,
1203
- apiKey: apiKeyEntryFull.key,
1253
+ apiKey: refreshedEntry.key,
1204
1254
  forceRefund
1205
1255
  });
1206
1256
  if (refundResult.success) {
1207
1257
  this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
1208
1258
  } else {
1209
- this.storageAdapter.updateApiKeyBalance(
1210
- apiKeyEntry.baseUrl,
1211
- apiKeyEntry.amount
1259
+ const currentEntry = this.storageAdapter.getApiKey(
1260
+ apiKeyEntry.baseUrl
1212
1261
  );
1262
+ if (currentEntry) {
1263
+ this.storageAdapter.updateApiKeyBalance(
1264
+ apiKeyEntry.baseUrl,
1265
+ currentEntry.balance
1266
+ );
1267
+ }
1213
1268
  }
1214
1269
  results.push({
1215
1270
  baseUrl: apiKeyEntry.baseUrl,
@@ -1276,10 +1331,11 @@ var CashuSpender = class {
1276
1331
 
1277
1332
  // wallet/BalanceManager.ts
1278
1333
  var BalanceManager = class _BalanceManager {
1279
- constructor(walletAdapter, storageAdapter, providerRegistry, cashuSpender) {
1334
+ constructor(walletAdapter, storageAdapter, providerRegistry, cashuSpender, logger) {
1280
1335
  this.walletAdapter = walletAdapter;
1281
1336
  this.storageAdapter = storageAdapter;
1282
1337
  this.providerRegistry = providerRegistry;
1338
+ this.logger = (logger ?? consoleLogger).child("BalanceManager");
1283
1339
  if (cashuSpender) {
1284
1340
  this.cashuSpender = cashuSpender;
1285
1341
  } else {
@@ -1296,6 +1352,7 @@ var BalanceManager = class _BalanceManager {
1296
1352
  providerWalletOps = /* @__PURE__ */ new Map();
1297
1353
  /** Cooldown (ms) between opposite operations on the same provider */
1298
1354
  static PROVIDER_WALLET_COOLDOWN_MS = 1e4;
1355
+ logger;
1299
1356
  /**
1300
1357
  * Check whether a wallet operation (topup/refund) may run for a provider.
1301
1358
  * Returns the reason when blocked.
@@ -1370,7 +1427,7 @@ var BalanceManager = class _BalanceManager {
1370
1427
  const { mintUrl, baseUrl, apiKey, forceRefund } = options;
1371
1428
  const guard = this._canRunProviderWalletOperation(baseUrl, "refund");
1372
1429
  if (!guard.allowed) {
1373
- console.log(`[BalanceManager] Skipping refund for ${baseUrl} - ${guard.reason}`);
1430
+ this.logger.log(`Skipping refund for ${baseUrl} - ${guard.reason}`);
1374
1431
  return { success: false, message: guard.reason };
1375
1432
  }
1376
1433
  this._beginProviderWalletOperation(baseUrl, "refund");
@@ -1390,9 +1447,7 @@ var BalanceManager = class _BalanceManager {
1390
1447
  if (apiKeyEntry?.lastUsed) {
1391
1448
  const fiveMinutesAgo = Date.now() - 5 * 60 * 1e3;
1392
1449
  if (apiKeyEntry.lastUsed > fiveMinutesAgo) {
1393
- console.log(
1394
- `[BalanceManager] Skipping refund for ${baseUrl} - used ${Math.round((Date.now() - apiKeyEntry.lastUsed) / 1e3)}s ago`
1395
- );
1450
+ this.logger.log(`Skipping refund for ${baseUrl} - used ${Math.round((Date.now() - apiKeyEntry.lastUsed) / 1e3)}s ago`);
1396
1451
  return {
1397
1452
  success: false,
1398
1453
  message: "API key was used recently, skipping refund"
@@ -1418,7 +1473,8 @@ var BalanceManager = class _BalanceManager {
1418
1473
  };
1419
1474
  }
1420
1475
  if (fetchResult.error === "No balance to refund") {
1421
- return { success: false, message: "No balance to refund" };
1476
+ this.storageAdapter.removeApiKey(baseUrl);
1477
+ return { success: true, message: "No balance to refund, key cleaned up" };
1422
1478
  }
1423
1479
  const receiveResult = await this.cashuSpender.receiveToken(
1424
1480
  fetchResult.token
@@ -1434,7 +1490,7 @@ var BalanceManager = class _BalanceManager {
1434
1490
  requestId: fetchResult.requestId
1435
1491
  };
1436
1492
  } catch (error) {
1437
- console.error("[BalanceManager] API key refund error", error);
1493
+ this.logger.error("API key refund error", error);
1438
1494
  return this._handleRefundError(error, mintUrl, fetchResult?.requestId);
1439
1495
  }
1440
1496
  }
@@ -1486,7 +1542,7 @@ var BalanceManager = class _BalanceManager {
1486
1542
  };
1487
1543
  } catch (error) {
1488
1544
  clearTimeout(timeoutId);
1489
- console.error("[BalanceManager.fetchRefundToken] Fetch error", error);
1545
+ this.logger.error("fetchRefundToken fetch error", error);
1490
1546
  if (error instanceof Error) {
1491
1547
  if (error.name === "AbortError") {
1492
1548
  return {
@@ -1512,7 +1568,7 @@ var BalanceManager = class _BalanceManager {
1512
1568
  const { mintUrl, baseUrl, amount, token: providedToken } = options;
1513
1569
  const guard = this._canRunProviderWalletOperation(baseUrl, "topup");
1514
1570
  if (!guard.allowed) {
1515
- console.log(`[BalanceManager] Skipping topup for ${baseUrl} - ${guard.reason}`);
1571
+ this.logger.log(`Skipping topup for ${baseUrl} - ${guard.reason}`);
1516
1572
  return { success: false, message: guard.reason };
1517
1573
  }
1518
1574
  this._beginProviderWalletOperation(baseUrl, "topup");
@@ -1549,7 +1605,7 @@ var BalanceManager = class _BalanceManager {
1549
1605
  cashuToken = tokenResult.token;
1550
1606
  const topUpResult = await this._postTopUp(baseUrl, apiKey, cashuToken);
1551
1607
  requestId = topUpResult.requestId;
1552
- console.log(topUpResult);
1608
+ this.logger.log("topUpResult:", topUpResult);
1553
1609
  if (!topUpResult.success) {
1554
1610
  await this._recoverFailedTopUp(cashuToken);
1555
1611
  return {
@@ -1565,10 +1621,7 @@ var BalanceManager = class _BalanceManager {
1565
1621
  requestId
1566
1622
  };
1567
1623
  } catch (error) {
1568
- console.log(
1569
- "DEBUG",
1570
- `[TopuPU] topup: Topup result for ${baseUrl}: error=${error}`
1571
- );
1624
+ this.logger.log(`topup error for ${baseUrl}: ${error}`);
1572
1625
  if (cashuToken) {
1573
1626
  await this._recoverFailedTopUp(cashuToken);
1574
1627
  }
@@ -1585,13 +1638,9 @@ var BalanceManager = class _BalanceManager {
1585
1638
  p2pkPubkey
1586
1639
  } = options;
1587
1640
  const adjustedAmount = Math.ceil(amount);
1588
- console.log(
1589
- `[BalanceManager.createProviderToken] Starting: baseUrl=${baseUrl}, mintUrl=${mintUrl}, amount=${amount}, adjustedAmount=${adjustedAmount}, retryCount=${retryCount}`
1590
- );
1641
+ this.logger.log(`createProviderToken: baseUrl=${baseUrl} mintUrl=${mintUrl} amount=${amount} adjustedAmount=${adjustedAmount} retryCount=${retryCount}`);
1591
1642
  if (!adjustedAmount || isNaN(adjustedAmount)) {
1592
- console.error(
1593
- `[BalanceManager.createProviderToken] FAILURE: Invalid amount - amount=${amount}, adjustedAmount=${adjustedAmount}`
1594
- );
1643
+ this.logger.error(`createProviderToken: invalid amount=${amount}`);
1595
1644
  return { success: false, error: "Invalid top up amount" };
1596
1645
  }
1597
1646
  const balanceState = await this.getBalanceState();
@@ -1622,9 +1671,7 @@ var BalanceManager = class _BalanceManager {
1622
1671
  { url: "", balance: 0 }
1623
1672
  ).url
1624
1673
  );
1625
- console.error(
1626
- `[BalanceManager.createProviderToken] FAILURE: Insufficient balance - required=${adjustedAmount}, available=${totalMintBalance + targetProviderBalance}, totalMintBalance=${totalMintBalance}, targetProviderBalance=${targetProviderBalance}, refundableProviderBalance=${refundableProviderBalance}`
1627
- );
1674
+ this.logger.error(`createProviderToken: insufficient balance required=${adjustedAmount} available=${totalMintBalance + targetProviderBalance} totalMint=${totalMintBalance} targetProvider=${targetProviderBalance}`);
1628
1675
  return { success: false, error: error.message };
1629
1676
  }
1630
1677
  const providerMints = baseUrl && this.providerRegistry ? this.providerRegistry.getProviderMints(baseUrl) : [];
@@ -1660,9 +1707,7 @@ var BalanceManager = class _BalanceManager {
1660
1707
  maxMintUrl = mintUrl2;
1661
1708
  }
1662
1709
  }
1663
- console.error(
1664
- `[BalanceManager.createProviderToken] FAILURE: No candidate mints found - requiredAmount=${requiredAmount}, totalMintBalance=${totalMintBalance}, maxBalance=${maxBalance}, maxMintUrl=${maxMintUrl}, providerMints=${JSON.stringify(providerMints)}`
1665
- );
1710
+ this.logger.error(`createProviderToken: no candidate mints required=${requiredAmount} totalMint=${totalMintBalance} maxBalance=${maxBalance} maxMint=${maxMintUrl}`);
1666
1711
  const error = new InsufficientBalanceError(
1667
1712
  adjustedAmount,
1668
1713
  totalMintBalance,
@@ -1674,17 +1719,13 @@ var BalanceManager = class _BalanceManager {
1674
1719
  let lastError;
1675
1720
  for (const candidateMint of candidates) {
1676
1721
  try {
1677
- console.log(
1678
- `[BalanceManager.createProviderToken] Attempting mint: ${candidateMint}, amount: ${requiredAmount}`
1679
- );
1722
+ this.logger.log(`createProviderToken: attempting mint=${candidateMint} amount=${requiredAmount}`);
1680
1723
  const token = await this.walletAdapter.sendToken(
1681
1724
  candidateMint,
1682
1725
  requiredAmount,
1683
1726
  p2pkPubkey
1684
1727
  );
1685
- console.log(
1686
- `[BalanceManager.createProviderToken] SUCCESS: Token created from mint ${candidateMint}, all mint balances: ${JSON.stringify(Object.fromEntries(Object.entries(balances).map(([mint, balance]) => [mint, getBalanceInSats(balance, units[mint])])))}`
1687
- );
1728
+ this.logger.log(`createProviderToken: success from mint=${candidateMint}`);
1688
1729
  return {
1689
1730
  success: true,
1690
1731
  token,
@@ -1693,15 +1734,11 @@ var BalanceManager = class _BalanceManager {
1693
1734
  };
1694
1735
  } catch (error) {
1695
1736
  const errorMsg = error instanceof Error ? error.message : String(error);
1696
- console.error(
1697
- `[BalanceManager.createProviderToken] FAILURE: Mint ${candidateMint} failed with error: ${errorMsg}`
1698
- );
1737
+ this.logger.error(`createProviderToken: mint=${candidateMint} failed: ${errorMsg}`);
1699
1738
  if (error instanceof Error) {
1700
1739
  lastError = errorMsg;
1701
1740
  if (isNetworkErrorMessage(error.message)) {
1702
- console.warn(
1703
- `[BalanceManager.createProviderToken] Network error from ${candidateMint}, trying next mint...`
1704
- );
1741
+ this.logger.warn(`createProviderToken: network error from ${candidateMint}, trying next mint...`);
1705
1742
  continue;
1706
1743
  }
1707
1744
  }
@@ -1711,9 +1748,7 @@ var BalanceManager = class _BalanceManager {
1711
1748
  };
1712
1749
  }
1713
1750
  }
1714
- console.error(
1715
- `[BalanceManager.createProviderToken] FAILURE: All candidate mints exhausted - lastError=${lastError}, candidates=${JSON.stringify(candidates)}`
1716
- );
1751
+ this.logger.error(`createProviderToken: all candidate mints exhausted lastError=${lastError}`);
1717
1752
  return {
1718
1753
  success: false,
1719
1754
  error: lastError || "All candidate mints failed while creating top up token"
@@ -1828,7 +1863,7 @@ var BalanceManager = class _BalanceManager {
1828
1863
  return { success: true, requestId };
1829
1864
  } catch (error) {
1830
1865
  clearTimeout(timeoutId);
1831
- console.error("[BalanceManager._postTopUp] Fetch error", error);
1866
+ this.logger.error("_postTopUp fetch error", error);
1832
1867
  if (error instanceof Error) {
1833
1868
  if (error.name === "AbortError") {
1834
1869
  return {
@@ -1854,10 +1889,7 @@ var BalanceManager = class _BalanceManager {
1854
1889
  try {
1855
1890
  await this.cashuSpender.receiveToken(cashuToken);
1856
1891
  } catch (error) {
1857
- console.error(
1858
- "[BalanceManager._recoverFailedTopUp] Failed to recover token",
1859
- error
1860
- );
1892
+ this.logger.error("_recoverFailedTopUp: failed to recover token", error);
1861
1893
  }
1862
1894
  }
1863
1895
  /**
@@ -1910,9 +1942,9 @@ var BalanceManager = class _BalanceManager {
1910
1942
  apiKey: data.api_key
1911
1943
  };
1912
1944
  } else {
1913
- console.log(response.status);
1945
+ this.logger.warn(`getTokenBalance: status=${response.status}`);
1914
1946
  const data = await response.json();
1915
- console.log("FAILED ", data);
1947
+ this.logger.warn("getTokenBalance: FAILED", data);
1916
1948
  const isInvalidApiKey = response.status === 401 && data?.detail?.error?.code === "invalid_api_key" && data?.detail?.error?.message?.includes("proofs already spent");
1917
1949
  return {
1918
1950
  amount: -1,
@@ -1923,7 +1955,7 @@ var BalanceManager = class _BalanceManager {
1923
1955
  };
1924
1956
  }
1925
1957
  } catch (error) {
1926
- console.error("ERRORR IN RESTPONSE", error);
1958
+ this.logger.error("getTokenBalance error", error);
1927
1959
  }
1928
1960
  return { amount: -1, reserved: 0, unit: "sat", apiKey: "" };
1929
1961
  }
@@ -2445,9 +2477,10 @@ function isInsecureHttpUrl(url) {
2445
2477
  return url.startsWith("http://");
2446
2478
  }
2447
2479
  var ProviderManager = class _ProviderManager {
2448
- constructor(providerRegistry, store) {
2480
+ constructor(providerRegistry, store, logger) {
2449
2481
  this.providerRegistry = providerRegistry;
2450
2482
  this.instanceId = `pm_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
2483
+ this.logger = (logger ?? consoleLogger).child(`ProviderManager:${this.instanceId}`);
2451
2484
  if (store) {
2452
2485
  this.store = store;
2453
2486
  this.hydrateFromStore();
@@ -2464,6 +2497,7 @@ var ProviderManager = class _ProviderManager {
2464
2497
  store = null;
2465
2498
  /** Instance ID for debugging */
2466
2499
  instanceId;
2500
+ logger;
2467
2501
  /**
2468
2502
  * Hydrate in-memory state from persistent store
2469
2503
  */
@@ -2476,10 +2510,7 @@ var ProviderManager = class _ProviderManager {
2476
2510
  this.providersOnCoolDown = state.providersOnCooldown.filter(
2477
2511
  (entry) => now - entry.timestamp < _ProviderManager.COOLDOWN_DURATION_MS
2478
2512
  ).map((entry) => [entry.baseUrl, entry.timestamp]);
2479
- console.log(`[ProviderManager:${this.instanceId}] Hydrated from store:`);
2480
- console.log(` failedProviders: ${this.failedProviders.size}`);
2481
- console.log(` lastFailed: ${this.lastFailed.size}`);
2482
- console.log(` providersOnCooldown: ${this.providersOnCoolDown.length}`);
2513
+ this.logger.log(`Hydrated from store: failedProviders=${this.failedProviders.size} lastFailed=${this.lastFailed.size} providersOnCooldown=${this.providersOnCoolDown.length}`);
2483
2514
  }
2484
2515
  /**
2485
2516
  * Get instance ID for debugging
@@ -2499,9 +2530,7 @@ var ProviderManager = class _ProviderManager {
2499
2530
  const age = now - timestamp;
2500
2531
  const isExpired = age >= _ProviderManager.COOLDOWN_DURATION_MS;
2501
2532
  if (isExpired) {
2502
- console.log(
2503
- `[cleanupExpiredCooldowns:${this.instanceId}] Removing expired cooldown for ${url} (age: ${age}ms, cooldown: ${_ProviderManager.COOLDOWN_DURATION_MS}ms)`
2504
- );
2533
+ this.logger.log(`Removing expired cooldown for ${url} (age: ${age}ms)`);
2505
2534
  this.failedProviders.delete(url);
2506
2535
  if (this.store) {
2507
2536
  this.store.getState().removeFailedProvider(url);
@@ -2512,9 +2541,7 @@ var ProviderManager = class _ProviderManager {
2512
2541
  );
2513
2542
  const after = this.providersOnCoolDown.length;
2514
2543
  if (before !== after) {
2515
- console.log(
2516
- `[cleanupExpiredCooldowns:${this.instanceId}] Cleaned up ${before - after} expired cooldown(s), ${after} remaining`
2517
- );
2544
+ this.logger.log(`Cleaned up ${before - after} expired cooldown(s), ${after} remaining`);
2518
2545
  }
2519
2546
  }
2520
2547
  /**
@@ -2566,24 +2593,10 @@ var ProviderManager = class _ProviderManager {
2566
2593
  markFailed(baseUrl) {
2567
2594
  const now = Date.now();
2568
2595
  const lastFailure = this.lastFailed.get(baseUrl);
2569
- console.log(`[markFailed:${this.instanceId}] baseUrl: ${baseUrl}`);
2570
- console.log(
2571
- `[markFailed:${this.instanceId}] lastFailure from map: ${lastFailure}`
2572
- );
2573
- console.log(
2574
- `[markFailed:${this.instanceId}] current timestamp (now): ${now}`
2575
- );
2576
- console.log(
2577
- `[markFailed:${this.instanceId}] COOLDOWN_DURATION_MS: ${_ProviderManager.COOLDOWN_DURATION_MS}`
2578
- );
2596
+ this.logger.log(`markFailed: ${baseUrl} lastFailure=${lastFailure} now=${now}`);
2579
2597
  if (lastFailure !== void 0) {
2580
2598
  const timeSinceLastFailure = now - lastFailure;
2581
- console.log(
2582
- `[markFailed:${this.instanceId}] timeSinceLastFailure: ${timeSinceLastFailure}ms`
2583
- );
2584
- console.log(
2585
- `[markFailed:${this.instanceId}] isWithinCooldownWindow: ${timeSinceLastFailure < _ProviderManager.COOLDOWN_DURATION_MS}`
2586
- );
2599
+ this.logger.log(`markFailed: timeSinceLastFailure=${timeSinceLastFailure}ms withinCooldown=${timeSinceLastFailure < _ProviderManager.COOLDOWN_DURATION_MS}`);
2587
2600
  }
2588
2601
  this.lastFailed.set(baseUrl, now);
2589
2602
  this.failedProviders.add(baseUrl);
@@ -2591,38 +2604,23 @@ var ProviderManager = class _ProviderManager {
2591
2604
  this.store.getState().setLastFailedTimestamp(baseUrl, now);
2592
2605
  this.store.getState().addFailedProvider(baseUrl);
2593
2606
  }
2594
- console.log(
2595
- `[markFailed:${this.instanceId}] Updated lastFailed map for ${baseUrl} to ${now}`
2596
- );
2597
- console.log(
2598
- `[markFailed:${this.instanceId}] failedProviders set size: ${this.failedProviders.size}`
2599
- );
2607
+ this.logger.log(`markFailed: updated ${baseUrl} to ${now}, failedProviders=${this.failedProviders.size}`);
2600
2608
  if (lastFailure !== void 0 && now - lastFailure < _ProviderManager.COOLDOWN_DURATION_MS) {
2601
- console.log(
2602
- `[markFailed:${this.instanceId}] Second failure detected within cooldown window for ${baseUrl}`
2603
- );
2609
+ this.logger.log(`markFailed: second failure within cooldown window for ${baseUrl}`);
2604
2610
  if (!this.isOnCooldown(baseUrl)) {
2605
2611
  this.providersOnCoolDown.push([baseUrl, now]);
2606
2612
  if (this.store) {
2607
2613
  this.store.getState().addProviderOnCooldown(baseUrl, now);
2608
2614
  }
2609
- console.log(
2610
- `[markFailed:${this.instanceId}] Provider ${baseUrl} added to cooldown after second failure within 5 minutes`
2611
- );
2615
+ this.logger.log(`markFailed: ${baseUrl} added to cooldown`);
2612
2616
  } else {
2613
- console.log(
2614
- `[markFailed:${this.instanceId}] Provider ${baseUrl} is already on cooldown`
2615
- );
2617
+ this.logger.log(`markFailed: ${baseUrl} already on cooldown`);
2616
2618
  }
2617
2619
  } else {
2618
2620
  if (lastFailure === void 0) {
2619
- console.log(
2620
- `[markFailed:${this.instanceId}] First failure for ${baseUrl} - not adding to cooldown yet`
2621
- );
2621
+ this.logger.log(`markFailed: first failure for ${baseUrl}`);
2622
2622
  } else {
2623
- console.log(
2624
- `[markFailed:${this.instanceId}] Failure outside cooldown window for ${baseUrl} (timeSinceLastFailure: ${now - lastFailure}ms)`
2625
- );
2623
+ this.logger.log(`markFailed: failure outside cooldown window for ${baseUrl} (${now - lastFailure}ms ago)`);
2626
2624
  }
2627
2625
  }
2628
2626
  }
@@ -2679,25 +2677,12 @@ var ProviderManager = class _ProviderManager {
2679
2677
  const disabledProviders = new Set(
2680
2678
  this.providerRegistry.getDisabledProviders()
2681
2679
  );
2682
- console.log(
2683
- `[findNextBestProvider:${this.instanceId}] Starting search for model: ${modelId}`
2684
- );
2685
- console.log(
2686
- `[findNextBestProvider:${this.instanceId}] disabledProviders: ${[...disabledProviders]}`
2687
- );
2688
- console.log(
2689
- `[findNextBestProvider:${this.instanceId}] providersOnCooldown: ${this.providersOnCoolDown.map(([url]) => url)}`
2690
- );
2680
+ this.logger.log(`findNextBestProvider: model=${modelId} disabled=${[...disabledProviders].length} onCooldown=${this.providersOnCoolDown.length}`);
2691
2681
  const allProviders = this.providerRegistry.getAllProvidersModels();
2692
- console.log(
2693
- `[findNextBestProvider:${this.instanceId}] Total providers in registry: ${Object.keys(allProviders).length}`
2694
- );
2682
+ this.logger.log(`findNextBestProvider: total providers=${Object.keys(allProviders).length}`);
2695
2683
  const candidates = [];
2696
2684
  for (const [baseUrl, models] of Object.entries(allProviders)) {
2697
2685
  if (baseUrl === currentBaseUrl) {
2698
- console.log(
2699
- `[findNextBestProvider:${this.instanceId}] SKIP (current): ${baseUrl}`
2700
- );
2701
2686
  continue;
2702
2687
  }
2703
2688
  if (disabledProviders.has(baseUrl)) {
@@ -2723,7 +2708,7 @@ var ProviderManager = class _ProviderManager {
2723
2708
  return null;
2724
2709
  }
2725
2710
  } catch (error) {
2726
- console.error("Error finding next best provider:", error);
2711
+ this.logger.error("findNextBestProvider error:", error);
2727
2712
  return null;
2728
2713
  }
2729
2714
  }
@@ -2850,16 +2835,9 @@ var ProviderManager = class _ProviderManager {
2850
2835
  res.height
2851
2836
  );
2852
2837
  imageTokens += tokensFromImage;
2853
- console.log("IMAGE INPUT RESOLUTION", {
2854
- width: res.width,
2855
- height: res.height,
2856
- tokensFromImage
2857
- });
2838
+ this.logger.log(`IMAGE INPUT RESOLUTION width=${res.width} height=${res.height} tokens=${tokensFromImage}`);
2858
2839
  } else {
2859
- console.log(
2860
- "IMAGE INPUT RESOLUTION",
2861
- "unknown (unsupported format or parse failure)"
2862
- );
2840
+ this.logger.log("IMAGE INPUT RESOLUTION: unknown format");
2863
2841
  }
2864
2842
  }
2865
2843
  }
@@ -2892,7 +2870,7 @@ var ProviderManager = class _ProviderManager {
2892
2870
  const totalEstimatedCosts = (promptCosts + completionCost) * 1.05;
2893
2871
  return totalEstimatedCosts;
2894
2872
  } catch (e) {
2895
- console.error(e);
2873
+ this.logger.error("getRequiredSatsForModel error:", e);
2896
2874
  return 0;
2897
2875
  }
2898
2876
  }
@@ -3091,7 +3069,8 @@ var createSqliteDriver = (options = {}) => {
3091
3069
  }
3092
3070
  };
3093
3071
  };
3094
- async function createBunSqliteDriver(dbPath) {
3072
+ async function createBunSqliteDriver(dbPath, options) {
3073
+ const logger = (options?.logger ?? consoleLogger).child("BunSqliteDriver");
3095
3074
  const SQLite = (await import(
3096
3075
  /* webpackIgnore: true */
3097
3076
  'bun:sqlite'
@@ -3117,7 +3096,7 @@ async function createBunSqliteDriver(dbPath) {
3117
3096
  throw parseError;
3118
3097
  }
3119
3098
  } catch (error) {
3120
- console.error(`SQLite getItem failed for key "${key}":`, error);
3099
+ logger.error(`getItem failed for key "${key}":`, error);
3121
3100
  return defaultValue;
3122
3101
  }
3123
3102
  },
@@ -3127,14 +3106,14 @@ async function createBunSqliteDriver(dbPath) {
3127
3106
  "INSERT INTO sdk_storage (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
3128
3107
  ).run(key, JSON.stringify(value));
3129
3108
  } catch (error) {
3130
- console.error(`SQLite setItem failed for key "${key}":`, error);
3109
+ logger.error(`setItem failed for key "${key}":`, error);
3131
3110
  }
3132
3111
  },
3133
3112
  async removeItem(key) {
3134
3113
  try {
3135
3114
  db.query("DELETE FROM sdk_storage WHERE key = ?").run(key);
3136
3115
  } catch (error) {
3137
- console.error(`SQLite removeItem failed for key "${key}":`, error);
3116
+ logger.error(`removeItem failed for key "${key}":`, error);
3138
3117
  }
3139
3118
  }
3140
3119
  };
@@ -4308,9 +4287,7 @@ var createStorageAdapterFromStore = (store) => ({
4308
4287
  const distributionMap = {};
4309
4288
  for (const entry of apiKeys) {
4310
4289
  const sum = entry.balance || 0;
4311
- if (sum > 0) {
4312
- distributionMap[entry.baseUrl] = (distributionMap[entry.baseUrl] || 0) + sum;
4313
- }
4290
+ distributionMap[entry.baseUrl] = (distributionMap[entry.baseUrl] || 0) + sum;
4314
4291
  }
4315
4292
  return Object.entries(distributionMap).map(([baseUrl, amt]) => ({ baseUrl, amount: amt })).sort((a, b) => b.amount - a.amount);
4316
4293
  },
@@ -4485,37 +4462,40 @@ var createStorageAdapterFromStore = (store) => ({
4485
4462
  store.getState().updateXcashuTokenTryCount(token, tryCount);
4486
4463
  }
4487
4464
  });
4488
- var createProviderRegistryFromStore = (store) => ({
4489
- getModelsForProvider: (baseUrl) => {
4490
- const normalized = normalizeBaseUrl5(baseUrl);
4491
- return store.getState().modelsFromAllProviders[normalized] || [];
4492
- },
4493
- getDisabledProviders: () => store.getState().disabledProviders,
4494
- getProviderMints: (baseUrl) => {
4495
- const normalized = normalizeBaseUrl5(baseUrl);
4496
- return store.getState().mintsFromAllProviders[normalized] || [];
4497
- },
4498
- getProviderInfo: async (baseUrl) => {
4499
- const normalized = normalizeBaseUrl5(baseUrl);
4500
- const cached = store.getState().infoFromAllProviders[normalized];
4501
- if (cached) return cached;
4502
- try {
4503
- const response = await fetch(`${normalized}v1/info`);
4504
- if (!response.ok) {
4505
- throw new Error(`Failed ${response.status}`);
4465
+ var createProviderRegistryFromStore = (store, logger) => {
4466
+ const log = (logger ?? consoleLogger).child("ProviderRegistry");
4467
+ return {
4468
+ getModelsForProvider: (baseUrl) => {
4469
+ const normalized = normalizeBaseUrl5(baseUrl);
4470
+ return store.getState().modelsFromAllProviders[normalized] || [];
4471
+ },
4472
+ getDisabledProviders: () => store.getState().disabledProviders,
4473
+ getProviderMints: (baseUrl) => {
4474
+ const normalized = normalizeBaseUrl5(baseUrl);
4475
+ return store.getState().mintsFromAllProviders[normalized] || [];
4476
+ },
4477
+ getProviderInfo: async (baseUrl) => {
4478
+ const normalized = normalizeBaseUrl5(baseUrl);
4479
+ const cached = store.getState().infoFromAllProviders[normalized];
4480
+ if (cached) return cached;
4481
+ try {
4482
+ const response = await fetch(`${normalized}v1/info`);
4483
+ if (!response.ok) {
4484
+ throw new Error(`Failed ${response.status}`);
4485
+ }
4486
+ const info = await response.json();
4487
+ const next = { ...store.getState().infoFromAllProviders };
4488
+ next[normalized] = info;
4489
+ store.getState().setInfoFromAllProviders(next);
4490
+ return info;
4491
+ } catch (error) {
4492
+ log.warn(`Failed to fetch provider info from ${normalized}:`, error);
4493
+ return null;
4506
4494
  }
4507
- const info = await response.json();
4508
- const next = { ...store.getState().infoFromAllProviders };
4509
- next[normalized] = info;
4510
- store.getState().setInfoFromAllProviders(next);
4511
- return info;
4512
- } catch (error) {
4513
- console.warn(`Failed to fetch provider info from ${normalized}:`, error);
4514
- return null;
4515
- }
4516
- },
4517
- getAllProvidersModels: () => store.getState().modelsFromAllProviders
4518
- });
4495
+ },
4496
+ getAllProvidersModels: () => store.getState().modelsFromAllProviders
4497
+ };
4498
+ };
4519
4499
 
4520
4500
  // storage/index.ts
4521
4501
  var isBrowser3 = () => {
@@ -4786,6 +4766,7 @@ var RoutstrClient = class {
4786
4766
  this.walletAdapter = walletAdapter;
4787
4767
  this.storageAdapter = storageAdapter;
4788
4768
  this.providerRegistry = providerRegistry;
4769
+ this.logger = (options.logger ?? consoleLogger).child("RoutstrClient");
4789
4770
  this.balanceManager = new BalanceManager(
4790
4771
  walletAdapter,
4791
4772
  storageAdapter,
@@ -4802,7 +4783,7 @@ var RoutstrClient = class {
4802
4783
  this.mode = mode;
4803
4784
  this.usageTrackingDriver = options.usageTrackingDriver;
4804
4785
  this.sdkStore = options.sdkStore;
4805
- this.providerManager = options.providerManager ?? new ProviderManager(providerRegistry, this.sdkStore);
4786
+ this.providerManager = options.providerManager ?? new ProviderManager(providerRegistry, this.sdkStore, this.logger);
4806
4787
  }
4807
4788
  cashuSpender;
4808
4789
  balanceManager;
@@ -4813,6 +4794,7 @@ var RoutstrClient = class {
4813
4794
  debugLevel = "WARN";
4814
4795
  usageTrackingDriver;
4815
4796
  sdkStore;
4797
+ logger;
4816
4798
  /**
4817
4799
  * Get the current client mode
4818
4800
  */
@@ -4834,13 +4816,13 @@ var RoutstrClient = class {
4834
4816
  if (levelPriority[level] >= levelPriority[this.debugLevel]) {
4835
4817
  switch (level) {
4836
4818
  case "DEBUG":
4837
- console.log(...args);
4819
+ this.logger.log(...args);
4838
4820
  break;
4839
4821
  case "WARN":
4840
- console.warn(...args);
4822
+ this.logger.warn(...args);
4841
4823
  break;
4842
4824
  case "ERROR":
4843
- console.error(...args);
4825
+ this.logger.error(...args);
4844
4826
  break;
4845
4827
  }
4846
4828
  }
@@ -5444,7 +5426,7 @@ var RoutstrClient = class {
5444
5426
  tryNextProvider = true;
5445
5427
  }
5446
5428
  }
5447
- if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 429 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
5429
+ if ((status === 401 || status === 403 || status === 404 || status === 413 || status === 400 || status === 429 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
5448
5430
  this._log(
5449
5431
  "DEBUG",
5450
5432
  `[RoutstrClient] _handleErrorResponse: Status ${status} (${status === 429 ? "rate limited" : "auth/server error"}), attempting refund for ${baseUrl}, mode=${this.mode}`
@@ -5948,7 +5930,8 @@ async function resolveRouteRequestContext(options) {
5948
5930
  mode = "apikeys",
5949
5931
  usageTrackingDriver,
5950
5932
  sdkStore,
5951
- providerManager: providedProviderManager
5933
+ providerManager: providedProviderManager,
5934
+ logger
5952
5935
  } = options;
5953
5936
  let modelManager;
5954
5937
  let providers;
@@ -5960,7 +5943,8 @@ async function resolveRouteRequestContext(options) {
5960
5943
  }
5961
5944
  } else {
5962
5945
  modelManager = new ModelManager(discoveryAdapter, {
5963
- includeProviderUrls: forcedProvider ? [forcedProvider, ...includeProviderUrls] : includeProviderUrls
5946
+ includeProviderUrls: forcedProvider ? [forcedProvider, ...includeProviderUrls] : includeProviderUrls,
5947
+ logger
5964
5948
  });
5965
5949
  providers = await modelManager.bootstrapProviders(torMode);
5966
5950
  if (providers.length === 0) {
@@ -5968,7 +5952,7 @@ async function resolveRouteRequestContext(options) {
5968
5952
  }
5969
5953
  await modelManager.fetchModels(providers, forceRefresh);
5970
5954
  }
5971
- const providerManager = providedProviderManager ?? new ProviderManager(providerRegistry, sdkStore);
5955
+ const providerManager = providedProviderManager ?? new ProviderManager(providerRegistry, sdkStore, logger);
5972
5956
  let baseUrl;
5973
5957
  let selectedModel;
5974
5958
  if (forcedProvider) {
@@ -6013,7 +5997,7 @@ async function resolveRouteRequestContext(options) {
6013
5997
  providerRegistry,
6014
5998
  "min",
6015
5999
  mode,
6016
- { usageTrackingDriver, sdkStore, providerManager }
6000
+ { usageTrackingDriver, sdkStore, providerManager, logger }
6017
6001
  );
6018
6002
  if (debugLevel) {
6019
6003
  client.setDebugLevel(debugLevel);
@@ -6096,6 +6080,7 @@ exports.SDK_STORAGE_KEYS = SDK_STORAGE_KEYS;
6096
6080
  exports.StreamProcessor = StreamProcessor;
6097
6081
  exports.StreamingError = StreamingError;
6098
6082
  exports.TokenOperationError = TokenOperationError;
6083
+ exports.consoleLogger = consoleLogger;
6099
6084
  exports.createBunSqliteDriver = createBunSqliteDriver;
6100
6085
  exports.createBunSqliteUsageTrackingDriver = createBunSqliteUsageTrackingDriver;
6101
6086
  exports.createDiscoveryAdapterFromStore = createDiscoveryAdapterFromStore;
@@ -6121,6 +6106,7 @@ exports.inspectSSEWebStream = inspectSSEWebStream;
6121
6106
  exports.isOnionUrl = isOnionUrl;
6122
6107
  exports.isTorContext = isTorContext;
6123
6108
  exports.localStorageDriver = localStorageDriver;
6109
+ exports.noopLogger = noopLogger;
6124
6110
  exports.normalizeProviderUrl = normalizeProviderUrl;
6125
6111
  exports.routeRequests = routeRequests;
6126
6112
  exports.setDefaultUsageTrackingDriver = setDefaultUsageTrackingDriver;