@routstr/sdk 0.1.6 → 0.1.7

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.js CHANGED
@@ -1822,6 +1822,14 @@ var BalanceManager = class {
1822
1822
  console.log(response.status);
1823
1823
  const data = await response.json();
1824
1824
  console.log("FAILED ", data);
1825
+ const isInvalidApiKey = response.status === 401 && data?.code === "invalid_api_key" && data?.message?.includes("proofs already spent");
1826
+ return {
1827
+ amount: -1,
1828
+ reserved: data.reserved ?? 0,
1829
+ unit: "msat",
1830
+ apiKey: data.api_key,
1831
+ isInvalidApiKey
1832
+ };
1825
1833
  }
1826
1834
  } catch (error) {
1827
1835
  console.error("ERRORR IN RESTPONSE", error);
@@ -2770,7 +2778,8 @@ var RoutstrClient = class {
2770
2778
  response.status,
2771
2779
  requestId,
2772
2780
  this.mode === "xcashu" ? response.headers.get("x-cashu") ?? void 0 : void 0,
2773
- bodyText
2781
+ bodyText,
2782
+ params.retryCount ?? 0
2774
2783
  );
2775
2784
  }
2776
2785
  return response;
@@ -2779,8 +2788,12 @@ var RoutstrClient = class {
2779
2788
  return await this._handleErrorResponse(
2780
2789
  params,
2781
2790
  token,
2782
- -1
2791
+ -1,
2783
2792
  // just for Network Error to skip all statuses
2793
+ void 0,
2794
+ void 0,
2795
+ void 0,
2796
+ params.retryCount ?? 0
2784
2797
  );
2785
2798
  }
2786
2799
  throw error;
@@ -2789,7 +2802,8 @@ var RoutstrClient = class {
2789
2802
  /**
2790
2803
  * Handle error responses with failover
2791
2804
  */
2792
- async _handleErrorResponse(params, token, status, requestId, xCashuRefundToken, responseBody) {
2805
+ async _handleErrorResponse(params, token, status, requestId, xCashuRefundToken, responseBody, retryCount = 0) {
2806
+ const MAX_RETRIES_PER_PROVIDER = 2;
2793
2807
  const { path, method, body, selectedModel, baseUrl, mintUrl } = params;
2794
2808
  let tryNextProvider = false;
2795
2809
  this._log(
@@ -2895,12 +2909,26 @@ var RoutstrClient = class {
2895
2909
  `[RoutstrClient] _handleErrorResponse: Topup successful, will retry with new token`
2896
2910
  );
2897
2911
  }
2898
- if (!tryNextProvider)
2899
- return this._makeRequest({
2900
- ...params,
2901
- token: params.token,
2902
- headers: this._withAuthHeader(params.baseHeaders, params.token)
2903
- });
2912
+ if (!tryNextProvider) {
2913
+ if (retryCount < MAX_RETRIES_PER_PROVIDER) {
2914
+ this._log(
2915
+ "DEBUG",
2916
+ `[RoutstrClient] _handleErrorResponse: Retrying 402 (attempt ${retryCount + 1}/${MAX_RETRIES_PER_PROVIDER})`
2917
+ );
2918
+ return this._makeRequest({
2919
+ ...params,
2920
+ token: params.token,
2921
+ headers: this._withAuthHeader(params.baseHeaders, params.token),
2922
+ retryCount: retryCount + 1
2923
+ });
2924
+ } else {
2925
+ this._log(
2926
+ "DEBUG",
2927
+ `[RoutstrClient] _handleErrorResponse: 402 retry limit reached (${retryCount}/${MAX_RETRIES_PER_PROVIDER}), failing over to next provider`
2928
+ );
2929
+ tryNextProvider = true;
2930
+ }
2931
+ }
2904
2932
  }
2905
2933
  const isInsufficientBalance413 = status === 413 && responseBody?.includes("Insufficient balance");
2906
2934
  if (isInsufficientBalance413 && !tryNextProvider && this.mode === "apikeys") {
@@ -2910,19 +2938,28 @@ var RoutstrClient = class {
2910
2938
  params.token,
2911
2939
  baseUrl
2912
2940
  );
2913
- const latestTokenBalance = latestBalanceInfo.unit === "msat" ? latestBalanceInfo.amount / 1e3 : latestBalanceInfo.amount;
2914
- if (latestBalanceInfo.apiKey) {
2915
- const storedApiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
2916
- if (storedApiKeyEntry?.key !== latestBalanceInfo.apiKey) {
2917
- if (storedApiKeyEntry) {
2918
- this.storageAdapter.removeApiKey(baseUrl);
2941
+ if (latestBalanceInfo.isInvalidApiKey) {
2942
+ this._log(
2943
+ "DEBUG",
2944
+ `[RoutstrClient] _handleErrorResponse: Invalid API key (proofs already spent), removing for ${baseUrl}`
2945
+ );
2946
+ this.storageAdapter.removeApiKey(baseUrl);
2947
+ tryNextProvider = true;
2948
+ } else {
2949
+ const latestTokenBalance = latestBalanceInfo.unit === "msat" ? latestBalanceInfo.amount / 1e3 : latestBalanceInfo.amount;
2950
+ if (latestBalanceInfo.apiKey) {
2951
+ const storedApiKeyEntry = this.storageAdapter.getApiKey(baseUrl);
2952
+ if (storedApiKeyEntry?.key !== latestBalanceInfo.apiKey) {
2953
+ if (storedApiKeyEntry) {
2954
+ this.storageAdapter.removeApiKey(baseUrl);
2955
+ }
2956
+ this.storageAdapter.setApiKey(baseUrl, latestBalanceInfo.apiKey);
2919
2957
  }
2920
- this.storageAdapter.setApiKey(baseUrl, latestBalanceInfo.apiKey);
2958
+ retryToken = latestBalanceInfo.apiKey;
2959
+ }
2960
+ if (latestTokenBalance >= 0) {
2961
+ this.storageAdapter.updateApiKeyBalance(baseUrl, latestTokenBalance);
2921
2962
  }
2922
- retryToken = latestBalanceInfo.apiKey;
2923
- }
2924
- if (latestTokenBalance >= 0) {
2925
- this.storageAdapter.updateApiKeyBalance(baseUrl, latestTokenBalance);
2926
2963
  }
2927
2964
  } catch (error) {
2928
2965
  this._log(
@@ -2931,11 +2968,24 @@ var RoutstrClient = class {
2931
2968
  error
2932
2969
  );
2933
2970
  }
2934
- return this._makeRequest({
2935
- ...params,
2936
- token: retryToken,
2937
- headers: this._withAuthHeader(params.baseHeaders, retryToken)
2938
- });
2971
+ if (retryCount < MAX_RETRIES_PER_PROVIDER) {
2972
+ this._log(
2973
+ "DEBUG",
2974
+ `[RoutstrClient] _handleErrorResponse: Retrying 413 (attempt ${retryCount + 1}/${MAX_RETRIES_PER_PROVIDER})`
2975
+ );
2976
+ return this._makeRequest({
2977
+ ...params,
2978
+ token: retryToken,
2979
+ headers: this._withAuthHeader(params.baseHeaders, retryToken),
2980
+ retryCount: retryCount + 1
2981
+ });
2982
+ } else {
2983
+ this._log(
2984
+ "DEBUG",
2985
+ `[RoutstrClient] _handleErrorResponse: 413 retry limit reached (${retryCount}/${MAX_RETRIES_PER_PROVIDER}), failing over to next provider`
2986
+ );
2987
+ tryNextProvider = true;
2988
+ }
2939
2989
  }
2940
2990
  if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
2941
2991
  this._log(
@@ -3051,7 +3101,8 @@ var RoutstrClient = class {
3051
3101
  selectedModel: newModel,
3052
3102
  token: spendResult.token,
3053
3103
  requiredSats: newRequiredSats,
3054
- headers: this._withAuthHeader(params.baseHeaders, spendResult.token)
3104
+ headers: this._withAuthHeader(params.baseHeaders, spendResult.token),
3105
+ retryCount: 0
3055
3106
  });
3056
3107
  }
3057
3108
  throw new FailoverError(baseUrl, Array.from(this.providerManager));
@@ -3686,7 +3737,7 @@ var SDK_STORAGE_KEYS = {
3686
3737
 
3687
3738
  // storage/store.ts
3688
3739
  var normalizeBaseUrl = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
3689
- var getTokenBalance = (token) => {
3740
+ var getCashuTokenBalance = (token) => {
3690
3741
  try {
3691
3742
  const decoded = cashuTs.getDecodedToken(token);
3692
3743
  const unitDivisor = decoded.unit === "msat" ? 1e3 : 1;
@@ -3779,7 +3830,7 @@ var createSdkStore = async ({
3779
3830
  const cachedTokens = rawCachedTokens.map((entry) => ({
3780
3831
  ...entry,
3781
3832
  baseUrl: normalizeBaseUrl(entry.baseUrl),
3782
- balance: typeof entry.balance === "number" ? entry.balance : getTokenBalance(entry.token),
3833
+ balance: typeof entry.balance === "number" ? entry.balance : getCashuTokenBalance(entry.token),
3783
3834
  lastUsed: entry.lastUsed ?? null
3784
3835
  }));
3785
3836
  const apiKeys = rawApiKeys.map((entry) => ({
@@ -3883,7 +3934,7 @@ var createSdkStore = async ({
3883
3934
  const normalized = updates.map((entry) => ({
3884
3935
  ...entry,
3885
3936
  baseUrl: normalizeBaseUrl(entry.baseUrl),
3886
- balance: typeof entry.balance === "number" ? entry.balance : getTokenBalance(entry.token),
3937
+ balance: typeof entry.balance === "number" ? entry.balance : getCashuTokenBalance(entry.token),
3887
3938
  lastUsed: entry.lastUsed ?? null
3888
3939
  }));
3889
3940
  void driver.setItem(SDK_STORAGE_KEYS.LOCAL_CASHU_TOKENS, normalized);
@@ -3982,7 +4033,7 @@ var createStorageAdapterFromStore = (store) => ({
3982
4033
  setToken: (baseUrl, token) => {
3983
4034
  const normalized = normalizeBaseUrl(baseUrl);
3984
4035
  const tokens = store.getState().cachedTokens;
3985
- const balance = getTokenBalance(token);
4036
+ const balance = getCashuTokenBalance(token);
3986
4037
  const existingIndex = tokens.findIndex(
3987
4038
  (entry) => entry.baseUrl === normalized
3988
4039
  );