ton-provider-system 0.3.0 → 0.4.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 +85 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +85 -3
- package/dist/index.js.map +1 -1
- package/package.json +15 -13
- package/rpc.json +2 -2
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
|
|
@@ -324,7 +325,13 @@ var DEFAULT_PROVIDERS = {
|
|
|
324
325
|
},
|
|
325
326
|
rps: 1,
|
|
326
327
|
// Without API key
|
|
327
|
-
|
|
328
|
+
// Preferred on testnet: Toncenter serves the full v2 surface incl.
|
|
329
|
+
// getTransactions (curl-proven 200). Orbs only proxies liteserver
|
|
330
|
+
// get-methods/state and 403s on getTransactions, so it must NOT be the
|
|
331
|
+
// primary testnet provider (it stays a fallback for get-method reads).
|
|
332
|
+
// Selection is score-based and priority is the lever (lower = better),
|
|
333
|
+
// so this gives Toncenter the testnet edge over Orbs (priority 90).
|
|
334
|
+
priority: 10,
|
|
328
335
|
enabled: true,
|
|
329
336
|
description: "Official TON Center public endpoint"
|
|
330
337
|
},
|
|
@@ -336,7 +343,9 @@ var DEFAULT_PROVIDERS = {
|
|
|
336
343
|
v2: "https://ton-testnet.orbs.network/api/v2"
|
|
337
344
|
},
|
|
338
345
|
rps: 10,
|
|
339
|
-
priority:
|
|
346
|
+
// Demoted below toncenter_testnet (priority 10): Orbs is the decentralised
|
|
347
|
+
// fallback for non-transaction (get-method/state) testnet reads only.
|
|
348
|
+
priority: 90,
|
|
340
349
|
enabled: true,
|
|
341
350
|
isDynamic: true,
|
|
342
351
|
description: "Decentralized gateway - no API key needed"
|
|
@@ -373,7 +382,12 @@ function createDefaultConfig() {
|
|
|
373
382
|
version: "1.0",
|
|
374
383
|
providers: { ...DEFAULT_PROVIDERS },
|
|
375
384
|
defaults: {
|
|
376
|
-
|
|
385
|
+
// Testnet: Toncenter first (transactions-capable), Orbs as fallback.
|
|
386
|
+
// This default order only governs the no-healthy-providers fallback
|
|
387
|
+
// path; the primary, score-based selection is driven by priority
|
|
388
|
+
// (see toncenter_testnet/orbs_testnet above). Mainnet order is left
|
|
389
|
+
// unchanged (Orbs stays primary there — no regression).
|
|
390
|
+
testnet: ["toncenter_testnet", "orbs_testnet"],
|
|
377
391
|
mainnet: ["orbs_mainnet", "toncenter_mainnet"]
|
|
378
392
|
}
|
|
379
393
|
};
|
|
@@ -3236,6 +3250,74 @@ var NodeAdapter = class {
|
|
|
3236
3250
|
};
|
|
3237
3251
|
}
|
|
3238
3252
|
// ========================================================================
|
|
3253
|
+
// Failover-aware high-level reads
|
|
3254
|
+
// ========================================================================
|
|
3255
|
+
/**
|
|
3256
|
+
* Get account transactions with provider failover.
|
|
3257
|
+
*
|
|
3258
|
+
* Unlike `getClient().getTransactions(...)`, this loops across the network's
|
|
3259
|
+
* providers: a provider that passes the `getMasterchainInfo` health probe but
|
|
3260
|
+
* fails the v2 `getTransactions` call (e.g. Chainstack/Orbs testnet, which
|
|
3261
|
+
* 403 on transaction reads) is no longer able to permanently break this path.
|
|
3262
|
+
*
|
|
3263
|
+
* Semantics:
|
|
3264
|
+
* 1. Pick the current best provider (the selector's scored top).
|
|
3265
|
+
* 2. Acquire a rate-limit token for THAT provider, bind a short-lived
|
|
3266
|
+
* `TonClient` to its endpoint, and call `getTransactions`.
|
|
3267
|
+
* 3. On success → `reportSuccess()` and return.
|
|
3268
|
+
* 4. On error → `reportError()` (marks the provider success:false, scoring 0
|
|
3269
|
+
* within its cooldown, and clears the selection cache) so the next pick is
|
|
3270
|
+
* a DIFFERENT, still-eligible provider, then retry.
|
|
3271
|
+
* 5. When every candidate has been tried, re-throw the last error so the
|
|
3272
|
+
* caller's retry/dead-letter logic still triggers — but only after a
|
|
3273
|
+
* genuine failover across all providers.
|
|
3274
|
+
*
|
|
3275
|
+
* Returns the same `Transaction[]` `TonClient.getTransactions` returns, so a
|
|
3276
|
+
* consumer can swap `client.getTransactions(addr, opts)` for
|
|
3277
|
+
* `adapter.getTransactions(addr, opts)` with no shape change.
|
|
3278
|
+
*/
|
|
3279
|
+
async getTransactions(address, opts = {}, timeoutMs = 15e3) {
|
|
3280
|
+
const network = this.manager.getNetwork();
|
|
3281
|
+
if (!network) {
|
|
3282
|
+
throw new Error("ProviderManager not initialized");
|
|
3283
|
+
}
|
|
3284
|
+
const addr = typeof address === "string" ? core.Address.parse(address) : address;
|
|
3285
|
+
const reqOpts = { limit: opts.limit ?? 20, ...opts };
|
|
3286
|
+
const maxAttempts = Math.max(1, this.manager.getProviders().length);
|
|
3287
|
+
const rateLimiter = this.manager.getRateLimiter();
|
|
3288
|
+
const tried = /* @__PURE__ */ new Set();
|
|
3289
|
+
let lastError;
|
|
3290
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
3291
|
+
const provider = this.manager.getActiveProvider();
|
|
3292
|
+
if (!provider) break;
|
|
3293
|
+
if (tried.has(provider.id)) break;
|
|
3294
|
+
tried.add(provider.id);
|
|
3295
|
+
if (rateLimiter) {
|
|
3296
|
+
await rateLimiter.acquire(provider.id, timeoutMs);
|
|
3297
|
+
}
|
|
3298
|
+
const endpoint = await this.manager.getEndpoint();
|
|
3299
|
+
const apiKey = this.manager.getActiveProvider()?.apiKey;
|
|
3300
|
+
const client = new ton.TonClient({ endpoint, apiKey });
|
|
3301
|
+
try {
|
|
3302
|
+
const result = await withTimeout(
|
|
3303
|
+
client.getTransactions(addr, reqOpts),
|
|
3304
|
+
timeoutMs,
|
|
3305
|
+
`getTransactions(${provider.id})`
|
|
3306
|
+
);
|
|
3307
|
+
this.manager.reportSuccess();
|
|
3308
|
+
return result;
|
|
3309
|
+
} catch (error) {
|
|
3310
|
+
lastError = error;
|
|
3311
|
+
this.logger.warn(
|
|
3312
|
+
`getTransactions failed on ${provider.id}, failing over`,
|
|
3313
|
+
{ error: error?.message || String(error) }
|
|
3314
|
+
);
|
|
3315
|
+
this.manager.reportError(error);
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
throw lastError || new Error(`getTransactions: no available provider for ${network}`);
|
|
3319
|
+
}
|
|
3320
|
+
// ========================================================================
|
|
3239
3321
|
// Direct REST API Methods
|
|
3240
3322
|
// ========================================================================
|
|
3241
3323
|
/**
|