@sodax/sdk 2.0.0-rc.18 → 2.0.0-rc.19

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.mjs CHANGED
@@ -17,6 +17,7 @@ import * as IconSdkRaw from 'icon-sdk-js';
17
17
  import { ChainGrpcWasmApi, TxGrpcApi, toBase64, fromBase64, MsgExecuteContract, ChainRestAuthApi, BaseAccount, createTransaction } from '@injectivelabs/sdk-ts';
18
18
  import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx.js';
19
19
  import { getNetworkEndpoints, Network } from '@injectivelabs/networks';
20
+ import * as v4 from 'valibot';
20
21
  import BigNumber5, { BigNumber } from 'bignumber.js';
21
22
  import { Token, Price } from '@pancakeswap/swap-sdk-core';
22
23
  import { sqrtRatioX96ToPrice, PositionMath, tickToPrice, TickMath, maxLiquidityForAmount0Precise, maxLiquidityForAmount1, maxLiquidityForAmounts } from '@pancakeswap/v3-sdk';
@@ -91,8 +92,8 @@ function serializeCause(cause, depth) {
91
92
  }
92
93
  function sanitizeContext(value, depth) {
93
94
  const out = {};
94
- for (const [key, v] of Object.entries(value)) {
95
- out[key] = sanitizeValue(v, depth + 1);
95
+ for (const [key, v6] of Object.entries(value)) {
96
+ out[key] = sanitizeValue(v6, depth + 1);
96
97
  }
97
98
  return out;
98
99
  }
@@ -103,13 +104,13 @@ function sanitizeValue(value, depth) {
103
104
  if (t === "bigint") return value.toString();
104
105
  if (t === "string" || t === "number" || t === "boolean") return value;
105
106
  if (t === "function" || t === "symbol") return safeString(value);
106
- if (Array.isArray(value)) return value.map((v) => sanitizeValue(v, depth + 1));
107
+ if (Array.isArray(value)) return value.map((v6) => sanitizeValue(v6, depth + 1));
107
108
  if (value instanceof Date) return value.toISOString();
108
109
  if (value instanceof Map) {
109
- return Array.from(value.entries()).map(([k, v]) => [sanitizeValue(k, depth + 1), sanitizeValue(v, depth + 1)]);
110
+ return Array.from(value.entries()).map(([k, v6]) => [sanitizeValue(k, depth + 1), sanitizeValue(v6, depth + 1)]);
110
111
  }
111
112
  if (value instanceof Set) {
112
- return Array.from(value.values()).map((v) => sanitizeValue(v, depth + 1));
113
+ return Array.from(value.values()).map((v6) => sanitizeValue(v6, depth + 1));
113
114
  }
114
115
  if (value instanceof Error) return { name: value.name, message: value.message };
115
116
  if (t === "object") {
@@ -121,9 +122,9 @@ function sanitizeValue(value, depth) {
121
122
  }
122
123
  return safeString(value);
123
124
  }
124
- function safeString(v) {
125
+ function safeString(v6) {
125
126
  try {
126
- return String(v);
127
+ return String(v6);
127
128
  } catch {
128
129
  return "[unserializable]";
129
130
  }
@@ -171,6 +172,7 @@ var SODAX_FEATURES = [
171
172
  "dex",
172
173
  "partner",
173
174
  "recovery",
175
+ "backend",
174
176
  "leverageYield"
175
177
  ];
176
178
 
@@ -2612,7 +2614,7 @@ var RelayChainIdMap = {
2612
2614
  [ChainKeys.STACKS_MAINNET]: 60n
2613
2615
  };
2614
2616
  var INTENT_CHAIN_IDS = Object.values(RelayChainIdMap);
2615
- var IntentRelayChainIdToChainKey = Object.fromEntries(Object.entries(RelayChainIdMap).map(([chainKey, chainId]) => [chainId, chainKey]));
2617
+ var IntentRelayChainIdToChainKey = new Map(Object.entries(RelayChainIdMap).map(([chainKey, chainId]) => [chainId, chainKey]));
2616
2618
  var CHAIN_LOGO_BASE_URL = "https://raw.githubusercontent.com/icon-project/sodax-sdks/main/packages/assets/chain";
2617
2619
  var chainLogo = (key) => `${CHAIN_LOGO_BASE_URL}/${key}.png`;
2618
2620
  var baseChainInfo = {
@@ -4218,7 +4220,7 @@ function isValidWalletProviderForChainKey(chainKey, walletProvider) {
4218
4220
  }
4219
4221
 
4220
4222
  // ../types/dist/index.js
4221
- var CONFIG_VERSION = 216;
4223
+ var CONFIG_VERSION = 217;
4222
4224
  function isEvmSpokeChainConfig(value) {
4223
4225
  return typeof value === "object" && value !== null && value.chain.type === "EVM" && value.chain.key !== HUB_CHAIN_KEY;
4224
4226
  }
@@ -4308,26 +4310,6 @@ function isRawDestinationParams(value) {
4308
4310
  if (typeof obj.dstAddress !== "string") return false;
4309
4311
  return typeof obj.dstChainKey === "string" && spokeChainKeysSet.has(obj.dstChainKey);
4310
4312
  }
4311
- function isSubmitSwapTxResponse(value) {
4312
- return typeof value === "object" && value !== null && typeof value.success === "boolean" && typeof value.message === "string";
4313
- }
4314
- function isSubmitSwapTxStatusResponse(value) {
4315
- if (typeof value !== "object" || value === null) return false;
4316
- const obj = value;
4317
- if (typeof obj.success !== "boolean") return false;
4318
- if (typeof obj.data !== "object" || obj.data === null) return false;
4319
- const data = obj.data;
4320
- if (typeof data.txHash !== "string") return false;
4321
- if (typeof data.srcChainKey !== "string") return false;
4322
- if (typeof data.status !== "string") return false;
4323
- if (typeof data.failedAttempts !== "number") return false;
4324
- if (data.result !== void 0) {
4325
- if (typeof data.result !== "object" || data.result === null) return false;
4326
- const result = data.result;
4327
- if (typeof result.dstIntentTxHash !== "string") return false;
4328
- }
4329
- return true;
4330
- }
4331
4313
  function isBitcoinWalletProviderType(wp) {
4332
4314
  return wp.chainType === "BITCOIN";
4333
4315
  }
@@ -4365,11 +4347,11 @@ async function retry(action, retryCount = DEFAULT_MAX_RETRY, delayMs = DEFAULT_R
4365
4347
  throw new Error(`Retry exceeded MAX_RETRY_DEFAULT=${DEFAULT_MAX_RETRY}`);
4366
4348
  }
4367
4349
  function getRandomBytes(length) {
4368
- const array = new Uint8Array(length);
4350
+ const array3 = new Uint8Array(length);
4369
4351
  for (let i = 0; i < length; i++) {
4370
- array[i] = Math.floor(Math.random() * 256);
4352
+ array3[i] = Math.floor(Math.random() * 256);
4371
4353
  }
4372
- return array;
4354
+ return array3;
4373
4355
  }
4374
4356
  function randomUint256() {
4375
4357
  const bytes = getRandomBytes(32);
@@ -13616,29 +13598,6 @@ var universalRouterAbi = [
13616
13598
  }
13617
13599
  ];
13618
13600
 
13619
- // src/shared/utils/deepMerge.ts
13620
- function deepMerge(target, source) {
13621
- const result = { ...target };
13622
- for (const key of Object.keys(source)) {
13623
- const sourceVal = source[key];
13624
- const targetVal = target[key];
13625
- if (sourceVal !== void 0 && typeof sourceVal === "object" && sourceVal !== null && !Array.isArray(sourceVal) && typeof targetVal === "object" && targetVal !== null && !Array.isArray(targetVal)) {
13626
- result[key] = deepMerge(
13627
- targetVal,
13628
- sourceVal
13629
- );
13630
- } else if (sourceVal !== void 0) {
13631
- result[key] = sourceVal;
13632
- }
13633
- }
13634
- return result;
13635
- }
13636
-
13637
- // src/shared/config/mergeSodaxConfig.ts
13638
- function mergeSodaxConfig(base2, override) {
13639
- return deepMerge(base2, override);
13640
- }
13641
-
13642
13601
  // src/shared/logger.ts
13643
13602
  var consoleLogger = {
13644
13603
  debug: (message, data) => data ? console.debug(message, data) : console.debug(message),
@@ -13731,8 +13690,9 @@ function resolveAnalytics(option) {
13731
13690
  // src/shared/config/ConfigService.ts
13732
13691
  var ConfigService = class {
13733
13692
  sodax;
13734
- api;
13735
- userConfig;
13693
+ // TODO(config-v2): restore `api` / `userConfig` when initialize() dynamic fetch is re-enabled.
13694
+ // private readonly api: BackendApiService;
13695
+ // private readonly userConfig?: SodaxOptions;
13736
13696
  /**
13737
13697
  * SDK log sink. Resolved once at construction and kept independent of {@link sodax} so that
13738
13698
  * {@link initialize}'s dynamic-config swap never clobbers it. Read by services via `config.logger`.
@@ -13761,10 +13721,10 @@ var ConfigService = class {
13761
13721
  stakedATokenAddressesSet;
13762
13722
  chainToSupportedTokenAddressMap;
13763
13723
  hubAssetToXTokenMap;
13724
+ // `api` / `userConfig` are accepted but unused while initialize()'s dynamic fetch is disabled
13725
+ // (see TODO(config-v2) below); restore their assignments when re-enabling.
13764
13726
  constructor({ api, config, userConfig, logger, analytics, fee }) {
13765
- this.api = api;
13766
13727
  this.sodax = config;
13767
- this.userConfig = userConfig;
13768
13728
  this.logger = logger ?? resolveLogger(void 0);
13769
13729
  this.analytics = analytics ?? noopAnalytics;
13770
13730
  this.fee = fee;
@@ -13772,19 +13732,6 @@ var ConfigService = class {
13772
13732
  }
13773
13733
  async initialize() {
13774
13734
  try {
13775
- const result = await this.api.getAllConfig();
13776
- if (!result.ok) return result;
13777
- const response = result.value;
13778
- if (!response.version || response.version < CONFIG_VERSION) {
13779
- this.logger.warn(
13780
- `Dynamic config version is less than the current version, resorting to the default one. Current version: ${CONFIG_VERSION}, response version: ${response.version}`
13781
- );
13782
- } else {
13783
- const next = this.userConfig ? mergeSodaxConfig(response.config, this.userConfig) : response.config;
13784
- this.loadSodaxConfigDataStructures(next);
13785
- this.sodax = next;
13786
- this.initialized = true;
13787
- }
13788
13735
  return { ok: true, value: void 0 };
13789
13736
  } catch (error) {
13790
13737
  return { ok: false, error };
@@ -14054,9 +14001,32 @@ function parseTokenArrayFromJson(input) {
14054
14001
  }
14055
14002
  return tokens;
14056
14003
  }
14004
+
14005
+ // src/shared/utils/deepMerge.ts
14006
+ function deepMerge(target, source) {
14007
+ const result = { ...target };
14008
+ for (const key of Object.keys(source)) {
14009
+ const sourceVal = source[key];
14010
+ const targetVal = target[key];
14011
+ if (sourceVal !== void 0 && typeof sourceVal === "object" && sourceVal !== null && !Array.isArray(sourceVal) && typeof targetVal === "object" && targetVal !== null && !Array.isArray(targetVal)) {
14012
+ result[key] = deepMerge(
14013
+ targetVal,
14014
+ sourceVal
14015
+ );
14016
+ } else if (sourceVal !== void 0) {
14017
+ result[key] = sourceVal;
14018
+ }
14019
+ }
14020
+ return result;
14021
+ }
14022
+
14023
+ // src/shared/config/mergeSodaxConfig.ts
14024
+ function mergeSodaxConfig(base2, override) {
14025
+ return deepMerge(base2, override);
14026
+ }
14057
14027
  function encodeContractCalls(calls) {
14058
14028
  return encodeAbiParameters(parseAbiParameters("(address,uint256,bytes)[]"), [
14059
- calls.map((v) => [v.address, v.value, v.data])
14029
+ calls.map((v6) => [v6.address, v6.value, v6.data])
14060
14030
  ]);
14061
14031
  }
14062
14032
  async function waitForTransactionReceipt(hash, provider) {
@@ -15737,6 +15707,32 @@ var BitcoinSpokeService = class {
15737
15707
  throw error;
15738
15708
  }
15739
15709
  }
15710
+ /**
15711
+ * Sign and submit a TRADING-wallet raw transaction — the Bound-built *unsigned* PSBT returned by
15712
+ * `deposit({ raw: true })` / the Swaps API (`createIntent().tx.data`). Signs it with the wallet
15713
+ * provider's key, then sends it to Bound Exchange to co-sign with the second 2-of-2 key and
15714
+ * broadcast. Returns the broadcast tx id.
15715
+ *
15716
+ * This is the client-side completion of the TRADING deposit flow: the backend builds the PSBT
15717
+ * (it can't broadcast — the user's signature is missing), the client signs here, and Bound
15718
+ * co-signs + broadcasts. `relayData` ({ address, payload }) is the relay identity returned by
15719
+ * `createIntent()`; forwarding it lets Bound auto-resubmit a stuck relay. It is **not** recoverable
15720
+ * from `rawTx` (whose `to` is the asset manager, not the hub wallet), so callers must supply it.
15721
+ *
15722
+ * @throws if the chain is not in `TRADING` wallet mode (raw txs only exist in TRADING mode).
15723
+ */
15724
+ async signAndSubmitRawTransaction(params) {
15725
+ if (this.walletMode !== "TRADING") {
15726
+ throw new Error("signAndSubmitRawTransaction requires TRADING wallet mode.");
15727
+ }
15728
+ const { rawTx, walletProvider, relayData, accessToken = this.radfi.accessToken } = params;
15729
+ if (!rawTx?.data || !rawTx?.from) {
15730
+ throw new Error("signAndSubmitRawTransaction: rawTx.data (PSBT) and rawTx.from are required.");
15731
+ }
15732
+ const signedTx = await walletProvider.signTransaction(rawTx.data, false);
15733
+ const signedBase64Tx = normalizePsbtToBase64(signedTx);
15734
+ return this.radfi.requestRadfiSignature({ userAddress: rawTx.from, signedBase64Tx, relayData }, accessToken);
15735
+ }
15740
15736
  /**
15741
15737
  * Build deposit PSBT with embedded cross-chain data
15742
15738
  */
@@ -16006,7 +16002,7 @@ function hexToBytes2(hex) {
16006
16002
  const al = hl / 2;
16007
16003
  if (hl % 2)
16008
16004
  throw new Error("hex string expected, got unpadded hex of length " + hl);
16009
- const array = new Uint8Array(al);
16005
+ const array3 = new Uint8Array(al);
16010
16006
  for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
16011
16007
  const n1 = asciiToBase16(hex.charCodeAt(hi));
16012
16008
  const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
@@ -16014,9 +16010,9 @@ function hexToBytes2(hex) {
16014
16010
  const char = hex[hi] + hex[hi + 1];
16015
16011
  throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
16016
16012
  }
16017
- array[ai] = n1 * 16 + n2;
16013
+ array3[ai] = n1 * 16 + n2;
16018
16014
  }
16019
- return array;
16015
+ return array3;
16020
16016
  }
16021
16017
  function concatBytes(...arrays) {
16022
16018
  let sum = 0;
@@ -16646,22 +16642,22 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
16646
16642
  const byte0 = Uint8Array.of(0);
16647
16643
  const byte1 = Uint8Array.of(1);
16648
16644
  const _maxDrbgIters = 1e3;
16649
- let v = u8n(hashLen);
16645
+ let v6 = u8n(hashLen);
16650
16646
  let k = u8n(hashLen);
16651
16647
  let i = 0;
16652
16648
  const reset = () => {
16653
- v.fill(1);
16649
+ v6.fill(1);
16654
16650
  k.fill(0);
16655
16651
  i = 0;
16656
16652
  };
16657
- const h = (...msgs) => hmacFn(k, concatBytes(v, ...msgs));
16653
+ const h = (...msgs) => hmacFn(k, concatBytes(v6, ...msgs));
16658
16654
  const reseed = (seed = NULL) => {
16659
16655
  k = h(byte0, seed);
16660
- v = h();
16656
+ v6 = h();
16661
16657
  if (seed.length === 0)
16662
16658
  return;
16663
16659
  k = h(byte1, seed);
16664
- v = h();
16660
+ v6 = h();
16665
16661
  };
16666
16662
  const gen = () => {
16667
16663
  if (i++ >= _maxDrbgIters)
@@ -16669,10 +16665,10 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
16669
16665
  let len = 0;
16670
16666
  const out = [];
16671
16667
  while (len < qByteLen) {
16672
- v = h();
16673
- const sl = v.slice();
16668
+ v6 = h();
16669
+ const sl = v6.slice();
16674
16670
  out.push(sl);
16675
- len += v.length;
16671
+ len += v6.length;
16676
16672
  }
16677
16673
  return concatBytes(...out);
16678
16674
  };
@@ -16687,18 +16683,18 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
16687
16683
  };
16688
16684
  return genUntil;
16689
16685
  }
16690
- function validateObject(object, fields = {}, optFields = {}) {
16691
- if (!object || typeof object !== "object")
16686
+ function validateObject(object4, fields = {}, optFields = {}) {
16687
+ if (!object4 || typeof object4 !== "object")
16692
16688
  throw new Error("expected valid options object");
16693
16689
  function checkField(fieldName, expectedType, isOpt) {
16694
- const val = object[fieldName];
16690
+ const val = object4[fieldName];
16695
16691
  if (isOpt && val === void 0)
16696
16692
  return;
16697
16693
  const current = typeof val;
16698
16694
  if (current !== expectedType || val === null)
16699
16695
  throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
16700
16696
  }
16701
- const iter = (f, isOpt) => Object.entries(f).forEach(([k, v]) => checkField(k, v, isOpt));
16697
+ const iter = (f, isOpt) => Object.entries(f).forEach(([k, v6]) => checkField(k, v6, isOpt));
16702
16698
  iter(fields, false);
16703
16699
  iter(optFields, true);
16704
16700
  }
@@ -16737,12 +16733,12 @@ function pow2(x, power, modulo) {
16737
16733
  }
16738
16734
  return res;
16739
16735
  }
16740
- function invert(number, modulo) {
16741
- if (number === _0n2)
16736
+ function invert(number4, modulo) {
16737
+ if (number4 === _0n2)
16742
16738
  throw new Error("invert: expected non-zero number");
16743
16739
  if (modulo <= _0n2)
16744
16740
  throw new Error("invert: expected positive modulus, got " + modulo);
16745
- let a = mod(number, modulo);
16741
+ let a = mod(number4, modulo);
16746
16742
  let b = modulo;
16747
16743
  let x = _0n2, u = _1n2;
16748
16744
  while (a !== _0n2) {
@@ -16769,9 +16765,9 @@ function sqrt3mod4(Fp, n) {
16769
16765
  function sqrt5mod8(Fp, n) {
16770
16766
  const p5div8 = (Fp.ORDER - _5n) / _8n;
16771
16767
  const n2 = Fp.mul(n, _2n);
16772
- const v = Fp.pow(n2, p5div8);
16773
- const nv = Fp.mul(n, v);
16774
- const i = Fp.mul(Fp.mul(nv, _2n), v);
16768
+ const v6 = Fp.pow(n2, p5div8);
16769
+ const nv = Fp.mul(n, v6);
16770
+ const i = Fp.mul(Fp.mul(nv, _2n), v6);
16775
16771
  const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
16776
16772
  assertIsSquare(Fp, root, n);
16777
16773
  return root;
@@ -17246,27 +17242,27 @@ var wNAF = class {
17246
17242
  assert0(n);
17247
17243
  return acc;
17248
17244
  }
17249
- getPrecomputes(W, point, transform) {
17245
+ getPrecomputes(W, point, transform2) {
17250
17246
  let comp = pointPrecomputes.get(point);
17251
17247
  if (!comp) {
17252
17248
  comp = this.precomputeWindow(point, W);
17253
17249
  if (W !== 1) {
17254
- if (typeof transform === "function")
17255
- comp = transform(comp);
17250
+ if (typeof transform2 === "function")
17251
+ comp = transform2(comp);
17256
17252
  pointPrecomputes.set(point, comp);
17257
17253
  }
17258
17254
  }
17259
17255
  return comp;
17260
17256
  }
17261
- cached(point, scalar, transform) {
17257
+ cached(point, scalar, transform2) {
17262
17258
  const W = getW(point);
17263
- return this.wNAF(W, this.getPrecomputes(W, point, transform), scalar);
17259
+ return this.wNAF(W, this.getPrecomputes(W, point, transform2), scalar);
17264
17260
  }
17265
- unsafe(point, scalar, transform, prev) {
17261
+ unsafe(point, scalar, transform2, prev) {
17266
17262
  const W = getW(point);
17267
17263
  if (W === 1)
17268
17264
  return this._unsafeLadder(point, scalar, prev);
17269
- return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform), scalar, prev);
17265
+ return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform2), scalar, prev);
17270
17266
  }
17271
17267
  // We calculate precomputes for elliptic curve point multiplication
17272
17268
  // using windowed method. This specifies window size and
@@ -17353,9 +17349,9 @@ function edwards(params, extraOpts = {}) {
17353
17349
  validateObject(extraOpts, {}, { uvRatio: "function" });
17354
17350
  const MASK = _2n2 << BigInt(Fn.BYTES * 8) - _1n4;
17355
17351
  const modP = (n) => Fp.create(n);
17356
- const uvRatio2 = extraOpts.uvRatio || ((u, v) => {
17352
+ const uvRatio2 = extraOpts.uvRatio || ((u, v6) => {
17357
17353
  try {
17358
- return { isValid: true, value: Fp.sqrt(Fp.div(u, v)) };
17354
+ return { isValid: true, value: Fp.sqrt(Fp.div(u, v6)) };
17359
17355
  } catch (e) {
17360
17356
  return { isValid: false, value: _0n4 };
17361
17357
  }
@@ -17451,8 +17447,8 @@ function edwards(params, extraOpts = {}) {
17451
17447
  aInRange("point.y", y, _0n4, max);
17452
17448
  const y2 = modP(y * y);
17453
17449
  const u = modP(y2 - _1n4);
17454
- const v = modP(d * y2 - a);
17455
- let { isValid, value: x } = uvRatio2(u, v);
17450
+ const v6 = modP(d * y2 - a);
17451
+ let { isValid, value: x } = uvRatio2(u, v6);
17456
17452
  if (!isValid)
17457
17453
  throw new Error("bad point: invalid y coordinate");
17458
17454
  const isXOdd = (x & _1n4) === _1n4;
@@ -17792,13 +17788,13 @@ function adjustScalarBytes(bytes) {
17792
17788
  return bytes;
17793
17789
  }
17794
17790
  var ED25519_SQRT_M1 = /* @__PURE__ */ BigInt("19681161376707505956807079304988542015446066515923890162744021073123829784752");
17795
- function uvRatio(u, v) {
17791
+ function uvRatio(u, v6) {
17796
17792
  const P = ed25519_CURVE_p;
17797
- const v3 = mod(v * v * v, P);
17798
- const v7 = mod(v3 * v3 * v, P);
17793
+ const v32 = mod(v6 * v6 * v6, P);
17794
+ const v7 = mod(v32 * v32 * v6, P);
17799
17795
  const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8;
17800
- let x = mod(u * v3 * pow, P);
17801
- const vx2 = mod(v * x * x, P);
17796
+ let x = mod(u * v32 * pow, P);
17797
+ const vx2 = mod(v6 * x * x, P);
17802
17798
  const root1 = x;
17803
17799
  const root2 = mod(x * ED25519_SQRT_M1, P);
17804
17800
  const useRoot1 = vx2 === u;
@@ -18129,7 +18125,7 @@ function findSeatPrice(validators, maxNumberOfSeats, minimumStakeRatio, protocol
18129
18125
  return findSeatPriceForProtocolAfter49(validators, maxNumberOfSeats, minimumStakeRatio);
18130
18126
  }
18131
18127
  function findSeatPriceForProtocolBefore49(validators, numSeats) {
18132
- const stakes = validators.map((v) => BigInt(v.stake)).sort(sortBigIntAsc);
18128
+ const stakes = validators.map((v6) => BigInt(v6.stake)).sort(sortBigIntAsc);
18133
18129
  const num = BigInt(numSeats);
18134
18130
  const stakesSum = stakes.reduce((a, b) => a + b);
18135
18131
  if (stakesSum < num) {
@@ -18158,7 +18154,7 @@ function findSeatPriceForProtocolAfter49(validators, maxNumberOfSeats, minimumSt
18158
18154
  if (minimumStakeRatio.length != 2) {
18159
18155
  throw Error("minimumStakeRatio should have 2 elements");
18160
18156
  }
18161
- const stakes = validators.map((v) => BigInt(v.stake)).sort(sortBigIntAsc);
18157
+ const stakes = validators.map((v6) => BigInt(v6.stake)).sort(sortBigIntAsc);
18162
18158
  const stakesSum = stakes.reduce((a, b) => a + b);
18163
18159
  if (validators.length < maxNumberOfSeats) {
18164
18160
  return stakesSum * BigInt(minimumStakeRatio[0]) / BigInt(minimumStakeRatio[1]);
@@ -18330,10 +18326,10 @@ var DER = {
18330
18326
  if (length < 128)
18331
18327
  throw new E("tlv.decode(long): not minimal encoding");
18332
18328
  }
18333
- const v = data.subarray(pos, pos + length);
18334
- if (v.length !== length)
18329
+ const v6 = data.subarray(pos, pos + length);
18330
+ if (v6.length !== length)
18335
18331
  throw new E("tlv.decode: wrong value length");
18336
- return { v, l: data.subarray(pos + length) };
18332
+ return { v: v6, l: data.subarray(pos + length) };
18337
18333
  }
18338
18334
  },
18339
18335
  // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
@@ -18901,9 +18897,9 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
18901
18897
  extraEntropy: false
18902
18898
  };
18903
18899
  const hasLargeCofactor = CURVE_ORDER * _2n4 < Fp.ORDER;
18904
- function isBiggerThanHalfOrder(number) {
18900
+ function isBiggerThanHalfOrder(number4) {
18905
18901
  const HALF = CURVE_ORDER >> _1n6;
18906
- return number > HALF;
18902
+ return number4 > HALF;
18907
18903
  }
18908
18904
  function validateRS(title, num) {
18909
18905
  if (!Fn.isValidNot0(num))
@@ -19080,14 +19076,14 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
19080
19076
  return false;
19081
19077
  const { r, s } = sig;
19082
19078
  const h = bits2int_modN(message);
19083
- const is = Fn.inv(s);
19084
- const u1 = Fn.create(h * is);
19085
- const u2 = Fn.create(r * is);
19079
+ const is2 = Fn.inv(s);
19080
+ const u1 = Fn.create(h * is2);
19081
+ const u2 = Fn.create(r * is2);
19086
19082
  const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2));
19087
19083
  if (R.is0())
19088
19084
  return false;
19089
- const v = Fn.create(R.x);
19090
- return v === r;
19085
+ const v6 = Fn.create(R.x);
19086
+ return v6 === r;
19091
19087
  } catch (e) {
19092
19088
  return false;
19093
19089
  }
@@ -26433,13 +26429,18 @@ var SwapService = class {
26433
26429
  solver;
26434
26430
  partnerFee;
26435
26431
  relayerApiEndpoint;
26436
- constructor({ config, hubProvider, spoke }) {
26432
+ // backend swaps-API client + opt-in 2-step submit-tx flag
26433
+ backendApi;
26434
+ useBackendSubmitTx;
26435
+ constructor({ config, hubProvider, spoke, backendApi, useBackendSubmitTx }) {
26437
26436
  this.solver = config.solver;
26438
26437
  this.partnerFee = config.swapPartnerFee;
26439
26438
  this.relayerApiEndpoint = config.relay.relayerApiEndpoint;
26440
26439
  this.config = config;
26441
26440
  this.hubProvider = hubProvider;
26442
26441
  this.spoke = spoke;
26442
+ this.backendApi = backendApi;
26443
+ this.useBackendSubmitTx = useBackendSubmitTx ?? false;
26443
26444
  }
26444
26445
  /**
26445
26446
  * Estimates the gas cost for a raw (unsigned) transaction on a spoke chain.
@@ -26583,14 +26584,22 @@ var SwapService = class {
26583
26584
  /**
26584
26585
  * Executes a full end-to-end cross-chain swap.
26585
26586
  *
26586
- * Orchestrates the complete swap lifecycle:
26587
- * 1. Calls `createIntent` to submit the intent transaction on the source spoke chain.
26588
- * 2. Verifies the spoke transaction landed on-chain.
26589
- * 3. For non-hub source chains: submits the spoke tx to the relayer and waits for the
26590
- * relay packet to land on the hub (Sonic). Skipped when `srcChainKey` is the hub.
26591
- * 4. Calls `postExecution` to notify the solver, triggering it to fill the intent.
26592
- *
26593
- * @param _params - Swap action params including intent parameters, wallet provider, and optional timeout.
26587
+ * Orchestrates the complete swap lifecycle. `createIntent` first submits the intent transaction on
26588
+ * the source spoke chain; completion then runs via one of two paths, both bounded by a single
26589
+ * shared `timeout` budget:
26590
+ *
26591
+ * - **Client-side (default), {@link fallbackSwapSteps}:** verifies the spoke tx landed on-chain,
26592
+ * relays it to the hub (Sonic) and waits for the packet skipped when `srcChainKey` is the hub,
26593
+ * where the spoke tx already is the hub tx — then calls `postExecution` to notify the solver,
26594
+ * triggering it to fill the intent.
26595
+ * - **Backend 2-step (opt-in via `swapsOptions.useBackendSubmitTx`), {@link submitTx}:** hands the
26596
+ * broadcast tx to the swaps API, which verifies, relays and post-executes server-side, then polls
26597
+ * for completion. On ANY non-success it transparently falls back to the client-side path above —
26598
+ * safe because re-relaying / re-posting an already-processed swap is idempotent (no double-fill).
26599
+ *
26600
+ * @param _params - Swap action params including intent parameters, wallet provider, and an optional
26601
+ * `timeout` — the single shared budget for the whole completion flow (relay/poll plus any
26602
+ * fallback), so total wall-clock never exceeds it.
26594
26603
  * @returns A `Result<SwapResponse, SwapError>`. On success:
26595
26604
  * - `solverExecutionResponse` — solver acknowledgement (`{ answer: 'OK', intent_hash }`).
26596
26605
  * - `intent` — the on-chain intent object that was created.
@@ -26619,59 +26628,23 @@ var SwapService = class {
26619
26628
  "swap",
26620
26629
  async () => {
26621
26630
  try {
26622
- const timeout = _params.timeout;
26623
26631
  const createIntentResult = await this.createIntent(_params);
26624
26632
  if (!createIntentResult.ok) {
26625
26633
  return { ok: false, error: createIntentResult.error };
26626
26634
  }
26627
- const { tx: spokeTxHash, intent, relayData } = createIntentResult.value;
26628
- const verifyTxHashResult = await this.spoke.verifyTxHash({
26629
- txHash: spokeTxHash,
26630
- chainKey: srcChainKey
26631
- });
26632
- if (!verifyTxHashResult.ok) {
26633
- return { ok: false, error: verifyFailed("swap", verifyTxHashResult.error, { ...baseCtx, action: "swap" }) };
26634
- }
26635
- let dstIntentTxHash;
26636
- if (isHubChainKeyType(srcChainKey)) {
26637
- dstIntentTxHash = spokeTxHash;
26638
- } else {
26639
- const packet = await relayTxAndWaitPacket({
26640
- srcTxHash: spokeTxHash,
26641
- data: relayData,
26642
- chainKey: srcChainKey,
26643
- relayerApiEndpoint: this.relayerApiEndpoint,
26644
- timeout
26645
- });
26646
- if (!packet.ok) {
26647
- return {
26648
- ok: false,
26649
- error: mapRelayFailure(packet.error, { feature: "swap", action: "swap", ...baseCtx })
26650
- };
26651
- }
26652
- dstIntentTxHash = packet.value.dst_tx_hash;
26653
- }
26654
- const postExecResult = await this.postExecution({
26655
- intent_tx_hash: dstIntentTxHash
26656
- });
26657
- if (!postExecResult.ok) {
26658
- return { ok: false, error: postExecResult.error };
26659
- }
26660
- return {
26661
- ok: true,
26662
- value: {
26663
- solverExecutionResponse: postExecResult.value,
26664
- intent,
26665
- intentDeliveryInfo: {
26666
- srcChainKey,
26667
- srcTxHash: spokeTxHash,
26668
- srcAddress: params.srcAddress,
26669
- dstChainKey: params.dstChainKey,
26670
- dstTxHash: dstIntentTxHash,
26671
- dstAddress: params.dstAddress
26635
+ const created = createIntentResult.value;
26636
+ const deadline = Date.now() + (_params.timeout ?? DEFAULT_RELAY_TX_TIMEOUT);
26637
+ if (this.useBackendSubmitTx) {
26638
+ const submitted = await this.submitTx(_params, created, deadline);
26639
+ if (submitted.ok) return submitted;
26640
+ this.config.logger.warn(
26641
+ "[swap] backend submit-tx did not complete; falling back to the client-side relay",
26642
+ {
26643
+ error: submitted.error
26672
26644
  }
26673
- }
26674
- };
26645
+ );
26646
+ }
26647
+ return this.fallbackSwapSteps(_params, created, deadline);
26675
26648
  } catch (error) {
26676
26649
  if (isSwapError(error)) return { ok: false, error };
26677
26650
  return {
@@ -26697,6 +26670,134 @@ var SwapService = class {
26697
26670
  }
26698
26671
  );
26699
26672
  }
26673
+ /**
26674
+ * Client-side swap completion (the default path): relay the broadcast intent tx to the hub — or
26675
+ * use it directly when the source IS the hub — then notify the solver via post-execution and
26676
+ * build the {@link SwapResponse}. Extracted verbatim from `swap()` so the opt-in backend 2-step
26677
+ * path ({@link submitTx}) can fall back to it on any non-success.
26678
+ */
26679
+ async fallbackSwapSteps(_params, created, deadline) {
26680
+ const { params } = _params;
26681
+ const srcChainKey = params.srcChainKey;
26682
+ const baseCtx = { srcChainKey, dstChainKey: params.dstChainKey };
26683
+ const { tx: spokeTxHash, intent, relayData } = created;
26684
+ const verifyTxHashResult = await this.spoke.verifyTxHash({
26685
+ txHash: created.tx,
26686
+ chainKey: srcChainKey
26687
+ });
26688
+ if (!verifyTxHashResult.ok) {
26689
+ return { ok: false, error: verifyFailed("swap", verifyTxHashResult.error, { ...baseCtx, action: "swap" }) };
26690
+ }
26691
+ let dstIntentTxHash;
26692
+ if (isHubChainKeyType(srcChainKey)) {
26693
+ dstIntentTxHash = spokeTxHash;
26694
+ } else {
26695
+ const packet = await relayTxAndWaitPacket({
26696
+ srcTxHash: spokeTxHash,
26697
+ data: relayData,
26698
+ chainKey: srcChainKey,
26699
+ relayerApiEndpoint: this.relayerApiEndpoint,
26700
+ // Remaining shared budget: ≈ full `timeout` on the flag-off path (called immediately), or
26701
+ // the reserve `submitTx` left on the backend path. Floor keeps a stalled-backend fallback viable.
26702
+ timeout: Math.max(deadline - Date.now(), 5e3)
26703
+ });
26704
+ if (!packet.ok) {
26705
+ return { ok: false, error: mapRelayFailure(packet.error, { feature: "swap", action: "swap", ...baseCtx }) };
26706
+ }
26707
+ dstIntentTxHash = packet.value.dst_tx_hash;
26708
+ }
26709
+ const postExecResult = await this.postExecution({
26710
+ intent_tx_hash: dstIntentTxHash
26711
+ });
26712
+ if (!postExecResult.ok) {
26713
+ return { ok: false, error: postExecResult.error };
26714
+ }
26715
+ return {
26716
+ ok: true,
26717
+ value: {
26718
+ solverExecutionResponse: postExecResult.value,
26719
+ intent,
26720
+ intentDeliveryInfo: {
26721
+ srcChainKey,
26722
+ srcTxHash: spokeTxHash,
26723
+ srcAddress: params.srcAddress,
26724
+ dstChainKey: params.dstChainKey,
26725
+ dstTxHash: dstIntentTxHash,
26726
+ dstAddress: params.dstAddress
26727
+ }
26728
+ }
26729
+ };
26730
+ }
26731
+ /**
26732
+ * Backend 2-step swap path (opt-in via `swapsOptions.useBackendSubmitTx`): hand the broadcast
26733
+ * intent tx to the swaps API (`POST /swaps/submit-tx`); the backend relays + post-executes
26734
+ * server-side. Polls `getSubmitTxStatus` until `executed`, then reconstructs the same
26735
+ * {@link SwapResponse} the client-side path returns (`result.dstIntentTxHash` → delivery info,
26736
+ * `result.intent_hash` → solver response).
26737
+ *
26738
+ * Never throws — returns `{ ok: false }` on any non-success (submit `!ok`, terminal `failed` /
26739
+ * abandoned, or poll timeout) so `swap()` falls back to {@link fallbackSwapSteps}.
26740
+ *
26741
+ * Falling back is safe: re-relaying / re-posting an already-processed swap is idempotent — the
26742
+ * relay dedups and returns the existing `executed` packet, and the solver re-affirms the intent
26743
+ * (no double-fill). Verified live by `e2e-tests/e2e-relay.test.ts`. Polling stops at
26744
+ * `deadline - reserve` so the fallback keeps a guaranteed slice of the shared `swap` budget.
26745
+ */
26746
+ async submitTx(_params, created, deadline) {
26747
+ const { params } = _params;
26748
+ const srcChainKey = params.srcChainKey;
26749
+ const baseCtx = { srcChainKey, dstChainKey: params.dstChainKey };
26750
+ const { tx: spokeTxHash, intent, relayData } = created;
26751
+ const submitTxFailed = (cause) => ({
26752
+ ok: false,
26753
+ error: executionFailed("swap", cause, { ...baseCtx, action: "swap" })
26754
+ });
26755
+ try {
26756
+ const submitted = await this.backendApi.swaps.submitTx({
26757
+ txHash: spokeTxHash,
26758
+ srcChainKey,
26759
+ walletAddress: params.srcAddress,
26760
+ intent,
26761
+ relayData: relayData.payload
26762
+ });
26763
+ if (!submitted.ok) return submitTxFailed(submitted.error);
26764
+ const reserveMs = Math.min(Math.ceil((deadline - Date.now()) / 3), 2e4);
26765
+ const pollDeadline = deadline - reserveMs;
26766
+ const pollIntervalMs = 1e3;
26767
+ while (Date.now() < pollDeadline) {
26768
+ const statusResult = await this.backendApi.swaps.getSubmitTxStatus({ txHash: spokeTxHash, srcChainKey });
26769
+ if (statusResult.ok) {
26770
+ const { status, result, failureReason, abandonedAt } = statusResult.value.data;
26771
+ if (status === "executed" && result?.dstIntentTxHash && result.intent_hash) {
26772
+ return {
26773
+ ok: true,
26774
+ value: {
26775
+ // Backend serializes the hex intent_hash as a plain string; brand it at the boundary.
26776
+ solverExecutionResponse: { answer: "OK", intent_hash: result.intent_hash },
26777
+ intent,
26778
+ intentDeliveryInfo: {
26779
+ srcChainKey,
26780
+ srcTxHash: spokeTxHash,
26781
+ srcAddress: params.srcAddress,
26782
+ dstChainKey: params.dstChainKey,
26783
+ dstTxHash: result.dstIntentTxHash,
26784
+ dstAddress: params.dstAddress
26785
+ }
26786
+ }
26787
+ };
26788
+ }
26789
+ if (status === "failed" || abandonedAt) {
26790
+ const reason = failureReason ? `: ${failureReason}` : "";
26791
+ return submitTxFailed(new Error(`backend submit-tx ${status}${reason}`));
26792
+ }
26793
+ }
26794
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
26795
+ }
26796
+ return submitTxFailed(new Error("backend submit-tx polling timed out before reaching executed"));
26797
+ } catch (error) {
26798
+ return { ok: false, error: unknownFailed("swap", error, { ...baseCtx, action: "swap" }) };
26799
+ }
26800
+ }
26700
26801
  /**
26701
26802
  * Checks whether the relevant spender contract is already approved to spend the input token amount.
26702
26803
  *
@@ -29419,71 +29520,883 @@ var MigrationService = class {
29419
29520
  }
29420
29521
  };
29421
29522
 
29422
- // src/backendApi/BackendApiService.ts
29423
- var BackendApiService = class {
29523
+ // src/backendApi/api-utils.ts
29524
+ var toJsonBody = (value) => JSON.stringify(value, (_key, val) => typeof val === "bigint" ? val.toString() : val);
29525
+ async function makeRequest(params) {
29526
+ const { endpoint, config, overrideConfig = {}, logger, serviceLabel } = params;
29527
+ const baseURL = overrideConfig.baseURL || config.baseURL || "";
29528
+ const url = `${baseURL}${endpoint}`;
29529
+ const headers = { ...config.headers, ...overrideConfig.headers };
29530
+ const controller = new AbortController();
29531
+ const timeout = overrideConfig.timeout ?? config.timeout ?? DEFAULT_BACKEND_API_TIMEOUT;
29532
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
29533
+ try {
29534
+ const response = await fetch(url, {
29535
+ method: config.method,
29536
+ headers,
29537
+ body: config.body,
29538
+ signal: controller.signal
29539
+ });
29540
+ clearTimeout(timeoutId);
29541
+ if (!response.ok) {
29542
+ const errorText = await response.text();
29543
+ throw new Error("HTTP_REQUEST_FAILED", { cause: new Error(`HTTP ${response.status}: ${errorText}`) });
29544
+ }
29545
+ const data = await response.json();
29546
+ return data;
29547
+ } catch (error) {
29548
+ clearTimeout(timeoutId);
29549
+ if (error instanceof Error) {
29550
+ if (error.name === "AbortError") {
29551
+ throw new Error("REQUEST_TIMEOUT", { cause: new Error(`Request timeout after ${timeout}ms`) });
29552
+ }
29553
+ logger.error(`[${serviceLabel}] Request error`, error);
29554
+ throw error;
29555
+ }
29556
+ logger.error(`[${serviceLabel}] Unknown error`, error);
29557
+ throw new Error("UNKNOWN_REQUEST_ERROR", { cause: error });
29558
+ }
29559
+ }
29560
+ var SwapTokenSchema = v4.object({
29561
+ symbol: v4.string(),
29562
+ name: v4.string(),
29563
+ decimals: v4.number(),
29564
+ address: v4.string(),
29565
+ chainKey: v4.string(),
29566
+ hubAsset: v4.string(),
29567
+ vault: v4.string()
29568
+ });
29569
+ var IntentResponseSchema = v4.object({
29570
+ intentId: v4.string(),
29571
+ creator: v4.string(),
29572
+ inputToken: v4.string(),
29573
+ outputToken: v4.string(),
29574
+ inputAmount: v4.string(),
29575
+ minOutputAmount: v4.string(),
29576
+ deadline: v4.string(),
29577
+ allowPartialFill: v4.boolean(),
29578
+ srcChain: v4.string(),
29579
+ dstChain: v4.string(),
29580
+ srcAddress: v4.string(),
29581
+ dstAddress: v4.string(),
29582
+ solver: v4.string(),
29583
+ data: v4.string()
29584
+ });
29585
+ var RelayExtraDataResponseSchema = v4.object({
29586
+ address: v4.string(),
29587
+ payload: v4.string()
29588
+ });
29589
+ var makeCreateIntentResponseSchema = (txSchema) => v4.object({
29590
+ tx: txSchema,
29591
+ intent: IntentResponseSchema,
29592
+ relayData: RelayExtraDataResponseSchema
29593
+ });
29594
+ var GetSwapTokensResponseSchema = v4.record(v4.string(), v4.array(SwapTokenSchema));
29595
+ var GetSwapTokensByChainResponseSchema = v4.array(SwapTokenSchema);
29596
+ var makeQuoteResponseSchema = (txSchema) => v4.object({
29597
+ quotedAmount: v4.string(),
29598
+ txData: v4.optional(makeCreateIntentResponseSchema(txSchema))
29599
+ });
29600
+ var DeadlineResponseSchema = v4.object({
29601
+ deadline: v4.string()
29602
+ });
29603
+ var AllowanceCheckResponseSchema = v4.object({
29604
+ valid: v4.boolean()
29605
+ });
29606
+ var makeApproveResponseSchema = (txSchema) => v4.object({ tx: txSchema });
29607
+ var SubmitIntentResponseSchema = v4.object({
29608
+ result: v4.unknown()
29609
+ });
29610
+ var StatusResponseSchema = v4.object({
29611
+ status: v4.picklist([-1, 1, 2, 3, 4]),
29612
+ fillTxHash: v4.optional(v4.string())
29613
+ });
29614
+ var makeCancelIntentResponseSchema = (txSchema) => v4.object({ tx: txSchema });
29615
+ var IntentHashResponseSchema = v4.object({
29616
+ hash: v4.string()
29617
+ });
29618
+ var IntentPacketResponseSchema = v4.object({
29619
+ srcChainId: v4.number(),
29620
+ srcTxHash: v4.string(),
29621
+ srcAddress: v4.string(),
29622
+ status: v4.string(),
29623
+ dstChainId: v4.number(),
29624
+ connSn: v4.number(),
29625
+ dstAddress: v4.string(),
29626
+ dstTxHash: v4.string(),
29627
+ signatures: v4.array(v4.string()),
29628
+ payload: v4.string()
29629
+ });
29630
+ var IntentStateResponseSchema = v4.object({
29631
+ exists: v4.boolean(),
29632
+ remainingInput: v4.string(),
29633
+ receivedOutput: v4.string(),
29634
+ pendingPayment: v4.boolean()
29635
+ });
29636
+ var GasEstimateResponseSchema = v4.object({
29637
+ gas: v4.unknown()
29638
+ });
29639
+ var FeeResponseSchema = v4.object({
29640
+ fee: v4.string()
29641
+ });
29642
+ var SubmitTxResponseSchema = v4.object({
29643
+ success: v4.boolean(),
29644
+ data: v4.object({
29645
+ status: v4.picklist(["inserted", "duplicate"]),
29646
+ message: v4.string()
29647
+ })
29648
+ });
29649
+ var SubmitSwapTxStatusSchema = v4.picklist([
29650
+ "pending",
29651
+ "relaying",
29652
+ "relayed",
29653
+ "posting_execution",
29654
+ "executed",
29655
+ "failed"
29656
+ ]);
29657
+ var PacketDataSchema = v4.object({
29658
+ src_chain_id: v4.number(),
29659
+ src_tx_hash: v4.string(),
29660
+ src_address: v4.string(),
29661
+ status: v4.picklist(["pending", "validating", "executing", "executed"]),
29662
+ dst_chain_id: v4.number(),
29663
+ conn_sn: v4.number(),
29664
+ dst_address: v4.string(),
29665
+ dst_tx_hash: v4.string(),
29666
+ signatures: v4.array(v4.string()),
29667
+ payload: v4.string()
29668
+ });
29669
+ var SubmitTxStatusResultSchema = v4.object({
29670
+ dstIntentTxHash: v4.string(),
29671
+ packetData: v4.optional(PacketDataSchema),
29672
+ intent_hash: v4.optional(v4.string())
29673
+ });
29674
+ var SubmitTxStatusDataSchema = v4.object({
29675
+ txHash: v4.string(),
29676
+ srcChainKey: v4.string(),
29677
+ status: SubmitSwapTxStatusSchema,
29678
+ failedAtStep: v4.optional(SubmitSwapTxStatusSchema),
29679
+ failureReason: v4.optional(v4.string()),
29680
+ processingAttempts: v4.number(),
29681
+ abandonedAt: v4.optional(v4.string()),
29682
+ result: v4.optional(SubmitTxStatusResultSchema),
29683
+ userMessage: v4.optional(v4.string()),
29684
+ intentCancelled: v4.optional(v4.boolean())
29685
+ });
29686
+ var SubmitTxStatusResponseSchema = v4.object({
29687
+ success: v4.boolean(),
29688
+ data: SubmitTxStatusDataSchema
29689
+ });
29690
+ var AddressSchema = v4.custom((input) => typeof input === "string");
29691
+ var HexSchema = v4.custom((input) => typeof input === "string");
29692
+ var BigintFromString = v4.pipe(v4.string(), v4.toBigint());
29693
+ var BytesFromIndexRecord = v4.pipe(
29694
+ v4.record(v4.string(), v4.number()),
29695
+ v4.transform((indexed) => Uint8Array.from(Object.values(indexed)))
29696
+ );
29697
+ var EvmRawTxSchema = v4.object({
29698
+ from: AddressSchema,
29699
+ to: AddressSchema,
29700
+ value: BigintFromString,
29701
+ data: HexSchema
29702
+ });
29703
+ var SolanaRawTxSchema = v4.object({
29704
+ from: v4.string(),
29705
+ to: v4.string(),
29706
+ value: BigintFromString,
29707
+ data: v4.string()
29708
+ });
29709
+ var SuiRawTxSchema = v4.object({
29710
+ from: HexSchema,
29711
+ to: v4.string(),
29712
+ value: BigintFromString,
29713
+ data: v4.string()
29714
+ });
29715
+ var StellarRawTxSchema = v4.object({
29716
+ from: v4.string(),
29717
+ to: v4.string(),
29718
+ value: BigintFromString,
29719
+ data: v4.string()
29720
+ });
29721
+ var InjectiveRawTxSchema = v4.object({
29722
+ from: HexSchema,
29723
+ to: HexSchema,
29724
+ signedDoc: v4.object({
29725
+ bodyBytes: BytesFromIndexRecord,
29726
+ authInfoBytes: BytesFromIndexRecord,
29727
+ chainId: v4.string(),
29728
+ accountNumber: BigintFromString
29729
+ })
29730
+ });
29731
+ var NearRawTxSchema = v4.object({
29732
+ signerId: v4.string(),
29733
+ params: v4.object({
29734
+ contractId: v4.string(),
29735
+ method: v4.string(),
29736
+ args: v4.custom((input) => typeof input === "object" && input !== null),
29737
+ gas: v4.optional(BigintFromString),
29738
+ deposit: v4.optional(BigintFromString)
29739
+ })
29740
+ });
29741
+ var IconRawTxSchema = v4.record(
29742
+ v4.string(),
29743
+ v4.union([v4.string(), v4.custom((input) => typeof input === "object" && input !== null)])
29744
+ );
29745
+ var StacksRawTxSchema = v4.object({
29746
+ payload: v4.string(),
29747
+ estimatedLength: v4.optional(v4.number())
29748
+ });
29749
+ var AnyRawTxSchema = v4.custom((input) => typeof input === "object" && input !== null);
29750
+ function rawTxSchemaForChainKey(chainKey) {
29751
+ let chainType;
29752
+ try {
29753
+ chainType = getChainType(chainKey);
29754
+ } catch {
29755
+ chainType = void 0;
29756
+ }
29757
+ switch (chainType) {
29758
+ case "EVM":
29759
+ return EvmRawTxSchema;
29760
+ case "SOLANA":
29761
+ return SolanaRawTxSchema;
29762
+ case "SUI":
29763
+ return SuiRawTxSchema;
29764
+ case "STELLAR":
29765
+ return StellarRawTxSchema;
29766
+ case "INJECTIVE":
29767
+ return InjectiveRawTxSchema;
29768
+ case "ICON":
29769
+ return IconRawTxSchema;
29770
+ case "STACKS":
29771
+ return StacksRawTxSchema;
29772
+ case "NEAR":
29773
+ return NearRawTxSchema;
29774
+ default:
29775
+ return AnyRawTxSchema;
29776
+ }
29777
+ }
29778
+
29779
+ // src/backendApi/SwapsApiService.ts
29780
+ var SwapsApiService = class {
29781
+ // Fully-resolved swaps-API config supplied by the caller (BackendApiService resolves the
29782
+ // `ApiConfig` union via `resolveSwapsApiConfig`); this service does not resolve the union.
29783
+ config;
29784
+ headers;
29785
+ logger;
29424
29786
  constructor(config, logger = consoleLogger) {
29425
29787
  this.config = config;
29426
29788
  this.headers = { ...config.headers };
29427
29789
  this.logger = logger;
29428
29790
  }
29429
- headers;
29430
- logger;
29431
29791
  /**
29432
- * Execute a single HTTP request and return the parsed JSON body.
29433
- *
29434
- * Applies an `AbortController`-backed timeout (falls back to `this.config.timeout`
29435
- * when `config.timeout` is absent). Throws on non-2xx status codes or when the
29436
- * request exceeds the timeout, so callers should use {@link request} instead of
29437
- * calling this directly.
29438
- *
29439
- * @throws `Error('HTTP_REQUEST_FAILED')` on non-2xx responses.
29440
- * @throws `Error('REQUEST_TIMEOUT')` when the request exceeds the timeout.
29441
- * @throws `Error('UNKNOWN_REQUEST_ERROR')` for any other unexpected failure.
29792
+ * Issues a single HTTP request, validates the JSON body against `schema`, and
29793
+ * wraps the result in `Result<T>`. The service-level `baseURL`/`timeout`/
29794
+ * `headers` are merged with the optional per-call `overrideConfig` (which takes
29795
+ * precedence) inside {@link makeRequest}. Every public method delegates here.
29442
29796
  */
29443
- async makeRequest(endpoint, config) {
29444
- const url = config.baseURL ? `${config.baseURL}${endpoint}` : `${this.config.baseURL}${endpoint}`;
29445
- const headers = { ...this.headers, ...config.headers };
29446
- const controller = new AbortController();
29447
- const timeout = config.timeout ?? this.config.timeout;
29448
- const timeoutId = setTimeout(() => controller.abort(), timeout);
29797
+ async request(endpoint, config, schema, overrideConfig) {
29449
29798
  try {
29450
- const response = await fetch(url, {
29451
- method: config.method,
29452
- headers,
29453
- body: config.body,
29454
- signal: controller.signal
29799
+ const raw = await makeRequest({
29800
+ endpoint,
29801
+ config: { baseURL: this.config.baseURL, timeout: this.config.timeout, headers: this.headers, ...config },
29802
+ overrideConfig,
29803
+ logger: this.logger,
29804
+ serviceLabel: "SwapsApiService"
29455
29805
  });
29456
- clearTimeout(timeoutId);
29457
- if (!response.ok) {
29458
- const errorText = await response.text();
29459
- throw new Error("HTTP_REQUEST_FAILED", { cause: new Error(`HTTP ${response.status}: ${errorText}`) });
29806
+ const parsed = v4.safeParse(schema, raw);
29807
+ if (!parsed.success) {
29808
+ return {
29809
+ ok: false,
29810
+ error: new SodaxError("EXTERNAL_API_ERROR", `Invalid response shape from swaps API for ${endpoint}`, {
29811
+ feature: "backend",
29812
+ context: { api: "swaps", endpoint, reason: "invalid_response_shape", issues: v4.flatten(parsed.issues) }
29813
+ })
29814
+ };
29460
29815
  }
29461
- const data = await response.json();
29462
- return data;
29816
+ return { ok: true, value: parsed.output };
29463
29817
  } catch (error) {
29464
- clearTimeout(timeoutId);
29465
- if (error instanceof Error) {
29466
- if (error.name === "AbortError") {
29467
- throw new Error("REQUEST_TIMEOUT", { cause: new Error(`Request timeout after ${timeout}ms`) });
29468
- }
29469
- this.logger.error("[BackendApiService] Request error", error);
29470
- throw error;
29471
- }
29472
- this.logger.error("[BackendApiService] Unknown error", error);
29473
- throw new Error("UNKNOWN_REQUEST_ERROR", { cause: error });
29818
+ return {
29819
+ ok: false,
29820
+ error: new SodaxError(
29821
+ "EXTERNAL_API_ERROR",
29822
+ error instanceof Error ? error.message : `Request to ${endpoint} failed`,
29823
+ {
29824
+ feature: "backend",
29825
+ cause: error,
29826
+ context: { api: "swaps", endpoint }
29827
+ }
29828
+ )
29829
+ };
29474
29830
  }
29475
29831
  }
29832
+ // ──────────────────────────────────────────────────────────────────────
29833
+ // Tokens
29834
+ // ──────────────────────────────────────────────────────────────────────
29835
+ /**
29836
+ * Fetch all supported swap tokens grouped by SpokeChainKey.
29837
+ *
29838
+ * @returns `Result<GetSwapTokensResponseV2>` — map of chain key → token list.
29839
+ */
29840
+ async getTokens(config) {
29841
+ return this.request("/swaps/tokens", { method: "GET" }, GetSwapTokensResponseSchema, config);
29842
+ }
29843
+ /**
29844
+ * Fetch supported swap tokens for a single SpokeChainKey.
29845
+ *
29846
+ * @param chainKey - SODAX SpokeChainKey (e.g. `0xa4b1.arbitrum`, `solana`).
29847
+ * @returns `Result<GetSwapTokensByChainResponseV2>` — token list for the chain.
29848
+ */
29849
+ async getTokensByChain(chainKey, config) {
29850
+ return this.request(
29851
+ `/swaps/tokens/${chainKey}`,
29852
+ { method: "GET" },
29853
+ GetSwapTokensByChainResponseSchema,
29854
+ config
29855
+ );
29856
+ }
29857
+ // ──────────────────────────────────────────────────────────────────────
29858
+ // Quote · deadline
29859
+ // ──────────────────────────────────────────────────────────────────────
29860
+ /**
29861
+ * Get a solver quote for a cross-chain swap.
29862
+ *
29863
+ * Pass `query.includeTxData = true` to also build an unsigned create-intent
29864
+ * transaction (`txData`) using the quoted amount as `minOutputAmount`; in that
29865
+ * case `srcAddress`/`dstAddress` are required in the body.
29866
+ *
29867
+ * @returns `Result<QuoteResponseV2>` — `quotedAmount` (decimal string) and optional `txData`.
29868
+ */
29869
+ async getQuote(body, query, config) {
29870
+ const endpoint = query?.includeTxData ? "/swaps/quote?includeTxData=true" : "/swaps/quote";
29871
+ const txSchema = rawTxSchemaForChainKey(body.tokenSrcChainKey);
29872
+ return this.request(
29873
+ endpoint,
29874
+ { method: "POST", body: toJsonBody(body) },
29875
+ makeQuoteResponseSchema(txSchema),
29876
+ config
29877
+ );
29878
+ }
29879
+ /**
29880
+ * Compute a swap deadline (hub timestamp + `offsetSeconds`, default 300s).
29881
+ *
29882
+ * @returns `Result<DeadlineResponseV2>` — unix-seconds deadline (decimal string).
29883
+ */
29884
+ async getDeadline(query, config) {
29885
+ const queryParams = new URLSearchParams();
29886
+ if (query?.offsetSeconds !== void 0) queryParams.append("offsetSeconds", String(query.offsetSeconds));
29887
+ const queryString = queryParams.toString();
29888
+ const endpoint = queryString.length > 0 ? `/swaps/deadline?${queryString}` : "/swaps/deadline";
29889
+ return this.request(endpoint, { method: "GET" }, DeadlineResponseSchema, config);
29890
+ }
29891
+ // ──────────────────────────────────────────────────────────────────────
29892
+ // Allowance · approve · create intent
29893
+ // ──────────────────────────────────────────────────────────────────────
29894
+ /**
29895
+ * Check whether the source token allowance is already sufficient for the intent.
29896
+ *
29897
+ * @returns `Result<AllowanceCheckResponseV2>` — `{ valid }`.
29898
+ */
29899
+ async checkAllowance(body, config) {
29900
+ return this.request(
29901
+ "/swaps/allowance/check",
29902
+ { method: "POST", body: toJsonBody(body) },
29903
+ AllowanceCheckResponseSchema,
29904
+ config
29905
+ );
29906
+ }
29907
+ /**
29908
+ * Build an unsigned token-approval transaction for the source token.
29909
+ *
29910
+ * @returns `Result<ApproveResponseV2>` — `{ tx }` (chain-specific unsigned tx).
29911
+ */
29912
+ async approve(body, config) {
29913
+ const txSchema = rawTxSchemaForChainKey(body.srcChainKey);
29914
+ return this.request(
29915
+ "/swaps/approve",
29916
+ { method: "POST", body: toJsonBody(body) },
29917
+ makeApproveResponseSchema(txSchema),
29918
+ config
29919
+ );
29920
+ }
29921
+ /**
29922
+ * Build an unsigned create-intent transaction.
29923
+ *
29924
+ * @returns `Result<CreateIntentResponseV2>` — `{ tx, intent, relayData }`.
29925
+ */
29926
+ async createIntent(body, config) {
29927
+ const txSchema = rawTxSchemaForChainKey(body.srcChainKey);
29928
+ return this.request(
29929
+ "/swaps/intents",
29930
+ { method: "POST", body: toJsonBody(body) },
29931
+ makeCreateIntentResponseSchema(txSchema),
29932
+ config
29933
+ );
29934
+ }
29935
+ // ──────────────────────────────────────────────────────────────────────
29936
+ // Intent lifecycle: submit · status · cancel · hash · packet · extra-data
29937
+ // ──────────────────────────────────────────────────────────────────────
29938
+ /**
29939
+ * Submit the broadcast intent tx to the relay.
29940
+ *
29941
+ * @returns `Result<SubmitIntentResponseV2>` — `{ result }` (opaque relay response).
29942
+ */
29943
+ async submitIntent(body, config) {
29944
+ return this.request(
29945
+ "/swaps/intents/submit",
29946
+ { method: "POST", body: toJsonBody(body) },
29947
+ SubmitIntentResponseSchema,
29948
+ config
29949
+ );
29950
+ }
29951
+ /**
29952
+ * Poll the solver for intent execution status.
29953
+ *
29954
+ * @returns `Result<StatusResponseV2>` — `{ status, fillTxHash? }` (`fillTxHash` set when `status === 3`).
29955
+ */
29956
+ async getStatus(body, config) {
29957
+ return this.request(
29958
+ "/swaps/intents/status",
29959
+ { method: "POST", body: toJsonBody(body) },
29960
+ StatusResponseSchema,
29961
+ config
29962
+ );
29963
+ }
29964
+ /**
29965
+ * Build an unsigned cancel-intent transaction. The `intent` field carries
29966
+ * `bigint` numerics — {@link toJsonBody} serializes them to decimal strings.
29967
+ *
29968
+ * @returns `Result<CancelIntentResponseV2>` — `{ tx }`.
29969
+ */
29970
+ async cancelIntent(body, config) {
29971
+ const txSchema = rawTxSchemaForChainKey(body.srcChainKey);
29972
+ return this.request(
29973
+ "/swaps/intents/cancel",
29974
+ { method: "POST", body: toJsonBody(body) },
29975
+ makeCancelIntentResponseSchema(txSchema),
29976
+ config
29977
+ );
29978
+ }
29979
+ /**
29980
+ * Compute the keccak256 hash of an Intent struct. The `intent` field carries
29981
+ * `bigint` numerics — {@link toJsonBody} serializes them to decimal strings.
29982
+ *
29983
+ * @returns `Result<IntentHashResponseV2>` — `{ hash }`.
29984
+ */
29985
+ async getIntentHash(body, config) {
29986
+ return this.request(
29987
+ "/swaps/intents/hash",
29988
+ { method: "POST", body: toJsonBody(body) },
29989
+ IntentHashResponseSchema,
29990
+ config
29991
+ );
29992
+ }
29993
+ /**
29994
+ * Long-poll the relayer until the fill packet lands on the destination chain.
29995
+ *
29996
+ * @returns `Result<IntentPacketResponseV2>` — delivered packet data.
29997
+ */
29998
+ async getSolvedIntentPacket(body, config) {
29999
+ return this.request(
30000
+ "/swaps/intents/packet",
30001
+ { method: "POST", body: toJsonBody(body) },
30002
+ IntentPacketResponseSchema,
30003
+ config
30004
+ );
30005
+ }
30006
+ /**
30007
+ * Recover the relay extra data needed by `/swaps/intents/submit`. Provide
30008
+ * EITHER `txHash` OR `intent` (whose `bigint` numerics {@link toJsonBody} serializes).
30009
+ *
30010
+ * @returns `Result<IntentExtraDataResponseV2>` — `{ address, payload }`.
30011
+ */
30012
+ async getIntentSubmitTxExtraData(body, config) {
30013
+ return this.request(
30014
+ "/swaps/intents/extra-data",
30015
+ { method: "POST", body: toJsonBody(body) },
30016
+ RelayExtraDataResponseSchema,
30017
+ config
30018
+ );
30019
+ }
30020
+ /**
30021
+ * Get the on-chain fill state for an intent by its hub-chain tx hash.
30022
+ *
30023
+ * @returns `Result<IntentStateV2>` — `{ exists, remainingInput, receivedOutput, pendingPayment }`.
30024
+ */
30025
+ async getFilledIntent(txHash, config) {
30026
+ return this.request(`/swaps/intents/${txHash}/fill`, { method: "GET" }, IntentStateResponseSchema, config);
30027
+ }
30028
+ /**
30029
+ * Look up an Intent struct by its hub-chain creation tx hash.
30030
+ *
30031
+ * @returns `Result<GetIntentResponseV2>` — the decoded intent (bigint fields as decimal strings).
30032
+ */
30033
+ async getIntent(txHash, config) {
30034
+ return this.request(`/swaps/intents/${txHash}`, { method: "GET" }, IntentResponseSchema, config);
30035
+ }
30036
+ // ──────────────────────────────────────────────────────────────────────
30037
+ // Limit orders · gas · fees
30038
+ // ──────────────────────────────────────────────────────────────────────
30039
+ /**
30040
+ * Build an unsigned create-limit-order-intent transaction (same as create-intent
30041
+ * but `deadline` is optional).
30042
+ *
30043
+ * @returns `Result<CreateLimitOrderResponseV2>` — `{ tx, intent, relayData }`.
30044
+ */
30045
+ async createLimitOrderIntent(body, config) {
30046
+ const txSchema = rawTxSchemaForChainKey(body.srcChainKey);
30047
+ return this.request(
30048
+ "/swaps/limit-orders",
30049
+ { method: "POST", body: toJsonBody(body) },
30050
+ makeCreateIntentResponseSchema(txSchema),
30051
+ config
30052
+ );
30053
+ }
30054
+ /**
30055
+ * Estimate gas for a raw transaction on a spoke chain.
30056
+ *
30057
+ * @returns `Result<GasEstimateResponseV2>` — `{ gas }` (chain-specific shape).
30058
+ */
30059
+ async estimateGas(body, config) {
30060
+ return this.request(
30061
+ "/swaps/gas/estimate",
30062
+ { method: "POST", body: toJsonBody(body) },
30063
+ GasEstimateResponseSchema,
30064
+ config
30065
+ );
30066
+ }
30067
+ /**
30068
+ * Compute the partner fee for a given input amount.
30069
+ *
30070
+ * @returns `Result<FeeResponseV2>` — `{ fee }` (decimal string).
30071
+ */
30072
+ async getPartnerFee(query, config) {
30073
+ const queryParams = new URLSearchParams({ amount: query.amount });
30074
+ return this.request(
30075
+ `/swaps/fees/partner?${queryParams.toString()}`,
30076
+ { method: "GET" },
30077
+ FeeResponseSchema,
30078
+ config
30079
+ );
30080
+ }
30081
+ /**
30082
+ * Compute the protocol (solver) fee for a given input amount.
30083
+ *
30084
+ * @returns `Result<FeeResponseV2>` — `{ fee }` (decimal string).
30085
+ */
30086
+ async getSolverFee(query, config) {
30087
+ const queryParams = new URLSearchParams({ amount: query.amount });
30088
+ return this.request(
30089
+ `/swaps/fees/solver?${queryParams.toString()}`,
30090
+ { method: "GET" },
30091
+ FeeResponseSchema,
30092
+ config
30093
+ );
30094
+ }
30095
+ // ──────────────────────────────────────────────────────────────────────
30096
+ // Submit-tx state machine
30097
+ // ──────────────────────────────────────────────────────────────────────
30098
+ /**
30099
+ * Submit a swap transaction to be processed (relay, post-execution, etc.). The
30100
+ * `intent` field carries `bigint` numerics — {@link toJsonBody} serializes them.
30101
+ * Idempotent on `(txHash, srcChainKey)`.
30102
+ *
30103
+ * @returns `Result<SubmitTxResponseV2>` — `{ success, data: { status, message } }`.
30104
+ */
30105
+ async submitTx(body, config) {
30106
+ return this.request(
30107
+ "/swaps/submit-tx",
30108
+ { method: "POST", body: toJsonBody(body) },
30109
+ SubmitTxResponseSchema,
30110
+ config
30111
+ );
30112
+ }
30113
+ /**
30114
+ * Get the processing status of a submitted swap transaction by `(txHash, srcChainKey)`.
30115
+ *
30116
+ * @returns `Result<SubmitTxStatusResponseV2>` — `{ success, data }` (processing state).
30117
+ */
30118
+ async getSubmitTxStatus(query, config) {
30119
+ const queryParams = new URLSearchParams({ txHash: query.txHash, srcChainKey: query.srcChainKey });
30120
+ return this.request(
30121
+ `/swaps/submit-tx/status?${queryParams.toString()}`,
30122
+ { method: "GET" },
30123
+ SubmitTxStatusResponseSchema,
30124
+ config
30125
+ );
30126
+ }
30127
+ // ──────────────────────────────────────────────────────────────────────
30128
+ // Utilities (parity with BackendApiService)
30129
+ // ──────────────────────────────────────────────────────────────────────
30130
+ /**
30131
+ * Merge additional headers into the service's default header set. Existing
30132
+ * keys are overwritten; keys absent from `headers` are preserved.
30133
+ */
30134
+ setHeaders(headers) {
30135
+ Object.entries(headers).forEach(([key, value]) => {
30136
+ this.headers[key] = value;
30137
+ });
30138
+ }
30139
+ /** Return the base URL the service is currently pointing at. */
30140
+ getBaseURL() {
30141
+ return this.config.baseURL;
30142
+ }
30143
+ };
30144
+
30145
+ // src/backendApi/apiConfig.ts
30146
+ function isCustomApiConfig(config) {
30147
+ return "baseApiConfig" in config || "swapsApiConfig" in config;
30148
+ }
30149
+ function layerConfigs(...slices) {
30150
+ return slices.reduce(
30151
+ (acc, slice) => slice ? {
30152
+ baseURL: slice.baseURL ?? acc.baseURL,
30153
+ timeout: slice.timeout ?? acc.timeout,
30154
+ headers: { ...acc.headers, ...slice.headers }
30155
+ } : acc,
30156
+ {
30157
+ baseURL: DEFAULT_BACKEND_API_ENDPOINT,
30158
+ timeout: DEFAULT_BACKEND_API_TIMEOUT,
30159
+ headers: { ...DEFAULT_BACKEND_API_HEADERS }
30160
+ }
30161
+ );
30162
+ }
30163
+ function resolveBaseApiConfig(config) {
30164
+ if (isCustomApiConfig(config)) {
30165
+ return layerConfigs(config.baseApiConfig);
30166
+ }
30167
+ return layerConfigs(config);
30168
+ }
30169
+ function resolveSwapsApiConfig(config) {
30170
+ if (isCustomApiConfig(config)) {
30171
+ return layerConfigs(config.baseApiConfig, config.swapsApiConfig);
30172
+ }
30173
+ return layerConfigs(config);
30174
+ }
30175
+ var ChainKeySchema = v4.custom((input) => typeof input === "string");
30176
+ var SpokeChainKeySchema = v4.custom((input) => typeof input === "string");
30177
+ var AddressSchema2 = v4.custom((input) => typeof input === "string");
30178
+ var XTokenSchema = v4.object({
30179
+ symbol: v4.string(),
30180
+ name: v4.string(),
30181
+ decimals: v4.number(),
30182
+ address: v4.string(),
30183
+ chainKey: ChainKeySchema,
30184
+ hubAsset: AddressSchema2,
30185
+ vault: AddressSchema2,
30186
+ access: v4.optional(v4.picklist(["withdrawOnly", "depositOnly"]))
30187
+ });
30188
+ var IntentStructSchema = v4.object({
30189
+ intentId: v4.string(),
30190
+ creator: v4.string(),
30191
+ inputToken: v4.string(),
30192
+ outputToken: v4.string(),
30193
+ inputAmount: v4.string(),
30194
+ minOutputAmount: v4.string(),
30195
+ deadline: v4.string(),
30196
+ allowPartialFill: v4.boolean(),
30197
+ srcChain: v4.number(),
30198
+ dstChain: v4.number(),
30199
+ srcAddress: v4.string(),
30200
+ dstAddress: v4.string(),
30201
+ solver: v4.string(),
30202
+ data: v4.string()
30203
+ });
30204
+ var IntentResponseSchema2 = v4.object({
30205
+ intentHash: v4.string(),
30206
+ txHash: v4.string(),
30207
+ logIndex: v4.number(),
30208
+ chainId: v4.number(),
30209
+ blockNumber: v4.number(),
30210
+ open: v4.boolean(),
30211
+ intent: IntentStructSchema,
30212
+ events: v4.array(v4.unknown())
30213
+ });
30214
+ var UserIntentsResponseSchema = v4.object({
30215
+ total: v4.number(),
30216
+ offset: v4.number(),
30217
+ limit: v4.number(),
30218
+ items: v4.array(IntentResponseSchema2)
30219
+ });
30220
+ var OrderbookResponseSchema = v4.object({
30221
+ total: v4.number(),
30222
+ data: v4.array(
30223
+ v4.object({
30224
+ intentState: v4.object({
30225
+ exists: v4.boolean(),
30226
+ remainingInput: v4.string(),
30227
+ receivedOutput: v4.string(),
30228
+ pendingPayment: v4.boolean()
30229
+ }),
30230
+ intentData: v4.object({
30231
+ intentId: v4.string(),
30232
+ creator: v4.string(),
30233
+ inputToken: v4.string(),
30234
+ outputToken: v4.string(),
30235
+ inputAmount: v4.string(),
30236
+ minOutputAmount: v4.string(),
30237
+ deadline: v4.string(),
30238
+ allowPartialFill: v4.boolean(),
30239
+ srcChain: v4.number(),
30240
+ dstChain: v4.number(),
30241
+ srcAddress: v4.string(),
30242
+ dstAddress: v4.string(),
30243
+ solver: v4.string(),
30244
+ data: v4.string(),
30245
+ intentHash: v4.string(),
30246
+ txHash: v4.string(),
30247
+ blockNumber: v4.number()
30248
+ })
30249
+ })
30250
+ )
30251
+ });
30252
+ var MoneyMarketPositionSchema = v4.object({
30253
+ userAddress: v4.string(),
30254
+ positions: v4.array(
30255
+ v4.object({
30256
+ reserveAddress: v4.string(),
30257
+ aTokenAddress: v4.string(),
30258
+ variableDebtTokenAddress: v4.string(),
30259
+ aTokenBalance: v4.string(),
30260
+ variableDebtTokenBalance: v4.string(),
30261
+ blockNumber: v4.number()
30262
+ })
30263
+ )
30264
+ });
30265
+ var MoneyMarketAssetSchema = v4.object({
30266
+ reserveAddress: v4.string(),
30267
+ aTokenAddress: v4.string(),
30268
+ totalATokenBalance: v4.string(),
30269
+ variableDebtTokenAddress: v4.string(),
30270
+ totalVariableDebtTokenBalance: v4.string(),
30271
+ liquidityRate: v4.string(),
30272
+ symbol: v4.string(),
30273
+ totalSuppliers: v4.number(),
30274
+ totalBorrowers: v4.number(),
30275
+ variableBorrowRate: v4.string(),
30276
+ stableBorrowRate: v4.string(),
30277
+ liquidityIndex: v4.string(),
30278
+ variableBorrowIndex: v4.string(),
30279
+ blockNumber: v4.number()
30280
+ });
30281
+ var MoneyMarketAssetsSchema = v4.array(MoneyMarketAssetSchema);
30282
+ var MoneyMarketAssetBorrowersSchema = v4.object({
30283
+ borrowers: v4.array(v4.string()),
30284
+ total: v4.number(),
30285
+ offset: v4.number(),
30286
+ limit: v4.number()
30287
+ });
30288
+ var MoneyMarketAssetSuppliersSchema = v4.object({
30289
+ suppliers: v4.array(v4.string()),
30290
+ total: v4.number(),
30291
+ offset: v4.number(),
30292
+ limit: v4.number()
30293
+ });
30294
+ var MoneyMarketBorrowersSchema = v4.object({
30295
+ borrowers: v4.array(v4.string()),
30296
+ total: v4.number(),
30297
+ offset: v4.number(),
30298
+ limit: v4.number()
30299
+ });
30300
+ var GetChainsResponseSchema = v4.array(SpokeChainKeySchema);
30301
+ var TokensByChainMapSchema = v4.custom(
30302
+ (input) => typeof input === "object" && input !== null && Object.values(input).every((tokens) => Array.isArray(tokens) && tokens.every((t) => v4.is(XTokenSchema, t)))
30303
+ );
30304
+ var TokensListSchema = v4.array(XTokenSchema);
30305
+ var ReserveAssetsSchema = v4.array(AddressSchema2);
30306
+
30307
+ // src/backendApi/BackendApiService.ts
30308
+ var BackendApiService = class {
30309
+ // sub-services exposing domain-specific APIs
30310
+ swaps;
30311
+ // resolved base-API slice of the ApiConfig union (flat config, or its `baseApiConfig`)
30312
+ config;
30313
+ headers;
30314
+ logger;
30315
+ constructor(config, logger = consoleLogger) {
30316
+ this.config = resolveBaseApiConfig(config);
30317
+ this.headers = { ...this.config.headers };
30318
+ this.logger = logger;
30319
+ this.swaps = new SwapsApiService(resolveSwapsApiConfig(config), this.logger);
30320
+ }
29476
30321
  /**
29477
30322
  * Wraps {@link makeRequest} in a `Result<T>` so all errors are captured rather
29478
30323
  * than propagated as thrown exceptions. Every public endpoint method delegates
29479
30324
  * here instead of calling `makeRequest` directly.
29480
30325
  */
29481
- async request(endpoint, config) {
30326
+ /**
30327
+ * Fold any per-call override (carried on `config` alongside `method`/`body`) over the service
30328
+ * defaults: baseURL truthy-fallback (an empty-string override defers to the default), timeout
30329
+ * nullish-fallback, headers merged (override wins per key). Mirrors the original makeRequest merge.
30330
+ */
30331
+ resolveRequestConfig(config) {
30332
+ const { baseURL, timeout, headers, ...rest } = config;
30333
+ return {
30334
+ ...rest,
30335
+ baseURL: baseURL || this.config.baseURL,
30336
+ timeout: timeout ?? this.config.timeout,
30337
+ headers: { ...this.headers, ...headers }
30338
+ };
30339
+ }
30340
+ /**
30341
+ * Wrap a thrown transport failure (HTTP_REQUEST_FAILED / REQUEST_TIMEOUT / network error) as the
30342
+ * canonical backend `SodaxError` — identical shape to SwapsApiService; the underlying failure is
30343
+ * preserved on `error.cause`.
30344
+ */
30345
+ toExternalApiError(endpoint, error) {
30346
+ return new SodaxError(
30347
+ "EXTERNAL_API_ERROR",
30348
+ error instanceof Error ? error.message : `Backend API request to ${endpoint} failed`,
30349
+ { feature: "backend", cause: error, context: { api: "backend", endpoint } }
30350
+ );
30351
+ }
30352
+ /**
30353
+ * Issue a request and validate the JSON body against `schema`, wrapping the result in `Result<T>`.
30354
+ * Mirrors {@link SwapsApiService}: a 2xx body that fails the schema is surfaced as
30355
+ * `EXTERNAL_API_ERROR` (`context.reason: 'invalid_response_shape'`) rather than returned untyped.
30356
+ * Every data/token/money-market method delegates here; the config/relay reads use
30357
+ * {@link requestUnvalidated} instead.
30358
+ */
30359
+ async request(endpoint, config, schema) {
30360
+ try {
30361
+ const raw = await makeRequest({
30362
+ endpoint,
30363
+ config: this.resolveRequestConfig(config),
30364
+ logger: this.logger,
30365
+ serviceLabel: "BackendApiService"
30366
+ });
30367
+ const parsed = v4.safeParse(schema, raw);
30368
+ if (!parsed.success) {
30369
+ return {
30370
+ ok: false,
30371
+ error: new SodaxError("EXTERNAL_API_ERROR", `Invalid response shape from backend API for ${endpoint}`, {
30372
+ feature: "backend",
30373
+ context: { api: "backend", endpoint, reason: "invalid_response_shape", issues: v4.flatten(parsed.issues) }
30374
+ })
30375
+ };
30376
+ }
30377
+ return { ok: true, value: parsed.output };
30378
+ } catch (error) {
30379
+ return { ok: false, error: this.toExternalApiError(endpoint, error) };
30380
+ }
30381
+ }
30382
+ /**
30383
+ * Issue a request WITHOUT response-shape validation (passthrough typing). Reserved for the
30384
+ * config/relay reads whose shapes are too large/brittle to schema-validate (`SodaxConfig` via
30385
+ * `getAllConfig`, `SpokeChainConfigMap` via `getSpokeChainConfig`) or carry `bigint` values that
30386
+ * cannot survive JSON validation (`getRelayChainIdMap`). `ConfigService` version-gates and falls
30387
+ * back to packaged defaults, so it relies on no response-shape guarantee from these endpoints.
30388
+ */
30389
+ async requestUnvalidated(endpoint, config) {
29482
30390
  try {
29483
- const value = await this.makeRequest(endpoint, config);
30391
+ const value = await makeRequest({
30392
+ endpoint,
30393
+ config: this.resolveRequestConfig(config),
30394
+ logger: this.logger,
30395
+ serviceLabel: "BackendApiService"
30396
+ });
29484
30397
  return { ok: true, value };
29485
30398
  } catch (error) {
29486
- return { ok: false, error };
30399
+ return { ok: false, error: this.toExternalApiError(endpoint, error) };
29487
30400
  }
29488
30401
  }
29489
30402
  // Intent endpoints
@@ -29498,7 +30411,7 @@ var BackendApiService = class {
29498
30411
  * open/closed state, token amounts, and any fill events.
29499
30412
  */
29500
30413
  async getIntentByTxHash(txHash, config) {
29501
- return this.request(`/intent/tx/${txHash}`, { ...config, method: "GET" });
30414
+ return this.request(`/intent/tx/${txHash}`, { ...config, method: "GET" }, IntentResponseSchema2);
29502
30415
  }
29503
30416
  /**
29504
30417
  * Fetch a swap intent by its canonical intent hash.
@@ -29507,58 +30420,7 @@ var BackendApiService = class {
29507
30420
  * @returns `Result<IntentResponse>` — on success, the full intent details.
29508
30421
  */
29509
30422
  async getIntentByHash(intentHash, config) {
29510
- return this.request(`/intent/${intentHash}`, { ...config, method: "GET" });
29511
- }
29512
- // Swap submit-tx endpoints
29513
- /**
29514
- * Submit a signed spoke-chain swap transaction to the backend for processing.
29515
- *
29516
- * The backend relays the transaction to the hub chain, posts execution data
29517
- * to the solver, and advances the intent through its lifecycle. The response
29518
- * shape is validated at runtime via a type guard; an invalid shape is
29519
- * returned as `{ ok: false }`.
29520
- *
29521
- * @param params - The signed transaction hash, source chain key, sender wallet
29522
- * address, intent data, and relay data required to process the swap.
29523
- * @returns `Result<SubmitSwapTxResponse>` — on success, a confirmation object
29524
- * with `success: true` and a human-readable `message`.
29525
- */
29526
- async submitSwapTx(params, config) {
29527
- const result = await this.request("/swaps/submit-tx", {
29528
- ...config,
29529
- method: "POST",
29530
- body: JSON.stringify(params)
29531
- });
29532
- if (!result.ok) return result;
29533
- if (!isSubmitSwapTxResponse(result.value)) {
29534
- return { ok: false, error: new Error("Invalid submitSwapTx response: unexpected response shape") };
29535
- }
29536
- return { ok: true, value: result.value };
29537
- }
29538
- /**
29539
- * Poll the backend relay pipeline for the current status of a previously
29540
- * submitted swap transaction.
29541
- *
29542
- * Status progresses through: `pending` → `verifying` → `verified` →
29543
- * `relaying` → `relayed` → `posting_execution` → `executed` (or `failed`).
29544
- *
29545
- * @param params - Object containing the source-chain transaction hash and,
29546
- * optionally, the source chain key to disambiguate cross-chain hashes.
29547
- * @returns `Result<SubmitSwapTxStatusResponse>` — on success, includes the
29548
- * current `status`, any `failureReason`, and (once executed) the
29549
- * `dstIntentTxHash` on the hub chain.
29550
- */
29551
- async getSubmitSwapTxStatus(params, config) {
29552
- const queryParams = new URLSearchParams();
29553
- queryParams.append("txHash", params.txHash);
29554
- if (params.srcChainKey) queryParams.append("srcChainKey", params.srcChainKey);
29555
- const endpoint = `/swaps/submit-tx/status?${queryParams.toString()}`;
29556
- const result = await this.request(endpoint, { ...config, method: "GET" });
29557
- if (!result.ok) return result;
29558
- if (!isSubmitSwapTxStatusResponse(result.value)) {
29559
- return { ok: false, error: new Error("Invalid submitSwapTxStatus response: unexpected response shape") };
29560
- }
29561
- return { ok: true, value: result.value };
30423
+ return this.request(`/intent/${intentHash}`, { ...config, method: "GET" }, IntentResponseSchema2);
29562
30424
  }
29563
30425
  // Solver endpoints
29564
30426
  /**
@@ -29575,7 +30437,7 @@ var BackendApiService = class {
29575
30437
  queryParams.append("limit", params.limit);
29576
30438
  const queryString = queryParams.toString();
29577
30439
  const endpoint = `/solver/orderbook?${queryString}`;
29578
- return this.request(endpoint, { ...config, method: "GET" });
30440
+ return this.request(endpoint, { ...config, method: "GET" }, OrderbookResponseSchema);
29579
30441
  }
29580
30442
  /**
29581
30443
  * Fetch all swap intents created by a specific wallet address, with optional
@@ -29601,7 +30463,7 @@ var BackendApiService = class {
29601
30463
  if (offset) queryParams.append("offset", offset);
29602
30464
  const queryString = queryParams.toString();
29603
30465
  const endpoint = queryString.length > 0 ? `/intent/user/${userAddress}?${queryString}` : `/intent/user/${userAddress}`;
29604
- return this.request(endpoint, { ...config, method: "GET" });
30466
+ return this.request(endpoint, { ...config, method: "GET" }, UserIntentsResponseSchema);
29605
30467
  }
29606
30468
  // Money Market endpoints
29607
30469
  /**
@@ -29616,7 +30478,11 @@ var BackendApiService = class {
29616
30478
  * position across all active reserves.
29617
30479
  */
29618
30480
  async getMoneyMarketPosition(userAddress, config) {
29619
- return this.request(`/moneymarket/position/${userAddress}`, { ...config, method: "GET" });
30481
+ return this.request(
30482
+ `/moneymarket/position/${userAddress}`,
30483
+ { ...config, method: "GET" },
30484
+ MoneyMarketPositionSchema
30485
+ );
29620
30486
  }
29621
30487
  /**
29622
30488
  * Fetch the on-chain state for every active money market reserve asset.
@@ -29625,7 +30491,7 @@ var BackendApiService = class {
29625
30491
  * snapshots including interest rates, liquidity indices, and participant counts.
29626
30492
  */
29627
30493
  async getAllMoneyMarketAssets(config) {
29628
- return this.request("/moneymarket/asset/all", { ...config, method: "GET" });
30494
+ return this.request("/moneymarket/asset/all", { ...config, method: "GET" }, MoneyMarketAssetsSchema);
29629
30495
  }
29630
30496
  /**
29631
30497
  * Fetch the on-chain state for a single money market reserve asset.
@@ -29635,7 +30501,11 @@ var BackendApiService = class {
29635
30501
  * including interest rates, total balances, and liquidity indices.
29636
30502
  */
29637
30503
  async getMoneyMarketAsset(reserveAddress, config) {
29638
- return this.request(`/moneymarket/asset/${reserveAddress}`, { ...config, method: "GET" });
30504
+ return this.request(
30505
+ `/moneymarket/asset/${reserveAddress}`,
30506
+ { ...config, method: "GET" },
30507
+ MoneyMarketAssetSchema
30508
+ );
29639
30509
  }
29640
30510
  /**
29641
30511
  * Fetch a paginated list of wallets that currently have an outstanding borrow
@@ -29652,7 +30522,7 @@ var BackendApiService = class {
29652
30522
  queryParams.append("limit", params.limit);
29653
30523
  const queryString = queryParams.toString();
29654
30524
  const endpoint = `/moneymarket/asset/${reserveAddress}/borrowers?${queryString}`;
29655
- return this.request(endpoint, { ...config, method: "GET" });
30525
+ return this.request(endpoint, { ...config, method: "GET" }, MoneyMarketAssetBorrowersSchema);
29656
30526
  }
29657
30527
  /**
29658
30528
  * Fetch a paginated list of wallets that currently have an active supply
@@ -29669,7 +30539,7 @@ var BackendApiService = class {
29669
30539
  queryParams.append("limit", params.limit);
29670
30540
  const queryString = queryParams.toString();
29671
30541
  const endpoint = `/moneymarket/asset/${reserveAddress}/suppliers?${queryString}`;
29672
- return this.request(endpoint, { ...config, method: "GET" });
30542
+ return this.request(endpoint, { ...config, method: "GET" }, MoneyMarketAssetSuppliersSchema);
29673
30543
  }
29674
30544
  /**
29675
30545
  * Fetch a paginated list of all wallet addresses that hold an active borrow
@@ -29685,7 +30555,7 @@ var BackendApiService = class {
29685
30555
  queryParams.append("limit", params.limit);
29686
30556
  const queryString = queryParams.toString();
29687
30557
  const endpoint = `/moneymarket/borrowers?${queryString}`;
29688
- return this.request(endpoint, { ...config, method: "GET" });
30558
+ return this.request(endpoint, { ...config, method: "GET" }, MoneyMarketBorrowersSchema);
29689
30559
  }
29690
30560
  /**
29691
30561
  * Fetch the complete SODAX runtime configuration in a single request.
@@ -29698,7 +30568,7 @@ var BackendApiService = class {
29698
30568
  * `config` is the current `SodaxConfig` used by all SDK services.
29699
30569
  */
29700
30570
  async getAllConfig(config) {
29701
- return this.request("/config/all", { ...config, method: "GET" });
30571
+ return this.requestUnvalidated("/config/all", { ...config, method: "GET" });
29702
30572
  }
29703
30573
  /**
29704
30574
  * Fetch the list of spoke chain keys that are currently supported by the
@@ -29711,7 +30581,7 @@ var BackendApiService = class {
29711
30581
  * `SpokeChainKey` strings (e.g. `["ethereum", "arbitrum", "solana", …]`).
29712
30582
  */
29713
30583
  async getChains(config) {
29714
- return this.request("/config/spoke/chains", { ...config, method: "GET" });
30584
+ return this.request("/config/spoke/chains", { ...config, method: "GET" }, GetChainsResponseSchema);
29715
30585
  }
29716
30586
  /**
29717
30587
  * Fetch the full map of tokens available for swapping, keyed by spoke chain.
@@ -29723,7 +30593,7 @@ var BackendApiService = class {
29723
30593
  * supported spoke chain key to its list of swappable `XToken` definitions.
29724
30594
  */
29725
30595
  async getSwapTokens(config) {
29726
- return this.request("/config/swap/tokens", { ...config, method: "GET" });
30596
+ return this.request("/config/swap/tokens", { ...config, method: "GET" }, TokensByChainMapSchema);
29727
30597
  }
29728
30598
  /**
29729
30599
  * Fetch the list of tokens available for swapping on a specific spoke chain.
@@ -29735,10 +30605,7 @@ var BackendApiService = class {
29735
30605
  * array of `XToken` definitions supported for swapping on that chain.
29736
30606
  */
29737
30607
  async getSwapTokensByChainId(chainId, config) {
29738
- return this.request(`/config/swap/${chainId}/tokens`, {
29739
- ...config,
29740
- method: "GET"
29741
- });
30608
+ return this.request(`/config/swap/${chainId}/tokens`, { ...config, method: "GET" }, TokensListSchema);
29742
30609
  }
29743
30610
  /**
29744
30611
  * Fetch the full map of tokens available in the money market (lending/borrowing),
@@ -29750,10 +30617,7 @@ var BackendApiService = class {
29750
30617
  * each supported spoke chain key to its list of money-market `XToken` definitions.
29751
30618
  */
29752
30619
  async getMoneyMarketTokens(config) {
29753
- return this.request("/config/money-market/tokens", {
29754
- ...config,
29755
- method: "GET"
29756
- });
30620
+ return this.request("/config/money-market/tokens", { ...config, method: "GET" }, TokensByChainMapSchema);
29757
30621
  }
29758
30622
  /**
29759
30623
  * Fetch the list of hub-chain reserve asset addresses registered in the
@@ -29767,10 +30631,11 @@ var BackendApiService = class {
29767
30631
  * readonly array of reserve `Address` strings.
29768
30632
  */
29769
30633
  async getMoneyMarketReserveAssets(config) {
29770
- return this.request("/config/money-market/reserve-assets", {
29771
- ...config,
29772
- method: "GET"
29773
- });
30634
+ return this.request(
30635
+ "/config/money-market/reserve-assets",
30636
+ { ...config, method: "GET" },
30637
+ ReserveAssetsSchema
30638
+ );
29774
30639
  }
29775
30640
  /**
29776
30641
  * Fetch the list of tokens available for lending/borrowing on a specific
@@ -29783,10 +30648,11 @@ var BackendApiService = class {
29783
30648
  * readonly array of `XToken` definitions supported in the money market on that chain.
29784
30649
  */
29785
30650
  async getMoneyMarketTokensByChainId(chainId, config) {
29786
- return this.request(`/config/money-market/${chainId}/tokens`, {
29787
- ...config,
29788
- method: "GET"
29789
- });
30651
+ return this.request(
30652
+ `/config/money-market/${chainId}/tokens`,
30653
+ { ...config, method: "GET" },
30654
+ TokensListSchema
30655
+ );
29790
30656
  }
29791
30657
  /**
29792
30658
  * Fetch the mapping from spoke chain keys to the numeric chain IDs used by
@@ -29800,7 +30666,7 @@ var BackendApiService = class {
29800
30666
  * `IntentRelayChainIdMap` record mapping each spoke chain key to its relay chain ID.
29801
30667
  */
29802
30668
  async getRelayChainIdMap(config) {
29803
- return this.request("/config/relay/chain-id-map", {
30669
+ return this.requestUnvalidated("/config/relay/chain-id-map", {
29804
30670
  ...config,
29805
30671
  method: "GET"
29806
30672
  });
@@ -29817,7 +30683,7 @@ var BackendApiService = class {
29817
30683
  * `SpokeChainConfigMap` for all currently enabled spoke chains.
29818
30684
  */
29819
30685
  async getSpokeChainConfig(config) {
29820
- return this.request("/config/spoke/all-chains-configs", {
30686
+ return this.requestUnvalidated("/config/spoke/all-chains-configs", {
29821
30687
  ...config,
29822
30688
  method: "GET"
29823
30689
  });
@@ -29829,12 +30695,17 @@ var BackendApiService = class {
29829
30695
  * without constructing a new service instance. Existing header keys are
29830
30696
  * overwritten; keys absent from `headers` are preserved.
29831
30697
  *
30698
+ * The headers are also fanned out to the sub-services (`swaps`), which hold
30699
+ * their own header copies — so a token set here applies to every request made
30700
+ * through this client, including `swaps.*`.
30701
+ *
29832
30702
  * @param headers - Key-value pairs to add or overwrite in the default headers.
29833
30703
  */
29834
30704
  setHeaders(headers) {
29835
30705
  Object.entries(headers).forEach(([key, value]) => {
29836
30706
  this.headers[key] = value;
29837
30707
  });
30708
+ this.swaps.setHeaders(headers);
29838
30709
  }
29839
30710
  /**
29840
30711
  * Return the base URL the service is currently pointing at.
@@ -38554,7 +39425,7 @@ var LeverageYieldService = class {
38554
39425
  }
38555
39426
  /** Looks up a vault by its `name` field. Returns `undefined` when not registered. */
38556
39427
  getVault(name) {
38557
- return this.listVaults().find((v) => v.name === name);
39428
+ return this.listVaults().find((v6) => v6.name === name);
38558
39429
  }
38559
39430
  /**
38560
39431
  * Looks up a registered vault by its on-chain proxy address (case-insensitive).
@@ -38562,7 +39433,7 @@ var LeverageYieldService = class {
38562
39433
  */
38563
39434
  getVaultByAddress(address) {
38564
39435
  const normalized = address.toLowerCase();
38565
- return this.listVaults().find((v) => v.vault.toLowerCase() === normalized);
39436
+ return this.listVaults().find((v6) => v6.vault.toLowerCase() === normalized);
38566
39437
  }
38567
39438
  /**
38568
39439
  * Resolves the intent `deadline`: returns the caller-supplied value verbatim, otherwise
@@ -39355,6 +40226,8 @@ var Sodax = class {
39355
40226
  // ICX migration service enabling ICX migration to SODA
39356
40227
  backendApi;
39357
40228
  // backend API service enabling backend API endpoints
40229
+ api;
40230
+ // syntactic sugar for backend API service
39358
40231
  bridge;
39359
40232
  // Bridge service enabling cross-chain transfers
39360
40233
  staking;
@@ -39377,8 +40250,10 @@ var Sodax = class {
39377
40250
  const logger = resolveLogger(options?.logger);
39378
40251
  const analytics = resolveAnalytics(options?.analytics);
39379
40252
  const fee = options?.fee;
40253
+ const useBackendSubmitTx = options?.swapsOptions?.useBackendSubmitTx ?? false;
39380
40254
  this.instanceConfig = options ? mergeSodaxConfig(sodaxConfig, options) : sodaxConfig;
39381
40255
  this.backendApi = new BackendApiService(this.instanceConfig.api, logger);
40256
+ this.api = this.backendApi;
39382
40257
  this.config = new ConfigService({
39383
40258
  api: this.backendApi,
39384
40259
  config: this.instanceConfig,
@@ -39392,7 +40267,9 @@ var Sodax = class {
39392
40267
  this.swaps = new SwapService({
39393
40268
  config: this.config,
39394
40269
  hubProvider: this.hubProvider,
39395
- spoke: this.spoke
40270
+ spoke: this.spoke,
40271
+ backendApi: this.backendApi,
40272
+ useBackendSubmitTx
39396
40273
  });
39397
40274
  this.moneyMarket = new MoneyMarketService({
39398
40275
  config: this.config,
@@ -39466,4 +40343,4 @@ var isPartnerError = isCodeMember(PARTNER_CODES);
39466
40343
  (*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
39467
40344
  */
39468
40345
 
39469
- export { ALLOWANCE_CHECK_CODES, APPROVE_CODES, AssetService, BITCOIN_CHAIN_KEYS, BITCOIN_CHAIN_KEYS_SET, BTC_WALLET_ADDRESS_TYPES, BackendApiService, BalnSwapService, BigIntToHex, BigNumberZeroDecimal, BitcoinSpokeService, BnUSDMigrationService, BridgeService, CHAIN_KEYS, CHAIN_LOGO_BASE_URL, CONFIG_VERSION, CREATE_INTENT_CODES, ChainKeys, ChainTypeArr, ClService, ConfigService, CustomSorobanServer, CustomStellarAccount, DEFAULT_BACKEND_API_ENDPOINT, DEFAULT_BACKEND_API_HEADERS, DEFAULT_BACKEND_API_TIMEOUT, DEFAULT_DEADLINE_OFFSET, DEFAULT_MAX_RETRY, DEFAULT_RELAYER_API_ENDPOINT, DEFAULT_RELAY_TX_TIMEOUT, DEFAULT_RETRY_DELAY_MS, DexService, EVM_CHAIN_ID_TO_KEY, EVM_CHAIN_KEYS, EVM_CHAIN_KEYS_SET, EVM_SPOKE_ONLY_CHAIN_KEYS, EVM_SPOKE_ONLY_CHAIN_KEYS_SET, Erc20Service, Erc4626Service, EvmAssetManagerService, EvmHubProvider, EvmSolverService, EvmSpokeService, EvmVaultTokenService, FEE_PERCENTAGE_SCALE, GAS_ESTIMATION_CODES, HALF_RAY, HALF_WAD, HUB_CHAIN_KEY, HookKind, HookService, HttpRelayError, HubVaultSymbols, ICON_CHAIN_KEYS, ICON_CHAIN_KEYS_SET, ICON_TX_RESULT_WAIT_MAX_RETRY, INJECTIVE_CHAIN_KEYS, INJECTIVE_CHAIN_KEYS_SET, INTENT_CHAIN_IDS, IconSpokeService, IcxMigrationService, Injective20Token, InjectiveSpokeService, IntentCreatedEventAbi, IntentDataService, IntentDataType, IntentFilledEventAbi, IntentRelayChainIdToChainKey, IntentsAbi, LOOKUP_CODES, LTV_PRECISION, LendingPoolService, LeverageYieldService, LockupMultiplier, LockupPeriod, LsodaSymbols, LsodaTokens, MAX_UINT256, MigrationService, MintPositionEventAbi, MoneyMarketDataService, MoneyMarketService, NEAR_CHAIN_KEYS, NEAR_CHAIN_KEYS_SET, NEAR_DEFAULT_GAS, NEAR_STORAGE_DEPOSIT, NearSpokeService, PartnerFeeClaimService, PartnerService, Permit2Service, ProtocolIntentsAbi, RAY, RAY_DECIMALS, RELAY_ERROR_CODES, RadfiApiError, RadfiProvider, RecoveryService, RelayChainIdMap, SECONDS_PER_YEAR, SODAX_ERROR_CODES, SODAX_FEATURES, SOLANA_CHAIN_KEYS, SOLANA_CHAIN_KEYS_SET, SONIC_CHAIN_KEYS, SONIC_CHAIN_KEYS_SET, STACKS_CHAIN_KEYS, STACKS_CHAIN_KEYS_SET, STELLAR_CHAIN_KEYS, STELLAR_CHAIN_KEYS_SET, SUI_CHAIN_KEYS, SUI_CHAIN_KEYS_SET, SodaTokens, Sodax, SodaxError, SolanaSpokeService, SolverApiService, SolverIntentErrorCode, SolverIntentStatusCode, SonicSpokeService, SpokeService, StacksSpokeService, StakingLogic, StakingService, StatATokenAddresses, StellarSpokeService, SuiSpokeService, SupportedMigrationTokens, SwapService, USD_DECIMALS, UiPoolDataProviderService, VAULT_TOKEN_DECIMALS, WAD, WAD_RAY_RATIO, WEI_DECIMALS, adjustAmountByFee, allowanceCheckFailed, apiConfig, approveFailed, arbitrumSupportedTokens, assetManagerAbi, avalancheSupportedTokens, balnSwapAbi, baseChainInfo, baseSupportedTokens, binomialApproximatedRayPow, bitcoinSupportedTokens, bnUSDLegacySpokeChainIds, bnUSDLegacyTokens, bridgeConfig, bridgeInvariant, bscSupportedTokens, calcOpReturnOutputVbytes, calculateAllReserveIncentives, calculateAllUserIncentives, calculateAvailableBorrowsMarketReferenceCurrency, calculateCompoundedInterest, calculateCompoundedRate, calculateFeeAmount, calculateHealthFactorFromBalances, calculateHealthFactorFromBalancesBigUnits, calculateLinearInterest, calculatePercentageFeeAmount, clPoolAbi, clPoolManagerAbi, clPositionManagerAbi, clQuoterAbi, clRouterAbi, clTickLensAbi, concentratedLiquidityConfig, connectionAbi, consoleLogger, convertTransactionInstructionToRaw, createInvariant, deepMerge, defaultHookAbi, detectBitcoinAddressType, dexConfig, dexInvariant, dexPools, encodeAddress, encodeBtcPayloadToBytes, encodeContractCalls, erc20Abi, erc4626Abi, estimateBitcoinTxSize, ethereumSupportedTokens, executionFailed, formatBasisPoints, formatEModeCategory, formatEModes, formatPercentage, formatReserve, formatReserveUSD, formatReserves, formatReservesAndIncentives, formatUserSummary, formatUserSummaryAndIncentives, gasEstimationFailed, getAllLegacybnUSDTokens, getAndFormatReserveEModes, getAssetManagerIdl, getAssetManagerProgram, getChainKeyFromRelayChainId, getChainType, getCompoundedBalance, getConcentratedLiquidityConfig, getConnectionIdl, getConnectionProgram, getEvmChainKeyByChainId, getEvmViemChain, getIconAddressBytes, getIntentRelayChainId, getLinearBalance, getMarketReferenceCurrencyAndUsdBalance, getPacket, getProvider, getRandomBytes, getReserveNormalizedIncome, getReservesEModes, getSolanaAddressBytes, getSolverConfig, getSpokeHook, getSpokeHooks, getStagingSolverTokens, getSupportedSolverTokens, getTransactionPackets, getbnUSDToken, hexToBigInt, hexToSolanaAddress, hubConfig, hyper, hyperevmSupportedTokens, iconSupportedTokens, injectiveSupportedTokens, intentCreationFailed, isBalnMigrateParams, isBitcoinChainKey, isBitcoinChainKeyType, isBitcoinWalletProviderType, isBridgeAllowanceCheckError, isBridgeApproveError, isBridgeCreateIntentError, isBridgeError, isBridgeLookupError, isBridgeOrchestrationError, isCodeMember, isDexError, isEvmChainKey, isEvmChainKeyType, isEvmSpokeChainConfig, isEvmSpokeOnlyChainKey, isEvmSpokeOnlyChainKeyType, isEvmWalletProviderType, isFeatureError, isHookSupportedToken, isHubChainKey, isHubChainKeyType, isIconAddress, isIconChainKey, isIconChainKeyType, isIcxCreateRevertMigrationParams, isIcxMigrateParams, isInjectiveChainKey, isInjectiveChainKeyType, isJsonRpcPayloadResponse, isLegacybnUSDChainId, isLegacybnUSDToken, isLeverageYieldAllowanceCheckError, isLeverageYieldApproveError, isLeverageYieldCreateIntentError, isLeverageYieldError, isLeverageYieldLookupError, isLeverageYieldPostExecutionError, isLeverageYieldSwapError, isMigrateOrchestrationError, isMigrationAllowanceCheckError, isMigrationApproveError, isMigrationCreateIntentError, isMigrationError, isMigrationLookupError, isMoneyMarketAllowanceCheckError, isMoneyMarketApproveError, isMoneyMarketCreateIntentError, isMoneyMarketError, isMoneyMarketGasEstimationError, isMoneyMarketOrchestrationError, isNativeToken, isNearChainKey, isNearChainKeyType, isNewbnUSDChainId, isNewbnUSDToken, isOptionalBitcoinWalletProviderType, isOptionalEvmWalletProviderType, isOptionalStellarWalletProviderType, isPartnerError, isPartnerFeeAmount, isPartnerFeePercentage, isPostExecutionError, isRawDestinationParams, isRecoveryError, isResponseAddressType, isResponseSigningType, isRevertMigrationOrchestrationError, isSodaxError, isSolanaChainKey, isSolanaChainKeyType, isSolanaNativeToken, isSonicChainKey, isSonicChainKeyType, isSpokeApproveParamsEvmSpoke, isSpokeApproveParamsHub, isSpokeApproveParamsStellar, isSpokeChainKey, isSpokeIsAllowanceValidParamsEvmSpoke, isSpokeIsAllowanceValidParamsHub, isSpokeIsAllowanceValidParamsStellar, isStacksChainKey, isStacksChainKeyType, isStakeOrchestrationError, isStakingAllowanceCheckError, isStakingApproveError, isStakingCreateIntentError, isStakingError, isStakingInfoFetchError, isStakingOrchestrationError, isStellarChainKey, isStellarChainKeyType, isStellarWalletProviderType, isSubmitSwapTxResponse, isSubmitSwapTxStatusResponse, isSuiChainKey, isSuiChainKeyType, isSupportedBitcoinAddressType, isSwapCreateIntentError, isSwapError, isSwapSupportedToken, isUndefinedOrValidWalletProviderForChainKey, isUnifiedBnUSDMigrateParams, isValidWalletProviderForChainKey, kaiaSupportedTokens, leverageYieldConfig, leverageYieldInvariant, leverageYieldVaults, lightlinkSupportedTokens, lookupFailed, mapRelayFailure, mergeSodaxConfig, messageOf, migrationInvariant, mintPositionParamsAbi, mmInvariant, modifyLiquidityParamsAbi, moneyMarketConfig, moneyMarketReserveAssets, moneyMarketSupportedTokens, nativeToUSD, nearSupportedTokens, newbnUSDSpokeChainIds, noopAnalytics, normalize, normalizeBN, normalizePsbtToBase64, normalizeSignatureToBase64, normalizedToUsd, optimismSupportedTokens, pancakeSwapInfinityDefaultHookAbi, pancakeSwapInfinityPoolManagerAbi, pancakeSwapInfinityPositionManagerAbi, parseToStroops, parseTokenArrayFromJson, partnerInvariant, permit2Abi, polygonSupportedTokens, poolAbi, poolKeyAbi, randomUint256, rayDiv, rayMul, rayPow, rayToWad, recoveryInvariant, redbellySupportedTokens, relayConfig, relayTxAndWaitPacket, requestAddress, requestJsonRpc, requestSigning, resolveAnalytics, resolveLogger, retry, reverseEncodeAddress, serializeAddressData, silentLogger, sleep, sodaxConfig, sodaxInvariant, solanaSupportedTokens, solverConfig, sonicSupportedTokens, sonicWalletFactoryAbi, spokeAssetManagerAbi, spokeChainConfig, spokeChainKeysSet, spokeHooks, stacksSupportedTokens, stagingSwapSupportedTokens, stakedSodaAbi, stakingInvariant, stakingRouterAbi, stataTokenFactoryAbi, stellarSupportedTokens, submitTransaction, suiSupportedTokens, supportedSpokeChains, supportedTokensByChain, swapExactInSingleParamsAbi, swapInvariant, swapSupportedTokens, swapsConfig, uiPoolDataAbi, universalRouterAbi, unknownFailed, usesBip322MessageSigning, valueToBigNumber, valueToZDBigNumber, variableDebtTokenAbi, vaultTokenAbi, verifyFailed, wadToRay, waitForStacksTransaction, waitForTransactionReceipt, waitUntilIntentExecuted, walletFactoryAbi, wrappedSonicAbi };
40346
+ export { ALLOWANCE_CHECK_CODES, APPROVE_CODES, AssetService, BITCOIN_CHAIN_KEYS, BITCOIN_CHAIN_KEYS_SET, BTC_WALLET_ADDRESS_TYPES, BackendApiService, BalnSwapService, BigIntToHex, BigNumberZeroDecimal, BitcoinSpokeService, BnUSDMigrationService, BridgeService, CHAIN_KEYS, CHAIN_LOGO_BASE_URL, CONFIG_VERSION, CREATE_INTENT_CODES, ChainKeys, ChainTypeArr, ClService, ConfigService, CustomSorobanServer, CustomStellarAccount, DEFAULT_BACKEND_API_ENDPOINT, DEFAULT_BACKEND_API_HEADERS, DEFAULT_BACKEND_API_TIMEOUT, DEFAULT_DEADLINE_OFFSET, DEFAULT_MAX_RETRY, DEFAULT_RELAYER_API_ENDPOINT, DEFAULT_RELAY_TX_TIMEOUT, DEFAULT_RETRY_DELAY_MS, DexService, EVM_CHAIN_ID_TO_KEY, EVM_CHAIN_KEYS, EVM_CHAIN_KEYS_SET, EVM_SPOKE_ONLY_CHAIN_KEYS, EVM_SPOKE_ONLY_CHAIN_KEYS_SET, Erc20Service, Erc4626Service, EvmAssetManagerService, EvmHubProvider, EvmSolverService, EvmSpokeService, EvmVaultTokenService, FEE_PERCENTAGE_SCALE, GAS_ESTIMATION_CODES, HALF_RAY, HALF_WAD, HUB_CHAIN_KEY, HookKind, HookService, HttpRelayError, HubVaultSymbols, ICON_CHAIN_KEYS, ICON_CHAIN_KEYS_SET, ICON_TX_RESULT_WAIT_MAX_RETRY, INJECTIVE_CHAIN_KEYS, INJECTIVE_CHAIN_KEYS_SET, INTENT_CHAIN_IDS, IconSpokeService, IcxMigrationService, Injective20Token, InjectiveSpokeService, IntentCreatedEventAbi, IntentDataService, IntentDataType, IntentFilledEventAbi, IntentRelayChainIdToChainKey, IntentsAbi, LOOKUP_CODES, LTV_PRECISION, LendingPoolService, LeverageYieldService, LockupMultiplier, LockupPeriod, LsodaSymbols, LsodaTokens, MAX_UINT256, MigrationService, MintPositionEventAbi, MoneyMarketDataService, MoneyMarketService, NEAR_CHAIN_KEYS, NEAR_CHAIN_KEYS_SET, NEAR_DEFAULT_GAS, NEAR_STORAGE_DEPOSIT, NearSpokeService, PartnerFeeClaimService, PartnerService, Permit2Service, ProtocolIntentsAbi, RAY, RAY_DECIMALS, RELAY_ERROR_CODES, RadfiApiError, RadfiProvider, RecoveryService, RelayChainIdMap, SECONDS_PER_YEAR, SODAX_ERROR_CODES, SODAX_FEATURES, SOLANA_CHAIN_KEYS, SOLANA_CHAIN_KEYS_SET, SONIC_CHAIN_KEYS, SONIC_CHAIN_KEYS_SET, STACKS_CHAIN_KEYS, STACKS_CHAIN_KEYS_SET, STELLAR_CHAIN_KEYS, STELLAR_CHAIN_KEYS_SET, SUI_CHAIN_KEYS, SUI_CHAIN_KEYS_SET, SodaTokens, Sodax, SodaxError, SolanaSpokeService, SolverApiService, SolverIntentErrorCode, SolverIntentStatusCode, SonicSpokeService, SpokeService, StacksSpokeService, StakingLogic, StakingService, StatATokenAddresses, StellarSpokeService, SuiSpokeService, SupportedMigrationTokens, SwapService, SwapsApiService, USD_DECIMALS, UiPoolDataProviderService, VAULT_TOKEN_DECIMALS, WAD, WAD_RAY_RATIO, WEI_DECIMALS, adjustAmountByFee, allowanceCheckFailed, apiConfig, approveFailed, arbitrumSupportedTokens, assetManagerAbi, avalancheSupportedTokens, balnSwapAbi, baseChainInfo, baseSupportedTokens, binomialApproximatedRayPow, bitcoinSupportedTokens, bnUSDLegacySpokeChainIds, bnUSDLegacyTokens, bridgeConfig, bridgeInvariant, bscSupportedTokens, calcOpReturnOutputVbytes, calculateAllReserveIncentives, calculateAllUserIncentives, calculateAvailableBorrowsMarketReferenceCurrency, calculateCompoundedInterest, calculateCompoundedRate, calculateFeeAmount, calculateHealthFactorFromBalances, calculateHealthFactorFromBalancesBigUnits, calculateLinearInterest, calculatePercentageFeeAmount, clPoolAbi, clPoolManagerAbi, clPositionManagerAbi, clQuoterAbi, clRouterAbi, clTickLensAbi, concentratedLiquidityConfig, connectionAbi, consoleLogger, convertTransactionInstructionToRaw, createInvariant, deepMerge, defaultHookAbi, detectBitcoinAddressType, dexConfig, dexInvariant, dexPools, encodeAddress, encodeBtcPayloadToBytes, encodeContractCalls, erc20Abi, erc4626Abi, estimateBitcoinTxSize, ethereumSupportedTokens, executionFailed, formatBasisPoints, formatEModeCategory, formatEModes, formatPercentage, formatReserve, formatReserveUSD, formatReserves, formatReservesAndIncentives, formatUserSummary, formatUserSummaryAndIncentives, gasEstimationFailed, getAllLegacybnUSDTokens, getAndFormatReserveEModes, getAssetManagerIdl, getAssetManagerProgram, getChainKeyFromRelayChainId, getChainType, getCompoundedBalance, getConcentratedLiquidityConfig, getConnectionIdl, getConnectionProgram, getEvmChainKeyByChainId, getEvmViemChain, getIconAddressBytes, getIntentRelayChainId, getLinearBalance, getMarketReferenceCurrencyAndUsdBalance, getPacket, getProvider, getRandomBytes, getReserveNormalizedIncome, getReservesEModes, getSolanaAddressBytes, getSolverConfig, getSpokeHook, getSpokeHooks, getStagingSolverTokens, getSupportedSolverTokens, getTransactionPackets, getbnUSDToken, hexToBigInt, hexToSolanaAddress, hubConfig, hyper, hyperevmSupportedTokens, iconSupportedTokens, injectiveSupportedTokens, intentCreationFailed, isBalnMigrateParams, isBitcoinChainKey, isBitcoinChainKeyType, isBitcoinWalletProviderType, isBridgeAllowanceCheckError, isBridgeApproveError, isBridgeCreateIntentError, isBridgeError, isBridgeLookupError, isBridgeOrchestrationError, isCodeMember, isDexError, isEvmChainKey, isEvmChainKeyType, isEvmSpokeChainConfig, isEvmSpokeOnlyChainKey, isEvmSpokeOnlyChainKeyType, isEvmWalletProviderType, isFeatureError, isHookSupportedToken, isHubChainKey, isHubChainKeyType, isIconAddress, isIconChainKey, isIconChainKeyType, isIcxCreateRevertMigrationParams, isIcxMigrateParams, isInjectiveChainKey, isInjectiveChainKeyType, isJsonRpcPayloadResponse, isLegacybnUSDChainId, isLegacybnUSDToken, isLeverageYieldAllowanceCheckError, isLeverageYieldApproveError, isLeverageYieldCreateIntentError, isLeverageYieldError, isLeverageYieldLookupError, isLeverageYieldPostExecutionError, isLeverageYieldSwapError, isMigrateOrchestrationError, isMigrationAllowanceCheckError, isMigrationApproveError, isMigrationCreateIntentError, isMigrationError, isMigrationLookupError, isMoneyMarketAllowanceCheckError, isMoneyMarketApproveError, isMoneyMarketCreateIntentError, isMoneyMarketError, isMoneyMarketGasEstimationError, isMoneyMarketOrchestrationError, isNativeToken, isNearChainKey, isNearChainKeyType, isNewbnUSDChainId, isNewbnUSDToken, isOptionalBitcoinWalletProviderType, isOptionalEvmWalletProviderType, isOptionalStellarWalletProviderType, isPartnerError, isPartnerFeeAmount, isPartnerFeePercentage, isPostExecutionError, isRawDestinationParams, isRecoveryError, isResponseAddressType, isResponseSigningType, isRevertMigrationOrchestrationError, isSodaxError, isSolanaChainKey, isSolanaChainKeyType, isSolanaNativeToken, isSonicChainKey, isSonicChainKeyType, isSpokeApproveParamsEvmSpoke, isSpokeApproveParamsHub, isSpokeApproveParamsStellar, isSpokeChainKey, isSpokeIsAllowanceValidParamsEvmSpoke, isSpokeIsAllowanceValidParamsHub, isSpokeIsAllowanceValidParamsStellar, isStacksChainKey, isStacksChainKeyType, isStakeOrchestrationError, isStakingAllowanceCheckError, isStakingApproveError, isStakingCreateIntentError, isStakingError, isStakingInfoFetchError, isStakingOrchestrationError, isStellarChainKey, isStellarChainKeyType, isStellarWalletProviderType, isSuiChainKey, isSuiChainKeyType, isSupportedBitcoinAddressType, isSwapCreateIntentError, isSwapError, isSwapSupportedToken, isUndefinedOrValidWalletProviderForChainKey, isUnifiedBnUSDMigrateParams, isValidWalletProviderForChainKey, kaiaSupportedTokens, leverageYieldConfig, leverageYieldInvariant, leverageYieldVaults, lightlinkSupportedTokens, lookupFailed, mapRelayFailure, mergeSodaxConfig, messageOf, migrationInvariant, mintPositionParamsAbi, mmInvariant, modifyLiquidityParamsAbi, moneyMarketConfig, moneyMarketReserveAssets, moneyMarketSupportedTokens, nativeToUSD, nearSupportedTokens, newbnUSDSpokeChainIds, noopAnalytics, normalize, normalizeBN, normalizePsbtToBase64, normalizeSignatureToBase64, normalizedToUsd, optimismSupportedTokens, pancakeSwapInfinityDefaultHookAbi, pancakeSwapInfinityPoolManagerAbi, pancakeSwapInfinityPositionManagerAbi, parseToStroops, parseTokenArrayFromJson, partnerInvariant, permit2Abi, polygonSupportedTokens, poolAbi, poolKeyAbi, randomUint256, rayDiv, rayMul, rayPow, rayToWad, recoveryInvariant, redbellySupportedTokens, relayConfig, relayTxAndWaitPacket, requestAddress, requestJsonRpc, requestSigning, resolveAnalytics, resolveLogger, retry, reverseEncodeAddress, serializeAddressData, silentLogger, sleep, sodaxConfig, sodaxInvariant, solanaSupportedTokens, solverConfig, sonicSupportedTokens, sonicWalletFactoryAbi, spokeAssetManagerAbi, spokeChainConfig, spokeChainKeysSet, spokeHooks, stacksSupportedTokens, stagingSwapSupportedTokens, stakedSodaAbi, stakingInvariant, stakingRouterAbi, stataTokenFactoryAbi, stellarSupportedTokens, submitTransaction, suiSupportedTokens, supportedSpokeChains, supportedTokensByChain, swapExactInSingleParamsAbi, swapInvariant, swapSupportedTokens, swapsConfig, uiPoolDataAbi, universalRouterAbi, unknownFailed, usesBip322MessageSigning, valueToBigNumber, valueToZDBigNumber, variableDebtTokenAbi, vaultTokenAbi, verifyFailed, wadToRay, waitForStacksTransaction, waitForTransactionReceipt, waitUntilIntentExecuted, walletFactoryAbi, wrappedSonicAbi };