@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.cjs +1187 -310
- package/dist/index.d.cts +304 -67
- package/dist/index.d.ts +304 -67
- package/dist/index.mjs +1186 -309
- package/package.json +4 -3
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,
|
|
95
|
-
out[key] = sanitizeValue(
|
|
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((
|
|
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,
|
|
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((
|
|
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(
|
|
125
|
+
function safeString(v6) {
|
|
125
126
|
try {
|
|
126
|
-
return String(
|
|
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 =
|
|
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 =
|
|
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
|
|
4350
|
+
const array3 = new Uint8Array(length);
|
|
4369
4351
|
for (let i = 0; i < length; i++) {
|
|
4370
|
-
|
|
4352
|
+
array3[i] = Math.floor(Math.random() * 256);
|
|
4371
4353
|
}
|
|
4372
|
-
return
|
|
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
|
-
|
|
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((
|
|
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
|
|
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
|
-
|
|
16013
|
+
array3[ai] = n1 * 16 + n2;
|
|
16018
16014
|
}
|
|
16019
|
-
return
|
|
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
|
|
16645
|
+
let v6 = u8n(hashLen);
|
|
16650
16646
|
let k = u8n(hashLen);
|
|
16651
16647
|
let i = 0;
|
|
16652
16648
|
const reset = () => {
|
|
16653
|
-
|
|
16649
|
+
v6.fill(1);
|
|
16654
16650
|
k.fill(0);
|
|
16655
16651
|
i = 0;
|
|
16656
16652
|
};
|
|
16657
|
-
const h = (...msgs) => hmacFn(k, concatBytes(
|
|
16653
|
+
const h = (...msgs) => hmacFn(k, concatBytes(v6, ...msgs));
|
|
16658
16654
|
const reseed = (seed = NULL) => {
|
|
16659
16655
|
k = h(byte0, seed);
|
|
16660
|
-
|
|
16656
|
+
v6 = h();
|
|
16661
16657
|
if (seed.length === 0)
|
|
16662
16658
|
return;
|
|
16663
16659
|
k = h(byte1, seed);
|
|
16664
|
-
|
|
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
|
-
|
|
16673
|
-
const sl =
|
|
16668
|
+
v6 = h();
|
|
16669
|
+
const sl = v6.slice();
|
|
16674
16670
|
out.push(sl);
|
|
16675
|
-
len +=
|
|
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(
|
|
16691
|
-
if (!
|
|
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 =
|
|
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,
|
|
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(
|
|
16741
|
-
if (
|
|
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(
|
|
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
|
|
16773
|
-
const nv = Fp.mul(n,
|
|
16774
|
-
const i = Fp.mul(Fp.mul(nv, _2n),
|
|
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,
|
|
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
|
|
17255
|
-
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,
|
|
17257
|
+
cached(point, scalar, transform2) {
|
|
17262
17258
|
const W = getW(point);
|
|
17263
|
-
return this.wNAF(W, this.getPrecomputes(W, point,
|
|
17259
|
+
return this.wNAF(W, this.getPrecomputes(W, point, transform2), scalar);
|
|
17264
17260
|
}
|
|
17265
|
-
unsafe(point, scalar,
|
|
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,
|
|
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,
|
|
17352
|
+
const uvRatio2 = extraOpts.uvRatio || ((u, v6) => {
|
|
17357
17353
|
try {
|
|
17358
|
-
return { isValid: true, value: Fp.sqrt(Fp.div(u,
|
|
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
|
|
17455
|
-
let { isValid, value: x } = uvRatio2(u,
|
|
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,
|
|
17791
|
+
function uvRatio(u, v6) {
|
|
17796
17792
|
const P = ed25519_CURVE_p;
|
|
17797
|
-
const
|
|
17798
|
-
const v7 = mod(
|
|
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 *
|
|
17801
|
-
const vx2 = mod(
|
|
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((
|
|
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((
|
|
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
|
|
18334
|
-
if (
|
|
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(
|
|
18900
|
+
function isBiggerThanHalfOrder(number4) {
|
|
18905
18901
|
const HALF = CURVE_ORDER >> _1n6;
|
|
18906
|
-
return
|
|
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
|
|
19084
|
-
const u1 = Fn.create(h *
|
|
19085
|
-
const u2 = Fn.create(r *
|
|
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
|
|
19090
|
-
return
|
|
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
|
-
|
|
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
|
-
*
|
|
26588
|
-
*
|
|
26589
|
-
*
|
|
26590
|
-
*
|
|
26591
|
-
*
|
|
26592
|
-
*
|
|
26593
|
-
*
|
|
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
|
|
26628
|
-
const
|
|
26629
|
-
|
|
26630
|
-
|
|
26631
|
-
|
|
26632
|
-
|
|
26633
|
-
|
|
26634
|
-
|
|
26635
|
-
|
|
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/
|
|
29423
|
-
var
|
|
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
|
-
*
|
|
29433
|
-
*
|
|
29434
|
-
*
|
|
29435
|
-
*
|
|
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
|
|
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
|
|
29451
|
-
|
|
29452
|
-
headers,
|
|
29453
|
-
|
|
29454
|
-
|
|
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
|
-
|
|
29457
|
-
if (!
|
|
29458
|
-
|
|
29459
|
-
|
|
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
|
-
|
|
29462
|
-
return data;
|
|
29816
|
+
return { ok: true, value: parsed.output };
|
|
29463
29817
|
} catch (error) {
|
|
29464
|
-
|
|
29465
|
-
|
|
29466
|
-
|
|
29467
|
-
|
|
29468
|
-
|
|
29469
|
-
|
|
29470
|
-
|
|
29471
|
-
|
|
29472
|
-
|
|
29473
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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.
|
|
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(
|
|
29771
|
-
|
|
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(
|
|
29787
|
-
|
|
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.
|
|
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.
|
|
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((
|
|
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((
|
|
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,
|
|
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 };
|