ton-provider-system 0.3.1 → 0.5.0
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 +118 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -3
- package/dist/index.d.ts +83 -3
- package/dist/index.js +118 -13
- package/dist/index.js.map +1 -1
- package/package.json +15 -13
- package/rpc-schema.json +5 -0
- package/rpc.json +6 -3
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var zod = require('zod');
|
|
4
4
|
var ton = require('@ton/ton');
|
|
5
|
+
var core = require('@ton/core');
|
|
5
6
|
|
|
6
7
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
7
8
|
// src/types.ts
|
|
@@ -71,6 +72,7 @@ var ProviderConfigSchema = zod.z.object({
|
|
|
71
72
|
enabled: zod.z.boolean().default(true),
|
|
72
73
|
isDynamic: zod.z.boolean().optional().default(false),
|
|
73
74
|
browserCompatible: zod.z.boolean().optional(),
|
|
75
|
+
servesGetTransactions: zod.z.boolean().optional(),
|
|
74
76
|
description: zod.z.string().optional()
|
|
75
77
|
});
|
|
76
78
|
var NetworkDefaultsSchema = zod.z.object({
|
|
@@ -219,7 +221,10 @@ function resolveProvider(id, config) {
|
|
|
219
221
|
rps: config.rps,
|
|
220
222
|
priority: config.priority,
|
|
221
223
|
isDynamic: config.isDynamic || false,
|
|
222
|
-
browserCompatible: config.browserCompatible !== void 0 ? config.browserCompatible : true
|
|
224
|
+
browserCompatible: config.browserCompatible !== void 0 ? config.browserCompatible : true,
|
|
225
|
+
// Default true: a provider is assumed to serve getTransactions unless the
|
|
226
|
+
// config explicitly opts out (e.g. Chainstack/Orbs testnet liteserver proxies).
|
|
227
|
+
servesGetTransactions: config.servesGetTransactions !== false
|
|
223
228
|
};
|
|
224
229
|
}
|
|
225
230
|
function resolveAllProviders(config) {
|
|
@@ -2553,8 +2558,10 @@ var ProviderSelector = class {
|
|
|
2553
2558
|
rps: 10,
|
|
2554
2559
|
priority: 0,
|
|
2555
2560
|
isDynamic: false,
|
|
2556
|
-
browserCompatible: true
|
|
2561
|
+
browserCompatible: true,
|
|
2557
2562
|
// Custom endpoints are assumed compatible
|
|
2563
|
+
servesGetTransactions: true
|
|
2564
|
+
// Custom endpoints are assumed fully capable
|
|
2558
2565
|
};
|
|
2559
2566
|
}
|
|
2560
2567
|
/**
|
|
@@ -2885,26 +2892,39 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2885
2892
|
// ========================================================================
|
|
2886
2893
|
/**
|
|
2887
2894
|
* Report a successful request
|
|
2895
|
+
*
|
|
2896
|
+
* @param providerId - Optionally attribute the success to a SPECIFIC provider
|
|
2897
|
+
* (used by callers that drive their own candidate list, e.g.
|
|
2898
|
+
* NodeAdapter.getTransactions, where the provider used is not necessarily the
|
|
2899
|
+
* selector's current best). Defaults to the current best provider.
|
|
2888
2900
|
*/
|
|
2889
|
-
reportSuccess() {
|
|
2901
|
+
reportSuccess(providerId) {
|
|
2890
2902
|
if (!this.initialized || !this.network) return;
|
|
2891
|
-
const
|
|
2892
|
-
if (
|
|
2893
|
-
this.rateLimiter.reportSuccess(
|
|
2903
|
+
const id = providerId ?? this.selector.getBestProvider(this.network)?.id;
|
|
2904
|
+
if (id) {
|
|
2905
|
+
this.rateLimiter.reportSuccess(id);
|
|
2894
2906
|
}
|
|
2895
2907
|
}
|
|
2896
2908
|
/**
|
|
2897
2909
|
* Report an error (triggers provider switch if needed)
|
|
2910
|
+
*
|
|
2911
|
+
* @param providerId - Optionally attribute the error to a SPECIFIC provider
|
|
2912
|
+
* (used by callers that drive their own candidate list, e.g.
|
|
2913
|
+
* NodeAdapter.getTransactions). Defaults to the current active/best provider.
|
|
2898
2914
|
*/
|
|
2899
|
-
reportError(error) {
|
|
2915
|
+
reportError(error, providerId) {
|
|
2900
2916
|
if (!this.initialized || !this.network) return;
|
|
2901
|
-
const activeProviderId = this.selector.getActiveProviderId(this.network);
|
|
2902
2917
|
let provider = null;
|
|
2903
|
-
if (
|
|
2904
|
-
provider = this.registry.getProvider(
|
|
2905
|
-
}
|
|
2906
|
-
|
|
2907
|
-
|
|
2918
|
+
if (providerId) {
|
|
2919
|
+
provider = this.registry.getProvider(providerId) || null;
|
|
2920
|
+
} else {
|
|
2921
|
+
const activeProviderId = this.selector.getActiveProviderId(this.network);
|
|
2922
|
+
if (activeProviderId) {
|
|
2923
|
+
provider = this.registry.getProvider(activeProviderId) || null;
|
|
2924
|
+
}
|
|
2925
|
+
if (!provider) {
|
|
2926
|
+
provider = this.selector.getBestProvider(this.network);
|
|
2927
|
+
}
|
|
2908
2928
|
}
|
|
2909
2929
|
if (!provider) {
|
|
2910
2930
|
this.options.logger.warn(`Cannot report error: no provider available for ${this.network}`);
|
|
@@ -3034,6 +3054,21 @@ var _ProviderManager = class _ProviderManager {
|
|
|
3034
3054
|
}
|
|
3035
3055
|
return providers;
|
|
3036
3056
|
}
|
|
3057
|
+
/**
|
|
3058
|
+
* Get transaction-capable providers for the current network, in selector
|
|
3059
|
+
* score order (best first).
|
|
3060
|
+
*
|
|
3061
|
+
* Read-only: enumerates the score-ordered available providers and excludes any
|
|
3062
|
+
* flagged `servesGetTransactions: false` (Chainstack/Orbs testnet liteserver
|
|
3063
|
+
* proxies, which 403 on v2 getTransactions). Used by
|
|
3064
|
+
* NodeAdapter.getTransactions to build its candidate set WITHOUT poisoning the
|
|
3065
|
+
* incapable providers' global health — so the get-method path keeps using them.
|
|
3066
|
+
* Returns [] when no capable provider is currently selectable.
|
|
3067
|
+
*/
|
|
3068
|
+
getTransactionCapableProviders() {
|
|
3069
|
+
if (!this.initialized || !this.network) return [];
|
|
3070
|
+
return this.selector.getAvailableProviders(this.network).filter((p) => p.servesGetTransactions !== false);
|
|
3071
|
+
}
|
|
3037
3072
|
/**
|
|
3038
3073
|
* Get provider health results for current network
|
|
3039
3074
|
*/
|
|
@@ -3249,6 +3284,76 @@ var NodeAdapter = class {
|
|
|
3249
3284
|
};
|
|
3250
3285
|
}
|
|
3251
3286
|
// ========================================================================
|
|
3287
|
+
// Failover-aware high-level reads
|
|
3288
|
+
// ========================================================================
|
|
3289
|
+
/**
|
|
3290
|
+
* Get account transactions with capability-aware provider failover.
|
|
3291
|
+
*
|
|
3292
|
+
* Unlike `getClient().getTransactions(...)`, this builds a candidate set of the
|
|
3293
|
+
* network's *transaction-capable* providers (score-ordered, best first) and
|
|
3294
|
+
* loops over THAT set. Providers known not to serve the v2 `getTransactions`
|
|
3295
|
+
* shape — flagged `servesGetTransactions: false` in config (Chainstack/Orbs
|
|
3296
|
+
* testnet, which pass the `getMasterchainInfo` health probe but 403 on
|
|
3297
|
+
* transaction reads) — are excluded UP FRONT. They are never called and never
|
|
3298
|
+
* `reportError`-ed here, so their global health stays intact and the fast
|
|
3299
|
+
* get-method path keeps using them (a wasted 403 would otherwise evict them).
|
|
3300
|
+
*
|
|
3301
|
+
* Semantics (per capable candidate, in score order):
|
|
3302
|
+
* 1. Acquire a rate-limit token for THAT provider, bind a short-lived
|
|
3303
|
+
* `TonClient` to its endpoint, and call `getTransactions`.
|
|
3304
|
+
* 2. On success → `reportSuccess(provider.id)` and return.
|
|
3305
|
+
* 3. On a GENUINE error → `reportError(error, provider.id)` (marks THAT
|
|
3306
|
+
* provider success:false + clears the selection cache) and try the next
|
|
3307
|
+
* capable candidate.
|
|
3308
|
+
* 4. When every capable candidate has been tried, re-throw the last error so
|
|
3309
|
+
* the caller's retry/dead-letter logic still triggers.
|
|
3310
|
+
* 5. If there is NO capable provider at all, throw a clear error.
|
|
3311
|
+
*
|
|
3312
|
+
* Returns the same `Transaction[]` `TonClient.getTransactions` returns, so a
|
|
3313
|
+
* consumer can swap `client.getTransactions(addr, opts)` for
|
|
3314
|
+
* `adapter.getTransactions(addr, opts)` with no shape change.
|
|
3315
|
+
*/
|
|
3316
|
+
async getTransactions(address, opts = {}, timeoutMs = 15e3) {
|
|
3317
|
+
const network = this.manager.getNetwork();
|
|
3318
|
+
if (!network) {
|
|
3319
|
+
throw new Error("ProviderManager not initialized");
|
|
3320
|
+
}
|
|
3321
|
+
const addr = typeof address === "string" ? core.Address.parse(address) : address;
|
|
3322
|
+
const reqOpts = { limit: opts.limit ?? 20, ...opts };
|
|
3323
|
+
const candidates = this.manager.getTransactionCapableProviders();
|
|
3324
|
+
if (candidates.length === 0) {
|
|
3325
|
+
throw new Error(
|
|
3326
|
+
`getTransactions: no transaction-capable provider for ${network}`
|
|
3327
|
+
);
|
|
3328
|
+
}
|
|
3329
|
+
const rateLimiter = this.manager.getRateLimiter();
|
|
3330
|
+
let lastError;
|
|
3331
|
+
for (const provider of candidates) {
|
|
3332
|
+
if (rateLimiter) {
|
|
3333
|
+
await rateLimiter.acquire(provider.id, timeoutMs);
|
|
3334
|
+
}
|
|
3335
|
+
const endpoint = normalizeV2Endpoint(provider.endpointV2, provider);
|
|
3336
|
+
const client = new ton.TonClient({ endpoint, apiKey: provider.apiKey });
|
|
3337
|
+
try {
|
|
3338
|
+
const result = await withTimeout(
|
|
3339
|
+
client.getTransactions(addr, reqOpts),
|
|
3340
|
+
timeoutMs,
|
|
3341
|
+
`getTransactions(${provider.id})`
|
|
3342
|
+
);
|
|
3343
|
+
this.manager.reportSuccess(provider.id);
|
|
3344
|
+
return result;
|
|
3345
|
+
} catch (error) {
|
|
3346
|
+
lastError = error;
|
|
3347
|
+
this.logger.warn(
|
|
3348
|
+
`getTransactions failed on ${provider.id}, failing over`,
|
|
3349
|
+
{ error: error?.message || String(error) }
|
|
3350
|
+
);
|
|
3351
|
+
this.manager.reportError(error, provider.id);
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
throw lastError || new Error(`getTransactions: all transaction-capable providers failed for ${network}`);
|
|
3355
|
+
}
|
|
3356
|
+
// ========================================================================
|
|
3252
3357
|
// Direct REST API Methods
|
|
3253
3358
|
// ========================================================================
|
|
3254
3359
|
/**
|