ton-provider-system 0.1.9 → 0.1.11
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 +144 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/index.js +144 -24
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/rpc.json +4 -2
package/dist/index.d.cts
CHANGED
|
@@ -59,6 +59,8 @@ interface ProviderConfig {
|
|
|
59
59
|
enabled: boolean;
|
|
60
60
|
/** Whether this provider requires dynamic endpoint discovery (e.g., Orbs) */
|
|
61
61
|
isDynamic?: boolean;
|
|
62
|
+
/** Whether this provider is compatible with browser environments (default: true) */
|
|
63
|
+
browserCompatible?: boolean;
|
|
62
64
|
/** Optional description or notes */
|
|
63
65
|
description?: string;
|
|
64
66
|
}
|
|
@@ -114,6 +116,8 @@ interface ResolvedProvider {
|
|
|
114
116
|
priority: number;
|
|
115
117
|
/** Whether dynamic discovery is needed */
|
|
116
118
|
isDynamic: boolean;
|
|
119
|
+
/** Whether this provider is compatible with browser environments */
|
|
120
|
+
browserCompatible: boolean;
|
|
117
121
|
}
|
|
118
122
|
/**
|
|
119
123
|
* Provider health check result
|
|
@@ -139,6 +143,8 @@ interface ProviderHealthResult {
|
|
|
139
143
|
cachedEndpoint?: string;
|
|
140
144
|
/** Error message if failed */
|
|
141
145
|
error?: string;
|
|
146
|
+
/** Whether this provider is compatible with browser environments */
|
|
147
|
+
browserCompatible: boolean;
|
|
142
148
|
}
|
|
143
149
|
/**
|
|
144
150
|
* Provider state for runtime tracking
|
|
@@ -1039,6 +1045,15 @@ declare class HealthChecker {
|
|
|
1039
1045
|
*/
|
|
1040
1046
|
private callGetMasterchainInfo;
|
|
1041
1047
|
private sleep;
|
|
1048
|
+
/**
|
|
1049
|
+
* Detect CORS errors (browser compatibility issues)
|
|
1050
|
+
*
|
|
1051
|
+
* CORS errors occur when:
|
|
1052
|
+
* - Request header field is not allowed by Access-Control-Allow-Headers
|
|
1053
|
+
* - Specifically, x-ton-client-version header is blocked by some providers
|
|
1054
|
+
* - Error message contains "CORS", "Access-Control", or "x-ton-client-version"
|
|
1055
|
+
*/
|
|
1056
|
+
private isCorsError;
|
|
1042
1057
|
}
|
|
1043
1058
|
/**
|
|
1044
1059
|
* Create a health checker with default configuration
|
|
@@ -1078,12 +1093,13 @@ declare class ProviderSelector {
|
|
|
1078
1093
|
private healthChecker;
|
|
1079
1094
|
private config;
|
|
1080
1095
|
private logger;
|
|
1096
|
+
private adapter;
|
|
1081
1097
|
private selectedProviderId;
|
|
1082
1098
|
private autoSelect;
|
|
1083
1099
|
private customEndpoint;
|
|
1084
1100
|
private bestProviderByNetwork;
|
|
1085
1101
|
private activeProviderByNetwork;
|
|
1086
|
-
constructor(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger);
|
|
1102
|
+
constructor(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger, adapter?: 'node' | 'browser');
|
|
1087
1103
|
/**
|
|
1088
1104
|
* Get the best provider for a network
|
|
1089
1105
|
*/
|
|
@@ -1166,11 +1182,19 @@ declare class ProviderSelector {
|
|
|
1166
1182
|
* Create a pseudo-provider for custom endpoint
|
|
1167
1183
|
*/
|
|
1168
1184
|
private createCustomProvider;
|
|
1185
|
+
/**
|
|
1186
|
+
* Filter providers to only include browser-compatible ones
|
|
1187
|
+
*
|
|
1188
|
+
* Checks both:
|
|
1189
|
+
* 1. Provider config browserCompatible flag
|
|
1190
|
+
* 2. Health check result browserCompatible flag (if health check was performed)
|
|
1191
|
+
*/
|
|
1192
|
+
private filterBrowserCompatible;
|
|
1169
1193
|
}
|
|
1170
1194
|
/**
|
|
1171
1195
|
* Create a provider selector
|
|
1172
1196
|
*/
|
|
1173
|
-
declare function createSelector(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger): ProviderSelector;
|
|
1197
|
+
declare function createSelector(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger, adapter?: 'node' | 'browser'): ProviderSelector;
|
|
1174
1198
|
|
|
1175
1199
|
/**
|
|
1176
1200
|
* Unified Provider System - Provider Manager
|
package/dist/index.d.ts
CHANGED
|
@@ -59,6 +59,8 @@ interface ProviderConfig {
|
|
|
59
59
|
enabled: boolean;
|
|
60
60
|
/** Whether this provider requires dynamic endpoint discovery (e.g., Orbs) */
|
|
61
61
|
isDynamic?: boolean;
|
|
62
|
+
/** Whether this provider is compatible with browser environments (default: true) */
|
|
63
|
+
browserCompatible?: boolean;
|
|
62
64
|
/** Optional description or notes */
|
|
63
65
|
description?: string;
|
|
64
66
|
}
|
|
@@ -114,6 +116,8 @@ interface ResolvedProvider {
|
|
|
114
116
|
priority: number;
|
|
115
117
|
/** Whether dynamic discovery is needed */
|
|
116
118
|
isDynamic: boolean;
|
|
119
|
+
/** Whether this provider is compatible with browser environments */
|
|
120
|
+
browserCompatible: boolean;
|
|
117
121
|
}
|
|
118
122
|
/**
|
|
119
123
|
* Provider health check result
|
|
@@ -139,6 +143,8 @@ interface ProviderHealthResult {
|
|
|
139
143
|
cachedEndpoint?: string;
|
|
140
144
|
/** Error message if failed */
|
|
141
145
|
error?: string;
|
|
146
|
+
/** Whether this provider is compatible with browser environments */
|
|
147
|
+
browserCompatible: boolean;
|
|
142
148
|
}
|
|
143
149
|
/**
|
|
144
150
|
* Provider state for runtime tracking
|
|
@@ -1039,6 +1045,15 @@ declare class HealthChecker {
|
|
|
1039
1045
|
*/
|
|
1040
1046
|
private callGetMasterchainInfo;
|
|
1041
1047
|
private sleep;
|
|
1048
|
+
/**
|
|
1049
|
+
* Detect CORS errors (browser compatibility issues)
|
|
1050
|
+
*
|
|
1051
|
+
* CORS errors occur when:
|
|
1052
|
+
* - Request header field is not allowed by Access-Control-Allow-Headers
|
|
1053
|
+
* - Specifically, x-ton-client-version header is blocked by some providers
|
|
1054
|
+
* - Error message contains "CORS", "Access-Control", or "x-ton-client-version"
|
|
1055
|
+
*/
|
|
1056
|
+
private isCorsError;
|
|
1042
1057
|
}
|
|
1043
1058
|
/**
|
|
1044
1059
|
* Create a health checker with default configuration
|
|
@@ -1078,12 +1093,13 @@ declare class ProviderSelector {
|
|
|
1078
1093
|
private healthChecker;
|
|
1079
1094
|
private config;
|
|
1080
1095
|
private logger;
|
|
1096
|
+
private adapter;
|
|
1081
1097
|
private selectedProviderId;
|
|
1082
1098
|
private autoSelect;
|
|
1083
1099
|
private customEndpoint;
|
|
1084
1100
|
private bestProviderByNetwork;
|
|
1085
1101
|
private activeProviderByNetwork;
|
|
1086
|
-
constructor(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger);
|
|
1102
|
+
constructor(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger, adapter?: 'node' | 'browser');
|
|
1087
1103
|
/**
|
|
1088
1104
|
* Get the best provider for a network
|
|
1089
1105
|
*/
|
|
@@ -1166,11 +1182,19 @@ declare class ProviderSelector {
|
|
|
1166
1182
|
* Create a pseudo-provider for custom endpoint
|
|
1167
1183
|
*/
|
|
1168
1184
|
private createCustomProvider;
|
|
1185
|
+
/**
|
|
1186
|
+
* Filter providers to only include browser-compatible ones
|
|
1187
|
+
*
|
|
1188
|
+
* Checks both:
|
|
1189
|
+
* 1. Provider config browserCompatible flag
|
|
1190
|
+
* 2. Health check result browserCompatible flag (if health check was performed)
|
|
1191
|
+
*/
|
|
1192
|
+
private filterBrowserCompatible;
|
|
1169
1193
|
}
|
|
1170
1194
|
/**
|
|
1171
1195
|
* Create a provider selector
|
|
1172
1196
|
*/
|
|
1173
|
-
declare function createSelector(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger): ProviderSelector;
|
|
1197
|
+
declare function createSelector(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger, adapter?: 'node' | 'browser'): ProviderSelector;
|
|
1174
1198
|
|
|
1175
1199
|
/**
|
|
1176
1200
|
* Unified Provider System - Provider Manager
|
package/dist/index.js
CHANGED
|
@@ -214,7 +214,8 @@ function resolveProvider(id, config) {
|
|
|
214
214
|
apiKey,
|
|
215
215
|
rps: config.rps,
|
|
216
216
|
priority: config.priority,
|
|
217
|
-
isDynamic: config.isDynamic || false
|
|
217
|
+
isDynamic: config.isDynamic || false,
|
|
218
|
+
browserCompatible: config.browserCompatible !== void 0 ? config.browserCompatible : true
|
|
218
219
|
};
|
|
219
220
|
}
|
|
220
221
|
function resolveAllProviders(config) {
|
|
@@ -773,7 +774,8 @@ var HealthChecker = class {
|
|
|
773
774
|
latencyMs: null,
|
|
774
775
|
seqno: null,
|
|
775
776
|
blocksBehind: 0,
|
|
776
|
-
lastTested: null
|
|
777
|
+
lastTested: null,
|
|
778
|
+
browserCompatible: provider.browserCompatible
|
|
777
779
|
};
|
|
778
780
|
this.results.set(key, testingResult);
|
|
779
781
|
try {
|
|
@@ -833,7 +835,8 @@ var HealthChecker = class {
|
|
|
833
835
|
seqno,
|
|
834
836
|
blocksBehind,
|
|
835
837
|
lastTested: /* @__PURE__ */ new Date(),
|
|
836
|
-
cachedEndpoint: normalizedEndpoint
|
|
838
|
+
cachedEndpoint: normalizedEndpoint,
|
|
839
|
+
browserCompatible: provider.browserCompatible
|
|
837
840
|
};
|
|
838
841
|
this.results.set(key, result);
|
|
839
842
|
this.logger.debug(
|
|
@@ -844,6 +847,7 @@ var HealthChecker = class {
|
|
|
844
847
|
const endTime = performance.now();
|
|
845
848
|
const latencyMs = Math.round(endTime - startTime);
|
|
846
849
|
const errorMsg = error.message || String(error) || "Unknown error";
|
|
850
|
+
const isCorsError = this.isCorsError(error, errorMsg);
|
|
847
851
|
const is429 = errorMsg.includes("429") || errorMsg.toLowerCase().includes("rate limit");
|
|
848
852
|
const is404 = errorMsg.includes("404") || errorMsg.toLowerCase().includes("not found");
|
|
849
853
|
const is503 = errorMsg.includes("503") || errorMsg.toLowerCase().includes("service unavailable");
|
|
@@ -858,6 +862,7 @@ var HealthChecker = class {
|
|
|
858
862
|
} else if (isTimeout) {
|
|
859
863
|
status = "offline";
|
|
860
864
|
}
|
|
865
|
+
const browserCompatible = isCorsError ? false : provider.browserCompatible;
|
|
861
866
|
const result = {
|
|
862
867
|
id: provider.id,
|
|
863
868
|
network: provider.network,
|
|
@@ -867,7 +872,8 @@ var HealthChecker = class {
|
|
|
867
872
|
seqno: null,
|
|
868
873
|
blocksBehind: 0,
|
|
869
874
|
lastTested: /* @__PURE__ */ new Date(),
|
|
870
|
-
error: errorMsg
|
|
875
|
+
error: errorMsg,
|
|
876
|
+
browserCompatible
|
|
871
877
|
};
|
|
872
878
|
this.results.set(key, result);
|
|
873
879
|
this.logger.warn(`Provider ${provider.id} health check failed: ${result.error}`);
|
|
@@ -949,21 +955,25 @@ var HealthChecker = class {
|
|
|
949
955
|
const existing = this.results.get(key);
|
|
950
956
|
const result = existing ? {
|
|
951
957
|
...existing,
|
|
952
|
-
success:
|
|
953
|
-
//
|
|
958
|
+
success: true,
|
|
959
|
+
// Degraded providers are still usable, just slower/rate-limited
|
|
954
960
|
status: "degraded",
|
|
955
961
|
error: error || "Marked as degraded",
|
|
956
|
-
lastTested: /* @__PURE__ */ new Date()
|
|
962
|
+
lastTested: /* @__PURE__ */ new Date(),
|
|
963
|
+
browserCompatible: existing.browserCompatible ?? true
|
|
957
964
|
} : {
|
|
958
965
|
id: providerId,
|
|
959
966
|
network,
|
|
960
|
-
success:
|
|
967
|
+
success: true,
|
|
968
|
+
// Degraded providers are still usable
|
|
961
969
|
status: "degraded",
|
|
962
970
|
latencyMs: null,
|
|
963
971
|
seqno: null,
|
|
964
972
|
blocksBehind: 0,
|
|
965
973
|
lastTested: /* @__PURE__ */ new Date(),
|
|
966
|
-
error: error || "Marked as degraded"
|
|
974
|
+
error: error || "Marked as degraded",
|
|
975
|
+
browserCompatible: true
|
|
976
|
+
// Default to compatible if unknown
|
|
967
977
|
};
|
|
968
978
|
this.results.set(key, result);
|
|
969
979
|
}
|
|
@@ -979,7 +989,8 @@ var HealthChecker = class {
|
|
|
979
989
|
success: false,
|
|
980
990
|
// Ensure success is false for offline providers
|
|
981
991
|
error: error || "Marked as offline",
|
|
982
|
-
lastTested: /* @__PURE__ */ new Date()
|
|
992
|
+
lastTested: /* @__PURE__ */ new Date(),
|
|
993
|
+
browserCompatible: existing.browserCompatible ?? true
|
|
983
994
|
} : {
|
|
984
995
|
id: providerId,
|
|
985
996
|
network,
|
|
@@ -989,7 +1000,9 @@ var HealthChecker = class {
|
|
|
989
1000
|
seqno: null,
|
|
990
1001
|
blocksBehind: 0,
|
|
991
1002
|
lastTested: /* @__PURE__ */ new Date(),
|
|
992
|
-
error: error || "Marked as offline"
|
|
1003
|
+
error: error || "Marked as offline",
|
|
1004
|
+
browserCompatible: true
|
|
1005
|
+
// Default to compatible if unknown
|
|
993
1006
|
};
|
|
994
1007
|
this.results.set(key, result);
|
|
995
1008
|
}
|
|
@@ -1121,6 +1134,24 @@ var HealthChecker = class {
|
|
|
1121
1134
|
sleep(ms) {
|
|
1122
1135
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1123
1136
|
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Detect CORS errors (browser compatibility issues)
|
|
1139
|
+
*
|
|
1140
|
+
* CORS errors occur when:
|
|
1141
|
+
* - Request header field is not allowed by Access-Control-Allow-Headers
|
|
1142
|
+
* - Specifically, x-ton-client-version header is blocked by some providers
|
|
1143
|
+
* - Error message contains "CORS", "Access-Control", or "x-ton-client-version"
|
|
1144
|
+
*/
|
|
1145
|
+
isCorsError(error, errorMsg) {
|
|
1146
|
+
const msg = errorMsg.toLowerCase();
|
|
1147
|
+
if (msg.includes("cors") || msg.includes("access-control") || msg.includes("x-ton-client-version") || msg.includes("not allowed by access-control-allow-headers") || msg.includes("blocked by cors policy")) {
|
|
1148
|
+
return true;
|
|
1149
|
+
}
|
|
1150
|
+
if (error.name === "TypeError" && (msg.includes("failed to fetch") || msg.includes("network error"))) {
|
|
1151
|
+
return false;
|
|
1152
|
+
}
|
|
1153
|
+
return false;
|
|
1154
|
+
}
|
|
1124
1155
|
};
|
|
1125
1156
|
function createHealthChecker(config, logger, rateLimiter) {
|
|
1126
1157
|
return new HealthChecker(config, logger, rateLimiter);
|
|
@@ -1565,7 +1596,7 @@ var DEFAULT_CONFIG2 = {
|
|
|
1565
1596
|
minStatus: ["available", "degraded"]
|
|
1566
1597
|
};
|
|
1567
1598
|
var ProviderSelector = class {
|
|
1568
|
-
constructor(registry, healthChecker, config, logger) {
|
|
1599
|
+
constructor(registry, healthChecker, config, logger, adapter = "node") {
|
|
1569
1600
|
// Selection state
|
|
1570
1601
|
this.selectedProviderId = null;
|
|
1571
1602
|
this.autoSelect = true;
|
|
@@ -1577,6 +1608,7 @@ var ProviderSelector = class {
|
|
|
1577
1608
|
this.healthChecker = healthChecker;
|
|
1578
1609
|
this.config = { ...DEFAULT_CONFIG2, ...config };
|
|
1579
1610
|
this.logger = logger || consoleLogger4;
|
|
1611
|
+
this.adapter = adapter;
|
|
1580
1612
|
}
|
|
1581
1613
|
// ========================================================================
|
|
1582
1614
|
// Selection Methods
|
|
@@ -1617,9 +1649,19 @@ var ProviderSelector = class {
|
|
|
1617
1649
|
* Find the best provider for a network (recalculates)
|
|
1618
1650
|
*/
|
|
1619
1651
|
findBestProvider(network) {
|
|
1620
|
-
|
|
1652
|
+
let providers = this.registry.getProvidersForNetwork(network);
|
|
1653
|
+
if (this.adapter === "browser") {
|
|
1654
|
+
const beforeCount = providers.length;
|
|
1655
|
+
providers = this.filterBrowserCompatible(providers, network);
|
|
1656
|
+
const filteredCount = beforeCount - providers.length;
|
|
1657
|
+
if (filteredCount > 0) {
|
|
1658
|
+
this.logger.debug(
|
|
1659
|
+
`Filtered out ${filteredCount} browser-incompatible provider(s) for ${network}`
|
|
1660
|
+
);
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1621
1663
|
if (providers.length === 0) {
|
|
1622
|
-
this.logger.warn(`No providers available for ${network}`);
|
|
1664
|
+
this.logger.warn(`No browser-compatible providers available for ${network}`);
|
|
1623
1665
|
return null;
|
|
1624
1666
|
}
|
|
1625
1667
|
const scored = providers.map((provider) => ({
|
|
@@ -1636,13 +1678,25 @@ var ProviderSelector = class {
|
|
|
1636
1678
|
);
|
|
1637
1679
|
this.activeProviderByNetwork.set(network, defaultProvider.id);
|
|
1638
1680
|
return defaultProvider;
|
|
1639
|
-
}
|
|
1681
|
+
}
|
|
1682
|
+
if (health.success === true) {
|
|
1640
1683
|
this.logger.warn(
|
|
1641
1684
|
`No healthy providers for ${network}, using default: ${defaultProvider.id}`
|
|
1642
1685
|
);
|
|
1643
1686
|
this.activeProviderByNetwork.set(network, defaultProvider.id);
|
|
1644
1687
|
return defaultProvider;
|
|
1645
1688
|
}
|
|
1689
|
+
if (health.success === false && health.lastTested) {
|
|
1690
|
+
const timeSinceFailure = Date.now() - health.lastTested.getTime();
|
|
1691
|
+
const cooldownMs = 3e4;
|
|
1692
|
+
if (timeSinceFailure > cooldownMs) {
|
|
1693
|
+
this.logger.warn(
|
|
1694
|
+
`No healthy providers for ${network}, retrying failed default after cooldown: ${defaultProvider.id}`
|
|
1695
|
+
);
|
|
1696
|
+
this.activeProviderByNetwork.set(network, defaultProvider.id);
|
|
1697
|
+
return defaultProvider;
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1646
1700
|
}
|
|
1647
1701
|
for (const provider of providers) {
|
|
1648
1702
|
const health = this.healthChecker.getResult(provider.id, network);
|
|
@@ -1653,8 +1707,19 @@ var ProviderSelector = class {
|
|
|
1653
1707
|
this.activeProviderByNetwork.set(network, provider.id);
|
|
1654
1708
|
return provider;
|
|
1655
1709
|
}
|
|
1710
|
+
if (health.success === false && health.lastTested) {
|
|
1711
|
+
const timeSinceFailure = Date.now() - health.lastTested.getTime();
|
|
1712
|
+
const cooldownMs = 3e4;
|
|
1713
|
+
if (timeSinceFailure > cooldownMs) {
|
|
1714
|
+
this.logger.warn(
|
|
1715
|
+
`No healthy providers for ${network}, retrying failed provider after cooldown: ${provider.id}`
|
|
1716
|
+
);
|
|
1717
|
+
this.activeProviderByNetwork.set(network, provider.id);
|
|
1718
|
+
return provider;
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1656
1721
|
}
|
|
1657
|
-
this.logger.error(`No available providers for ${network} (all tested and failed)`);
|
|
1722
|
+
this.logger.error(`No available providers for ${network} (all tested and failed, cooldown active)`);
|
|
1658
1723
|
return null;
|
|
1659
1724
|
}
|
|
1660
1725
|
const best = scored[0].provider;
|
|
@@ -1677,7 +1742,10 @@ var ProviderSelector = class {
|
|
|
1677
1742
|
* Get all available providers for a network, sorted by score
|
|
1678
1743
|
*/
|
|
1679
1744
|
getAvailableProviders(network) {
|
|
1680
|
-
|
|
1745
|
+
let providers = this.registry.getProvidersForNetwork(network);
|
|
1746
|
+
if (this.adapter === "browser") {
|
|
1747
|
+
providers = this.filterBrowserCompatible(providers, network);
|
|
1748
|
+
}
|
|
1681
1749
|
return providers.map((provider) => ({
|
|
1682
1750
|
provider,
|
|
1683
1751
|
score: this.scoreProvider(provider, network)
|
|
@@ -1687,7 +1755,10 @@ var ProviderSelector = class {
|
|
|
1687
1755
|
* Get the next best provider (for failover)
|
|
1688
1756
|
*/
|
|
1689
1757
|
getNextProvider(network, excludeIds) {
|
|
1690
|
-
|
|
1758
|
+
let providers = this.registry.getProvidersForNetwork(network);
|
|
1759
|
+
if (this.adapter === "browser") {
|
|
1760
|
+
providers = this.filterBrowserCompatible(providers, network);
|
|
1761
|
+
}
|
|
1691
1762
|
const available = providers.filter((p) => !excludeIds.includes(p.id)).map((provider) => ({
|
|
1692
1763
|
provider,
|
|
1693
1764
|
score: this.scoreProvider(provider, network)
|
|
@@ -1709,6 +1780,13 @@ var ProviderSelector = class {
|
|
|
1709
1780
|
return 0.01 * (1 / (provider.priority + 1));
|
|
1710
1781
|
}
|
|
1711
1782
|
if (health.success === false) {
|
|
1783
|
+
if (health.lastTested) {
|
|
1784
|
+
const timeSinceFailure = Date.now() - health.lastTested.getTime();
|
|
1785
|
+
const cooldownMs = 3e4;
|
|
1786
|
+
if (timeSinceFailure > cooldownMs) {
|
|
1787
|
+
return 1e-3 * (1 / (provider.priority + 1));
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1712
1790
|
return 0;
|
|
1713
1791
|
}
|
|
1714
1792
|
if (health.status === "offline") {
|
|
@@ -1871,12 +1949,39 @@ var ProviderSelector = class {
|
|
|
1871
1949
|
endpointV2: this.customEndpoint,
|
|
1872
1950
|
rps: 10,
|
|
1873
1951
|
priority: 0,
|
|
1874
|
-
isDynamic: false
|
|
1952
|
+
isDynamic: false,
|
|
1953
|
+
browserCompatible: true
|
|
1954
|
+
// Custom endpoints are assumed compatible
|
|
1875
1955
|
};
|
|
1876
1956
|
}
|
|
1957
|
+
/**
|
|
1958
|
+
* Filter providers to only include browser-compatible ones
|
|
1959
|
+
*
|
|
1960
|
+
* Checks both:
|
|
1961
|
+
* 1. Provider config browserCompatible flag
|
|
1962
|
+
* 2. Health check result browserCompatible flag (if health check was performed)
|
|
1963
|
+
*/
|
|
1964
|
+
filterBrowserCompatible(providers, network) {
|
|
1965
|
+
return providers.filter((provider) => {
|
|
1966
|
+
if (!provider.browserCompatible) {
|
|
1967
|
+
this.logger.debug(
|
|
1968
|
+
`Provider ${provider.id} marked as browser-incompatible in config`
|
|
1969
|
+
);
|
|
1970
|
+
return false;
|
|
1971
|
+
}
|
|
1972
|
+
const health = this.healthChecker.getResult(provider.id, network);
|
|
1973
|
+
if (health && health.browserCompatible === false) {
|
|
1974
|
+
this.logger.debug(
|
|
1975
|
+
`Provider ${provider.id} marked as browser-incompatible by health check (CORS error detected)`
|
|
1976
|
+
);
|
|
1977
|
+
return false;
|
|
1978
|
+
}
|
|
1979
|
+
return true;
|
|
1980
|
+
});
|
|
1981
|
+
}
|
|
1877
1982
|
};
|
|
1878
|
-
function createSelector(registry, healthChecker, config, logger) {
|
|
1879
|
-
return new ProviderSelector(registry, healthChecker, config, logger);
|
|
1983
|
+
function createSelector(registry, healthChecker, config, logger, adapter = "node") {
|
|
1984
|
+
return new ProviderSelector(registry, healthChecker, config, logger, adapter);
|
|
1880
1985
|
}
|
|
1881
1986
|
|
|
1882
1987
|
// src/core/manager.ts
|
|
@@ -1983,7 +2088,8 @@ var _ProviderManager = class _ProviderManager {
|
|
|
1983
2088
|
this.registry,
|
|
1984
2089
|
this.healthChecker,
|
|
1985
2090
|
void 0,
|
|
1986
|
-
this.options.logger
|
|
2091
|
+
this.options.logger,
|
|
2092
|
+
this.options.adapter
|
|
1987
2093
|
);
|
|
1988
2094
|
this.initialized = true;
|
|
1989
2095
|
this.notifyListeners();
|
|
@@ -2250,7 +2356,20 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2250
2356
|
*/
|
|
2251
2357
|
getProviders() {
|
|
2252
2358
|
if (!this.initialized || !this.network) return [];
|
|
2253
|
-
|
|
2359
|
+
let providers = this.registry.getProvidersForNetwork(this.network);
|
|
2360
|
+
if (this.options.adapter === "browser") {
|
|
2361
|
+
providers = providers.filter((provider) => {
|
|
2362
|
+
if (!provider.browserCompatible) {
|
|
2363
|
+
return false;
|
|
2364
|
+
}
|
|
2365
|
+
const health = this.healthChecker.getResult(provider.id, this.network);
|
|
2366
|
+
if (health && health.browserCompatible === false) {
|
|
2367
|
+
return false;
|
|
2368
|
+
}
|
|
2369
|
+
return true;
|
|
2370
|
+
});
|
|
2371
|
+
}
|
|
2372
|
+
return providers;
|
|
2254
2373
|
}
|
|
2255
2374
|
/**
|
|
2256
2375
|
* Get provider health results for current network
|
|
@@ -2296,7 +2415,8 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2296
2415
|
latencyMs: null,
|
|
2297
2416
|
seqno: null,
|
|
2298
2417
|
blocksBehind: 0,
|
|
2299
|
-
lastTested: null
|
|
2418
|
+
lastTested: null,
|
|
2419
|
+
browserCompatible: provider.browserCompatible
|
|
2300
2420
|
},
|
|
2301
2421
|
rateLimit: rateLimit || {
|
|
2302
2422
|
tokens: 0,
|