@stablechain/sdk 1.0.2 → 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
@@ -126,7 +126,11 @@ var HttpError = class extends Error {
126
126
  };
127
127
  function isRetryableError(err) {
128
128
  if (err instanceof HttpError) return err.retryable;
129
- return err instanceof TypeError;
129
+ if (err instanceof TypeError) {
130
+ const msg = err.message.toLowerCase();
131
+ return !(msg.includes("cors") || msg.includes("blocked"));
132
+ }
133
+ return false;
130
134
  }
131
135
  async function retryWithBackoff(fn, isRetryable = isRetryableError, opts = {}) {
132
136
  const maxAttempts = _nullishCoalesce(opts.maxAttempts, () => ( 3));
@@ -166,6 +170,7 @@ var MorphoService = class {
166
170
  })
167
171
  });
168
172
  this.morpho = new (0, _morphosdk.MorphoClient)(morphoWc, { supportSignature: true });
173
+ this.morphoNoSig = new (0, _morphosdk.MorphoClient)(morphoWc, { supportSignature: false });
169
174
  this.pc = _viem.createPublicClient.call(void 0, {
170
175
  chain: this.chain,
171
176
  transport: _viem.http.call(void 0, config.rpc)
@@ -303,6 +308,109 @@ var MorphoService = class {
303
308
  () => this._forceRedeem(params)
304
309
  );
305
310
  }
311
+ // ─── Calldata preparation (no signing) ───────────────────────────────────
312
+ async prepareDepositCalldata(params) {
313
+ this._validateAmount(params.amount, "prepareDepositCalldata");
314
+ if (params.depositBuffer !== void 0 && (params.depositBuffer <= 0 || params.depositBuffer > 1)) {
315
+ throw new StableValidationError(
316
+ "depositBuffer",
317
+ params.depositBuffer,
318
+ "prepareDepositCalldata: depositBuffer must be > 0 and \u2264 1"
319
+ );
320
+ }
321
+ const { amount, tokenDecimals, slippageTolerance, depositBuffer } = params;
322
+ const from = this._requireFrom();
323
+ const vaultAddr = _nullishCoalesce(params.vault, () => ( this.config.vault));
324
+ const vault = this.morphoNoSig.vaultV2(vaultAddr, this.config.chainId);
325
+ const vaultData = await vault.getData();
326
+ const decimals = await _asyncNullishCoalesce(tokenDecimals, async () => ( await this._resolveDecimals(vaultData.asset, "prepareDepositCalldata")));
327
+ const assetsRaw = _viem.parseUnits.call(void 0, String(amount), decimals);
328
+ if (depositBuffer !== void 0) {
329
+ const bps = BigInt(Math.round(depositBuffer * 1e4));
330
+ const maxAllowed = vaultData.assetBalance * bps / 10000n;
331
+ if (assetsRaw > maxAllowed) {
332
+ const maxFormatted = Number(_viem.formatUnits.call(void 0, maxAllowed, decimals));
333
+ const idleFormatted = Number(_viem.formatUnits.call(void 0, vaultData.assetBalance, decimals));
334
+ throw new StableValidationError(
335
+ "amount",
336
+ amount,
337
+ `prepareDepositCalldata: amount ${amount} exceeds deposit buffer \u2014 max ${maxFormatted} (${depositBuffer * 100}% of ${idleFormatted} idle liquidity)`
338
+ );
339
+ }
340
+ }
341
+ const depositAction = vault.deposit({
342
+ amount: assetsRaw,
343
+ userAddress: from,
344
+ accrualVault: vaultData,
345
+ slippageTolerance: slippageTolerance !== void 0 ? _viem.parseUnits.call(void 0, String(slippageTolerance), 18) : void 0
346
+ });
347
+ const requirements = await depositAction.getRequirements();
348
+ const steps = [];
349
+ for (const req of requirements) {
350
+ if (_morphosdk.isRequirementApproval.call(void 0, req)) {
351
+ steps.push({ to: req.to, data: req.data, value: req.value });
352
+ }
353
+ }
354
+ const tx = depositAction.buildTx(void 0);
355
+ steps.push({ to: tx.to, data: tx.data, value: tx.value });
356
+ return { steps, chainId: this.config.chainId };
357
+ }
358
+ async prepareWithdrawCalldata(params) {
359
+ this._validateAmount(params.amount, "prepareWithdrawCalldata");
360
+ const { amount, tokenDecimals } = params;
361
+ const from = this._requireFrom();
362
+ const vaultAddr = this.config.vault;
363
+ const vault = this.morpho.vaultV2(vaultAddr, this.config.chainId);
364
+ const vaultData = await vault.getData();
365
+ const decimals = await _asyncNullishCoalesce(tokenDecimals, async () => ( await this._resolveDecimals(vaultData.asset, "prepareWithdrawCalldata")));
366
+ const assetsRaw = _viem.parseUnits.call(void 0, String(amount), decimals);
367
+ const tx = vaultData.assetBalance >= assetsRaw ? vault.withdraw({ amount: assetsRaw, userAddress: from }).buildTx() : vault.forceWithdraw({
368
+ deallocations: this._buildAutoDeallocs(
369
+ vaultData.accrualAdapters,
370
+ assetsRaw - vaultData.assetBalance,
371
+ amount
372
+ ),
373
+ withdraw: { amount: assetsRaw },
374
+ userAddress: from
375
+ }).buildTx();
376
+ return { to: tx.to, data: tx.data, value: tx.value, chainId: this.config.chainId };
377
+ }
378
+ async prepareRedeemCalldata(params) {
379
+ this._validateShares(params.shares, "prepareRedeemCalldata");
380
+ const { shares, shareDecimals } = params;
381
+ const from = this._requireFrom();
382
+ const vaultAddr = this.config.vault;
383
+ let decimals = shareDecimals;
384
+ if (decimals === void 0) {
385
+ try {
386
+ decimals = await this.pc.readContract({
387
+ address: vaultAddr,
388
+ abi: _viem.erc20Abi,
389
+ functionName: "decimals"
390
+ });
391
+ } catch (e2) {
392
+ throw new StableValidationError(
393
+ "shareDecimals",
394
+ void 0,
395
+ `prepareRedeemCalldata: could not fetch share decimals for vault "${vaultAddr}" \u2014 pass shareDecimals explicitly`
396
+ );
397
+ }
398
+ }
399
+ const sharesRaw = _viem.parseUnits.call(void 0, String(shares), decimals);
400
+ const vault = this.morpho.vaultV2(vaultAddr, this.config.chainId);
401
+ const vaultData = await vault.getData();
402
+ const assetsEquivalent = vaultData.toAssets(sharesRaw);
403
+ const tx = vaultData.assetBalance >= assetsEquivalent ? vault.redeem({ shares: sharesRaw, userAddress: from }).buildTx() : vault.forceRedeem({
404
+ deallocations: this._buildAutoDeallocs(
405
+ vaultData.accrualAdapters,
406
+ assetsEquivalent - vaultData.assetBalance,
407
+ shares
408
+ ),
409
+ redeem: { shares: sharesRaw },
410
+ userAddress: from
411
+ }).buildTx();
412
+ return { to: tx.to, data: tx.data, value: tx.value, chainId: this.config.chainId };
413
+ }
306
414
  // ─── Private operations ──────────────────────────────────────────────────
307
415
  async _deposit(params) {
308
416
  const {
@@ -390,7 +498,15 @@ var MorphoService = class {
390
498
  const vaultData = await vault.getData();
391
499
  const decimals = await _asyncNullishCoalesce(tokenDecimals, async () => ( await this._resolveDecimals(vaultData.asset, "earn withdraw")));
392
500
  const assetsRaw = _viem.parseUnits.call(void 0, String(amount), decimals);
393
- const tx = vault.withdraw({ amount: assetsRaw, userAddress: from }).buildTx();
501
+ const tx = vaultData.assetBalance >= assetsRaw ? vault.withdraw({ amount: assetsRaw, userAddress: from }).buildTx() : vault.forceWithdraw({
502
+ deallocations: this._buildAutoDeallocs(
503
+ vaultData.accrualAdapters,
504
+ assetsRaw - vaultData.assetBalance,
505
+ amount
506
+ ),
507
+ withdraw: { amount: assetsRaw },
508
+ userAddress: from
509
+ }).buildTx();
394
510
  const hash = await this._sendTx(tx.to, tx.data, tx.value, from);
395
511
  const receipt = await this.pc.waitForTransactionReceipt({ hash });
396
512
  if (receipt.status === "reverted") {
@@ -416,7 +532,7 @@ var MorphoService = class {
416
532
  abi: _viem.erc20Abi,
417
533
  functionName: "decimals"
418
534
  });
419
- } catch (e2) {
535
+ } catch (e3) {
420
536
  throw new StableValidationError(
421
537
  "shareDecimals",
422
538
  void 0,
@@ -426,7 +542,17 @@ var MorphoService = class {
426
542
  }
427
543
  const sharesRaw = _viem.parseUnits.call(void 0, String(shares), decimals);
428
544
  const vault = this.morpho.vaultV2(vaultAddr, this.config.chainId);
429
- const tx = vault.redeem({ shares: sharesRaw, userAddress: from }).buildTx();
545
+ const vaultData = await vault.getData();
546
+ const assetsEquivalent = vaultData.toAssets(sharesRaw);
547
+ const tx = vaultData.assetBalance >= assetsEquivalent ? vault.redeem({ shares: sharesRaw, userAddress: from }).buildTx() : vault.forceRedeem({
548
+ deallocations: this._buildAutoDeallocs(
549
+ vaultData.accrualAdapters,
550
+ assetsEquivalent - vaultData.assetBalance,
551
+ shares
552
+ ),
553
+ redeem: { shares: sharesRaw },
554
+ userAddress: from
555
+ }).buildTx();
430
556
  const hash = await this._sendTx(tx.to, tx.data, tx.value, from);
431
557
  const receipt = await this.pc.waitForTransactionReceipt({ hash });
432
558
  if (receipt.status === "reverted") {
@@ -490,7 +616,7 @@ var MorphoService = class {
490
616
  abi: _viem.erc20Abi,
491
617
  functionName: "decimals"
492
618
  });
493
- } catch (e3) {
619
+ } catch (e4) {
494
620
  throw new StableValidationError(
495
621
  "shareDecimals",
496
622
  void 0,
@@ -523,6 +649,51 @@ var MorphoService = class {
523
649
  }
524
650
  return { txHash: receipt.transactionHash, idempotencyKey };
525
651
  }
652
+ // Automatically derives the minimum set of adapter deallocations needed to cover `deficit`
653
+ // when the vault has insufficient idle cash for a direct withdraw/redeem. Adds a 0.5%
654
+ // buffer to account for interest accrual between vaultData read and tx execution.
655
+ _buildAutoDeallocs(adapters, deficit, amount) {
656
+ const needed = deficit + deficit * 50n / 10000n;
657
+ const now = BigInt(Math.floor(Date.now() / 1e3));
658
+ const result = [];
659
+ let remaining = needed;
660
+ for (const adapter of adapters) {
661
+ if (remaining === 0n) break;
662
+ remaining = this._pullFromAdapter(adapter, remaining, now, result);
663
+ }
664
+ if (remaining > 0n) {
665
+ throw new StableValidationError(
666
+ "amount",
667
+ amount,
668
+ "earn withdraw: insufficient adapter liquidity \u2014 reduce the amount or wait for market liquidity to free up"
669
+ );
670
+ }
671
+ return result;
672
+ }
673
+ _pullFromAdapter(adapter, remaining, now, result) {
674
+ if (adapter.type !== "VaultV2MorphoMarketV1AdapterV2") {
675
+ const available = adapter.realAssets(now);
676
+ if (available === 0n) return remaining;
677
+ const pull = available < remaining ? available : remaining;
678
+ result.push({ adapter: adapter.address, amount: pull });
679
+ return remaining - pull;
680
+ }
681
+ const a = adapter;
682
+ return this._pullFromV2Markets(adapter.address, a.markets, a.supplyShares, remaining, result);
683
+ }
684
+ _pullFromV2Markets(adapterAddress, markets, supplyShares, remaining, result) {
685
+ let rem = remaining;
686
+ for (const mkt of markets) {
687
+ if (rem === 0n) break;
688
+ const adapterShares = _nullishCoalesce(supplyShares[mkt.id], () => ( 0n));
689
+ const available = mkt.totalSupplyShares > 0n ? adapterShares * mkt.totalSupplyAssets / mkt.totalSupplyShares : 0n;
690
+ if (available === 0n) continue;
691
+ const pull = available < rem ? available : rem;
692
+ result.push({ adapter: adapterAddress, marketParams: mkt.params, amount: pull });
693
+ rem -= pull;
694
+ }
695
+ return rem;
696
+ }
526
697
  _buildDeallocs(deallocations, assetDecimals) {
527
698
  return deallocations.map((d) => ({
528
699
  adapter: d.adapter,
@@ -587,7 +758,7 @@ var MorphoService = class {
587
758
  functionName: "decimals"
588
759
  })
589
760
  );
590
- } catch (e4) {
761
+ } catch (e5) {
591
762
  throw new StableValidationError(
592
763
  "tokenDecimals",
593
764
  void 0,
@@ -636,19 +807,19 @@ var MorphoService = class {
636
807
 
637
808
 
638
809
  // src/types.ts
639
- var Chain = /* @__PURE__ */ ((Chain2) => {
640
- Chain2["Sepolia"] = "sepolia";
641
- Chain2["StableTestnet"] = "stable-testnet";
642
- Chain2["Stable"] = "stable";
643
- Chain2["Ethereum"] = "ethereum";
644
- Chain2["Arbitrum"] = "arbitrum";
645
- Chain2["Ink"] = "ink";
646
- Chain2["Bera"] = "bera";
647
- Chain2["MegaETH"] = "megaeth";
648
- Chain2["Base"] = "base";
649
- Chain2["BSC"] = "bsc";
650
- Chain2["HyperEVM"] = "hyperevm";
651
- 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;
652
823
  })(Chain || {});
653
824
  var Network = /* @__PURE__ */ ((Network2) => {
654
825
  Network2["Mainnet"] = "mainnet";
@@ -843,6 +1014,233 @@ var EarnReader = class {
843
1014
  }
844
1015
  };
845
1016
 
1017
+ // src/earn/merkl.ts
1018
+
1019
+
1020
+
1021
+
1022
+
1023
+
1024
+
1025
+
1026
+ var MERKL_API_BASE_DEFAULT = "https://api.merkl.xyz";
1027
+ var DISTRIBUTOR_ADDRESS = "0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae";
1028
+ var DISTRIBUTOR_ABI = [
1029
+ {
1030
+ inputs: [
1031
+ { name: "users", type: "address[]" },
1032
+ { name: "tokens", type: "address[]" },
1033
+ { name: "amounts", type: "uint256[]" },
1034
+ { name: "proofs", type: "bytes32[][]" }
1035
+ ],
1036
+ name: "claim",
1037
+ outputs: [],
1038
+ stateMutability: "nonpayable",
1039
+ type: "function"
1040
+ }
1041
+ ];
1042
+ var MerklService = class {
1043
+ constructor(config) {
1044
+ this.config = config;
1045
+ }
1046
+ async fetchRewards(address) {
1047
+ if (!_viem.isAddress.call(void 0, address)) {
1048
+ throw new StableValidationError(
1049
+ "address",
1050
+ address,
1051
+ `merkl: invalid address "${address}"`
1052
+ );
1053
+ }
1054
+ const base = (_nullishCoalesce(this.config.merklApiBase, () => ( MERKL_API_BASE_DEFAULT))).replace(/\/$/, "");
1055
+ const url = `${base}/v4/users/${address}/rewards?chainId=${this.config.chainId}`;
1056
+ const data = await this._fetch(url);
1057
+ return this._parseRewards(data);
1058
+ }
1059
+ async claim() {
1060
+ const address = this._requireFrom();
1061
+ const { rewards } = await this.fetchRewards(address);
1062
+ const claimable = rewards.filter(
1063
+ (r) => r.rawAmount !== "0" && r.proofs.length > 0
1064
+ );
1065
+ if (claimable.length === 0) {
1066
+ throw new StableValidationError(
1067
+ "rewards",
1068
+ [],
1069
+ 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"
1070
+ );
1071
+ }
1072
+ const chain = makeChain(this.config.chainId, this.config.rpc);
1073
+ const wc = _nullishCoalesce(this.config.walletClient, () => ( _viem.createWalletClient.call(void 0, {
1074
+ account: this.config.account,
1075
+ chain,
1076
+ transport: _nullishCoalesce(this.config.transport, () => ( _viem.http.call(void 0, this.config.rpc)))
1077
+ })));
1078
+ try {
1079
+ await wc.switchChain({ id: this.config.chainId });
1080
+ } catch (err) {
1081
+ throw new StableTransactionError({
1082
+ phase: "switch_chain",
1083
+ shortMessage: `merkl: wallet rejected or failed to switch to chain ${this.config.chainId}`,
1084
+ chainId: this.config.chainId,
1085
+ cause: err
1086
+ });
1087
+ }
1088
+ const users = claimable.map(() => address);
1089
+ const tokens = claimable.map(
1090
+ (r) => r.token.address
1091
+ );
1092
+ const amounts = claimable.map((r) => BigInt(r.rawAmount));
1093
+ const proofs = claimable.map((r) => r.proofs);
1094
+ let hash;
1095
+ try {
1096
+ hash = await wc.writeContract({
1097
+ address: DISTRIBUTOR_ADDRESS,
1098
+ abi: DISTRIBUTOR_ABI,
1099
+ functionName: "claim",
1100
+ args: [users, tokens, amounts, proofs],
1101
+ account: wc.account,
1102
+ chain
1103
+ });
1104
+ } catch (err) {
1105
+ throw new StableTransactionError({
1106
+ phase: "send",
1107
+ shortMessage: "merkl: claim transaction failed",
1108
+ chainId: this.config.chainId,
1109
+ cause: err
1110
+ });
1111
+ }
1112
+ const pc = _viem.createPublicClient.call(void 0, {
1113
+ chain,
1114
+ transport: _viem.http.call(void 0, this.config.rpc)
1115
+ });
1116
+ const receipt = await pc.waitForTransactionReceipt({ hash });
1117
+ if (receipt.status === "reverted") {
1118
+ throw new StableTransactionError({
1119
+ phase: "receipt",
1120
+ shortMessage: "merkl: claim transaction reverted on-chain",
1121
+ txHash: receipt.transactionHash,
1122
+ chainId: this.config.chainId
1123
+ });
1124
+ }
1125
+ return {
1126
+ txHash: receipt.transactionHash,
1127
+ tokenCount: claimable.length
1128
+ };
1129
+ }
1130
+ async prepareClaimCalldata(address) {
1131
+ if (!_viem.isAddress.call(void 0, address)) {
1132
+ throw new StableValidationError(
1133
+ "address",
1134
+ address,
1135
+ `merkl: invalid address "${address}"`
1136
+ );
1137
+ }
1138
+ const { rewards } = await this.fetchRewards(address);
1139
+ const claimable = rewards.filter(
1140
+ (r) => r.rawAmount !== "0" && r.proofs.length > 0
1141
+ );
1142
+ if (claimable.length === 0) {
1143
+ throw new StableValidationError(
1144
+ "rewards",
1145
+ [],
1146
+ 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"
1147
+ );
1148
+ }
1149
+ const users = claimable.map(() => address);
1150
+ const tokens = claimable.map((r) => r.token.address);
1151
+ const amounts = claimable.map((r) => BigInt(r.rawAmount));
1152
+ const proofs = claimable.map((r) => r.proofs);
1153
+ const data = _viem.encodeFunctionData.call(void 0, {
1154
+ abi: DISTRIBUTOR_ABI,
1155
+ functionName: "claim",
1156
+ args: [users, tokens, amounts, proofs]
1157
+ });
1158
+ return {
1159
+ to: DISTRIBUTOR_ADDRESS,
1160
+ data,
1161
+ chainId: this.config.chainId,
1162
+ rewards: claimable
1163
+ };
1164
+ }
1165
+ _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])));
1167
+ if (!from) {
1168
+ throw new StableValidationError(
1169
+ "signer",
1170
+ void 0,
1171
+ "merkl.claim: requires a signer \u2014 set walletClient or account in StableConfig"
1172
+ );
1173
+ }
1174
+ return from;
1175
+ }
1176
+ _parseRewards(data) {
1177
+ const { chainId } = this.config;
1178
+ const rewards = [];
1179
+ const entries = Array.isArray(data) ? data : [data];
1180
+ for (const entry of entries) {
1181
+ if (_optionalChain([entry, 'optionalAccess', _19 => _19.chain, 'optionalAccess', _20 => _20.id]) !== chainId) continue;
1182
+ for (const reward of _nullishCoalesce(entry.rewards, () => ( []))) {
1183
+ const parsed = this._parseReward(reward);
1184
+ if (parsed) rewards.push(parsed);
1185
+ }
1186
+ }
1187
+ return { chainId, rewards };
1188
+ }
1189
+ _parseReward(reward) {
1190
+ if (!_optionalChain([reward, 'optionalAccess', _21 => _21.token, 'optionalAccess', _22 => _22.address])) return null;
1191
+ const net = BigInt(_nullishCoalesce(reward.amount, () => ( "0"))) - BigInt(_nullishCoalesce(reward.claimed, () => ( "0")));
1192
+ if (net <= 0n) return null;
1193
+ const rawAmount = net.toString();
1194
+ const decimals = _nullishCoalesce(reward.token.decimals, () => ( 18));
1195
+ return {
1196
+ token: {
1197
+ address: reward.token.address,
1198
+ symbol: _nullishCoalesce(reward.token.symbol, () => ( "")),
1199
+ decimals
1200
+ },
1201
+ rawAmount,
1202
+ amount: Number(_viem.formatUnits.call(void 0, BigInt(rawAmount), decimals)),
1203
+ proofs: _nullishCoalesce(reward.proofs, () => ( []))
1204
+ };
1205
+ }
1206
+ async _fetch(url) {
1207
+ try {
1208
+ return await retryWithBackoff(() => this._fetchOnce(url));
1209
+ } catch (err) {
1210
+ if (err instanceof StableNetworkError) throw err;
1211
+ if (err instanceof HttpError) {
1212
+ throw new StableNetworkError({
1213
+ shortMessage: `merkl: request failed \u2014 ${err.message}`,
1214
+ url,
1215
+ cause: err
1216
+ });
1217
+ }
1218
+ throw new StableNetworkError({
1219
+ shortMessage: "merkl: request failed before reaching the server",
1220
+ url,
1221
+ cause: err
1222
+ });
1223
+ }
1224
+ }
1225
+ async _fetchOnce(url) {
1226
+ const res = await fetch(url);
1227
+ if (!res.ok) {
1228
+ if (res.status === 429 || res.status >= 500) {
1229
+ throw new HttpError(
1230
+ `merkl: ${res.statusText}`,
1231
+ res.status,
1232
+ true
1233
+ );
1234
+ }
1235
+ throw new StableNetworkError({
1236
+ shortMessage: `merkl: API error ${res.status} ${res.statusText}`,
1237
+ url
1238
+ });
1239
+ }
1240
+ return res.json();
1241
+ }
1242
+ };
1243
+
846
1244
  // src/services/lifi.ts
847
1245
 
848
1246
 
@@ -978,7 +1376,7 @@ var LiFiService = class {
978
1376
  fromDecimals = 6,
979
1377
  recipient
980
1378
  } = params;
981
- const from = _nullishCoalesce(_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]))), () => ( "0x0000000000000000000000000000000000000000"));
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"));
982
1380
  const src = CHAIN_CONFIGS[fromChain];
983
1381
  const dst = CHAIN_CONFIGS[toChain];
984
1382
  if (!src)
@@ -1136,7 +1534,7 @@ var LiFiService = class {
1136
1534
  }
1137
1535
  }
1138
1536
  _requireFrom() {
1139
- const from = _nullishCoalesce(_optionalChain([this, 'access', _19 => _19.config, 'access', _20 => _20.walletClient, 'optionalAccess', _21 => _21.account, 'optionalAccess', _22 => _22.address]), () => ( _optionalChain([this, 'access', _23 => _23.config, 'access', _24 => _24.account, 'optionalAccess', _25 => _25.address])));
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])));
1140
1538
  if (!from) {
1141
1539
  throw new StableValidationError(
1142
1540
  "signer",
@@ -1325,7 +1723,304 @@ function isLiFiQuoteShape(v) {
1325
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);
1326
1724
  }
1327
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
+
1328
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
+ }
1329
2024
  function validateTransferParams({
1330
2025
  to,
1331
2026
  amount,
@@ -1369,7 +2064,7 @@ async function resolveTokenDecimals(publicClient, token, tokenDecimals) {
1369
2064
  abi: _viem.erc20Abi,
1370
2065
  functionName: "decimals"
1371
2066
  });
1372
- } catch (e5) {
2067
+ } catch (e6) {
1373
2068
  throw new StableValidationError(
1374
2069
  "tokenDecimals",
1375
2070
  void 0,
@@ -1406,7 +2101,8 @@ function createStable({
1406
2101
  account,
1407
2102
  transport,
1408
2103
  walletClient,
1409
- earn: earnConfig
2104
+ earn: earnConfig,
2105
+ merklApiBase
1410
2106
  }) {
1411
2107
  const chain = network === "mainnet" /* Mainnet */ ? _chains.stable : _chains.stableTestnet;
1412
2108
  const rpc = (_nullishCoalesce(rpcOverride, () => ( chain.rpcUrls.default.http[0]))).replace(
@@ -1415,6 +2111,8 @@ function createStable({
1415
2111
  );
1416
2112
  const signerConfig = { account, transport, walletClient };
1417
2113
  const lifi = new LiFiService({ ...signerConfig, rpc, chainId: chain.id });
2114
+ const lz = new LayerZeroService(signerConfig);
2115
+ const merkl = new MerklService({ ...signerConfig, rpc, chainId: chain.id, merklApiBase });
1418
2116
  const morpho = earnConfig ? new MorphoService({
1419
2117
  ...signerConfig,
1420
2118
  rpc,
@@ -1431,10 +2129,21 @@ function createStable({
1431
2129
  }
1432
2130
  return morpho;
1433
2131
  }
2132
+ function requireSignerAddress() {
2133
+ const from = _nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _46 => _46.account, 'optionalAccess', _47 => _47.address]), () => ( _optionalChain([account, 'optionalAccess', _48 => _48.address])));
2134
+ if (!from) {
2135
+ throw new StableValidationError(
2136
+ "signer",
2137
+ void 0,
2138
+ "stable.rewards.*: requires a signer \u2014 set walletClient or account in StableConfig"
2139
+ );
2140
+ }
2141
+ return from;
2142
+ }
1434
2143
  async function transfer(params) {
1435
2144
  validateTransferParams(params);
1436
2145
  const { from, to, amount, token, tokenDecimals } = params;
1437
- const acc = _nullishCoalesce(_nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _26 => _26.account]), () => ( account)), () => ( from));
2146
+ const acc = _nullishCoalesce(_nullishCoalesce(_optionalChain([walletClient, 'optionalAccess', _49 => _49.account]), () => ( account)), () => ( from));
1438
2147
  const wc = _nullishCoalesce(walletClient, () => ( _viem.createWalletClient.call(void 0, {
1439
2148
  account: acc,
1440
2149
  chain,
@@ -1486,8 +2195,8 @@ function createStable({
1486
2195
  }
1487
2196
  return {
1488
2197
  transfer,
1489
- quoteBridge: (params) => lifi.quoteBridge(params),
1490
- 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),
1491
2200
  quoteSwap: (params) => lifi.quoteSwap(params),
1492
2201
  swap: (params) => lifi.swap(params),
1493
2202
  earn: {
@@ -1497,25 +2206,39 @@ function createStable({
1497
2206
  bulkWithdraw: (items, options) => requireEarn().bulkWithdraw(items, options),
1498
2207
  redeem: (params) => requireEarn().redeem(params),
1499
2208
  forceWithdraw: (params) => requireEarn().forceWithdraw(params),
1500
- forceRedeem: (params) => requireEarn().forceRedeem(params)
2209
+ forceRedeem: (params) => requireEarn().forceRedeem(params),
2210
+ prepareDepositCalldata: (params) => requireEarn().prepareDepositCalldata(params),
2211
+ prepareWithdrawCalldata: (params) => requireEarn().prepareWithdrawCalldata(params),
2212
+ prepareRedeemCalldata: (params) => requireEarn().prepareRedeemCalldata(params),
2213
+ incentiveRewards: {
2214
+ fetch: () => merkl.fetchRewards(requireSignerAddress()),
2215
+ claim: () => merkl.claim()
2216
+ }
1501
2217
  }
1502
2218
  };
1503
2219
  }
1504
2220
  function createStableReader(config) {
1505
2221
  const reader = new EarnReader(config);
2222
+ const chain = config.network === "testnet" /* Testnet */ ? _chains.stableTestnet : _chains.stable;
2223
+ const rpc = (_nullishCoalesce(config.rpc, () => ( chain.rpcUrls.default.http[0]))).replace(/\/$/, "");
2224
+ const merkl = new MerklService({ chainId: chain.id, rpc, merklApiBase: config.merklApiBase });
1506
2225
  return {
1507
2226
  earn: {
1508
2227
  getYield: () => reader.getYield(),
1509
2228
  position: () => reader.position(),
1510
2229
  preview: (params) => reader.preview(params),
1511
- withdrawability: (params) => reader.withdrawability(params)
2230
+ withdrawability: (params) => reader.withdrawability(params),
2231
+ incentiveRewards: {
2232
+ fetch: () => merkl.fetchRewards(config.address)
2233
+ }
1512
2234
  }
1513
2235
  };
1514
2236
  }
1515
2237
 
1516
2238
  // src/constants.ts
1517
2239
  var STABLE_USDT_ADDRESS = "0x779ded0c9e1022225f8e0630b35a9b54be713736";
1518
- var STABLE_VAULT_ADDRESS = "0x461eF73F640456138242398a39AB48a557A49293";
2240
+ var STABLE_VAULT_ADDRESS = "0xb7Df8db22A5DBBFA9ebeb94b3910aec6a4f05c08";
2241
+
1519
2242
 
1520
2243
 
1521
2244
 
@@ -1530,4 +2253,4 @@ var STABLE_VAULT_ADDRESS = "0x461eF73F640456138242398a39AB48a557A49293";
1530
2253
 
1531
2254
 
1532
2255
 
1533
- 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;
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;