@stablechain/sdk 1.0.5 → 1.0.7
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 +233 -9
- package/dist/index.cjs +630 -163
- package/dist/index.d.cts +435 -20
- package/dist/index.d.ts +435 -20
- package/dist/index.js +620 -153
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1737,46 +1737,88 @@ function isLiFiQuoteShape(v) {
|
|
|
1737
1737
|
|
|
1738
1738
|
|
|
1739
1739
|
|
|
1740
|
+
|
|
1741
|
+
|
|
1740
1742
|
var C = CHAIN_CONFIGS;
|
|
1743
|
+
var XAUT0_DEPLOYMENTS = {
|
|
1744
|
+
["ethereum" /* Ethereum */]: { address: "0x68749665FF8D2d112Fa859AA293F07A622782F38", decimals: 6, oftAdapter: "0xb9c2321BB7D0Db468f570D10A424d1Cc8EFd696C", approvalRequired: true },
|
|
1745
|
+
["stable" /* Stable */]: { address: "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb", decimals: 6, oftAdapter: "0xD8479f87686ed263D00Ca7505F86327dbeD4171A", approvalRequired: false },
|
|
1746
|
+
["arbitrum" /* Arbitrum */]: { address: "0x40461291347e1eCbb09499F3371D3f17f10d7159", decimals: 6, oftAdapter: "0xf40542a7B66AD7C68C459EE3679635D2fDB6dF39", approvalRequired: false },
|
|
1747
|
+
["ink" /* Ink */]: { address: "0xF50258D3c1dd88946C567920B986A12e65b50dAc", decimals: 6, oftAdapter: "0xA1bE1572B4beef24f812EfDc58bdc41D56a0dAB2", approvalRequired: false },
|
|
1748
|
+
["hyperevm" /* HyperEVM */]: { address: "0xf4D9235269a96aaDaFc9aDAe454a0618eBE37949", decimals: 6, oftAdapter: "0x4E41cfc3F3B19E29E323D2c36F8f202a1e151dAF", approvalRequired: false },
|
|
1749
|
+
["polygon" /* Polygon */]: { address: "0xF1815bd50389c46847f0Bda824eC8da914045D14", decimals: 6, oftAdapter: "0x5421Cf4288d8007D3c43AC4246eaFCe5b049e352", approvalRequired: false },
|
|
1750
|
+
["plasma" /* Plasma */]: { address: "0x1B64B9025EEbb9A6239575dF9Ea4b9Ac46D4d193", decimals: 6, oftAdapter: "0x63aB93cBC9d4ecD9c4947b1A38F458147C08E6F7", approvalRequired: false },
|
|
1751
|
+
["bsc" /* BSC */]: { address: "0x21cAef8A43163Eea865baeE23b9C2E327696A3bf", decimals: 6, oftAdapter: "0x53C3A64c8942288e12813C1F8457Db45980BcfC2", approvalRequired: false }
|
|
1752
|
+
};
|
|
1753
|
+
var USDT0_LOCKBOX_CHAINS = /* @__PURE__ */ new Set(["ethereum" /* Ethereum */, "sepolia" /* Sepolia */]);
|
|
1754
|
+
function bridgeChain(chain, lzEid, blockTimeSec, usdt0Adapter) {
|
|
1755
|
+
const base = C[chain];
|
|
1756
|
+
const tokens = {};
|
|
1757
|
+
if (usdt0Adapter) {
|
|
1758
|
+
tokens.usdt0 = {
|
|
1759
|
+
address: base.usdt,
|
|
1760
|
+
decimals: base.decimals,
|
|
1761
|
+
oftAdapter: usdt0Adapter,
|
|
1762
|
+
approvalRequired: USDT0_LOCKBOX_CHAINS.has(chain)
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1765
|
+
const xaut0 = XAUT0_DEPLOYMENTS[chain];
|
|
1766
|
+
if (xaut0) tokens.xaut0 = xaut0;
|
|
1767
|
+
return { ...base, lzEid, blockTimeSec, tokens, oftAdapter: usdt0Adapter };
|
|
1768
|
+
}
|
|
1741
1769
|
var BRIDGE_CHAIN_CONFIGS = {
|
|
1742
1770
|
// ─── Testnet ───────────────────────────────────────────────────────────────
|
|
1743
|
-
["sepolia" /* Sepolia */]:
|
|
1744
|
-
["stable-testnet" /* StableTestnet */]:
|
|
1771
|
+
["sepolia" /* Sepolia */]: bridgeChain("sepolia" /* Sepolia */, 40161, 12, "0xc099cD946d5efCC35A99D64E808c1430cEf08126"),
|
|
1772
|
+
["stable-testnet" /* StableTestnet */]: bridgeChain("stable-testnet" /* StableTestnet */, 40374, 0.7, "0x779Ded0c9e1022225f8E0630b35a9b54bE713736"),
|
|
1745
1773
|
// ─── Mainnet ──────────────────────────────────────────────────────────────
|
|
1746
|
-
["stable" /* Stable */]:
|
|
1747
|
-
["ethereum" /* Ethereum */]:
|
|
1748
|
-
["arbitrum" /* Arbitrum */]:
|
|
1749
|
-
["ink" /* Ink */]:
|
|
1750
|
-
["bera" /* Bera */]:
|
|
1751
|
-
["megaeth" /* MegaETH */]:
|
|
1752
|
-
["hyperevm" /* HyperEVM */]:
|
|
1753
|
-
["polygon" /* Polygon */]:
|
|
1754
|
-
["plasma" /* Plasma */]:
|
|
1755
|
-
["optimism" /* Optimism */]:
|
|
1756
|
-
["unichain" /* Unichain */]:
|
|
1757
|
-
["sei" /* Sei */]:
|
|
1758
|
-
["flare" /* Flare */]:
|
|
1759
|
-
["xlayer" /* XLayer */]:
|
|
1760
|
-
["rootstock" /* Rootstock */]:
|
|
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"),
|
|
1777
|
+
["ink" /* Ink */]: bridgeChain("ink" /* Ink */, 30339, 1, "0x1cB6De532588fCA4a21B7209DE7C456AF8434A65"),
|
|
1778
|
+
["bera" /* Bera */]: bridgeChain("bera" /* Bera */, 30362, 2, "0x3Dc96399109df5ceb2C226664A086140bD0379cB"),
|
|
1779
|
+
["megaeth" /* MegaETH */]: bridgeChain("megaeth" /* MegaETH */, 30398, 1, "0x9151434b16b9763660705744891fa906f660ecc5"),
|
|
1780
|
+
["hyperevm" /* HyperEVM */]: bridgeChain("hyperevm" /* HyperEVM */, 30367, 1, "0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98"),
|
|
1781
|
+
["polygon" /* Polygon */]: bridgeChain("polygon" /* Polygon */, 30109, 1.5, "0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13"),
|
|
1782
|
+
["plasma" /* Plasma */]: bridgeChain("plasma" /* Plasma */, 30383, 1, "0x02ca37966753bDdDf11216B73B16C1dE756A7CF9"),
|
|
1783
|
+
["optimism" /* Optimism */]: bridgeChain("optimism" /* Optimism */, 30111, 2, "0xF03b4d9AC1D5d1E7c4cEf54C2A313b9fe051A0aD"),
|
|
1784
|
+
["unichain" /* Unichain */]: bridgeChain("unichain" /* Unichain */, 30320, 1, "0xc07bE8994D035631c36fb4a89C918CeFB2f03EC3"),
|
|
1785
|
+
["sei" /* Sei */]: bridgeChain("sei" /* Sei */, 30280, 0.5, "0x56Fe74A2e3b484b921c447357203431a3485CC60"),
|
|
1786
|
+
["flare" /* Flare */]: bridgeChain("flare" /* Flare */, 30295, 1.1, "0x567287d2A9829215a37e3B88843d32f9221E7588"),
|
|
1787
|
+
["xlayer" /* XLayer */]: bridgeChain("xlayer" /* XLayer */, 30274, 1, "0x94BCCa6bdfd6A61817Ab0E960bFedE4984505554"),
|
|
1788
|
+
["rootstock" /* Rootstock */]: bridgeChain("rootstock" /* Rootstock */, 30333, 31, "0x1a594d5d5d1c426281C1064B07f23F57B2716B61"),
|
|
1789
|
+
// XAUt0 only — BSC has no USDT0 deployment. Block time measured 2026-08-20.
|
|
1790
|
+
["bsc" /* BSC */]: bridgeChain("bsc" /* BSC */, 30102, 0.45)
|
|
1791
|
+
};
|
|
1792
|
+
function bridgeAssetFor(cfg, token) {
|
|
1793
|
+
const needle = token.toLowerCase();
|
|
1794
|
+
return Object.keys(cfg.tokens).find(
|
|
1795
|
+
(asset) => _optionalChain([cfg, 'access', _36 => _36.tokens, 'access', _37 => _37[asset], 'optionalAccess', _38 => _38.address, 'access', _39 => _39.toLowerCase, 'call', _40 => _40()]) === needle
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
function describeAssets(cfg) {
|
|
1799
|
+
const assets = Object.entries(cfg.tokens);
|
|
1800
|
+
if (assets.length === 0) return "no OFT assets";
|
|
1801
|
+
return assets.map(([asset, token]) => `${asset} (${token.address})`).join(" or ");
|
|
1802
|
+
}
|
|
1803
|
+
var SEND_PARAM_INPUT = {
|
|
1804
|
+
name: "_sendParam",
|
|
1805
|
+
type: "tuple",
|
|
1806
|
+
components: [
|
|
1807
|
+
{ name: "dstEid", type: "uint32" },
|
|
1808
|
+
{ name: "to", type: "bytes32" },
|
|
1809
|
+
{ name: "amountLD", type: "uint256" },
|
|
1810
|
+
{ name: "minAmountLD", type: "uint256" },
|
|
1811
|
+
{ name: "extraOptions", type: "bytes" },
|
|
1812
|
+
{ name: "composeMsg", type: "bytes" },
|
|
1813
|
+
{ name: "oftCmd", type: "bytes" }
|
|
1814
|
+
]
|
|
1761
1815
|
};
|
|
1762
1816
|
var OFT_ADAPTER_ABI = [
|
|
1763
1817
|
{
|
|
1764
1818
|
name: "quoteSend",
|
|
1765
1819
|
type: "function",
|
|
1766
1820
|
inputs: [
|
|
1767
|
-
|
|
1768
|
-
name: "_sendParam",
|
|
1769
|
-
type: "tuple",
|
|
1770
|
-
components: [
|
|
1771
|
-
{ name: "dstEid", type: "uint32" },
|
|
1772
|
-
{ name: "to", type: "bytes32" },
|
|
1773
|
-
{ name: "amountLD", type: "uint256" },
|
|
1774
|
-
{ name: "minAmountLD", type: "uint256" },
|
|
1775
|
-
{ name: "extraOptions", type: "bytes" },
|
|
1776
|
-
{ name: "composeMsg", type: "bytes" },
|
|
1777
|
-
{ name: "oftCmd", type: "bytes" }
|
|
1778
|
-
]
|
|
1779
|
-
},
|
|
1821
|
+
SEND_PARAM_INPUT,
|
|
1780
1822
|
{ name: "_payInLzToken", type: "bool" }
|
|
1781
1823
|
],
|
|
1782
1824
|
outputs: [
|
|
@@ -1792,22 +1834,48 @@ var OFT_ADAPTER_ABI = [
|
|
|
1792
1834
|
stateMutability: "view"
|
|
1793
1835
|
},
|
|
1794
1836
|
{
|
|
1795
|
-
|
|
1837
|
+
// OFT-level accounting, independent of the LayerZero messaging fee: the
|
|
1838
|
+
// pathway's accepted range, any fee the adapter charges itself, and what the
|
|
1839
|
+
// recipient actually ends up credited.
|
|
1840
|
+
name: "quoteOFT",
|
|
1796
1841
|
type: "function",
|
|
1797
1842
|
inputs: [
|
|
1843
|
+
SEND_PARAM_INPUT
|
|
1844
|
+
],
|
|
1845
|
+
outputs: [
|
|
1798
1846
|
{
|
|
1799
|
-
name: "
|
|
1847
|
+
name: "oftLimit",
|
|
1800
1848
|
type: "tuple",
|
|
1801
1849
|
components: [
|
|
1802
|
-
{ name: "dstEid", type: "uint32" },
|
|
1803
|
-
{ name: "to", type: "bytes32" },
|
|
1804
|
-
{ name: "amountLD", type: "uint256" },
|
|
1805
1850
|
{ name: "minAmountLD", type: "uint256" },
|
|
1806
|
-
{ name: "
|
|
1807
|
-
{ name: "composeMsg", type: "bytes" },
|
|
1808
|
-
{ name: "oftCmd", type: "bytes" }
|
|
1851
|
+
{ name: "maxAmountLD", type: "uint256" }
|
|
1809
1852
|
]
|
|
1810
1853
|
},
|
|
1854
|
+
{
|
|
1855
|
+
name: "oftFeeDetails",
|
|
1856
|
+
type: "tuple[]",
|
|
1857
|
+
components: [
|
|
1858
|
+
// Signed: a negative detail is a credit to the sender, not a charge.
|
|
1859
|
+
{ name: "feeAmountLD", type: "int256" },
|
|
1860
|
+
{ name: "description", type: "string" }
|
|
1861
|
+
]
|
|
1862
|
+
},
|
|
1863
|
+
{
|
|
1864
|
+
name: "oftReceipt",
|
|
1865
|
+
type: "tuple",
|
|
1866
|
+
components: [
|
|
1867
|
+
{ name: "amountSentLD", type: "uint256" },
|
|
1868
|
+
{ name: "amountReceivedLD", type: "uint256" }
|
|
1869
|
+
]
|
|
1870
|
+
}
|
|
1871
|
+
],
|
|
1872
|
+
stateMutability: "view"
|
|
1873
|
+
},
|
|
1874
|
+
{
|
|
1875
|
+
name: "send",
|
|
1876
|
+
type: "function",
|
|
1877
|
+
inputs: [
|
|
1878
|
+
SEND_PARAM_INPUT,
|
|
1811
1879
|
{
|
|
1812
1880
|
name: "_fee",
|
|
1813
1881
|
type: "tuple",
|
|
@@ -1880,7 +1948,7 @@ var ScanHttpError = class extends Error {
|
|
|
1880
1948
|
async function scanFetch(path, timeoutMs = 8e3) {
|
|
1881
1949
|
const res = await fetch(`${LZ_SCAN_API}${path}`, { signal: AbortSignal.timeout(timeoutMs) });
|
|
1882
1950
|
if (!res.ok) throw new ScanHttpError(res.status, path);
|
|
1883
|
-
return res.json();
|
|
1951
|
+
return await res.json();
|
|
1884
1952
|
}
|
|
1885
1953
|
var TERMINAL_FAILURE_STATUSES = /* @__PURE__ */ new Set([
|
|
1886
1954
|
"FAILED",
|
|
@@ -1896,62 +1964,293 @@ function median(values) {
|
|
|
1896
1964
|
const mid = Math.floor(sorted.length / 2);
|
|
1897
1965
|
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
1898
1966
|
}
|
|
1899
|
-
|
|
1967
|
+
var WORKER_EXECUTOR = 1;
|
|
1968
|
+
var OPTION_LZRECEIVE = 1;
|
|
1969
|
+
var OPTION_NATIVE_DROP = 2;
|
|
1970
|
+
function lzOption(optionType, payload) {
|
|
1971
|
+
const payloadBytes = (payload.length - 2) / 2;
|
|
1972
|
+
return _viem.concat.call(void 0, [
|
|
1973
|
+
_viem.numberToHex.call(void 0, WORKER_EXECUTOR, { size: 1 }),
|
|
1974
|
+
_viem.numberToHex.call(void 0, 1 + payloadBytes, { size: 2 }),
|
|
1975
|
+
_viem.numberToHex.call(void 0, optionType, { size: 1 }),
|
|
1976
|
+
payload
|
|
1977
|
+
]);
|
|
1978
|
+
}
|
|
1979
|
+
function buildLzOptions(gasLimit = 0n, nativeDrop = 0n, dropReceiver) {
|
|
1980
|
+
const options = [
|
|
1981
|
+
lzOption(OPTION_LZRECEIVE, _viem.numberToHex.call(void 0, gasLimit, { size: 16 }))
|
|
1982
|
+
];
|
|
1983
|
+
if (nativeDrop > 0n) {
|
|
1984
|
+
if (!dropReceiver) {
|
|
1985
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
1986
|
+
"recipient",
|
|
1987
|
+
dropReceiver,
|
|
1988
|
+
"buildLzOptions: a native drop needs a receiver address"
|
|
1989
|
+
);
|
|
1990
|
+
}
|
|
1991
|
+
options.push(
|
|
1992
|
+
lzOption(
|
|
1993
|
+
OPTION_NATIVE_DROP,
|
|
1994
|
+
_viem.concat.call(void 0, [
|
|
1995
|
+
_viem.numberToHex.call(void 0, nativeDrop, { size: 16 }),
|
|
1996
|
+
_viem.padHex.call(void 0, dropReceiver, { dir: "left", size: 32 })
|
|
1997
|
+
])
|
|
1998
|
+
)
|
|
1999
|
+
);
|
|
2000
|
+
}
|
|
1900
2001
|
return _viem.concat.call(void 0, [
|
|
1901
2002
|
_viem.numberToHex.call(void 0, 3, { size: 2 }),
|
|
1902
2003
|
// TYPE_3 header
|
|
1903
|
-
|
|
1904
|
-
// Executor worker ID
|
|
1905
|
-
_viem.numberToHex.call(void 0, 17, { size: 2 }),
|
|
1906
|
-
// option payload length = 17 bytes
|
|
1907
|
-
_viem.numberToHex.call(void 0, 1, { size: 1 }),
|
|
1908
|
-
// LzReceive option type
|
|
1909
|
-
_viem.numberToHex.call(void 0, gasLimit, { size: 16 })
|
|
1910
|
-
// gas limit as uint128
|
|
2004
|
+
...options
|
|
1911
2005
|
]);
|
|
1912
2006
|
}
|
|
2007
|
+
var FALLBACK_SEND_GAS = 400000n;
|
|
2008
|
+
var DEFAULT_FEE_BUFFER_BPS = 500;
|
|
2009
|
+
var MAX_FEE_BUFFER_BPS = 1e4;
|
|
2010
|
+
function padFee(nativeFee, bufferBps) {
|
|
2011
|
+
return nativeFee * BigInt(1e4 + bufferBps) / 10000n;
|
|
2012
|
+
}
|
|
2013
|
+
function resolveFeeBuffer(feeBufferBps, method) {
|
|
2014
|
+
if (feeBufferBps === void 0) return DEFAULT_FEE_BUFFER_BPS;
|
|
2015
|
+
if (!Number.isInteger(feeBufferBps) || feeBufferBps < 0 || feeBufferBps > MAX_FEE_BUFFER_BPS) {
|
|
2016
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2017
|
+
"feeBufferBps",
|
|
2018
|
+
feeBufferBps,
|
|
2019
|
+
`${method}: feeBufferBps must be an integer between 0 and ${MAX_FEE_BUFFER_BPS}`
|
|
2020
|
+
);
|
|
2021
|
+
}
|
|
2022
|
+
return feeBufferBps;
|
|
2023
|
+
}
|
|
2024
|
+
function usableQuote(quote, amountLD) {
|
|
2025
|
+
if (!_optionalChain([quote, 'optionalAccess', _41 => _41.oft])) return quote;
|
|
2026
|
+
return quote.oft.amountSentLD <= amountLD ? quote : void 0;
|
|
2027
|
+
}
|
|
2028
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
1913
2029
|
var LayerZeroService = class {
|
|
1914
2030
|
constructor(config) {
|
|
1915
2031
|
this.config = config;
|
|
2032
|
+
this.rpcById = new Map(
|
|
2033
|
+
Object.entries(_nullishCoalesce(config.rpcOverrides, () => ( {}))).flatMap(([chain, rpc]) => {
|
|
2034
|
+
const id = _optionalChain([CHAIN_CONFIGS, 'access', _42 => _42[chain], 'optionalAccess', _43 => _43.id]);
|
|
2035
|
+
return id === void 0 || !rpc ? [] : [[id, rpc.replace(/\/$/, "")]];
|
|
2036
|
+
})
|
|
2037
|
+
);
|
|
2038
|
+
}
|
|
2039
|
+
/**
|
|
2040
|
+
* The RPC to read and broadcast on for a chain: the caller's override when they
|
|
2041
|
+
* gave one, else the built-in public endpoint. Every bridge read goes through
|
|
2042
|
+
* here — a backend quoting on a loop needs an endpoint it controls.
|
|
2043
|
+
*/
|
|
2044
|
+
rpcFor(cfg) {
|
|
2045
|
+
return _nullishCoalesce(this.rpcById.get(cfg.id), () => ( cfg.rpc));
|
|
1916
2046
|
}
|
|
1917
2047
|
async quoteBridge(params) {
|
|
1918
|
-
|
|
1919
|
-
|
|
2048
|
+
return this.buildQuote(this.plan(params, "quoteBridge"), params, "quoteBridge");
|
|
2049
|
+
}
|
|
2050
|
+
/**
|
|
2051
|
+
* The full quote for a planned send. `quoteBridge` reports one; the unsigned
|
|
2052
|
+
* build needs the same numbers and must not disagree with what a caller was
|
|
2053
|
+
* shown, so both come from here.
|
|
2054
|
+
*
|
|
2055
|
+
* `account` is who the gas simulation runs as — this service's signer when it
|
|
2056
|
+
* has one, and the address a prepared send will be signed by when it does not.
|
|
2057
|
+
*/
|
|
2058
|
+
async buildQuote(plan, params, method, opts = {}) {
|
|
2059
|
+
const [{ fee, oft }, estimate] = await Promise.all([
|
|
2060
|
+
this.quotePathway(plan, method, opts.requireOft),
|
|
1920
2061
|
this.estimateBridgeTime(params).catch(() => void 0)
|
|
1921
2062
|
]);
|
|
1922
|
-
|
|
2063
|
+
const srcGas = await this.estimateSendGas(plan, fee, oft, opts.account);
|
|
2064
|
+
return {
|
|
2065
|
+
...fee,
|
|
2066
|
+
// What a send built from this quote will actually carry as its `value`.
|
|
2067
|
+
nativeFeeMax: padFee(fee.nativeFee, plan.feeBufferBps),
|
|
2068
|
+
oft,
|
|
2069
|
+
// What the recipient is actually credited: input minus any OFT fee and
|
|
2070
|
+
// minus dust. Falls back to the input when quoteOFT could not be read.
|
|
2071
|
+
toAmount: _nullishCoalesce(_optionalChain([oft, 'optionalAccess', _44 => _44.amountReceived]), () => ( params.amount)),
|
|
2072
|
+
srcGas,
|
|
2073
|
+
totalCostWei: srcGas ? srcGas.costWei + fee.nativeFee : void 0,
|
|
2074
|
+
estimate
|
|
2075
|
+
};
|
|
1923
2076
|
}
|
|
1924
2077
|
/**
|
|
1925
|
-
* LayerZero messaging fee for a send,
|
|
1926
|
-
*
|
|
2078
|
+
* The LayerZero messaging fee for a send, plus the OFT's own accounting.
|
|
2079
|
+
*
|
|
2080
|
+
* The fee is required — a send cannot be built without it. The OFT accounting is
|
|
2081
|
+
* best-effort for a quote: an adapter that does not answer `quoteOFT` costs a
|
|
2082
|
+
* caller the fee breakdown and the exact output amount, not the whole quote.
|
|
2083
|
+
*
|
|
2084
|
+
* `requireOft` flips that for the paths that go on to build a send. Without the
|
|
2085
|
+
* receipt the only slippage floor left is the full input amount, which reverts
|
|
2086
|
+
* with `SlippageExceeded` the moment a pathway charges a fee — so a send that
|
|
2087
|
+
* cannot read `quoteOFT` is one to refuse loudly rather than assemble blind.
|
|
1927
2088
|
*/
|
|
1928
|
-
async
|
|
1929
|
-
const
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
const amountLD = _viem.parseUnits.call(void 0, String(amount), src.decimals);
|
|
1934
|
-
try {
|
|
1935
|
-
const { nativeFee, lzTokenFee } = await _viem.createPublicClient.call(void 0, {
|
|
1936
|
-
chain: makeChain(src.id, src.rpc),
|
|
1937
|
-
transport: _viem.http.call(void 0, src.rpc)
|
|
1938
|
-
}).readContract({
|
|
1939
|
-
address: oftAdapter,
|
|
2089
|
+
async quotePathway(plan, method, requireOft = false) {
|
|
2090
|
+
const sendParam = this.buildSendParams(plan, 0n);
|
|
2091
|
+
const [msgFee, oft] = await Promise.all([
|
|
2092
|
+
plan.pc.readContract({
|
|
2093
|
+
address: plan.oftAdapter,
|
|
1940
2094
|
abi: OFT_ADAPTER_ABI,
|
|
1941
2095
|
functionName: "quoteSend",
|
|
1942
|
-
args: [
|
|
2096
|
+
args: [sendParam, false]
|
|
2097
|
+
}).catch((err) => {
|
|
2098
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableQuoteError)({
|
|
2099
|
+
provider: "layerzero",
|
|
2100
|
+
shortMessage: plan.nativeDrop > 0n ? `${method}: quoteSend call failed \u2014 a dstNativeDrop over the pathway's executor nativeCap is the usual cause` : `${method}: quoteSend call failed`,
|
|
2101
|
+
cause: err
|
|
2102
|
+
});
|
|
2103
|
+
}),
|
|
2104
|
+
this.readOftQuote(plan, sendParam).catch((err) => {
|
|
2105
|
+
if (!requireOft) return void 0;
|
|
2106
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableQuoteError)({
|
|
2107
|
+
provider: "layerzero",
|
|
2108
|
+
shortMessage: `${method}: quoteOFT call failed \u2014 the adapter's receipt is what floors the send at what it would actually deliver, and there is no safe default for it`,
|
|
2109
|
+
cause: err
|
|
2110
|
+
});
|
|
2111
|
+
})
|
|
2112
|
+
]);
|
|
2113
|
+
const { nativeFee, lzTokenFee } = msgFee;
|
|
2114
|
+
return { fee: { nativeFee, lzTokenFee }, oft };
|
|
2115
|
+
}
|
|
2116
|
+
/**
|
|
2117
|
+
* The adapter's own view of a send: accepted range, its fees, and what lands on
|
|
2118
|
+
* the far side. Throws when the adapter will not answer; `quotePathway` decides
|
|
2119
|
+
* whether that is fatal for the caller it is serving.
|
|
2120
|
+
*/
|
|
2121
|
+
async readOftQuote(plan, sendParam) {
|
|
2122
|
+
const [limit, feeDetails, receipt] = await plan.pc.readContract({
|
|
2123
|
+
address: plan.oftAdapter,
|
|
2124
|
+
abi: OFT_ADAPTER_ABI,
|
|
2125
|
+
functionName: "quoteOFT",
|
|
2126
|
+
args: [sendParam]
|
|
2127
|
+
});
|
|
2128
|
+
const decimals = plan.srcToken.decimals;
|
|
2129
|
+
return {
|
|
2130
|
+
amountSentLD: receipt.amountSentLD,
|
|
2131
|
+
amountReceivedLD: receipt.amountReceivedLD,
|
|
2132
|
+
amountReceived: Number(_viem.formatUnits.call(void 0, receipt.amountReceivedLD, decimals)),
|
|
2133
|
+
fees: feeDetails.map((detail) => ({
|
|
2134
|
+
amountLD: detail.feeAmountLD,
|
|
2135
|
+
amount: Number(_viem.formatUnits.call(void 0, detail.feeAmountLD, decimals)),
|
|
2136
|
+
description: detail.description
|
|
2137
|
+
})),
|
|
2138
|
+
minAmountLD: limit.minAmountLD,
|
|
2139
|
+
maxAmountLD: limit.maxAmountLD
|
|
2140
|
+
};
|
|
2141
|
+
}
|
|
2142
|
+
/**
|
|
2143
|
+
* Source-chain cost of the `send` transaction.
|
|
2144
|
+
*
|
|
2145
|
+
* Simulating the real call is the only honest answer, and it needs a sender with
|
|
2146
|
+
* the allowance and the native balance already in place — which a quote taken
|
|
2147
|
+
* before approving does not have. When the simulation reverts, fall back to a
|
|
2148
|
+
* measured constant so the caller still has a cost to show, flagged as such.
|
|
2149
|
+
*/
|
|
2150
|
+
async estimateSendGas(plan, fee, oft, sender) {
|
|
2151
|
+
const gasPriceWei = await this.gasPrice(plan);
|
|
2152
|
+
if (gasPriceWei === void 0) return void 0;
|
|
2153
|
+
let gas = FALLBACK_SEND_GAS;
|
|
2154
|
+
let source = "fallback";
|
|
2155
|
+
const account = _nullishCoalesce(sender, () => ( this.signerAddress()));
|
|
2156
|
+
if (account) {
|
|
2157
|
+
const sendFee = {
|
|
2158
|
+
nativeFee: padFee(fee.nativeFee, plan.feeBufferBps),
|
|
2159
|
+
lzTokenFee: fee.lzTokenFee
|
|
2160
|
+
};
|
|
2161
|
+
try {
|
|
2162
|
+
gas = await plan.pc.estimateContractGas({
|
|
2163
|
+
address: plan.oftAdapter,
|
|
2164
|
+
abi: OFT_ADAPTER_ABI,
|
|
2165
|
+
functionName: "send",
|
|
2166
|
+
args: [
|
|
2167
|
+
this.buildSendParams(plan, _nullishCoalesce(_optionalChain([oft, 'optionalAccess', _45 => _45.amountReceivedLD]), () => ( plan.amountLD))),
|
|
2168
|
+
sendFee,
|
|
2169
|
+
account
|
|
2170
|
+
],
|
|
2171
|
+
account,
|
|
2172
|
+
value: sendFee.nativeFee
|
|
2173
|
+
});
|
|
2174
|
+
source = "simulated";
|
|
2175
|
+
} catch (e5) {
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
return { gas, gasPriceWei, costWei: gas * gasPriceWei, source };
|
|
2179
|
+
}
|
|
2180
|
+
/** Price per gas unit on the source chain, or undefined if the RPC won't say. */
|
|
2181
|
+
async gasPrice(plan) {
|
|
2182
|
+
try {
|
|
2183
|
+
const fees = await plan.pc.estimateFeesPerGas();
|
|
2184
|
+
const price = _nullishCoalesce(fees.maxFeePerGas, () => ( fees.gasPrice));
|
|
2185
|
+
if (price !== void 0) return price;
|
|
2186
|
+
} catch (e6) {
|
|
2187
|
+
}
|
|
2188
|
+
try {
|
|
2189
|
+
return await plan.pc.getGasPrice();
|
|
2190
|
+
} catch (e7) {
|
|
2191
|
+
return void 0;
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
/**
|
|
2195
|
+
* The `approve` amounts to send, in order, before `send` can pull `amountLD` —
|
|
2196
|
+
* empty when the adapter needs no allowance or the existing one already covers
|
|
2197
|
+
* the send.
|
|
2198
|
+
*
|
|
2199
|
+
* A short but non-zero allowance takes two approvals, not one. Legacy USDT on
|
|
2200
|
+
* Ethereum — the only token a lockbox pathway ever approves — refuses to
|
|
2201
|
+
* overwrite a non-zero allowance with another non-zero value:
|
|
2202
|
+
*
|
|
2203
|
+
* require(!((_value != 0) && (allowed[msg.sender][_spender] != 0)))
|
|
2204
|
+
*
|
|
2205
|
+
* so a holder who once approved 5 USDT and now bridges 10 gets a reverted
|
|
2206
|
+
* approve and pays the gas for nothing. Zeroing first is harmless on every
|
|
2207
|
+
* other ERC-20, so it is unconditional rather than sniffed per token.
|
|
2208
|
+
*/
|
|
2209
|
+
async approvalPlan(plan, owner, amountLD) {
|
|
2210
|
+
if (plan.srcToken.approvalRequired === false) return [];
|
|
2211
|
+
const allowance = await plan.pc.readContract({
|
|
2212
|
+
address: plan.srcToken.address,
|
|
2213
|
+
abi: _viem.erc20Abi,
|
|
2214
|
+
functionName: "allowance",
|
|
2215
|
+
args: [owner, plan.oftAdapter]
|
|
2216
|
+
});
|
|
2217
|
+
if (allowance >= amountLD) return [];
|
|
2218
|
+
return allowance > 0n ? [0n, amountLD] : [amountLD];
|
|
2219
|
+
}
|
|
2220
|
+
/** Send one `approve` and wait for it to land. */
|
|
2221
|
+
async sendApprove(plan, wc, value) {
|
|
2222
|
+
const { src, asset, srcToken, oftAdapter, pc, chain: srcChain } = plan;
|
|
2223
|
+
const what = value === 0n ? "allowance reset" : "approve";
|
|
2224
|
+
let approveHash;
|
|
2225
|
+
try {
|
|
2226
|
+
approveHash = await wc.writeContract({
|
|
2227
|
+
address: srcToken.address,
|
|
2228
|
+
abi: _viem.erc20Abi,
|
|
2229
|
+
functionName: "approve",
|
|
2230
|
+
args: [oftAdapter, value],
|
|
2231
|
+
account: wc.account,
|
|
2232
|
+
chain: srcChain
|
|
1943
2233
|
});
|
|
1944
|
-
return { nativeFee, lzTokenFee };
|
|
1945
2234
|
} catch (err) {
|
|
1946
|
-
throw new (0, _chunkQQ26UI3Fcjs.
|
|
1947
|
-
|
|
1948
|
-
shortMessage:
|
|
2235
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
|
|
2236
|
+
phase: "approve",
|
|
2237
|
+
shortMessage: `bridge: ${asset} ${what} failed`,
|
|
2238
|
+
chainId: src.id,
|
|
1949
2239
|
cause: err
|
|
1950
2240
|
});
|
|
1951
2241
|
}
|
|
2242
|
+
const approveReceipt = await pc.waitForTransactionReceipt({ hash: approveHash });
|
|
2243
|
+
if (approveReceipt.status === "reverted") {
|
|
2244
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
|
|
2245
|
+
phase: "approve",
|
|
2246
|
+
shortMessage: `bridge: ${asset} ${what} reverted on-chain`,
|
|
2247
|
+
txHash: approveReceipt.transactionHash,
|
|
2248
|
+
chainId: src.id
|
|
2249
|
+
});
|
|
2250
|
+
}
|
|
1952
2251
|
}
|
|
1953
|
-
async bridge(
|
|
1954
|
-
const from =
|
|
2252
|
+
async bridge(params) {
|
|
2253
|
+
const from = this.signerAddress();
|
|
1955
2254
|
if (!from) {
|
|
1956
2255
|
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
1957
2256
|
"signer",
|
|
@@ -1959,17 +2258,20 @@ var LayerZeroService = class {
|
|
|
1959
2258
|
"bridge: requires a signer \u2014 set walletClient or account in StableConfig"
|
|
1960
2259
|
);
|
|
1961
2260
|
}
|
|
1962
|
-
const
|
|
1963
|
-
|
|
1964
|
-
const
|
|
1965
|
-
const oftAdapter = src.oftAdapter;
|
|
1966
|
-
const srcChain = makeChain(src.id, src.rpc);
|
|
2261
|
+
const plan = this.plan({ ...params, recipient: _nullishCoalesce(params.recipient, () => ( from)) }, "bridge");
|
|
2262
|
+
const { src, oftAdapter, amountLD, chain: srcChain } = plan;
|
|
2263
|
+
const refundAddress = this.resolveRefundAddress(params.refundAddress, from, "bridge");
|
|
1967
2264
|
const wc = _nullishCoalesce(this.config.walletClient, () => ( _viem.createWalletClient.call(void 0, {
|
|
1968
2265
|
account: this.config.account,
|
|
1969
2266
|
chain: srcChain,
|
|
1970
|
-
|
|
2267
|
+
// `config.transport` is the caller's *Stable-chain* transport. A browser
|
|
2268
|
+
// wallet transport is chain-agnostic — the wallet holds the keys and picks
|
|
2269
|
+
// the network — but an HTTP one is a broadcast channel bound to a single
|
|
2270
|
+
// chain, and broadcasting an Ethereum send to the Stable RPC fails. With a
|
|
2271
|
+
// local account we sign here and only need somewhere to broadcast, so the
|
|
2272
|
+
// source chain's own endpoint is always the right answer.
|
|
2273
|
+
transport: this.config.account ? _viem.http.call(void 0, plan.rpc) : _nullishCoalesce(this.config.transport, () => ( _viem.http.call(void 0, plan.rpc)))
|
|
1971
2274
|
})));
|
|
1972
|
-
const pc = _viem.createPublicClient.call(void 0, { chain: srcChain, transport: _viem.http.call(void 0, src.rpc) });
|
|
1973
2275
|
try {
|
|
1974
2276
|
await wc.switchChain({ id: src.id });
|
|
1975
2277
|
} catch (err) {
|
|
@@ -1980,55 +2282,24 @@ var LayerZeroService = class {
|
|
|
1980
2282
|
cause: err
|
|
1981
2283
|
});
|
|
1982
2284
|
}
|
|
1983
|
-
const
|
|
1984
|
-
const
|
|
1985
|
-
const
|
|
1986
|
-
const
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
functionName: "allowance",
|
|
1990
|
-
args: [from, oftAdapter]
|
|
1991
|
-
});
|
|
1992
|
-
if (allowance < amountLD) {
|
|
1993
|
-
let approveHash;
|
|
1994
|
-
try {
|
|
1995
|
-
approveHash = await wc.writeContract({
|
|
1996
|
-
address: src.usdt,
|
|
1997
|
-
abi: _viem.erc20Abi,
|
|
1998
|
-
functionName: "approve",
|
|
1999
|
-
args: [oftAdapter, amountLD],
|
|
2000
|
-
account: wc.account,
|
|
2001
|
-
chain: srcChain
|
|
2002
|
-
});
|
|
2003
|
-
} catch (err) {
|
|
2004
|
-
throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
|
|
2005
|
-
phase: "approve",
|
|
2006
|
-
shortMessage: "bridge: USDT0 approve failed",
|
|
2007
|
-
chainId: src.id,
|
|
2008
|
-
cause: err
|
|
2009
|
-
});
|
|
2010
|
-
}
|
|
2011
|
-
const approveReceipt = await pc.waitForTransactionReceipt({ hash: approveHash });
|
|
2012
|
-
if (approveReceipt.status === "reverted") {
|
|
2013
|
-
throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
|
|
2014
|
-
phase: "approve",
|
|
2015
|
-
shortMessage: "bridge: USDT0 approve reverted on-chain",
|
|
2016
|
-
txHash: approveReceipt.transactionHash,
|
|
2017
|
-
chainId: src.id
|
|
2018
|
-
});
|
|
2019
|
-
}
|
|
2285
|
+
const quote = usableQuote(params.quote, amountLD);
|
|
2286
|
+
const { nativeFee, lzTokenFee, oft } = _optionalChain([quote, 'optionalAccess', _46 => _46.nativeFee]) !== void 0 && _optionalChain([quote, 'optionalAccess', _47 => _47.lzTokenFee]) !== void 0 ? { nativeFee: quote.nativeFee, lzTokenFee: quote.lzTokenFee, oft: quote.oft } : await this.quotePathway(plan, "bridge", true).then((r) => ({ ...r.fee, oft: r.oft }));
|
|
2287
|
+
const sendParams = this.buildSendParams(plan, _nullishCoalesce(_optionalChain([oft, 'optionalAccess', _48 => _48.amountReceivedLD]), () => ( amountLD)));
|
|
2288
|
+
const sendFee = padFee(nativeFee, plan.feeBufferBps);
|
|
2289
|
+
for (const value of await this.approvalPlan(plan, from, amountLD)) {
|
|
2290
|
+
await this.sendApprove(plan, wc, value);
|
|
2020
2291
|
}
|
|
2021
2292
|
try {
|
|
2022
2293
|
const hash = await wc.writeContract({
|
|
2023
2294
|
address: oftAdapter,
|
|
2024
2295
|
abi: OFT_ADAPTER_ABI,
|
|
2025
2296
|
functionName: "send",
|
|
2026
|
-
args: [sendParams, { nativeFee, lzTokenFee },
|
|
2027
|
-
value:
|
|
2297
|
+
args: [sendParams, { nativeFee: sendFee, lzTokenFee }, refundAddress],
|
|
2298
|
+
value: sendFee,
|
|
2028
2299
|
account: wc.account,
|
|
2029
2300
|
chain: srcChain
|
|
2030
2301
|
});
|
|
2031
|
-
return { txHash: hash, toAmount: amount };
|
|
2302
|
+
return { txHash: hash, toAmount: _nullishCoalesce(_optionalChain([oft, 'optionalAccess', _49 => _49.amountReceived]), () => ( params.amount)) };
|
|
2032
2303
|
} catch (err) {
|
|
2033
2304
|
throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
|
|
2034
2305
|
phase: "send",
|
|
@@ -2038,6 +2309,77 @@ var LayerZeroService = class {
|
|
|
2038
2309
|
});
|
|
2039
2310
|
}
|
|
2040
2311
|
}
|
|
2312
|
+
/**
|
|
2313
|
+
* Everything needed to send a bridge, without signing or sending any of it: the
|
|
2314
|
+
* ordered transactions, the quote they were built from, and the `SendParam` the
|
|
2315
|
+
* send step encodes, decoded.
|
|
2316
|
+
*
|
|
2317
|
+
* This is the split-responsibility shape — a backend quotes, builds and checks
|
|
2318
|
+
* while the holder's wallet only signs — and the only way to inspect a bridge
|
|
2319
|
+
* before it exists. Send `steps` in order from `from`, each one confirmed before
|
|
2320
|
+
* the next: an allowance reset and an approve where the lockbox pathway needs
|
|
2321
|
+
* them, then the OFT `send` carrying its fee as `value`.
|
|
2322
|
+
*
|
|
2323
|
+
* Refuses to build when the adapter will not answer `quoteOFT`: the receipt is
|
|
2324
|
+
* what floors the send at what it would actually deliver, and guessing the floor
|
|
2325
|
+
* is how a send reverts with `SlippageExceeded` after the gas is spent.
|
|
2326
|
+
*/
|
|
2327
|
+
async prepareBridgeCalldata(params) {
|
|
2328
|
+
const method = "prepareBridgeCalldata";
|
|
2329
|
+
const from = params.from;
|
|
2330
|
+
if (!_viem.isAddress.call(void 0, from)) {
|
|
2331
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2332
|
+
"from",
|
|
2333
|
+
params.from,
|
|
2334
|
+
`${method}: invalid from address "${params.from}" \u2014 the address that will sign these transactions`
|
|
2335
|
+
);
|
|
2336
|
+
}
|
|
2337
|
+
const refundAddress = this.resolveRefundAddress(params.refundAddress, from, method);
|
|
2338
|
+
const plan = this.plan({ ...params, recipient: _nullishCoalesce(params.recipient, () => ( from)) }, method);
|
|
2339
|
+
const supplied = usableQuote(params.quote, plan.amountLD);
|
|
2340
|
+
const quote = _optionalChain([supplied, 'optionalAccess', _50 => _50.oft]) && supplied.nativeFee !== void 0 && supplied.lzTokenFee !== void 0 ? supplied : await this.buildQuote(plan, params, method, { account: from, requireOft: true });
|
|
2341
|
+
const oft = quote.oft;
|
|
2342
|
+
const nativeFee = padFee(quote.nativeFee, plan.feeBufferBps);
|
|
2343
|
+
const lzTokenFee = quote.lzTokenFee;
|
|
2344
|
+
const sendParam = this.buildSendParams(plan, oft.amountReceivedLD);
|
|
2345
|
+
const steps = (await this.approvalPlan(plan, from, plan.amountLD)).map((value) => ({
|
|
2346
|
+
chainId: plan.src.id,
|
|
2347
|
+
to: plan.srcToken.address,
|
|
2348
|
+
data: _viem.encodeFunctionData.call(void 0, {
|
|
2349
|
+
abi: _viem.erc20Abi,
|
|
2350
|
+
functionName: "approve",
|
|
2351
|
+
args: [plan.oftAdapter, value]
|
|
2352
|
+
}),
|
|
2353
|
+
value: 0n
|
|
2354
|
+
}));
|
|
2355
|
+
steps.push({
|
|
2356
|
+
chainId: plan.src.id,
|
|
2357
|
+
to: plan.oftAdapter,
|
|
2358
|
+
data: _viem.encodeFunctionData.call(void 0, {
|
|
2359
|
+
abi: OFT_ADAPTER_ABI,
|
|
2360
|
+
functionName: "send",
|
|
2361
|
+
args: [sendParam, { nativeFee, lzTokenFee }, refundAddress]
|
|
2362
|
+
}),
|
|
2363
|
+
value: nativeFee
|
|
2364
|
+
});
|
|
2365
|
+
return {
|
|
2366
|
+
steps,
|
|
2367
|
+
chainId: plan.src.id,
|
|
2368
|
+
asset: plan.asset,
|
|
2369
|
+
quote,
|
|
2370
|
+
send: {
|
|
2371
|
+
dstEid: sendParam.dstEid,
|
|
2372
|
+
recipient: plan.recipient,
|
|
2373
|
+
to: sendParam.to,
|
|
2374
|
+
amountLD: sendParam.amountLD,
|
|
2375
|
+
minAmountLD: sendParam.minAmountLD,
|
|
2376
|
+
extraOptions: sendParam.extraOptions,
|
|
2377
|
+
nativeFee,
|
|
2378
|
+
lzTokenFee,
|
|
2379
|
+
refundAddress
|
|
2380
|
+
}
|
|
2381
|
+
};
|
|
2382
|
+
}
|
|
2041
2383
|
/**
|
|
2042
2384
|
* Estimate how long a USDT0 bridge will take, end to end.
|
|
2043
2385
|
*
|
|
@@ -2052,18 +2394,26 @@ var LayerZeroService = class {
|
|
|
2052
2394
|
* computes to ~15s (60 blocks × 0.25s) while real deliveries take ~18min, because
|
|
2053
2395
|
* the DVNs wait for the L2 batch to finalize on L1.
|
|
2054
2396
|
*/
|
|
2055
|
-
async estimateBridgeTime({
|
|
2397
|
+
async estimateBridgeTime({
|
|
2398
|
+
fromChain,
|
|
2399
|
+
toChain,
|
|
2400
|
+
fromToken,
|
|
2401
|
+
toToken
|
|
2402
|
+
}) {
|
|
2056
2403
|
const src = BRIDGE_CHAIN_CONFIGS[fromChain];
|
|
2057
2404
|
const dst = BRIDGE_CHAIN_CONFIGS[toChain];
|
|
2058
|
-
|
|
2405
|
+
const from = _nullishCoalesce(fromToken, () => ( _optionalChain([src, 'optionalAccess', _51 => _51.tokens, 'access', _52 => _52.usdt0, 'optionalAccess', _53 => _53.address])));
|
|
2406
|
+
const to = _nullishCoalesce(toToken, () => ( _optionalChain([dst, 'optionalAccess', _54 => _54.tokens, 'access', _55 => _55.usdt0, 'optionalAccess', _56 => _56.address])));
|
|
2407
|
+
if (!(src && from)) {
|
|
2059
2408
|
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)("fromChain", fromChain, `estimateBridgeTime: no OFT adapter for "${fromChain}"`);
|
|
2060
2409
|
}
|
|
2061
|
-
if (!
|
|
2410
|
+
if (!(dst && to)) {
|
|
2062
2411
|
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)("toChain", toChain, `estimateBridgeTime: no OFT adapter for "${toChain}"`);
|
|
2063
2412
|
}
|
|
2413
|
+
const { srcToken, dstToken } = this.resolveRoute(fromChain, toChain, from, to);
|
|
2064
2414
|
const [uln, observedSeconds] = await Promise.all([
|
|
2065
|
-
this.getUlnConfig(src, dst).catch(() => void 0),
|
|
2066
|
-
this.observedBridgeSeconds(src, dst).catch(() => void 0)
|
|
2415
|
+
this.getUlnConfig(src, dst, srcToken.oftAdapter).catch(() => void 0),
|
|
2416
|
+
this.observedBridgeSeconds(src, dst, srcToken.oftAdapter, dstToken.oftAdapter).catch(() => void 0)
|
|
2067
2417
|
]);
|
|
2068
2418
|
const dvnCount = uln ? uln.requiredDVNCount + uln.optionalDVNCount : void 0;
|
|
2069
2419
|
let formulaSeconds;
|
|
@@ -2085,7 +2435,7 @@ var LayerZeroService = class {
|
|
|
2085
2435
|
source: observedSeconds !== void 0 ? "observed" : "formula",
|
|
2086
2436
|
observedSeconds,
|
|
2087
2437
|
formulaSeconds,
|
|
2088
|
-
confirmations: Number.isFinite(_optionalChain([uln, 'optionalAccess',
|
|
2438
|
+
confirmations: Number.isFinite(_optionalChain([uln, 'optionalAccess', _57 => _57.confirmations])) ? _optionalChain([uln, 'optionalAccess', _58 => _58.confirmations]) : void 0,
|
|
2089
2439
|
dvnCount: Number.isFinite(dvnCount) ? dvnCount : void 0
|
|
2090
2440
|
};
|
|
2091
2441
|
}
|
|
@@ -2098,7 +2448,7 @@ var LayerZeroService = class {
|
|
|
2098
2448
|
const scanUrl = `${LZ_SCAN_UI}/tx/${srcTxHash}`;
|
|
2099
2449
|
let message;
|
|
2100
2450
|
try {
|
|
2101
|
-
message = await _asyncOptionalChain([(await scanFetch(`/messages/tx/${srcTxHash}`)), 'optionalAccess', async
|
|
2451
|
+
message = await _asyncOptionalChain([(await scanFetch(`/messages/tx/${srcTxHash}`)), 'optionalAccess', async _59 => _59.data, 'optionalAccess', async _60 => _60[0]]);
|
|
2102
2452
|
} catch (err) {
|
|
2103
2453
|
if (err instanceof ScanHttpError && err.status === 404) {
|
|
2104
2454
|
return { state: "pending", srcTxHash, scanUrl };
|
|
@@ -2110,24 +2460,24 @@ var LayerZeroService = class {
|
|
|
2110
2460
|
});
|
|
2111
2461
|
}
|
|
2112
2462
|
if (!message) return { state: "pending", srcTxHash, scanUrl };
|
|
2113
|
-
const raw = _nullishCoalesce(_optionalChain([message, 'access',
|
|
2114
|
-
const sentAt = _optionalChain([message, 'access',
|
|
2463
|
+
const raw = _nullishCoalesce(_optionalChain([message, 'access', _61 => _61.status, 'optionalAccess', _62 => _62.name]), () => ( ""));
|
|
2464
|
+
const sentAt = _optionalChain([message, 'access', _63 => _63.source, 'optionalAccess', _64 => _64.tx, 'optionalAccess', _65 => _65.blockTimestamp]);
|
|
2115
2465
|
return {
|
|
2116
2466
|
// Everything terminal that is not DELIVERED means the tokens will not land
|
|
2117
2467
|
// on their own; `raw` carries which of those it was.
|
|
2118
2468
|
state: raw === "DELIVERED" ? "delivered" : TERMINAL_FAILURE_STATUSES.has(raw) ? "failed" : "inflight",
|
|
2119
2469
|
raw,
|
|
2120
2470
|
srcTxHash,
|
|
2121
|
-
dstTxHash: _optionalChain([message, 'access',
|
|
2471
|
+
dstTxHash: _optionalChain([message, 'access', _66 => _66.destination, 'optionalAccess', _67 => _67.tx, 'optionalAccess', _68 => _68.txHash]),
|
|
2122
2472
|
elapsedSeconds: sentAt ? Math.max(0, Math.floor(Date.now() / 1e3) - sentAt) : void 0,
|
|
2123
2473
|
scanUrl
|
|
2124
2474
|
};
|
|
2125
2475
|
}
|
|
2126
2476
|
/** Effective ULN config the DVNs enforce for this pathway, read from the source chain. */
|
|
2127
|
-
async getUlnConfig(src, dst) {
|
|
2128
|
-
return cached(`uln:${src.lzEid}-${dst.lzEid}`, CACHE_TTL_MS, async () => {
|
|
2129
|
-
const
|
|
2130
|
-
const
|
|
2477
|
+
async getUlnConfig(src, dst, oapp) {
|
|
2478
|
+
return cached(`uln:${src.lzEid}-${dst.lzEid}-${oapp.toLowerCase()}`, CACHE_TTL_MS, async () => {
|
|
2479
|
+
const rpc = this.rpcFor(src);
|
|
2480
|
+
const pc = _viem.createPublicClient.call(void 0, { chain: makeChain(src.id, rpc), transport: _viem.http.call(void 0, rpc) });
|
|
2131
2481
|
const endpoint = await pc.readContract({ address: oapp, abi: OAPP_ABI, functionName: "endpoint" });
|
|
2132
2482
|
const sendLib = await pc.readContract({
|
|
2133
2483
|
address: endpoint,
|
|
@@ -2149,11 +2499,11 @@ var LayerZeroService = class {
|
|
|
2149
2499
|
});
|
|
2150
2500
|
}
|
|
2151
2501
|
/** Median delivery time of recently delivered messages on this pathway, in seconds. */
|
|
2152
|
-
async observedBridgeSeconds(src, dst) {
|
|
2153
|
-
const pathwayId = `${src.lzEid}-${dst.lzEid}-${
|
|
2502
|
+
async observedBridgeSeconds(src, dst, srcOapp, dstOapp) {
|
|
2503
|
+
const pathwayId = `${src.lzEid}-${dst.lzEid}-${srcOapp.toLowerCase()}-${dstOapp.toLowerCase()}`;
|
|
2154
2504
|
return cached(`observed:${pathwayId}`, CACHE_TTL_MS, async () => {
|
|
2155
2505
|
const { data } = await scanFetch(`/messages/pathway/${pathwayId}?limit=50`);
|
|
2156
|
-
const durations = (_nullishCoalesce(data, () => ( []))).filter((m) => _optionalChain([m, 'access',
|
|
2506
|
+
const durations = (_nullishCoalesce(data, () => ( []))).filter((m) => _optionalChain([m, 'access', _69 => _69.status, 'optionalAccess', _70 => _70.name]) === "DELIVERED").map((m) => (_nullishCoalesce(_optionalChain([m, 'access', _71 => _71.destination, 'optionalAccess', _72 => _72.tx, 'optionalAccess', _73 => _73.blockTimestamp]), () => ( 0))) - (_nullishCoalesce(_optionalChain([m, 'access', _74 => _74.source, 'optionalAccess', _75 => _75.tx, 'optionalAccess', _76 => _76.blockTimestamp]), () => ( 0)))).filter((d) => d > 0);
|
|
2157
2507
|
return durations.length >= 3 ? Math.round(median(durations)) : void 0;
|
|
2158
2508
|
});
|
|
2159
2509
|
}
|
|
@@ -2180,37 +2530,122 @@ var LayerZeroService = class {
|
|
|
2180
2530
|
);
|
|
2181
2531
|
}
|
|
2182
2532
|
}
|
|
2183
|
-
|
|
2533
|
+
/**
|
|
2534
|
+
* Resolve a bridge request to one OFT mesh and its two endpoints.
|
|
2535
|
+
*
|
|
2536
|
+
* Both sides must name the same asset. An OFT escrows one specific ERC-20 and
|
|
2537
|
+
* mints its own peer on the far side — it cannot hand back a different token,
|
|
2538
|
+
* so a USDT0→XAUt0 request is a trade, not a bridge, and belongs to LI.FI.
|
|
2539
|
+
*/
|
|
2540
|
+
resolveRoute(fromChain, toChain, fromToken, toToken) {
|
|
2184
2541
|
const src = BRIDGE_CHAIN_CONFIGS[fromChain];
|
|
2185
2542
|
const dst = BRIDGE_CHAIN_CONFIGS[toChain];
|
|
2186
2543
|
if (!src) throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)("fromChain", fromChain, `Unsupported source chain: "${fromChain}"`);
|
|
2187
2544
|
if (!dst) throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)("toChain", toChain, `Unsupported destination chain: "${toChain}"`);
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
}
|
|
2191
|
-
if (fromToken.toLowerCase() !== src.usdt.toLowerCase()) {
|
|
2545
|
+
const asset = bridgeAssetFor(src, fromToken);
|
|
2546
|
+
if (!asset) {
|
|
2192
2547
|
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2193
2548
|
"fromToken",
|
|
2194
2549
|
fromToken,
|
|
2195
|
-
`
|
|
2550
|
+
`Native OFT bridge does not recognize "${fromToken}" on "${fromChain}" \u2014 it moves ${describeAssets(src)}. Use route "lifi" to bridge other tokens.`
|
|
2551
|
+
);
|
|
2552
|
+
}
|
|
2553
|
+
const srcToken = src.tokens[asset];
|
|
2554
|
+
const dstToken = dst.tokens[asset];
|
|
2555
|
+
if (!dstToken) {
|
|
2556
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2557
|
+
"toChain",
|
|
2558
|
+
toChain,
|
|
2559
|
+
`Native OFT bridge cannot deliver ${asset} to "${toChain}" \u2014 no ${asset} deployment there. Use route "lifi" instead.`
|
|
2196
2560
|
);
|
|
2197
2561
|
}
|
|
2198
|
-
if (
|
|
2562
|
+
if (dstToken.address.toLowerCase() !== toToken.toLowerCase()) {
|
|
2199
2563
|
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2200
2564
|
"toToken",
|
|
2201
2565
|
toToken,
|
|
2202
|
-
`
|
|
2566
|
+
`Native OFT bridge moves ${asset} to itself \u2014 toToken must be ${dstToken.address} on "${toChain}", got "${toToken}". Use route "lifi" to bridge between different tokens.`
|
|
2203
2567
|
);
|
|
2204
2568
|
}
|
|
2205
|
-
return { src, dst };
|
|
2569
|
+
return { src, dst, asset, srcToken, dstToken };
|
|
2206
2570
|
}
|
|
2207
|
-
|
|
2571
|
+
/**
|
|
2572
|
+
* Validate a request and resolve it to a single OFT pathway. No network calls —
|
|
2573
|
+
* everything here is config, arithmetic and encoding.
|
|
2574
|
+
*/
|
|
2575
|
+
plan(params, method) {
|
|
2576
|
+
const { fromChain, toChain, fromToken, toToken, amount, recipient, dstNativeDrop } = params;
|
|
2577
|
+
const recipientAddr = _nullishCoalesce(recipient, () => ( ZERO_ADDRESS));
|
|
2578
|
+
this.validateBridgeParams({ fromChain, toChain, amount, recipient: recipientAddr }, method);
|
|
2579
|
+
if (dstNativeDrop !== void 0 && dstNativeDrop < 0n) {
|
|
2580
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2581
|
+
"dstNativeDrop",
|
|
2582
|
+
dstNativeDrop,
|
|
2583
|
+
`${method}: dstNativeDrop must not be negative`
|
|
2584
|
+
);
|
|
2585
|
+
}
|
|
2586
|
+
const feeBufferBps = resolveFeeBuffer(params.feeBufferBps, method);
|
|
2587
|
+
const { src, dst, asset, srcToken, dstToken } = this.resolveRoute(
|
|
2588
|
+
fromChain,
|
|
2589
|
+
toChain,
|
|
2590
|
+
fromToken,
|
|
2591
|
+
toToken
|
|
2592
|
+
);
|
|
2593
|
+
if (params.fromDecimals !== void 0 && params.fromDecimals !== srcToken.decimals) {
|
|
2594
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2595
|
+
"fromDecimals",
|
|
2596
|
+
params.fromDecimals,
|
|
2597
|
+
`${method}: ${asset} has ${srcToken.decimals} decimals on "${fromChain}", not ${params.fromDecimals}. The native OFT route parses the amount with the token's own decimals; fromDecimals applies to LI.FI routes only.`
|
|
2598
|
+
);
|
|
2599
|
+
}
|
|
2600
|
+
const rpc = this.rpcFor(src);
|
|
2601
|
+
const chain = makeChain(src.id, rpc);
|
|
2208
2602
|
return {
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2603
|
+
src,
|
|
2604
|
+
dst,
|
|
2605
|
+
asset,
|
|
2606
|
+
srcToken,
|
|
2607
|
+
dstToken,
|
|
2608
|
+
oftAdapter: srcToken.oftAdapter,
|
|
2609
|
+
amountLD: _viem.parseUnits.call(void 0, String(amount), srcToken.decimals),
|
|
2610
|
+
recipient: recipientAddr,
|
|
2611
|
+
nativeDrop: _nullishCoalesce(dstNativeDrop, () => ( 0n)),
|
|
2612
|
+
rpc,
|
|
2613
|
+
feeBufferBps,
|
|
2614
|
+
chain,
|
|
2615
|
+
pc: _viem.createPublicClient.call(void 0, { chain, transport: _viem.http.call(void 0, rpc) })
|
|
2616
|
+
};
|
|
2617
|
+
}
|
|
2618
|
+
/**
|
|
2619
|
+
* Where `send` returns messaging fee it did not need. Defaults to the sender,
|
|
2620
|
+
* which is what a caller wants unless they are routing refunds somewhere of
|
|
2621
|
+
* their own — a backend paying the fee on a user's behalf, say.
|
|
2622
|
+
*/
|
|
2623
|
+
resolveRefundAddress(refundAddress, sender, method) {
|
|
2624
|
+
if (refundAddress === void 0) return sender;
|
|
2625
|
+
if (!_viem.isAddress.call(void 0, refundAddress)) {
|
|
2626
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2627
|
+
"refundAddress",
|
|
2628
|
+
refundAddress,
|
|
2629
|
+
`${method}: invalid refundAddress "${refundAddress}"`
|
|
2630
|
+
);
|
|
2631
|
+
}
|
|
2632
|
+
return refundAddress;
|
|
2633
|
+
}
|
|
2634
|
+
/** The address that will sign, or undefined when this service has no signer. */
|
|
2635
|
+
signerAddress() {
|
|
2636
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _77 => _77.config, 'access', _78 => _78.walletClient, 'optionalAccess', _79 => _79.account, 'optionalAccess', _80 => _80.address]), () => ( _optionalChain([this, 'access', _81 => _81.config, 'access', _82 => _82.account, 'optionalAccess', _83 => _83.address])));
|
|
2637
|
+
}
|
|
2638
|
+
/**
|
|
2639
|
+
* `SendParam` for one call. `minAmountLD` is the caller's slippage floor: 0 when
|
|
2640
|
+
* asking what a send would yield, and the quoted output when actually sending.
|
|
2641
|
+
*/
|
|
2642
|
+
buildSendParams(plan, minAmountLD) {
|
|
2643
|
+
return {
|
|
2644
|
+
dstEid: plan.dst.lzEid,
|
|
2645
|
+
to: _viem.padHex.call(void 0, plan.recipient, { dir: "left", size: 32 }),
|
|
2646
|
+
amountLD: plan.amountLD,
|
|
2647
|
+
minAmountLD,
|
|
2648
|
+
extraOptions: buildLzOptions(0n, plan.nativeDrop, plan.recipient),
|
|
2214
2649
|
composeMsg: "0x",
|
|
2215
2650
|
oftCmd: "0x"
|
|
2216
2651
|
};
|
|
@@ -2218,21 +2653,37 @@ var LayerZeroService = class {
|
|
|
2218
2653
|
};
|
|
2219
2654
|
|
|
2220
2655
|
// src/stable.ts
|
|
2221
|
-
function
|
|
2656
|
+
function isNativeOftRoute(fromChain, toChain, fromToken, toToken) {
|
|
2222
2657
|
const src = BRIDGE_CHAIN_CONFIGS[fromChain];
|
|
2223
2658
|
const dst = BRIDGE_CHAIN_CONFIGS[toChain];
|
|
2224
|
-
|
|
2659
|
+
if (!(src && dst)) return false;
|
|
2660
|
+
const asset = bridgeAssetFor(src, fromToken);
|
|
2661
|
+
if (!asset) return false;
|
|
2662
|
+
const srcToken = src.tokens[asset];
|
|
2663
|
+
const dstToken = dst.tokens[asset];
|
|
2664
|
+
return src.lzOutbound !== false && !!srcToken && srcToken.lzOutbound !== false && !!dstToken && dstToken.address.toLowerCase() === toToken.toLowerCase();
|
|
2225
2665
|
}
|
|
2226
2666
|
function selectBridge(params) {
|
|
2667
|
+
const selected = resolveBridge(params);
|
|
2668
|
+
if (selected === "lifi" && (_nullishCoalesce(params.dstNativeDrop, () => ( 0n))) > 0n) {
|
|
2669
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2670
|
+
"dstNativeDrop",
|
|
2671
|
+
params.dstNativeDrop,
|
|
2672
|
+
`bridge: dstNativeDrop is only supported on the native OFT route, and ${params.fromChain}\u2192${params.toChain} resolved to LI.FI`
|
|
2673
|
+
);
|
|
2674
|
+
}
|
|
2675
|
+
return selected;
|
|
2676
|
+
}
|
|
2677
|
+
function resolveBridge(params) {
|
|
2227
2678
|
const route = _nullishCoalesce(params.route, () => ( "auto"));
|
|
2228
|
-
if (route === "usdt0") return "
|
|
2679
|
+
if (route === "oft" || route === "usdt0") return "oft";
|
|
2229
2680
|
if (route === "lifi") return "lifi";
|
|
2230
|
-
return
|
|
2681
|
+
return isNativeOftRoute(
|
|
2231
2682
|
params.fromChain,
|
|
2232
2683
|
params.toChain,
|
|
2233
2684
|
params.fromToken,
|
|
2234
2685
|
params.toToken
|
|
2235
|
-
) ? "
|
|
2686
|
+
) ? "oft" : "lifi";
|
|
2236
2687
|
}
|
|
2237
2688
|
function validateTransferParams({
|
|
2238
2689
|
to,
|
|
@@ -2277,7 +2728,7 @@ async function resolveTokenDecimals(publicClient, token, tokenDecimals) {
|
|
|
2277
2728
|
abi: _viem.erc20Abi,
|
|
2278
2729
|
functionName: "decimals"
|
|
2279
2730
|
});
|
|
2280
|
-
} catch (
|
|
2731
|
+
} catch (e8) {
|
|
2281
2732
|
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2282
2733
|
"tokenDecimals",
|
|
2283
2734
|
void 0,
|
|
@@ -2311,6 +2762,7 @@ async function executeTokenTransfer(wc, publicClient, token, to, amount, tokenDe
|
|
|
2311
2762
|
function createStable({
|
|
2312
2763
|
network = "mainnet" /* Mainnet */,
|
|
2313
2764
|
rpc: rpcOverride,
|
|
2765
|
+
rpcOverrides,
|
|
2314
2766
|
account,
|
|
2315
2767
|
transport,
|
|
2316
2768
|
walletClient,
|
|
@@ -2324,7 +2776,7 @@ function createStable({
|
|
|
2324
2776
|
);
|
|
2325
2777
|
const signerConfig = { account, transport, walletClient };
|
|
2326
2778
|
const lifi = new LiFiService({ ...signerConfig, rpc, chainId: chain.id });
|
|
2327
|
-
const lz = new LayerZeroService(signerConfig);
|
|
2779
|
+
const lz = new LayerZeroService({ ...signerConfig, rpcOverrides });
|
|
2328
2780
|
const merkl = new MerklService({ ...signerConfig, rpc, chainId: chain.id, merklApiBase });
|
|
2329
2781
|
const morpho = earnConfig ? new MorphoService({
|
|
2330
2782
|
...signerConfig,
|
|
@@ -2349,7 +2801,7 @@ function createStable({
|
|
|
2349
2801
|
return morpho;
|
|
2350
2802
|
}
|
|
2351
2803
|
function requireSignerAddress() {
|
|
2352
|
-
const from = _nullishCoalesce(_optionalChain([walletClient, 'optionalAccess',
|
|
2804
|
+
const from = _nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _84 => _84.account, 'optionalAccess', _85 => _85.address]), () => ( _optionalChain([account, 'optionalAccess', _86 => _86.address])));
|
|
2353
2805
|
if (!from) {
|
|
2354
2806
|
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2355
2807
|
"signer",
|
|
@@ -2362,7 +2814,7 @@ function createStable({
|
|
|
2362
2814
|
async function transfer(params) {
|
|
2363
2815
|
validateTransferParams(params);
|
|
2364
2816
|
const { from, to, amount, token, tokenDecimals } = params;
|
|
2365
|
-
const acc = _nullishCoalesce(_nullishCoalesce(_optionalChain([walletClient, 'optionalAccess',
|
|
2817
|
+
const acc = _nullishCoalesce(_nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _87 => _87.account]), () => ( account)), () => ( from));
|
|
2366
2818
|
const wc = _nullishCoalesce(walletClient, () => ( _viem.createWalletClient.call(void 0, {
|
|
2367
2819
|
account: acc,
|
|
2368
2820
|
chain,
|
|
@@ -2414,8 +2866,20 @@ function createStable({
|
|
|
2414
2866
|
}
|
|
2415
2867
|
return {
|
|
2416
2868
|
transfer,
|
|
2417
|
-
|
|
2418
|
-
|
|
2869
|
+
// `async` so a rejected route (see selectBridge) surfaces as a rejected
|
|
2870
|
+
// promise like every other validation error, not a synchronous throw.
|
|
2871
|
+
quoteBridge: async (params) => selectBridge(params) === "oft" ? lz.quoteBridge(params) : lifi.quoteBridge(params),
|
|
2872
|
+
bridge: async (params) => selectBridge(params) === "oft" ? lz.bridge(params) : lifi.bridge(params),
|
|
2873
|
+
prepareBridgeCalldata: async (params) => {
|
|
2874
|
+
if (selectBridge(params) !== "oft") {
|
|
2875
|
+
throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
|
|
2876
|
+
"route",
|
|
2877
|
+
_nullishCoalesce(params.route, () => ( "auto")),
|
|
2878
|
+
`prepareBridgeCalldata: only the native OFT route can be built unsigned, and ${params.fromChain}\u2192${params.toChain} resolved to LI.FI`
|
|
2879
|
+
);
|
|
2880
|
+
}
|
|
2881
|
+
return lz.prepareBridgeCalldata(params);
|
|
2882
|
+
},
|
|
2419
2883
|
estimateBridgeTime: (params) => lz.estimateBridgeTime(params),
|
|
2420
2884
|
trackBridge: (srcTxHash) => lz.trackBridge(srcTxHash),
|
|
2421
2885
|
quoteSwap: (params) => lifi.quoteSwap(params),
|
|
@@ -2483,4 +2947,7 @@ function createStableReader(config) {
|
|
|
2483
2947
|
|
|
2484
2948
|
|
|
2485
2949
|
|
|
2486
|
-
|
|
2950
|
+
|
|
2951
|
+
|
|
2952
|
+
|
|
2953
|
+
exports.BRIDGE_CHAIN_CONFIGS = BRIDGE_CHAIN_CONFIGS; exports.CHAIN_CONFIGS = CHAIN_CONFIGS; exports.Chain = Chain; exports.ERC3009_ABI = _chunkQQ26UI3Fcjs.ERC3009_ABI; exports.Network = Network; exports.OFT_ADAPTER_ABI = OFT_ADAPTER_ABI; exports.STABLE_USDT_ADDRESS = _chunkQQ26UI3Fcjs.STABLE_USDT_ADDRESS; exports.STABLE_VAULT_ADDRESS = _chunkQQ26UI3Fcjs.STABLE_VAULT_ADDRESS; exports.StableBulkError = _chunkQQ26UI3Fcjs.StableBulkError; exports.StableError = _chunkQQ26UI3Fcjs.StableError; exports.StableNetworkError = _chunkQQ26UI3Fcjs.StableNetworkError; exports.StableQuoteError = _chunkQQ26UI3Fcjs.StableQuoteError; exports.StableTransactionError = _chunkQQ26UI3Fcjs.StableTransactionError; exports.StableValidationError = _chunkQQ26UI3Fcjs.StableValidationError; exports.bridgeAssetFor = bridgeAssetFor; exports.buildLzOptions = buildLzOptions; exports.cancelAuthorization = _chunkQQ26UI3Fcjs.cancelAuthorization; exports.clearBridgeEstimateCache = clearBridgeEstimateCache; exports.createStable = createStable; exports.createStableReader = createStableReader; exports.erc3009Actions = _chunkQQ26UI3Fcjs.erc3009Actions; exports.getAuthorizationState = _chunkQQ26UI3Fcjs.getAuthorizationState; exports.getAuthorizationUsage = _chunkQQ26UI3Fcjs.getAuthorizationUsage; exports.prepareTransferWithAuthorization = _chunkQQ26UI3Fcjs.prepareTransferWithAuthorization; exports.receiveWithAuthorization = _chunkQQ26UI3Fcjs.receiveWithAuthorization; exports.signReceiveAuthorization = _chunkQQ26UI3Fcjs.signReceiveAuthorization; exports.signTransferAuthorization = _chunkQQ26UI3Fcjs.signTransferAuthorization; exports.transferWithAuthorization = _chunkQQ26UI3Fcjs.transferWithAuthorization; exports.verifyAuthorization = _chunkQQ26UI3Fcjs.verifyAuthorization;
|