@routstr/sdk 0.1.6 → 0.1.8

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
@@ -766,6 +766,9 @@ var CashuSpender = class {
766
766
  return result;
767
767
  }
768
768
  async _getBalanceState() {
769
+ if (this.balanceManager) {
770
+ return this.balanceManager.getBalanceState();
771
+ }
769
772
  const mintBalances = await this.walletAdapter.getBalances();
770
773
  const units = this.walletAdapter.getMintUnits();
771
774
  let totalMintBalance = 0;
@@ -781,15 +784,16 @@ var CashuSpender = class {
781
784
  const providerBalances = {};
782
785
  let totalProviderBalance = 0;
783
786
  for (const pending of pendingDistribution) {
784
- providerBalances[pending.baseUrl] = pending.amount;
787
+ providerBalances[pending.baseUrl] = (providerBalances[pending.baseUrl] || 0) + pending.amount;
785
788
  totalProviderBalance += pending.amount;
786
789
  }
787
790
  const apiKeys = this.storageAdapter.getAllApiKeys();
788
791
  for (const apiKey of apiKeys) {
789
792
  if (!providerBalances[apiKey.baseUrl]) {
790
- providerBalances[apiKey.baseUrl] = apiKey.balance;
791
- totalProviderBalance += apiKey.balance;
793
+ providerBalances[apiKey.baseUrl] = 0;
792
794
  }
795
+ providerBalances[apiKey.baseUrl] += apiKey.balance;
796
+ totalProviderBalance += apiKey.balance;
793
797
  }
794
798
  return {
795
799
  totalBalance: totalMintBalance + totalProviderBalance,
@@ -938,25 +942,12 @@ var CashuSpender = class {
938
942
  `[CashuSpender] _spendInternal: Could not reuse token, will create new token`
939
943
  );
940
944
  }
941
- const balances = await this.walletAdapter.getBalances();
942
- const units = this.walletAdapter.getMintUnits();
943
- let totalBalance = 0;
944
- for (const url in balances) {
945
- const balance = balances[url];
946
- const unit = units[url];
947
- const balanceInSats = getBalanceInSats(balance, unit);
948
- totalBalance += balanceInSats;
949
- }
950
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
951
- const totalPending = pendingDistribution.reduce(
952
- (sum, item) => sum + item.amount,
953
- 0
954
- );
945
+ const balanceState = await this._getBalanceState();
946
+ const totalAvailableBalance = balanceState.totalBalance;
955
947
  this._log(
956
948
  "DEBUG",
957
- `[CashuSpender] _spendInternal: totalBalance=${totalBalance}, totalPending=${totalPending}, adjustedAmount=${adjustedAmount}`
949
+ `[CashuSpender] _spendInternal: totalAvailableBalance=${totalAvailableBalance}, adjustedAmount=${adjustedAmount}`
958
950
  );
959
- const totalAvailableBalance = totalBalance + totalPending;
960
951
  if (totalAvailableBalance < adjustedAmount) {
961
952
  this._log(
962
953
  "ERROR",
@@ -964,8 +955,7 @@ var CashuSpender = class {
964
955
  );
965
956
  return this._createInsufficientBalanceError(
966
957
  adjustedAmount,
967
- balances,
968
- units,
958
+ balanceState.mintBalances,
969
959
  totalAvailableBalance
970
960
  );
971
961
  }
@@ -985,8 +975,7 @@ var CashuSpender = class {
985
975
  if ((tokenResult.error || "").includes("Insufficient balance")) {
986
976
  return this._createInsufficientBalanceError(
987
977
  adjustedAmount,
988
- balances,
989
- units,
978
+ balanceState.mintBalances,
990
979
  totalAvailableBalance
991
980
  );
992
981
  }
@@ -1031,6 +1020,7 @@ var CashuSpender = class {
1031
1020
  "DEBUG",
1032
1021
  `[CashuSpender] _spendInternal: Successfully spent ${spentAmount}, returning token with balance=${spentAmount}`
1033
1022
  );
1023
+ const units = this.walletAdapter.getMintUnits();
1034
1024
  return {
1035
1025
  token,
1036
1026
  status: "success",
@@ -1168,13 +1158,11 @@ var CashuSpender = class {
1168
1158
  /**
1169
1159
  * Create an insufficient balance error result
1170
1160
  */
1171
- _createInsufficientBalanceError(required, balances, units, availableBalance) {
1161
+ _createInsufficientBalanceError(required, normalizedBalances, availableBalance) {
1172
1162
  let maxBalance = 0;
1173
1163
  let maxMintUrl = "";
1174
- for (const mintUrl in balances) {
1175
- const balance = balances[mintUrl];
1176
- const unit = units[mintUrl];
1177
- const balanceInSats = getBalanceInSats(balance, unit);
1164
+ for (const mintUrl in normalizedBalances) {
1165
+ const balanceInSats = normalizedBalances[mintUrl];
1178
1166
  if (balanceInSats > maxBalance) {
1179
1167
  maxBalance = balanceInSats;
1180
1168
  maxMintUrl = mintUrl;
@@ -1235,6 +1223,39 @@ var BalanceManager = class {
1235
1223
  }
1236
1224
  }
1237
1225
  cashuSpender;
1226
+ async getBalanceState() {
1227
+ const mintBalances = await this.walletAdapter.getBalances();
1228
+ const units = this.walletAdapter.getMintUnits();
1229
+ let totalMintBalance = 0;
1230
+ const normalizedMintBalances = {};
1231
+ for (const url in mintBalances) {
1232
+ const balance = mintBalances[url];
1233
+ const unit = units[url];
1234
+ const balanceInSats = getBalanceInSats(balance, unit);
1235
+ normalizedMintBalances[url] = balanceInSats;
1236
+ totalMintBalance += balanceInSats;
1237
+ }
1238
+ const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
1239
+ const providerBalances = {};
1240
+ let totalProviderBalance = 0;
1241
+ for (const pending of pendingDistribution) {
1242
+ providerBalances[pending.baseUrl] = (providerBalances[pending.baseUrl] || 0) + pending.amount;
1243
+ totalProviderBalance += pending.amount;
1244
+ }
1245
+ const apiKeys = this.storageAdapter.getAllApiKeys();
1246
+ for (const apiKey of apiKeys) {
1247
+ if (!providerBalances[apiKey.baseUrl]) {
1248
+ providerBalances[apiKey.baseUrl] = 0;
1249
+ }
1250
+ providerBalances[apiKey.baseUrl] += apiKey.balance;
1251
+ totalProviderBalance += apiKey.balance;
1252
+ }
1253
+ return {
1254
+ totalBalance: totalMintBalance + totalProviderBalance,
1255
+ providerBalances,
1256
+ mintBalances: normalizedMintBalances
1257
+ };
1258
+ }
1238
1259
  /**
1239
1260
  * Unified refund - handles both NIP-60 and legacy wallet refunds
1240
1261
  */
@@ -1464,17 +1485,17 @@ var BalanceManager = class {
1464
1485
  if (!adjustedAmount || isNaN(adjustedAmount)) {
1465
1486
  return { success: false, error: "Invalid top up amount" };
1466
1487
  }
1488
+ const balanceState = await this.getBalanceState();
1467
1489
  const balances = await this.walletAdapter.getBalances();
1468
1490
  const units = this.walletAdapter.getMintUnits();
1469
- let totalMintBalance = 0;
1470
- for (const url in balances) {
1471
- const unit = units[url];
1472
- const balanceInSats = getBalanceInSats(balances[url], unit);
1473
- totalMintBalance += balanceInSats;
1474
- }
1475
- const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
1476
- const refundablePending = pendingDistribution.filter((entry) => entry.baseUrl !== baseUrl).reduce((sum, entry) => sum + entry.amount, 0);
1477
- if (totalMintBalance < adjustedAmount && totalMintBalance + refundablePending >= adjustedAmount && retryCount < 1) {
1491
+ const totalMintBalance = Object.values(balanceState.mintBalances).reduce(
1492
+ (sum, value) => sum + value,
1493
+ 0
1494
+ );
1495
+ const refundableProviderBalance = Object.entries(
1496
+ balanceState.providerBalances
1497
+ ).filter(([providerBaseUrl]) => providerBaseUrl !== baseUrl).reduce((sum, [, value]) => sum + value, 0);
1498
+ if (totalMintBalance < adjustedAmount && totalMintBalance + refundableProviderBalance >= adjustedAmount && retryCount < 1) {
1478
1499
  await this._refundOtherProvidersForTopUp(baseUrl, mintUrl);
1479
1500
  return this.createProviderToken({
1480
1501
  ...options,
@@ -1596,10 +1617,14 @@ var BalanceManager = class {
1596
1617
  }
1597
1618
  async _refundOtherProvidersForTopUp(baseUrl, mintUrl) {
1598
1619
  const pendingDistribution = this.storageAdapter.getCachedTokenDistribution();
1620
+ const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
1599
1621
  const toRefund = pendingDistribution.filter(
1600
1622
  (pending) => pending.baseUrl !== baseUrl
1601
1623
  );
1602
- const refundResults = await Promise.allSettled(
1624
+ const apiKeysToRefund = apiKeyDistribution.filter(
1625
+ (apiKey) => apiKey.baseUrl !== baseUrl && apiKey.amount > 0
1626
+ );
1627
+ const tokenRefundResults = await Promise.allSettled(
1603
1628
  toRefund.map(async (pending) => {
1604
1629
  const token = this.storageAdapter.getToken(pending.baseUrl);
1605
1630
  if (!token) {
@@ -1617,11 +1642,32 @@ var BalanceManager = class {
1617
1642
  return { baseUrl: pending.baseUrl, success: result.success };
1618
1643
  })
1619
1644
  );
1620
- for (const result of refundResults) {
1645
+ for (const result of tokenRefundResults) {
1621
1646
  if (result.status === "fulfilled" && result.value.success) {
1622
1647
  this.storageAdapter.removeToken(result.value.baseUrl);
1623
1648
  }
1624
1649
  }
1650
+ const apiKeyRefundResults = await Promise.allSettled(
1651
+ apiKeysToRefund.map(async (apiKeyEntry) => {
1652
+ const fullApiKeyEntry = this.storageAdapter.getApiKey(
1653
+ apiKeyEntry.baseUrl
1654
+ );
1655
+ if (!fullApiKeyEntry) {
1656
+ return { baseUrl: apiKeyEntry.baseUrl, success: false };
1657
+ }
1658
+ const result = await this.refundApiKey({
1659
+ mintUrl,
1660
+ baseUrl: apiKeyEntry.baseUrl,
1661
+ apiKey: fullApiKeyEntry.key
1662
+ });
1663
+ return { baseUrl: apiKeyEntry.baseUrl, success: result.success };
1664
+ })
1665
+ );
1666
+ for (const result of apiKeyRefundResults) {
1667
+ if (result.status === "fulfilled" && result.value.success) {
1668
+ this.storageAdapter.updateApiKeyBalance(result.value.baseUrl, 0);
1669
+ }
1670
+ }
1625
1671
  }
1626
1672
  /**
1627
1673
  * Fetch refund token from provider API
@@ -1820,6 +1866,14 @@ var BalanceManager = class {
1820
1866
  console.log(response.status);
1821
1867
  const data = await response.json();
1822
1868
  console.log("FAILED ", data);
1869
+ const isInvalidApiKey = response.status === 401 && data?.code === "invalid_api_key" && data?.message?.includes("proofs already spent");
1870
+ return {
1871
+ amount: -1,
1872
+ reserved: data.reserved ?? 0,
1873
+ unit: "msat",
1874
+ apiKey: data.api_key,
1875
+ isInvalidApiKey
1876
+ };
1823
1877
  }
1824
1878
  } catch (error) {
1825
1879
  console.error("ERRORR IN RESTPONSE", error);
@@ -2768,7 +2822,8 @@ var RoutstrClient = class {
2768
2822
  response.status,
2769
2823
  requestId,
2770
2824
  this.mode === "xcashu" ? response.headers.get("x-cashu") ?? void 0 : void 0,
2771
- bodyText
2825
+ bodyText,
2826
+ params.retryCount ?? 0
2772
2827
  );
2773
2828
  }
2774
2829
  return response;
@@ -2777,8 +2832,12 @@ var RoutstrClient = class {
2777
2832
  return await this._handleErrorResponse(
2778
2833
  params,
2779
2834
  token,
2780
- -1
2835
+ -1,
2781
2836
  // just for Network Error to skip all statuses
2837
+ void 0,
2838
+ void 0,
2839
+ void 0,
2840
+ params.retryCount ?? 0
2782
2841
  );
2783
2842
  }
2784
2843
  throw error;
@@ -2787,7 +2846,8 @@ var RoutstrClient = class {
2787
2846
  /**
2788
2847
  * Handle error responses with failover
2789
2848
  */
2790
- async _handleErrorResponse(params, token, status, requestId, xCashuRefundToken, responseBody) {
2849
+ async _handleErrorResponse(params, token, status, requestId, xCashuRefundToken, responseBody, retryCount = 0) {
2850
+ const MAX_RETRIES_PER_PROVIDER = 2;
2791
2851
  const { path, method, body, selectedModel, baseUrl, mintUrl } = params;
2792
2852
  let tryNextProvider = false;
2793
2853
  this._log(
@@ -2858,10 +2918,34 @@ var RoutstrClient = class {
2858
2918
  }
2859
2919
  }
2860
2920
  if (status === 402 && !tryNextProvider && (this.mode === "apikeys" || this.mode === "lazyrefund")) {
2921
+ this.storageAdapter.getApiKey(baseUrl);
2922
+ let topupAmount = params.requiredSats;
2923
+ try {
2924
+ let currentBalance = 0;
2925
+ if (this.mode === "apikeys") {
2926
+ const currentBalanceInfo = await this.balanceManager.getTokenBalance(
2927
+ params.token,
2928
+ baseUrl
2929
+ );
2930
+ currentBalance = currentBalanceInfo.unit === "msat" ? currentBalanceInfo.amount / 1e3 : currentBalanceInfo.amount;
2931
+ } else if (this.mode === "lazyrefund") {
2932
+ const distribution = this.storageAdapter.getCachedTokenDistribution();
2933
+ const tokenEntry = distribution.find((t) => t.baseUrl === baseUrl);
2934
+ currentBalance = tokenEntry?.amount ?? 0;
2935
+ }
2936
+ const shortfall = Math.max(0, params.requiredSats - currentBalance);
2937
+ topupAmount = shortfall > 0 ? shortfall : params.requiredSats;
2938
+ } catch (e) {
2939
+ this._log(
2940
+ "WARN",
2941
+ "Could not get current token balance for topup calculation:",
2942
+ e
2943
+ );
2944
+ }
2861
2945
  const topupResult = await this.balanceManager.topUp({
2862
2946
  mintUrl,
2863
2947
  baseUrl,
2864
- amount: params.requiredSats * TOPUP_MARGIN,
2948
+ amount: topupAmount * TOPUP_MARGIN,
2865
2949
  token: params.token
2866
2950
  });
2867
2951
  this._log(
@@ -2893,12 +2977,26 @@ var RoutstrClient = class {
2893
2977
  `[RoutstrClient] _handleErrorResponse: Topup successful, will retry with new token`
2894
2978
  );
2895
2979
  }
2896
- if (!tryNextProvider)
2897
- return this._makeRequest({
2898
- ...params,
2899
- token: params.token,
2900
- headers: this._withAuthHeader(params.baseHeaders, params.token)
2901
- });
2980
+ if (!tryNextProvider) {
2981
+ if (retryCount < MAX_RETRIES_PER_PROVIDER) {
2982
+ this._log(
2983
+ "DEBUG",
2984
+ `[RoutstrClient] _handleErrorResponse: Retrying 402 (attempt ${retryCount + 1}/${MAX_RETRIES_PER_PROVIDER})`
2985
+ );
2986
+ return this._makeRequest({
2987
+ ...params,
2988
+ token: params.token,
2989
+ headers: this._withAuthHeader(params.baseHeaders, params.token),
2990
+ retryCount: retryCount + 1
2991
+ });
2992
+ } else {
2993
+ this._log(
2994
+ "DEBUG",
2995
+ `[RoutstrClient] _handleErrorResponse: 402 retry limit reached (${retryCount}/${MAX_RETRIES_PER_PROVIDER}), failing over to next provider`
2996
+ );
2997
+ tryNextProvider = true;
2998
+ }
2999
+ }
2902
3000
  }
2903
3001
  const isInsufficientBalance413 = status === 413 && responseBody?.includes("Insufficient balance");
2904
3002
  if (isInsufficientBalance413 && !tryNextProvider && this.mode === "apikeys") {
@@ -2908,19 +3006,31 @@ var RoutstrClient = class {
2908
3006
  params.token,
2909
3007
  baseUrl
2910
3008
  );
2911
- const latestTokenBalance = latestBalanceInfo.unit === "msat" ? latestBalanceInfo.amount / 1e3 : latestBalanceInfo.amount;
2912
- if (latestBalanceInfo.apiKey) {
2913
- const storedApiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
2914
- if (storedApiKeyEntry?.key !== latestBalanceInfo.apiKey) {
2915
- if (storedApiKeyEntry) {
2916
- this.storageAdapter.removeApiKey(baseUrl);
3009
+ if (latestBalanceInfo.isInvalidApiKey) {
3010
+ this._log(
3011
+ "DEBUG",
3012
+ `[RoutstrClient] _handleErrorResponse: Invalid API key (proofs already spent), removing for ${baseUrl}`
3013
+ );
3014
+ this.storageAdapter.removeApiKey(baseUrl);
3015
+ tryNextProvider = true;
3016
+ } else {
3017
+ const latestTokenBalance = latestBalanceInfo.unit === "msat" ? latestBalanceInfo.amount / 1e3 : latestBalanceInfo.amount;
3018
+ if (latestBalanceInfo.apiKey) {
3019
+ const storedApiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
3020
+ if (storedApiKeyEntry?.key !== latestBalanceInfo.apiKey) {
3021
+ if (storedApiKeyEntry) {
3022
+ this.storageAdapter.removeApiKey(baseUrl);
3023
+ }
3024
+ this.storageAdapter.setApiKey(baseUrl, latestBalanceInfo.apiKey);
2917
3025
  }
2918
- this.storageAdapter.setApiKey(baseUrl, latestBalanceInfo.apiKey);
3026
+ retryToken = latestBalanceInfo.apiKey;
3027
+ }
3028
+ if (latestTokenBalance >= 0) {
3029
+ this.storageAdapter.updateApiKeyBalance(
3030
+ baseUrl,
3031
+ latestTokenBalance
3032
+ );
2919
3033
  }
2920
- retryToken = latestBalanceInfo.apiKey;
2921
- }
2922
- if (latestTokenBalance >= 0) {
2923
- this.storageAdapter.updateApiKeyBalance(baseUrl, latestTokenBalance);
2924
3034
  }
2925
3035
  } catch (error) {
2926
3036
  this._log(
@@ -2929,11 +3039,24 @@ var RoutstrClient = class {
2929
3039
  error
2930
3040
  );
2931
3041
  }
2932
- return this._makeRequest({
2933
- ...params,
2934
- token: retryToken,
2935
- headers: this._withAuthHeader(params.baseHeaders, retryToken)
2936
- });
3042
+ if (retryCount < MAX_RETRIES_PER_PROVIDER) {
3043
+ this._log(
3044
+ "DEBUG",
3045
+ `[RoutstrClient] _handleErrorResponse: Retrying 413 (attempt ${retryCount + 1}/${MAX_RETRIES_PER_PROVIDER})`
3046
+ );
3047
+ return this._makeRequest({
3048
+ ...params,
3049
+ token: retryToken,
3050
+ headers: this._withAuthHeader(params.baseHeaders, retryToken),
3051
+ retryCount: retryCount + 1
3052
+ });
3053
+ } else {
3054
+ this._log(
3055
+ "DEBUG",
3056
+ `[RoutstrClient] _handleErrorResponse: 413 retry limit reached (${retryCount}/${MAX_RETRIES_PER_PROVIDER}), failing over to next provider`
3057
+ );
3058
+ tryNextProvider = true;
3059
+ }
2937
3060
  }
2938
3061
  if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
2939
3062
  this._log(
@@ -3049,7 +3172,8 @@ var RoutstrClient = class {
3049
3172
  selectedModel: newModel,
3050
3173
  token: spendResult.token,
3051
3174
  requiredSats: newRequiredSats,
3052
- headers: this._withAuthHeader(params.baseHeaders, spendResult.token)
3175
+ headers: this._withAuthHeader(params.baseHeaders, spendResult.token),
3176
+ retryCount: 0
3053
3177
  });
3054
3178
  }
3055
3179
  throw new FailoverError(baseUrl, Array.from(this.providerManager));
@@ -3679,12 +3803,13 @@ var SDK_STORAGE_KEYS = {
3679
3803
  CHILD_KEYS: "child_keys",
3680
3804
  ROUTSTR21_MODELS: "routstr21Models",
3681
3805
  LAST_ROUTSTR21_MODELS_UPDATE: "lastRoutstr21ModelsUpdate",
3682
- CACHED_RECEIVE_TOKENS: "cached_receive_tokens"
3806
+ CACHED_RECEIVE_TOKENS: "cached_receive_tokens",
3807
+ USAGE_TRACKING: "usage_tracking"
3683
3808
  };
3684
3809
 
3685
3810
  // storage/store.ts
3686
3811
  var normalizeBaseUrl = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
3687
- var getTokenBalance = (token) => {
3812
+ var getCashuTokenBalance = (token) => {
3688
3813
  try {
3689
3814
  const decoded = getDecodedToken(token);
3690
3815
  const unitDivisor = decoded.unit === "msat" ? 1e3 : 1;
@@ -3714,7 +3839,8 @@ var createSdkStore = async ({
3714
3839
  rawChildKeys,
3715
3840
  rawRoutstr21Models,
3716
3841
  rawLastRoutstr21ModelsUpdate,
3717
- rawCachedReceiveTokens
3842
+ rawCachedReceiveTokens,
3843
+ rawUsageTracking
3718
3844
  ] = await Promise.all([
3719
3845
  driver.getItem(
3720
3846
  SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS,
@@ -3744,7 +3870,8 @@ var createSdkStore = async ({
3744
3870
  SDK_STORAGE_KEYS.LAST_ROUTSTR21_MODELS_UPDATE,
3745
3871
  null
3746
3872
  ),
3747
- driver.getItem(SDK_STORAGE_KEYS.CACHED_RECEIVE_TOKENS, [])
3873
+ driver.getItem(SDK_STORAGE_KEYS.CACHED_RECEIVE_TOKENS, []),
3874
+ driver.getItem(SDK_STORAGE_KEYS.USAGE_TRACKING, [])
3748
3875
  ]);
3749
3876
  const modelsFromAllProviders = Object.fromEntries(
3750
3877
  Object.entries(rawModels).map(([baseUrl, models]) => [
@@ -3777,7 +3904,7 @@ var createSdkStore = async ({
3777
3904
  const cachedTokens = rawCachedTokens.map((entry) => ({
3778
3905
  ...entry,
3779
3906
  baseUrl: normalizeBaseUrl(entry.baseUrl),
3780
- balance: typeof entry.balance === "number" ? entry.balance : getTokenBalance(entry.token),
3907
+ balance: typeof entry.balance === "number" ? entry.balance : getCashuTokenBalance(entry.token),
3781
3908
  lastUsed: entry.lastUsed ?? null
3782
3909
  }));
3783
3910
  const apiKeys = rawApiKeys.map((entry) => ({
@@ -3802,6 +3929,7 @@ var createSdkStore = async ({
3802
3929
  unit: entry.unit || "sat",
3803
3930
  createdAt: entry.createdAt ?? Date.now()
3804
3931
  }));
3932
+ const usageTracking = rawUsageTracking;
3805
3933
  return createStore((set, get) => ({
3806
3934
  modelsFromAllProviders,
3807
3935
  lastUsedModel,
@@ -3817,6 +3945,7 @@ var createSdkStore = async ({
3817
3945
  routstr21Models,
3818
3946
  lastRoutstr21ModelsUpdate,
3819
3947
  cachedReceiveTokens,
3948
+ usageTracking,
3820
3949
  setModelsFromAllProviders: (value) => {
3821
3950
  const normalized = {};
3822
3951
  for (const [baseUrl, models] of Object.entries(value)) {
@@ -3881,7 +4010,7 @@ var createSdkStore = async ({
3881
4010
  const normalized = updates.map((entry) => ({
3882
4011
  ...entry,
3883
4012
  baseUrl: normalizeBaseUrl(entry.baseUrl),
3884
- balance: typeof entry.balance === "number" ? entry.balance : getTokenBalance(entry.token),
4013
+ balance: typeof entry.balance === "number" ? entry.balance : getCashuTokenBalance(entry.token),
3885
4014
  lastUsed: entry.lastUsed ?? null
3886
4015
  }));
3887
4016
  void driver.setItem(SDK_STORAGE_KEYS.LOCAL_CASHU_TOKENS, normalized);
@@ -3933,6 +4062,10 @@ var createSdkStore = async ({
3933
4062
  }));
3934
4063
  void driver.setItem(SDK_STORAGE_KEYS.CACHED_RECEIVE_TOKENS, normalized);
3935
4064
  set({ cachedReceiveTokens: normalized });
4065
+ },
4066
+ setUsageTracking: (value) => {
4067
+ void driver.setItem(SDK_STORAGE_KEYS.USAGE_TRACKING, value);
4068
+ set({ usageTracking: value });
3936
4069
  }
3937
4070
  }));
3938
4071
  };
@@ -3980,7 +4113,7 @@ var createStorageAdapterFromStore = (store) => ({
3980
4113
  setToken: (baseUrl, token) => {
3981
4114
  const normalized = normalizeBaseUrl(baseUrl);
3982
4115
  const tokens = store.getState().cachedTokens;
3983
- const balance = getTokenBalance(token);
4116
+ const balance = getCashuTokenBalance(token);
3984
4117
  const existingIndex = tokens.findIndex(
3985
4118
  (entry) => entry.baseUrl === normalized
3986
4119
  );