@stablechain/sdk 1.0.7 → 1.0.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/README.md +28 -15
- package/dist/index.cjs +33 -20
- package/dist/index.d.cts +32 -6
- package/dist/index.d.ts +32 -6
- package/dist/index.js +33 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -455,44 +455,57 @@ Nearly all of the wait is **source-chain finality**: the DVNs securing the pathw
|
|
|
455
455
|
not attest until the send transaction is buried under `confirmations` source blocks.
|
|
456
456
|
Destination execution is a few blocks on top.
|
|
457
457
|
|
|
458
|
-
|
|
458
|
+
`estimateBridgeTime` reports that breakdown:
|
|
459
459
|
|
|
460
460
|
| Field | Meaning |
|
|
461
461
|
|-------------------|--------------------------------------------------------------------------------------------------|
|
|
462
|
-
| `seconds` |
|
|
463
|
-
| `source` | `"
|
|
462
|
+
| `seconds` | The estimate — display this |
|
|
463
|
+
| `source` | `"formula"`, `"floor"`, or `"observed"` — which input produced `seconds` |
|
|
464
464
|
| `observedSeconds` | Median delivery time of recent messages on this exact pathway, from LayerZero Scan |
|
|
465
465
|
| `formulaSeconds` | LayerZero's documented estimate: `srcBlockTime × confirmations + dstBlockTime × (2 + dvnCount)` |
|
|
466
466
|
| `confirmations` | Source blocks the DVNs wait for, read live from the pathway's ULN config |
|
|
467
467
|
| `dvnCount` | DVNs verifying the pathway |
|
|
468
468
|
|
|
469
|
-
`
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
469
|
+
`seconds` comes from the formula — the pathway's live ULN config is what the DVNs are
|
|
470
|
+
actually bound by, so a config change is reflected the moment it lands. On every pathway
|
|
471
|
+
that is purely confirmation-bound it agrees with both usdt0.to's own estimate and the
|
|
472
|
+
delivery times LayerZero Scan reports to well under a percent.
|
|
473
|
+
|
|
474
|
+
Some source chains carry a floor. DVN attestation and destination execution sit outside the
|
|
475
|
+
formula, and on Ethereum and Arbitrum the DVNs additionally hold until the send finalizes on
|
|
476
|
+
the beacon chain. Where confirmations are high that overhead vanishes into the rounding;
|
|
477
|
+
where they are low it dominates — Arbitrum's 60 confirmations compute to ~19 s against a real
|
|
478
|
+
~18 min. Those chains are floored at a measured minimum, and `source` reports `"floor"`.
|
|
479
|
+
|
|
480
|
+
`observedSeconds` is fetched alongside and reported for comparison, but does not drive
|
|
481
|
+
`seconds`: a 50-message window can reach back months, so on a pathway that has been
|
|
482
|
+
reconfigured or has gone quiet it answers from a config that no longer exists.
|
|
473
483
|
|
|
474
484
|
Pathway configs and observed medians are cached for 5 minutes; call
|
|
475
485
|
`clearBridgeEstimateCache()` to force a refetch.
|
|
476
486
|
|
|
477
|
-
Roughly what to expect on mainnet,
|
|
487
|
+
Roughly what to expect on mainnet, from configs read 2026-08-27:
|
|
478
488
|
|
|
479
489
|
| Pathway | Confirmations | Typical delivery |
|
|
480
490
|
|---------------------|---------------|------------------|
|
|
481
|
-
| Polygon → Stable | 32 | ~1 min
|
|
482
|
-
| Bera → Stable | 60 | ~2 min
|
|
483
|
-
|
|
|
484
|
-
| Flare → Stable | 500 | ~11 min |
|
|
485
|
-
| Optimism → Stable | 1000 | ~15 min |
|
|
486
|
-
| Ethereum → Stable | 65 | ~17 min |
|
|
491
|
+
| Polygon → Stable | 32 | ~1 min ᶠ |
|
|
492
|
+
| Bera → Stable | 60 | ~2 min ᶠ |
|
|
493
|
+
| Flare → Stable | 500 | ~10 min ᶠ |
|
|
487
494
|
| Sei → Stable | 2000 | ~17 min |
|
|
488
|
-
|
|
|
495
|
+
| Ethereum → Stable | 65 | ~19.5 min ᶠ |
|
|
496
|
+
| Arbitrum → Stable | 60 | ~22.5 min ᶠ |
|
|
497
|
+
| Unichain → Stable | 1600 | ~27 min |
|
|
489
498
|
| Plasma → Stable | 1800 | ~30 min |
|
|
499
|
+
| Optimism → Stable | 1000 | ~33 min |
|
|
490
500
|
| Stable → any | 3600 | ~42 min |
|
|
491
501
|
| Rootstock → Stable | 120 | ~62 min |
|
|
492
502
|
| MegaETH → Stable | 5400 | ~90 min |
|
|
493
503
|
| X Layer → Stable | 9000 | ~2.5 h |
|
|
494
504
|
| HyperEVM → Stable | 43200 | ~12 h |
|
|
495
505
|
|
|
506
|
+
ᶠ Floored at the source chain's measured minimum, because its confirmation count is not the
|
|
507
|
+
whole wait — Ethereum and Arbitrum would otherwise compute to ~13 min and ~19 s.
|
|
508
|
+
|
|
496
509
|
---
|
|
497
510
|
|
|
498
511
|
### `trackBridge(srcTxHash)` → `BridgeStatus`
|
package/dist/index.cjs
CHANGED
|
@@ -1751,7 +1751,7 @@ var XAUT0_DEPLOYMENTS = {
|
|
|
1751
1751
|
["bsc" /* BSC */]: { address: "0x21cAef8A43163Eea865baeE23b9C2E327696A3bf", decimals: 6, oftAdapter: "0x53C3A64c8942288e12813C1F8457Db45980BcfC2", approvalRequired: false }
|
|
1752
1752
|
};
|
|
1753
1753
|
var USDT0_LOCKBOX_CHAINS = /* @__PURE__ */ new Set(["ethereum" /* Ethereum */, "sepolia" /* Sepolia */]);
|
|
1754
|
-
function bridgeChain(chain, lzEid, blockTimeSec, usdt0Adapter) {
|
|
1754
|
+
function bridgeChain(chain, lzEid, blockTimeSec, usdt0Adapter, minDeliverySec) {
|
|
1755
1755
|
const base = C[chain];
|
|
1756
1756
|
const tokens = {};
|
|
1757
1757
|
if (usdt0Adapter) {
|
|
@@ -1764,7 +1764,7 @@ function bridgeChain(chain, lzEid, blockTimeSec, usdt0Adapter) {
|
|
|
1764
1764
|
}
|
|
1765
1765
|
const xaut0 = XAUT0_DEPLOYMENTS[chain];
|
|
1766
1766
|
if (xaut0) tokens.xaut0 = xaut0;
|
|
1767
|
-
return { ...base, lzEid, blockTimeSec, tokens, oftAdapter: usdt0Adapter };
|
|
1767
|
+
return { ...base, lzEid, blockTimeSec, minDeliverySec, tokens, oftAdapter: usdt0Adapter };
|
|
1768
1768
|
}
|
|
1769
1769
|
var BRIDGE_CHAIN_CONFIGS = {
|
|
1770
1770
|
// ─── Testnet ───────────────────────────────────────────────────────────────
|
|
@@ -1772,18 +1772,18 @@ var BRIDGE_CHAIN_CONFIGS = {
|
|
|
1772
1772
|
["stable-testnet" /* StableTestnet */]: bridgeChain("stable-testnet" /* StableTestnet */, 40374, 0.7, "0x779Ded0c9e1022225f8E0630b35a9b54bE713736"),
|
|
1773
1773
|
// ─── Mainnet ──────────────────────────────────────────────────────────────
|
|
1774
1774
|
["stable" /* Stable */]: bridgeChain("stable" /* Stable */, 30396, 0.7, "0xedaba024be4d87974d5aB11C6Dd586963CcCB027"),
|
|
1775
|
-
["ethereum" /* Ethereum */]: bridgeChain("ethereum" /* Ethereum */, 30101, 12, "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee"),
|
|
1776
|
-
["arbitrum" /* Arbitrum */]: bridgeChain("arbitrum" /* Arbitrum */, 30110, 0.25, "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92"),
|
|
1775
|
+
["ethereum" /* Ethereum */]: bridgeChain("ethereum" /* Ethereum */, 30101, 12, "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee", 1170),
|
|
1776
|
+
["arbitrum" /* Arbitrum */]: bridgeChain("arbitrum" /* Arbitrum */, 30110, 0.25, "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92", 1350),
|
|
1777
1777
|
["ink" /* Ink */]: bridgeChain("ink" /* Ink */, 30339, 1, "0x1cB6De532588fCA4a21B7209DE7C456AF8434A65"),
|
|
1778
|
-
["bera" /* Bera */]: bridgeChain("bera" /* Bera */, 30362, 2, "0x3Dc96399109df5ceb2C226664A086140bD0379cB"),
|
|
1778
|
+
["bera" /* Bera */]: bridgeChain("bera" /* Bera */, 30362, 2, "0x3Dc96399109df5ceb2C226664A086140bD0379cB", 135),
|
|
1779
1779
|
["megaeth" /* MegaETH */]: bridgeChain("megaeth" /* MegaETH */, 30398, 1, "0x9151434b16b9763660705744891fa906f660ecc5"),
|
|
1780
1780
|
["hyperevm" /* HyperEVM */]: bridgeChain("hyperevm" /* HyperEVM */, 30367, 1, "0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98"),
|
|
1781
|
-
["polygon" /* Polygon */]: bridgeChain("polygon" /* Polygon */, 30109, 1.5, "0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13"),
|
|
1781
|
+
["polygon" /* Polygon */]: bridgeChain("polygon" /* Polygon */, 30109, 1.5, "0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13", 70),
|
|
1782
1782
|
["plasma" /* Plasma */]: bridgeChain("plasma" /* Plasma */, 30383, 1, "0x02ca37966753bDdDf11216B73B16C1dE756A7CF9"),
|
|
1783
1783
|
["optimism" /* Optimism */]: bridgeChain("optimism" /* Optimism */, 30111, 2, "0xF03b4d9AC1D5d1E7c4cEf54C2A313b9fe051A0aD"),
|
|
1784
1784
|
["unichain" /* Unichain */]: bridgeChain("unichain" /* Unichain */, 30320, 1, "0xc07bE8994D035631c36fb4a89C918CeFB2f03EC3"),
|
|
1785
1785
|
["sei" /* Sei */]: bridgeChain("sei" /* Sei */, 30280, 0.5, "0x56Fe74A2e3b484b921c447357203431a3485CC60"),
|
|
1786
|
-
["flare" /* Flare */]: bridgeChain("flare" /* Flare */, 30295, 1.1, "0x567287d2A9829215a37e3B88843d32f9221E7588"),
|
|
1786
|
+
["flare" /* Flare */]: bridgeChain("flare" /* Flare */, 30295, 1.1, "0x567287d2A9829215a37e3B88843d32f9221E7588", 600),
|
|
1787
1787
|
["xlayer" /* XLayer */]: bridgeChain("xlayer" /* XLayer */, 30274, 1, "0x94BCCa6bdfd6A61817Ab0E960bFedE4984505554"),
|
|
1788
1788
|
["rootstock" /* Rootstock */]: bridgeChain("rootstock" /* Rootstock */, 30333, 31, "0x1a594d5d5d1c426281C1064B07f23F57B2716B61"),
|
|
1789
1789
|
// XAUt0 only — BSC has no USDT0 deployment. Block time measured 2026-08-20.
|
|
@@ -1964,6 +1964,14 @@ function median(values) {
|
|
|
1964
1964
|
const mid = Math.floor(sorted.length / 2);
|
|
1965
1965
|
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
1966
1966
|
}
|
|
1967
|
+
function resolveDeliverySeconds(formulaSeconds, observedSeconds, minDeliverySec) {
|
|
1968
|
+
const base = _nullishCoalesce(formulaSeconds, () => ( observedSeconds));
|
|
1969
|
+
if (base === void 0) return void 0;
|
|
1970
|
+
if (minDeliverySec !== void 0 && minDeliverySec > base) {
|
|
1971
|
+
return { seconds: minDeliverySec, source: "floor" };
|
|
1972
|
+
}
|
|
1973
|
+
return { seconds: base, source: formulaSeconds !== void 0 ? "formula" : "observed" };
|
|
1974
|
+
}
|
|
1967
1975
|
var WORKER_EXECUTOR = 1;
|
|
1968
1976
|
var OPTION_LZRECEIVE = 1;
|
|
1969
1977
|
var OPTION_NATIVE_DROP = 2;
|
|
@@ -2383,16 +2391,22 @@ var LayerZeroService = class {
|
|
|
2383
2391
|
/**
|
|
2384
2392
|
* Estimate how long a USDT0 bridge will take, end to end.
|
|
2385
2393
|
*
|
|
2386
|
-
*
|
|
2387
|
-
*
|
|
2388
|
-
*
|
|
2389
|
-
*
|
|
2390
|
-
*
|
|
2394
|
+
* The number comes from the pathway's live ULN config:
|
|
2395
|
+
* `srcBlockTime × confirmations + dstBlockTime × (2 + dvnCount)`, floored at the
|
|
2396
|
+
* source chain's {@link BridgeChainConfig.minDeliverySec} where the confirmation
|
|
2397
|
+
* count is not the whole wait. This is what the DVNs are actually bound by, so it
|
|
2398
|
+
* tracks a config change the moment it lands — and on every pathway that is purely
|
|
2399
|
+
* confirmation-bound it agrees with both usdt0.to's own estimate and the delivery
|
|
2400
|
+
* times Scan reports to well under a percent.
|
|
2391
2401
|
*
|
|
2392
|
-
*
|
|
2393
|
-
*
|
|
2394
|
-
*
|
|
2395
|
-
*
|
|
2402
|
+
* The observed median of recent deliveries on this exact pathway is fetched too
|
|
2403
|
+
* and reported as {@link BridgeTimeEstimate.observedSeconds}, but it no longer
|
|
2404
|
+
* drives `seconds`. History lags the config: after Optimism→Stable was raised to
|
|
2405
|
+
* 1000 confirmations, a 50-message window still reaching back 261 days put the
|
|
2406
|
+
* median at ~15min against a real ~33min, and pathways quiet for months (Unichain,
|
|
2407
|
+
* XAUt0 from Arbitrum) were answering from configs that no longer exist. It stays
|
|
2408
|
+
* the fallback for the case the formula cannot be computed at all — an RPC that
|
|
2409
|
+
* will not serve the ULN read.
|
|
2396
2410
|
*/
|
|
2397
2411
|
async estimateBridgeTime({
|
|
2398
2412
|
fromChain,
|
|
@@ -2423,16 +2437,15 @@ var LayerZeroService = class {
|
|
|
2423
2437
|
);
|
|
2424
2438
|
formulaSeconds = Number.isFinite(computed) ? computed : void 0;
|
|
2425
2439
|
}
|
|
2426
|
-
const
|
|
2427
|
-
if (
|
|
2440
|
+
const resolved = resolveDeliverySeconds(formulaSeconds, observedSeconds, src.minDeliverySec);
|
|
2441
|
+
if (!resolved) {
|
|
2428
2442
|
throw new (0, _chunkQQ26UI3Fcjs.StableQuoteError)({
|
|
2429
2443
|
provider: "layerzero",
|
|
2430
2444
|
shortMessage: `estimateBridgeTime: no pathway data for ${fromChain}\u2192${toChain}`
|
|
2431
2445
|
});
|
|
2432
2446
|
}
|
|
2433
2447
|
return {
|
|
2434
|
-
|
|
2435
|
-
source: observedSeconds !== void 0 ? "observed" : "formula",
|
|
2448
|
+
...resolved,
|
|
2436
2449
|
observedSeconds,
|
|
2437
2450
|
formulaSeconds,
|
|
2438
2451
|
confirmations: Number.isFinite(_optionalChain([uln, 'optionalAccess', _57 => _57.confirmations])) ? _optionalChain([uln, 'optionalAccess', _58 => _58.confirmations]) : void 0,
|
package/dist/index.d.cts
CHANGED
|
@@ -222,17 +222,23 @@ interface BridgeGasEstimate {
|
|
|
222
222
|
interface BridgeTimeEstimate {
|
|
223
223
|
/** Best available estimate, in seconds — prefer this for display */
|
|
224
224
|
seconds: number;
|
|
225
|
-
/** Which input produced `seconds` — see {@link BridgeTimeEstimate.observedSeconds} */
|
|
226
|
-
source: "observed" | "formula";
|
|
227
225
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
226
|
+
* Which input produced `seconds`. `"formula"` normally; `"floor"` when the
|
|
227
|
+
* source chain's measured minimum exceeded it (Ethereum, Arbitrum, Polygon,
|
|
228
|
+
* Bera, Flare); `"observed"` only when the pathway's ULN config could not be read.
|
|
229
|
+
*/
|
|
230
|
+
source: "formula" | "floor" | "observed";
|
|
231
|
+
/**
|
|
232
|
+
* Median delivery time of recent delivered messages on this exact pathway, from
|
|
233
|
+
* LayerZero Scan. Reported for comparison but no longer preferred: a 50-message
|
|
234
|
+
* window can reach back months, so it answers from a ULN config the pathway has
|
|
235
|
+
* since moved off.
|
|
231
236
|
*/
|
|
232
237
|
observedSeconds?: number;
|
|
233
238
|
/**
|
|
234
239
|
* LayerZero's documented estimate:
|
|
235
|
-
* `srcBlockTime × confirmations + dstBlockTime × (2 + dvnCount)`.
|
|
240
|
+
* `srcBlockTime × confirmations + dstBlockTime × (2 + dvnCount)`. What `seconds`
|
|
241
|
+
* reports unless the source chain's measured floor is higher.
|
|
236
242
|
*/
|
|
237
243
|
formulaSeconds?: number;
|
|
238
244
|
/** Source-chain block confirmations the DVNs wait for before attesting */
|
|
@@ -743,6 +749,26 @@ interface BridgeChainConfig extends ChainConfig {
|
|
|
743
749
|
* requirement into a wall-clock estimate. Measured from mainnet, 2026-07-30.
|
|
744
750
|
*/
|
|
745
751
|
blockTimeSec?: number;
|
|
752
|
+
/**
|
|
753
|
+
* Floor on delivery time, in seconds, for sends *from* this chain — set only
|
|
754
|
+
* where the confirmation count is demonstrably not the whole wait.
|
|
755
|
+
*
|
|
756
|
+
* Two things sit outside the formula: DVN attestation and destination execution,
|
|
757
|
+
* a roughly fixed overhead, and on Ethereum and Arbitrum a hold until the send
|
|
758
|
+
* finalizes on the beacon chain. Where confirmations are high the overhead is lost
|
|
759
|
+
* in the rounding — Optimism's 1000 and X Layer's 9000 both land within 0.5% of
|
|
760
|
+
* observed. Where they are low it dominates: Arbitrum's 60 confirmations compute
|
|
761
|
+
* to ~19s against a real ~18min, Ethereum's 65 to ~13min against ~17min, Polygon's
|
|
762
|
+
* 32 to ~52s against a real ~70s, Flare's 500 to ~9min against a real ~10min.
|
|
763
|
+
*
|
|
764
|
+
* Each figure is taken from deliveries LayerZero Scan held on 2026-08-27, no older
|
|
765
|
+
* than 45 days — the ceiling of that spread for the two finality-bound chains, so
|
|
766
|
+
* the estimate errs long, and the median for the rest. Flare's is a median across
|
|
767
|
+
* its destinations rather than one pathway's, since the hub pathway alone had only
|
|
768
|
+
* six recent sends to go on; those settled at ~9m30s and the busier pathways to
|
|
769
|
+
* Ethereum, Arbitrum, Plasma, Polygon and Optimism between ~9m20s and ~10m10s.
|
|
770
|
+
*/
|
|
771
|
+
minDeliverySec?: number;
|
|
746
772
|
}
|
|
747
773
|
declare const BRIDGE_CHAIN_CONFIGS: Partial<Record<Chain, BridgeChainConfig>>;
|
|
748
774
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -222,17 +222,23 @@ interface BridgeGasEstimate {
|
|
|
222
222
|
interface BridgeTimeEstimate {
|
|
223
223
|
/** Best available estimate, in seconds — prefer this for display */
|
|
224
224
|
seconds: number;
|
|
225
|
-
/** Which input produced `seconds` — see {@link BridgeTimeEstimate.observedSeconds} */
|
|
226
|
-
source: "observed" | "formula";
|
|
227
225
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
226
|
+
* Which input produced `seconds`. `"formula"` normally; `"floor"` when the
|
|
227
|
+
* source chain's measured minimum exceeded it (Ethereum, Arbitrum, Polygon,
|
|
228
|
+
* Bera, Flare); `"observed"` only when the pathway's ULN config could not be read.
|
|
229
|
+
*/
|
|
230
|
+
source: "formula" | "floor" | "observed";
|
|
231
|
+
/**
|
|
232
|
+
* Median delivery time of recent delivered messages on this exact pathway, from
|
|
233
|
+
* LayerZero Scan. Reported for comparison but no longer preferred: a 50-message
|
|
234
|
+
* window can reach back months, so it answers from a ULN config the pathway has
|
|
235
|
+
* since moved off.
|
|
231
236
|
*/
|
|
232
237
|
observedSeconds?: number;
|
|
233
238
|
/**
|
|
234
239
|
* LayerZero's documented estimate:
|
|
235
|
-
* `srcBlockTime × confirmations + dstBlockTime × (2 + dvnCount)`.
|
|
240
|
+
* `srcBlockTime × confirmations + dstBlockTime × (2 + dvnCount)`. What `seconds`
|
|
241
|
+
* reports unless the source chain's measured floor is higher.
|
|
236
242
|
*/
|
|
237
243
|
formulaSeconds?: number;
|
|
238
244
|
/** Source-chain block confirmations the DVNs wait for before attesting */
|
|
@@ -743,6 +749,26 @@ interface BridgeChainConfig extends ChainConfig {
|
|
|
743
749
|
* requirement into a wall-clock estimate. Measured from mainnet, 2026-07-30.
|
|
744
750
|
*/
|
|
745
751
|
blockTimeSec?: number;
|
|
752
|
+
/**
|
|
753
|
+
* Floor on delivery time, in seconds, for sends *from* this chain — set only
|
|
754
|
+
* where the confirmation count is demonstrably not the whole wait.
|
|
755
|
+
*
|
|
756
|
+
* Two things sit outside the formula: DVN attestation and destination execution,
|
|
757
|
+
* a roughly fixed overhead, and on Ethereum and Arbitrum a hold until the send
|
|
758
|
+
* finalizes on the beacon chain. Where confirmations are high the overhead is lost
|
|
759
|
+
* in the rounding — Optimism's 1000 and X Layer's 9000 both land within 0.5% of
|
|
760
|
+
* observed. Where they are low it dominates: Arbitrum's 60 confirmations compute
|
|
761
|
+
* to ~19s against a real ~18min, Ethereum's 65 to ~13min against ~17min, Polygon's
|
|
762
|
+
* 32 to ~52s against a real ~70s, Flare's 500 to ~9min against a real ~10min.
|
|
763
|
+
*
|
|
764
|
+
* Each figure is taken from deliveries LayerZero Scan held on 2026-08-27, no older
|
|
765
|
+
* than 45 days — the ceiling of that spread for the two finality-bound chains, so
|
|
766
|
+
* the estimate errs long, and the median for the rest. Flare's is a median across
|
|
767
|
+
* its destinations rather than one pathway's, since the hub pathway alone had only
|
|
768
|
+
* six recent sends to go on; those settled at ~9m30s and the busier pathways to
|
|
769
|
+
* Ethereum, Arbitrum, Plasma, Polygon and Optimism between ~9m20s and ~10m10s.
|
|
770
|
+
*/
|
|
771
|
+
minDeliverySec?: number;
|
|
746
772
|
}
|
|
747
773
|
declare const BRIDGE_CHAIN_CONFIGS: Partial<Record<Chain, BridgeChainConfig>>;
|
|
748
774
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1751,7 +1751,7 @@ var XAUT0_DEPLOYMENTS = {
|
|
|
1751
1751
|
["bsc" /* BSC */]: { address: "0x21cAef8A43163Eea865baeE23b9C2E327696A3bf", decimals: 6, oftAdapter: "0x53C3A64c8942288e12813C1F8457Db45980BcfC2", approvalRequired: false }
|
|
1752
1752
|
};
|
|
1753
1753
|
var USDT0_LOCKBOX_CHAINS = /* @__PURE__ */ new Set(["ethereum" /* Ethereum */, "sepolia" /* Sepolia */]);
|
|
1754
|
-
function bridgeChain(chain, lzEid, blockTimeSec, usdt0Adapter) {
|
|
1754
|
+
function bridgeChain(chain, lzEid, blockTimeSec, usdt0Adapter, minDeliverySec) {
|
|
1755
1755
|
const base = C[chain];
|
|
1756
1756
|
const tokens = {};
|
|
1757
1757
|
if (usdt0Adapter) {
|
|
@@ -1764,7 +1764,7 @@ function bridgeChain(chain, lzEid, blockTimeSec, usdt0Adapter) {
|
|
|
1764
1764
|
}
|
|
1765
1765
|
const xaut0 = XAUT0_DEPLOYMENTS[chain];
|
|
1766
1766
|
if (xaut0) tokens.xaut0 = xaut0;
|
|
1767
|
-
return { ...base, lzEid, blockTimeSec, tokens, oftAdapter: usdt0Adapter };
|
|
1767
|
+
return { ...base, lzEid, blockTimeSec, minDeliverySec, tokens, oftAdapter: usdt0Adapter };
|
|
1768
1768
|
}
|
|
1769
1769
|
var BRIDGE_CHAIN_CONFIGS = {
|
|
1770
1770
|
// ─── Testnet ───────────────────────────────────────────────────────────────
|
|
@@ -1772,18 +1772,18 @@ var BRIDGE_CHAIN_CONFIGS = {
|
|
|
1772
1772
|
["stable-testnet" /* StableTestnet */]: bridgeChain("stable-testnet" /* StableTestnet */, 40374, 0.7, "0x779Ded0c9e1022225f8E0630b35a9b54bE713736"),
|
|
1773
1773
|
// ─── Mainnet ──────────────────────────────────────────────────────────────
|
|
1774
1774
|
["stable" /* Stable */]: bridgeChain("stable" /* Stable */, 30396, 0.7, "0xedaba024be4d87974d5aB11C6Dd586963CcCB027"),
|
|
1775
|
-
["ethereum" /* Ethereum */]: bridgeChain("ethereum" /* Ethereum */, 30101, 12, "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee"),
|
|
1776
|
-
["arbitrum" /* Arbitrum */]: bridgeChain("arbitrum" /* Arbitrum */, 30110, 0.25, "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92"),
|
|
1775
|
+
["ethereum" /* Ethereum */]: bridgeChain("ethereum" /* Ethereum */, 30101, 12, "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee", 1170),
|
|
1776
|
+
["arbitrum" /* Arbitrum */]: bridgeChain("arbitrum" /* Arbitrum */, 30110, 0.25, "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92", 1350),
|
|
1777
1777
|
["ink" /* Ink */]: bridgeChain("ink" /* Ink */, 30339, 1, "0x1cB6De532588fCA4a21B7209DE7C456AF8434A65"),
|
|
1778
|
-
["bera" /* Bera */]: bridgeChain("bera" /* Bera */, 30362, 2, "0x3Dc96399109df5ceb2C226664A086140bD0379cB"),
|
|
1778
|
+
["bera" /* Bera */]: bridgeChain("bera" /* Bera */, 30362, 2, "0x3Dc96399109df5ceb2C226664A086140bD0379cB", 135),
|
|
1779
1779
|
["megaeth" /* MegaETH */]: bridgeChain("megaeth" /* MegaETH */, 30398, 1, "0x9151434b16b9763660705744891fa906f660ecc5"),
|
|
1780
1780
|
["hyperevm" /* HyperEVM */]: bridgeChain("hyperevm" /* HyperEVM */, 30367, 1, "0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98"),
|
|
1781
|
-
["polygon" /* Polygon */]: bridgeChain("polygon" /* Polygon */, 30109, 1.5, "0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13"),
|
|
1781
|
+
["polygon" /* Polygon */]: bridgeChain("polygon" /* Polygon */, 30109, 1.5, "0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13", 70),
|
|
1782
1782
|
["plasma" /* Plasma */]: bridgeChain("plasma" /* Plasma */, 30383, 1, "0x02ca37966753bDdDf11216B73B16C1dE756A7CF9"),
|
|
1783
1783
|
["optimism" /* Optimism */]: bridgeChain("optimism" /* Optimism */, 30111, 2, "0xF03b4d9AC1D5d1E7c4cEf54C2A313b9fe051A0aD"),
|
|
1784
1784
|
["unichain" /* Unichain */]: bridgeChain("unichain" /* Unichain */, 30320, 1, "0xc07bE8994D035631c36fb4a89C918CeFB2f03EC3"),
|
|
1785
1785
|
["sei" /* Sei */]: bridgeChain("sei" /* Sei */, 30280, 0.5, "0x56Fe74A2e3b484b921c447357203431a3485CC60"),
|
|
1786
|
-
["flare" /* Flare */]: bridgeChain("flare" /* Flare */, 30295, 1.1, "0x567287d2A9829215a37e3B88843d32f9221E7588"),
|
|
1786
|
+
["flare" /* Flare */]: bridgeChain("flare" /* Flare */, 30295, 1.1, "0x567287d2A9829215a37e3B88843d32f9221E7588", 600),
|
|
1787
1787
|
["xlayer" /* XLayer */]: bridgeChain("xlayer" /* XLayer */, 30274, 1, "0x94BCCa6bdfd6A61817Ab0E960bFedE4984505554"),
|
|
1788
1788
|
["rootstock" /* Rootstock */]: bridgeChain("rootstock" /* Rootstock */, 30333, 31, "0x1a594d5d5d1c426281C1064B07f23F57B2716B61"),
|
|
1789
1789
|
// XAUt0 only — BSC has no USDT0 deployment. Block time measured 2026-08-20.
|
|
@@ -1964,6 +1964,14 @@ function median(values) {
|
|
|
1964
1964
|
const mid = Math.floor(sorted.length / 2);
|
|
1965
1965
|
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
1966
1966
|
}
|
|
1967
|
+
function resolveDeliverySeconds(formulaSeconds, observedSeconds, minDeliverySec) {
|
|
1968
|
+
const base = formulaSeconds ?? observedSeconds;
|
|
1969
|
+
if (base === void 0) return void 0;
|
|
1970
|
+
if (minDeliverySec !== void 0 && minDeliverySec > base) {
|
|
1971
|
+
return { seconds: minDeliverySec, source: "floor" };
|
|
1972
|
+
}
|
|
1973
|
+
return { seconds: base, source: formulaSeconds !== void 0 ? "formula" : "observed" };
|
|
1974
|
+
}
|
|
1967
1975
|
var WORKER_EXECUTOR = 1;
|
|
1968
1976
|
var OPTION_LZRECEIVE = 1;
|
|
1969
1977
|
var OPTION_NATIVE_DROP = 2;
|
|
@@ -2383,16 +2391,22 @@ var LayerZeroService = class {
|
|
|
2383
2391
|
/**
|
|
2384
2392
|
* Estimate how long a USDT0 bridge will take, end to end.
|
|
2385
2393
|
*
|
|
2386
|
-
*
|
|
2387
|
-
*
|
|
2388
|
-
*
|
|
2389
|
-
*
|
|
2390
|
-
*
|
|
2394
|
+
* The number comes from the pathway's live ULN config:
|
|
2395
|
+
* `srcBlockTime × confirmations + dstBlockTime × (2 + dvnCount)`, floored at the
|
|
2396
|
+
* source chain's {@link BridgeChainConfig.minDeliverySec} where the confirmation
|
|
2397
|
+
* count is not the whole wait. This is what the DVNs are actually bound by, so it
|
|
2398
|
+
* tracks a config change the moment it lands — and on every pathway that is purely
|
|
2399
|
+
* confirmation-bound it agrees with both usdt0.to's own estimate and the delivery
|
|
2400
|
+
* times Scan reports to well under a percent.
|
|
2391
2401
|
*
|
|
2392
|
-
*
|
|
2393
|
-
*
|
|
2394
|
-
*
|
|
2395
|
-
*
|
|
2402
|
+
* The observed median of recent deliveries on this exact pathway is fetched too
|
|
2403
|
+
* and reported as {@link BridgeTimeEstimate.observedSeconds}, but it no longer
|
|
2404
|
+
* drives `seconds`. History lags the config: after Optimism→Stable was raised to
|
|
2405
|
+
* 1000 confirmations, a 50-message window still reaching back 261 days put the
|
|
2406
|
+
* median at ~15min against a real ~33min, and pathways quiet for months (Unichain,
|
|
2407
|
+
* XAUt0 from Arbitrum) were answering from configs that no longer exist. It stays
|
|
2408
|
+
* the fallback for the case the formula cannot be computed at all — an RPC that
|
|
2409
|
+
* will not serve the ULN read.
|
|
2396
2410
|
*/
|
|
2397
2411
|
async estimateBridgeTime({
|
|
2398
2412
|
fromChain,
|
|
@@ -2423,16 +2437,15 @@ var LayerZeroService = class {
|
|
|
2423
2437
|
);
|
|
2424
2438
|
formulaSeconds = Number.isFinite(computed) ? computed : void 0;
|
|
2425
2439
|
}
|
|
2426
|
-
const
|
|
2427
|
-
if (
|
|
2440
|
+
const resolved = resolveDeliverySeconds(formulaSeconds, observedSeconds, src.minDeliverySec);
|
|
2441
|
+
if (!resolved) {
|
|
2428
2442
|
throw new StableQuoteError({
|
|
2429
2443
|
provider: "layerzero",
|
|
2430
2444
|
shortMessage: `estimateBridgeTime: no pathway data for ${fromChain}\u2192${toChain}`
|
|
2431
2445
|
});
|
|
2432
2446
|
}
|
|
2433
2447
|
return {
|
|
2434
|
-
|
|
2435
|
-
source: observedSeconds !== void 0 ? "observed" : "formula",
|
|
2448
|
+
...resolved,
|
|
2436
2449
|
observedSeconds,
|
|
2437
2450
|
formulaSeconds,
|
|
2438
2451
|
confirmations: Number.isFinite(uln?.confirmations) ? uln?.confirmations : void 0,
|