@stablechain/sdk 1.0.4 → 1.0.6

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
@@ -1,4 +1,26 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/stable.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } async function _asyncOptionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = await fn(value); } else if (op === 'call' || op === 'optionalCall') { value = await fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+ var _chunkQQ26UI3Fcjs = require('./chunk-QQ26UI3F.cjs');
22
+
23
+ // src/stable.ts
2
24
 
3
25
 
4
26
 
@@ -25,85 +47,6 @@ var _morphosdk = require('@morpho-org/morpho-sdk');
25
47
 
26
48
 
27
49
 
28
- // src/errors.ts
29
-
30
- var StableError = class extends _viem.BaseError {
31
- };
32
- var StableValidationError = class extends StableError {
33
- constructor(field, value, reason, opts) {
34
- super(reason, {
35
- name: "StableValidationError",
36
- cause: _optionalChain([opts, 'optionalAccess', _ => _.cause]),
37
- metaMessages: [`Field: ${field}`, `Value: ${formatValue(value)}`]
38
- });
39
- this.field = field;
40
- this.value = value;
41
- }
42
- };
43
- var StableQuoteError = class extends StableError {
44
- constructor(args) {
45
- const meta = [`Provider: ${args.provider}`];
46
- if (args.httpStatus !== void 0)
47
- meta.push(`HTTP status: ${args.httpStatus}`);
48
- if (args.providerCode) meta.push(`Provider code: ${args.providerCode}`);
49
- super(args.shortMessage, {
50
- name: "StableQuoteError",
51
- cause: args.cause,
52
- metaMessages: meta
53
- });
54
- this.provider = args.provider;
55
- this.httpStatus = args.httpStatus;
56
- this.providerCode = args.providerCode;
57
- this.body = args.body;
58
- }
59
- };
60
- var StableTransactionError = class extends StableError {
61
- constructor(args) {
62
- const meta = [`Phase: ${args.phase}`];
63
- if (args.chainId !== void 0) meta.push(`Chain ID: ${args.chainId}`);
64
- if (args.txHash) meta.push(`Tx hash: ${args.txHash}`);
65
- if (args.revertReason) meta.push(`Revert reason: ${args.revertReason}`);
66
- super(args.shortMessage, {
67
- name: "StableTransactionError",
68
- cause: args.cause,
69
- metaMessages: meta
70
- });
71
- this.phase = args.phase;
72
- this.txHash = args.txHash;
73
- this.chainId = args.chainId;
74
- this.revertReason = args.revertReason;
75
- }
76
- };
77
- var StableNetworkError = class extends StableError {
78
- constructor(args) {
79
- super(args.shortMessage, {
80
- name: "StableNetworkError",
81
- cause: args.cause,
82
- metaMessages: args.url ? [`URL: ${args.url}`] : void 0
83
- });
84
- this.url = args.url;
85
- }
86
- };
87
- var StableBulkError = class extends StableError {
88
- constructor(args) {
89
- super(args.shortMessage, { name: "StableBulkError" });
90
- this.results = args.results;
91
- this.succeeded = args.succeeded;
92
- this.failed = args.failed;
93
- }
94
- };
95
- function formatValue(v) {
96
- if (typeof v === "bigint") return `${v}n`;
97
- if (typeof v === "string") return JSON.stringify(v);
98
- if (v === null) return "null";
99
- if (v === void 0) return "undefined";
100
- try {
101
- return JSON.stringify(v);
102
- } catch (e) {
103
- return String(v);
104
- }
105
- }
106
-
107
50
  // src/helpers/chain.ts
108
51
 
109
52
  function makeChain(id, rpc) {
@@ -162,7 +105,7 @@ var MorphoService = class {
162
105
  chain: this.chain,
163
106
  transport: _nullishCoalesce(config.transport, () => ( _viem.http.call(void 0, config.rpc)))
164
107
  })));
165
- const morphoWc = _optionalChain([this, 'access', _2 => _2.wc, 'access', _3 => _3.chain, 'optionalAccess', _4 => _4.id]) === config.chainId ? this.wc : _viem.createWalletClient.call(void 0, {
108
+ const morphoWc = _optionalChain([this, 'access', _ => _.wc, 'access', _2 => _2.chain, 'optionalAccess', _3 => _3.id]) === config.chainId ? this.wc : _viem.createWalletClient.call(void 0, {
166
109
  account: this.wc.account,
167
110
  chain: this.chain,
168
111
  transport: _viem.custom.call(void 0, {
@@ -179,7 +122,7 @@ var MorphoService = class {
179
122
  deposit(params) {
180
123
  this._validateAmount(params.amount, "earn deposit");
181
124
  if (params.depositBuffer !== void 0 && (params.depositBuffer <= 0 || params.depositBuffer > 1)) {
182
- throw new StableValidationError(
125
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
183
126
  "depositBuffer",
184
127
  params.depositBuffer,
185
128
  "earn deposit: depositBuffer must be > 0 and \u2264 1"
@@ -215,7 +158,7 @@ var MorphoService = class {
215
158
  const succeeded2 = results.filter(
216
159
  (r) => r.status === "fulfilled"
217
160
  ).length;
218
- throw new StableBulkError({
161
+ throw new (0, _chunkQQ26UI3Fcjs.StableBulkError)({
219
162
  shortMessage: "bulkDeposit halted on first failure",
220
163
  results,
221
164
  succeeded: succeeded2,
@@ -259,7 +202,7 @@ var MorphoService = class {
259
202
  const succeeded2 = results.filter(
260
203
  (r) => r.status === "fulfilled"
261
204
  ).length;
262
- throw new StableBulkError({
205
+ throw new (0, _chunkQQ26UI3Fcjs.StableBulkError)({
263
206
  shortMessage: "bulkWithdraw halted on first failure",
264
207
  results,
265
208
  succeeded: succeeded2,
@@ -312,7 +255,7 @@ var MorphoService = class {
312
255
  async prepareDepositCalldata(params) {
313
256
  this._validateAmount(params.amount, "prepareDepositCalldata");
314
257
  if (params.depositBuffer !== void 0 && (params.depositBuffer <= 0 || params.depositBuffer > 1)) {
315
- throw new StableValidationError(
258
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
316
259
  "depositBuffer",
317
260
  params.depositBuffer,
318
261
  "prepareDepositCalldata: depositBuffer must be > 0 and \u2264 1"
@@ -331,7 +274,7 @@ var MorphoService = class {
331
274
  if (assetsRaw > maxAllowed) {
332
275
  const maxFormatted = Number(_viem.formatUnits.call(void 0, maxAllowed, decimals));
333
276
  const idleFormatted = Number(_viem.formatUnits.call(void 0, vaultData.assetBalance, decimals));
334
- throw new StableValidationError(
277
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
335
278
  "amount",
336
279
  amount,
337
280
  `prepareDepositCalldata: amount ${amount} exceeds deposit buffer \u2014 max ${maxFormatted} (${depositBuffer * 100}% of ${idleFormatted} idle liquidity)`
@@ -388,8 +331,8 @@ var MorphoService = class {
388
331
  abi: _viem.erc20Abi,
389
332
  functionName: "decimals"
390
333
  });
391
- } catch (e2) {
392
- throw new StableValidationError(
334
+ } catch (e) {
335
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
393
336
  "shareDecimals",
394
337
  void 0,
395
338
  `prepareRedeemCalldata: could not fetch share decimals for vault "${vaultAddr}" \u2014 pass shareDecimals explicitly`
@@ -435,7 +378,7 @@ var MorphoService = class {
435
378
  const idleFormatted = Number(
436
379
  _viem.formatUnits.call(void 0, vaultData.assetBalance, decimals)
437
380
  );
438
- throw new StableValidationError(
381
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
439
382
  "amount",
440
383
  amount,
441
384
  `earn deposit: amount ${amount} exceeds deposit buffer \u2014 max ${maxFormatted} (${depositBuffer * 100}% of ${idleFormatted} idle liquidity)`
@@ -465,7 +408,7 @@ var MorphoService = class {
465
408
  hash: approveHash
466
409
  });
467
410
  if (approveReceipt.status === "reverted") {
468
- throw new StableTransactionError({
411
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
469
412
  phase: "approve",
470
413
  shortMessage: "earn deposit: token approval reverted on-chain",
471
414
  txHash: approveReceipt.transactionHash,
@@ -480,7 +423,7 @@ var MorphoService = class {
480
423
  const hash = await this._sendTx(tx.to, tx.data, tx.value, from);
481
424
  const receipt = await this.pc.waitForTransactionReceipt({ hash });
482
425
  if (receipt.status === "reverted") {
483
- throw new StableTransactionError({
426
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
484
427
  phase: "receipt",
485
428
  shortMessage: "earn deposit: vault deposit reverted on-chain",
486
429
  txHash: receipt.transactionHash,
@@ -510,7 +453,7 @@ var MorphoService = class {
510
453
  const hash = await this._sendTx(tx.to, tx.data, tx.value, from);
511
454
  const receipt = await this.pc.waitForTransactionReceipt({ hash });
512
455
  if (receipt.status === "reverted") {
513
- throw new StableTransactionError({
456
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
514
457
  phase: "receipt",
515
458
  shortMessage: "earn withdraw: vault withdraw reverted on-chain",
516
459
  txHash: receipt.transactionHash,
@@ -532,8 +475,8 @@ var MorphoService = class {
532
475
  abi: _viem.erc20Abi,
533
476
  functionName: "decimals"
534
477
  });
535
- } catch (e3) {
536
- throw new StableValidationError(
478
+ } catch (e2) {
479
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
537
480
  "shareDecimals",
538
481
  void 0,
539
482
  `earn redeem: could not fetch share decimals for vault "${vaultAddr}" \u2014 pass shareDecimals explicitly`
@@ -556,7 +499,7 @@ var MorphoService = class {
556
499
  const hash = await this._sendTx(tx.to, tx.data, tx.value, from);
557
500
  const receipt = await this.pc.waitForTransactionReceipt({ hash });
558
501
  if (receipt.status === "reverted") {
559
- throw new StableTransactionError({
502
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
560
503
  phase: "receipt",
561
504
  shortMessage: "earn redeem: vault redeem reverted on-chain",
562
505
  txHash: receipt.transactionHash,
@@ -587,7 +530,7 @@ var MorphoService = class {
587
530
  const hash = await this._sendTx(tx.to, tx.data, tx.value, from);
588
531
  const receipt = await this.pc.waitForTransactionReceipt({ hash });
589
532
  if (receipt.status === "reverted") {
590
- throw new StableTransactionError({
533
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
591
534
  phase: "receipt",
592
535
  shortMessage: "earn forceWithdraw: vault forceWithdraw reverted on-chain",
593
536
  txHash: receipt.transactionHash,
@@ -616,8 +559,8 @@ var MorphoService = class {
616
559
  abi: _viem.erc20Abi,
617
560
  functionName: "decimals"
618
561
  });
619
- } catch (e4) {
620
- throw new StableValidationError(
562
+ } catch (e3) {
563
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
621
564
  "shareDecimals",
622
565
  void 0,
623
566
  `earn forceRedeem: could not fetch share decimals for vault "${vaultAddr}" \u2014 pass shareDecimals explicitly`
@@ -640,7 +583,7 @@ var MorphoService = class {
640
583
  const hash = await this._sendTx(tx.to, tx.data, tx.value, from);
641
584
  const receipt = await this.pc.waitForTransactionReceipt({ hash });
642
585
  if (receipt.status === "reverted") {
643
- throw new StableTransactionError({
586
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
644
587
  phase: "receipt",
645
588
  shortMessage: "earn forceRedeem: vault forceRedeem reverted on-chain",
646
589
  txHash: receipt.transactionHash,
@@ -662,7 +605,7 @@ var MorphoService = class {
662
605
  remaining = this._pullFromAdapter(adapter, remaining, now, result);
663
606
  }
664
607
  if (remaining > 0n) {
665
- throw new StableValidationError(
608
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
666
609
  "amount",
667
610
  amount,
668
611
  "earn withdraw: insufficient adapter liquidity \u2014 reduce the amount or wait for market liquidity to free up"
@@ -707,9 +650,9 @@ var MorphoService = class {
707
650
  }
708
651
  // ─── Helpers ─────────────────────────────────────────────────────────────
709
652
  _requireFrom() {
710
- const from = _optionalChain([this, 'access', _5 => _5.wc, 'access', _6 => _6.account, 'optionalAccess', _7 => _7.address]);
653
+ const from = _optionalChain([this, 'access', _4 => _4.wc, 'access', _5 => _5.account, 'optionalAccess', _6 => _6.address]);
711
654
  if (!from) {
712
- throw new StableValidationError(
655
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
713
656
  "signer",
714
657
  void 0,
715
658
  "earn: requires a signer \u2014 set walletClient or account in StableConfig"
@@ -722,7 +665,7 @@ var MorphoService = class {
722
665
  await this.wc.switchChain({ id: this.config.chainId });
723
666
  } catch (err) {
724
667
  if (err.code === 4001) {
725
- throw new StableTransactionError({
668
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
726
669
  phase: "switch_chain",
727
670
  shortMessage: `earn: wallet rejected switch to chain ${this.config.chainId}`,
728
671
  chainId: this.config.chainId,
@@ -741,7 +684,7 @@ var MorphoService = class {
741
684
  chain: this.chain
742
685
  });
743
686
  } catch (err) {
744
- throw new StableTransactionError({
687
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
745
688
  phase: "send",
746
689
  shortMessage: "earn: transaction send failed",
747
690
  chainId: this.config.chainId,
@@ -758,8 +701,8 @@ var MorphoService = class {
758
701
  functionName: "decimals"
759
702
  })
760
703
  );
761
- } catch (e5) {
762
- throw new StableValidationError(
704
+ } catch (e4) {
705
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
763
706
  "tokenDecimals",
764
707
  void 0,
765
708
  `${op}: could not fetch decimals for asset "${asset}" \u2014 pass tokenDecimals explicitly`
@@ -776,7 +719,7 @@ var MorphoService = class {
776
719
  }
777
720
  _validateAmount(amount, op) {
778
721
  if (!Number.isFinite(amount) || amount <= 0) {
779
- throw new StableValidationError(
722
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
780
723
  "amount",
781
724
  amount,
782
725
  `${op}: amount must be a finite positive number`
@@ -785,7 +728,7 @@ var MorphoService = class {
785
728
  }
786
729
  _validateShares(shares, op) {
787
730
  if (!Number.isFinite(shares) || shares <= 0) {
788
- throw new StableValidationError(
731
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
789
732
  "shares",
790
733
  shares,
791
734
  `${op}: shares must be a finite positive number`
@@ -807,19 +750,27 @@ var MorphoService = class {
807
750
 
808
751
 
809
752
  // src/types.ts
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;
753
+ var Chain = /* @__PURE__ */ ((Chain2) => {
754
+ Chain2["Sepolia"] = "sepolia";
755
+ Chain2["StableTestnet"] = "stable-testnet";
756
+ Chain2["Stable"] = "stable";
757
+ Chain2["Ethereum"] = "ethereum";
758
+ Chain2["Arbitrum"] = "arbitrum";
759
+ Chain2["Ink"] = "ink";
760
+ Chain2["Bera"] = "bera";
761
+ Chain2["MegaETH"] = "megaeth";
762
+ Chain2["Base"] = "base";
763
+ Chain2["BSC"] = "bsc";
764
+ Chain2["HyperEVM"] = "hyperevm";
765
+ Chain2["Polygon"] = "polygon";
766
+ Chain2["Plasma"] = "plasma";
767
+ Chain2["Optimism"] = "optimism";
768
+ Chain2["Unichain"] = "unichain";
769
+ Chain2["Sei"] = "sei";
770
+ Chain2["Flare"] = "flare";
771
+ Chain2["XLayer"] = "xlayer";
772
+ Chain2["Rootstock"] = "rootstock";
773
+ return Chain2;
823
774
  })(Chain || {});
824
775
  var Network = /* @__PURE__ */ ((Network2) => {
825
776
  Network2["Mainnet"] = "mainnet";
@@ -831,22 +782,22 @@ var Network = /* @__PURE__ */ ((Network2) => {
831
782
  var MORPHO_API_URL = "https://blue-api.morpho.org/graphql";
832
783
  var EarnReader = class {
833
784
  constructor(config) {
834
- if (!_optionalChain([config, 'access', _8 => _8.earn, 'optionalAccess', _9 => _9.vault])) {
835
- throw new StableValidationError(
785
+ if (!_optionalChain([config, 'access', _7 => _7.earn, 'optionalAccess', _8 => _8.vault])) {
786
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
836
787
  "earn.vault",
837
788
  void 0,
838
789
  "createStableReader: earn.vault is required"
839
790
  );
840
791
  }
841
792
  if (!_viem.isAddress.call(void 0, config.address)) {
842
- throw new StableValidationError(
793
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
843
794
  "address",
844
795
  config.address,
845
796
  `createStableReader: invalid user address "${config.address}"`
846
797
  );
847
798
  }
848
799
  if (!_viem.isAddress.call(void 0, config.earn.vault)) {
849
- throw new StableValidationError(
800
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
850
801
  "earn.vault",
851
802
  config.earn.vault,
852
803
  `createStableReader: invalid vault address "${config.earn.vault}"`
@@ -981,7 +932,7 @@ var EarnReader = class {
981
932
  );
982
933
  } catch (err) {
983
934
  if (err instanceof TypeError || err instanceof HttpError) {
984
- throw new StableNetworkError({
935
+ throw new (0, _chunkQQ26UI3Fcjs.StableNetworkError)({
985
936
  shortMessage: err instanceof HttpError ? `earn: Morpho API returned ${err.status} after retries` : `earn: failed to reach Morpho API after retries \u2014 ${String(
986
937
  err
987
938
  )}`,
@@ -991,9 +942,9 @@ var EarnReader = class {
991
942
  }
992
943
  throw err;
993
944
  }
994
- const vault = _optionalChain([body, 'optionalAccess', _10 => _10.data, 'optionalAccess', _11 => _11.vaultV2ByAddress]);
945
+ const vault = _optionalChain([body, 'optionalAccess', _9 => _9.data, 'optionalAccess', _10 => _10.vaultV2ByAddress]);
995
946
  if (!vault || typeof vault.avgNetApy !== "number") {
996
- throw new StableValidationError(
947
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
997
948
  "apy",
998
949
  void 0,
999
950
  "earn: vault not found in Morpho API or unexpected response shape"
@@ -1045,7 +996,7 @@ var MerklService = class {
1045
996
  }
1046
997
  async fetchRewards(address) {
1047
998
  if (!_viem.isAddress.call(void 0, address)) {
1048
- throw new StableValidationError(
999
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1049
1000
  "address",
1050
1001
  address,
1051
1002
  `merkl: invalid address "${address}"`
@@ -1063,7 +1014,7 @@ var MerklService = class {
1063
1014
  (r) => r.rawAmount !== "0" && r.proofs.length > 0
1064
1015
  );
1065
1016
  if (claimable.length === 0) {
1066
- throw new StableValidationError(
1017
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1067
1018
  "rewards",
1068
1019
  [],
1069
1020
  rewards.length > 0 ? "merkl: rewards are pending the next merkle tree update \u2014 try again in ~2 hours" : "merkl: no rewards to claim on this chain"
@@ -1078,7 +1029,7 @@ var MerklService = class {
1078
1029
  try {
1079
1030
  await wc.switchChain({ id: this.config.chainId });
1080
1031
  } catch (err) {
1081
- throw new StableTransactionError({
1032
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
1082
1033
  phase: "switch_chain",
1083
1034
  shortMessage: `merkl: wallet rejected or failed to switch to chain ${this.config.chainId}`,
1084
1035
  chainId: this.config.chainId,
@@ -1102,7 +1053,7 @@ var MerklService = class {
1102
1053
  chain
1103
1054
  });
1104
1055
  } catch (err) {
1105
- throw new StableTransactionError({
1056
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
1106
1057
  phase: "send",
1107
1058
  shortMessage: "merkl: claim transaction failed",
1108
1059
  chainId: this.config.chainId,
@@ -1115,7 +1066,7 @@ var MerklService = class {
1115
1066
  });
1116
1067
  const receipt = await pc.waitForTransactionReceipt({ hash });
1117
1068
  if (receipt.status === "reverted") {
1118
- throw new StableTransactionError({
1069
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
1119
1070
  phase: "receipt",
1120
1071
  shortMessage: "merkl: claim transaction reverted on-chain",
1121
1072
  txHash: receipt.transactionHash,
@@ -1129,7 +1080,7 @@ var MerklService = class {
1129
1080
  }
1130
1081
  async prepareClaimCalldata(address) {
1131
1082
  if (!_viem.isAddress.call(void 0, address)) {
1132
- throw new StableValidationError(
1083
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1133
1084
  "address",
1134
1085
  address,
1135
1086
  `merkl: invalid address "${address}"`
@@ -1140,7 +1091,7 @@ var MerklService = class {
1140
1091
  (r) => r.rawAmount !== "0" && r.proofs.length > 0
1141
1092
  );
1142
1093
  if (claimable.length === 0) {
1143
- throw new StableValidationError(
1094
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1144
1095
  "rewards",
1145
1096
  [],
1146
1097
  rewards.length > 0 ? "merkl: rewards are pending the next merkle tree update \u2014 try again in ~2 hours" : "merkl: no rewards to claim on this chain"
@@ -1163,9 +1114,9 @@ var MerklService = class {
1163
1114
  };
1164
1115
  }
1165
1116
  _requireFrom() {
1166
- const from = _nullishCoalesce(_optionalChain([this, 'access', _12 => _12.config, 'access', _13 => _13.walletClient, 'optionalAccess', _14 => _14.account, 'optionalAccess', _15 => _15.address]), () => ( _optionalChain([this, 'access', _16 => _16.config, 'access', _17 => _17.account, 'optionalAccess', _18 => _18.address])));
1117
+ const from = _nullishCoalesce(_optionalChain([this, 'access', _11 => _11.config, 'access', _12 => _12.walletClient, 'optionalAccess', _13 => _13.account, 'optionalAccess', _14 => _14.address]), () => ( _optionalChain([this, 'access', _15 => _15.config, 'access', _16 => _16.account, 'optionalAccess', _17 => _17.address])));
1167
1118
  if (!from) {
1168
- throw new StableValidationError(
1119
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1169
1120
  "signer",
1170
1121
  void 0,
1171
1122
  "merkl.claim: requires a signer \u2014 set walletClient or account in StableConfig"
@@ -1178,7 +1129,7 @@ var MerklService = class {
1178
1129
  const rewards = [];
1179
1130
  const entries = Array.isArray(data) ? data : [data];
1180
1131
  for (const entry of entries) {
1181
- if (_optionalChain([entry, 'optionalAccess', _19 => _19.chain, 'optionalAccess', _20 => _20.id]) !== chainId) continue;
1132
+ if (_optionalChain([entry, 'optionalAccess', _18 => _18.chain, 'optionalAccess', _19 => _19.id]) !== chainId) continue;
1182
1133
  for (const reward of _nullishCoalesce(entry.rewards, () => ( []))) {
1183
1134
  const parsed = this._parseReward(reward);
1184
1135
  if (parsed) rewards.push(parsed);
@@ -1187,7 +1138,7 @@ var MerklService = class {
1187
1138
  return { chainId, rewards };
1188
1139
  }
1189
1140
  _parseReward(reward) {
1190
- if (!_optionalChain([reward, 'optionalAccess', _21 => _21.token, 'optionalAccess', _22 => _22.address])) return null;
1141
+ if (!_optionalChain([reward, 'optionalAccess', _20 => _20.token, 'optionalAccess', _21 => _21.address])) return null;
1191
1142
  const net = BigInt(_nullishCoalesce(reward.amount, () => ( "0"))) - BigInt(_nullishCoalesce(reward.claimed, () => ( "0")));
1192
1143
  if (net <= 0n) return null;
1193
1144
  const rawAmount = net.toString();
@@ -1207,15 +1158,15 @@ var MerklService = class {
1207
1158
  try {
1208
1159
  return await retryWithBackoff(() => this._fetchOnce(url));
1209
1160
  } catch (err) {
1210
- if (err instanceof StableNetworkError) throw err;
1161
+ if (err instanceof _chunkQQ26UI3Fcjs.StableNetworkError) throw err;
1211
1162
  if (err instanceof HttpError) {
1212
- throw new StableNetworkError({
1163
+ throw new (0, _chunkQQ26UI3Fcjs.StableNetworkError)({
1213
1164
  shortMessage: `merkl: request failed \u2014 ${err.message}`,
1214
1165
  url,
1215
1166
  cause: err
1216
1167
  });
1217
1168
  }
1218
- throw new StableNetworkError({
1169
+ throw new (0, _chunkQQ26UI3Fcjs.StableNetworkError)({
1219
1170
  shortMessage: "merkl: request failed before reaching the server",
1220
1171
  url,
1221
1172
  cause: err
@@ -1232,7 +1183,7 @@ var MerklService = class {
1232
1183
  true
1233
1184
  );
1234
1185
  }
1235
- throw new StableNetworkError({
1186
+ throw new (0, _chunkQQ26UI3Fcjs.StableNetworkError)({
1236
1187
  shortMessage: `merkl: API error ${res.status} ${res.statusText}`,
1237
1188
  url
1238
1189
  });
@@ -1259,7 +1210,7 @@ var CHAIN_CONFIGS = {
1259
1210
  id: 11155111,
1260
1211
  rpc: "https://ethereum-sepolia-rpc.publicnode.com",
1261
1212
  usdt: "0xc4DCC311c028e341fd8602D8eB89c5de94625927",
1262
- decimals: 18
1213
+ decimals: 6
1263
1214
  },
1264
1215
  ["stable-testnet" /* StableTestnet */]: {
1265
1216
  id: 2201,
@@ -1277,13 +1228,15 @@ var CHAIN_CONFIGS = {
1277
1228
  ["ethereum" /* Ethereum */]: {
1278
1229
  id: 1,
1279
1230
  rpc: "https://ethereum-rpc.publicnode.com",
1280
- usdt: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee",
1231
+ // Canonical USDT. Not the OFT adapter — this field is used as an ERC-20
1232
+ // (allowance/approve/balanceOf) and as the token address for LI.FI.
1233
+ usdt: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
1281
1234
  decimals: 6
1282
1235
  },
1283
1236
  ["arbitrum" /* Arbitrum */]: {
1284
1237
  id: 42161,
1285
1238
  rpc: "https://arbitrum-one-rpc.publicnode.com",
1286
- usdt: "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92",
1239
+ usdt: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
1287
1240
  decimals: 6
1288
1241
  },
1289
1242
  ["ink" /* Ink */]: {
@@ -1300,7 +1253,7 @@ var CHAIN_CONFIGS = {
1300
1253
  },
1301
1254
  ["megaeth" /* MegaETH */]: {
1302
1255
  id: 4326,
1303
- rpc: "https://carrot.megaeth.com",
1256
+ rpc: "https://mainnet.megaeth.com/rpc",
1304
1257
  usdt: "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb",
1305
1258
  decimals: 6
1306
1259
  },
@@ -1321,6 +1274,55 @@ var CHAIN_CONFIGS = {
1321
1274
  rpc: "https://rpc.hyperliquid.xyz/evm",
1322
1275
  usdt: "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
1323
1276
  decimals: 6
1277
+ },
1278
+ ["polygon" /* Polygon */]: {
1279
+ id: 137,
1280
+ rpc: "https://polygon-bor-rpc.publicnode.com",
1281
+ // Polygon's canonical USDT, migrated to USDT0
1282
+ usdt: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
1283
+ decimals: 6
1284
+ },
1285
+ ["plasma" /* Plasma */]: {
1286
+ id: 9745,
1287
+ rpc: "https://rpc.plasma.to",
1288
+ usdt: "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
1289
+ decimals: 6
1290
+ },
1291
+ ["optimism" /* Optimism */]: {
1292
+ id: 10,
1293
+ rpc: "https://optimism-rpc.publicnode.com",
1294
+ usdt: "0x01bFF41798a0BcF287b996046Ca68b395DbC1071",
1295
+ decimals: 6
1296
+ },
1297
+ ["unichain" /* Unichain */]: {
1298
+ id: 130,
1299
+ rpc: "https://unichain-rpc.publicnode.com",
1300
+ usdt: "0x9151434b16b9763660705744891fA906F660EcC5",
1301
+ decimals: 6
1302
+ },
1303
+ ["sei" /* Sei */]: {
1304
+ id: 1329,
1305
+ rpc: "https://sei-evm-rpc.publicnode.com",
1306
+ usdt: "0x9151434b16b9763660705744891fA906F660EcC5",
1307
+ decimals: 6
1308
+ },
1309
+ ["flare" /* Flare */]: {
1310
+ id: 14,
1311
+ rpc: "https://flare-api.flare.network/ext/C/rpc",
1312
+ usdt: "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
1313
+ decimals: 6
1314
+ },
1315
+ ["xlayer" /* XLayer */]: {
1316
+ id: 196,
1317
+ rpc: "https://rpc.xlayer.tech",
1318
+ usdt: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
1319
+ decimals: 6
1320
+ },
1321
+ ["rootstock" /* Rootstock */]: {
1322
+ id: 30,
1323
+ rpc: "https://public-node.rsk.co",
1324
+ usdt: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
1325
+ decimals: 6
1324
1326
  }
1325
1327
  };
1326
1328
 
@@ -1376,17 +1378,17 @@ var LiFiService = class {
1376
1378
  fromDecimals = 6,
1377
1379
  recipient
1378
1380
  } = params;
1379
- const from = _nullishCoalesce(_nullishCoalesce(_optionalChain([this, 'access', _23 => _23.config, 'access', _24 => _24.walletClient, 'optionalAccess', _25 => _25.account, 'optionalAccess', _26 => _26.address]), () => ( _optionalChain([this, 'access', _27 => _27.config, 'access', _28 => _28.account, 'optionalAccess', _29 => _29.address]))), () => ( "0x0000000000000000000000000000000000000000"));
1381
+ const from = _nullishCoalesce(_nullishCoalesce(_optionalChain([this, 'access', _22 => _22.config, 'access', _23 => _23.walletClient, 'optionalAccess', _24 => _24.account, 'optionalAccess', _25 => _25.address]), () => ( _optionalChain([this, 'access', _26 => _26.config, 'access', _27 => _27.account, 'optionalAccess', _28 => _28.address]))), () => ( "0x0000000000000000000000000000000000000000"));
1380
1382
  const src = CHAIN_CONFIGS[fromChain];
1381
1383
  const dst = CHAIN_CONFIGS[toChain];
1382
1384
  if (!src)
1383
- throw new StableValidationError(
1385
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1384
1386
  "fromChain",
1385
1387
  fromChain,
1386
1388
  `LI.FI bridge: unsupported source chain "${fromChain}"`
1387
1389
  );
1388
1390
  if (!dst)
1389
- throw new StableValidationError(
1391
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1390
1392
  "toChain",
1391
1393
  toChain,
1392
1394
  `LI.FI bridge: unsupported destination chain "${toChain}"`
@@ -1418,14 +1420,14 @@ var LiFiService = class {
1418
1420
  const src = CHAIN_CONFIGS[fromChain];
1419
1421
  const dst = CHAIN_CONFIGS[toChain];
1420
1422
  if (!src) {
1421
- throw new StableValidationError(
1423
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1422
1424
  "fromChain",
1423
1425
  fromChain,
1424
1426
  `LI.FI bridge: unsupported source chain "${fromChain}"`
1425
1427
  );
1426
1428
  }
1427
1429
  if (!dst) {
1428
- throw new StableValidationError(
1430
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1429
1431
  "toChain",
1430
1432
  toChain,
1431
1433
  `LI.FI bridge: unsupported destination chain "${toChain}"`
@@ -1454,35 +1456,35 @@ var LiFiService = class {
1454
1456
  toAddress
1455
1457
  }) {
1456
1458
  if (!_viem.isAddress.call(void 0, fromToken)) {
1457
- throw new StableValidationError(
1459
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1458
1460
  "fromToken",
1459
1461
  fromToken,
1460
1462
  `swap: invalid fromToken address "${fromToken}"`
1461
1463
  );
1462
1464
  }
1463
1465
  if (!_viem.isAddress.call(void 0, toToken)) {
1464
- throw new StableValidationError(
1466
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1465
1467
  "toToken",
1466
1468
  toToken,
1467
1469
  `swap: invalid toToken address "${toToken}"`
1468
1470
  );
1469
1471
  }
1470
1472
  if (fromToken.toLowerCase() === toToken.toLowerCase()) {
1471
- throw new StableValidationError(
1473
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1472
1474
  "toToken",
1473
1475
  toToken,
1474
1476
  "swap: fromToken and toToken must differ"
1475
1477
  );
1476
1478
  }
1477
1479
  if (!Number.isFinite(amount) || amount <= 0) {
1478
- throw new StableValidationError(
1480
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1479
1481
  "amount",
1480
1482
  amount,
1481
1483
  "swap: amount must be a finite positive number"
1482
1484
  );
1483
1485
  }
1484
1486
  if (toAddress !== void 0 && !_viem.isAddress.call(void 0, toAddress)) {
1485
- throw new StableValidationError(
1487
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1486
1488
  "toAddress",
1487
1489
  toAddress,
1488
1490
  `swap: invalid toAddress "${toAddress}"`
@@ -1498,35 +1500,35 @@ var LiFiService = class {
1498
1500
  recipient
1499
1501
  }) {
1500
1502
  if (!_viem.isAddress.call(void 0, fromToken)) {
1501
- throw new StableValidationError(
1503
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1502
1504
  "fromToken",
1503
1505
  fromToken,
1504
1506
  `LI.FI bridge: invalid fromToken address "${fromToken}"`
1505
1507
  );
1506
1508
  }
1507
1509
  if (!_viem.isAddress.call(void 0, toToken)) {
1508
- throw new StableValidationError(
1510
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1509
1511
  "toToken",
1510
1512
  toToken,
1511
1513
  `LI.FI bridge: invalid toToken address "${toToken}"`
1512
1514
  );
1513
1515
  }
1514
1516
  if (!Number.isFinite(amount) || amount <= 0) {
1515
- throw new StableValidationError(
1517
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1516
1518
  "amount",
1517
1519
  amount,
1518
1520
  "LI.FI bridge: amount must be a finite positive number"
1519
1521
  );
1520
1522
  }
1521
1523
  if (recipient !== void 0 && !_viem.isAddress.call(void 0, recipient)) {
1522
- throw new StableValidationError(
1524
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1523
1525
  "recipient",
1524
1526
  recipient,
1525
1527
  `LI.FI bridge: invalid recipient address "${recipient}"`
1526
1528
  );
1527
1529
  }
1528
1530
  if (fromChain === toChain) {
1529
- throw new StableValidationError(
1531
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1530
1532
  "toChain",
1531
1533
  toChain,
1532
1534
  "LI.FI bridge: fromChain and toChain must differ"
@@ -1534,9 +1536,9 @@ var LiFiService = class {
1534
1536
  }
1535
1537
  }
1536
1538
  _requireFrom() {
1537
- const from = _nullishCoalesce(_optionalChain([this, 'access', _30 => _30.config, 'access', _31 => _31.walletClient, 'optionalAccess', _32 => _32.account, 'optionalAccess', _33 => _33.address]), () => ( _optionalChain([this, 'access', _34 => _34.config, 'access', _35 => _35.account, 'optionalAccess', _36 => _36.address])));
1539
+ const from = _nullishCoalesce(_optionalChain([this, 'access', _29 => _29.config, 'access', _30 => _30.walletClient, 'optionalAccess', _31 => _31.account, 'optionalAccess', _32 => _32.address]), () => ( _optionalChain([this, 'access', _33 => _33.config, 'access', _34 => _34.account, 'optionalAccess', _35 => _35.address])));
1538
1540
  if (!from) {
1539
- throw new StableValidationError(
1541
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1540
1542
  "signer",
1541
1543
  void 0,
1542
1544
  "LI.FI: requires a signer \u2014 set walletClient or account in StableConfig"
@@ -1549,16 +1551,16 @@ var LiFiService = class {
1549
1551
  try {
1550
1552
  return await retryWithBackoff(() => this._fetchQuoteOnce(url));
1551
1553
  } catch (err) {
1552
- if (err instanceof StableQuoteError) throw err;
1554
+ if (err instanceof _chunkQQ26UI3Fcjs.StableQuoteError) throw err;
1553
1555
  if (err instanceof HttpError) {
1554
- throw new StableQuoteError({
1556
+ throw new (0, _chunkQQ26UI3Fcjs.StableQuoteError)({
1555
1557
  provider: "lifi",
1556
1558
  shortMessage: err.message,
1557
1559
  httpStatus: err.status,
1558
1560
  cause: err
1559
1561
  });
1560
1562
  }
1561
- throw new StableNetworkError({
1563
+ throw new (0, _chunkQQ26UI3Fcjs.StableNetworkError)({
1562
1564
  shortMessage: "LI.FI: quote request failed before reaching the server",
1563
1565
  url,
1564
1566
  cause: err
@@ -1578,7 +1580,7 @@ var LiFiService = class {
1578
1580
  true
1579
1581
  );
1580
1582
  }
1581
- throw new StableQuoteError({
1583
+ throw new (0, _chunkQQ26UI3Fcjs.StableQuoteError)({
1582
1584
  provider: "lifi",
1583
1585
  shortMessage: `LI.FI: ${_nullishCoalesce(providerMessage, () => ( res.statusText))}`,
1584
1586
  httpStatus: res.status,
@@ -1587,7 +1589,7 @@ var LiFiService = class {
1587
1589
  });
1588
1590
  }
1589
1591
  if (!isLiFiQuoteShape(body)) {
1590
- throw new StableQuoteError({
1592
+ throw new (0, _chunkQQ26UI3Fcjs.StableQuoteError)({
1591
1593
  provider: "lifi",
1592
1594
  shortMessage: "LI.FI: unexpected quote response shape",
1593
1595
  httpStatus: res.status,
@@ -1615,7 +1617,7 @@ var LiFiService = class {
1615
1617
  const { transactionRequest } = quote;
1616
1618
  const srcChainId = transactionRequest.chainId;
1617
1619
  if (srcChainId !== expectedChainId) {
1618
- throw new StableQuoteError({
1620
+ throw new (0, _chunkQQ26UI3Fcjs.StableQuoteError)({
1619
1621
  provider: "lifi",
1620
1622
  shortMessage: `LI.FI: returned tx for chain ${srcChainId} but expected ${expectedChainId}`,
1621
1623
  providerCode: "chain_mismatch",
@@ -1631,7 +1633,7 @@ var LiFiService = class {
1631
1633
  try {
1632
1634
  await wc.switchChain({ id: srcChainId });
1633
1635
  } catch (err) {
1634
- throw new StableTransactionError({
1636
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
1635
1637
  phase: "switch_chain",
1636
1638
  shortMessage: `LI.FI: wallet rejected or failed to switch to chain ${srcChainId}`,
1637
1639
  chainId: srcChainId,
@@ -1657,7 +1659,7 @@ var LiFiService = class {
1657
1659
  chain: srcChain
1658
1660
  });
1659
1661
  } catch (err) {
1660
- throw new StableTransactionError({
1662
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
1661
1663
  phase: "send",
1662
1664
  shortMessage: "LI.FI: swap/bridge transaction failed",
1663
1665
  chainId: srcChainId,
@@ -1692,7 +1694,7 @@ var LiFiService = class {
1692
1694
  chain: srcChain
1693
1695
  });
1694
1696
  } catch (err) {
1695
- throw new StableTransactionError({
1697
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
1696
1698
  phase: "approve",
1697
1699
  shortMessage: "LI.FI: token approve failed",
1698
1700
  chainId: srcChainId,
@@ -1703,7 +1705,7 @@ var LiFiService = class {
1703
1705
  hash: approveHash
1704
1706
  });
1705
1707
  if (approveReceipt.status === "reverted") {
1706
- throw new StableTransactionError({
1708
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
1707
1709
  phase: "approve",
1708
1710
  shortMessage: "LI.FI: token approve reverted on-chain",
1709
1711
  txHash: approveReceipt.transactionHash,
@@ -1735,38 +1737,81 @@ function isLiFiQuoteShape(v) {
1735
1737
 
1736
1738
 
1737
1739
 
1740
+
1738
1741
  var C = CHAIN_CONFIGS;
1742
+ var XAUT0_DEPLOYMENTS = {
1743
+ ["ethereum" /* Ethereum */]: { address: "0x68749665FF8D2d112Fa859AA293F07A622782F38", decimals: 6, oftAdapter: "0xb9c2321BB7D0Db468f570D10A424d1Cc8EFd696C", approvalRequired: true },
1744
+ ["stable" /* Stable */]: { address: "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb", decimals: 6, oftAdapter: "0xD8479f87686ed263D00Ca7505F86327dbeD4171A", approvalRequired: false },
1745
+ ["arbitrum" /* Arbitrum */]: { address: "0x40461291347e1eCbb09499F3371D3f17f10d7159", decimals: 6, oftAdapter: "0xf40542a7B66AD7C68C459EE3679635D2fDB6dF39", approvalRequired: false },
1746
+ ["ink" /* Ink */]: { address: "0xF50258D3c1dd88946C567920B986A12e65b50dAc", decimals: 6, oftAdapter: "0xA1bE1572B4beef24f812EfDc58bdc41D56a0dAB2", approvalRequired: false },
1747
+ ["hyperevm" /* HyperEVM */]: { address: "0xf4D9235269a96aaDaFc9aDAe454a0618eBE37949", decimals: 6, oftAdapter: "0x4E41cfc3F3B19E29E323D2c36F8f202a1e151dAF", approvalRequired: false },
1748
+ ["polygon" /* Polygon */]: { address: "0xF1815bd50389c46847f0Bda824eC8da914045D14", decimals: 6, oftAdapter: "0x5421Cf4288d8007D3c43AC4246eaFCe5b049e352", approvalRequired: false },
1749
+ ["plasma" /* Plasma */]: { address: "0x1B64B9025EEbb9A6239575dF9Ea4b9Ac46D4d193", decimals: 6, oftAdapter: "0x63aB93cBC9d4ecD9c4947b1A38F458147C08E6F7", approvalRequired: false },
1750
+ ["bsc" /* BSC */]: { address: "0x21cAef8A43163Eea865baeE23b9C2E327696A3bf", decimals: 6, oftAdapter: "0x53C3A64c8942288e12813C1F8457Db45980BcfC2", approvalRequired: false }
1751
+ };
1752
+ function bridgeChain(chain, lzEid, blockTimeSec, usdt0Adapter) {
1753
+ const base = C[chain];
1754
+ const tokens = {};
1755
+ if (usdt0Adapter) {
1756
+ tokens.usdt0 = { address: base.usdt, decimals: base.decimals, oftAdapter: usdt0Adapter };
1757
+ }
1758
+ const xaut0 = XAUT0_DEPLOYMENTS[chain];
1759
+ if (xaut0) tokens.xaut0 = xaut0;
1760
+ return { ...base, lzEid, blockTimeSec, tokens, oftAdapter: usdt0Adapter };
1761
+ }
1739
1762
  var BRIDGE_CHAIN_CONFIGS = {
1740
1763
  // ─── Testnet ───────────────────────────────────────────────────────────────
1741
- ["sepolia" /* Sepolia */]: { ...C["sepolia" /* Sepolia */], lzEid: 40161, oftAdapter: "0xc099cD946d5efCC35A99D64E808c1430cEf08126" },
1742
- ["stable-testnet" /* StableTestnet */]: { ...C["stable-testnet" /* StableTestnet */], lzEid: 40374, oftAdapter: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736" },
1764
+ ["sepolia" /* Sepolia */]: bridgeChain("sepolia" /* Sepolia */, 40161, 12, "0xc099cD946d5efCC35A99D64E808c1430cEf08126"),
1765
+ ["stable-testnet" /* StableTestnet */]: bridgeChain("stable-testnet" /* StableTestnet */, 40374, 0.7, "0x779Ded0c9e1022225f8E0630b35a9b54bE713736"),
1743
1766
  // ─── 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" }
1767
+ ["stable" /* Stable */]: bridgeChain("stable" /* Stable */, 30396, 0.7, "0xedaba024be4d87974d5aB11C6Dd586963CcCB027"),
1768
+ ["ethereum" /* Ethereum */]: bridgeChain("ethereum" /* Ethereum */, 30101, 12, "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee"),
1769
+ ["arbitrum" /* Arbitrum */]: bridgeChain("arbitrum" /* Arbitrum */, 30110, 0.25, "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92"),
1770
+ ["ink" /* Ink */]: bridgeChain("ink" /* Ink */, 30339, 1, "0x1cB6De532588fCA4a21B7209DE7C456AF8434A65"),
1771
+ ["bera" /* Bera */]: bridgeChain("bera" /* Bera */, 30362, 2, "0x3Dc96399109df5ceb2C226664A086140bD0379cB"),
1772
+ ["megaeth" /* MegaETH */]: bridgeChain("megaeth" /* MegaETH */, 30398, 1, "0x9151434b16b9763660705744891fa906f660ecc5"),
1773
+ ["hyperevm" /* HyperEVM */]: bridgeChain("hyperevm" /* HyperEVM */, 30367, 1, "0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98"),
1774
+ ["polygon" /* Polygon */]: bridgeChain("polygon" /* Polygon */, 30109, 1.5, "0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13"),
1775
+ ["plasma" /* Plasma */]: bridgeChain("plasma" /* Plasma */, 30383, 1, "0x02ca37966753bDdDf11216B73B16C1dE756A7CF9"),
1776
+ ["optimism" /* Optimism */]: bridgeChain("optimism" /* Optimism */, 30111, 2, "0xF03b4d9AC1D5d1E7c4cEf54C2A313b9fe051A0aD"),
1777
+ ["unichain" /* Unichain */]: bridgeChain("unichain" /* Unichain */, 30320, 1, "0xc07bE8994D035631c36fb4a89C918CeFB2f03EC3"),
1778
+ ["sei" /* Sei */]: bridgeChain("sei" /* Sei */, 30280, 0.5, "0x56Fe74A2e3b484b921c447357203431a3485CC60"),
1779
+ ["flare" /* Flare */]: bridgeChain("flare" /* Flare */, 30295, 1.1, "0x567287d2A9829215a37e3B88843d32f9221E7588"),
1780
+ ["xlayer" /* XLayer */]: bridgeChain("xlayer" /* XLayer */, 30274, 1, "0x94BCCa6bdfd6A61817Ab0E960bFedE4984505554"),
1781
+ ["rootstock" /* Rootstock */]: bridgeChain("rootstock" /* Rootstock */, 30333, 31, "0x1a594d5d5d1c426281C1064B07f23F57B2716B61"),
1782
+ // XAUt0 only — BSC has no USDT0 deployment. Block time measured 2026-08-20.
1783
+ ["bsc" /* BSC */]: bridgeChain("bsc" /* BSC */, 30102, 0.45)
1784
+ };
1785
+ function bridgeAssetFor(cfg, token) {
1786
+ const needle = token.toLowerCase();
1787
+ return Object.keys(cfg.tokens).find(
1788
+ (asset) => _optionalChain([cfg, 'access', _36 => _36.tokens, 'access', _37 => _37[asset], 'optionalAccess', _38 => _38.address, 'access', _39 => _39.toLowerCase, 'call', _40 => _40()]) === needle
1789
+ );
1790
+ }
1791
+ function describeAssets(cfg) {
1792
+ const assets = Object.entries(cfg.tokens);
1793
+ if (assets.length === 0) return "no OFT assets";
1794
+ return assets.map(([asset, token]) => `${asset} (${token.address})`).join(" or ");
1795
+ }
1796
+ var SEND_PARAM_INPUT = {
1797
+ name: "_sendParam",
1798
+ type: "tuple",
1799
+ components: [
1800
+ { name: "dstEid", type: "uint32" },
1801
+ { name: "to", type: "bytes32" },
1802
+ { name: "amountLD", type: "uint256" },
1803
+ { name: "minAmountLD", type: "uint256" },
1804
+ { name: "extraOptions", type: "bytes" },
1805
+ { name: "composeMsg", type: "bytes" },
1806
+ { name: "oftCmd", type: "bytes" }
1807
+ ]
1751
1808
  };
1752
1809
  var OFT_ADAPTER_ABI = [
1753
1810
  {
1754
1811
  name: "quoteSend",
1755
1812
  type: "function",
1756
1813
  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
- },
1814
+ SEND_PARAM_INPUT,
1770
1815
  { name: "_payInLzToken", type: "bool" }
1771
1816
  ],
1772
1817
  outputs: [
@@ -1782,22 +1827,48 @@ var OFT_ADAPTER_ABI = [
1782
1827
  stateMutability: "view"
1783
1828
  },
1784
1829
  {
1785
- name: "send",
1830
+ // OFT-level accounting, independent of the LayerZero messaging fee: the
1831
+ // pathway's accepted range, any fee the adapter charges itself, and what the
1832
+ // recipient actually ends up credited.
1833
+ name: "quoteOFT",
1786
1834
  type: "function",
1787
1835
  inputs: [
1836
+ SEND_PARAM_INPUT
1837
+ ],
1838
+ outputs: [
1788
1839
  {
1789
- name: "_sendParam",
1840
+ name: "oftLimit",
1790
1841
  type: "tuple",
1791
1842
  components: [
1792
- { name: "dstEid", type: "uint32" },
1793
- { name: "to", type: "bytes32" },
1794
- { name: "amountLD", type: "uint256" },
1795
1843
  { name: "minAmountLD", type: "uint256" },
1796
- { name: "extraOptions", type: "bytes" },
1797
- { name: "composeMsg", type: "bytes" },
1798
- { name: "oftCmd", type: "bytes" }
1844
+ { name: "maxAmountLD", type: "uint256" }
1845
+ ]
1846
+ },
1847
+ {
1848
+ name: "oftFeeDetails",
1849
+ type: "tuple[]",
1850
+ components: [
1851
+ // Signed: a negative detail is a credit to the sender, not a charge.
1852
+ { name: "feeAmountLD", type: "int256" },
1853
+ { name: "description", type: "string" }
1799
1854
  ]
1800
1855
  },
1856
+ {
1857
+ name: "oftReceipt",
1858
+ type: "tuple",
1859
+ components: [
1860
+ { name: "amountSentLD", type: "uint256" },
1861
+ { name: "amountReceivedLD", type: "uint256" }
1862
+ ]
1863
+ }
1864
+ ],
1865
+ stateMutability: "view"
1866
+ },
1867
+ {
1868
+ name: "send",
1869
+ type: "function",
1870
+ inputs: [
1871
+ SEND_PARAM_INPUT,
1801
1872
  {
1802
1873
  name: "_fee",
1803
1874
  type: "tuple",
@@ -1812,117 +1883,324 @@ var OFT_ADAPTER_ABI = [
1812
1883
  stateMutability: "payable"
1813
1884
  }
1814
1885
  ];
1815
- function buildLzOptions(gasLimit = 0n) {
1886
+ var OAPP_ABI = [
1887
+ { name: "endpoint", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "address" }] }
1888
+ ];
1889
+ var ENDPOINT_V2_ABI = [
1890
+ {
1891
+ name: "getSendLibrary",
1892
+ type: "function",
1893
+ stateMutability: "view",
1894
+ inputs: [{ name: "_sender", type: "address" }, { name: "_dstEid", type: "uint32" }],
1895
+ outputs: [{ type: "address" }]
1896
+ }
1897
+ ];
1898
+ var SEND_ULN_ABI = [
1899
+ {
1900
+ name: "getUlnConfig",
1901
+ type: "function",
1902
+ stateMutability: "view",
1903
+ inputs: [{ name: "_oapp", type: "address" }, { name: "_remoteEid", type: "uint32" }],
1904
+ outputs: [
1905
+ {
1906
+ name: "rtnConfig",
1907
+ type: "tuple",
1908
+ components: [
1909
+ { name: "confirmations", type: "uint64" },
1910
+ { name: "requiredDVNCount", type: "uint8" },
1911
+ { name: "optionalDVNCount", type: "uint8" },
1912
+ { name: "optionalDVNThreshold", type: "uint8" },
1913
+ { name: "requiredDVNs", type: "address[]" },
1914
+ { name: "optionalDVNs", type: "address[]" }
1915
+ ]
1916
+ }
1917
+ ]
1918
+ }
1919
+ ];
1920
+ var LZ_SCAN_API = "https://scan.layerzero-api.com/v1";
1921
+ var LZ_SCAN_UI = "https://layerzeroscan.com";
1922
+ var CACHE_TTL_MS = 5 * 6e4;
1923
+ var cache = /* @__PURE__ */ new Map();
1924
+ function clearBridgeEstimateCache() {
1925
+ cache.clear();
1926
+ }
1927
+ async function cached(key, ttlMs, load) {
1928
+ const hit = cache.get(key);
1929
+ if (hit && Date.now() - hit.at < ttlMs) return hit.value;
1930
+ const value = await load();
1931
+ cache.set(key, { at: Date.now(), value });
1932
+ return value;
1933
+ }
1934
+ var ScanHttpError = class extends Error {
1935
+ constructor(status, path) {
1936
+ super(`LayerZero Scan ${status} for ${path}`);
1937
+ this.status = status;
1938
+ this.name = "ScanHttpError";
1939
+ }
1940
+ };
1941
+ async function scanFetch(path, timeoutMs = 8e3) {
1942
+ const res = await fetch(`${LZ_SCAN_API}${path}`, { signal: AbortSignal.timeout(timeoutMs) });
1943
+ if (!res.ok) throw new ScanHttpError(res.status, path);
1944
+ return await res.json();
1945
+ }
1946
+ var TERMINAL_FAILURE_STATUSES = /* @__PURE__ */ new Set([
1947
+ "FAILED",
1948
+ "BLOCKED",
1949
+ "PAYLOAD_STORED",
1950
+ "APPLICATION_BURNED",
1951
+ "APPLICATION_SKIPPED",
1952
+ "UNRESOLVABLE_COMMAND",
1953
+ "MALFORMED_COMMAND"
1954
+ ]);
1955
+ function median(values) {
1956
+ const sorted = [...values].sort((a, b) => a - b);
1957
+ const mid = Math.floor(sorted.length / 2);
1958
+ return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
1959
+ }
1960
+ var WORKER_EXECUTOR = 1;
1961
+ var OPTION_LZRECEIVE = 1;
1962
+ var OPTION_NATIVE_DROP = 2;
1963
+ function lzOption(optionType, payload) {
1964
+ const payloadBytes = (payload.length - 2) / 2;
1965
+ return _viem.concat.call(void 0, [
1966
+ _viem.numberToHex.call(void 0, WORKER_EXECUTOR, { size: 1 }),
1967
+ _viem.numberToHex.call(void 0, 1 + payloadBytes, { size: 2 }),
1968
+ _viem.numberToHex.call(void 0, optionType, { size: 1 }),
1969
+ payload
1970
+ ]);
1971
+ }
1972
+ function buildLzOptions(gasLimit = 0n, nativeDrop = 0n, dropReceiver) {
1973
+ const options = [
1974
+ lzOption(OPTION_LZRECEIVE, _viem.numberToHex.call(void 0, gasLimit, { size: 16 }))
1975
+ ];
1976
+ if (nativeDrop > 0n) {
1977
+ if (!dropReceiver) {
1978
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1979
+ "recipient",
1980
+ dropReceiver,
1981
+ "buildLzOptions: a native drop needs a receiver address"
1982
+ );
1983
+ }
1984
+ options.push(
1985
+ lzOption(
1986
+ OPTION_NATIVE_DROP,
1987
+ _viem.concat.call(void 0, [
1988
+ _viem.numberToHex.call(void 0, nativeDrop, { size: 16 }),
1989
+ _viem.padHex.call(void 0, dropReceiver, { dir: "left", size: 32 })
1990
+ ])
1991
+ )
1992
+ );
1993
+ }
1816
1994
  return _viem.concat.call(void 0, [
1817
1995
  _viem.numberToHex.call(void 0, 3, { size: 2 }),
1818
1996
  // 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
1997
+ ...options
1827
1998
  ]);
1828
1999
  }
2000
+ var FALLBACK_SEND_GAS = 400000n;
2001
+ function usableQuote(quote, amountLD) {
2002
+ if (!_optionalChain([quote, 'optionalAccess', _41 => _41.oft])) return quote;
2003
+ return quote.oft.amountSentLD <= amountLD ? quote : void 0;
2004
+ }
2005
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
1829
2006
  var LayerZeroService = class {
1830
2007
  constructor(config) {
1831
2008
  this.config = config;
1832
2009
  }
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,
2010
+ async quoteBridge(params) {
2011
+ const plan = this.plan(params, "quoteBridge");
2012
+ const [{ fee, oft }, estimate] = await Promise.all([
2013
+ this.quotePathway(plan, "quoteBridge"),
2014
+ this.estimateBridgeTime(params).catch(() => void 0)
2015
+ ]);
2016
+ const srcGas = await this.estimateSendGas(plan, fee, oft);
2017
+ return {
2018
+ ...fee,
2019
+ oft,
2020
+ // What the recipient is actually credited: input minus any OFT fee and
2021
+ // minus dust. Falls back to the input when quoteOFT could not be read.
2022
+ toAmount: _nullishCoalesce(_optionalChain([oft, 'optionalAccess', _42 => _42.amountReceived]), () => ( params.amount)),
2023
+ srcGas,
2024
+ totalCostWei: srcGas ? srcGas.costWei + fee.nativeFee : void 0,
2025
+ estimate
2026
+ };
2027
+ }
2028
+ /**
2029
+ * The LayerZero messaging fee for a send, plus the OFT's own accounting.
2030
+ *
2031
+ * The fee is required — a send cannot be built without it. The OFT accounting is
2032
+ * best-effort: an adapter that does not answer `quoteOFT` costs us the fee
2033
+ * breakdown and the exact output amount, not the whole quote.
2034
+ */
2035
+ async quotePathway(plan, method) {
2036
+ const sendParam = this.buildSendParams(plan, 0n);
2037
+ const [msgFee, oft] = await Promise.all([
2038
+ plan.pc.readContract({
2039
+ address: plan.oftAdapter,
1845
2040
  abi: OFT_ADAPTER_ABI,
1846
2041
  functionName: "quoteSend",
1847
- args: [this.buildSendParams(dst, amountLD, recipientAddr), false]
2042
+ args: [sendParam, false]
2043
+ }).catch((err) => {
2044
+ throw new (0, _chunkQQ26UI3Fcjs.StableQuoteError)({
2045
+ provider: "layerzero",
2046
+ 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`,
2047
+ cause: err
2048
+ });
2049
+ }),
2050
+ this.readOftQuote(plan, sendParam)
2051
+ ]);
2052
+ const { nativeFee, lzTokenFee } = msgFee;
2053
+ return { fee: { nativeFee, lzTokenFee }, oft };
2054
+ }
2055
+ /**
2056
+ * The adapter's own view of a send: accepted range, its fees, and what lands on
2057
+ * the far side. Resolves to `undefined` rather than throwing — see `quoteSend`.
2058
+ */
2059
+ async readOftQuote(plan, sendParam) {
2060
+ try {
2061
+ const [limit, feeDetails, receipt] = await plan.pc.readContract({
2062
+ address: plan.oftAdapter,
2063
+ abi: OFT_ADAPTER_ABI,
2064
+ functionName: "quoteOFT",
2065
+ args: [sendParam]
2066
+ });
2067
+ const decimals = plan.srcToken.decimals;
2068
+ return {
2069
+ amountSentLD: receipt.amountSentLD,
2070
+ amountReceivedLD: receipt.amountReceivedLD,
2071
+ amountReceived: Number(_viem.formatUnits.call(void 0, receipt.amountReceivedLD, decimals)),
2072
+ fees: feeDetails.map((detail) => ({
2073
+ amountLD: detail.feeAmountLD,
2074
+ amount: Number(_viem.formatUnits.call(void 0, detail.feeAmountLD, decimals)),
2075
+ description: detail.description
2076
+ })),
2077
+ minAmountLD: limit.minAmountLD,
2078
+ maxAmountLD: limit.maxAmountLD
2079
+ };
2080
+ } catch (e5) {
2081
+ return void 0;
2082
+ }
2083
+ }
2084
+ /**
2085
+ * Source-chain cost of the `send` transaction.
2086
+ *
2087
+ * Simulating the real call is the only honest answer, and it needs a sender with
2088
+ * the allowance and the native balance already in place — which a quote taken
2089
+ * before approving does not have. When the simulation reverts, fall back to a
2090
+ * measured constant so the caller still has a cost to show, flagged as such.
2091
+ */
2092
+ async estimateSendGas(plan, fee, oft) {
2093
+ const gasPriceWei = await this.gasPrice(plan);
2094
+ if (gasPriceWei === void 0) return void 0;
2095
+ let gas = FALLBACK_SEND_GAS;
2096
+ let source = "fallback";
2097
+ const account = this.signerAddress();
2098
+ if (account) {
2099
+ try {
2100
+ gas = await plan.pc.estimateContractGas({
2101
+ address: plan.oftAdapter,
2102
+ abi: OFT_ADAPTER_ABI,
2103
+ functionName: "send",
2104
+ args: [
2105
+ this.buildSendParams(plan, _nullishCoalesce(_optionalChain([oft, 'optionalAccess', _43 => _43.amountReceivedLD]), () => ( plan.amountLD))),
2106
+ fee,
2107
+ account
2108
+ ],
2109
+ account,
2110
+ value: fee.nativeFee
2111
+ });
2112
+ source = "simulated";
2113
+ } catch (e6) {
2114
+ }
2115
+ }
2116
+ return { gas, gasPriceWei, costWei: gas * gasPriceWei, source };
2117
+ }
2118
+ /** Price per gas unit on the source chain, or undefined if the RPC won't say. */
2119
+ async gasPrice(plan) {
2120
+ try {
2121
+ const fees = await plan.pc.estimateFeesPerGas();
2122
+ const price = _nullishCoalesce(fees.maxFeePerGas, () => ( fees.gasPrice));
2123
+ if (price !== void 0) return price;
2124
+ } catch (e7) {
2125
+ }
2126
+ try {
2127
+ return await plan.pc.getGasPrice();
2128
+ } catch (e8) {
2129
+ return void 0;
2130
+ }
2131
+ }
2132
+ /**
2133
+ * Top the adapter's allowance up to `amountLD` when it is short. Only the
2134
+ * lockbox chain reaches here — remote deployments burn from the caller.
2135
+ */
2136
+ async ensureAllowance(plan, wc, owner, amountLD) {
2137
+ const { src, asset, srcToken, oftAdapter, pc, chain: srcChain } = plan;
2138
+ const allowance = await pc.readContract({
2139
+ address: srcToken.address,
2140
+ abi: _viem.erc20Abi,
2141
+ functionName: "allowance",
2142
+ args: [owner, oftAdapter]
2143
+ });
2144
+ if (allowance >= amountLD) return;
2145
+ let approveHash;
2146
+ try {
2147
+ approveHash = await wc.writeContract({
2148
+ address: srcToken.address,
2149
+ abi: _viem.erc20Abi,
2150
+ functionName: "approve",
2151
+ args: [oftAdapter, amountLD],
2152
+ account: wc.account,
2153
+ chain: srcChain
1848
2154
  });
1849
- return { nativeFee, lzTokenFee, toAmount: amount };
1850
2155
  } catch (err) {
1851
- throw new StableQuoteError({
1852
- provider: "layerzero",
1853
- shortMessage: "quoteBridge: quoteSend call failed",
2156
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
2157
+ phase: "approve",
2158
+ shortMessage: `bridge: ${asset} approve failed`,
2159
+ chainId: src.id,
1854
2160
  cause: err
1855
2161
  });
1856
2162
  }
2163
+ const approveReceipt = await pc.waitForTransactionReceipt({ hash: approveHash });
2164
+ if (approveReceipt.status === "reverted") {
2165
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
2166
+ phase: "approve",
2167
+ shortMessage: `bridge: ${asset} approve reverted on-chain`,
2168
+ txHash: approveReceipt.transactionHash,
2169
+ chainId: src.id
2170
+ });
2171
+ }
1857
2172
  }
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])));
2173
+ async bridge(params) {
2174
+ const from = this.signerAddress();
1860
2175
  if (!from) {
1861
- throw new StableValidationError(
2176
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1862
2177
  "signer",
1863
2178
  void 0,
1864
2179
  "bridge: requires a signer \u2014 set walletClient or account in StableConfig"
1865
2180
  );
1866
2181
  }
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);
2182
+ const plan = this.plan({ ...params, recipient: _nullishCoalesce(params.recipient, () => ( from)) }, "bridge");
2183
+ const { src, srcToken, oftAdapter, amountLD, chain: srcChain } = plan;
1872
2184
  const wc = _nullishCoalesce(this.config.walletClient, () => ( _viem.createWalletClient.call(void 0, {
1873
2185
  account: this.config.account,
1874
2186
  chain: srcChain,
1875
2187
  transport: _nullishCoalesce(this.config.transport, () => ( _viem.http.call(void 0, src.rpc)))
1876
2188
  })));
1877
- const pc = _viem.createPublicClient.call(void 0, { chain: srcChain, transport: _viem.http.call(void 0, src.rpc) });
1878
2189
  try {
1879
2190
  await wc.switchChain({ id: src.id });
1880
2191
  } catch (err) {
1881
- throw new StableTransactionError({
2192
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
1882
2193
  phase: "switch_chain",
1883
2194
  shortMessage: `bridge: wallet rejected or failed to switch to chain ${src.id}`,
1884
2195
  chainId: src.id,
1885
2196
  cause: err
1886
2197
  });
1887
2198
  }
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
- }
2199
+ const quote = usableQuote(params.quote, amountLD);
2200
+ const { nativeFee, lzTokenFee, oft } = _optionalChain([quote, 'optionalAccess', _44 => _44.nativeFee]) !== void 0 && _optionalChain([quote, 'optionalAccess', _45 => _45.lzTokenFee]) !== void 0 ? { nativeFee: quote.nativeFee, lzTokenFee: quote.lzTokenFee, oft: quote.oft } : await this.quotePathway(plan, "bridge").then((r) => ({ ...r.fee, oft: r.oft }));
2201
+ const sendParams = this.buildSendParams(plan, _nullishCoalesce(_optionalChain([oft, 'optionalAccess', _46 => _46.amountReceivedLD]), () => ( amountLD)));
2202
+ if (srcToken.approvalRequired !== false) {
2203
+ await this.ensureAllowance(plan, wc, from, amountLD);
1926
2204
  }
1927
2205
  try {
1928
2206
  const hash = await wc.writeContract({
@@ -1934,9 +2212,9 @@ var LayerZeroService = class {
1934
2212
  account: wc.account,
1935
2213
  chain: srcChain
1936
2214
  });
1937
- return { txHash: hash, toAmount: amount };
2215
+ return { txHash: hash, toAmount: _nullishCoalesce(_optionalChain([oft, 'optionalAccess', _47 => _47.amountReceived]), () => ( params.amount)) };
1938
2216
  } catch (err) {
1939
- throw new StableTransactionError({
2217
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
1940
2218
  phase: "send",
1941
2219
  shortMessage: "bridge: OFT send failed",
1942
2220
  chainId: src.id,
@@ -1944,60 +2222,244 @@ var LayerZeroService = class {
1944
2222
  });
1945
2223
  }
1946
2224
  }
2225
+ /**
2226
+ * Estimate how long a USDT0 bridge will take, end to end.
2227
+ *
2228
+ * Two independent inputs, both cheap:
2229
+ * - **observed** — median delivery time of recent messages LayerZero Scan has
2230
+ * already settled on this exact pathway.
2231
+ * - **formula** — LayerZero's documented estimate from the on-chain ULN config:
2232
+ * `srcBlockTime × confirmations + dstBlockTime × (2 + dvnCount)`.
2233
+ *
2234
+ * `observed` wins when available. The formula assumes `confirmations` is the whole
2235
+ * wait, which holds for L1 sources but badly understates rollups: Arbitrum→Stable
2236
+ * computes to ~15s (60 blocks × 0.25s) while real deliveries take ~18min, because
2237
+ * the DVNs wait for the L2 batch to finalize on L1.
2238
+ */
2239
+ async estimateBridgeTime({
2240
+ fromChain,
2241
+ toChain,
2242
+ fromToken,
2243
+ toToken
2244
+ }) {
2245
+ const src = BRIDGE_CHAIN_CONFIGS[fromChain];
2246
+ const dst = BRIDGE_CHAIN_CONFIGS[toChain];
2247
+ const from = _nullishCoalesce(fromToken, () => ( _optionalChain([src, 'optionalAccess', _48 => _48.tokens, 'access', _49 => _49.usdt0, 'optionalAccess', _50 => _50.address])));
2248
+ const to = _nullishCoalesce(toToken, () => ( _optionalChain([dst, 'optionalAccess', _51 => _51.tokens, 'access', _52 => _52.usdt0, 'optionalAccess', _53 => _53.address])));
2249
+ if (!(src && from)) {
2250
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)("fromChain", fromChain, `estimateBridgeTime: no OFT adapter for "${fromChain}"`);
2251
+ }
2252
+ if (!(dst && to)) {
2253
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)("toChain", toChain, `estimateBridgeTime: no OFT adapter for "${toChain}"`);
2254
+ }
2255
+ const { srcToken, dstToken } = this.resolveRoute(fromChain, toChain, from, to);
2256
+ const [uln, observedSeconds] = await Promise.all([
2257
+ this.getUlnConfig(src, dst, srcToken.oftAdapter).catch(() => void 0),
2258
+ this.observedBridgeSeconds(src, dst, srcToken.oftAdapter, dstToken.oftAdapter).catch(() => void 0)
2259
+ ]);
2260
+ const dvnCount = uln ? uln.requiredDVNCount + uln.optionalDVNCount : void 0;
2261
+ let formulaSeconds;
2262
+ if (uln && dvnCount !== void 0 && src.blockTimeSec && dst.blockTimeSec) {
2263
+ const computed = Math.round(
2264
+ uln.confirmations * src.blockTimeSec + dst.blockTimeSec * (2 + dvnCount)
2265
+ );
2266
+ formulaSeconds = Number.isFinite(computed) ? computed : void 0;
2267
+ }
2268
+ const seconds = _nullishCoalesce(observedSeconds, () => ( formulaSeconds));
2269
+ if (seconds === void 0) {
2270
+ throw new (0, _chunkQQ26UI3Fcjs.StableQuoteError)({
2271
+ provider: "layerzero",
2272
+ shortMessage: `estimateBridgeTime: no pathway data for ${fromChain}\u2192${toChain}`
2273
+ });
2274
+ }
2275
+ return {
2276
+ seconds,
2277
+ source: observedSeconds !== void 0 ? "observed" : "formula",
2278
+ observedSeconds,
2279
+ formulaSeconds,
2280
+ confirmations: Number.isFinite(_optionalChain([uln, 'optionalAccess', _54 => _54.confirmations])) ? _optionalChain([uln, 'optionalAccess', _55 => _55.confirmations]) : void 0,
2281
+ dvnCount: Number.isFinite(dvnCount) ? dvnCount : void 0
2282
+ };
2283
+ }
2284
+ /**
2285
+ * Follow an in-flight bridge by its source transaction hash. Poll this after
2286
+ * `bridge()` to drive a progress UI; a message LayerZero Scan has not indexed
2287
+ * yet reports `"pending"` rather than throwing.
2288
+ */
2289
+ async trackBridge(srcTxHash) {
2290
+ const scanUrl = `${LZ_SCAN_UI}/tx/${srcTxHash}`;
2291
+ let message;
2292
+ try {
2293
+ message = await _asyncOptionalChain([(await scanFetch(`/messages/tx/${srcTxHash}`)), 'optionalAccess', async _56 => _56.data, 'optionalAccess', async _57 => _57[0]]);
2294
+ } catch (err) {
2295
+ if (err instanceof ScanHttpError && err.status === 404) {
2296
+ return { state: "pending", srcTxHash, scanUrl };
2297
+ }
2298
+ throw new (0, _chunkQQ26UI3Fcjs.StableQuoteError)({
2299
+ provider: "layerzero",
2300
+ shortMessage: `trackBridge: LayerZero Scan lookup failed for ${srcTxHash}`,
2301
+ cause: err
2302
+ });
2303
+ }
2304
+ if (!message) return { state: "pending", srcTxHash, scanUrl };
2305
+ const raw = _nullishCoalesce(_optionalChain([message, 'access', _58 => _58.status, 'optionalAccess', _59 => _59.name]), () => ( ""));
2306
+ const sentAt = _optionalChain([message, 'access', _60 => _60.source, 'optionalAccess', _61 => _61.tx, 'optionalAccess', _62 => _62.blockTimestamp]);
2307
+ return {
2308
+ // Everything terminal that is not DELIVERED means the tokens will not land
2309
+ // on their own; `raw` carries which of those it was.
2310
+ state: raw === "DELIVERED" ? "delivered" : TERMINAL_FAILURE_STATUSES.has(raw) ? "failed" : "inflight",
2311
+ raw,
2312
+ srcTxHash,
2313
+ dstTxHash: _optionalChain([message, 'access', _63 => _63.destination, 'optionalAccess', _64 => _64.tx, 'optionalAccess', _65 => _65.txHash]),
2314
+ elapsedSeconds: sentAt ? Math.max(0, Math.floor(Date.now() / 1e3) - sentAt) : void 0,
2315
+ scanUrl
2316
+ };
2317
+ }
2318
+ /** Effective ULN config the DVNs enforce for this pathway, read from the source chain. */
2319
+ async getUlnConfig(src, dst, oapp) {
2320
+ return cached(`uln:${src.lzEid}-${dst.lzEid}-${oapp.toLowerCase()}`, CACHE_TTL_MS, async () => {
2321
+ const pc = _viem.createPublicClient.call(void 0, { chain: makeChain(src.id, src.rpc), transport: _viem.http.call(void 0, src.rpc) });
2322
+ const endpoint = await pc.readContract({ address: oapp, abi: OAPP_ABI, functionName: "endpoint" });
2323
+ const sendLib = await pc.readContract({
2324
+ address: endpoint,
2325
+ abi: ENDPOINT_V2_ABI,
2326
+ functionName: "getSendLibrary",
2327
+ args: [oapp, dst.lzEid]
2328
+ });
2329
+ const cfg = await pc.readContract({
2330
+ address: sendLib,
2331
+ abi: SEND_ULN_ABI,
2332
+ functionName: "getUlnConfig",
2333
+ args: [oapp, dst.lzEid]
2334
+ });
2335
+ return {
2336
+ confirmations: Number(cfg.confirmations),
2337
+ requiredDVNCount: Number(cfg.requiredDVNCount),
2338
+ optionalDVNCount: Number(cfg.optionalDVNCount)
2339
+ };
2340
+ });
2341
+ }
2342
+ /** Median delivery time of recently delivered messages on this pathway, in seconds. */
2343
+ async observedBridgeSeconds(src, dst, srcOapp, dstOapp) {
2344
+ const pathwayId = `${src.lzEid}-${dst.lzEid}-${srcOapp.toLowerCase()}-${dstOapp.toLowerCase()}`;
2345
+ return cached(`observed:${pathwayId}`, CACHE_TTL_MS, async () => {
2346
+ const { data } = await scanFetch(`/messages/pathway/${pathwayId}?limit=50`);
2347
+ const durations = (_nullishCoalesce(data, () => ( []))).filter((m) => _optionalChain([m, 'access', _66 => _66.status, 'optionalAccess', _67 => _67.name]) === "DELIVERED").map((m) => (_nullishCoalesce(_optionalChain([m, 'access', _68 => _68.destination, 'optionalAccess', _69 => _69.tx, 'optionalAccess', _70 => _70.blockTimestamp]), () => ( 0))) - (_nullishCoalesce(_optionalChain([m, 'access', _71 => _71.source, 'optionalAccess', _72 => _72.tx, 'optionalAccess', _73 => _73.blockTimestamp]), () => ( 0)))).filter((d) => d > 0);
2348
+ return durations.length >= 3 ? Math.round(median(durations)) : void 0;
2349
+ });
2350
+ }
1947
2351
  validateBridgeParams(params, method) {
1948
2352
  if (!_viem.isAddress.call(void 0, params.recipient)) {
1949
- throw new StableValidationError(
2353
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1950
2354
  "recipient",
1951
2355
  params.recipient,
1952
2356
  `${method}: invalid recipient address "${params.recipient}"`
1953
2357
  );
1954
2358
  }
1955
2359
  if (!Number.isFinite(params.amount) || params.amount <= 0) {
1956
- throw new StableValidationError(
2360
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1957
2361
  "amount",
1958
2362
  params.amount,
1959
2363
  `${method}: amount must be a finite positive number`
1960
2364
  );
1961
2365
  }
1962
2366
  if (params.fromChain === params.toChain) {
1963
- throw new StableValidationError(
2367
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1964
2368
  "toChain",
1965
2369
  params.toChain,
1966
2370
  `${method}: fromChain and toChain must differ`
1967
2371
  );
1968
2372
  }
1969
2373
  }
1970
- resolveChains(fromChain, toChain, fromToken, toToken) {
2374
+ /**
2375
+ * Resolve a bridge request to one OFT mesh and its two endpoints.
2376
+ *
2377
+ * Both sides must name the same asset. An OFT escrows one specific ERC-20 and
2378
+ * mints its own peer on the far side — it cannot hand back a different token,
2379
+ * so a USDT0→XAUt0 request is a trade, not a bridge, and belongs to LI.FI.
2380
+ */
2381
+ resolveRoute(fromChain, toChain, fromToken, toToken) {
1971
2382
  const src = BRIDGE_CHAIN_CONFIGS[fromChain];
1972
2383
  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(
2384
+ if (!src) throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)("fromChain", fromChain, `Unsupported source chain: "${fromChain}"`);
2385
+ if (!dst) throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)("toChain", toChain, `Unsupported destination chain: "${toChain}"`);
2386
+ const asset = bridgeAssetFor(src, fromToken);
2387
+ if (!asset) {
2388
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1980
2389
  "fromToken",
1981
2390
  fromToken,
1982
- `USDT0 bridge only moves USDT0 \u2014 fromToken must be ${src.usdt} on "${fromChain}", got "${fromToken}". Use route "lifi" to bridge other tokens.`
2391
+ `Native OFT bridge does not recognize "${fromToken}" on "${fromChain}" \u2014 it moves ${describeAssets(src)}. Use route "lifi" to bridge other tokens.`
2392
+ );
2393
+ }
2394
+ const srcToken = src.tokens[asset];
2395
+ const dstToken = dst.tokens[asset];
2396
+ if (!dstToken) {
2397
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2398
+ "toChain",
2399
+ toChain,
2400
+ `Native OFT bridge cannot deliver ${asset} to "${toChain}" \u2014 no ${asset} deployment there. Use route "lifi" instead.`
1983
2401
  );
1984
2402
  }
1985
- if (toToken.toLowerCase() !== dst.usdt.toLowerCase()) {
1986
- throw new StableValidationError(
2403
+ if (dstToken.address.toLowerCase() !== toToken.toLowerCase()) {
2404
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
1987
2405
  "toToken",
1988
2406
  toToken,
1989
- `USDT0 bridge only moves USDT0 \u2014 toToken must be ${dst.usdt} on "${toChain}", got "${toToken}". Use route "lifi" to bridge other tokens.`
2407
+ `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.`
2408
+ );
2409
+ }
2410
+ return { src, dst, asset, srcToken, dstToken };
2411
+ }
2412
+ /**
2413
+ * Validate a request and resolve it to a single OFT pathway. No network calls —
2414
+ * everything here is config, arithmetic and encoding.
2415
+ */
2416
+ plan(params, method) {
2417
+ const { fromChain, toChain, fromToken, toToken, amount, recipient, dstNativeDrop } = params;
2418
+ const recipientAddr = _nullishCoalesce(recipient, () => ( ZERO_ADDRESS));
2419
+ this.validateBridgeParams({ fromChain, toChain, amount, recipient: recipientAddr }, method);
2420
+ if (dstNativeDrop !== void 0 && dstNativeDrop < 0n) {
2421
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2422
+ "dstNativeDrop",
2423
+ dstNativeDrop,
2424
+ `${method}: dstNativeDrop must not be negative`
1990
2425
  );
1991
2426
  }
1992
- return { src, dst };
2427
+ const { src, dst, asset, srcToken, dstToken } = this.resolveRoute(
2428
+ fromChain,
2429
+ toChain,
2430
+ fromToken,
2431
+ toToken
2432
+ );
2433
+ const chain = makeChain(src.id, src.rpc);
2434
+ return {
2435
+ src,
2436
+ dst,
2437
+ asset,
2438
+ srcToken,
2439
+ dstToken,
2440
+ oftAdapter: srcToken.oftAdapter,
2441
+ amountLD: _viem.parseUnits.call(void 0, String(amount), srcToken.decimals),
2442
+ recipient: recipientAddr,
2443
+ nativeDrop: _nullishCoalesce(dstNativeDrop, () => ( 0n)),
2444
+ chain,
2445
+ pc: _viem.createPublicClient.call(void 0, { chain, transport: _viem.http.call(void 0, src.rpc) })
2446
+ };
2447
+ }
2448
+ /** The address that will sign, or undefined when this service has no signer. */
2449
+ signerAddress() {
2450
+ return _nullishCoalesce(_optionalChain([this, 'access', _74 => _74.config, 'access', _75 => _75.walletClient, 'optionalAccess', _76 => _76.account, 'optionalAccess', _77 => _77.address]), () => ( _optionalChain([this, 'access', _78 => _78.config, 'access', _79 => _79.account, 'optionalAccess', _80 => _80.address])));
1993
2451
  }
1994
- buildSendParams(dst, amountLD, recipient) {
2452
+ /**
2453
+ * `SendParam` for one call. `minAmountLD` is the caller's slippage floor: 0 when
2454
+ * asking what a send would yield, and the quoted output when actually sending.
2455
+ */
2456
+ buildSendParams(plan, minAmountLD) {
1995
2457
  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(),
2458
+ dstEid: plan.dst.lzEid,
2459
+ to: _viem.padHex.call(void 0, plan.recipient, { dir: "left", size: 32 }),
2460
+ amountLD: plan.amountLD,
2461
+ minAmountLD,
2462
+ extraOptions: buildLzOptions(0n, plan.nativeDrop, plan.recipient),
2001
2463
  composeMsg: "0x",
2002
2464
  oftCmd: "0x"
2003
2465
  };
@@ -2005,21 +2467,37 @@ var LayerZeroService = class {
2005
2467
  };
2006
2468
 
2007
2469
  // src/stable.ts
2008
- function isUsdt0Route(fromChain, toChain, fromToken, toToken) {
2470
+ function isNativeOftRoute(fromChain, toChain, fromToken, toToken) {
2009
2471
  const src = BRIDGE_CHAIN_CONFIGS[fromChain];
2010
2472
  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();
2473
+ if (!(src && dst)) return false;
2474
+ const asset = bridgeAssetFor(src, fromToken);
2475
+ if (!asset) return false;
2476
+ const srcToken = src.tokens[asset];
2477
+ const dstToken = dst.tokens[asset];
2478
+ return src.lzOutbound !== false && !!srcToken && srcToken.lzOutbound !== false && !!dstToken && dstToken.address.toLowerCase() === toToken.toLowerCase();
2012
2479
  }
2013
2480
  function selectBridge(params) {
2481
+ const selected = resolveBridge(params);
2482
+ if (selected === "lifi" && (_nullishCoalesce(params.dstNativeDrop, () => ( 0n))) > 0n) {
2483
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2484
+ "dstNativeDrop",
2485
+ params.dstNativeDrop,
2486
+ `bridge: dstNativeDrop is only supported on the native OFT route, and ${params.fromChain}\u2192${params.toChain} resolved to LI.FI`
2487
+ );
2488
+ }
2489
+ return selected;
2490
+ }
2491
+ function resolveBridge(params) {
2014
2492
  const route = _nullishCoalesce(params.route, () => ( "auto"));
2015
- if (route === "usdt0") return "usdt0";
2493
+ if (route === "oft" || route === "usdt0") return "oft";
2016
2494
  if (route === "lifi") return "lifi";
2017
- return isUsdt0Route(
2495
+ return isNativeOftRoute(
2018
2496
  params.fromChain,
2019
2497
  params.toChain,
2020
2498
  params.fromToken,
2021
2499
  params.toToken
2022
- ) ? "usdt0" : "lifi";
2500
+ ) ? "oft" : "lifi";
2023
2501
  }
2024
2502
  function validateTransferParams({
2025
2503
  to,
@@ -2028,28 +2506,28 @@ function validateTransferParams({
2028
2506
  tokenDecimals
2029
2507
  }) {
2030
2508
  if (!_viem.isAddress.call(void 0, to)) {
2031
- throw new StableValidationError(
2509
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2032
2510
  "to",
2033
2511
  to,
2034
2512
  `transfer: invalid recipient address "${to}"`
2035
2513
  );
2036
2514
  }
2037
2515
  if (!Number.isFinite(amount) || amount <= 0) {
2038
- throw new StableValidationError(
2516
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2039
2517
  "amount",
2040
2518
  amount,
2041
2519
  "transfer: amount must be a finite positive number"
2042
2520
  );
2043
2521
  }
2044
2522
  if (token !== void 0 && !_viem.isAddress.call(void 0, token)) {
2045
- throw new StableValidationError(
2523
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2046
2524
  "token",
2047
2525
  token,
2048
2526
  `transfer: invalid token address "${token}"`
2049
2527
  );
2050
2528
  }
2051
2529
  if (tokenDecimals !== void 0 && (!Number.isInteger(tokenDecimals) || tokenDecimals < 0 || tokenDecimals > 77)) {
2052
- throw new StableValidationError(
2530
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2053
2531
  "tokenDecimals",
2054
2532
  tokenDecimals,
2055
2533
  "transfer: tokenDecimals must be an integer between 0 and 77"
@@ -2064,8 +2542,8 @@ async function resolveTokenDecimals(publicClient, token, tokenDecimals) {
2064
2542
  abi: _viem.erc20Abi,
2065
2543
  functionName: "decimals"
2066
2544
  });
2067
- } catch (e6) {
2068
- throw new StableValidationError(
2545
+ } catch (e9) {
2546
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2069
2547
  "tokenDecimals",
2070
2548
  void 0,
2071
2549
  `transfer: could not fetch decimals for token "${token}" \u2014 pass tokenDecimals explicitly`
@@ -2075,7 +2553,7 @@ async function resolveTokenDecimals(publicClient, token, tokenDecimals) {
2075
2553
  async function executeTokenTransfer(wc, publicClient, token, to, amount, tokenDecimals, acc, chain) {
2076
2554
  const code = await publicClient.getCode({ address: token });
2077
2555
  if (!code || code === "0x") {
2078
- throw new StableValidationError(
2556
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2079
2557
  "token",
2080
2558
  token,
2081
2559
  `transfer: no contract found at "${token}" on chain ${chain.id} \u2014 check the address and network`
@@ -2119,9 +2597,15 @@ function createStable({
2119
2597
  chainId: chain.id,
2120
2598
  vault: earnConfig.vault
2121
2599
  }) : null;
2600
+ const erc3009Client = walletClient ? walletClient : account ? _viem.createWalletClient.call(void 0, {
2601
+ account,
2602
+ chain,
2603
+ transport: _nullishCoalesce(transport, () => ( _viem.http.call(void 0, rpc)))
2604
+ }) : _viem.createPublicClient.call(void 0, { chain, transport: _viem.http.call(void 0, rpc) });
2605
+ const authorization = _chunkQQ26UI3Fcjs.erc3009Actions.call(void 0, erc3009Client);
2122
2606
  function requireEarn() {
2123
2607
  if (!morpho) {
2124
- throw new StableValidationError(
2608
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2125
2609
  "earn",
2126
2610
  void 0,
2127
2611
  "stable.earn.*: pass earn: { vault: '0x...' } to createStable() to enable earn operations"
@@ -2130,9 +2614,9 @@ function createStable({
2130
2614
  return morpho;
2131
2615
  }
2132
2616
  function requireSignerAddress() {
2133
- const from = _nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _46 => _46.account, 'optionalAccess', _47 => _47.address]), () => ( _optionalChain([account, 'optionalAccess', _48 => _48.address])));
2617
+ const from = _nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _81 => _81.account, 'optionalAccess', _82 => _82.address]), () => ( _optionalChain([account, 'optionalAccess', _83 => _83.address])));
2134
2618
  if (!from) {
2135
- throw new StableValidationError(
2619
+ throw new (0, _chunkQQ26UI3Fcjs.StableValidationError)(
2136
2620
  "signer",
2137
2621
  void 0,
2138
2622
  "stable.rewards.*: requires a signer \u2014 set walletClient or account in StableConfig"
@@ -2143,7 +2627,7 @@ function createStable({
2143
2627
  async function transfer(params) {
2144
2628
  validateTransferParams(params);
2145
2629
  const { from, to, amount, token, tokenDecimals } = params;
2146
- const acc = _nullishCoalesce(_nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _49 => _49.account]), () => ( account)), () => ( from));
2630
+ const acc = _nullishCoalesce(_nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _84 => _84.account]), () => ( account)), () => ( from));
2147
2631
  const wc = _nullishCoalesce(walletClient, () => ( _viem.createWalletClient.call(void 0, {
2148
2632
  account: acc,
2149
2633
  chain,
@@ -2152,7 +2636,7 @@ function createStable({
2152
2636
  try {
2153
2637
  await wc.switchChain({ id: chain.id });
2154
2638
  } catch (err) {
2155
- throw new StableTransactionError({
2639
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
2156
2640
  phase: "switch_chain",
2157
2641
  shortMessage: `transfer: wallet rejected or failed to switch to chain ${chain.id}`,
2158
2642
  chainId: chain.id,
@@ -2184,7 +2668,7 @@ function createStable({
2184
2668
  );
2185
2669
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
2186
2670
  if (receipt.status === "reverted") {
2187
- throw new StableTransactionError({
2671
+ throw new (0, _chunkQQ26UI3Fcjs.StableTransactionError)({
2188
2672
  phase: "receipt",
2189
2673
  shortMessage: "transfer: transaction reverted on-chain",
2190
2674
  txHash: receipt.transactionHash,
@@ -2195,10 +2679,15 @@ function createStable({
2195
2679
  }
2196
2680
  return {
2197
2681
  transfer,
2198
- quoteBridge: (params) => selectBridge(params) === "usdt0" ? lz.quoteBridge(params) : lifi.quoteBridge(params),
2199
- bridge: (params) => selectBridge(params) === "usdt0" ? lz.bridge(params) : lifi.bridge(params),
2682
+ // `async` so a rejected route (see selectBridge) surfaces as a rejected
2683
+ // promise like every other validation error, not a synchronous throw.
2684
+ quoteBridge: async (params) => selectBridge(params) === "oft" ? lz.quoteBridge(params) : lifi.quoteBridge(params),
2685
+ bridge: async (params) => selectBridge(params) === "oft" ? lz.bridge(params) : lifi.bridge(params),
2686
+ estimateBridgeTime: (params) => lz.estimateBridgeTime(params),
2687
+ trackBridge: (srcTxHash) => lz.trackBridge(srcTxHash),
2200
2688
  quoteSwap: (params) => lifi.quoteSwap(params),
2201
2689
  swap: (params) => lifi.swap(params),
2690
+ authorization,
2202
2691
  earn: {
2203
2692
  deposit: (params) => requireEarn().deposit(params),
2204
2693
  bulkDeposit: (items, options) => requireEarn().bulkDeposit(items, options),
@@ -2235,9 +2724,6 @@ function createStableReader(config) {
2235
2724
  };
2236
2725
  }
2237
2726
 
2238
- // src/constants.ts
2239
- var STABLE_USDT_ADDRESS = "0x779ded0c9e1022225f8e0630b35a9b54be713736";
2240
- var STABLE_VAULT_ADDRESS = "0xb7Df8db22A5DBBFA9ebeb94b3910aec6a4f05c08";
2241
2727
 
2242
2728
 
2243
2729
 
@@ -2253,4 +2739,16 @@ var STABLE_VAULT_ADDRESS = "0xb7Df8db22A5DBBFA9ebeb94b3910aec6a4f05c08";
2253
2739
 
2254
2740
 
2255
2741
 
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;
2742
+
2743
+
2744
+
2745
+
2746
+
2747
+
2748
+
2749
+
2750
+
2751
+
2752
+
2753
+
2754
+ 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.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.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;