@routstr/sdk 0.2.5 → 0.2.6

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.
package/dist/index.mjs CHANGED
@@ -2,16 +2,8 @@ import { RelayPool, onlyEvents } from 'applesauce-relay';
2
2
  import { EventStore } from 'applesauce-core';
3
3
  import { tap } from 'rxjs';
4
4
  import { createStore } from 'zustand/vanilla';
5
- import { getDecodedToken } from '@cashu/cashu-ts';
6
5
  import { Transform, Readable } from 'stream';
7
6
 
8
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
- }) : x)(function(x) {
11
- if (typeof require !== "undefined") return require.apply(this, arguments);
12
- throw Error('Dynamic require of "' + x + '" is not supported');
13
- });
14
-
15
7
  // core/errors.ts
16
8
  var InsufficientBalanceError = class extends Error {
17
9
  constructor(required, available, maxMintBalance = 0, maxMintUrl = "", customMessage) {
@@ -786,13 +778,8 @@ var CashuSpender = class {
786
778
  normalizedMintBalances[url] = balanceInSats;
787
779
  totalMintBalance += balanceInSats;
788
780
  }
789
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
790
781
  const providerBalances = {};
791
782
  let totalProviderBalance = 0;
792
- for (const pending of pendingDistribution) {
793
- providerBalances[pending.baseUrl] = (providerBalances[pending.baseUrl] || 0) + pending.amount;
794
- totalProviderBalance += pending.amount;
795
- }
796
783
  const apiKeys = this.storageAdapter.getAllApiKeys();
797
784
  for (const apiKey of apiKeys) {
798
785
  if (!providerBalances[apiKey.baseUrl]) {
@@ -1013,27 +1000,11 @@ var CashuSpender = class {
1013
1000
  };
1014
1001
  }
1015
1002
  }
1016
- if (token && baseUrl) {
1017
- try {
1018
- this.storageAdapter.setToken(baseUrl, token);
1019
- } catch (error) {
1020
- if (error instanceof Error && error.message.includes("Token already exists")) {
1021
- this._log(
1022
- "DEBUG",
1023
- `[CashuSpender] _spendInternal: Token already exists for ${baseUrl}, receiving newly created token and using existing`
1024
- );
1025
- const receiveResult = await this.receiveToken(token);
1026
- if (receiveResult.success) {
1027
- this._log(
1028
- "DEBUG",
1029
- `[CashuSpender] _spendInternal: Token restored successfully, amount=${receiveResult.amount}`
1030
- );
1031
- }
1032
- token = this.storageAdapter.getToken(baseUrl);
1033
- } else {
1034
- throw error;
1035
- }
1036
- }
1003
+ if (token) {
1004
+ this._log(
1005
+ "DEBUG",
1006
+ `[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`
1007
+ );
1037
1008
  }
1038
1009
  this._logTransaction("spend", {
1039
1010
  amount: spentAmount,
@@ -1054,19 +1025,19 @@ var CashuSpender = class {
1054
1025
  };
1055
1026
  }
1056
1027
  /**
1057
- * Try to reuse an existing token
1028
+ * Try to reuse an existing API key
1058
1029
  */
1059
1030
  async _tryReuseToken(baseUrl, amount, mintUrl) {
1060
- const storedToken = this.storageAdapter.getToken(baseUrl);
1061
- if (!storedToken) return null;
1062
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
1063
- const balanceForBaseUrl = pendingDistribution.find((b) => b.baseUrl === baseUrl)?.amount || 0;
1064
- this._log("DEBUG", "RESUINGDSR GSODGNSD", balanceForBaseUrl, amount);
1031
+ const apiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
1032
+ if (!apiKeyEntry) return null;
1033
+ const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
1034
+ const balanceForBaseUrl = apiKeyDistribution.find((b) => b.baseUrl === baseUrl)?.amount || 0;
1035
+ this._log("DEBUG", "Reusing API key", balanceForBaseUrl, amount);
1065
1036
  if (balanceForBaseUrl > amount) {
1066
1037
  const units = this.walletAdapter.getMintUnits();
1067
1038
  const unit = units[mintUrl] || "sat";
1068
1039
  return {
1069
- token: storedToken,
1040
+ token: apiKeyEntry.key,
1070
1041
  status: "success",
1071
1042
  balance: balanceForBaseUrl,
1072
1043
  unit
@@ -1077,7 +1048,8 @@ var CashuSpender = class {
1077
1048
  const topUpResult = await this.balanceManager.topUp({
1078
1049
  mintUrl,
1079
1050
  baseUrl,
1080
- amount: topUpAmount
1051
+ amount: topUpAmount,
1052
+ token: apiKeyEntry.key
1081
1053
  });
1082
1054
  this._log("DEBUG", "TOPUP ", topUpResult);
1083
1055
  if (topUpResult.success && topUpResult.toppedUpAmount) {
@@ -1091,7 +1063,7 @@ var CashuSpender = class {
1091
1063
  status: "success"
1092
1064
  });
1093
1065
  return {
1094
- token: storedToken,
1066
+ token: apiKeyEntry.key,
1095
1067
  status: "success",
1096
1068
  balance: newBalance,
1097
1069
  unit
@@ -1099,84 +1071,108 @@ var CashuSpender = class {
1099
1071
  }
1100
1072
  const providerBalance = await this._getProviderTokenBalance(
1101
1073
  baseUrl,
1102
- storedToken
1074
+ apiKeyEntry.key
1103
1075
  );
1104
1076
  this._log("DEBUG", providerBalance);
1105
1077
  if (providerBalance <= 0) {
1106
- this.storageAdapter.removeToken(baseUrl);
1078
+ this.storageAdapter.removeApiKey(baseUrl);
1107
1079
  }
1108
1080
  }
1109
1081
  return null;
1110
1082
  }
1111
1083
  /**
1112
- * Refund specific providers without retrying spend
1084
+ * Refund all xcashu tokens from storage and increment tryCounts on failure.
1085
+ * Reuses receiveToken from BalanceManager/CashuSpender for receiving refunds.
1086
+ * @param mintUrl - The mint URL for receiving tokens
1087
+ * @param excludeBaseUrls - Base URLs to exclude from refund (optional)
1088
+ * @returns Results for each xcashu token refund attempt
1113
1089
  */
1114
- async refundProviders(baseUrls, mintUrl, refundApiKeys = false, forceRefund) {
1090
+ async refundXcashuTokens(mintUrl, excludeBaseUrls) {
1115
1091
  const results = [];
1116
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
1117
- const toRefund = pendingDistribution.filter(
1118
- (p) => baseUrls.includes(p.baseUrl)
1119
- );
1120
- const refundResults = await Promise.allSettled(
1121
- toRefund.map(async (pending) => {
1122
- const token = this.storageAdapter.getToken(pending.baseUrl);
1123
- this._log("DEBUG", token, this.balanceManager);
1124
- if (!token || !this.balanceManager) {
1125
- return { baseUrl: pending.baseUrl, success: false };
1126
- }
1127
- const tokenBalance = await this.balanceManager.getTokenBalance(
1128
- token,
1129
- pending.baseUrl
1130
- );
1131
- if (tokenBalance.reserved > 0) {
1132
- return { baseUrl: pending.baseUrl, success: false };
1133
- }
1134
- const result = await this.balanceManager.refund({
1135
- mintUrl,
1136
- baseUrl: pending.baseUrl,
1137
- token
1138
- });
1139
- this._log("DEBUG", result);
1140
- if (result.success) {
1141
- this.storageAdapter.removeToken(pending.baseUrl);
1142
- }
1143
- return { baseUrl: pending.baseUrl, success: result.success };
1144
- })
1145
- );
1146
- results.push(
1147
- ...refundResults.map(
1148
- (r) => r.status === "fulfilled" ? r.value : { baseUrl: "", success: false }
1149
- )
1150
- );
1151
- if (refundApiKeys) {
1152
- const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
1153
- const apiKeysToRefund = apiKeyDistribution.filter(
1154
- (p) => baseUrls.includes(p.baseUrl)
1155
- );
1156
- for (const apiKeyEntry of apiKeysToRefund) {
1157
- const apiKeyEntryFull = this.storageAdapter.getApiKey(
1158
- apiKeyEntry.baseUrl
1159
- );
1160
- if (apiKeyEntryFull && this.balanceManager) {
1161
- const refundResult = await this.balanceManager.refundApiKey({
1162
- mintUrl,
1163
- baseUrl: apiKeyEntry.baseUrl,
1164
- apiKey: apiKeyEntryFull.key,
1165
- forceRefund
1166
- });
1167
- if (refundResult.success) {
1168
- this.storageAdapter.updateApiKeyBalance(apiKeyEntry.baseUrl, 0);
1092
+ const xcashuTokens = this.storageAdapter.getXcashuTokens();
1093
+ const excludedUrls = new Set(excludeBaseUrls || []);
1094
+ for (const [baseUrl, tokens] of Object.entries(xcashuTokens)) {
1095
+ if (excludedUrls.has(baseUrl)) continue;
1096
+ for (const xcashuToken of tokens) {
1097
+ try {
1098
+ const receiveResult = await this.receiveToken(xcashuToken.token);
1099
+ if (receiveResult.success) {
1100
+ this.storageAdapter.removeXcashuToken(baseUrl, xcashuToken.token);
1101
+ results.push({
1102
+ baseUrl,
1103
+ token: xcashuToken.token,
1104
+ success: true
1105
+ });
1106
+ this._log(
1107
+ "DEBUG",
1108
+ `[CashuSpender] refundXcashuTokens: Successfully refunded xcashu token for ${baseUrl}, amount=${receiveResult.amount}`
1109
+ );
1110
+ } else {
1111
+ const currentTryCount = xcashuToken.tryCount ?? 0;
1112
+ const newTryCount = currentTryCount + 1;
1113
+ this.storageAdapter.updateXcashuTokenTryCount(xcashuToken.token, newTryCount);
1114
+ results.push({
1115
+ baseUrl,
1116
+ token: xcashuToken.token,
1117
+ success: false,
1118
+ error: receiveResult.message ?? "Refund failed"
1119
+ });
1120
+ this._log(
1121
+ "DEBUG",
1122
+ `[CashuSpender] refundXcashuTokens: Failed to refund xcashu token for ${baseUrl}, incremented tryCount to ${newTryCount}`
1123
+ );
1169
1124
  }
1125
+ } catch (error) {
1126
+ const currentTryCount = xcashuToken.tryCount ?? 0;
1127
+ const newTryCount = currentTryCount + 1;
1128
+ this.storageAdapter.updateXcashuTokenTryCount(xcashuToken.token, newTryCount);
1129
+ const errorMessage = error instanceof Error ? error.message : String(error);
1170
1130
  results.push({
1171
- baseUrl: apiKeyEntry.baseUrl,
1172
- success: refundResult.success
1131
+ baseUrl,
1132
+ token: xcashuToken.token,
1133
+ success: false,
1134
+ error: errorMessage
1173
1135
  });
1136
+ this._log(
1137
+ "ERROR",
1138
+ `[CashuSpender] refundXcashuTokens: Exception during refund for ${baseUrl}: ${errorMessage}, incremented tryCount to ${newTryCount}`
1139
+ );
1140
+ }
1141
+ }
1142
+ }
1143
+ return results;
1144
+ }
1145
+ /**
1146
+ * Refund specific providers without retrying spend
1147
+ */
1148
+ async refundProviders(mintUrl, forceRefund) {
1149
+ const results = [];
1150
+ const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
1151
+ for (const apiKeyEntry of apiKeyDistribution) {
1152
+ const apiKeyEntryFull = this.storageAdapter.getApiKey(
1153
+ apiKeyEntry.baseUrl
1154
+ );
1155
+ if (apiKeyEntryFull && this.balanceManager) {
1156
+ const refundResult = await this.balanceManager.refundApiKey({
1157
+ mintUrl,
1158
+ baseUrl: apiKeyEntry.baseUrl,
1159
+ apiKey: apiKeyEntryFull.key,
1160
+ forceRefund
1161
+ });
1162
+ if (refundResult.success) {
1163
+ this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
1174
1164
  } else {
1175
- results.push({
1176
- baseUrl: apiKeyEntry.baseUrl,
1177
- success: false
1178
- });
1165
+ this.storageAdapter.updateApiKeyBalance(apiKeyEntry.baseUrl, apiKeyEntry.amount);
1179
1166
  }
1167
+ results.push({
1168
+ baseUrl: apiKeyEntry.baseUrl,
1169
+ success: refundResult.success
1170
+ });
1171
+ } else {
1172
+ results.push({
1173
+ baseUrl: apiKeyEntry.baseUrl,
1174
+ success: false
1175
+ });
1180
1176
  }
1181
1177
  }
1182
1178
  return results;
@@ -1261,13 +1257,8 @@ var BalanceManager = class {
1261
1257
  normalizedMintBalances[url] = balanceInSats;
1262
1258
  totalMintBalance += balanceInSats;
1263
1259
  }
1264
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
1265
1260
  const providerBalances = {};
1266
1261
  let totalProviderBalance = 0;
1267
- for (const pending of pendingDistribution) {
1268
- providerBalances[pending.baseUrl] = (providerBalances[pending.baseUrl] || 0) + pending.amount;
1269
- totalProviderBalance += pending.amount;
1270
- }
1271
1262
  const apiKeys = this.storageAdapter.getAllApiKeys();
1272
1263
  for (const apiKey of apiKeys) {
1273
1264
  if (!providerBalances[apiKey.baseUrl]) {
@@ -1282,57 +1273,6 @@ var BalanceManager = class {
1282
1273
  mintBalances: normalizedMintBalances
1283
1274
  };
1284
1275
  }
1285
- /**
1286
- * Unified refund - handles both NIP-60 and legacy wallet refunds
1287
- */
1288
- async refund(options) {
1289
- const { mintUrl, baseUrl, token: providedToken } = options;
1290
- const storedToken = providedToken || this.storageAdapter.getToken(baseUrl);
1291
- if (!storedToken) {
1292
- console.log("[BalanceManager] No token to refund, returning early");
1293
- return { success: true, message: "No API key to refund" };
1294
- }
1295
- let fetchResult;
1296
- try {
1297
- fetchResult = await this._fetchRefundToken(baseUrl, storedToken);
1298
- if (!fetchResult.success) {
1299
- return {
1300
- success: false,
1301
- message: fetchResult.error || "Refund failed",
1302
- requestId: fetchResult.requestId
1303
- };
1304
- }
1305
- if (!fetchResult.token) {
1306
- return {
1307
- success: false,
1308
- message: "No token received from refund",
1309
- requestId: fetchResult.requestId
1310
- };
1311
- }
1312
- if (fetchResult.error === "No balance to refund") {
1313
- console.log(
1314
- "[BalanceManager] No balance to refund, removing stored token"
1315
- );
1316
- this.storageAdapter.removeToken(baseUrl);
1317
- return { success: true, message: "No balance to refund" };
1318
- }
1319
- const receiveResult = await this.cashuSpender.receiveToken(
1320
- fetchResult.token
1321
- );
1322
- const totalAmountMsat = receiveResult.unit === "msat" ? receiveResult.amount : receiveResult.amount * 1e3;
1323
- if (!providedToken) {
1324
- this.storageAdapter.removeToken(baseUrl);
1325
- }
1326
- return {
1327
- success: receiveResult.success,
1328
- refundedAmount: totalAmountMsat,
1329
- requestId: fetchResult.requestId
1330
- };
1331
- } catch (error) {
1332
- console.error("[BalanceManager] Refund error", error);
1333
- return this._handleRefundError(error, mintUrl, fetchResult?.requestId);
1334
- }
1335
- }
1336
1276
  /**
1337
1277
  * Refund API key balance - convert remaining API key balance to cashu token
1338
1278
  * @param options - Refund options including forceRefund flag
@@ -1468,8 +1408,9 @@ var BalanceManager = class {
1468
1408
  if (!amount || amount <= 0) {
1469
1409
  return { success: false, message: "Invalid top up amount" };
1470
1410
  }
1471
- const storedToken = providedToken || this.storageAdapter.getToken(baseUrl);
1472
- if (!storedToken) {
1411
+ const apiKeyEntry = providedToken ? null : this.storageAdapter.getApiKey(baseUrl);
1412
+ const apiKey = providedToken || apiKeyEntry?.key;
1413
+ if (!apiKey) {
1473
1414
  return { success: false, message: "No API key available for top up" };
1474
1415
  }
1475
1416
  let cashuToken = null;
@@ -1489,7 +1430,7 @@ var BalanceManager = class {
1489
1430
  cashuToken = tokenResult.token;
1490
1431
  const topUpResult = await this._postTopUp(
1491
1432
  baseUrl,
1492
- storedToken,
1433
+ apiKey,
1493
1434
  cashuToken
1494
1435
  );
1495
1436
  requestId = topUpResult.requestId;
@@ -1704,38 +1645,11 @@ var BalanceManager = class {
1704
1645
  return candidates;
1705
1646
  }
1706
1647
  async _refundOtherProvidersForTopUp(baseUrl, mintUrl, retryCount) {
1707
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
1708
1648
  const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
1709
1649
  const forceRefund = retryCount >= 2;
1710
- const toRefund = pendingDistribution.filter(
1711
- (pending) => pending.baseUrl !== baseUrl
1712
- );
1713
1650
  const apiKeysToRefund = apiKeyDistribution.filter(
1714
1651
  (apiKey) => apiKey.baseUrl !== baseUrl && apiKey.amount > 0
1715
1652
  );
1716
- const tokenRefundResults = await Promise.allSettled(
1717
- toRefund.map(async (pending) => {
1718
- const token = this.storageAdapter.getToken(pending.baseUrl);
1719
- if (!token) {
1720
- return { baseUrl: pending.baseUrl, success: false };
1721
- }
1722
- const tokenBalance = await this.getTokenBalance(token, pending.baseUrl);
1723
- if (tokenBalance.reserved > 0) {
1724
- return { baseUrl: pending.baseUrl, success: false };
1725
- }
1726
- const result = await this.refund({
1727
- mintUrl,
1728
- baseUrl: pending.baseUrl,
1729
- token
1730
- });
1731
- return { baseUrl: pending.baseUrl, success: result.success };
1732
- })
1733
- );
1734
- for (const result of tokenRefundResults) {
1735
- if (result.status === "fulfilled" && result.value.success) {
1736
- this.storageAdapter.removeToken(result.value.baseUrl);
1737
- }
1738
- }
1739
1653
  const apiKeyRefundResults = await Promise.allSettled(
1740
1654
  apiKeysToRefund.map(async (apiKeyEntry) => {
1741
1655
  const fullApiKeyEntry = this.storageAdapter.getApiKey(
@@ -1759,77 +1673,6 @@ var BalanceManager = class {
1759
1673
  }
1760
1674
  }
1761
1675
  }
1762
- /**
1763
- * Fetch refund token from provider API
1764
- */
1765
- async _fetchRefundToken(baseUrl, storedToken) {
1766
- if (!baseUrl) {
1767
- return {
1768
- success: false,
1769
- error: "No base URL configured"
1770
- };
1771
- }
1772
- const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
1773
- const url = `${normalizedBaseUrl}v1/wallet/refund`;
1774
- const controller = new AbortController();
1775
- const timeoutId = setTimeout(() => {
1776
- controller.abort();
1777
- }, 6e4);
1778
- try {
1779
- const response = await fetch(url, {
1780
- method: "POST",
1781
- headers: {
1782
- Authorization: `Bearer ${storedToken}`,
1783
- "Content-Type": "application/json"
1784
- },
1785
- signal: controller.signal
1786
- });
1787
- clearTimeout(timeoutId);
1788
- const requestId = response.headers.get("x-routstr-request-id") || void 0;
1789
- if (!response.ok) {
1790
- const errorData = await response.json().catch(() => ({}));
1791
- if (response.status === 400 && errorData?.detail === "No balance to refund") {
1792
- this.storageAdapter.removeToken(baseUrl);
1793
- return {
1794
- success: false,
1795
- requestId,
1796
- error: "No balance to refund"
1797
- };
1798
- }
1799
- return {
1800
- success: false,
1801
- requestId,
1802
- error: `Refund request failed with status ${response.status}: ${errorData?.detail || response.statusText}`
1803
- };
1804
- }
1805
- const data = await response.json();
1806
- console.log("refund rsule", data);
1807
- return {
1808
- success: true,
1809
- token: data.token,
1810
- requestId
1811
- };
1812
- } catch (error) {
1813
- clearTimeout(timeoutId);
1814
- console.error("[BalanceManager._fetchRefundToken] Fetch error", error);
1815
- if (error instanceof Error) {
1816
- if (error.name === "AbortError") {
1817
- return {
1818
- success: false,
1819
- error: "Request timed out after 1 minute"
1820
- };
1821
- }
1822
- return {
1823
- success: false,
1824
- error: error.message
1825
- };
1826
- }
1827
- return {
1828
- success: false,
1829
- error: "Unknown error occurred during refund request"
1830
- };
1831
- }
1832
- }
1833
1676
  /**
1834
1677
  * Post topup request to provider API
1835
1678
  */
@@ -2874,38 +2717,54 @@ var createMemoryDriver = (seed) => {
2874
2717
  var isBun = () => {
2875
2718
  return typeof process.versions.bun !== "undefined";
2876
2719
  };
2877
- var createDatabase = (dbPath) => {
2720
+ var cachedDbModule = null;
2721
+ var loadDatabase = async (dbPath) => {
2878
2722
  if (isBun()) {
2879
2723
  throw new Error(
2880
- "SQLite driver not supported in Bun. Use createMemoryDriver() instead."
2724
+ "SQLite driver not supported in Bun. Use createBunSqliteDriver() instead."
2881
2725
  );
2882
2726
  }
2883
- let Database = null;
2884
2727
  try {
2885
- Database = __require("better-sqlite3");
2728
+ if (!cachedDbModule) {
2729
+ cachedDbModule = (await import('better-sqlite3')).default;
2730
+ }
2731
+ return new cachedDbModule(dbPath);
2886
2732
  } catch (error) {
2887
2733
  throw new Error(
2888
2734
  `better-sqlite3 is required for sqlite storage. Install it to use sqlite storage. (${error})`
2889
2735
  );
2890
2736
  }
2891
- return new Database(dbPath);
2892
2737
  };
2893
2738
  var createSqliteDriver = (options = {}) => {
2894
2739
  const dbPath = options.dbPath || "routstr.sqlite";
2895
2740
  const tableName = options.tableName || "sdk_storage";
2896
- const db = createDatabase(dbPath);
2897
- db.exec(
2898
- `CREATE TABLE IF NOT EXISTS ${tableName} (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
2899
- );
2900
- const selectStmt = db.prepare(`SELECT value FROM ${tableName} WHERE key = ?`);
2901
- const upsertStmt = db.prepare(
2902
- `INSERT INTO ${tableName} (key, value) VALUES (?, ?)
2741
+ let db;
2742
+ let selectStmt;
2743
+ let upsertStmt;
2744
+ let deleteStmt;
2745
+ const initDb = async () => {
2746
+ if (!db) {
2747
+ db = await loadDatabase(dbPath);
2748
+ db.exec(
2749
+ `CREATE TABLE IF NOT EXISTS ${tableName} (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
2750
+ );
2751
+ selectStmt = db.prepare(`SELECT value FROM ${tableName} WHERE key = ?`);
2752
+ upsertStmt = db.prepare(
2753
+ `INSERT INTO ${tableName} (key, value) VALUES (?, ?)
2903
2754
  ON CONFLICT(key) DO UPDATE SET value = excluded.value`
2904
- );
2905
- const deleteStmt = db.prepare(`DELETE FROM ${tableName} WHERE key = ?`);
2755
+ );
2756
+ deleteStmt = db.prepare(`DELETE FROM ${tableName} WHERE key = ?`);
2757
+ }
2758
+ };
2759
+ const ensureInit = async () => {
2760
+ if (!db) {
2761
+ await initDb();
2762
+ }
2763
+ };
2906
2764
  return {
2907
2765
  async getItem(key, defaultValue) {
2908
2766
  try {
2767
+ await ensureInit();
2909
2768
  const row = selectStmt.get(key);
2910
2769
  if (!row || typeof row.value !== "string") return defaultValue;
2911
2770
  try {
@@ -2923,6 +2782,7 @@ var createSqliteDriver = (options = {}) => {
2923
2782
  },
2924
2783
  async setItem(key, value) {
2925
2784
  try {
2785
+ await ensureInit();
2926
2786
  upsertStmt.run(key, JSON.stringify(value));
2927
2787
  } catch (error) {
2928
2788
  console.error(`SQLite setItem failed for key "${key}":`, error);
@@ -2930,6 +2790,7 @@ var createSqliteDriver = (options = {}) => {
2930
2790
  },
2931
2791
  async removeItem(key) {
2932
2792
  try {
2793
+ await ensureInit();
2933
2794
  deleteStmt.run(key);
2934
2795
  } catch (error) {
2935
2796
  console.error(`SQLite removeItem failed for key "${key}":`, error);
@@ -2937,6 +2798,54 @@ var createSqliteDriver = (options = {}) => {
2937
2798
  }
2938
2799
  };
2939
2800
  };
2801
+ async function createBunSqliteDriver(dbPath) {
2802
+ const SQLite = (await import(
2803
+ /* webpackIgnore: true */
2804
+ 'bun:sqlite'
2805
+ )).default;
2806
+ const db = new SQLite(dbPath);
2807
+ db.run(`
2808
+ CREATE TABLE IF NOT EXISTS sdk_storage (
2809
+ key TEXT PRIMARY KEY,
2810
+ value TEXT NOT NULL
2811
+ )
2812
+ `);
2813
+ return {
2814
+ async getItem(key, defaultValue) {
2815
+ try {
2816
+ const row = db.query("SELECT value FROM sdk_storage WHERE key = ?").get(key);
2817
+ if (!row || typeof row.value !== "string") return defaultValue;
2818
+ try {
2819
+ return JSON.parse(row.value);
2820
+ } catch (parseError) {
2821
+ if (typeof defaultValue === "string") {
2822
+ return row.value;
2823
+ }
2824
+ throw parseError;
2825
+ }
2826
+ } catch (error) {
2827
+ console.error(`SQLite getItem failed for key "${key}":`, error);
2828
+ return defaultValue;
2829
+ }
2830
+ },
2831
+ async setItem(key, value) {
2832
+ try {
2833
+ db.query(
2834
+ "INSERT INTO sdk_storage (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
2835
+ ).run(key, JSON.stringify(value));
2836
+ } catch (error) {
2837
+ console.error(`SQLite setItem failed for key "${key}":`, error);
2838
+ }
2839
+ },
2840
+ async removeItem(key) {
2841
+ try {
2842
+ db.query("DELETE FROM sdk_storage WHERE key = ?").run(key);
2843
+ } catch (error) {
2844
+ console.error(`SQLite removeItem failed for key "${key}":`, error);
2845
+ }
2846
+ }
2847
+ };
2848
+ }
2940
2849
 
2941
2850
  // storage/drivers/indexedDB.ts
2942
2851
  var isBrowser = typeof indexedDB !== "undefined";
@@ -3042,9 +2951,9 @@ var SDK_STORAGE_KEYS = {
3042
2951
  INFO_FROM_ALL_PROVIDERS: "info_from_all_providers",
3043
2952
  LAST_MODELS_UPDATE: "lastModelsUpdate",
3044
2953
  LAST_BASE_URLS_UPDATE: "lastBaseUrlsUpdate",
3045
- LOCAL_CASHU_TOKENS: "local_cashu_tokens",
3046
2954
  API_KEYS: "api_keys",
3047
2955
  CHILD_KEYS: "child_keys",
2956
+ XCASHU_TOKENS: "xcashu_tokens",
3048
2957
  ROUTSTR21_MODELS: "routstr21Models",
3049
2958
  LAST_ROUTSTR21_MODELS_UPDATE: "lastRoutstr21ModelsUpdate",
3050
2959
  CACHED_RECEIVE_TOKENS: "cached_receive_tokens",
@@ -3235,21 +3144,23 @@ var normalizeBaseUrl2 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUr
3235
3144
  var isBun2 = () => {
3236
3145
  return typeof process.versions.bun !== "undefined";
3237
3146
  };
3238
- var createDatabase2 = (dbPath) => {
3147
+ var cachedDbModule2 = null;
3148
+ var loadDatabase2 = async (dbPath) => {
3239
3149
  if (isBun2()) {
3240
3150
  throw new Error(
3241
3151
  "SQLite driver not supported in Bun. Use createMemoryDriver() instead."
3242
3152
  );
3243
3153
  }
3244
- let Database = null;
3245
3154
  try {
3246
- Database = __require("better-sqlite3");
3155
+ if (!cachedDbModule2) {
3156
+ cachedDbModule2 = (await import('better-sqlite3')).default;
3157
+ }
3158
+ return new cachedDbModule2(dbPath);
3247
3159
  } catch (error) {
3248
3160
  throw new Error(
3249
3161
  `better-sqlite3 is required for sqlite usage tracking. Install it to use sqlite storage. (${error})`
3250
3162
  );
3251
3163
  }
3252
- return new Database(dbPath);
3253
3164
  };
3254
3165
  var buildWhereClause = (options = {}) => {
3255
3166
  const clauses = [];
@@ -3286,38 +3197,49 @@ var buildWhereClause = (options = {}) => {
3286
3197
  var createSqliteUsageTrackingDriver = (options = {}) => {
3287
3198
  const dbPath = options.dbPath || "routstr.sqlite";
3288
3199
  const tableName = options.tableName || "usage_tracking";
3289
- const db = createDatabase2(dbPath);
3290
3200
  const legacyStorageDriver = options.legacyStorageDriver;
3291
- db.exec(`
3292
- CREATE TABLE IF NOT EXISTS ${tableName} (
3293
- id TEXT PRIMARY KEY,
3294
- timestamp INTEGER NOT NULL,
3295
- model_id TEXT NOT NULL,
3296
- base_url TEXT NOT NULL,
3297
- request_id TEXT NOT NULL,
3298
- cost REAL NOT NULL,
3299
- sats_cost REAL NOT NULL,
3300
- prompt_tokens INTEGER NOT NULL,
3301
- completion_tokens INTEGER NOT NULL,
3302
- total_tokens INTEGER NOT NULL,
3303
- client TEXT,
3304
- session_id TEXT,
3305
- tags TEXT
3306
- );
3307
- CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp);
3308
- CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id);
3309
- CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url);
3310
- CREATE INDEX IF NOT EXISTS idx_${tableName}_session_id ON ${tableName}(session_id);
3311
- CREATE INDEX IF NOT EXISTS idx_${tableName}_client ON ${tableName}(client);
3312
- `);
3313
- const insertStmt = db.prepare(`
3314
- INSERT OR REPLACE INTO ${tableName} (
3315
- id, timestamp, model_id, base_url, request_id,
3316
- cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
3317
- client, session_id, tags
3318
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3319
- `);
3201
+ let db;
3202
+ let insertStmt;
3320
3203
  let migrationComplete = false;
3204
+ const initDb = async () => {
3205
+ if (!db) {
3206
+ db = await loadDatabase2(dbPath);
3207
+ db.exec(`
3208
+ CREATE TABLE IF NOT EXISTS ${tableName} (
3209
+ id TEXT PRIMARY KEY,
3210
+ timestamp INTEGER NOT NULL,
3211
+ model_id TEXT NOT NULL,
3212
+ base_url TEXT NOT NULL,
3213
+ request_id TEXT NOT NULL,
3214
+ cost REAL NOT NULL,
3215
+ sats_cost REAL NOT NULL,
3216
+ prompt_tokens INTEGER NOT NULL,
3217
+ completion_tokens INTEGER NOT NULL,
3218
+ total_tokens INTEGER NOT NULL,
3219
+ client TEXT,
3220
+ session_id TEXT,
3221
+ tags TEXT
3222
+ );
3223
+ CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp);
3224
+ CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id);
3225
+ CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url);
3226
+ CREATE INDEX IF NOT EXISTS idx_${tableName}_session_id ON ${tableName}(session_id);
3227
+ CREATE INDEX IF NOT EXISTS idx_${tableName}_client ON ${tableName}(client);
3228
+ `);
3229
+ insertStmt = db.prepare(`
3230
+ INSERT OR REPLACE INTO ${tableName} (
3231
+ id, timestamp, model_id, base_url, request_id,
3232
+ cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
3233
+ client, session_id, tags
3234
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3235
+ `);
3236
+ }
3237
+ };
3238
+ const ensureInit = async () => {
3239
+ if (!db) {
3240
+ await initDb();
3241
+ }
3242
+ };
3321
3243
  const appendOne = (entry) => {
3322
3244
  insertStmt.run(
3323
3245
  entry.id,
@@ -3375,19 +3297,23 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
3375
3297
  });
3376
3298
  return {
3377
3299
  async migrate() {
3300
+ await ensureInit();
3378
3301
  await ensureMigrated();
3379
3302
  },
3380
3303
  async append(entry) {
3304
+ await ensureInit();
3381
3305
  await ensureMigrated();
3382
3306
  appendOne(entry);
3383
3307
  },
3384
3308
  async appendMany(entries) {
3309
+ await ensureInit();
3385
3310
  await ensureMigrated();
3386
3311
  for (const entry of entries) {
3387
3312
  appendOne(entry);
3388
3313
  }
3389
3314
  },
3390
3315
  async list(options2 = {}) {
3316
+ await ensureInit();
3391
3317
  await ensureMigrated();
3392
3318
  const { sql, params } = buildWhereClause(options2);
3393
3319
  const limitSql = typeof options2.limit === "number" ? " LIMIT ?" : "";
@@ -3400,6 +3326,7 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
3400
3326
  return rows.map(mapRow);
3401
3327
  },
3402
3328
  async count(options2 = {}) {
3329
+ await ensureInit();
3403
3330
  await ensureMigrated();
3404
3331
  const { sql, params } = buildWhereClause(options2);
3405
3332
  const stmt = db.prepare(`SELECT COUNT(*) as count FROM ${tableName} ${sql}`);
@@ -3407,20 +3334,197 @@ var createSqliteUsageTrackingDriver = (options = {}) => {
3407
3334
  return Number(row?.count ?? 0);
3408
3335
  },
3409
3336
  async deleteOlderThan(timestamp) {
3337
+ await ensureInit();
3410
3338
  await ensureMigrated();
3411
3339
  const stmt = db.prepare(`DELETE FROM ${tableName} WHERE timestamp < ?`);
3412
3340
  const result = stmt.run(timestamp);
3413
3341
  return result.changes;
3414
3342
  },
3415
3343
  async clear() {
3344
+ await ensureInit();
3416
3345
  await ensureMigrated();
3417
3346
  db.prepare(`DELETE FROM ${tableName}`).run();
3418
3347
  }
3419
3348
  };
3420
3349
  };
3421
3350
 
3422
- // storage/usageTracking/memory.ts
3351
+ // storage/usageTracking/bunSqlite.ts
3352
+ var MIGRATION_MARKER_KEY3 = "usage_tracking_migration_v1";
3423
3353
  var normalizeBaseUrl3 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
3354
+ var buildWhereClause2 = (options = {}) => {
3355
+ const clauses = [];
3356
+ const params = [];
3357
+ if (typeof options.before === "number") {
3358
+ clauses.push("timestamp < ?");
3359
+ params.push(options.before);
3360
+ }
3361
+ if (typeof options.after === "number") {
3362
+ clauses.push("timestamp > ?");
3363
+ params.push(options.after);
3364
+ }
3365
+ if (options.modelId) {
3366
+ clauses.push("model_id = ?");
3367
+ params.push(options.modelId);
3368
+ }
3369
+ if (options.baseUrl) {
3370
+ clauses.push("base_url = ?");
3371
+ params.push(normalizeBaseUrl3(options.baseUrl));
3372
+ }
3373
+ if (options.sessionId) {
3374
+ clauses.push("session_id = ?");
3375
+ params.push(options.sessionId);
3376
+ }
3377
+ if (options.client) {
3378
+ clauses.push("client = ?");
3379
+ params.push(options.client);
3380
+ }
3381
+ return {
3382
+ sql: clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "",
3383
+ params
3384
+ };
3385
+ };
3386
+ var createBunSqliteUsageTrackingDriver = (options = {}) => {
3387
+ const dbPath = options.dbPath || "routstr.sqlite";
3388
+ const tableName = options.tableName || "usage_tracking";
3389
+ const legacyStorageDriver = options.legacyStorageDriver;
3390
+ const SQLiteDatabase = options.sqlite?.Database;
3391
+ let migrationPromise = null;
3392
+ if (!SQLiteDatabase) {
3393
+ throw new Error(
3394
+ "Bun SQLite Database constructor is required. Pass { sqlite: { Database } } when creating the driver."
3395
+ );
3396
+ }
3397
+ const db = new SQLiteDatabase(dbPath);
3398
+ db.run(`
3399
+ CREATE TABLE IF NOT EXISTS ${tableName} (
3400
+ id TEXT PRIMARY KEY,
3401
+ timestamp INTEGER NOT NULL,
3402
+ model_id TEXT NOT NULL,
3403
+ base_url TEXT NOT NULL,
3404
+ request_id TEXT NOT NULL,
3405
+ cost REAL NOT NULL,
3406
+ sats_cost REAL NOT NULL,
3407
+ prompt_tokens INTEGER NOT NULL,
3408
+ completion_tokens INTEGER NOT NULL,
3409
+ total_tokens INTEGER NOT NULL,
3410
+ client TEXT,
3411
+ session_id TEXT,
3412
+ tags TEXT
3413
+ )
3414
+ `);
3415
+ db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp)`);
3416
+ db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id)`);
3417
+ db.run(`CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url)`);
3418
+ const appendOne = (entry) => {
3419
+ db.query(`
3420
+ INSERT OR REPLACE INTO ${tableName} (
3421
+ id, timestamp, model_id, base_url, request_id,
3422
+ cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
3423
+ client, session_id, tags
3424
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3425
+ `).run(
3426
+ entry.id,
3427
+ entry.timestamp,
3428
+ entry.modelId,
3429
+ normalizeBaseUrl3(entry.baseUrl),
3430
+ entry.requestId,
3431
+ entry.cost,
3432
+ entry.satsCost,
3433
+ entry.promptTokens,
3434
+ entry.completionTokens,
3435
+ entry.totalTokens,
3436
+ entry.client ?? null,
3437
+ entry.sessionId ?? null,
3438
+ JSON.stringify(entry.tags ?? [])
3439
+ );
3440
+ };
3441
+ const mapRow = (row) => ({
3442
+ id: row.id,
3443
+ timestamp: row.timestamp,
3444
+ modelId: row.model_id,
3445
+ baseUrl: row.base_url,
3446
+ requestId: row.request_id,
3447
+ cost: row.cost,
3448
+ satsCost: row.sats_cost,
3449
+ promptTokens: row.prompt_tokens,
3450
+ completionTokens: row.completion_tokens,
3451
+ totalTokens: row.total_tokens,
3452
+ client: row.client ?? void 0,
3453
+ sessionId: row.session_id ?? void 0,
3454
+ tags: typeof row.tags === "string" ? JSON.parse(row.tags) : void 0
3455
+ });
3456
+ const ensureMigrated = async () => {
3457
+ if (!legacyStorageDriver) return;
3458
+ if (!migrationPromise) {
3459
+ migrationPromise = (async () => {
3460
+ const migrated = await legacyStorageDriver.getItem(
3461
+ MIGRATION_MARKER_KEY3,
3462
+ false
3463
+ );
3464
+ if (migrated) return;
3465
+ const legacyEntries = await legacyStorageDriver.getItem(
3466
+ SDK_STORAGE_KEYS.USAGE_TRACKING,
3467
+ []
3468
+ );
3469
+ if (legacyEntries.length > 0) {
3470
+ for (const entry of legacyEntries) {
3471
+ appendOne(entry);
3472
+ }
3473
+ await legacyStorageDriver.removeItem(SDK_STORAGE_KEYS.USAGE_TRACKING);
3474
+ }
3475
+ await legacyStorageDriver.setItem(MIGRATION_MARKER_KEY3, true);
3476
+ })();
3477
+ }
3478
+ await migrationPromise;
3479
+ };
3480
+ return {
3481
+ async migrate() {
3482
+ await ensureMigrated();
3483
+ },
3484
+ async append(entry) {
3485
+ await ensureMigrated();
3486
+ appendOne(entry);
3487
+ },
3488
+ async appendMany(entries) {
3489
+ await ensureMigrated();
3490
+ for (const entry of entries) {
3491
+ appendOne(entry);
3492
+ }
3493
+ },
3494
+ async list(options2 = {}) {
3495
+ await ensureMigrated();
3496
+ const { sql, params } = buildWhereClause2(options2);
3497
+ const limitSql = typeof options2.limit === "number" ? " LIMIT ?" : "";
3498
+ const query = `SELECT * FROM ${tableName} ${sql} ORDER BY timestamp DESC${limitSql}`;
3499
+ let rows;
3500
+ if (typeof options2.limit === "number") {
3501
+ rows = db.query(query).all(...params, options2.limit);
3502
+ } else {
3503
+ rows = db.query(query).all(...params);
3504
+ }
3505
+ return rows.map(mapRow);
3506
+ },
3507
+ async count(options2 = {}) {
3508
+ const { sql, params } = buildWhereClause2(options2);
3509
+ const query = `SELECT COUNT(*) as count FROM ${tableName} ${sql}`;
3510
+ const row = db.query(query).get(...params);
3511
+ return Number(row?.count ?? 0);
3512
+ },
3513
+ async deleteOlderThan(timestamp) {
3514
+ await ensureMigrated();
3515
+ const before = timestamp;
3516
+ const result = db.query(`DELETE FROM ${tableName} WHERE timestamp < ?`).run(before);
3517
+ return result.changes ?? 0;
3518
+ },
3519
+ async clear() {
3520
+ await ensureMigrated();
3521
+ db.query(`DELETE FROM ${tableName}`).run();
3522
+ }
3523
+ };
3524
+ };
3525
+
3526
+ // storage/usageTracking/memory.ts
3527
+ var normalizeBaseUrl4 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
3424
3528
  var matchesFilters2 = (entry, options = {}) => {
3425
3529
  if (typeof options.before === "number" && entry.timestamp >= options.before) {
3426
3530
  return false;
@@ -3431,7 +3535,7 @@ var matchesFilters2 = (entry, options = {}) => {
3431
3535
  if (options.modelId && entry.modelId !== options.modelId) {
3432
3536
  return false;
3433
3537
  }
3434
- if (options.baseUrl && normalizeBaseUrl3(entry.baseUrl) !== normalizeBaseUrl3(options.baseUrl)) {
3538
+ if (options.baseUrl && normalizeBaseUrl4(entry.baseUrl) !== normalizeBaseUrl4(options.baseUrl)) {
3435
3539
  return false;
3436
3540
  }
3437
3541
  if (options.sessionId && entry.sessionId !== options.sessionId) {
@@ -3445,18 +3549,18 @@ var matchesFilters2 = (entry, options = {}) => {
3445
3549
  var createMemoryUsageTrackingDriver = (seed = []) => {
3446
3550
  const store = /* @__PURE__ */ new Map();
3447
3551
  for (const entry of seed) {
3448
- store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl3(entry.baseUrl) });
3552
+ store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
3449
3553
  }
3450
3554
  return {
3451
3555
  async migrate() {
3452
3556
  return;
3453
3557
  },
3454
3558
  async append(entry) {
3455
- store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl3(entry.baseUrl) });
3559
+ store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
3456
3560
  },
3457
3561
  async appendMany(entries) {
3458
3562
  for (const entry of entries) {
3459
- store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl3(entry.baseUrl) });
3563
+ store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl4(entry.baseUrl) });
3460
3564
  }
3461
3565
  },
3462
3566
  async list(options = {}) {
@@ -3484,20 +3588,7 @@ var createMemoryUsageTrackingDriver = (seed = []) => {
3484
3588
  }
3485
3589
  };
3486
3590
  };
3487
- var normalizeBaseUrl4 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
3488
- var getCashuTokenBalance = (token) => {
3489
- try {
3490
- const decoded = getDecodedToken(token);
3491
- const unitDivisor = decoded.unit === "msat" ? 1e3 : 1;
3492
- let sum = 0;
3493
- for (const proof of decoded.proofs) {
3494
- sum += proof.amount / unitDivisor;
3495
- }
3496
- return sum;
3497
- } catch {
3498
- return 0;
3499
- }
3500
- };
3591
+ var normalizeBaseUrl5 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
3501
3592
  var createEmptyStore = (driver) => createStore((set, get) => ({
3502
3593
  modelsFromAllProviders: {},
3503
3594
  lastUsedModel: null,
@@ -3507,9 +3598,9 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
3507
3598
  mintsFromAllProviders: {},
3508
3599
  infoFromAllProviders: {},
3509
3600
  lastModelsUpdate: {},
3510
- cachedTokens: [],
3511
3601
  apiKeys: [],
3512
3602
  childKeys: [],
3603
+ xcashuTokens: {},
3513
3604
  routstr21Models: [],
3514
3605
  lastRoutstr21ModelsUpdate: null,
3515
3606
  cachedReceiveTokens: [],
@@ -3517,7 +3608,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
3517
3608
  setModelsFromAllProviders: (value) => {
3518
3609
  const normalized = {};
3519
3610
  for (const [baseUrl, models] of Object.entries(value)) {
3520
- normalized[normalizeBaseUrl4(baseUrl)] = models;
3611
+ normalized[normalizeBaseUrl5(baseUrl)] = models;
3521
3612
  }
3522
3613
  void driver.setItem(
3523
3614
  SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS,
@@ -3530,7 +3621,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
3530
3621
  set({ lastUsedModel: value });
3531
3622
  },
3532
3623
  setBaseUrlsList: (value) => {
3533
- const normalized = value.map((url) => normalizeBaseUrl4(url));
3624
+ const normalized = value.map((url) => normalizeBaseUrl5(url));
3534
3625
  void driver.setItem(SDK_STORAGE_KEYS.BASE_URLS_LIST, normalized);
3535
3626
  set({ baseUrlsList: normalized });
3536
3627
  },
@@ -3539,14 +3630,14 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
3539
3630
  set({ lastBaseUrlsUpdate: value });
3540
3631
  },
3541
3632
  setDisabledProviders: (value) => {
3542
- const normalized = value.map((url) => normalizeBaseUrl4(url));
3633
+ const normalized = value.map((url) => normalizeBaseUrl5(url));
3543
3634
  void driver.setItem(SDK_STORAGE_KEYS.DISABLED_PROVIDERS, normalized);
3544
3635
  set({ disabledProviders: normalized });
3545
3636
  },
3546
3637
  setMintsFromAllProviders: (value) => {
3547
3638
  const normalized = {};
3548
3639
  for (const [baseUrl, mints] of Object.entries(value)) {
3549
- normalized[normalizeBaseUrl4(baseUrl)] = mints.map(
3640
+ normalized[normalizeBaseUrl5(baseUrl)] = mints.map(
3550
3641
  (mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint
3551
3642
  );
3552
3643
  }
@@ -3559,7 +3650,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
3559
3650
  setInfoFromAllProviders: (value) => {
3560
3651
  const normalized = {};
3561
3652
  for (const [baseUrl, info] of Object.entries(value)) {
3562
- normalized[normalizeBaseUrl4(baseUrl)] = info;
3653
+ normalized[normalizeBaseUrl5(baseUrl)] = info;
3563
3654
  }
3564
3655
  void driver.setItem(SDK_STORAGE_KEYS.INFO_FROM_ALL_PROVIDERS, normalized);
3565
3656
  set({ infoFromAllProviders: normalized });
@@ -3567,30 +3658,17 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
3567
3658
  setLastModelsUpdate: (value) => {
3568
3659
  const normalized = {};
3569
3660
  for (const [baseUrl, timestamp] of Object.entries(value)) {
3570
- normalized[normalizeBaseUrl4(baseUrl)] = timestamp;
3661
+ normalized[normalizeBaseUrl5(baseUrl)] = timestamp;
3571
3662
  }
3572
3663
  void driver.setItem(SDK_STORAGE_KEYS.LAST_MODELS_UPDATE, normalized);
3573
3664
  set({ lastModelsUpdate: normalized });
3574
3665
  },
3575
- setCachedTokens: (value) => {
3576
- set((state) => {
3577
- const updates = typeof value === "function" ? value(state.cachedTokens) : value;
3578
- const normalized = updates.map((entry) => ({
3579
- ...entry,
3580
- baseUrl: normalizeBaseUrl4(entry.baseUrl),
3581
- balance: typeof entry.balance === "number" ? entry.balance : getCashuTokenBalance(entry.token),
3582
- lastUsed: entry.lastUsed ?? null
3583
- }));
3584
- void driver.setItem(SDK_STORAGE_KEYS.LOCAL_CASHU_TOKENS, normalized);
3585
- return { cachedTokens: normalized };
3586
- });
3587
- },
3588
3666
  setApiKeys: (value) => {
3589
3667
  set((state) => {
3590
3668
  const updates = typeof value === "function" ? value(state.apiKeys) : value;
3591
3669
  const normalized = updates.map((entry) => ({
3592
3670
  ...entry,
3593
- baseUrl: normalizeBaseUrl4(entry.baseUrl),
3671
+ baseUrl: normalizeBaseUrl5(entry.baseUrl),
3594
3672
  balance: entry.balance ?? 0,
3595
3673
  lastUsed: entry.lastUsed ?? null
3596
3674
  }));
@@ -3602,7 +3680,7 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
3602
3680
  set((state) => {
3603
3681
  const updates = typeof value === "function" ? value(state.childKeys) : value;
3604
3682
  const normalized = updates.map((entry) => ({
3605
- parentBaseUrl: normalizeBaseUrl4(entry.parentBaseUrl),
3683
+ parentBaseUrl: normalizeBaseUrl5(entry.parentBaseUrl),
3606
3684
  childKey: entry.childKey,
3607
3685
  balance: entry.balance ?? 0,
3608
3686
  balanceLimit: entry.balanceLimit,
@@ -3613,6 +3691,30 @@ var createEmptyStore = (driver) => createStore((set, get) => ({
3613
3691
  return { childKeys: normalized };
3614
3692
  });
3615
3693
  },
3694
+ setXcashuTokens: (value) => {
3695
+ const normalized = {};
3696
+ for (const [baseUrl, tokens] of Object.entries(value)) {
3697
+ normalized[normalizeBaseUrl5(baseUrl)] = tokens.map((entry) => ({
3698
+ ...entry,
3699
+ baseUrl: normalizeBaseUrl5(entry.baseUrl),
3700
+ createdAt: entry.createdAt ?? Date.now(),
3701
+ tryCount: entry.tryCount ?? 0
3702
+ }));
3703
+ }
3704
+ void driver.setItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, normalized);
3705
+ set({ xcashuTokens: normalized });
3706
+ },
3707
+ updateXcashuTokenTryCount: (token, tryCount) => {
3708
+ const currentTokens = get().xcashuTokens;
3709
+ const updatedTokens = {};
3710
+ for (const [baseUrl, tokens] of Object.entries(currentTokens)) {
3711
+ updatedTokens[baseUrl] = tokens.map(
3712
+ (entry) => entry.token === token ? { ...entry, tryCount } : entry
3713
+ );
3714
+ }
3715
+ void driver.setItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, updatedTokens);
3716
+ set({ xcashuTokens: updatedTokens });
3717
+ },
3616
3718
  setRoutstr21Models: (value) => {
3617
3719
  void driver.setItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, value);
3618
3720
  set({ routstr21Models: value });
@@ -3654,9 +3756,9 @@ var hydrateStoreFromDriver = async (store, driver) => {
3654
3756
  rawMints,
3655
3757
  rawInfo,
3656
3758
  rawLastModelsUpdate,
3657
- rawCachedTokens,
3658
3759
  rawApiKeys,
3659
3760
  rawChildKeys,
3761
+ rawXcashuTokens,
3660
3762
  rawRoutstr21Models,
3661
3763
  rawLastRoutstr21ModelsUpdate,
3662
3764
  rawCachedReceiveTokens,
@@ -3682,9 +3784,9 @@ var hydrateStoreFromDriver = async (store, driver) => {
3682
3784
  SDK_STORAGE_KEYS.LAST_MODELS_UPDATE,
3683
3785
  {}
3684
3786
  ),
3685
- driver.getItem(SDK_STORAGE_KEYS.LOCAL_CASHU_TOKENS, []),
3686
3787
  driver.getItem(SDK_STORAGE_KEYS.API_KEYS, []),
3687
3788
  driver.getItem(SDK_STORAGE_KEYS.CHILD_KEYS, []),
3789
+ driver.getItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, {}),
3688
3790
  driver.getItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, []),
3689
3791
  driver.getItem(
3690
3792
  SDK_STORAGE_KEYS.LAST_ROUTSTR21_MODELS_UPDATE,
@@ -3695,52 +3797,57 @@ var hydrateStoreFromDriver = async (store, driver) => {
3695
3797
  ]);
3696
3798
  const modelsFromAllProviders = Object.fromEntries(
3697
3799
  Object.entries(rawModels).map(([baseUrl, models]) => [
3698
- normalizeBaseUrl4(baseUrl),
3800
+ normalizeBaseUrl5(baseUrl),
3699
3801
  models
3700
3802
  ])
3701
3803
  );
3702
- const baseUrlsList = rawBaseUrls.map((url) => normalizeBaseUrl4(url));
3804
+ const baseUrlsList = rawBaseUrls.map((url) => normalizeBaseUrl5(url));
3703
3805
  const disabledProviders = rawDisabledProviders.map(
3704
- (url) => normalizeBaseUrl4(url)
3806
+ (url) => normalizeBaseUrl5(url)
3705
3807
  );
3706
3808
  const mintsFromAllProviders = Object.fromEntries(
3707
3809
  Object.entries(rawMints).map(([baseUrl, mints]) => [
3708
- normalizeBaseUrl4(baseUrl),
3810
+ normalizeBaseUrl5(baseUrl),
3709
3811
  mints.map((mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint)
3710
3812
  ])
3711
3813
  );
3712
3814
  const infoFromAllProviders = Object.fromEntries(
3713
3815
  Object.entries(rawInfo).map(([baseUrl, info]) => [
3714
- normalizeBaseUrl4(baseUrl),
3816
+ normalizeBaseUrl5(baseUrl),
3715
3817
  info
3716
3818
  ])
3717
3819
  );
3718
3820
  const lastModelsUpdate = Object.fromEntries(
3719
3821
  Object.entries(rawLastModelsUpdate).map(([baseUrl, timestamp]) => [
3720
- normalizeBaseUrl4(baseUrl),
3822
+ normalizeBaseUrl5(baseUrl),
3721
3823
  timestamp
3722
3824
  ])
3723
3825
  );
3724
- const cachedTokens = rawCachedTokens.map((entry) => ({
3725
- ...entry,
3726
- baseUrl: normalizeBaseUrl4(entry.baseUrl),
3727
- balance: typeof entry.balance === "number" ? entry.balance : getCashuTokenBalance(entry.token),
3728
- lastUsed: entry.lastUsed ?? null
3729
- }));
3730
3826
  const apiKeys = rawApiKeys.map((entry) => ({
3731
3827
  ...entry,
3732
- baseUrl: normalizeBaseUrl4(entry.baseUrl),
3828
+ baseUrl: normalizeBaseUrl5(entry.baseUrl),
3733
3829
  balance: entry.balance ?? 0,
3734
3830
  lastUsed: entry.lastUsed ?? null
3735
3831
  }));
3736
3832
  const childKeys = rawChildKeys.map((entry) => ({
3737
- parentBaseUrl: normalizeBaseUrl4(entry.parentBaseUrl),
3833
+ parentBaseUrl: normalizeBaseUrl5(entry.parentBaseUrl),
3738
3834
  childKey: entry.childKey,
3739
3835
  balance: entry.balance ?? 0,
3740
3836
  balanceLimit: entry.balanceLimit,
3741
3837
  validityDate: entry.validityDate,
3742
3838
  createdAt: entry.createdAt ?? Date.now()
3743
3839
  }));
3840
+ const xcashuTokens = Object.fromEntries(
3841
+ Object.entries(rawXcashuTokens).map(([baseUrl, tokens]) => [
3842
+ normalizeBaseUrl5(baseUrl),
3843
+ tokens.map((entry) => ({
3844
+ baseUrl: normalizeBaseUrl5(entry.baseUrl),
3845
+ token: entry.token,
3846
+ createdAt: entry.createdAt ?? Date.now(),
3847
+ tryCount: entry.tryCount ?? 0
3848
+ }))
3849
+ ])
3850
+ );
3744
3851
  const routstr21Models = rawRoutstr21Models;
3745
3852
  const lastRoutstr21ModelsUpdate = rawLastRoutstr21ModelsUpdate;
3746
3853
  const cachedReceiveTokens = rawCachedReceiveTokens?.map((entry) => ({
@@ -3763,9 +3870,9 @@ var hydrateStoreFromDriver = async (store, driver) => {
3763
3870
  mintsFromAllProviders,
3764
3871
  infoFromAllProviders,
3765
3872
  lastModelsUpdate,
3766
- cachedTokens,
3767
3873
  apiKeys,
3768
3874
  childKeys,
3875
+ xcashuTokens,
3769
3876
  routstr21Models,
3770
3877
  lastRoutstr21ModelsUpdate,
3771
3878
  cachedReceiveTokens,
@@ -3789,12 +3896,12 @@ var createDiscoveryAdapterFromStore = (store) => ({
3789
3896
  getCachedProviderInfo: () => store.getState().infoFromAllProviders,
3790
3897
  setCachedProviderInfo: (info) => store.getState().setInfoFromAllProviders(info),
3791
3898
  getProviderLastUpdate: (baseUrl) => {
3792
- const normalized = normalizeBaseUrl4(baseUrl);
3899
+ const normalized = normalizeBaseUrl5(baseUrl);
3793
3900
  const timestamps = store.getState().lastModelsUpdate;
3794
3901
  return timestamps[normalized] || null;
3795
3902
  },
3796
3903
  setProviderLastUpdate: (baseUrl, timestamp) => {
3797
- const normalized = normalizeBaseUrl4(baseUrl);
3904
+ const normalized = normalizeBaseUrl5(baseUrl);
3798
3905
  const timestamps = { ...store.getState().lastModelsUpdate };
3799
3906
  timestamps[normalized] = timestamp;
3800
3907
  store.getState().setLastModelsUpdate(timestamps);
@@ -3812,59 +3919,6 @@ var createDiscoveryAdapterFromStore = (store) => ({
3812
3919
  setRoutstr21ModelsLastUpdate: (timestamp) => store.getState().setRoutstr21ModelsLastUpdate(timestamp)
3813
3920
  });
3814
3921
  var createStorageAdapterFromStore = (store) => ({
3815
- getToken: (baseUrl) => {
3816
- const normalized = normalizeBaseUrl4(baseUrl);
3817
- const entry = store.getState().cachedTokens.find((token) => token.baseUrl === normalized);
3818
- if (!entry) return null;
3819
- const next = store.getState().cachedTokens.map(
3820
- (token) => token.baseUrl === normalized ? { ...token, lastUsed: Date.now() } : token
3821
- );
3822
- store.getState().setCachedTokens(next);
3823
- return entry.token;
3824
- },
3825
- setToken: (baseUrl, token) => {
3826
- const normalized = normalizeBaseUrl4(baseUrl);
3827
- const tokens = store.getState().cachedTokens;
3828
- const balance = getCashuTokenBalance(token);
3829
- const existingIndex = tokens.findIndex(
3830
- (entry) => entry.baseUrl === normalized
3831
- );
3832
- if (existingIndex !== -1) {
3833
- throw new Error(`Token already exists for baseUrl: ${normalized}`);
3834
- }
3835
- const next = [...tokens];
3836
- next.push({
3837
- baseUrl: normalized,
3838
- token,
3839
- balance,
3840
- lastUsed: Date.now()
3841
- });
3842
- store.getState().setCachedTokens(next);
3843
- },
3844
- removeToken: (baseUrl) => {
3845
- const normalized = normalizeBaseUrl4(baseUrl);
3846
- const next = store.getState().cachedTokens.filter((entry) => entry.baseUrl !== normalized);
3847
- store.getState().setCachedTokens(next);
3848
- },
3849
- updateTokenBalance: (baseUrl, balance) => {
3850
- const normalized = normalizeBaseUrl4(baseUrl);
3851
- const tokens = store.getState().cachedTokens;
3852
- const next = tokens.map(
3853
- (entry) => entry.baseUrl === normalized ? { ...entry, balance } : entry
3854
- );
3855
- store.getState().setCachedTokens(next);
3856
- },
3857
- getCachedTokenDistribution: () => {
3858
- const cachedTokens = store.getState().cachedTokens;
3859
- const distributionMap = {};
3860
- for (const entry of cachedTokens) {
3861
- const sum = entry.balance || 0;
3862
- if (sum > 0) {
3863
- distributionMap[entry.baseUrl] = (distributionMap[entry.baseUrl] || 0) + sum;
3864
- }
3865
- }
3866
- return Object.entries(distributionMap).map(([baseUrl, amt]) => ({ baseUrl, amount: amt })).sort((a, b) => b.amount - a.amount);
3867
- },
3868
3922
  getApiKeyDistribution: () => {
3869
3923
  const apiKeys = store.getState().apiKeys;
3870
3924
  const distributionMap = {};
@@ -3877,28 +3931,24 @@ var createStorageAdapterFromStore = (store) => ({
3877
3931
  return Object.entries(distributionMap).map(([baseUrl, amt]) => ({ baseUrl, amount: amt })).sort((a, b) => b.amount - a.amount);
3878
3932
  },
3879
3933
  saveProviderInfo: (baseUrl, info) => {
3880
- const normalized = normalizeBaseUrl4(baseUrl);
3934
+ const normalized = normalizeBaseUrl5(baseUrl);
3881
3935
  const next = { ...store.getState().infoFromAllProviders };
3882
3936
  next[normalized] = info;
3883
3937
  store.getState().setInfoFromAllProviders(next);
3884
3938
  },
3885
3939
  getProviderInfo: (baseUrl) => {
3886
- const normalized = normalizeBaseUrl4(baseUrl);
3940
+ const normalized = normalizeBaseUrl5(baseUrl);
3887
3941
  return store.getState().infoFromAllProviders[normalized] || null;
3888
3942
  },
3889
3943
  // ========== API Keys (for apikeys mode) ==========
3890
3944
  getApiKey: (baseUrl) => {
3891
- const normalized = normalizeBaseUrl4(baseUrl);
3945
+ const normalized = normalizeBaseUrl5(baseUrl);
3892
3946
  const entry = store.getState().apiKeys.find((key) => key.baseUrl === normalized);
3893
3947
  if (!entry) return null;
3894
- const next = store.getState().apiKeys.map(
3895
- (key) => key.baseUrl === normalized ? { ...key, lastUsed: Date.now() } : key
3896
- );
3897
- store.getState().setApiKeys(next);
3898
3948
  return entry;
3899
3949
  },
3900
3950
  setApiKey: (baseUrl, key) => {
3901
- const normalized = normalizeBaseUrl4(baseUrl);
3951
+ const normalized = normalizeBaseUrl5(baseUrl);
3902
3952
  const keys = store.getState().apiKeys;
3903
3953
  const existingIndex = keys.findIndex(
3904
3954
  (entry) => entry.baseUrl === normalized
@@ -3916,15 +3966,15 @@ var createStorageAdapterFromStore = (store) => ({
3916
3966
  store.getState().setApiKeys(next);
3917
3967
  },
3918
3968
  updateApiKeyBalance: (baseUrl, balance) => {
3919
- const normalized = normalizeBaseUrl4(baseUrl);
3969
+ const normalized = normalizeBaseUrl5(baseUrl);
3920
3970
  const keys = store.getState().apiKeys;
3921
3971
  const next = keys.map(
3922
- (entry) => entry.baseUrl === normalized ? { ...entry, balance } : entry
3972
+ (entry) => entry.baseUrl === normalized ? { ...entry, balance, lastUsed: Date.now() } : entry
3923
3973
  );
3924
3974
  store.getState().setApiKeys(next);
3925
3975
  },
3926
3976
  removeApiKey: (baseUrl) => {
3927
- const normalized = normalizeBaseUrl4(baseUrl);
3977
+ const normalized = normalizeBaseUrl5(baseUrl);
3928
3978
  const next = store.getState().apiKeys.filter((entry) => entry.baseUrl !== normalized);
3929
3979
  store.getState().setApiKeys(next);
3930
3980
  },
@@ -3938,7 +3988,7 @@ var createStorageAdapterFromStore = (store) => ({
3938
3988
  },
3939
3989
  // ========== Child Keys ==========
3940
3990
  getChildKey: (parentBaseUrl) => {
3941
- const normalized = normalizeBaseUrl4(parentBaseUrl);
3991
+ const normalized = normalizeBaseUrl5(parentBaseUrl);
3942
3992
  const entry = store.getState().childKeys.find((key) => key.parentBaseUrl === normalized);
3943
3993
  if (!entry) return null;
3944
3994
  return {
@@ -3951,7 +4001,7 @@ var createStorageAdapterFromStore = (store) => ({
3951
4001
  };
3952
4002
  },
3953
4003
  setChildKey: (parentBaseUrl, childKey, balance, validityDate, balanceLimit) => {
3954
- const normalized = normalizeBaseUrl4(parentBaseUrl);
4004
+ const normalized = normalizeBaseUrl5(parentBaseUrl);
3955
4005
  const keys = store.getState().childKeys;
3956
4006
  const existingIndex = keys.findIndex(
3957
4007
  (entry) => entry.parentBaseUrl === normalized
@@ -3982,7 +4032,7 @@ var createStorageAdapterFromStore = (store) => ({
3982
4032
  }
3983
4033
  },
3984
4034
  updateChildKeyBalance: (parentBaseUrl, balance) => {
3985
- const normalized = normalizeBaseUrl4(parentBaseUrl);
4035
+ const normalized = normalizeBaseUrl5(parentBaseUrl);
3986
4036
  const keys = store.getState().childKeys;
3987
4037
  const next = keys.map(
3988
4038
  (entry) => entry.parentBaseUrl === normalized ? { ...entry, balance } : entry
@@ -3990,7 +4040,7 @@ var createStorageAdapterFromStore = (store) => ({
3990
4040
  store.getState().setChildKeys(next);
3991
4041
  },
3992
4042
  removeChildKey: (parentBaseUrl) => {
3993
- const normalized = normalizeBaseUrl4(parentBaseUrl);
4043
+ const normalized = normalizeBaseUrl5(parentBaseUrl);
3994
4044
  const next = store.getState().childKeys.filter((entry) => entry.parentBaseUrl !== normalized);
3995
4045
  store.getState().setChildKeys(next);
3996
4046
  },
@@ -4009,20 +4059,60 @@ var createStorageAdapterFromStore = (store) => ({
4009
4059
  },
4010
4060
  setCachedReceiveTokens: (tokens) => {
4011
4061
  store.getState().setCachedReceiveTokens(tokens);
4062
+ },
4063
+ // ========== XCashu Tokens (multiple tokens per baseUrl) ==========
4064
+ getXcashuTokens: () => {
4065
+ return store.getState().xcashuTokens;
4066
+ },
4067
+ getXcashuTokensForBaseUrl: (baseUrl) => {
4068
+ const normalized = normalizeBaseUrl5(baseUrl);
4069
+ return store.getState().xcashuTokens[normalized] || [];
4070
+ },
4071
+ addXcashuToken: (baseUrl, token) => {
4072
+ const normalized = normalizeBaseUrl5(baseUrl);
4073
+ const tokens = store.getState().xcashuTokens;
4074
+ const existing = tokens[normalized] || [];
4075
+ const next = { ...tokens };
4076
+ next[normalized] = [
4077
+ ...existing,
4078
+ { baseUrl: normalized, token, createdAt: Date.now(), tryCount: 0 }
4079
+ ];
4080
+ store.getState().setXcashuTokens(next);
4081
+ },
4082
+ removeXcashuToken: (baseUrl, token) => {
4083
+ const normalized = normalizeBaseUrl5(baseUrl);
4084
+ const tokens = store.getState().xcashuTokens;
4085
+ const existing = tokens[normalized] || [];
4086
+ const next = { ...tokens };
4087
+ next[normalized] = existing.filter((entry) => entry.token !== token);
4088
+ if (next[normalized].length === 0) {
4089
+ delete next[normalized];
4090
+ }
4091
+ store.getState().setXcashuTokens(next);
4092
+ },
4093
+ clearXcashuTokensForBaseUrl: (baseUrl) => {
4094
+ const normalized = normalizeBaseUrl5(baseUrl);
4095
+ const tokens = store.getState().xcashuTokens;
4096
+ const next = { ...tokens };
4097
+ delete next[normalized];
4098
+ store.getState().setXcashuTokens(next);
4099
+ },
4100
+ updateXcashuTokenTryCount: (token, tryCount) => {
4101
+ store.getState().updateXcashuTokenTryCount(token, tryCount);
4012
4102
  }
4013
4103
  });
4014
4104
  var createProviderRegistryFromStore = (store) => ({
4015
4105
  getModelsForProvider: (baseUrl) => {
4016
- const normalized = normalizeBaseUrl4(baseUrl);
4106
+ const normalized = normalizeBaseUrl5(baseUrl);
4017
4107
  return store.getState().modelsFromAllProviders[normalized] || [];
4018
4108
  },
4019
4109
  getDisabledProviders: () => store.getState().disabledProviders,
4020
4110
  getProviderMints: (baseUrl) => {
4021
- const normalized = normalizeBaseUrl4(baseUrl);
4111
+ const normalized = normalizeBaseUrl5(baseUrl);
4022
4112
  return store.getState().mintsFromAllProviders[normalized] || [];
4023
4113
  },
4024
4114
  getProviderInfo: async (baseUrl) => {
4025
- const normalized = normalizeBaseUrl4(baseUrl);
4115
+ const normalized = normalizeBaseUrl5(baseUrl);
4026
4116
  const cached = store.getState().infoFromAllProviders[normalized];
4027
4117
  if (cached) return cached;
4028
4118
  try {
@@ -4097,7 +4187,7 @@ var getDefaultUsageTrackingDriver = () => {
4097
4187
  return defaultUsageTrackingDriver;
4098
4188
  }
4099
4189
  if (isBun3()) {
4100
- defaultUsageTrackingDriver = createMemoryUsageTrackingDriver();
4190
+ defaultUsageTrackingDriver = createBunSqliteUsageTrackingDriver();
4101
4191
  return defaultUsageTrackingDriver;
4102
4192
  }
4103
4193
  if (isNode()) {
@@ -4109,21 +4199,28 @@ var getDefaultUsageTrackingDriver = () => {
4109
4199
  defaultUsageTrackingDriver = createMemoryUsageTrackingDriver();
4110
4200
  return defaultUsageTrackingDriver;
4111
4201
  };
4202
+ var setDefaultUsageTrackingDriver = (driver) => {
4203
+ defaultUsageTrackingDriver = driver;
4204
+ };
4112
4205
  var getDefaultDiscoveryAdapter = async () => createDiscoveryAdapterFromStore(await getDefaultSdkStore());
4113
4206
  var getDefaultStorageAdapter = async () => createStorageAdapterFromStore(await getDefaultSdkStore());
4114
4207
  var getDefaultProviderRegistry = async () => createProviderRegistryFromStore(await getDefaultSdkStore());
4115
4208
  function createSSEParserTransform(onUsage, onResponseId) {
4116
4209
  let buffer = "";
4210
+ let usageCaptured = false;
4211
+ let responseIdCaptured = false;
4117
4212
  const maybeCaptureUsageFromJson = (jsonText) => {
4118
4213
  try {
4119
4214
  const data = JSON.parse(jsonText);
4120
4215
  const responseId = data.id;
4121
4216
  if (typeof responseId === "string" && responseId.trim().length > 0) {
4122
4217
  onResponseId?.(responseId.trim());
4218
+ responseIdCaptured = true;
4123
4219
  }
4124
4220
  const usage = extractUsageFromSSEJson(data);
4125
4221
  if (usage) {
4126
4222
  onUsage(usage);
4223
+ usageCaptured = true;
4127
4224
  }
4128
4225
  } catch {
4129
4226
  }
@@ -4179,7 +4276,7 @@ function createSSEParserTransform(onUsage, onResponseId) {
4179
4276
  }
4180
4277
  var TOPUP_MARGIN = 1.2;
4181
4278
  var RoutstrClient = class {
4182
- constructor(walletAdapter, storageAdapter, providerRegistry, alertLevel, mode = "xcashu") {
4279
+ constructor(walletAdapter, storageAdapter, providerRegistry, alertLevel, mode = "xcashu", options = {}) {
4183
4280
  this.walletAdapter = walletAdapter;
4184
4281
  this.storageAdapter = storageAdapter;
4185
4282
  this.providerRegistry = providerRegistry;
@@ -4197,13 +4294,9 @@ var RoutstrClient = class {
4197
4294
  this.streamProcessor = new StreamProcessor();
4198
4295
  this.providerManager = new ProviderManager(providerRegistry);
4199
4296
  this.alertLevel = alertLevel;
4200
- if (mode === "lazyrefund") {
4201
- this.mode = "apikeys";
4202
- } else if (mode === "apikeys") {
4203
- this.mode = "lazyrefund";
4204
- } else {
4205
- this.mode = mode;
4206
- }
4297
+ this.mode = mode;
4298
+ this.usageTrackingDriver = options.usageTrackingDriver;
4299
+ this.sdkStore = options.sdkStore;
4207
4300
  }
4208
4301
  cashuSpender;
4209
4302
  balanceManager;
@@ -4212,6 +4305,8 @@ var RoutstrClient = class {
4212
4305
  alertLevel;
4213
4306
  mode;
4214
4307
  debugLevel = "WARN";
4308
+ usageTrackingDriver;
4309
+ sdkStore;
4215
4310
  /**
4216
4311
  * Get the current client mode
4217
4312
  */
@@ -4281,11 +4376,13 @@ var RoutstrClient = class {
4281
4376
  const satsSpent = await this._handlePostResponseBalanceUpdate({
4282
4377
  token: prepared.tokenUsed,
4283
4378
  baseUrl: prepared.baseUrlUsed,
4379
+ mintUrl: params.mintUrl,
4284
4380
  initialTokenBalance: prepared.tokenBalanceInSats,
4285
4381
  response: prepared.response,
4286
4382
  modelId: prepared.modelId,
4287
4383
  usage: prepared.capturedUsage,
4288
- requestId: prepared.capturedResponseId
4384
+ requestId: prepared.capturedResponseId,
4385
+ clientApiKey: prepared.clientApiKey
4289
4386
  });
4290
4387
  prepared.response.satsSpent = satsSpent;
4291
4388
  prepared.response.usage = prepared.capturedUsage;
@@ -4304,11 +4401,13 @@ var RoutstrClient = class {
4304
4401
  const satsSpent = await this._handlePostResponseBalanceUpdate({
4305
4402
  token: prepared.tokenUsed,
4306
4403
  baseUrl: prepared.baseUrlUsed,
4404
+ mintUrl: params.mintUrl,
4307
4405
  initialTokenBalance: prepared.tokenBalanceInSats,
4308
4406
  response: prepared.response,
4309
4407
  modelId: prepared.modelId,
4310
4408
  usage: prepared.capturedUsage,
4311
- requestId: prepared.capturedResponseId
4409
+ requestId: prepared.capturedResponseId,
4410
+ clientApiKey: prepared.clientApiKey
4312
4411
  });
4313
4412
  prepared.response.satsSpent = satsSpent;
4314
4413
  res.end();
@@ -4324,11 +4423,13 @@ var RoutstrClient = class {
4324
4423
  const satsSpent = await this._handlePostResponseBalanceUpdate({
4325
4424
  token: prepared.tokenUsed,
4326
4425
  baseUrl: prepared.baseUrlUsed,
4426
+ mintUrl: params.mintUrl,
4327
4427
  initialTokenBalance: prepared.tokenBalanceInSats,
4328
4428
  response: prepared.response,
4329
4429
  modelId: prepared.modelId,
4330
4430
  usage: prepared.capturedUsage,
4331
- requestId: prepared.capturedResponseId
4431
+ requestId: prepared.capturedResponseId,
4432
+ clientApiKey: prepared.clientApiKey
4332
4433
  });
4333
4434
  prepared.response.satsSpent = satsSpent;
4334
4435
  prepared.response.usage = prepared.capturedUsage;
@@ -4358,8 +4459,10 @@ var RoutstrClient = class {
4358
4459
  headers = {},
4359
4460
  baseUrl,
4360
4461
  mintUrl,
4361
- modelId
4462
+ modelId,
4463
+ clientApiKey: providedClientApiKey
4362
4464
  } = params;
4465
+ const clientApiKey = providedClientApiKey ?? this._extractClientApiKey(headers);
4363
4466
  await this._checkBalance();
4364
4467
  let requiredSats = 1;
4365
4468
  let selectedModel;
@@ -4381,7 +4484,6 @@ var RoutstrClient = class {
4381
4484
  amount: requiredSats,
4382
4485
  baseUrl
4383
4486
  });
4384
- this._log("DEBUG", token, baseUrl);
4385
4487
  let requestBody = body;
4386
4488
  if (body && typeof body === "object") {
4387
4489
  const bodyObj = body;
@@ -4389,7 +4491,7 @@ var RoutstrClient = class {
4389
4491
  requestBody = { ...bodyObj, stream: false };
4390
4492
  }
4391
4493
  }
4392
- const baseHeaders = this._buildBaseHeaders(headers);
4494
+ const baseHeaders = this._buildBaseHeaders();
4393
4495
  const requestHeaders = this._withAuthHeader(baseHeaders, token);
4394
4496
  const response = await this._makeRequest({
4395
4497
  path,
@@ -4441,9 +4543,21 @@ var RoutstrClient = class {
4441
4543
  tokenBalanceInSats,
4442
4544
  modelId,
4443
4545
  capturedUsage,
4444
- capturedResponseId
4546
+ capturedResponseId,
4547
+ clientApiKey
4445
4548
  };
4446
4549
  }
4550
+ /**
4551
+ * Extract clientApiKey from Authorization Bearer token if present
4552
+ */
4553
+ _extractClientApiKey(headers) {
4554
+ const authHeader = headers["Authorization"] || headers["authorization"];
4555
+ if (authHeader?.startsWith("Bearer ")) {
4556
+ const extractedKey = authHeader.slice(7);
4557
+ return extractedKey;
4558
+ }
4559
+ return void 0;
4560
+ }
4447
4561
  /**
4448
4562
  * Fetch AI response with streaming
4449
4563
  */
@@ -4547,6 +4661,7 @@ var RoutstrClient = class {
4547
4661
  let satsSpent = await this._handlePostResponseBalanceUpdate({
4548
4662
  token,
4549
4663
  baseUrl: baseUrlUsed,
4664
+ mintUrl,
4550
4665
  initialTokenBalance: tokenBalanceInSats,
4551
4666
  fallbackSatsSpent: isApikeysEstimate ? this._getEstimatedCosts(selectedModel, streamingResult) : void 0,
4552
4667
  response,
@@ -4585,7 +4700,6 @@ var RoutstrClient = class {
4585
4700
  try {
4586
4701
  const url = `${baseUrl.replace(/\/$/, "")}${path}`;
4587
4702
  if (this.mode === "xcashu") this._log("DEBUG", "HEADERS,", headers);
4588
- this._log("DEBUG", "HEADERS,", headers);
4589
4703
  const response = await fetch(url, {
4590
4704
  method,
4591
4705
  headers,
@@ -4654,8 +4768,6 @@ var RoutstrClient = class {
4654
4768
  `[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${tryReceiveTokenResult.amount}`
4655
4769
  );
4656
4770
  tryNextProvider = true;
4657
- if (this.mode === "lazyrefund")
4658
- this.storageAdapter.removeToken(baseUrl);
4659
4771
  } else {
4660
4772
  this._log(
4661
4773
  "DEBUG",
@@ -4703,22 +4815,15 @@ var RoutstrClient = class {
4703
4815
  );
4704
4816
  }
4705
4817
  }
4706
- if (status === 402 && !tryNextProvider && (this.mode === "apikeys" || this.mode === "lazyrefund")) {
4818
+ if (status === 402 && !tryNextProvider && this.mode === "apikeys") {
4707
4819
  this.storageAdapter.getApiKey(baseUrl);
4708
4820
  let topupAmount = params.requiredSats;
4709
4821
  try {
4710
- let currentBalance = 0;
4711
- if (this.mode === "apikeys") {
4712
- const currentBalanceInfo = await this.balanceManager.getTokenBalance(
4713
- params.token,
4714
- baseUrl
4715
- );
4716
- currentBalance = currentBalanceInfo.unit === "msat" ? currentBalanceInfo.amount / 1e3 : currentBalanceInfo.amount;
4717
- } else if (this.mode === "lazyrefund") {
4718
- const distribution = this.storageAdapter.getCachedTokenDistribution();
4719
- const tokenEntry = distribution.find((t) => t.baseUrl === baseUrl);
4720
- currentBalance = tokenEntry?.amount ?? 0;
4721
- }
4822
+ const currentBalanceInfo = await this.balanceManager.getTokenBalance(
4823
+ params.token,
4824
+ baseUrl
4825
+ );
4826
+ const currentBalance = currentBalanceInfo.unit === "msat" ? currentBalanceInfo.amount / 1e3 : currentBalanceInfo.amount;
4722
4827
  const shortfall = Math.max(0, params.requiredSats - currentBalance);
4723
4828
  topupAmount = shortfall > 0 ? shortfall : params.requiredSats;
4724
4829
  } catch (e) {
@@ -4855,34 +4960,7 @@ var RoutstrClient = class {
4855
4960
  "DEBUG",
4856
4961
  `[RoutstrClient] _handleErrorResponse: Status ${status} (auth/server error), attempting refund for ${baseUrl}, mode=${this.mode}`
4857
4962
  );
4858
- if (this.mode === "lazyrefund") {
4859
- try {
4860
- const refundResult = await this.balanceManager.refund({
4861
- mintUrl,
4862
- baseUrl,
4863
- token: params.token
4864
- });
4865
- this._log(
4866
- "DEBUG",
4867
- `[RoutstrClient] _handleErrorResponse: Lazyrefund result: success=${refundResult.success}`
4868
- );
4869
- if (refundResult.success) this.storageAdapter.removeToken(baseUrl);
4870
- else
4871
- throw new ProviderError(
4872
- baseUrl,
4873
- status,
4874
- "refund failed",
4875
- requestId
4876
- );
4877
- } catch (error) {
4878
- throw new ProviderError(
4879
- baseUrl,
4880
- status,
4881
- "Failed to refund token",
4882
- requestId
4883
- );
4884
- }
4885
- } else if (this.mode === "apikeys") {
4963
+ if (this.mode === "apikeys") {
4886
4964
  this._log(
4887
4965
  "DEBUG",
4888
4966
  `[RoutstrClient] _handleErrorResponse: Attempting API key refund for ${baseUrl}, key preview=${token}`
@@ -4898,7 +4976,8 @@ var RoutstrClient = class {
4898
4976
  const refundResult = await this.balanceManager.refundApiKey({
4899
4977
  mintUrl,
4900
4978
  baseUrl,
4901
- apiKey: token
4979
+ apiKey: token,
4980
+ forceRefund: true
4902
4981
  });
4903
4982
  this._log(
4904
4983
  "DEBUG",
@@ -4980,12 +5059,14 @@ var RoutstrClient = class {
4980
5059
  const {
4981
5060
  token,
4982
5061
  baseUrl,
5062
+ mintUrl,
4983
5063
  initialTokenBalance,
4984
5064
  fallbackSatsSpent,
4985
5065
  response,
4986
5066
  modelId,
4987
5067
  usage,
4988
- requestId
5068
+ requestId,
5069
+ clientApiKey
4989
5070
  } = params;
4990
5071
  let satsSpent = initialTokenBalance;
4991
5072
  if (this.mode === "xcashu" && response) {
@@ -4993,19 +5074,14 @@ var RoutstrClient = class {
4993
5074
  if (refundToken) {
4994
5075
  try {
4995
5076
  const receiveResult = await this.cashuSpender.receiveToken(refundToken);
4996
- satsSpent = initialTokenBalance - receiveResult.amount * (receiveResult.unit == "sat" ? 1 : 1e3);
5077
+ if (receiveResult.success) {
5078
+ this.storageAdapter.removeXcashuToken(baseUrl, token);
5079
+ satsSpent = initialTokenBalance - receiveResult.amount * (receiveResult.unit == "sat" ? 1 : 1e3);
5080
+ }
4997
5081
  } catch (error) {
4998
5082
  this._log("ERROR", "[xcashu] Failed to receive refund token:", error);
4999
5083
  }
5000
5084
  }
5001
- } else if (this.mode === "lazyrefund") {
5002
- const latestBalanceInfo = await this.balanceManager.getTokenBalance(
5003
- token,
5004
- baseUrl
5005
- );
5006
- const latestTokenBalance = latestBalanceInfo.unit === "msat" ? latestBalanceInfo.amount / 1e3 : latestBalanceInfo.amount;
5007
- this.storageAdapter.updateTokenBalance(baseUrl, latestTokenBalance);
5008
- satsSpent = initialTokenBalance - latestTokenBalance;
5009
5085
  } else if (this.mode === "apikeys") {
5010
5086
  try {
5011
5087
  const latestBalanceInfo = await this.balanceManager.getTokenBalance(
@@ -5040,8 +5116,18 @@ var RoutstrClient = class {
5040
5116
  modelId,
5041
5117
  satsSpent,
5042
5118
  usage,
5043
- requestId
5119
+ requestId,
5120
+ clientApiKey
5044
5121
  });
5122
+ (async () => {
5123
+ try {
5124
+ const xcashuResults = await this.cashuSpender.refundXcashuTokens(mintUrl);
5125
+ this._log("DEBUG", "Refund xcashu tokens results:", xcashuResults);
5126
+ const results = await this.cashuSpender.refundProviders(mintUrl);
5127
+ } catch (error) {
5128
+ this._log("ERROR", "Failed to refund providers:", error);
5129
+ }
5130
+ })();
5045
5131
  return satsSpent;
5046
5132
  }
5047
5133
  async _trackResponseUsage(params) {
@@ -5052,7 +5138,8 @@ var RoutstrClient = class {
5052
5138
  modelId,
5053
5139
  satsSpent,
5054
5140
  usage: providedUsage,
5055
- requestId: providedRequestId
5141
+ requestId: providedRequestId,
5142
+ clientApiKey
5056
5143
  } = params;
5057
5144
  if (!response || !modelId) {
5058
5145
  return;
@@ -5079,13 +5166,14 @@ var RoutstrClient = class {
5079
5166
  return;
5080
5167
  }
5081
5168
  const finalRequestId = requestId || "unknown";
5082
- const store = await getDefaultSdkStore();
5169
+ const store = this.sdkStore ?? await getDefaultSdkStore();
5083
5170
  const state = store.getState();
5171
+ const matchKey = clientApiKey ?? token;
5084
5172
  const matchingClient = state.clientIds.find(
5085
- (client) => client.apiKey === token
5173
+ (client) => client.apiKey === matchKey
5086
5174
  );
5087
5175
  const entryId = finalRequestId === "unknown" ? `req-${Date.now()}-${modelId}` : finalRequestId;
5088
- const usageTracking = getDefaultUsageTrackingDriver();
5176
+ const usageTracking = this.usageTrackingDriver ?? getDefaultUsageTrackingDriver();
5089
5177
  const entry = {
5090
5178
  id: entryId,
5091
5179
  timestamp: Date.now(),
@@ -5160,11 +5248,11 @@ var RoutstrClient = class {
5160
5248
  return estimatedCosts;
5161
5249
  }
5162
5250
  /**
5163
- * Get pending cashu token amount
5251
+ * Get pending API key amount
5164
5252
  */
5165
5253
  _getPendingCashuTokenAmount() {
5166
- const distribution = this.storageAdapter.getCachedTokenDistribution();
5167
- return distribution.reduce((total, item) => total + item.amount, 0);
5254
+ const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
5255
+ return apiKeyDistribution.reduce((total, item) => total + item.amount, 0);
5168
5256
  }
5169
5257
  /**
5170
5258
  * Handle errors and notify callbacks
@@ -5311,8 +5399,8 @@ var RoutstrClient = class {
5311
5399
  const spendResult = await this.cashuSpender.spend({
5312
5400
  mintUrl,
5313
5401
  amount,
5314
- baseUrl: this.mode === "lazyrefund" ? baseUrl : "",
5315
- reuseToken: this.mode === "lazyrefund"
5402
+ baseUrl: "",
5403
+ reuseToken: false
5316
5404
  });
5317
5405
  if (!spendResult.token) {
5318
5406
  this._log(
@@ -5325,6 +5413,7 @@ var RoutstrClient = class {
5325
5413
  "DEBUG",
5326
5414
  `[RoutstrClient] _spendToken: Cashu token created, token preview: ${spendResult.token}, balance: ${spendResult.balance} ${spendResult.unit ?? "sat"}`
5327
5415
  );
5416
+ this.storageAdapter.addXcashuToken(baseUrl, spendResult.token);
5328
5417
  }
5329
5418
  return {
5330
5419
  token: spendResult.token,
@@ -5362,6 +5451,7 @@ async function resolveRouteRequestContext(options) {
5362
5451
  modelId,
5363
5452
  requestBody,
5364
5453
  path = "/v1/chat/completions",
5454
+ headers = {},
5365
5455
  forcedProvider,
5366
5456
  walletAdapter,
5367
5457
  storageAdapter,
@@ -5372,7 +5462,9 @@ async function resolveRouteRequestContext(options) {
5372
5462
  forceRefresh = false,
5373
5463
  modelManager: providedModelManager,
5374
5464
  debugLevel,
5375
- mode = "apikeys"
5465
+ mode = "apikeys",
5466
+ usageTrackingDriver,
5467
+ sdkStore
5376
5468
  } = options;
5377
5469
  let modelManager;
5378
5470
  let providers;
@@ -5436,7 +5528,8 @@ async function resolveRouteRequestContext(options) {
5436
5528
  storageAdapter,
5437
5529
  providerRegistry,
5438
5530
  "min",
5439
- mode
5531
+ mode,
5532
+ { usageTrackingDriver, sdkStore }
5440
5533
  );
5441
5534
  if (debugLevel) {
5442
5535
  client.setDebugLevel(debugLevel);
@@ -5456,17 +5549,19 @@ async function resolveRouteRequestContext(options) {
5456
5549
  baseUrl,
5457
5550
  mintUrl,
5458
5551
  path,
5552
+ headers,
5459
5553
  modelId,
5460
5554
  proxiedBody
5461
5555
  };
5462
5556
  }
5463
5557
  async function routeRequests(options) {
5464
- const { client, baseUrl, mintUrl, path, modelId, proxiedBody } = await resolveRouteRequestContext(options);
5558
+ const { client, baseUrl, mintUrl, path, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options);
5465
5559
  try {
5466
5560
  const response = await client.routeRequest({
5467
5561
  path,
5468
5562
  method: "POST",
5469
5563
  body: proxiedBody,
5564
+ headers,
5470
5565
  baseUrl,
5471
5566
  mintUrl,
5472
5567
  modelId
@@ -5484,12 +5579,13 @@ async function routeRequests(options) {
5484
5579
  }
5485
5580
  async function routeRequestsToNodeResponse(options) {
5486
5581
  const { res } = options;
5487
- const { client, baseUrl, mintUrl, path, modelId, proxiedBody } = await resolveRouteRequestContext(options);
5582
+ const { client, baseUrl, mintUrl, path, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options);
5488
5583
  try {
5489
5584
  await client.routeRequestToNodeResponse({
5490
5585
  path,
5491
5586
  method: "POST",
5492
5587
  body: proxiedBody,
5588
+ headers,
5493
5589
  baseUrl,
5494
5590
  mintUrl,
5495
5591
  modelId,
@@ -5519,6 +5615,6 @@ function extractStream(requestBody) {
5519
5615
  return typeof stream === "boolean" ? stream : void 0;
5520
5616
  }
5521
5617
 
5522
- export { BalanceManager, CashuSpender, FailoverError, InsufficientBalanceError, MintDiscovery, MintDiscoveryError, MintUnreachableError, ModelManager, ModelNotFoundError, NoProvidersAvailableError, ProviderBootstrapError, ProviderError, ProviderManager, RoutstrClient, SDK_STORAGE_KEYS, StreamProcessor, StreamingError, TokenOperationError, createDiscoveryAdapterFromStore, createIndexedDBDriver, createIndexedDBUsageTrackingDriver, createMemoryDriver, createMemoryUsageTrackingDriver, createProviderRegistryFromStore, createSSEParserTransform, createSdkStore, createSqliteDriver, createSqliteUsageTrackingDriver, createStorageAdapterFromStore, filterBaseUrlsForTor, getDefaultDiscoveryAdapter, getDefaultProviderRegistry, getDefaultSdkDriver, getDefaultSdkStore, getDefaultStorageAdapter, getDefaultUsageTrackingDriver, getProviderEndpoints, isOnionUrl, isTorContext, localStorageDriver, normalizeProviderUrl, routeRequests, routeRequestsToNodeResponse };
5618
+ export { BalanceManager, CashuSpender, FailoverError, InsufficientBalanceError, MintDiscovery, MintDiscoveryError, MintUnreachableError, ModelManager, ModelNotFoundError, NoProvidersAvailableError, ProviderBootstrapError, ProviderError, ProviderManager, RoutstrClient, SDK_STORAGE_KEYS, StreamProcessor, StreamingError, TokenOperationError, createBunSqliteDriver, createBunSqliteUsageTrackingDriver, createDiscoveryAdapterFromStore, createIndexedDBDriver, createIndexedDBUsageTrackingDriver, createMemoryDriver, createMemoryUsageTrackingDriver, createProviderRegistryFromStore, createSSEParserTransform, createSdkStore, createSqliteDriver, createSqliteUsageTrackingDriver, createStorageAdapterFromStore, filterBaseUrlsForTor, getDefaultDiscoveryAdapter, getDefaultProviderRegistry, getDefaultSdkDriver, getDefaultSdkStore, getDefaultStorageAdapter, getDefaultUsageTrackingDriver, getProviderEndpoints, isOnionUrl, isTorContext, localStorageDriver, normalizeProviderUrl, routeRequests, routeRequestsToNodeResponse, setDefaultUsageTrackingDriver };
5523
5619
  //# sourceMappingURL=index.mjs.map
5524
5620
  //# sourceMappingURL=index.mjs.map