ton-provider-system 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.cjs CHANGED
@@ -950,14 +950,23 @@ var HealthChecker = class {
950
950
  markDegraded(providerId, network, error) {
951
951
  const key = this.getResultKey(providerId, network);
952
952
  const existing = this.results.get(key);
953
- if (existing) {
954
- this.results.set(key, {
955
- ...existing,
956
- status: "degraded",
957
- error: error || "Marked as degraded",
958
- lastTested: /* @__PURE__ */ new Date()
959
- });
960
- }
953
+ const result = existing ? {
954
+ ...existing,
955
+ status: "degraded",
956
+ error: error || "Marked as degraded",
957
+ lastTested: /* @__PURE__ */ new Date()
958
+ } : {
959
+ id: providerId,
960
+ network,
961
+ success: false,
962
+ status: "degraded",
963
+ latencyMs: null,
964
+ seqno: null,
965
+ blocksBehind: 0,
966
+ lastTested: /* @__PURE__ */ new Date(),
967
+ error: error || "Marked as degraded"
968
+ };
969
+ this.results.set(key, result);
961
970
  }
962
971
  /**
963
972
  * Mark a provider as offline
@@ -965,14 +974,25 @@ var HealthChecker = class {
965
974
  markOffline(providerId, network, error) {
966
975
  const key = this.getResultKey(providerId, network);
967
976
  const existing = this.results.get(key);
968
- if (existing) {
969
- this.results.set(key, {
970
- ...existing,
971
- status: "offline",
972
- error: error || "Marked as offline",
973
- lastTested: /* @__PURE__ */ new Date()
974
- });
975
- }
977
+ const result = existing ? {
978
+ ...existing,
979
+ status: "offline",
980
+ success: false,
981
+ // Ensure success is false for offline providers
982
+ error: error || "Marked as offline",
983
+ lastTested: /* @__PURE__ */ new Date()
984
+ } : {
985
+ id: providerId,
986
+ network,
987
+ success: false,
988
+ status: "offline",
989
+ latencyMs: null,
990
+ seqno: null,
991
+ blocksBehind: 0,
992
+ lastTested: /* @__PURE__ */ new Date(),
993
+ error: error || "Marked as offline"
994
+ };
995
+ this.results.set(key, result);
976
996
  }
977
997
  // ========================================================================
978
998
  // Private Methods
@@ -2095,12 +2115,22 @@ var _ProviderManager = class _ProviderManager {
2095
2115
  if (!this.initialized || !this.network) return;
2096
2116
  const provider = this.selector.getBestProvider(this.network);
2097
2117
  if (!provider) return;
2098
- const errorMsg = error instanceof Error ? error.message : error;
2099
- if (isRateLimitError(error)) {
2118
+ const errorMsg = error instanceof Error ? error.message : String(error);
2119
+ const errorMsgLower = errorMsg.toLowerCase();
2120
+ const is429 = errorMsgLower.includes("429") || errorMsgLower.includes("rate limit");
2121
+ const is503 = errorMsgLower.includes("503") || errorMsgLower.includes("service unavailable");
2122
+ const is502 = errorMsgLower.includes("502") || errorMsgLower.includes("bad gateway");
2123
+ const is404 = errorMsgLower.includes("404") || errorMsgLower.includes("not found");
2124
+ const isTimeout = errorMsgLower.includes("timeout") || errorMsgLower.includes("abort");
2125
+ if (isRateLimitError(error) || is429) {
2100
2126
  this.rateLimiter.reportRateLimitError(provider.id);
2101
2127
  this.healthChecker.markDegraded(provider.id, this.network, errorMsg);
2128
+ } else if (is503 || is502 || is404 || isTimeout) {
2129
+ this.rateLimiter.reportError(provider.id);
2130
+ this.healthChecker.markOffline(provider.id, this.network, errorMsg);
2102
2131
  } else {
2103
2132
  this.rateLimiter.reportError(provider.id);
2133
+ this.healthChecker.markDegraded(provider.id, this.network, errorMsg);
2104
2134
  }
2105
2135
  this.selector.handleProviderFailure(provider.id, this.network);
2106
2136
  this.notifyListeners();
@@ -2559,16 +2589,42 @@ async function getTonClient(manager) {
2559
2589
  async function getTonClientWithRateLimit(manager) {
2560
2590
  const adapter = new NodeAdapter(manager);
2561
2591
  const client = await adapter.getClient();
2562
- const withRateLimit = async (fn) => {
2563
- await manager.getEndpointWithRateLimit();
2564
- try {
2565
- const result = await fn();
2566
- manager.reportSuccess();
2567
- return result;
2568
- } catch (error) {
2569
- manager.reportError(error);
2570
- throw error;
2592
+ const withRateLimit = async (fn, maxRetries = 3) => {
2593
+ let lastError;
2594
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
2595
+ try {
2596
+ await manager.getEndpointWithRateLimit(6e4);
2597
+ const result = await fn();
2598
+ manager.reportSuccess();
2599
+ return result;
2600
+ } catch (error) {
2601
+ lastError = error;
2602
+ const errorMsg = error?.message || String(error) || "";
2603
+ const is429 = errorMsg.includes("429") || errorMsg.includes("rate limit") || error?.status === 429 || error?.response?.status === 429;
2604
+ if (is429 && attempt < maxRetries) {
2605
+ manager.reportError(error);
2606
+ const managerState = manager.getState();
2607
+ const provider = manager.getActiveProvider();
2608
+ let backoff = 1e3;
2609
+ if (provider && managerState.providers) {
2610
+ const providerState = managerState.providers.get(provider.id);
2611
+ if (providerState?.rateLimit?.currentBackoff) {
2612
+ backoff = providerState.rateLimit.currentBackoff;
2613
+ }
2614
+ }
2615
+ const additionalDelay = Math.min(attempt * 500, 2e3);
2616
+ const waitTime = backoff + additionalDelay;
2617
+ console.warn(
2618
+ `[ProviderSystem] Rate limit error (429), retrying in ${waitTime}ms (attempt ${attempt + 1}/${maxRetries + 1})`
2619
+ );
2620
+ await sleep(waitTime);
2621
+ continue;
2622
+ }
2623
+ manager.reportError(error);
2624
+ throw error;
2625
+ }
2571
2626
  }
2627
+ throw lastError || new Error("Rate limit retries exhausted");
2572
2628
  };
2573
2629
  return { client, withRateLimit };
2574
2630
  }