ton-provider-system 0.1.10 → 0.1.12
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 +109 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -2
- package/dist/index.d.ts +36 -2
- package/dist/index.js +109 -19
- 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
|
|
@@ -357,6 +363,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
|
|
|
357
363
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
358
364
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
359
365
|
isDynamic: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
366
|
+
browserCompatible: z.ZodOptional<z.ZodBoolean>;
|
|
360
367
|
description: z.ZodOptional<z.ZodString>;
|
|
361
368
|
}, "strip", z.ZodTypeAny, {
|
|
362
369
|
type: "chainstack" | "quicknode" | "toncenter" | "orbs" | "onfinality" | "ankr" | "getblock" | "tatum" | "tonhub" | "custom";
|
|
@@ -374,6 +381,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
|
|
|
374
381
|
isDynamic: boolean;
|
|
375
382
|
keyEnvVar?: string | undefined;
|
|
376
383
|
apiKeyEnvVar?: string | undefined;
|
|
384
|
+
browserCompatible?: boolean | undefined;
|
|
377
385
|
description?: string | undefined;
|
|
378
386
|
}, {
|
|
379
387
|
type: "chainstack" | "quicknode" | "toncenter" | "orbs" | "onfinality" | "ankr" | "getblock" | "tatum" | "tonhub" | "custom";
|
|
@@ -391,6 +399,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
|
|
|
391
399
|
priority?: number | undefined;
|
|
392
400
|
enabled?: boolean | undefined;
|
|
393
401
|
isDynamic?: boolean | undefined;
|
|
402
|
+
browserCompatible?: boolean | undefined;
|
|
394
403
|
description?: string | undefined;
|
|
395
404
|
}>;
|
|
396
405
|
/**
|
|
@@ -435,6 +444,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
435
444
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
436
445
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
437
446
|
isDynamic: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
447
|
+
browserCompatible: z.ZodOptional<z.ZodBoolean>;
|
|
438
448
|
description: z.ZodOptional<z.ZodString>;
|
|
439
449
|
}, "strip", z.ZodTypeAny, {
|
|
440
450
|
type: "chainstack" | "quicknode" | "toncenter" | "orbs" | "onfinality" | "ankr" | "getblock" | "tatum" | "tonhub" | "custom";
|
|
@@ -452,6 +462,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
452
462
|
isDynamic: boolean;
|
|
453
463
|
keyEnvVar?: string | undefined;
|
|
454
464
|
apiKeyEnvVar?: string | undefined;
|
|
465
|
+
browserCompatible?: boolean | undefined;
|
|
455
466
|
description?: string | undefined;
|
|
456
467
|
}, {
|
|
457
468
|
type: "chainstack" | "quicknode" | "toncenter" | "orbs" | "onfinality" | "ankr" | "getblock" | "tatum" | "tonhub" | "custom";
|
|
@@ -469,6 +480,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
469
480
|
priority?: number | undefined;
|
|
470
481
|
enabled?: boolean | undefined;
|
|
471
482
|
isDynamic?: boolean | undefined;
|
|
483
|
+
browserCompatible?: boolean | undefined;
|
|
472
484
|
description?: string | undefined;
|
|
473
485
|
}>>;
|
|
474
486
|
defaults: z.ZodObject<{
|
|
@@ -499,6 +511,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
499
511
|
isDynamic: boolean;
|
|
500
512
|
keyEnvVar?: string | undefined;
|
|
501
513
|
apiKeyEnvVar?: string | undefined;
|
|
514
|
+
browserCompatible?: boolean | undefined;
|
|
502
515
|
description?: string | undefined;
|
|
503
516
|
}>;
|
|
504
517
|
defaults: {
|
|
@@ -523,6 +536,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
523
536
|
priority?: number | undefined;
|
|
524
537
|
enabled?: boolean | undefined;
|
|
525
538
|
isDynamic?: boolean | undefined;
|
|
539
|
+
browserCompatible?: boolean | undefined;
|
|
526
540
|
description?: string | undefined;
|
|
527
541
|
}>;
|
|
528
542
|
defaults: {
|
|
@@ -549,6 +563,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
549
563
|
isDynamic: boolean;
|
|
550
564
|
keyEnvVar?: string | undefined;
|
|
551
565
|
apiKeyEnvVar?: string | undefined;
|
|
566
|
+
browserCompatible?: boolean | undefined;
|
|
552
567
|
description?: string | undefined;
|
|
553
568
|
}>;
|
|
554
569
|
defaults: {
|
|
@@ -573,6 +588,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
573
588
|
priority?: number | undefined;
|
|
574
589
|
enabled?: boolean | undefined;
|
|
575
590
|
isDynamic?: boolean | undefined;
|
|
591
|
+
browserCompatible?: boolean | undefined;
|
|
576
592
|
description?: string | undefined;
|
|
577
593
|
}>;
|
|
578
594
|
defaults: {
|
|
@@ -1039,6 +1055,15 @@ declare class HealthChecker {
|
|
|
1039
1055
|
*/
|
|
1040
1056
|
private callGetMasterchainInfo;
|
|
1041
1057
|
private sleep;
|
|
1058
|
+
/**
|
|
1059
|
+
* Detect CORS errors (browser compatibility issues)
|
|
1060
|
+
*
|
|
1061
|
+
* CORS errors occur when:
|
|
1062
|
+
* - Request header field is not allowed by Access-Control-Allow-Headers
|
|
1063
|
+
* - Specifically, x-ton-client-version header is blocked by some providers
|
|
1064
|
+
* - Error message contains "CORS", "Access-Control", or "x-ton-client-version"
|
|
1065
|
+
*/
|
|
1066
|
+
private isCorsError;
|
|
1042
1067
|
}
|
|
1043
1068
|
/**
|
|
1044
1069
|
* Create a health checker with default configuration
|
|
@@ -1078,12 +1103,13 @@ declare class ProviderSelector {
|
|
|
1078
1103
|
private healthChecker;
|
|
1079
1104
|
private config;
|
|
1080
1105
|
private logger;
|
|
1106
|
+
private adapter;
|
|
1081
1107
|
private selectedProviderId;
|
|
1082
1108
|
private autoSelect;
|
|
1083
1109
|
private customEndpoint;
|
|
1084
1110
|
private bestProviderByNetwork;
|
|
1085
1111
|
private activeProviderByNetwork;
|
|
1086
|
-
constructor(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger);
|
|
1112
|
+
constructor(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger, adapter?: 'node' | 'browser');
|
|
1087
1113
|
/**
|
|
1088
1114
|
* Get the best provider for a network
|
|
1089
1115
|
*/
|
|
@@ -1166,11 +1192,19 @@ declare class ProviderSelector {
|
|
|
1166
1192
|
* Create a pseudo-provider for custom endpoint
|
|
1167
1193
|
*/
|
|
1168
1194
|
private createCustomProvider;
|
|
1195
|
+
/**
|
|
1196
|
+
* Filter providers to only include browser-compatible ones
|
|
1197
|
+
*
|
|
1198
|
+
* Checks both:
|
|
1199
|
+
* 1. Provider config browserCompatible flag
|
|
1200
|
+
* 2. Health check result browserCompatible flag (if health check was performed)
|
|
1201
|
+
*/
|
|
1202
|
+
private filterBrowserCompatible;
|
|
1169
1203
|
}
|
|
1170
1204
|
/**
|
|
1171
1205
|
* Create a provider selector
|
|
1172
1206
|
*/
|
|
1173
|
-
declare function createSelector(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger): ProviderSelector;
|
|
1207
|
+
declare function createSelector(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger, adapter?: 'node' | 'browser'): ProviderSelector;
|
|
1174
1208
|
|
|
1175
1209
|
/**
|
|
1176
1210
|
* 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
|
|
@@ -357,6 +363,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
|
|
|
357
363
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
358
364
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
359
365
|
isDynamic: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
366
|
+
browserCompatible: z.ZodOptional<z.ZodBoolean>;
|
|
360
367
|
description: z.ZodOptional<z.ZodString>;
|
|
361
368
|
}, "strip", z.ZodTypeAny, {
|
|
362
369
|
type: "chainstack" | "quicknode" | "toncenter" | "orbs" | "onfinality" | "ankr" | "getblock" | "tatum" | "tonhub" | "custom";
|
|
@@ -374,6 +381,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
|
|
|
374
381
|
isDynamic: boolean;
|
|
375
382
|
keyEnvVar?: string | undefined;
|
|
376
383
|
apiKeyEnvVar?: string | undefined;
|
|
384
|
+
browserCompatible?: boolean | undefined;
|
|
377
385
|
description?: string | undefined;
|
|
378
386
|
}, {
|
|
379
387
|
type: "chainstack" | "quicknode" | "toncenter" | "orbs" | "onfinality" | "ankr" | "getblock" | "tatum" | "tonhub" | "custom";
|
|
@@ -391,6 +399,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
|
|
|
391
399
|
priority?: number | undefined;
|
|
392
400
|
enabled?: boolean | undefined;
|
|
393
401
|
isDynamic?: boolean | undefined;
|
|
402
|
+
browserCompatible?: boolean | undefined;
|
|
394
403
|
description?: string | undefined;
|
|
395
404
|
}>;
|
|
396
405
|
/**
|
|
@@ -435,6 +444,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
435
444
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
436
445
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
437
446
|
isDynamic: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
447
|
+
browserCompatible: z.ZodOptional<z.ZodBoolean>;
|
|
438
448
|
description: z.ZodOptional<z.ZodString>;
|
|
439
449
|
}, "strip", z.ZodTypeAny, {
|
|
440
450
|
type: "chainstack" | "quicknode" | "toncenter" | "orbs" | "onfinality" | "ankr" | "getblock" | "tatum" | "tonhub" | "custom";
|
|
@@ -452,6 +462,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
452
462
|
isDynamic: boolean;
|
|
453
463
|
keyEnvVar?: string | undefined;
|
|
454
464
|
apiKeyEnvVar?: string | undefined;
|
|
465
|
+
browserCompatible?: boolean | undefined;
|
|
455
466
|
description?: string | undefined;
|
|
456
467
|
}, {
|
|
457
468
|
type: "chainstack" | "quicknode" | "toncenter" | "orbs" | "onfinality" | "ankr" | "getblock" | "tatum" | "tonhub" | "custom";
|
|
@@ -469,6 +480,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
469
480
|
priority?: number | undefined;
|
|
470
481
|
enabled?: boolean | undefined;
|
|
471
482
|
isDynamic?: boolean | undefined;
|
|
483
|
+
browserCompatible?: boolean | undefined;
|
|
472
484
|
description?: string | undefined;
|
|
473
485
|
}>>;
|
|
474
486
|
defaults: z.ZodObject<{
|
|
@@ -499,6 +511,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
499
511
|
isDynamic: boolean;
|
|
500
512
|
keyEnvVar?: string | undefined;
|
|
501
513
|
apiKeyEnvVar?: string | undefined;
|
|
514
|
+
browserCompatible?: boolean | undefined;
|
|
502
515
|
description?: string | undefined;
|
|
503
516
|
}>;
|
|
504
517
|
defaults: {
|
|
@@ -523,6 +536,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
523
536
|
priority?: number | undefined;
|
|
524
537
|
enabled?: boolean | undefined;
|
|
525
538
|
isDynamic?: boolean | undefined;
|
|
539
|
+
browserCompatible?: boolean | undefined;
|
|
526
540
|
description?: string | undefined;
|
|
527
541
|
}>;
|
|
528
542
|
defaults: {
|
|
@@ -549,6 +563,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
549
563
|
isDynamic: boolean;
|
|
550
564
|
keyEnvVar?: string | undefined;
|
|
551
565
|
apiKeyEnvVar?: string | undefined;
|
|
566
|
+
browserCompatible?: boolean | undefined;
|
|
552
567
|
description?: string | undefined;
|
|
553
568
|
}>;
|
|
554
569
|
defaults: {
|
|
@@ -573,6 +588,7 @@ declare const RpcConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
573
588
|
priority?: number | undefined;
|
|
574
589
|
enabled?: boolean | undefined;
|
|
575
590
|
isDynamic?: boolean | undefined;
|
|
591
|
+
browserCompatible?: boolean | undefined;
|
|
576
592
|
description?: string | undefined;
|
|
577
593
|
}>;
|
|
578
594
|
defaults: {
|
|
@@ -1039,6 +1055,15 @@ declare class HealthChecker {
|
|
|
1039
1055
|
*/
|
|
1040
1056
|
private callGetMasterchainInfo;
|
|
1041
1057
|
private sleep;
|
|
1058
|
+
/**
|
|
1059
|
+
* Detect CORS errors (browser compatibility issues)
|
|
1060
|
+
*
|
|
1061
|
+
* CORS errors occur when:
|
|
1062
|
+
* - Request header field is not allowed by Access-Control-Allow-Headers
|
|
1063
|
+
* - Specifically, x-ton-client-version header is blocked by some providers
|
|
1064
|
+
* - Error message contains "CORS", "Access-Control", or "x-ton-client-version"
|
|
1065
|
+
*/
|
|
1066
|
+
private isCorsError;
|
|
1042
1067
|
}
|
|
1043
1068
|
/**
|
|
1044
1069
|
* Create a health checker with default configuration
|
|
@@ -1078,12 +1103,13 @@ declare class ProviderSelector {
|
|
|
1078
1103
|
private healthChecker;
|
|
1079
1104
|
private config;
|
|
1080
1105
|
private logger;
|
|
1106
|
+
private adapter;
|
|
1081
1107
|
private selectedProviderId;
|
|
1082
1108
|
private autoSelect;
|
|
1083
1109
|
private customEndpoint;
|
|
1084
1110
|
private bestProviderByNetwork;
|
|
1085
1111
|
private activeProviderByNetwork;
|
|
1086
|
-
constructor(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger);
|
|
1112
|
+
constructor(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger, adapter?: 'node' | 'browser');
|
|
1087
1113
|
/**
|
|
1088
1114
|
* Get the best provider for a network
|
|
1089
1115
|
*/
|
|
@@ -1166,11 +1192,19 @@ declare class ProviderSelector {
|
|
|
1166
1192
|
* Create a pseudo-provider for custom endpoint
|
|
1167
1193
|
*/
|
|
1168
1194
|
private createCustomProvider;
|
|
1195
|
+
/**
|
|
1196
|
+
* Filter providers to only include browser-compatible ones
|
|
1197
|
+
*
|
|
1198
|
+
* Checks both:
|
|
1199
|
+
* 1. Provider config browserCompatible flag
|
|
1200
|
+
* 2. Health check result browserCompatible flag (if health check was performed)
|
|
1201
|
+
*/
|
|
1202
|
+
private filterBrowserCompatible;
|
|
1169
1203
|
}
|
|
1170
1204
|
/**
|
|
1171
1205
|
* Create a provider selector
|
|
1172
1206
|
*/
|
|
1173
|
-
declare function createSelector(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger): ProviderSelector;
|
|
1207
|
+
declare function createSelector(registry: ProviderRegistry, healthChecker: HealthChecker, config?: Partial<SelectionConfig>, logger?: Logger, adapter?: 'node' | 'browser'): ProviderSelector;
|
|
1174
1208
|
|
|
1175
1209
|
/**
|
|
1176
1210
|
* Unified Provider System - Provider Manager
|
package/dist/index.js
CHANGED
|
@@ -67,6 +67,7 @@ var ProviderConfigSchema = z.object({
|
|
|
67
67
|
priority: z.number().int().nonnegative().default(10),
|
|
68
68
|
enabled: z.boolean().default(true),
|
|
69
69
|
isDynamic: z.boolean().optional().default(false),
|
|
70
|
+
browserCompatible: z.boolean().optional(),
|
|
70
71
|
description: z.string().optional()
|
|
71
72
|
});
|
|
72
73
|
var NetworkDefaultsSchema = z.object({
|
|
@@ -214,7 +215,8 @@ function resolveProvider(id, config) {
|
|
|
214
215
|
apiKey,
|
|
215
216
|
rps: config.rps,
|
|
216
217
|
priority: config.priority,
|
|
217
|
-
isDynamic: config.isDynamic || false
|
|
218
|
+
isDynamic: config.isDynamic || false,
|
|
219
|
+
browserCompatible: config.browserCompatible !== void 0 ? config.browserCompatible : true
|
|
218
220
|
};
|
|
219
221
|
}
|
|
220
222
|
function resolveAllProviders(config) {
|
|
@@ -773,7 +775,8 @@ var HealthChecker = class {
|
|
|
773
775
|
latencyMs: null,
|
|
774
776
|
seqno: null,
|
|
775
777
|
blocksBehind: 0,
|
|
776
|
-
lastTested: null
|
|
778
|
+
lastTested: null,
|
|
779
|
+
browserCompatible: provider.browserCompatible
|
|
777
780
|
};
|
|
778
781
|
this.results.set(key, testingResult);
|
|
779
782
|
try {
|
|
@@ -833,7 +836,8 @@ var HealthChecker = class {
|
|
|
833
836
|
seqno,
|
|
834
837
|
blocksBehind,
|
|
835
838
|
lastTested: /* @__PURE__ */ new Date(),
|
|
836
|
-
cachedEndpoint: normalizedEndpoint
|
|
839
|
+
cachedEndpoint: normalizedEndpoint,
|
|
840
|
+
browserCompatible: provider.browserCompatible
|
|
837
841
|
};
|
|
838
842
|
this.results.set(key, result);
|
|
839
843
|
this.logger.debug(
|
|
@@ -844,6 +848,7 @@ var HealthChecker = class {
|
|
|
844
848
|
const endTime = performance.now();
|
|
845
849
|
const latencyMs = Math.round(endTime - startTime);
|
|
846
850
|
const errorMsg = error.message || String(error) || "Unknown error";
|
|
851
|
+
const isCorsError = this.isCorsError(error, errorMsg);
|
|
847
852
|
const is429 = errorMsg.includes("429") || errorMsg.toLowerCase().includes("rate limit");
|
|
848
853
|
const is404 = errorMsg.includes("404") || errorMsg.toLowerCase().includes("not found");
|
|
849
854
|
const is503 = errorMsg.includes("503") || errorMsg.toLowerCase().includes("service unavailable");
|
|
@@ -858,6 +863,7 @@ var HealthChecker = class {
|
|
|
858
863
|
} else if (isTimeout) {
|
|
859
864
|
status = "offline";
|
|
860
865
|
}
|
|
866
|
+
const browserCompatible = isCorsError ? false : provider.browserCompatible;
|
|
861
867
|
const result = {
|
|
862
868
|
id: provider.id,
|
|
863
869
|
network: provider.network,
|
|
@@ -867,7 +873,8 @@ var HealthChecker = class {
|
|
|
867
873
|
seqno: null,
|
|
868
874
|
blocksBehind: 0,
|
|
869
875
|
lastTested: /* @__PURE__ */ new Date(),
|
|
870
|
-
error: errorMsg
|
|
876
|
+
error: errorMsg,
|
|
877
|
+
browserCompatible
|
|
871
878
|
};
|
|
872
879
|
this.results.set(key, result);
|
|
873
880
|
this.logger.warn(`Provider ${provider.id} health check failed: ${result.error}`);
|
|
@@ -953,7 +960,8 @@ var HealthChecker = class {
|
|
|
953
960
|
// Degraded providers are still usable, just slower/rate-limited
|
|
954
961
|
status: "degraded",
|
|
955
962
|
error: error || "Marked as degraded",
|
|
956
|
-
lastTested: /* @__PURE__ */ new Date()
|
|
963
|
+
lastTested: /* @__PURE__ */ new Date(),
|
|
964
|
+
browserCompatible: existing.browserCompatible ?? true
|
|
957
965
|
} : {
|
|
958
966
|
id: providerId,
|
|
959
967
|
network,
|
|
@@ -964,7 +972,9 @@ var HealthChecker = class {
|
|
|
964
972
|
seqno: null,
|
|
965
973
|
blocksBehind: 0,
|
|
966
974
|
lastTested: /* @__PURE__ */ new Date(),
|
|
967
|
-
error: error || "Marked as degraded"
|
|
975
|
+
error: error || "Marked as degraded",
|
|
976
|
+
browserCompatible: true
|
|
977
|
+
// Default to compatible if unknown
|
|
968
978
|
};
|
|
969
979
|
this.results.set(key, result);
|
|
970
980
|
}
|
|
@@ -980,7 +990,8 @@ var HealthChecker = class {
|
|
|
980
990
|
success: false,
|
|
981
991
|
// Ensure success is false for offline providers
|
|
982
992
|
error: error || "Marked as offline",
|
|
983
|
-
lastTested: /* @__PURE__ */ new Date()
|
|
993
|
+
lastTested: /* @__PURE__ */ new Date(),
|
|
994
|
+
browserCompatible: existing.browserCompatible ?? true
|
|
984
995
|
} : {
|
|
985
996
|
id: providerId,
|
|
986
997
|
network,
|
|
@@ -990,7 +1001,9 @@ var HealthChecker = class {
|
|
|
990
1001
|
seqno: null,
|
|
991
1002
|
blocksBehind: 0,
|
|
992
1003
|
lastTested: /* @__PURE__ */ new Date(),
|
|
993
|
-
error: error || "Marked as offline"
|
|
1004
|
+
error: error || "Marked as offline",
|
|
1005
|
+
browserCompatible: true
|
|
1006
|
+
// Default to compatible if unknown
|
|
994
1007
|
};
|
|
995
1008
|
this.results.set(key, result);
|
|
996
1009
|
}
|
|
@@ -1122,6 +1135,24 @@ var HealthChecker = class {
|
|
|
1122
1135
|
sleep(ms) {
|
|
1123
1136
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1124
1137
|
}
|
|
1138
|
+
/**
|
|
1139
|
+
* Detect CORS errors (browser compatibility issues)
|
|
1140
|
+
*
|
|
1141
|
+
* CORS errors occur when:
|
|
1142
|
+
* - Request header field is not allowed by Access-Control-Allow-Headers
|
|
1143
|
+
* - Specifically, x-ton-client-version header is blocked by some providers
|
|
1144
|
+
* - Error message contains "CORS", "Access-Control", or "x-ton-client-version"
|
|
1145
|
+
*/
|
|
1146
|
+
isCorsError(error, errorMsg) {
|
|
1147
|
+
const msg = errorMsg.toLowerCase();
|
|
1148
|
+
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")) {
|
|
1149
|
+
return true;
|
|
1150
|
+
}
|
|
1151
|
+
if (error.name === "TypeError" && (msg.includes("failed to fetch") || msg.includes("network error"))) {
|
|
1152
|
+
return false;
|
|
1153
|
+
}
|
|
1154
|
+
return false;
|
|
1155
|
+
}
|
|
1125
1156
|
};
|
|
1126
1157
|
function createHealthChecker(config, logger, rateLimiter) {
|
|
1127
1158
|
return new HealthChecker(config, logger, rateLimiter);
|
|
@@ -1566,7 +1597,7 @@ var DEFAULT_CONFIG2 = {
|
|
|
1566
1597
|
minStatus: ["available", "degraded"]
|
|
1567
1598
|
};
|
|
1568
1599
|
var ProviderSelector = class {
|
|
1569
|
-
constructor(registry, healthChecker, config, logger) {
|
|
1600
|
+
constructor(registry, healthChecker, config, logger, adapter = "node") {
|
|
1570
1601
|
// Selection state
|
|
1571
1602
|
this.selectedProviderId = null;
|
|
1572
1603
|
this.autoSelect = true;
|
|
@@ -1578,6 +1609,7 @@ var ProviderSelector = class {
|
|
|
1578
1609
|
this.healthChecker = healthChecker;
|
|
1579
1610
|
this.config = { ...DEFAULT_CONFIG2, ...config };
|
|
1580
1611
|
this.logger = logger || consoleLogger4;
|
|
1612
|
+
this.adapter = adapter;
|
|
1581
1613
|
}
|
|
1582
1614
|
// ========================================================================
|
|
1583
1615
|
// Selection Methods
|
|
@@ -1618,9 +1650,19 @@ var ProviderSelector = class {
|
|
|
1618
1650
|
* Find the best provider for a network (recalculates)
|
|
1619
1651
|
*/
|
|
1620
1652
|
findBestProvider(network) {
|
|
1621
|
-
|
|
1653
|
+
let providers = this.registry.getProvidersForNetwork(network);
|
|
1654
|
+
if (this.adapter === "browser") {
|
|
1655
|
+
const beforeCount = providers.length;
|
|
1656
|
+
providers = this.filterBrowserCompatible(providers, network);
|
|
1657
|
+
const filteredCount = beforeCount - providers.length;
|
|
1658
|
+
if (filteredCount > 0) {
|
|
1659
|
+
this.logger.debug(
|
|
1660
|
+
`Filtered out ${filteredCount} browser-incompatible provider(s) for ${network}`
|
|
1661
|
+
);
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1622
1664
|
if (providers.length === 0) {
|
|
1623
|
-
this.logger.warn(`No providers available for ${network}`);
|
|
1665
|
+
this.logger.warn(`No browser-compatible providers available for ${network}`);
|
|
1624
1666
|
return null;
|
|
1625
1667
|
}
|
|
1626
1668
|
const scored = providers.map((provider) => ({
|
|
@@ -1701,7 +1743,10 @@ var ProviderSelector = class {
|
|
|
1701
1743
|
* Get all available providers for a network, sorted by score
|
|
1702
1744
|
*/
|
|
1703
1745
|
getAvailableProviders(network) {
|
|
1704
|
-
|
|
1746
|
+
let providers = this.registry.getProvidersForNetwork(network);
|
|
1747
|
+
if (this.adapter === "browser") {
|
|
1748
|
+
providers = this.filterBrowserCompatible(providers, network);
|
|
1749
|
+
}
|
|
1705
1750
|
return providers.map((provider) => ({
|
|
1706
1751
|
provider,
|
|
1707
1752
|
score: this.scoreProvider(provider, network)
|
|
@@ -1711,7 +1756,10 @@ var ProviderSelector = class {
|
|
|
1711
1756
|
* Get the next best provider (for failover)
|
|
1712
1757
|
*/
|
|
1713
1758
|
getNextProvider(network, excludeIds) {
|
|
1714
|
-
|
|
1759
|
+
let providers = this.registry.getProvidersForNetwork(network);
|
|
1760
|
+
if (this.adapter === "browser") {
|
|
1761
|
+
providers = this.filterBrowserCompatible(providers, network);
|
|
1762
|
+
}
|
|
1715
1763
|
const available = providers.filter((p) => !excludeIds.includes(p.id)).map((provider) => ({
|
|
1716
1764
|
provider,
|
|
1717
1765
|
score: this.scoreProvider(provider, network)
|
|
@@ -1902,12 +1950,39 @@ var ProviderSelector = class {
|
|
|
1902
1950
|
endpointV2: this.customEndpoint,
|
|
1903
1951
|
rps: 10,
|
|
1904
1952
|
priority: 0,
|
|
1905
|
-
isDynamic: false
|
|
1953
|
+
isDynamic: false,
|
|
1954
|
+
browserCompatible: true
|
|
1955
|
+
// Custom endpoints are assumed compatible
|
|
1906
1956
|
};
|
|
1907
1957
|
}
|
|
1958
|
+
/**
|
|
1959
|
+
* Filter providers to only include browser-compatible ones
|
|
1960
|
+
*
|
|
1961
|
+
* Checks both:
|
|
1962
|
+
* 1. Provider config browserCompatible flag
|
|
1963
|
+
* 2. Health check result browserCompatible flag (if health check was performed)
|
|
1964
|
+
*/
|
|
1965
|
+
filterBrowserCompatible(providers, network) {
|
|
1966
|
+
return providers.filter((provider) => {
|
|
1967
|
+
if (!provider.browserCompatible) {
|
|
1968
|
+
this.logger.debug(
|
|
1969
|
+
`Provider ${provider.id} marked as browser-incompatible in config`
|
|
1970
|
+
);
|
|
1971
|
+
return false;
|
|
1972
|
+
}
|
|
1973
|
+
const health = this.healthChecker.getResult(provider.id, network);
|
|
1974
|
+
if (health && health.browserCompatible === false) {
|
|
1975
|
+
this.logger.debug(
|
|
1976
|
+
`Provider ${provider.id} marked as browser-incompatible by health check (CORS error detected)`
|
|
1977
|
+
);
|
|
1978
|
+
return false;
|
|
1979
|
+
}
|
|
1980
|
+
return true;
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1908
1983
|
};
|
|
1909
|
-
function createSelector(registry, healthChecker, config, logger) {
|
|
1910
|
-
return new ProviderSelector(registry, healthChecker, config, logger);
|
|
1984
|
+
function createSelector(registry, healthChecker, config, logger, adapter = "node") {
|
|
1985
|
+
return new ProviderSelector(registry, healthChecker, config, logger, adapter);
|
|
1911
1986
|
}
|
|
1912
1987
|
|
|
1913
1988
|
// src/core/manager.ts
|
|
@@ -2014,7 +2089,8 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2014
2089
|
this.registry,
|
|
2015
2090
|
this.healthChecker,
|
|
2016
2091
|
void 0,
|
|
2017
|
-
this.options.logger
|
|
2092
|
+
this.options.logger,
|
|
2093
|
+
this.options.adapter
|
|
2018
2094
|
);
|
|
2019
2095
|
this.initialized = true;
|
|
2020
2096
|
this.notifyListeners();
|
|
@@ -2281,7 +2357,20 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2281
2357
|
*/
|
|
2282
2358
|
getProviders() {
|
|
2283
2359
|
if (!this.initialized || !this.network) return [];
|
|
2284
|
-
|
|
2360
|
+
let providers = this.registry.getProvidersForNetwork(this.network);
|
|
2361
|
+
if (this.options.adapter === "browser") {
|
|
2362
|
+
providers = providers.filter((provider) => {
|
|
2363
|
+
if (!provider.browserCompatible) {
|
|
2364
|
+
return false;
|
|
2365
|
+
}
|
|
2366
|
+
const health = this.healthChecker.getResult(provider.id, this.network);
|
|
2367
|
+
if (health && health.browserCompatible === false) {
|
|
2368
|
+
return false;
|
|
2369
|
+
}
|
|
2370
|
+
return true;
|
|
2371
|
+
});
|
|
2372
|
+
}
|
|
2373
|
+
return providers;
|
|
2285
2374
|
}
|
|
2286
2375
|
/**
|
|
2287
2376
|
* Get provider health results for current network
|
|
@@ -2327,7 +2416,8 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2327
2416
|
latencyMs: null,
|
|
2328
2417
|
seqno: null,
|
|
2329
2418
|
blocksBehind: 0,
|
|
2330
|
-
lastTested: null
|
|
2419
|
+
lastTested: null,
|
|
2420
|
+
browserCompatible: provider.browserCompatible
|
|
2331
2421
|
},
|
|
2332
2422
|
rateLimit: rateLimit || {
|
|
2333
2423
|
tokens: 0,
|