@stablechain/sdk 1.0.3 → 1.0.4

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 CHANGED
@@ -807,19 +807,19 @@ var MorphoService = class {
807
807
 
808
808
 
809
809
  // src/types.ts
810
- var Chain = /* @__PURE__ */ ((Chain2) => {
811
- Chain2["Sepolia"] = "sepolia";
812
- Chain2["StableTestnet"] = "stable-testnet";
813
- Chain2["Stable"] = "stable";
814
- Chain2["Ethereum"] = "ethereum";
815
- Chain2["Arbitrum"] = "arbitrum";
816
- Chain2["Ink"] = "ink";
817
- Chain2["Bera"] = "bera";
818
- Chain2["MegaETH"] = "megaeth";
819
- Chain2["Base"] = "base";
820
- Chain2["BSC"] = "bsc";
821
- Chain2["HyperEVM"] = "hyperevm";
822
- return Chain2;
810
+ var Chain = /* @__PURE__ */ ((Chain3) => {
811
+ Chain3["Sepolia"] = "sepolia";
812
+ Chain3["StableTestnet"] = "stable-testnet";
813
+ Chain3["Stable"] = "stable";
814
+ Chain3["Ethereum"] = "ethereum";
815
+ Chain3["Arbitrum"] = "arbitrum";
816
+ Chain3["Ink"] = "ink";
817
+ Chain3["Bera"] = "bera";
818
+ Chain3["MegaETH"] = "megaeth";
819
+ Chain3["Base"] = "base";
820
+ Chain3["BSC"] = "bsc";
821
+ Chain3["HyperEVM"] = "hyperevm";
822
+ return Chain3;
823
823
  })(Chain || {});
824
824
  var Network = /* @__PURE__ */ ((Network2) => {
825
825
  Network2["Mainnet"] = "mainnet";
@@ -1723,7 +1723,304 @@ function isLiFiQuoteShape(v) {
1723
1723
  return isObject(tx) && typeof tx.to === "string" && typeof tx.data === "string" && typeof tx.chainId === "number" && isObject(est) && typeof est.fromAmount === "string" && typeof est.toAmount === "string" && isObject(act) && isObject(act.fromToken) && isObject(act.toToken);
1724
1724
  }
1725
1725
 
1726
+ // src/services/layerzero.ts
1727
+
1728
+
1729
+
1730
+
1731
+
1732
+
1733
+
1734
+
1735
+
1736
+
1737
+
1738
+ var C = CHAIN_CONFIGS;
1739
+ var BRIDGE_CHAIN_CONFIGS = {
1740
+ // ─── Testnet ───────────────────────────────────────────────────────────────
1741
+ ["sepolia" /* Sepolia */]: { ...C["sepolia" /* Sepolia */], lzEid: 40161, oftAdapter: "0xc099cD946d5efCC35A99D64E808c1430cEf08126" },
1742
+ ["stable-testnet" /* StableTestnet */]: { ...C["stable-testnet" /* StableTestnet */], lzEid: 40374, oftAdapter: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736" },
1743
+ // ─── Mainnet ──────────────────────────────────────────────────────────────
1744
+ ["stable" /* Stable */]: { ...C["stable" /* Stable */], lzEid: 30396, oftAdapter: "0xedaba024be4d87974d5aB11C6Dd586963CcCB027" },
1745
+ ["ethereum" /* Ethereum */]: { ...C["ethereum" /* Ethereum */], lzEid: 30101, oftAdapter: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee" },
1746
+ ["arbitrum" /* Arbitrum */]: { ...C["arbitrum" /* Arbitrum */], lzEid: 30110, oftAdapter: "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92" },
1747
+ ["ink" /* Ink */]: { ...C["ink" /* Ink */], lzEid: 30339, oftAdapter: "0x1cB6De532588fCA4a21B7209DE7C456AF8434A65" },
1748
+ ["bera" /* Bera */]: { ...C["bera" /* Bera */], lzEid: 30362, oftAdapter: "0x3Dc96399109df5ceb2C226664A086140bD0379cB" },
1749
+ ["megaeth" /* MegaETH */]: { ...C["megaeth" /* MegaETH */], lzEid: 30398, oftAdapter: "0x9151434b16b9763660705744891fa906f660ecc5" },
1750
+ ["hyperevm" /* HyperEVM */]: { ...C["hyperevm" /* HyperEVM */], lzEid: 30367, oftAdapter: "0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98" }
1751
+ };
1752
+ var OFT_ADAPTER_ABI = [
1753
+ {
1754
+ name: "quoteSend",
1755
+ type: "function",
1756
+ inputs: [
1757
+ {
1758
+ name: "_sendParam",
1759
+ type: "tuple",
1760
+ components: [
1761
+ { name: "dstEid", type: "uint32" },
1762
+ { name: "to", type: "bytes32" },
1763
+ { name: "amountLD", type: "uint256" },
1764
+ { name: "minAmountLD", type: "uint256" },
1765
+ { name: "extraOptions", type: "bytes" },
1766
+ { name: "composeMsg", type: "bytes" },
1767
+ { name: "oftCmd", type: "bytes" }
1768
+ ]
1769
+ },
1770
+ { name: "_payInLzToken", type: "bool" }
1771
+ ],
1772
+ outputs: [
1773
+ {
1774
+ name: "msgFee",
1775
+ type: "tuple",
1776
+ components: [
1777
+ { name: "nativeFee", type: "uint256" },
1778
+ { name: "lzTokenFee", type: "uint256" }
1779
+ ]
1780
+ }
1781
+ ],
1782
+ stateMutability: "view"
1783
+ },
1784
+ {
1785
+ name: "send",
1786
+ type: "function",
1787
+ inputs: [
1788
+ {
1789
+ name: "_sendParam",
1790
+ type: "tuple",
1791
+ components: [
1792
+ { name: "dstEid", type: "uint32" },
1793
+ { name: "to", type: "bytes32" },
1794
+ { name: "amountLD", type: "uint256" },
1795
+ { name: "minAmountLD", type: "uint256" },
1796
+ { name: "extraOptions", type: "bytes" },
1797
+ { name: "composeMsg", type: "bytes" },
1798
+ { name: "oftCmd", type: "bytes" }
1799
+ ]
1800
+ },
1801
+ {
1802
+ name: "_fee",
1803
+ type: "tuple",
1804
+ components: [
1805
+ { name: "nativeFee", type: "uint256" },
1806
+ { name: "lzTokenFee", type: "uint256" }
1807
+ ]
1808
+ },
1809
+ { name: "_refundAddress", type: "address" }
1810
+ ],
1811
+ outputs: [],
1812
+ stateMutability: "payable"
1813
+ }
1814
+ ];
1815
+ function buildLzOptions(gasLimit = 0n) {
1816
+ return _viem.concat.call(void 0, [
1817
+ _viem.numberToHex.call(void 0, 3, { size: 2 }),
1818
+ // TYPE_3 header
1819
+ _viem.numberToHex.call(void 0, 1, { size: 1 }),
1820
+ // Executor worker ID
1821
+ _viem.numberToHex.call(void 0, 17, { size: 2 }),
1822
+ // option payload length = 17 bytes
1823
+ _viem.numberToHex.call(void 0, 1, { size: 1 }),
1824
+ // LzReceive option type
1825
+ _viem.numberToHex.call(void 0, gasLimit, { size: 16 })
1826
+ // gas limit as uint128
1827
+ ]);
1828
+ }
1829
+ var LayerZeroService = class {
1830
+ constructor(config) {
1831
+ this.config = config;
1832
+ }
1833
+ async quoteBridge({ fromChain, toChain, fromToken, toToken, amount, recipient }) {
1834
+ const recipientAddr = _nullishCoalesce(recipient, () => ( "0x0000000000000000000000000000000000000000"));
1835
+ this.validateBridgeParams({ fromChain, toChain, amount, recipient: recipientAddr }, "quoteBridge");
1836
+ const { src, dst } = this.resolveChains(fromChain, toChain, fromToken, toToken);
1837
+ const oftAdapter = src.oftAdapter;
1838
+ const amountLD = _viem.parseUnits.call(void 0, String(amount), src.decimals);
1839
+ try {
1840
+ const { nativeFee, lzTokenFee } = await _viem.createPublicClient.call(void 0, {
1841
+ chain: makeChain(src.id, src.rpc),
1842
+ transport: _viem.http.call(void 0, src.rpc)
1843
+ }).readContract({
1844
+ address: oftAdapter,
1845
+ abi: OFT_ADAPTER_ABI,
1846
+ functionName: "quoteSend",
1847
+ args: [this.buildSendParams(dst, amountLD, recipientAddr), false]
1848
+ });
1849
+ return { nativeFee, lzTokenFee, toAmount: amount };
1850
+ } catch (err) {
1851
+ throw new StableQuoteError({
1852
+ provider: "layerzero",
1853
+ shortMessage: "quoteBridge: quoteSend call failed",
1854
+ cause: err
1855
+ });
1856
+ }
1857
+ }
1858
+ async bridge({ fromChain, toChain, fromToken, toToken, amount, recipient, quote }) {
1859
+ const from = _nullishCoalesce(_optionalChain([this, 'access', _37 => _37.config, 'access', _38 => _38.walletClient, 'optionalAccess', _39 => _39.account, 'optionalAccess', _40 => _40.address]), () => ( _optionalChain([this, 'access', _41 => _41.config, 'access', _42 => _42.account, 'optionalAccess', _43 => _43.address])));
1860
+ if (!from) {
1861
+ throw new StableValidationError(
1862
+ "signer",
1863
+ void 0,
1864
+ "bridge: requires a signer \u2014 set walletClient or account in StableConfig"
1865
+ );
1866
+ }
1867
+ const recipientAddr = _nullishCoalesce(recipient, () => ( from));
1868
+ this.validateBridgeParams({ fromChain, toChain, amount, recipient: recipientAddr }, "bridge");
1869
+ const { src, dst } = this.resolveChains(fromChain, toChain, fromToken, toToken);
1870
+ const oftAdapter = src.oftAdapter;
1871
+ const srcChain = makeChain(src.id, src.rpc);
1872
+ const wc = _nullishCoalesce(this.config.walletClient, () => ( _viem.createWalletClient.call(void 0, {
1873
+ account: this.config.account,
1874
+ chain: srcChain,
1875
+ transport: _nullishCoalesce(this.config.transport, () => ( _viem.http.call(void 0, src.rpc)))
1876
+ })));
1877
+ const pc = _viem.createPublicClient.call(void 0, { chain: srcChain, transport: _viem.http.call(void 0, src.rpc) });
1878
+ try {
1879
+ await wc.switchChain({ id: src.id });
1880
+ } catch (err) {
1881
+ throw new StableTransactionError({
1882
+ phase: "switch_chain",
1883
+ shortMessage: `bridge: wallet rejected or failed to switch to chain ${src.id}`,
1884
+ chainId: src.id,
1885
+ cause: err
1886
+ });
1887
+ }
1888
+ const amountLD = _viem.parseUnits.call(void 0, String(amount), src.decimals);
1889
+ const sendParams = this.buildSendParams(dst, amountLD, recipientAddr);
1890
+ const lzFee = _optionalChain([quote, 'optionalAccess', _44 => _44.nativeFee]) !== void 0 && _optionalChain([quote, 'optionalAccess', _45 => _45.lzTokenFee]) !== void 0 ? { nativeFee: quote.nativeFee, lzTokenFee: quote.lzTokenFee } : await this.quoteBridge({ fromChain, toChain, fromToken, toToken, amount, recipient: recipientAddr });
1891
+ const { nativeFee = 0n, lzTokenFee = 0n } = lzFee;
1892
+ const allowance = await pc.readContract({
1893
+ address: src.usdt,
1894
+ abi: _viem.erc20Abi,
1895
+ functionName: "allowance",
1896
+ args: [from, oftAdapter]
1897
+ });
1898
+ if (allowance < amountLD) {
1899
+ let approveHash;
1900
+ try {
1901
+ approveHash = await wc.writeContract({
1902
+ address: src.usdt,
1903
+ abi: _viem.erc20Abi,
1904
+ functionName: "approve",
1905
+ args: [oftAdapter, amountLD],
1906
+ account: wc.account,
1907
+ chain: srcChain
1908
+ });
1909
+ } catch (err) {
1910
+ throw new StableTransactionError({
1911
+ phase: "approve",
1912
+ shortMessage: "bridge: USDT0 approve failed",
1913
+ chainId: src.id,
1914
+ cause: err
1915
+ });
1916
+ }
1917
+ const approveReceipt = await pc.waitForTransactionReceipt({ hash: approveHash });
1918
+ if (approveReceipt.status === "reverted") {
1919
+ throw new StableTransactionError({
1920
+ phase: "approve",
1921
+ shortMessage: "bridge: USDT0 approve reverted on-chain",
1922
+ txHash: approveReceipt.transactionHash,
1923
+ chainId: src.id
1924
+ });
1925
+ }
1926
+ }
1927
+ try {
1928
+ const hash = await wc.writeContract({
1929
+ address: oftAdapter,
1930
+ abi: OFT_ADAPTER_ABI,
1931
+ functionName: "send",
1932
+ args: [sendParams, { nativeFee, lzTokenFee }, from],
1933
+ value: nativeFee,
1934
+ account: wc.account,
1935
+ chain: srcChain
1936
+ });
1937
+ return { txHash: hash, toAmount: amount };
1938
+ } catch (err) {
1939
+ throw new StableTransactionError({
1940
+ phase: "send",
1941
+ shortMessage: "bridge: OFT send failed",
1942
+ chainId: src.id,
1943
+ cause: err
1944
+ });
1945
+ }
1946
+ }
1947
+ validateBridgeParams(params, method) {
1948
+ if (!_viem.isAddress.call(void 0, params.recipient)) {
1949
+ throw new StableValidationError(
1950
+ "recipient",
1951
+ params.recipient,
1952
+ `${method}: invalid recipient address "${params.recipient}"`
1953
+ );
1954
+ }
1955
+ if (!Number.isFinite(params.amount) || params.amount <= 0) {
1956
+ throw new StableValidationError(
1957
+ "amount",
1958
+ params.amount,
1959
+ `${method}: amount must be a finite positive number`
1960
+ );
1961
+ }
1962
+ if (params.fromChain === params.toChain) {
1963
+ throw new StableValidationError(
1964
+ "toChain",
1965
+ params.toChain,
1966
+ `${method}: fromChain and toChain must differ`
1967
+ );
1968
+ }
1969
+ }
1970
+ resolveChains(fromChain, toChain, fromToken, toToken) {
1971
+ const src = BRIDGE_CHAIN_CONFIGS[fromChain];
1972
+ const dst = BRIDGE_CHAIN_CONFIGS[toChain];
1973
+ if (!src) throw new StableValidationError("fromChain", fromChain, `Unsupported source chain: "${fromChain}"`);
1974
+ if (!dst) throw new StableValidationError("toChain", toChain, `Unsupported destination chain: "${toChain}"`);
1975
+ if (!src.oftAdapter) {
1976
+ throw new StableValidationError("fromChain", fromChain, `No OFT adapter configured for "${fromChain}"`);
1977
+ }
1978
+ if (fromToken.toLowerCase() !== src.usdt.toLowerCase()) {
1979
+ throw new StableValidationError(
1980
+ "fromToken",
1981
+ fromToken,
1982
+ `USDT0 bridge only moves USDT0 \u2014 fromToken must be ${src.usdt} on "${fromChain}", got "${fromToken}". Use route "lifi" to bridge other tokens.`
1983
+ );
1984
+ }
1985
+ if (toToken.toLowerCase() !== dst.usdt.toLowerCase()) {
1986
+ throw new StableValidationError(
1987
+ "toToken",
1988
+ toToken,
1989
+ `USDT0 bridge only moves USDT0 \u2014 toToken must be ${dst.usdt} on "${toChain}", got "${toToken}". Use route "lifi" to bridge other tokens.`
1990
+ );
1991
+ }
1992
+ return { src, dst };
1993
+ }
1994
+ buildSendParams(dst, amountLD, recipient) {
1995
+ return {
1996
+ dstEid: dst.lzEid,
1997
+ to: _viem.padHex.call(void 0, recipient, { dir: "left", size: 32 }),
1998
+ amountLD,
1999
+ minAmountLD: amountLD,
2000
+ extraOptions: buildLzOptions(),
2001
+ composeMsg: "0x",
2002
+ oftCmd: "0x"
2003
+ };
2004
+ }
2005
+ };
2006
+
1726
2007
  // src/stable.ts
2008
+ function isUsdt0Route(fromChain, toChain, fromToken, toToken) {
2009
+ const src = BRIDGE_CHAIN_CONFIGS[fromChain];
2010
+ const dst = BRIDGE_CHAIN_CONFIGS[toChain];
2011
+ return !!src && !!dst && !!src.oftAdapter && src.lzOutbound !== false && src.usdt.toLowerCase() === fromToken.toLowerCase() && dst.usdt.toLowerCase() === toToken.toLowerCase();
2012
+ }
2013
+ function selectBridge(params) {
2014
+ const route = _nullishCoalesce(params.route, () => ( "auto"));
2015
+ if (route === "usdt0") return "usdt0";
2016
+ if (route === "lifi") return "lifi";
2017
+ return isUsdt0Route(
2018
+ params.fromChain,
2019
+ params.toChain,
2020
+ params.fromToken,
2021
+ params.toToken
2022
+ ) ? "usdt0" : "lifi";
2023
+ }
1727
2024
  function validateTransferParams({
1728
2025
  to,
1729
2026
  amount,
@@ -1814,6 +2111,7 @@ function createStable({
1814
2111
  );
1815
2112
  const signerConfig = { account, transport, walletClient };
1816
2113
  const lifi = new LiFiService({ ...signerConfig, rpc, chainId: chain.id });
2114
+ const lz = new LayerZeroService(signerConfig);
1817
2115
  const merkl = new MerklService({ ...signerConfig, rpc, chainId: chain.id, merklApiBase });
1818
2116
  const morpho = earnConfig ? new MorphoService({
1819
2117
  ...signerConfig,
@@ -1832,7 +2130,7 @@ function createStable({
1832
2130
  return morpho;
1833
2131
  }
1834
2132
  function requireSignerAddress() {
1835
- const from = _nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _37 => _37.account, 'optionalAccess', _38 => _38.address]), () => ( _optionalChain([account, 'optionalAccess', _39 => _39.address])));
2133
+ const from = _nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _46 => _46.account, 'optionalAccess', _47 => _47.address]), () => ( _optionalChain([account, 'optionalAccess', _48 => _48.address])));
1836
2134
  if (!from) {
1837
2135
  throw new StableValidationError(
1838
2136
  "signer",
@@ -1845,7 +2143,7 @@ function createStable({
1845
2143
  async function transfer(params) {
1846
2144
  validateTransferParams(params);
1847
2145
  const { from, to, amount, token, tokenDecimals } = params;
1848
- const acc = _nullishCoalesce(_nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _40 => _40.account]), () => ( account)), () => ( from));
2146
+ const acc = _nullishCoalesce(_nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _49 => _49.account]), () => ( account)), () => ( from));
1849
2147
  const wc = _nullishCoalesce(walletClient, () => ( _viem.createWalletClient.call(void 0, {
1850
2148
  account: acc,
1851
2149
  chain,
@@ -1897,8 +2195,8 @@ function createStable({
1897
2195
  }
1898
2196
  return {
1899
2197
  transfer,
1900
- quoteBridge: (params) => lifi.quoteBridge(params),
1901
- bridge: (params) => lifi.bridge(params),
2198
+ quoteBridge: (params) => selectBridge(params) === "usdt0" ? lz.quoteBridge(params) : lifi.quoteBridge(params),
2199
+ bridge: (params) => selectBridge(params) === "usdt0" ? lz.bridge(params) : lifi.bridge(params),
1902
2200
  quoteSwap: (params) => lifi.quoteSwap(params),
1903
2201
  swap: (params) => lifi.swap(params),
1904
2202
  earn: {
@@ -1954,4 +2252,5 @@ var STABLE_VAULT_ADDRESS = "0xb7Df8db22A5DBBFA9ebeb94b3910aec6a4f05c08";
1954
2252
 
1955
2253
 
1956
2254
 
1957
- exports.CHAIN_CONFIGS = CHAIN_CONFIGS; exports.Chain = Chain; exports.Network = Network; exports.STABLE_USDT_ADDRESS = STABLE_USDT_ADDRESS; exports.STABLE_VAULT_ADDRESS = STABLE_VAULT_ADDRESS; exports.StableBulkError = StableBulkError; exports.StableError = StableError; exports.StableNetworkError = StableNetworkError; exports.StableQuoteError = StableQuoteError; exports.StableTransactionError = StableTransactionError; exports.StableValidationError = StableValidationError; exports.createStable = createStable; exports.createStableReader = createStableReader;
2255
+
2256
+ exports.BRIDGE_CHAIN_CONFIGS = BRIDGE_CHAIN_CONFIGS; exports.CHAIN_CONFIGS = CHAIN_CONFIGS; exports.Chain = Chain; exports.Network = Network; exports.STABLE_USDT_ADDRESS = STABLE_USDT_ADDRESS; exports.STABLE_VAULT_ADDRESS = STABLE_VAULT_ADDRESS; exports.StableBulkError = StableBulkError; exports.StableError = StableError; exports.StableNetworkError = StableNetworkError; exports.StableQuoteError = StableQuoteError; exports.StableTransactionError = StableTransactionError; exports.StableValidationError = StableValidationError; exports.createStable = createStable; exports.createStableReader = createStableReader;
package/dist/index.d.cts CHANGED
@@ -95,7 +95,20 @@ declare enum Network {
95
95
  interface BridgeQuote {
96
96
  /** Estimated output amount on the destination chain */
97
97
  toAmount?: number;
98
+ /** LayerZero native messaging fee (wei) — only present for USDT0→USDT0 (OFT) routes */
99
+ nativeFee?: bigint;
100
+ /** LayerZero fee paid in LZ token (wei) — only present for USDT0→USDT0 (OFT) routes */
101
+ lzTokenFee?: bigint;
98
102
  }
103
+ /**
104
+ * Bridge route selection:
105
+ * - `"usdt0"` — force the USDT0 LayerZero OFT path (no protocol fee, just gas + LZ
106
+ * messaging fee; slower). Throws if the chain pair has no USDT0 adapter.
107
+ * - `"lifi"` — force the LI.FI aggregator path (fast, charges a fee).
108
+ * - `"auto"` — use USDT0 when both chains support it and tokens match, else LI.FI.
109
+ * This is the default.
110
+ */
111
+ type BridgeRoute = "auto" | "usdt0" | "lifi";
99
112
  interface BridgeParams {
100
113
  fromChain: Chain;
101
114
  toChain: Chain;
@@ -108,6 +121,11 @@ interface BridgeParams {
108
121
  fromDecimals?: number;
109
122
  /** Recipient address — defaults to the signer */
110
123
  recipient?: string;
124
+ /**
125
+ * Which bridge to use. Defaults to "auto" (USDT0 OFT when available, else LI.FI).
126
+ * See {@link BridgeRoute}.
127
+ */
128
+ route?: BridgeRoute;
111
129
  /** Pre-fetched quote from quoteBridge() — skips the quote fetch when passed to bridge() */
112
130
  quote?: BridgeQuote;
113
131
  }
@@ -395,6 +413,15 @@ interface ChainConfig {
395
413
  }
396
414
  declare const CHAIN_CONFIGS: Partial<Record<Chain, ChainConfig>>;
397
415
 
416
+ interface BridgeChainConfig extends ChainConfig {
417
+ lzEid: number;
418
+ /** Only set on source chains that have an OFT Adapter deployed */
419
+ oftAdapter?: Address;
420
+ /** False when the OFT adapter exists but has no outbound send pathways configured */
421
+ lzOutbound?: boolean;
422
+ }
423
+ declare const BRIDGE_CHAIN_CONFIGS: Partial<Record<Chain, BridgeChainConfig>>;
424
+
398
425
  declare const STABLE_USDT_ADDRESS: Address;
399
426
  declare const STABLE_VAULT_ADDRESS: Address;
400
427
 
@@ -455,4 +482,4 @@ declare class StableBulkError extends StableError {
455
482
  });
456
483
  }
457
484
 
458
- export { type BridgeParams, type BridgeQuote, type BulkDepositOptions, type BulkEarnResult, type BulkEarnResultItem, type BulkWithdrawOptions, CHAIN_CONFIGS, Chain, type ChainConfig, type EarnConfig, type EarnDepositCalldata, type EarnDepositParams, type EarnRedeemParams, type EarnResult, type EarnWithdrawCalldata, type EarnWithdrawParams, type ForceDeallocation, type ForceRedeemParams, type ForceWithdrawParams, type MerklClaimCalldata, type MerklClaimResult, type MerklReward, type MerklRewardToken, type MerklRewardsResult, Network, type OperationResult, STABLE_USDT_ADDRESS, STABLE_VAULT_ADDRESS, StableBulkError, type StableClient, type StableConfig, StableError, StableNetworkError, StableQuoteError, type StableReader, type StableReaderConfig, StableTransactionError, StableValidationError, type SwapParams, type SwapQuote, type TransferParams, type VaultPosition, type VaultYield, type VaultYieldReward, type WithdrawStatus, type YieldPreview, createStable, createStableReader };
485
+ export { BRIDGE_CHAIN_CONFIGS, type BridgeChainConfig, type BridgeParams, type BridgeQuote, type BridgeRoute, type BulkDepositOptions, type BulkEarnResult, type BulkEarnResultItem, type BulkWithdrawOptions, CHAIN_CONFIGS, Chain, type ChainConfig, type EarnConfig, type EarnDepositCalldata, type EarnDepositParams, type EarnRedeemParams, type EarnResult, type EarnWithdrawCalldata, type EarnWithdrawParams, type ForceDeallocation, type ForceRedeemParams, type ForceWithdrawParams, type MerklClaimCalldata, type MerklClaimResult, type MerklReward, type MerklRewardToken, type MerklRewardsResult, Network, type OperationResult, STABLE_USDT_ADDRESS, STABLE_VAULT_ADDRESS, StableBulkError, type StableClient, type StableConfig, StableError, StableNetworkError, StableQuoteError, type StableReader, type StableReaderConfig, StableTransactionError, StableValidationError, type SwapParams, type SwapQuote, type TransferParams, type VaultPosition, type VaultYield, type VaultYieldReward, type WithdrawStatus, type YieldPreview, createStable, createStableReader };
package/dist/index.d.ts CHANGED
@@ -95,7 +95,20 @@ declare enum Network {
95
95
  interface BridgeQuote {
96
96
  /** Estimated output amount on the destination chain */
97
97
  toAmount?: number;
98
+ /** LayerZero native messaging fee (wei) — only present for USDT0→USDT0 (OFT) routes */
99
+ nativeFee?: bigint;
100
+ /** LayerZero fee paid in LZ token (wei) — only present for USDT0→USDT0 (OFT) routes */
101
+ lzTokenFee?: bigint;
98
102
  }
103
+ /**
104
+ * Bridge route selection:
105
+ * - `"usdt0"` — force the USDT0 LayerZero OFT path (no protocol fee, just gas + LZ
106
+ * messaging fee; slower). Throws if the chain pair has no USDT0 adapter.
107
+ * - `"lifi"` — force the LI.FI aggregator path (fast, charges a fee).
108
+ * - `"auto"` — use USDT0 when both chains support it and tokens match, else LI.FI.
109
+ * This is the default.
110
+ */
111
+ type BridgeRoute = "auto" | "usdt0" | "lifi";
99
112
  interface BridgeParams {
100
113
  fromChain: Chain;
101
114
  toChain: Chain;
@@ -108,6 +121,11 @@ interface BridgeParams {
108
121
  fromDecimals?: number;
109
122
  /** Recipient address — defaults to the signer */
110
123
  recipient?: string;
124
+ /**
125
+ * Which bridge to use. Defaults to "auto" (USDT0 OFT when available, else LI.FI).
126
+ * See {@link BridgeRoute}.
127
+ */
128
+ route?: BridgeRoute;
111
129
  /** Pre-fetched quote from quoteBridge() — skips the quote fetch when passed to bridge() */
112
130
  quote?: BridgeQuote;
113
131
  }
@@ -395,6 +413,15 @@ interface ChainConfig {
395
413
  }
396
414
  declare const CHAIN_CONFIGS: Partial<Record<Chain, ChainConfig>>;
397
415
 
416
+ interface BridgeChainConfig extends ChainConfig {
417
+ lzEid: number;
418
+ /** Only set on source chains that have an OFT Adapter deployed */
419
+ oftAdapter?: Address;
420
+ /** False when the OFT adapter exists but has no outbound send pathways configured */
421
+ lzOutbound?: boolean;
422
+ }
423
+ declare const BRIDGE_CHAIN_CONFIGS: Partial<Record<Chain, BridgeChainConfig>>;
424
+
398
425
  declare const STABLE_USDT_ADDRESS: Address;
399
426
  declare const STABLE_VAULT_ADDRESS: Address;
400
427
 
@@ -455,4 +482,4 @@ declare class StableBulkError extends StableError {
455
482
  });
456
483
  }
457
484
 
458
- export { type BridgeParams, type BridgeQuote, type BulkDepositOptions, type BulkEarnResult, type BulkEarnResultItem, type BulkWithdrawOptions, CHAIN_CONFIGS, Chain, type ChainConfig, type EarnConfig, type EarnDepositCalldata, type EarnDepositParams, type EarnRedeemParams, type EarnResult, type EarnWithdrawCalldata, type EarnWithdrawParams, type ForceDeallocation, type ForceRedeemParams, type ForceWithdrawParams, type MerklClaimCalldata, type MerklClaimResult, type MerklReward, type MerklRewardToken, type MerklRewardsResult, Network, type OperationResult, STABLE_USDT_ADDRESS, STABLE_VAULT_ADDRESS, StableBulkError, type StableClient, type StableConfig, StableError, StableNetworkError, StableQuoteError, type StableReader, type StableReaderConfig, StableTransactionError, StableValidationError, type SwapParams, type SwapQuote, type TransferParams, type VaultPosition, type VaultYield, type VaultYieldReward, type WithdrawStatus, type YieldPreview, createStable, createStableReader };
485
+ export { BRIDGE_CHAIN_CONFIGS, type BridgeChainConfig, type BridgeParams, type BridgeQuote, type BridgeRoute, type BulkDepositOptions, type BulkEarnResult, type BulkEarnResultItem, type BulkWithdrawOptions, CHAIN_CONFIGS, Chain, type ChainConfig, type EarnConfig, type EarnDepositCalldata, type EarnDepositParams, type EarnRedeemParams, type EarnResult, type EarnWithdrawCalldata, type EarnWithdrawParams, type ForceDeallocation, type ForceRedeemParams, type ForceWithdrawParams, type MerklClaimCalldata, type MerklClaimResult, type MerklReward, type MerklRewardToken, type MerklRewardsResult, Network, type OperationResult, STABLE_USDT_ADDRESS, STABLE_VAULT_ADDRESS, StableBulkError, type StableClient, type StableConfig, StableError, StableNetworkError, StableQuoteError, type StableReader, type StableReaderConfig, StableTransactionError, StableValidationError, type SwapParams, type SwapQuote, type TransferParams, type VaultPosition, type VaultYield, type VaultYieldReward, type WithdrawStatus, type YieldPreview, createStable, createStableReader };
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // src/stable.ts
2
2
  import {
3
- http as http5,
4
- createPublicClient as createPublicClient5,
5
- createWalletClient as createWalletClient4,
6
- erc20Abi as erc20Abi4,
7
- isAddress as isAddress4,
8
- parseUnits as parseUnits4
3
+ http as http6,
4
+ createPublicClient as createPublicClient6,
5
+ createWalletClient as createWalletClient5,
6
+ erc20Abi as erc20Abi5,
7
+ isAddress as isAddress5,
8
+ parseUnits as parseUnits5
9
9
  } from "viem";
10
10
  import { stable as stableMainnet2, stableTestnet as stableTestnet2 } from "viem/chains";
11
11
 
@@ -807,19 +807,19 @@ import {
807
807
  import { stable as stableMainnet, stableTestnet } from "viem/chains";
808
808
 
809
809
  // src/types.ts
810
- var Chain = /* @__PURE__ */ ((Chain2) => {
811
- Chain2["Sepolia"] = "sepolia";
812
- Chain2["StableTestnet"] = "stable-testnet";
813
- Chain2["Stable"] = "stable";
814
- Chain2["Ethereum"] = "ethereum";
815
- Chain2["Arbitrum"] = "arbitrum";
816
- Chain2["Ink"] = "ink";
817
- Chain2["Bera"] = "bera";
818
- Chain2["MegaETH"] = "megaeth";
819
- Chain2["Base"] = "base";
820
- Chain2["BSC"] = "bsc";
821
- Chain2["HyperEVM"] = "hyperevm";
822
- return Chain2;
810
+ var Chain = /* @__PURE__ */ ((Chain3) => {
811
+ Chain3["Sepolia"] = "sepolia";
812
+ Chain3["StableTestnet"] = "stable-testnet";
813
+ Chain3["Stable"] = "stable";
814
+ Chain3["Ethereum"] = "ethereum";
815
+ Chain3["Arbitrum"] = "arbitrum";
816
+ Chain3["Ink"] = "ink";
817
+ Chain3["Bera"] = "bera";
818
+ Chain3["MegaETH"] = "megaeth";
819
+ Chain3["Base"] = "base";
820
+ Chain3["BSC"] = "bsc";
821
+ Chain3["HyperEVM"] = "hyperevm";
822
+ return Chain3;
823
823
  })(Chain || {});
824
824
  var Network = /* @__PURE__ */ ((Network2) => {
825
825
  Network2["Mainnet"] = "mainnet";
@@ -1723,14 +1723,311 @@ function isLiFiQuoteShape(v) {
1723
1723
  return isObject(tx) && typeof tx.to === "string" && typeof tx.data === "string" && typeof tx.chainId === "number" && isObject(est) && typeof est.fromAmount === "string" && typeof est.toAmount === "string" && isObject(act) && isObject(act.fromToken) && isObject(act.toToken);
1724
1724
  }
1725
1725
 
1726
+ // src/services/layerzero.ts
1727
+ import {
1728
+ concat,
1729
+ createPublicClient as createPublicClient5,
1730
+ createWalletClient as createWalletClient4,
1731
+ erc20Abi as erc20Abi4,
1732
+ http as http5,
1733
+ isAddress as isAddress4,
1734
+ numberToHex,
1735
+ padHex,
1736
+ parseUnits as parseUnits4
1737
+ } from "viem";
1738
+ var C = CHAIN_CONFIGS;
1739
+ var BRIDGE_CHAIN_CONFIGS = {
1740
+ // ─── Testnet ───────────────────────────────────────────────────────────────
1741
+ ["sepolia" /* Sepolia */]: { ...C["sepolia" /* Sepolia */], lzEid: 40161, oftAdapter: "0xc099cD946d5efCC35A99D64E808c1430cEf08126" },
1742
+ ["stable-testnet" /* StableTestnet */]: { ...C["stable-testnet" /* StableTestnet */], lzEid: 40374, oftAdapter: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736" },
1743
+ // ─── Mainnet ──────────────────────────────────────────────────────────────
1744
+ ["stable" /* Stable */]: { ...C["stable" /* Stable */], lzEid: 30396, oftAdapter: "0xedaba024be4d87974d5aB11C6Dd586963CcCB027" },
1745
+ ["ethereum" /* Ethereum */]: { ...C["ethereum" /* Ethereum */], lzEid: 30101, oftAdapter: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee" },
1746
+ ["arbitrum" /* Arbitrum */]: { ...C["arbitrum" /* Arbitrum */], lzEid: 30110, oftAdapter: "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92" },
1747
+ ["ink" /* Ink */]: { ...C["ink" /* Ink */], lzEid: 30339, oftAdapter: "0x1cB6De532588fCA4a21B7209DE7C456AF8434A65" },
1748
+ ["bera" /* Bera */]: { ...C["bera" /* Bera */], lzEid: 30362, oftAdapter: "0x3Dc96399109df5ceb2C226664A086140bD0379cB" },
1749
+ ["megaeth" /* MegaETH */]: { ...C["megaeth" /* MegaETH */], lzEid: 30398, oftAdapter: "0x9151434b16b9763660705744891fa906f660ecc5" },
1750
+ ["hyperevm" /* HyperEVM */]: { ...C["hyperevm" /* HyperEVM */], lzEid: 30367, oftAdapter: "0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98" }
1751
+ };
1752
+ var OFT_ADAPTER_ABI = [
1753
+ {
1754
+ name: "quoteSend",
1755
+ type: "function",
1756
+ inputs: [
1757
+ {
1758
+ name: "_sendParam",
1759
+ type: "tuple",
1760
+ components: [
1761
+ { name: "dstEid", type: "uint32" },
1762
+ { name: "to", type: "bytes32" },
1763
+ { name: "amountLD", type: "uint256" },
1764
+ { name: "minAmountLD", type: "uint256" },
1765
+ { name: "extraOptions", type: "bytes" },
1766
+ { name: "composeMsg", type: "bytes" },
1767
+ { name: "oftCmd", type: "bytes" }
1768
+ ]
1769
+ },
1770
+ { name: "_payInLzToken", type: "bool" }
1771
+ ],
1772
+ outputs: [
1773
+ {
1774
+ name: "msgFee",
1775
+ type: "tuple",
1776
+ components: [
1777
+ { name: "nativeFee", type: "uint256" },
1778
+ { name: "lzTokenFee", type: "uint256" }
1779
+ ]
1780
+ }
1781
+ ],
1782
+ stateMutability: "view"
1783
+ },
1784
+ {
1785
+ name: "send",
1786
+ type: "function",
1787
+ inputs: [
1788
+ {
1789
+ name: "_sendParam",
1790
+ type: "tuple",
1791
+ components: [
1792
+ { name: "dstEid", type: "uint32" },
1793
+ { name: "to", type: "bytes32" },
1794
+ { name: "amountLD", type: "uint256" },
1795
+ { name: "minAmountLD", type: "uint256" },
1796
+ { name: "extraOptions", type: "bytes" },
1797
+ { name: "composeMsg", type: "bytes" },
1798
+ { name: "oftCmd", type: "bytes" }
1799
+ ]
1800
+ },
1801
+ {
1802
+ name: "_fee",
1803
+ type: "tuple",
1804
+ components: [
1805
+ { name: "nativeFee", type: "uint256" },
1806
+ { name: "lzTokenFee", type: "uint256" }
1807
+ ]
1808
+ },
1809
+ { name: "_refundAddress", type: "address" }
1810
+ ],
1811
+ outputs: [],
1812
+ stateMutability: "payable"
1813
+ }
1814
+ ];
1815
+ function buildLzOptions(gasLimit = 0n) {
1816
+ return concat([
1817
+ numberToHex(3, { size: 2 }),
1818
+ // TYPE_3 header
1819
+ numberToHex(1, { size: 1 }),
1820
+ // Executor worker ID
1821
+ numberToHex(17, { size: 2 }),
1822
+ // option payload length = 17 bytes
1823
+ numberToHex(1, { size: 1 }),
1824
+ // LzReceive option type
1825
+ numberToHex(gasLimit, { size: 16 })
1826
+ // gas limit as uint128
1827
+ ]);
1828
+ }
1829
+ var LayerZeroService = class {
1830
+ constructor(config) {
1831
+ this.config = config;
1832
+ }
1833
+ async quoteBridge({ fromChain, toChain, fromToken, toToken, amount, recipient }) {
1834
+ const recipientAddr = recipient ?? "0x0000000000000000000000000000000000000000";
1835
+ this.validateBridgeParams({ fromChain, toChain, amount, recipient: recipientAddr }, "quoteBridge");
1836
+ const { src, dst } = this.resolveChains(fromChain, toChain, fromToken, toToken);
1837
+ const oftAdapter = src.oftAdapter;
1838
+ const amountLD = parseUnits4(String(amount), src.decimals);
1839
+ try {
1840
+ const { nativeFee, lzTokenFee } = await createPublicClient5({
1841
+ chain: makeChain(src.id, src.rpc),
1842
+ transport: http5(src.rpc)
1843
+ }).readContract({
1844
+ address: oftAdapter,
1845
+ abi: OFT_ADAPTER_ABI,
1846
+ functionName: "quoteSend",
1847
+ args: [this.buildSendParams(dst, amountLD, recipientAddr), false]
1848
+ });
1849
+ return { nativeFee, lzTokenFee, toAmount: amount };
1850
+ } catch (err) {
1851
+ throw new StableQuoteError({
1852
+ provider: "layerzero",
1853
+ shortMessage: "quoteBridge: quoteSend call failed",
1854
+ cause: err
1855
+ });
1856
+ }
1857
+ }
1858
+ async bridge({ fromChain, toChain, fromToken, toToken, amount, recipient, quote }) {
1859
+ const from = this.config.walletClient?.account?.address ?? this.config.account?.address;
1860
+ if (!from) {
1861
+ throw new StableValidationError(
1862
+ "signer",
1863
+ void 0,
1864
+ "bridge: requires a signer \u2014 set walletClient or account in StableConfig"
1865
+ );
1866
+ }
1867
+ const recipientAddr = recipient ?? from;
1868
+ this.validateBridgeParams({ fromChain, toChain, amount, recipient: recipientAddr }, "bridge");
1869
+ const { src, dst } = this.resolveChains(fromChain, toChain, fromToken, toToken);
1870
+ const oftAdapter = src.oftAdapter;
1871
+ const srcChain = makeChain(src.id, src.rpc);
1872
+ const wc = this.config.walletClient ?? createWalletClient4({
1873
+ account: this.config.account,
1874
+ chain: srcChain,
1875
+ transport: this.config.transport ?? http5(src.rpc)
1876
+ });
1877
+ const pc = createPublicClient5({ chain: srcChain, transport: http5(src.rpc) });
1878
+ try {
1879
+ await wc.switchChain({ id: src.id });
1880
+ } catch (err) {
1881
+ throw new StableTransactionError({
1882
+ phase: "switch_chain",
1883
+ shortMessage: `bridge: wallet rejected or failed to switch to chain ${src.id}`,
1884
+ chainId: src.id,
1885
+ cause: err
1886
+ });
1887
+ }
1888
+ const amountLD = parseUnits4(String(amount), src.decimals);
1889
+ const sendParams = this.buildSendParams(dst, amountLD, recipientAddr);
1890
+ const lzFee = quote?.nativeFee !== void 0 && quote?.lzTokenFee !== void 0 ? { nativeFee: quote.nativeFee, lzTokenFee: quote.lzTokenFee } : await this.quoteBridge({ fromChain, toChain, fromToken, toToken, amount, recipient: recipientAddr });
1891
+ const { nativeFee = 0n, lzTokenFee = 0n } = lzFee;
1892
+ const allowance = await pc.readContract({
1893
+ address: src.usdt,
1894
+ abi: erc20Abi4,
1895
+ functionName: "allowance",
1896
+ args: [from, oftAdapter]
1897
+ });
1898
+ if (allowance < amountLD) {
1899
+ let approveHash;
1900
+ try {
1901
+ approveHash = await wc.writeContract({
1902
+ address: src.usdt,
1903
+ abi: erc20Abi4,
1904
+ functionName: "approve",
1905
+ args: [oftAdapter, amountLD],
1906
+ account: wc.account,
1907
+ chain: srcChain
1908
+ });
1909
+ } catch (err) {
1910
+ throw new StableTransactionError({
1911
+ phase: "approve",
1912
+ shortMessage: "bridge: USDT0 approve failed",
1913
+ chainId: src.id,
1914
+ cause: err
1915
+ });
1916
+ }
1917
+ const approveReceipt = await pc.waitForTransactionReceipt({ hash: approveHash });
1918
+ if (approveReceipt.status === "reverted") {
1919
+ throw new StableTransactionError({
1920
+ phase: "approve",
1921
+ shortMessage: "bridge: USDT0 approve reverted on-chain",
1922
+ txHash: approveReceipt.transactionHash,
1923
+ chainId: src.id
1924
+ });
1925
+ }
1926
+ }
1927
+ try {
1928
+ const hash = await wc.writeContract({
1929
+ address: oftAdapter,
1930
+ abi: OFT_ADAPTER_ABI,
1931
+ functionName: "send",
1932
+ args: [sendParams, { nativeFee, lzTokenFee }, from],
1933
+ value: nativeFee,
1934
+ account: wc.account,
1935
+ chain: srcChain
1936
+ });
1937
+ return { txHash: hash, toAmount: amount };
1938
+ } catch (err) {
1939
+ throw new StableTransactionError({
1940
+ phase: "send",
1941
+ shortMessage: "bridge: OFT send failed",
1942
+ chainId: src.id,
1943
+ cause: err
1944
+ });
1945
+ }
1946
+ }
1947
+ validateBridgeParams(params, method) {
1948
+ if (!isAddress4(params.recipient)) {
1949
+ throw new StableValidationError(
1950
+ "recipient",
1951
+ params.recipient,
1952
+ `${method}: invalid recipient address "${params.recipient}"`
1953
+ );
1954
+ }
1955
+ if (!Number.isFinite(params.amount) || params.amount <= 0) {
1956
+ throw new StableValidationError(
1957
+ "amount",
1958
+ params.amount,
1959
+ `${method}: amount must be a finite positive number`
1960
+ );
1961
+ }
1962
+ if (params.fromChain === params.toChain) {
1963
+ throw new StableValidationError(
1964
+ "toChain",
1965
+ params.toChain,
1966
+ `${method}: fromChain and toChain must differ`
1967
+ );
1968
+ }
1969
+ }
1970
+ resolveChains(fromChain, toChain, fromToken, toToken) {
1971
+ const src = BRIDGE_CHAIN_CONFIGS[fromChain];
1972
+ const dst = BRIDGE_CHAIN_CONFIGS[toChain];
1973
+ if (!src) throw new StableValidationError("fromChain", fromChain, `Unsupported source chain: "${fromChain}"`);
1974
+ if (!dst) throw new StableValidationError("toChain", toChain, `Unsupported destination chain: "${toChain}"`);
1975
+ if (!src.oftAdapter) {
1976
+ throw new StableValidationError("fromChain", fromChain, `No OFT adapter configured for "${fromChain}"`);
1977
+ }
1978
+ if (fromToken.toLowerCase() !== src.usdt.toLowerCase()) {
1979
+ throw new StableValidationError(
1980
+ "fromToken",
1981
+ fromToken,
1982
+ `USDT0 bridge only moves USDT0 \u2014 fromToken must be ${src.usdt} on "${fromChain}", got "${fromToken}". Use route "lifi" to bridge other tokens.`
1983
+ );
1984
+ }
1985
+ if (toToken.toLowerCase() !== dst.usdt.toLowerCase()) {
1986
+ throw new StableValidationError(
1987
+ "toToken",
1988
+ toToken,
1989
+ `USDT0 bridge only moves USDT0 \u2014 toToken must be ${dst.usdt} on "${toChain}", got "${toToken}". Use route "lifi" to bridge other tokens.`
1990
+ );
1991
+ }
1992
+ return { src, dst };
1993
+ }
1994
+ buildSendParams(dst, amountLD, recipient) {
1995
+ return {
1996
+ dstEid: dst.lzEid,
1997
+ to: padHex(recipient, { dir: "left", size: 32 }),
1998
+ amountLD,
1999
+ minAmountLD: amountLD,
2000
+ extraOptions: buildLzOptions(),
2001
+ composeMsg: "0x",
2002
+ oftCmd: "0x"
2003
+ };
2004
+ }
2005
+ };
2006
+
1726
2007
  // src/stable.ts
2008
+ function isUsdt0Route(fromChain, toChain, fromToken, toToken) {
2009
+ const src = BRIDGE_CHAIN_CONFIGS[fromChain];
2010
+ const dst = BRIDGE_CHAIN_CONFIGS[toChain];
2011
+ return !!src && !!dst && !!src.oftAdapter && src.lzOutbound !== false && src.usdt.toLowerCase() === fromToken.toLowerCase() && dst.usdt.toLowerCase() === toToken.toLowerCase();
2012
+ }
2013
+ function selectBridge(params) {
2014
+ const route = params.route ?? "auto";
2015
+ if (route === "usdt0") return "usdt0";
2016
+ if (route === "lifi") return "lifi";
2017
+ return isUsdt0Route(
2018
+ params.fromChain,
2019
+ params.toChain,
2020
+ params.fromToken,
2021
+ params.toToken
2022
+ ) ? "usdt0" : "lifi";
2023
+ }
1727
2024
  function validateTransferParams({
1728
2025
  to,
1729
2026
  amount,
1730
2027
  token,
1731
2028
  tokenDecimals
1732
2029
  }) {
1733
- if (!isAddress4(to)) {
2030
+ if (!isAddress5(to)) {
1734
2031
  throw new StableValidationError(
1735
2032
  "to",
1736
2033
  to,
@@ -1744,7 +2041,7 @@ function validateTransferParams({
1744
2041
  "transfer: amount must be a finite positive number"
1745
2042
  );
1746
2043
  }
1747
- if (token !== void 0 && !isAddress4(token)) {
2044
+ if (token !== void 0 && !isAddress5(token)) {
1748
2045
  throw new StableValidationError(
1749
2046
  "token",
1750
2047
  token,
@@ -1764,7 +2061,7 @@ async function resolveTokenDecimals(publicClient, token, tokenDecimals) {
1764
2061
  try {
1765
2062
  return await publicClient.readContract({
1766
2063
  address: token,
1767
- abi: erc20Abi4,
2064
+ abi: erc20Abi5,
1768
2065
  functionName: "decimals"
1769
2066
  });
1770
2067
  } catch {
@@ -1791,9 +2088,9 @@ async function executeTokenTransfer(wc, publicClient, token, to, amount, tokenDe
1791
2088
  );
1792
2089
  return wc.writeContract({
1793
2090
  address: token,
1794
- abi: erc20Abi4,
2091
+ abi: erc20Abi5,
1795
2092
  functionName: "transfer",
1796
- args: [to, parseUnits4(String(amount), decimals)],
2093
+ args: [to, parseUnits5(String(amount), decimals)],
1797
2094
  account: acc,
1798
2095
  chain
1799
2096
  });
@@ -1814,6 +2111,7 @@ function createStable({
1814
2111
  );
1815
2112
  const signerConfig = { account, transport, walletClient };
1816
2113
  const lifi = new LiFiService({ ...signerConfig, rpc, chainId: chain.id });
2114
+ const lz = new LayerZeroService(signerConfig);
1817
2115
  const merkl = new MerklService({ ...signerConfig, rpc, chainId: chain.id, merklApiBase });
1818
2116
  const morpho = earnConfig ? new MorphoService({
1819
2117
  ...signerConfig,
@@ -1846,10 +2144,10 @@ function createStable({
1846
2144
  validateTransferParams(params);
1847
2145
  const { from, to, amount, token, tokenDecimals } = params;
1848
2146
  const acc = walletClient?.account ?? account ?? from;
1849
- const wc = walletClient ?? createWalletClient4({
2147
+ const wc = walletClient ?? createWalletClient5({
1850
2148
  account: acc,
1851
2149
  chain,
1852
- transport: transport ?? http5(rpc)
2150
+ transport: transport ?? http6(rpc)
1853
2151
  });
1854
2152
  try {
1855
2153
  await wc.switchChain({ id: chain.id });
@@ -1861,9 +2159,9 @@ function createStable({
1861
2159
  cause: err
1862
2160
  });
1863
2161
  }
1864
- const publicClient = createPublicClient5({
2162
+ const publicClient = createPublicClient6({
1865
2163
  chain,
1866
- transport: http5(rpc)
2164
+ transport: http6(rpc)
1867
2165
  });
1868
2166
  const hash = token !== void 0 ? await executeTokenTransfer(
1869
2167
  wc,
@@ -1881,7 +2179,7 @@ function createStable({
1881
2179
  account: acc,
1882
2180
  chain,
1883
2181
  to,
1884
- value: parseUnits4(String(amount), 18)
2182
+ value: parseUnits5(String(amount), 18)
1885
2183
  })
1886
2184
  );
1887
2185
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
@@ -1897,8 +2195,8 @@ function createStable({
1897
2195
  }
1898
2196
  return {
1899
2197
  transfer,
1900
- quoteBridge: (params) => lifi.quoteBridge(params),
1901
- bridge: (params) => lifi.bridge(params),
2198
+ quoteBridge: (params) => selectBridge(params) === "usdt0" ? lz.quoteBridge(params) : lifi.quoteBridge(params),
2199
+ bridge: (params) => selectBridge(params) === "usdt0" ? lz.bridge(params) : lifi.bridge(params),
1902
2200
  quoteSwap: (params) => lifi.quoteSwap(params),
1903
2201
  swap: (params) => lifi.swap(params),
1904
2202
  earn: {
@@ -1941,6 +2239,7 @@ function createStableReader(config) {
1941
2239
  var STABLE_USDT_ADDRESS = "0x779ded0c9e1022225f8e0630b35a9b54be713736";
1942
2240
  var STABLE_VAULT_ADDRESS = "0xb7Df8db22A5DBBFA9ebeb94b3910aec6a4f05c08";
1943
2241
  export {
2242
+ BRIDGE_CHAIN_CONFIGS,
1944
2243
  CHAIN_CONFIGS,
1945
2244
  Chain,
1946
2245
  Network,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stablechain/sdk",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Stable SDK",
5
5
  "keywords": ["stable", "usdt", "gasless", "web3", "yield"],
6
6
  "license": "MIT",