@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.cjs
CHANGED
|
@@ -19,6 +19,7 @@ var IconSdkRaw = require('icon-sdk-js');
|
|
|
19
19
|
var sdkTs = require('@injectivelabs/sdk-ts');
|
|
20
20
|
var tx_js = require('cosmjs-types/cosmos/tx/v1beta1/tx.js');
|
|
21
21
|
var networks = require('@injectivelabs/networks');
|
|
22
|
+
var v4 = require('valibot');
|
|
22
23
|
var BigNumber5 = require('bignumber.js');
|
|
23
24
|
var swapSdkCore = require('@pancakeswap/swap-sdk-core');
|
|
24
25
|
var v3Sdk = require('@pancakeswap/v3-sdk');
|
|
@@ -47,6 +48,7 @@ var rlp__namespace = /*#__PURE__*/_interopNamespace(rlp);
|
|
|
47
48
|
var ecc__namespace = /*#__PURE__*/_interopNamespace(ecc);
|
|
48
49
|
var BN__default = /*#__PURE__*/_interopDefault(BN);
|
|
49
50
|
var IconSdkRaw__namespace = /*#__PURE__*/_interopNamespace(IconSdkRaw);
|
|
51
|
+
var v4__namespace = /*#__PURE__*/_interopNamespace(v4);
|
|
50
52
|
var BigNumber5__default = /*#__PURE__*/_interopDefault(BigNumber5);
|
|
51
53
|
|
|
52
54
|
// src/errors/SodaxError.ts
|
|
@@ -119,8 +121,8 @@ function serializeCause(cause, depth) {
|
|
|
119
121
|
}
|
|
120
122
|
function sanitizeContext(value, depth) {
|
|
121
123
|
const out = {};
|
|
122
|
-
for (const [key,
|
|
123
|
-
out[key] = sanitizeValue(
|
|
124
|
+
for (const [key, v6] of Object.entries(value)) {
|
|
125
|
+
out[key] = sanitizeValue(v6, depth + 1);
|
|
124
126
|
}
|
|
125
127
|
return out;
|
|
126
128
|
}
|
|
@@ -131,13 +133,13 @@ function sanitizeValue(value, depth) {
|
|
|
131
133
|
if (t === "bigint") return value.toString();
|
|
132
134
|
if (t === "string" || t === "number" || t === "boolean") return value;
|
|
133
135
|
if (t === "function" || t === "symbol") return safeString(value);
|
|
134
|
-
if (Array.isArray(value)) return value.map((
|
|
136
|
+
if (Array.isArray(value)) return value.map((v6) => sanitizeValue(v6, depth + 1));
|
|
135
137
|
if (value instanceof Date) return value.toISOString();
|
|
136
138
|
if (value instanceof Map) {
|
|
137
|
-
return Array.from(value.entries()).map(([k,
|
|
139
|
+
return Array.from(value.entries()).map(([k, v6]) => [sanitizeValue(k, depth + 1), sanitizeValue(v6, depth + 1)]);
|
|
138
140
|
}
|
|
139
141
|
if (value instanceof Set) {
|
|
140
|
-
return Array.from(value.values()).map((
|
|
142
|
+
return Array.from(value.values()).map((v6) => sanitizeValue(v6, depth + 1));
|
|
141
143
|
}
|
|
142
144
|
if (value instanceof Error) return { name: value.name, message: value.message };
|
|
143
145
|
if (t === "object") {
|
|
@@ -149,9 +151,9 @@ function sanitizeValue(value, depth) {
|
|
|
149
151
|
}
|
|
150
152
|
return safeString(value);
|
|
151
153
|
}
|
|
152
|
-
function safeString(
|
|
154
|
+
function safeString(v6) {
|
|
153
155
|
try {
|
|
154
|
-
return String(
|
|
156
|
+
return String(v6);
|
|
155
157
|
} catch {
|
|
156
158
|
return "[unserializable]";
|
|
157
159
|
}
|
|
@@ -199,6 +201,7 @@ var SODAX_FEATURES = [
|
|
|
199
201
|
"dex",
|
|
200
202
|
"partner",
|
|
201
203
|
"recovery",
|
|
204
|
+
"backend",
|
|
202
205
|
"leverageYield"
|
|
203
206
|
];
|
|
204
207
|
|
|
@@ -2640,7 +2643,7 @@ var RelayChainIdMap = {
|
|
|
2640
2643
|
[ChainKeys.STACKS_MAINNET]: 60n
|
|
2641
2644
|
};
|
|
2642
2645
|
var INTENT_CHAIN_IDS = Object.values(RelayChainIdMap);
|
|
2643
|
-
var IntentRelayChainIdToChainKey =
|
|
2646
|
+
var IntentRelayChainIdToChainKey = new Map(Object.entries(RelayChainIdMap).map(([chainKey, chainId]) => [chainId, chainKey]));
|
|
2644
2647
|
var CHAIN_LOGO_BASE_URL = "https://raw.githubusercontent.com/icon-project/sodax-sdks/main/packages/assets/chain";
|
|
2645
2648
|
var chainLogo = (key) => `${CHAIN_LOGO_BASE_URL}/${key}.png`;
|
|
2646
2649
|
var baseChainInfo = {
|
|
@@ -4246,7 +4249,7 @@ function isValidWalletProviderForChainKey(chainKey, walletProvider) {
|
|
|
4246
4249
|
}
|
|
4247
4250
|
|
|
4248
4251
|
// ../types/dist/index.js
|
|
4249
|
-
var CONFIG_VERSION =
|
|
4252
|
+
var CONFIG_VERSION = 217;
|
|
4250
4253
|
function isEvmSpokeChainConfig(value) {
|
|
4251
4254
|
return typeof value === "object" && value !== null && value.chain.type === "EVM" && value.chain.key !== HUB_CHAIN_KEY;
|
|
4252
4255
|
}
|
|
@@ -4336,26 +4339,6 @@ function isRawDestinationParams(value) {
|
|
|
4336
4339
|
if (typeof obj.dstAddress !== "string") return false;
|
|
4337
4340
|
return typeof obj.dstChainKey === "string" && spokeChainKeysSet.has(obj.dstChainKey);
|
|
4338
4341
|
}
|
|
4339
|
-
function isSubmitSwapTxResponse(value) {
|
|
4340
|
-
return typeof value === "object" && value !== null && typeof value.success === "boolean" && typeof value.message === "string";
|
|
4341
|
-
}
|
|
4342
|
-
function isSubmitSwapTxStatusResponse(value) {
|
|
4343
|
-
if (typeof value !== "object" || value === null) return false;
|
|
4344
|
-
const obj = value;
|
|
4345
|
-
if (typeof obj.success !== "boolean") return false;
|
|
4346
|
-
if (typeof obj.data !== "object" || obj.data === null) return false;
|
|
4347
|
-
const data = obj.data;
|
|
4348
|
-
if (typeof data.txHash !== "string") return false;
|
|
4349
|
-
if (typeof data.srcChainKey !== "string") return false;
|
|
4350
|
-
if (typeof data.status !== "string") return false;
|
|
4351
|
-
if (typeof data.failedAttempts !== "number") return false;
|
|
4352
|
-
if (data.result !== void 0) {
|
|
4353
|
-
if (typeof data.result !== "object" || data.result === null) return false;
|
|
4354
|
-
const result = data.result;
|
|
4355
|
-
if (typeof result.dstIntentTxHash !== "string") return false;
|
|
4356
|
-
}
|
|
4357
|
-
return true;
|
|
4358
|
-
}
|
|
4359
4342
|
function isBitcoinWalletProviderType(wp) {
|
|
4360
4343
|
return wp.chainType === "BITCOIN";
|
|
4361
4344
|
}
|
|
@@ -4393,11 +4376,11 @@ async function retry(action, retryCount = DEFAULT_MAX_RETRY, delayMs = DEFAULT_R
|
|
|
4393
4376
|
throw new Error(`Retry exceeded MAX_RETRY_DEFAULT=${DEFAULT_MAX_RETRY}`);
|
|
4394
4377
|
}
|
|
4395
4378
|
function getRandomBytes(length) {
|
|
4396
|
-
const
|
|
4379
|
+
const array3 = new Uint8Array(length);
|
|
4397
4380
|
for (let i = 0; i < length; i++) {
|
|
4398
|
-
|
|
4381
|
+
array3[i] = Math.floor(Math.random() * 256);
|
|
4399
4382
|
}
|
|
4400
|
-
return
|
|
4383
|
+
return array3;
|
|
4401
4384
|
}
|
|
4402
4385
|
function randomUint256() {
|
|
4403
4386
|
const bytes = getRandomBytes(32);
|
|
@@ -13644,29 +13627,6 @@ var universalRouterAbi = [
|
|
|
13644
13627
|
}
|
|
13645
13628
|
];
|
|
13646
13629
|
|
|
13647
|
-
// src/shared/utils/deepMerge.ts
|
|
13648
|
-
function deepMerge(target, source) {
|
|
13649
|
-
const result = { ...target };
|
|
13650
|
-
for (const key of Object.keys(source)) {
|
|
13651
|
-
const sourceVal = source[key];
|
|
13652
|
-
const targetVal = target[key];
|
|
13653
|
-
if (sourceVal !== void 0 && typeof sourceVal === "object" && sourceVal !== null && !Array.isArray(sourceVal) && typeof targetVal === "object" && targetVal !== null && !Array.isArray(targetVal)) {
|
|
13654
|
-
result[key] = deepMerge(
|
|
13655
|
-
targetVal,
|
|
13656
|
-
sourceVal
|
|
13657
|
-
);
|
|
13658
|
-
} else if (sourceVal !== void 0) {
|
|
13659
|
-
result[key] = sourceVal;
|
|
13660
|
-
}
|
|
13661
|
-
}
|
|
13662
|
-
return result;
|
|
13663
|
-
}
|
|
13664
|
-
|
|
13665
|
-
// src/shared/config/mergeSodaxConfig.ts
|
|
13666
|
-
function mergeSodaxConfig(base2, override) {
|
|
13667
|
-
return deepMerge(base2, override);
|
|
13668
|
-
}
|
|
13669
|
-
|
|
13670
13630
|
// src/shared/logger.ts
|
|
13671
13631
|
var consoleLogger = {
|
|
13672
13632
|
debug: (message, data) => data ? console.debug(message, data) : console.debug(message),
|
|
@@ -13759,8 +13719,9 @@ function resolveAnalytics(option) {
|
|
|
13759
13719
|
// src/shared/config/ConfigService.ts
|
|
13760
13720
|
var ConfigService = class {
|
|
13761
13721
|
sodax;
|
|
13762
|
-
api
|
|
13763
|
-
|
|
13722
|
+
// TODO(config-v2): restore `api` / `userConfig` when initialize() dynamic fetch is re-enabled.
|
|
13723
|
+
// private readonly api: BackendApiService;
|
|
13724
|
+
// private readonly userConfig?: SodaxOptions;
|
|
13764
13725
|
/**
|
|
13765
13726
|
* SDK log sink. Resolved once at construction and kept independent of {@link sodax} so that
|
|
13766
13727
|
* {@link initialize}'s dynamic-config swap never clobbers it. Read by services via `config.logger`.
|
|
@@ -13789,10 +13750,10 @@ var ConfigService = class {
|
|
|
13789
13750
|
stakedATokenAddressesSet;
|
|
13790
13751
|
chainToSupportedTokenAddressMap;
|
|
13791
13752
|
hubAssetToXTokenMap;
|
|
13753
|
+
// `api` / `userConfig` are accepted but unused while initialize()'s dynamic fetch is disabled
|
|
13754
|
+
// (see TODO(config-v2) below); restore their assignments when re-enabling.
|
|
13792
13755
|
constructor({ api, config, userConfig, logger, analytics, fee }) {
|
|
13793
|
-
this.api = api;
|
|
13794
13756
|
this.sodax = config;
|
|
13795
|
-
this.userConfig = userConfig;
|
|
13796
13757
|
this.logger = logger ?? resolveLogger(void 0);
|
|
13797
13758
|
this.analytics = analytics ?? noopAnalytics;
|
|
13798
13759
|
this.fee = fee;
|
|
@@ -13800,19 +13761,6 @@ var ConfigService = class {
|
|
|
13800
13761
|
}
|
|
13801
13762
|
async initialize() {
|
|
13802
13763
|
try {
|
|
13803
|
-
const result = await this.api.getAllConfig();
|
|
13804
|
-
if (!result.ok) return result;
|
|
13805
|
-
const response = result.value;
|
|
13806
|
-
if (!response.version || response.version < CONFIG_VERSION) {
|
|
13807
|
-
this.logger.warn(
|
|
13808
|
-
`Dynamic config version is less than the current version, resorting to the default one. Current version: ${CONFIG_VERSION}, response version: ${response.version}`
|
|
13809
|
-
);
|
|
13810
|
-
} else {
|
|
13811
|
-
const next = this.userConfig ? mergeSodaxConfig(response.config, this.userConfig) : response.config;
|
|
13812
|
-
this.loadSodaxConfigDataStructures(next);
|
|
13813
|
-
this.sodax = next;
|
|
13814
|
-
this.initialized = true;
|
|
13815
|
-
}
|
|
13816
13764
|
return { ok: true, value: void 0 };
|
|
13817
13765
|
} catch (error) {
|
|
13818
13766
|
return { ok: false, error };
|
|
@@ -14082,9 +14030,32 @@ function parseTokenArrayFromJson(input) {
|
|
|
14082
14030
|
}
|
|
14083
14031
|
return tokens;
|
|
14084
14032
|
}
|
|
14033
|
+
|
|
14034
|
+
// src/shared/utils/deepMerge.ts
|
|
14035
|
+
function deepMerge(target, source) {
|
|
14036
|
+
const result = { ...target };
|
|
14037
|
+
for (const key of Object.keys(source)) {
|
|
14038
|
+
const sourceVal = source[key];
|
|
14039
|
+
const targetVal = target[key];
|
|
14040
|
+
if (sourceVal !== void 0 && typeof sourceVal === "object" && sourceVal !== null && !Array.isArray(sourceVal) && typeof targetVal === "object" && targetVal !== null && !Array.isArray(targetVal)) {
|
|
14041
|
+
result[key] = deepMerge(
|
|
14042
|
+
targetVal,
|
|
14043
|
+
sourceVal
|
|
14044
|
+
);
|
|
14045
|
+
} else if (sourceVal !== void 0) {
|
|
14046
|
+
result[key] = sourceVal;
|
|
14047
|
+
}
|
|
14048
|
+
}
|
|
14049
|
+
return result;
|
|
14050
|
+
}
|
|
14051
|
+
|
|
14052
|
+
// src/shared/config/mergeSodaxConfig.ts
|
|
14053
|
+
function mergeSodaxConfig(base2, override) {
|
|
14054
|
+
return deepMerge(base2, override);
|
|
14055
|
+
}
|
|
14085
14056
|
function encodeContractCalls(calls) {
|
|
14086
14057
|
return viem.encodeAbiParameters(viem.parseAbiParameters("(address,uint256,bytes)[]"), [
|
|
14087
|
-
calls.map((
|
|
14058
|
+
calls.map((v6) => [v6.address, v6.value, v6.data])
|
|
14088
14059
|
]);
|
|
14089
14060
|
}
|
|
14090
14061
|
async function waitForTransactionReceipt(hash, provider) {
|
|
@@ -15765,6 +15736,32 @@ var BitcoinSpokeService = class {
|
|
|
15765
15736
|
throw error;
|
|
15766
15737
|
}
|
|
15767
15738
|
}
|
|
15739
|
+
/**
|
|
15740
|
+
* Sign and submit a TRADING-wallet raw transaction — the Bound-built *unsigned* PSBT returned by
|
|
15741
|
+
* `deposit({ raw: true })` / the Swaps API (`createIntent().tx.data`). Signs it with the wallet
|
|
15742
|
+
* provider's key, then sends it to Bound Exchange to co-sign with the second 2-of-2 key and
|
|
15743
|
+
* broadcast. Returns the broadcast tx id.
|
|
15744
|
+
*
|
|
15745
|
+
* This is the client-side completion of the TRADING deposit flow: the backend builds the PSBT
|
|
15746
|
+
* (it can't broadcast — the user's signature is missing), the client signs here, and Bound
|
|
15747
|
+
* co-signs + broadcasts. `relayData` ({ address, payload }) is the relay identity returned by
|
|
15748
|
+
* `createIntent()`; forwarding it lets Bound auto-resubmit a stuck relay. It is **not** recoverable
|
|
15749
|
+
* from `rawTx` (whose `to` is the asset manager, not the hub wallet), so callers must supply it.
|
|
15750
|
+
*
|
|
15751
|
+
* @throws if the chain is not in `TRADING` wallet mode (raw txs only exist in TRADING mode).
|
|
15752
|
+
*/
|
|
15753
|
+
async signAndSubmitRawTransaction(params) {
|
|
15754
|
+
if (this.walletMode !== "TRADING") {
|
|
15755
|
+
throw new Error("signAndSubmitRawTransaction requires TRADING wallet mode.");
|
|
15756
|
+
}
|
|
15757
|
+
const { rawTx, walletProvider, relayData, accessToken = this.radfi.accessToken } = params;
|
|
15758
|
+
if (!rawTx?.data || !rawTx?.from) {
|
|
15759
|
+
throw new Error("signAndSubmitRawTransaction: rawTx.data (PSBT) and rawTx.from are required.");
|
|
15760
|
+
}
|
|
15761
|
+
const signedTx = await walletProvider.signTransaction(rawTx.data, false);
|
|
15762
|
+
const signedBase64Tx = normalizePsbtToBase64(signedTx);
|
|
15763
|
+
return this.radfi.requestRadfiSignature({ userAddress: rawTx.from, signedBase64Tx, relayData }, accessToken);
|
|
15764
|
+
}
|
|
15768
15765
|
/**
|
|
15769
15766
|
* Build deposit PSBT with embedded cross-chain data
|
|
15770
15767
|
*/
|
|
@@ -16034,7 +16031,7 @@ function hexToBytes2(hex) {
|
|
|
16034
16031
|
const al = hl / 2;
|
|
16035
16032
|
if (hl % 2)
|
|
16036
16033
|
throw new Error("hex string expected, got unpadded hex of length " + hl);
|
|
16037
|
-
const
|
|
16034
|
+
const array3 = new Uint8Array(al);
|
|
16038
16035
|
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
16039
16036
|
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
|
16040
16037
|
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
|
@@ -16042,9 +16039,9 @@ function hexToBytes2(hex) {
|
|
|
16042
16039
|
const char = hex[hi] + hex[hi + 1];
|
|
16043
16040
|
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
|
16044
16041
|
}
|
|
16045
|
-
|
|
16042
|
+
array3[ai] = n1 * 16 + n2;
|
|
16046
16043
|
}
|
|
16047
|
-
return
|
|
16044
|
+
return array3;
|
|
16048
16045
|
}
|
|
16049
16046
|
function concatBytes(...arrays) {
|
|
16050
16047
|
let sum = 0;
|
|
@@ -16674,22 +16671,22 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
|
|
|
16674
16671
|
const byte0 = Uint8Array.of(0);
|
|
16675
16672
|
const byte1 = Uint8Array.of(1);
|
|
16676
16673
|
const _maxDrbgIters = 1e3;
|
|
16677
|
-
let
|
|
16674
|
+
let v6 = u8n(hashLen);
|
|
16678
16675
|
let k = u8n(hashLen);
|
|
16679
16676
|
let i = 0;
|
|
16680
16677
|
const reset = () => {
|
|
16681
|
-
|
|
16678
|
+
v6.fill(1);
|
|
16682
16679
|
k.fill(0);
|
|
16683
16680
|
i = 0;
|
|
16684
16681
|
};
|
|
16685
|
-
const h = (...msgs) => hmacFn(k, concatBytes(
|
|
16682
|
+
const h = (...msgs) => hmacFn(k, concatBytes(v6, ...msgs));
|
|
16686
16683
|
const reseed = (seed = NULL) => {
|
|
16687
16684
|
k = h(byte0, seed);
|
|
16688
|
-
|
|
16685
|
+
v6 = h();
|
|
16689
16686
|
if (seed.length === 0)
|
|
16690
16687
|
return;
|
|
16691
16688
|
k = h(byte1, seed);
|
|
16692
|
-
|
|
16689
|
+
v6 = h();
|
|
16693
16690
|
};
|
|
16694
16691
|
const gen = () => {
|
|
16695
16692
|
if (i++ >= _maxDrbgIters)
|
|
@@ -16697,10 +16694,10 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
|
|
|
16697
16694
|
let len = 0;
|
|
16698
16695
|
const out = [];
|
|
16699
16696
|
while (len < qByteLen) {
|
|
16700
|
-
|
|
16701
|
-
const sl =
|
|
16697
|
+
v6 = h();
|
|
16698
|
+
const sl = v6.slice();
|
|
16702
16699
|
out.push(sl);
|
|
16703
|
-
len +=
|
|
16700
|
+
len += v6.length;
|
|
16704
16701
|
}
|
|
16705
16702
|
return concatBytes(...out);
|
|
16706
16703
|
};
|
|
@@ -16715,18 +16712,18 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
|
|
|
16715
16712
|
};
|
|
16716
16713
|
return genUntil;
|
|
16717
16714
|
}
|
|
16718
|
-
function validateObject(
|
|
16719
|
-
if (!
|
|
16715
|
+
function validateObject(object4, fields = {}, optFields = {}) {
|
|
16716
|
+
if (!object4 || typeof object4 !== "object")
|
|
16720
16717
|
throw new Error("expected valid options object");
|
|
16721
16718
|
function checkField(fieldName, expectedType, isOpt) {
|
|
16722
|
-
const val =
|
|
16719
|
+
const val = object4[fieldName];
|
|
16723
16720
|
if (isOpt && val === void 0)
|
|
16724
16721
|
return;
|
|
16725
16722
|
const current = typeof val;
|
|
16726
16723
|
if (current !== expectedType || val === null)
|
|
16727
16724
|
throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
|
|
16728
16725
|
}
|
|
16729
|
-
const iter = (f, isOpt) => Object.entries(f).forEach(([k,
|
|
16726
|
+
const iter = (f, isOpt) => Object.entries(f).forEach(([k, v6]) => checkField(k, v6, isOpt));
|
|
16730
16727
|
iter(fields, false);
|
|
16731
16728
|
iter(optFields, true);
|
|
16732
16729
|
}
|
|
@@ -16765,12 +16762,12 @@ function pow2(x, power, modulo) {
|
|
|
16765
16762
|
}
|
|
16766
16763
|
return res;
|
|
16767
16764
|
}
|
|
16768
|
-
function invert(
|
|
16769
|
-
if (
|
|
16765
|
+
function invert(number4, modulo) {
|
|
16766
|
+
if (number4 === _0n2)
|
|
16770
16767
|
throw new Error("invert: expected non-zero number");
|
|
16771
16768
|
if (modulo <= _0n2)
|
|
16772
16769
|
throw new Error("invert: expected positive modulus, got " + modulo);
|
|
16773
|
-
let a = mod(
|
|
16770
|
+
let a = mod(number4, modulo);
|
|
16774
16771
|
let b = modulo;
|
|
16775
16772
|
let x = _0n2, u = _1n2;
|
|
16776
16773
|
while (a !== _0n2) {
|
|
@@ -16797,9 +16794,9 @@ function sqrt3mod4(Fp, n) {
|
|
|
16797
16794
|
function sqrt5mod8(Fp, n) {
|
|
16798
16795
|
const p5div8 = (Fp.ORDER - _5n) / _8n;
|
|
16799
16796
|
const n2 = Fp.mul(n, _2n);
|
|
16800
|
-
const
|
|
16801
|
-
const nv = Fp.mul(n,
|
|
16802
|
-
const i = Fp.mul(Fp.mul(nv, _2n),
|
|
16797
|
+
const v6 = Fp.pow(n2, p5div8);
|
|
16798
|
+
const nv = Fp.mul(n, v6);
|
|
16799
|
+
const i = Fp.mul(Fp.mul(nv, _2n), v6);
|
|
16803
16800
|
const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
|
|
16804
16801
|
assertIsSquare(Fp, root, n);
|
|
16805
16802
|
return root;
|
|
@@ -17274,27 +17271,27 @@ var wNAF = class {
|
|
|
17274
17271
|
assert0(n);
|
|
17275
17272
|
return acc;
|
|
17276
17273
|
}
|
|
17277
|
-
getPrecomputes(W, point,
|
|
17274
|
+
getPrecomputes(W, point, transform2) {
|
|
17278
17275
|
let comp = pointPrecomputes.get(point);
|
|
17279
17276
|
if (!comp) {
|
|
17280
17277
|
comp = this.precomputeWindow(point, W);
|
|
17281
17278
|
if (W !== 1) {
|
|
17282
|
-
if (typeof
|
|
17283
|
-
comp =
|
|
17279
|
+
if (typeof transform2 === "function")
|
|
17280
|
+
comp = transform2(comp);
|
|
17284
17281
|
pointPrecomputes.set(point, comp);
|
|
17285
17282
|
}
|
|
17286
17283
|
}
|
|
17287
17284
|
return comp;
|
|
17288
17285
|
}
|
|
17289
|
-
cached(point, scalar,
|
|
17286
|
+
cached(point, scalar, transform2) {
|
|
17290
17287
|
const W = getW(point);
|
|
17291
|
-
return this.wNAF(W, this.getPrecomputes(W, point,
|
|
17288
|
+
return this.wNAF(W, this.getPrecomputes(W, point, transform2), scalar);
|
|
17292
17289
|
}
|
|
17293
|
-
unsafe(point, scalar,
|
|
17290
|
+
unsafe(point, scalar, transform2, prev) {
|
|
17294
17291
|
const W = getW(point);
|
|
17295
17292
|
if (W === 1)
|
|
17296
17293
|
return this._unsafeLadder(point, scalar, prev);
|
|
17297
|
-
return this.wNAFUnsafe(W, this.getPrecomputes(W, point,
|
|
17294
|
+
return this.wNAFUnsafe(W, this.getPrecomputes(W, point, transform2), scalar, prev);
|
|
17298
17295
|
}
|
|
17299
17296
|
// We calculate precomputes for elliptic curve point multiplication
|
|
17300
17297
|
// using windowed method. This specifies window size and
|
|
@@ -17381,9 +17378,9 @@ function edwards(params, extraOpts = {}) {
|
|
|
17381
17378
|
validateObject(extraOpts, {}, { uvRatio: "function" });
|
|
17382
17379
|
const MASK = _2n2 << BigInt(Fn.BYTES * 8) - _1n4;
|
|
17383
17380
|
const modP = (n) => Fp.create(n);
|
|
17384
|
-
const uvRatio2 = extraOpts.uvRatio || ((u,
|
|
17381
|
+
const uvRatio2 = extraOpts.uvRatio || ((u, v6) => {
|
|
17385
17382
|
try {
|
|
17386
|
-
return { isValid: true, value: Fp.sqrt(Fp.div(u,
|
|
17383
|
+
return { isValid: true, value: Fp.sqrt(Fp.div(u, v6)) };
|
|
17387
17384
|
} catch (e) {
|
|
17388
17385
|
return { isValid: false, value: _0n4 };
|
|
17389
17386
|
}
|
|
@@ -17479,8 +17476,8 @@ function edwards(params, extraOpts = {}) {
|
|
|
17479
17476
|
aInRange("point.y", y, _0n4, max);
|
|
17480
17477
|
const y2 = modP(y * y);
|
|
17481
17478
|
const u = modP(y2 - _1n4);
|
|
17482
|
-
const
|
|
17483
|
-
let { isValid, value: x } = uvRatio2(u,
|
|
17479
|
+
const v6 = modP(d * y2 - a);
|
|
17480
|
+
let { isValid, value: x } = uvRatio2(u, v6);
|
|
17484
17481
|
if (!isValid)
|
|
17485
17482
|
throw new Error("bad point: invalid y coordinate");
|
|
17486
17483
|
const isXOdd = (x & _1n4) === _1n4;
|
|
@@ -17820,13 +17817,13 @@ function adjustScalarBytes(bytes) {
|
|
|
17820
17817
|
return bytes;
|
|
17821
17818
|
}
|
|
17822
17819
|
var ED25519_SQRT_M1 = /* @__PURE__ */ BigInt("19681161376707505956807079304988542015446066515923890162744021073123829784752");
|
|
17823
|
-
function uvRatio(u,
|
|
17820
|
+
function uvRatio(u, v6) {
|
|
17824
17821
|
const P = ed25519_CURVE_p;
|
|
17825
|
-
const
|
|
17826
|
-
const v7 = mod(
|
|
17822
|
+
const v32 = mod(v6 * v6 * v6, P);
|
|
17823
|
+
const v7 = mod(v32 * v32 * v6, P);
|
|
17827
17824
|
const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8;
|
|
17828
|
-
let x = mod(u *
|
|
17829
|
-
const vx2 = mod(
|
|
17825
|
+
let x = mod(u * v32 * pow, P);
|
|
17826
|
+
const vx2 = mod(v6 * x * x, P);
|
|
17830
17827
|
const root1 = x;
|
|
17831
17828
|
const root2 = mod(x * ED25519_SQRT_M1, P);
|
|
17832
17829
|
const useRoot1 = vx2 === u;
|
|
@@ -18157,7 +18154,7 @@ function findSeatPrice(validators, maxNumberOfSeats, minimumStakeRatio, protocol
|
|
|
18157
18154
|
return findSeatPriceForProtocolAfter49(validators, maxNumberOfSeats, minimumStakeRatio);
|
|
18158
18155
|
}
|
|
18159
18156
|
function findSeatPriceForProtocolBefore49(validators, numSeats) {
|
|
18160
|
-
const stakes = validators.map((
|
|
18157
|
+
const stakes = validators.map((v6) => BigInt(v6.stake)).sort(sortBigIntAsc);
|
|
18161
18158
|
const num = BigInt(numSeats);
|
|
18162
18159
|
const stakesSum = stakes.reduce((a, b) => a + b);
|
|
18163
18160
|
if (stakesSum < num) {
|
|
@@ -18186,7 +18183,7 @@ function findSeatPriceForProtocolAfter49(validators, maxNumberOfSeats, minimumSt
|
|
|
18186
18183
|
if (minimumStakeRatio.length != 2) {
|
|
18187
18184
|
throw Error("minimumStakeRatio should have 2 elements");
|
|
18188
18185
|
}
|
|
18189
|
-
const stakes = validators.map((
|
|
18186
|
+
const stakes = validators.map((v6) => BigInt(v6.stake)).sort(sortBigIntAsc);
|
|
18190
18187
|
const stakesSum = stakes.reduce((a, b) => a + b);
|
|
18191
18188
|
if (validators.length < maxNumberOfSeats) {
|
|
18192
18189
|
return stakesSum * BigInt(minimumStakeRatio[0]) / BigInt(minimumStakeRatio[1]);
|
|
@@ -18358,10 +18355,10 @@ var DER = {
|
|
|
18358
18355
|
if (length < 128)
|
|
18359
18356
|
throw new E("tlv.decode(long): not minimal encoding");
|
|
18360
18357
|
}
|
|
18361
|
-
const
|
|
18362
|
-
if (
|
|
18358
|
+
const v6 = data.subarray(pos, pos + length);
|
|
18359
|
+
if (v6.length !== length)
|
|
18363
18360
|
throw new E("tlv.decode: wrong value length");
|
|
18364
|
-
return { v, l: data.subarray(pos + length) };
|
|
18361
|
+
return { v: v6, l: data.subarray(pos + length) };
|
|
18365
18362
|
}
|
|
18366
18363
|
},
|
|
18367
18364
|
// https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
|
|
@@ -18929,9 +18926,9 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
18929
18926
|
extraEntropy: false
|
|
18930
18927
|
};
|
|
18931
18928
|
const hasLargeCofactor = CURVE_ORDER * _2n4 < Fp.ORDER;
|
|
18932
|
-
function isBiggerThanHalfOrder(
|
|
18929
|
+
function isBiggerThanHalfOrder(number4) {
|
|
18933
18930
|
const HALF = CURVE_ORDER >> _1n6;
|
|
18934
|
-
return
|
|
18931
|
+
return number4 > HALF;
|
|
18935
18932
|
}
|
|
18936
18933
|
function validateRS(title, num) {
|
|
18937
18934
|
if (!Fn.isValidNot0(num))
|
|
@@ -19108,14 +19105,14 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
19108
19105
|
return false;
|
|
19109
19106
|
const { r, s } = sig;
|
|
19110
19107
|
const h = bits2int_modN(message);
|
|
19111
|
-
const
|
|
19112
|
-
const u1 = Fn.create(h *
|
|
19113
|
-
const u2 = Fn.create(r *
|
|
19108
|
+
const is2 = Fn.inv(s);
|
|
19109
|
+
const u1 = Fn.create(h * is2);
|
|
19110
|
+
const u2 = Fn.create(r * is2);
|
|
19114
19111
|
const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2));
|
|
19115
19112
|
if (R.is0())
|
|
19116
19113
|
return false;
|
|
19117
|
-
const
|
|
19118
|
-
return
|
|
19114
|
+
const v6 = Fn.create(R.x);
|
|
19115
|
+
return v6 === r;
|
|
19119
19116
|
} catch (e) {
|
|
19120
19117
|
return false;
|
|
19121
19118
|
}
|
|
@@ -26461,13 +26458,18 @@ var SwapService = class {
|
|
|
26461
26458
|
solver;
|
|
26462
26459
|
partnerFee;
|
|
26463
26460
|
relayerApiEndpoint;
|
|
26464
|
-
|
|
26461
|
+
// backend swaps-API client + opt-in 2-step submit-tx flag
|
|
26462
|
+
backendApi;
|
|
26463
|
+
useBackendSubmitTx;
|
|
26464
|
+
constructor({ config, hubProvider, spoke, backendApi, useBackendSubmitTx }) {
|
|
26465
26465
|
this.solver = config.solver;
|
|
26466
26466
|
this.partnerFee = config.swapPartnerFee;
|
|
26467
26467
|
this.relayerApiEndpoint = config.relay.relayerApiEndpoint;
|
|
26468
26468
|
this.config = config;
|
|
26469
26469
|
this.hubProvider = hubProvider;
|
|
26470
26470
|
this.spoke = spoke;
|
|
26471
|
+
this.backendApi = backendApi;
|
|
26472
|
+
this.useBackendSubmitTx = useBackendSubmitTx ?? false;
|
|
26471
26473
|
}
|
|
26472
26474
|
/**
|
|
26473
26475
|
* Estimates the gas cost for a raw (unsigned) transaction on a spoke chain.
|
|
@@ -26611,14 +26613,22 @@ var SwapService = class {
|
|
|
26611
26613
|
/**
|
|
26612
26614
|
* Executes a full end-to-end cross-chain swap.
|
|
26613
26615
|
*
|
|
26614
|
-
* Orchestrates the complete swap lifecycle
|
|
26615
|
-
*
|
|
26616
|
-
*
|
|
26617
|
-
*
|
|
26618
|
-
*
|
|
26619
|
-
*
|
|
26620
|
-
*
|
|
26621
|
-
*
|
|
26616
|
+
* Orchestrates the complete swap lifecycle. `createIntent` first submits the intent transaction on
|
|
26617
|
+
* the source spoke chain; completion then runs via one of two paths, both bounded by a single
|
|
26618
|
+
* shared `timeout` budget:
|
|
26619
|
+
*
|
|
26620
|
+
* - **Client-side (default), {@link fallbackSwapSteps}:** verifies the spoke tx landed on-chain,
|
|
26621
|
+
* relays it to the hub (Sonic) and waits for the packet — skipped when `srcChainKey` is the hub,
|
|
26622
|
+
* where the spoke tx already is the hub tx — then calls `postExecution` to notify the solver,
|
|
26623
|
+
* triggering it to fill the intent.
|
|
26624
|
+
* - **Backend 2-step (opt-in via `swapsOptions.useBackendSubmitTx`), {@link submitTx}:** hands the
|
|
26625
|
+
* broadcast tx to the swaps API, which verifies, relays and post-executes server-side, then polls
|
|
26626
|
+
* for completion. On ANY non-success it transparently falls back to the client-side path above —
|
|
26627
|
+
* safe because re-relaying / re-posting an already-processed swap is idempotent (no double-fill).
|
|
26628
|
+
*
|
|
26629
|
+
* @param _params - Swap action params including intent parameters, wallet provider, and an optional
|
|
26630
|
+
* `timeout` — the single shared budget for the whole completion flow (relay/poll plus any
|
|
26631
|
+
* fallback), so total wall-clock never exceeds it.
|
|
26622
26632
|
* @returns A `Result<SwapResponse, SwapError>`. On success:
|
|
26623
26633
|
* - `solverExecutionResponse` — solver acknowledgement (`{ answer: 'OK', intent_hash }`).
|
|
26624
26634
|
* - `intent` — the on-chain intent object that was created.
|
|
@@ -26647,59 +26657,23 @@ var SwapService = class {
|
|
|
26647
26657
|
"swap",
|
|
26648
26658
|
async () => {
|
|
26649
26659
|
try {
|
|
26650
|
-
const timeout = _params.timeout;
|
|
26651
26660
|
const createIntentResult = await this.createIntent(_params);
|
|
26652
26661
|
if (!createIntentResult.ok) {
|
|
26653
26662
|
return { ok: false, error: createIntentResult.error };
|
|
26654
26663
|
}
|
|
26655
|
-
const
|
|
26656
|
-
const
|
|
26657
|
-
|
|
26658
|
-
|
|
26659
|
-
|
|
26660
|
-
|
|
26661
|
-
|
|
26662
|
-
|
|
26663
|
-
|
|
26664
|
-
if (isHubChainKeyType(srcChainKey)) {
|
|
26665
|
-
dstIntentTxHash = spokeTxHash;
|
|
26666
|
-
} else {
|
|
26667
|
-
const packet = await relayTxAndWaitPacket({
|
|
26668
|
-
srcTxHash: spokeTxHash,
|
|
26669
|
-
data: relayData,
|
|
26670
|
-
chainKey: srcChainKey,
|
|
26671
|
-
relayerApiEndpoint: this.relayerApiEndpoint,
|
|
26672
|
-
timeout
|
|
26673
|
-
});
|
|
26674
|
-
if (!packet.ok) {
|
|
26675
|
-
return {
|
|
26676
|
-
ok: false,
|
|
26677
|
-
error: mapRelayFailure(packet.error, { feature: "swap", action: "swap", ...baseCtx })
|
|
26678
|
-
};
|
|
26679
|
-
}
|
|
26680
|
-
dstIntentTxHash = packet.value.dst_tx_hash;
|
|
26681
|
-
}
|
|
26682
|
-
const postExecResult = await this.postExecution({
|
|
26683
|
-
intent_tx_hash: dstIntentTxHash
|
|
26684
|
-
});
|
|
26685
|
-
if (!postExecResult.ok) {
|
|
26686
|
-
return { ok: false, error: postExecResult.error };
|
|
26687
|
-
}
|
|
26688
|
-
return {
|
|
26689
|
-
ok: true,
|
|
26690
|
-
value: {
|
|
26691
|
-
solverExecutionResponse: postExecResult.value,
|
|
26692
|
-
intent,
|
|
26693
|
-
intentDeliveryInfo: {
|
|
26694
|
-
srcChainKey,
|
|
26695
|
-
srcTxHash: spokeTxHash,
|
|
26696
|
-
srcAddress: params.srcAddress,
|
|
26697
|
-
dstChainKey: params.dstChainKey,
|
|
26698
|
-
dstTxHash: dstIntentTxHash,
|
|
26699
|
-
dstAddress: params.dstAddress
|
|
26664
|
+
const created = createIntentResult.value;
|
|
26665
|
+
const deadline = Date.now() + (_params.timeout ?? DEFAULT_RELAY_TX_TIMEOUT);
|
|
26666
|
+
if (this.useBackendSubmitTx) {
|
|
26667
|
+
const submitted = await this.submitTx(_params, created, deadline);
|
|
26668
|
+
if (submitted.ok) return submitted;
|
|
26669
|
+
this.config.logger.warn(
|
|
26670
|
+
"[swap] backend submit-tx did not complete; falling back to the client-side relay",
|
|
26671
|
+
{
|
|
26672
|
+
error: submitted.error
|
|
26700
26673
|
}
|
|
26701
|
-
|
|
26702
|
-
}
|
|
26674
|
+
);
|
|
26675
|
+
}
|
|
26676
|
+
return this.fallbackSwapSteps(_params, created, deadline);
|
|
26703
26677
|
} catch (error) {
|
|
26704
26678
|
if (isSwapError(error)) return { ok: false, error };
|
|
26705
26679
|
return {
|
|
@@ -26725,6 +26699,134 @@ var SwapService = class {
|
|
|
26725
26699
|
}
|
|
26726
26700
|
);
|
|
26727
26701
|
}
|
|
26702
|
+
/**
|
|
26703
|
+
* Client-side swap completion (the default path): relay the broadcast intent tx to the hub — or
|
|
26704
|
+
* use it directly when the source IS the hub — then notify the solver via post-execution and
|
|
26705
|
+
* build the {@link SwapResponse}. Extracted verbatim from `swap()` so the opt-in backend 2-step
|
|
26706
|
+
* path ({@link submitTx}) can fall back to it on any non-success.
|
|
26707
|
+
*/
|
|
26708
|
+
async fallbackSwapSteps(_params, created, deadline) {
|
|
26709
|
+
const { params } = _params;
|
|
26710
|
+
const srcChainKey = params.srcChainKey;
|
|
26711
|
+
const baseCtx = { srcChainKey, dstChainKey: params.dstChainKey };
|
|
26712
|
+
const { tx: spokeTxHash, intent, relayData } = created;
|
|
26713
|
+
const verifyTxHashResult = await this.spoke.verifyTxHash({
|
|
26714
|
+
txHash: created.tx,
|
|
26715
|
+
chainKey: srcChainKey
|
|
26716
|
+
});
|
|
26717
|
+
if (!verifyTxHashResult.ok) {
|
|
26718
|
+
return { ok: false, error: verifyFailed("swap", verifyTxHashResult.error, { ...baseCtx, action: "swap" }) };
|
|
26719
|
+
}
|
|
26720
|
+
let dstIntentTxHash;
|
|
26721
|
+
if (isHubChainKeyType(srcChainKey)) {
|
|
26722
|
+
dstIntentTxHash = spokeTxHash;
|
|
26723
|
+
} else {
|
|
26724
|
+
const packet = await relayTxAndWaitPacket({
|
|
26725
|
+
srcTxHash: spokeTxHash,
|
|
26726
|
+
data: relayData,
|
|
26727
|
+
chainKey: srcChainKey,
|
|
26728
|
+
relayerApiEndpoint: this.relayerApiEndpoint,
|
|
26729
|
+
// Remaining shared budget: ≈ full `timeout` on the flag-off path (called immediately), or
|
|
26730
|
+
// the reserve `submitTx` left on the backend path. Floor keeps a stalled-backend fallback viable.
|
|
26731
|
+
timeout: Math.max(deadline - Date.now(), 5e3)
|
|
26732
|
+
});
|
|
26733
|
+
if (!packet.ok) {
|
|
26734
|
+
return { ok: false, error: mapRelayFailure(packet.error, { feature: "swap", action: "swap", ...baseCtx }) };
|
|
26735
|
+
}
|
|
26736
|
+
dstIntentTxHash = packet.value.dst_tx_hash;
|
|
26737
|
+
}
|
|
26738
|
+
const postExecResult = await this.postExecution({
|
|
26739
|
+
intent_tx_hash: dstIntentTxHash
|
|
26740
|
+
});
|
|
26741
|
+
if (!postExecResult.ok) {
|
|
26742
|
+
return { ok: false, error: postExecResult.error };
|
|
26743
|
+
}
|
|
26744
|
+
return {
|
|
26745
|
+
ok: true,
|
|
26746
|
+
value: {
|
|
26747
|
+
solverExecutionResponse: postExecResult.value,
|
|
26748
|
+
intent,
|
|
26749
|
+
intentDeliveryInfo: {
|
|
26750
|
+
srcChainKey,
|
|
26751
|
+
srcTxHash: spokeTxHash,
|
|
26752
|
+
srcAddress: params.srcAddress,
|
|
26753
|
+
dstChainKey: params.dstChainKey,
|
|
26754
|
+
dstTxHash: dstIntentTxHash,
|
|
26755
|
+
dstAddress: params.dstAddress
|
|
26756
|
+
}
|
|
26757
|
+
}
|
|
26758
|
+
};
|
|
26759
|
+
}
|
|
26760
|
+
/**
|
|
26761
|
+
* Backend 2-step swap path (opt-in via `swapsOptions.useBackendSubmitTx`): hand the broadcast
|
|
26762
|
+
* intent tx to the swaps API (`POST /swaps/submit-tx`); the backend relays + post-executes
|
|
26763
|
+
* server-side. Polls `getSubmitTxStatus` until `executed`, then reconstructs the same
|
|
26764
|
+
* {@link SwapResponse} the client-side path returns (`result.dstIntentTxHash` → delivery info,
|
|
26765
|
+
* `result.intent_hash` → solver response).
|
|
26766
|
+
*
|
|
26767
|
+
* Never throws — returns `{ ok: false }` on any non-success (submit `!ok`, terminal `failed` /
|
|
26768
|
+
* abandoned, or poll timeout) so `swap()` falls back to {@link fallbackSwapSteps}.
|
|
26769
|
+
*
|
|
26770
|
+
* Falling back is safe: re-relaying / re-posting an already-processed swap is idempotent — the
|
|
26771
|
+
* relay dedups and returns the existing `executed` packet, and the solver re-affirms the intent
|
|
26772
|
+
* (no double-fill). Verified live by `e2e-tests/e2e-relay.test.ts`. Polling stops at
|
|
26773
|
+
* `deadline - reserve` so the fallback keeps a guaranteed slice of the shared `swap` budget.
|
|
26774
|
+
*/
|
|
26775
|
+
async submitTx(_params, created, deadline) {
|
|
26776
|
+
const { params } = _params;
|
|
26777
|
+
const srcChainKey = params.srcChainKey;
|
|
26778
|
+
const baseCtx = { srcChainKey, dstChainKey: params.dstChainKey };
|
|
26779
|
+
const { tx: spokeTxHash, intent, relayData } = created;
|
|
26780
|
+
const submitTxFailed = (cause) => ({
|
|
26781
|
+
ok: false,
|
|
26782
|
+
error: executionFailed("swap", cause, { ...baseCtx, action: "swap" })
|
|
26783
|
+
});
|
|
26784
|
+
try {
|
|
26785
|
+
const submitted = await this.backendApi.swaps.submitTx({
|
|
26786
|
+
txHash: spokeTxHash,
|
|
26787
|
+
srcChainKey,
|
|
26788
|
+
walletAddress: params.srcAddress,
|
|
26789
|
+
intent,
|
|
26790
|
+
relayData: relayData.payload
|
|
26791
|
+
});
|
|
26792
|
+
if (!submitted.ok) return submitTxFailed(submitted.error);
|
|
26793
|
+
const reserveMs = Math.min(Math.ceil((deadline - Date.now()) / 3), 2e4);
|
|
26794
|
+
const pollDeadline = deadline - reserveMs;
|
|
26795
|
+
const pollIntervalMs = 1e3;
|
|
26796
|
+
while (Date.now() < pollDeadline) {
|
|
26797
|
+
const statusResult = await this.backendApi.swaps.getSubmitTxStatus({ txHash: spokeTxHash, srcChainKey });
|
|
26798
|
+
if (statusResult.ok) {
|
|
26799
|
+
const { status, result, failureReason, abandonedAt } = statusResult.value.data;
|
|
26800
|
+
if (status === "executed" && result?.dstIntentTxHash && result.intent_hash) {
|
|
26801
|
+
return {
|
|
26802
|
+
ok: true,
|
|
26803
|
+
value: {
|
|
26804
|
+
// Backend serializes the hex intent_hash as a plain string; brand it at the boundary.
|
|
26805
|
+
solverExecutionResponse: { answer: "OK", intent_hash: result.intent_hash },
|
|
26806
|
+
intent,
|
|
26807
|
+
intentDeliveryInfo: {
|
|
26808
|
+
srcChainKey,
|
|
26809
|
+
srcTxHash: spokeTxHash,
|
|
26810
|
+
srcAddress: params.srcAddress,
|
|
26811
|
+
dstChainKey: params.dstChainKey,
|
|
26812
|
+
dstTxHash: result.dstIntentTxHash,
|
|
26813
|
+
dstAddress: params.dstAddress
|
|
26814
|
+
}
|
|
26815
|
+
}
|
|
26816
|
+
};
|
|
26817
|
+
}
|
|
26818
|
+
if (status === "failed" || abandonedAt) {
|
|
26819
|
+
const reason = failureReason ? `: ${failureReason}` : "";
|
|
26820
|
+
return submitTxFailed(new Error(`backend submit-tx ${status}${reason}`));
|
|
26821
|
+
}
|
|
26822
|
+
}
|
|
26823
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
26824
|
+
}
|
|
26825
|
+
return submitTxFailed(new Error("backend submit-tx polling timed out before reaching executed"));
|
|
26826
|
+
} catch (error) {
|
|
26827
|
+
return { ok: false, error: unknownFailed("swap", error, { ...baseCtx, action: "swap" }) };
|
|
26828
|
+
}
|
|
26829
|
+
}
|
|
26728
26830
|
/**
|
|
26729
26831
|
* Checks whether the relevant spender contract is already approved to spend the input token amount.
|
|
26730
26832
|
*
|
|
@@ -29447,71 +29549,883 @@ var MigrationService = class {
|
|
|
29447
29549
|
}
|
|
29448
29550
|
};
|
|
29449
29551
|
|
|
29450
|
-
// src/backendApi/
|
|
29451
|
-
var
|
|
29552
|
+
// src/backendApi/api-utils.ts
|
|
29553
|
+
var toJsonBody = (value) => JSON.stringify(value, (_key, val) => typeof val === "bigint" ? val.toString() : val);
|
|
29554
|
+
async function makeRequest(params) {
|
|
29555
|
+
const { endpoint, config, overrideConfig = {}, logger, serviceLabel } = params;
|
|
29556
|
+
const baseURL = overrideConfig.baseURL || config.baseURL || "";
|
|
29557
|
+
const url = `${baseURL}${endpoint}`;
|
|
29558
|
+
const headers = { ...config.headers, ...overrideConfig.headers };
|
|
29559
|
+
const controller = new AbortController();
|
|
29560
|
+
const timeout = overrideConfig.timeout ?? config.timeout ?? DEFAULT_BACKEND_API_TIMEOUT;
|
|
29561
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
29562
|
+
try {
|
|
29563
|
+
const response = await fetch(url, {
|
|
29564
|
+
method: config.method,
|
|
29565
|
+
headers,
|
|
29566
|
+
body: config.body,
|
|
29567
|
+
signal: controller.signal
|
|
29568
|
+
});
|
|
29569
|
+
clearTimeout(timeoutId);
|
|
29570
|
+
if (!response.ok) {
|
|
29571
|
+
const errorText = await response.text();
|
|
29572
|
+
throw new Error("HTTP_REQUEST_FAILED", { cause: new Error(`HTTP ${response.status}: ${errorText}`) });
|
|
29573
|
+
}
|
|
29574
|
+
const data = await response.json();
|
|
29575
|
+
return data;
|
|
29576
|
+
} catch (error) {
|
|
29577
|
+
clearTimeout(timeoutId);
|
|
29578
|
+
if (error instanceof Error) {
|
|
29579
|
+
if (error.name === "AbortError") {
|
|
29580
|
+
throw new Error("REQUEST_TIMEOUT", { cause: new Error(`Request timeout after ${timeout}ms`) });
|
|
29581
|
+
}
|
|
29582
|
+
logger.error(`[${serviceLabel}] Request error`, error);
|
|
29583
|
+
throw error;
|
|
29584
|
+
}
|
|
29585
|
+
logger.error(`[${serviceLabel}] Unknown error`, error);
|
|
29586
|
+
throw new Error("UNKNOWN_REQUEST_ERROR", { cause: error });
|
|
29587
|
+
}
|
|
29588
|
+
}
|
|
29589
|
+
var SwapTokenSchema = v4__namespace.object({
|
|
29590
|
+
symbol: v4__namespace.string(),
|
|
29591
|
+
name: v4__namespace.string(),
|
|
29592
|
+
decimals: v4__namespace.number(),
|
|
29593
|
+
address: v4__namespace.string(),
|
|
29594
|
+
chainKey: v4__namespace.string(),
|
|
29595
|
+
hubAsset: v4__namespace.string(),
|
|
29596
|
+
vault: v4__namespace.string()
|
|
29597
|
+
});
|
|
29598
|
+
var IntentResponseSchema = v4__namespace.object({
|
|
29599
|
+
intentId: v4__namespace.string(),
|
|
29600
|
+
creator: v4__namespace.string(),
|
|
29601
|
+
inputToken: v4__namespace.string(),
|
|
29602
|
+
outputToken: v4__namespace.string(),
|
|
29603
|
+
inputAmount: v4__namespace.string(),
|
|
29604
|
+
minOutputAmount: v4__namespace.string(),
|
|
29605
|
+
deadline: v4__namespace.string(),
|
|
29606
|
+
allowPartialFill: v4__namespace.boolean(),
|
|
29607
|
+
srcChain: v4__namespace.string(),
|
|
29608
|
+
dstChain: v4__namespace.string(),
|
|
29609
|
+
srcAddress: v4__namespace.string(),
|
|
29610
|
+
dstAddress: v4__namespace.string(),
|
|
29611
|
+
solver: v4__namespace.string(),
|
|
29612
|
+
data: v4__namespace.string()
|
|
29613
|
+
});
|
|
29614
|
+
var RelayExtraDataResponseSchema = v4__namespace.object({
|
|
29615
|
+
address: v4__namespace.string(),
|
|
29616
|
+
payload: v4__namespace.string()
|
|
29617
|
+
});
|
|
29618
|
+
var makeCreateIntentResponseSchema = (txSchema) => v4__namespace.object({
|
|
29619
|
+
tx: txSchema,
|
|
29620
|
+
intent: IntentResponseSchema,
|
|
29621
|
+
relayData: RelayExtraDataResponseSchema
|
|
29622
|
+
});
|
|
29623
|
+
var GetSwapTokensResponseSchema = v4__namespace.record(v4__namespace.string(), v4__namespace.array(SwapTokenSchema));
|
|
29624
|
+
var GetSwapTokensByChainResponseSchema = v4__namespace.array(SwapTokenSchema);
|
|
29625
|
+
var makeQuoteResponseSchema = (txSchema) => v4__namespace.object({
|
|
29626
|
+
quotedAmount: v4__namespace.string(),
|
|
29627
|
+
txData: v4__namespace.optional(makeCreateIntentResponseSchema(txSchema))
|
|
29628
|
+
});
|
|
29629
|
+
var DeadlineResponseSchema = v4__namespace.object({
|
|
29630
|
+
deadline: v4__namespace.string()
|
|
29631
|
+
});
|
|
29632
|
+
var AllowanceCheckResponseSchema = v4__namespace.object({
|
|
29633
|
+
valid: v4__namespace.boolean()
|
|
29634
|
+
});
|
|
29635
|
+
var makeApproveResponseSchema = (txSchema) => v4__namespace.object({ tx: txSchema });
|
|
29636
|
+
var SubmitIntentResponseSchema = v4__namespace.object({
|
|
29637
|
+
result: v4__namespace.unknown()
|
|
29638
|
+
});
|
|
29639
|
+
var StatusResponseSchema = v4__namespace.object({
|
|
29640
|
+
status: v4__namespace.picklist([-1, 1, 2, 3, 4]),
|
|
29641
|
+
fillTxHash: v4__namespace.optional(v4__namespace.string())
|
|
29642
|
+
});
|
|
29643
|
+
var makeCancelIntentResponseSchema = (txSchema) => v4__namespace.object({ tx: txSchema });
|
|
29644
|
+
var IntentHashResponseSchema = v4__namespace.object({
|
|
29645
|
+
hash: v4__namespace.string()
|
|
29646
|
+
});
|
|
29647
|
+
var IntentPacketResponseSchema = v4__namespace.object({
|
|
29648
|
+
srcChainId: v4__namespace.number(),
|
|
29649
|
+
srcTxHash: v4__namespace.string(),
|
|
29650
|
+
srcAddress: v4__namespace.string(),
|
|
29651
|
+
status: v4__namespace.string(),
|
|
29652
|
+
dstChainId: v4__namespace.number(),
|
|
29653
|
+
connSn: v4__namespace.number(),
|
|
29654
|
+
dstAddress: v4__namespace.string(),
|
|
29655
|
+
dstTxHash: v4__namespace.string(),
|
|
29656
|
+
signatures: v4__namespace.array(v4__namespace.string()),
|
|
29657
|
+
payload: v4__namespace.string()
|
|
29658
|
+
});
|
|
29659
|
+
var IntentStateResponseSchema = v4__namespace.object({
|
|
29660
|
+
exists: v4__namespace.boolean(),
|
|
29661
|
+
remainingInput: v4__namespace.string(),
|
|
29662
|
+
receivedOutput: v4__namespace.string(),
|
|
29663
|
+
pendingPayment: v4__namespace.boolean()
|
|
29664
|
+
});
|
|
29665
|
+
var GasEstimateResponseSchema = v4__namespace.object({
|
|
29666
|
+
gas: v4__namespace.unknown()
|
|
29667
|
+
});
|
|
29668
|
+
var FeeResponseSchema = v4__namespace.object({
|
|
29669
|
+
fee: v4__namespace.string()
|
|
29670
|
+
});
|
|
29671
|
+
var SubmitTxResponseSchema = v4__namespace.object({
|
|
29672
|
+
success: v4__namespace.boolean(),
|
|
29673
|
+
data: v4__namespace.object({
|
|
29674
|
+
status: v4__namespace.picklist(["inserted", "duplicate"]),
|
|
29675
|
+
message: v4__namespace.string()
|
|
29676
|
+
})
|
|
29677
|
+
});
|
|
29678
|
+
var SubmitSwapTxStatusSchema = v4__namespace.picklist([
|
|
29679
|
+
"pending",
|
|
29680
|
+
"relaying",
|
|
29681
|
+
"relayed",
|
|
29682
|
+
"posting_execution",
|
|
29683
|
+
"executed",
|
|
29684
|
+
"failed"
|
|
29685
|
+
]);
|
|
29686
|
+
var PacketDataSchema = v4__namespace.object({
|
|
29687
|
+
src_chain_id: v4__namespace.number(),
|
|
29688
|
+
src_tx_hash: v4__namespace.string(),
|
|
29689
|
+
src_address: v4__namespace.string(),
|
|
29690
|
+
status: v4__namespace.picklist(["pending", "validating", "executing", "executed"]),
|
|
29691
|
+
dst_chain_id: v4__namespace.number(),
|
|
29692
|
+
conn_sn: v4__namespace.number(),
|
|
29693
|
+
dst_address: v4__namespace.string(),
|
|
29694
|
+
dst_tx_hash: v4__namespace.string(),
|
|
29695
|
+
signatures: v4__namespace.array(v4__namespace.string()),
|
|
29696
|
+
payload: v4__namespace.string()
|
|
29697
|
+
});
|
|
29698
|
+
var SubmitTxStatusResultSchema = v4__namespace.object({
|
|
29699
|
+
dstIntentTxHash: v4__namespace.string(),
|
|
29700
|
+
packetData: v4__namespace.optional(PacketDataSchema),
|
|
29701
|
+
intent_hash: v4__namespace.optional(v4__namespace.string())
|
|
29702
|
+
});
|
|
29703
|
+
var SubmitTxStatusDataSchema = v4__namespace.object({
|
|
29704
|
+
txHash: v4__namespace.string(),
|
|
29705
|
+
srcChainKey: v4__namespace.string(),
|
|
29706
|
+
status: SubmitSwapTxStatusSchema,
|
|
29707
|
+
failedAtStep: v4__namespace.optional(SubmitSwapTxStatusSchema),
|
|
29708
|
+
failureReason: v4__namespace.optional(v4__namespace.string()),
|
|
29709
|
+
processingAttempts: v4__namespace.number(),
|
|
29710
|
+
abandonedAt: v4__namespace.optional(v4__namespace.string()),
|
|
29711
|
+
result: v4__namespace.optional(SubmitTxStatusResultSchema),
|
|
29712
|
+
userMessage: v4__namespace.optional(v4__namespace.string()),
|
|
29713
|
+
intentCancelled: v4__namespace.optional(v4__namespace.boolean())
|
|
29714
|
+
});
|
|
29715
|
+
var SubmitTxStatusResponseSchema = v4__namespace.object({
|
|
29716
|
+
success: v4__namespace.boolean(),
|
|
29717
|
+
data: SubmitTxStatusDataSchema
|
|
29718
|
+
});
|
|
29719
|
+
var AddressSchema = v4__namespace.custom((input) => typeof input === "string");
|
|
29720
|
+
var HexSchema = v4__namespace.custom((input) => typeof input === "string");
|
|
29721
|
+
var BigintFromString = v4__namespace.pipe(v4__namespace.string(), v4__namespace.toBigint());
|
|
29722
|
+
var BytesFromIndexRecord = v4__namespace.pipe(
|
|
29723
|
+
v4__namespace.record(v4__namespace.string(), v4__namespace.number()),
|
|
29724
|
+
v4__namespace.transform((indexed) => Uint8Array.from(Object.values(indexed)))
|
|
29725
|
+
);
|
|
29726
|
+
var EvmRawTxSchema = v4__namespace.object({
|
|
29727
|
+
from: AddressSchema,
|
|
29728
|
+
to: AddressSchema,
|
|
29729
|
+
value: BigintFromString,
|
|
29730
|
+
data: HexSchema
|
|
29731
|
+
});
|
|
29732
|
+
var SolanaRawTxSchema = v4__namespace.object({
|
|
29733
|
+
from: v4__namespace.string(),
|
|
29734
|
+
to: v4__namespace.string(),
|
|
29735
|
+
value: BigintFromString,
|
|
29736
|
+
data: v4__namespace.string()
|
|
29737
|
+
});
|
|
29738
|
+
var SuiRawTxSchema = v4__namespace.object({
|
|
29739
|
+
from: HexSchema,
|
|
29740
|
+
to: v4__namespace.string(),
|
|
29741
|
+
value: BigintFromString,
|
|
29742
|
+
data: v4__namespace.string()
|
|
29743
|
+
});
|
|
29744
|
+
var StellarRawTxSchema = v4__namespace.object({
|
|
29745
|
+
from: v4__namespace.string(),
|
|
29746
|
+
to: v4__namespace.string(),
|
|
29747
|
+
value: BigintFromString,
|
|
29748
|
+
data: v4__namespace.string()
|
|
29749
|
+
});
|
|
29750
|
+
var InjectiveRawTxSchema = v4__namespace.object({
|
|
29751
|
+
from: HexSchema,
|
|
29752
|
+
to: HexSchema,
|
|
29753
|
+
signedDoc: v4__namespace.object({
|
|
29754
|
+
bodyBytes: BytesFromIndexRecord,
|
|
29755
|
+
authInfoBytes: BytesFromIndexRecord,
|
|
29756
|
+
chainId: v4__namespace.string(),
|
|
29757
|
+
accountNumber: BigintFromString
|
|
29758
|
+
})
|
|
29759
|
+
});
|
|
29760
|
+
var NearRawTxSchema = v4__namespace.object({
|
|
29761
|
+
signerId: v4__namespace.string(),
|
|
29762
|
+
params: v4__namespace.object({
|
|
29763
|
+
contractId: v4__namespace.string(),
|
|
29764
|
+
method: v4__namespace.string(),
|
|
29765
|
+
args: v4__namespace.custom((input) => typeof input === "object" && input !== null),
|
|
29766
|
+
gas: v4__namespace.optional(BigintFromString),
|
|
29767
|
+
deposit: v4__namespace.optional(BigintFromString)
|
|
29768
|
+
})
|
|
29769
|
+
});
|
|
29770
|
+
var IconRawTxSchema = v4__namespace.record(
|
|
29771
|
+
v4__namespace.string(),
|
|
29772
|
+
v4__namespace.union([v4__namespace.string(), v4__namespace.custom((input) => typeof input === "object" && input !== null)])
|
|
29773
|
+
);
|
|
29774
|
+
var StacksRawTxSchema = v4__namespace.object({
|
|
29775
|
+
payload: v4__namespace.string(),
|
|
29776
|
+
estimatedLength: v4__namespace.optional(v4__namespace.number())
|
|
29777
|
+
});
|
|
29778
|
+
var AnyRawTxSchema = v4__namespace.custom((input) => typeof input === "object" && input !== null);
|
|
29779
|
+
function rawTxSchemaForChainKey(chainKey) {
|
|
29780
|
+
let chainType;
|
|
29781
|
+
try {
|
|
29782
|
+
chainType = getChainType(chainKey);
|
|
29783
|
+
} catch {
|
|
29784
|
+
chainType = void 0;
|
|
29785
|
+
}
|
|
29786
|
+
switch (chainType) {
|
|
29787
|
+
case "EVM":
|
|
29788
|
+
return EvmRawTxSchema;
|
|
29789
|
+
case "SOLANA":
|
|
29790
|
+
return SolanaRawTxSchema;
|
|
29791
|
+
case "SUI":
|
|
29792
|
+
return SuiRawTxSchema;
|
|
29793
|
+
case "STELLAR":
|
|
29794
|
+
return StellarRawTxSchema;
|
|
29795
|
+
case "INJECTIVE":
|
|
29796
|
+
return InjectiveRawTxSchema;
|
|
29797
|
+
case "ICON":
|
|
29798
|
+
return IconRawTxSchema;
|
|
29799
|
+
case "STACKS":
|
|
29800
|
+
return StacksRawTxSchema;
|
|
29801
|
+
case "NEAR":
|
|
29802
|
+
return NearRawTxSchema;
|
|
29803
|
+
default:
|
|
29804
|
+
return AnyRawTxSchema;
|
|
29805
|
+
}
|
|
29806
|
+
}
|
|
29807
|
+
|
|
29808
|
+
// src/backendApi/SwapsApiService.ts
|
|
29809
|
+
var SwapsApiService = class {
|
|
29810
|
+
// Fully-resolved swaps-API config supplied by the caller (BackendApiService resolves the
|
|
29811
|
+
// `ApiConfig` union via `resolveSwapsApiConfig`); this service does not resolve the union.
|
|
29812
|
+
config;
|
|
29813
|
+
headers;
|
|
29814
|
+
logger;
|
|
29452
29815
|
constructor(config, logger = consoleLogger) {
|
|
29453
29816
|
this.config = config;
|
|
29454
29817
|
this.headers = { ...config.headers };
|
|
29455
29818
|
this.logger = logger;
|
|
29456
29819
|
}
|
|
29457
|
-
headers;
|
|
29458
|
-
logger;
|
|
29459
29820
|
/**
|
|
29460
|
-
*
|
|
29461
|
-
*
|
|
29462
|
-
*
|
|
29463
|
-
*
|
|
29464
|
-
* request exceeds the timeout, so callers should use {@link request} instead of
|
|
29465
|
-
* calling this directly.
|
|
29466
|
-
*
|
|
29467
|
-
* @throws `Error('HTTP_REQUEST_FAILED')` on non-2xx responses.
|
|
29468
|
-
* @throws `Error('REQUEST_TIMEOUT')` when the request exceeds the timeout.
|
|
29469
|
-
* @throws `Error('UNKNOWN_REQUEST_ERROR')` for any other unexpected failure.
|
|
29821
|
+
* Issues a single HTTP request, validates the JSON body against `schema`, and
|
|
29822
|
+
* wraps the result in `Result<T>`. The service-level `baseURL`/`timeout`/
|
|
29823
|
+
* `headers` are merged with the optional per-call `overrideConfig` (which takes
|
|
29824
|
+
* precedence) inside {@link makeRequest}. Every public method delegates here.
|
|
29470
29825
|
*/
|
|
29471
|
-
async
|
|
29472
|
-
const url = config.baseURL ? `${config.baseURL}${endpoint}` : `${this.config.baseURL}${endpoint}`;
|
|
29473
|
-
const headers = { ...this.headers, ...config.headers };
|
|
29474
|
-
const controller = new AbortController();
|
|
29475
|
-
const timeout = config.timeout ?? this.config.timeout;
|
|
29476
|
-
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
29826
|
+
async request(endpoint, config, schema, overrideConfig) {
|
|
29477
29827
|
try {
|
|
29478
|
-
const
|
|
29479
|
-
|
|
29480
|
-
headers,
|
|
29481
|
-
|
|
29482
|
-
|
|
29828
|
+
const raw = await makeRequest({
|
|
29829
|
+
endpoint,
|
|
29830
|
+
config: { baseURL: this.config.baseURL, timeout: this.config.timeout, headers: this.headers, ...config },
|
|
29831
|
+
overrideConfig,
|
|
29832
|
+
logger: this.logger,
|
|
29833
|
+
serviceLabel: "SwapsApiService"
|
|
29483
29834
|
});
|
|
29484
|
-
|
|
29485
|
-
if (!
|
|
29486
|
-
|
|
29487
|
-
|
|
29835
|
+
const parsed = v4__namespace.safeParse(schema, raw);
|
|
29836
|
+
if (!parsed.success) {
|
|
29837
|
+
return {
|
|
29838
|
+
ok: false,
|
|
29839
|
+
error: new SodaxError("EXTERNAL_API_ERROR", `Invalid response shape from swaps API for ${endpoint}`, {
|
|
29840
|
+
feature: "backend",
|
|
29841
|
+
context: { api: "swaps", endpoint, reason: "invalid_response_shape", issues: v4__namespace.flatten(parsed.issues) }
|
|
29842
|
+
})
|
|
29843
|
+
};
|
|
29488
29844
|
}
|
|
29489
|
-
|
|
29490
|
-
return data;
|
|
29845
|
+
return { ok: true, value: parsed.output };
|
|
29491
29846
|
} catch (error) {
|
|
29492
|
-
|
|
29493
|
-
|
|
29494
|
-
|
|
29495
|
-
|
|
29496
|
-
|
|
29497
|
-
|
|
29498
|
-
|
|
29499
|
-
|
|
29500
|
-
|
|
29501
|
-
|
|
29847
|
+
return {
|
|
29848
|
+
ok: false,
|
|
29849
|
+
error: new SodaxError(
|
|
29850
|
+
"EXTERNAL_API_ERROR",
|
|
29851
|
+
error instanceof Error ? error.message : `Request to ${endpoint} failed`,
|
|
29852
|
+
{
|
|
29853
|
+
feature: "backend",
|
|
29854
|
+
cause: error,
|
|
29855
|
+
context: { api: "swaps", endpoint }
|
|
29856
|
+
}
|
|
29857
|
+
)
|
|
29858
|
+
};
|
|
29502
29859
|
}
|
|
29503
29860
|
}
|
|
29861
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
29862
|
+
// Tokens
|
|
29863
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
29864
|
+
/**
|
|
29865
|
+
* Fetch all supported swap tokens grouped by SpokeChainKey.
|
|
29866
|
+
*
|
|
29867
|
+
* @returns `Result<GetSwapTokensResponseV2>` — map of chain key → token list.
|
|
29868
|
+
*/
|
|
29869
|
+
async getTokens(config) {
|
|
29870
|
+
return this.request("/swaps/tokens", { method: "GET" }, GetSwapTokensResponseSchema, config);
|
|
29871
|
+
}
|
|
29872
|
+
/**
|
|
29873
|
+
* Fetch supported swap tokens for a single SpokeChainKey.
|
|
29874
|
+
*
|
|
29875
|
+
* @param chainKey - SODAX SpokeChainKey (e.g. `0xa4b1.arbitrum`, `solana`).
|
|
29876
|
+
* @returns `Result<GetSwapTokensByChainResponseV2>` — token list for the chain.
|
|
29877
|
+
*/
|
|
29878
|
+
async getTokensByChain(chainKey, config) {
|
|
29879
|
+
return this.request(
|
|
29880
|
+
`/swaps/tokens/${chainKey}`,
|
|
29881
|
+
{ method: "GET" },
|
|
29882
|
+
GetSwapTokensByChainResponseSchema,
|
|
29883
|
+
config
|
|
29884
|
+
);
|
|
29885
|
+
}
|
|
29886
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
29887
|
+
// Quote · deadline
|
|
29888
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
29889
|
+
/**
|
|
29890
|
+
* Get a solver quote for a cross-chain swap.
|
|
29891
|
+
*
|
|
29892
|
+
* Pass `query.includeTxData = true` to also build an unsigned create-intent
|
|
29893
|
+
* transaction (`txData`) using the quoted amount as `minOutputAmount`; in that
|
|
29894
|
+
* case `srcAddress`/`dstAddress` are required in the body.
|
|
29895
|
+
*
|
|
29896
|
+
* @returns `Result<QuoteResponseV2>` — `quotedAmount` (decimal string) and optional `txData`.
|
|
29897
|
+
*/
|
|
29898
|
+
async getQuote(body, query, config) {
|
|
29899
|
+
const endpoint = query?.includeTxData ? "/swaps/quote?includeTxData=true" : "/swaps/quote";
|
|
29900
|
+
const txSchema = rawTxSchemaForChainKey(body.tokenSrcChainKey);
|
|
29901
|
+
return this.request(
|
|
29902
|
+
endpoint,
|
|
29903
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
29904
|
+
makeQuoteResponseSchema(txSchema),
|
|
29905
|
+
config
|
|
29906
|
+
);
|
|
29907
|
+
}
|
|
29908
|
+
/**
|
|
29909
|
+
* Compute a swap deadline (hub timestamp + `offsetSeconds`, default 300s).
|
|
29910
|
+
*
|
|
29911
|
+
* @returns `Result<DeadlineResponseV2>` — unix-seconds deadline (decimal string).
|
|
29912
|
+
*/
|
|
29913
|
+
async getDeadline(query, config) {
|
|
29914
|
+
const queryParams = new URLSearchParams();
|
|
29915
|
+
if (query?.offsetSeconds !== void 0) queryParams.append("offsetSeconds", String(query.offsetSeconds));
|
|
29916
|
+
const queryString = queryParams.toString();
|
|
29917
|
+
const endpoint = queryString.length > 0 ? `/swaps/deadline?${queryString}` : "/swaps/deadline";
|
|
29918
|
+
return this.request(endpoint, { method: "GET" }, DeadlineResponseSchema, config);
|
|
29919
|
+
}
|
|
29920
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
29921
|
+
// Allowance · approve · create intent
|
|
29922
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
29923
|
+
/**
|
|
29924
|
+
* Check whether the source token allowance is already sufficient for the intent.
|
|
29925
|
+
*
|
|
29926
|
+
* @returns `Result<AllowanceCheckResponseV2>` — `{ valid }`.
|
|
29927
|
+
*/
|
|
29928
|
+
async checkAllowance(body, config) {
|
|
29929
|
+
return this.request(
|
|
29930
|
+
"/swaps/allowance/check",
|
|
29931
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
29932
|
+
AllowanceCheckResponseSchema,
|
|
29933
|
+
config
|
|
29934
|
+
);
|
|
29935
|
+
}
|
|
29936
|
+
/**
|
|
29937
|
+
* Build an unsigned token-approval transaction for the source token.
|
|
29938
|
+
*
|
|
29939
|
+
* @returns `Result<ApproveResponseV2>` — `{ tx }` (chain-specific unsigned tx).
|
|
29940
|
+
*/
|
|
29941
|
+
async approve(body, config) {
|
|
29942
|
+
const txSchema = rawTxSchemaForChainKey(body.srcChainKey);
|
|
29943
|
+
return this.request(
|
|
29944
|
+
"/swaps/approve",
|
|
29945
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
29946
|
+
makeApproveResponseSchema(txSchema),
|
|
29947
|
+
config
|
|
29948
|
+
);
|
|
29949
|
+
}
|
|
29950
|
+
/**
|
|
29951
|
+
* Build an unsigned create-intent transaction.
|
|
29952
|
+
*
|
|
29953
|
+
* @returns `Result<CreateIntentResponseV2>` — `{ tx, intent, relayData }`.
|
|
29954
|
+
*/
|
|
29955
|
+
async createIntent(body, config) {
|
|
29956
|
+
const txSchema = rawTxSchemaForChainKey(body.srcChainKey);
|
|
29957
|
+
return this.request(
|
|
29958
|
+
"/swaps/intents",
|
|
29959
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
29960
|
+
makeCreateIntentResponseSchema(txSchema),
|
|
29961
|
+
config
|
|
29962
|
+
);
|
|
29963
|
+
}
|
|
29964
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
29965
|
+
// Intent lifecycle: submit · status · cancel · hash · packet · extra-data
|
|
29966
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
29967
|
+
/**
|
|
29968
|
+
* Submit the broadcast intent tx to the relay.
|
|
29969
|
+
*
|
|
29970
|
+
* @returns `Result<SubmitIntentResponseV2>` — `{ result }` (opaque relay response).
|
|
29971
|
+
*/
|
|
29972
|
+
async submitIntent(body, config) {
|
|
29973
|
+
return this.request(
|
|
29974
|
+
"/swaps/intents/submit",
|
|
29975
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
29976
|
+
SubmitIntentResponseSchema,
|
|
29977
|
+
config
|
|
29978
|
+
);
|
|
29979
|
+
}
|
|
29980
|
+
/**
|
|
29981
|
+
* Poll the solver for intent execution status.
|
|
29982
|
+
*
|
|
29983
|
+
* @returns `Result<StatusResponseV2>` — `{ status, fillTxHash? }` (`fillTxHash` set when `status === 3`).
|
|
29984
|
+
*/
|
|
29985
|
+
async getStatus(body, config) {
|
|
29986
|
+
return this.request(
|
|
29987
|
+
"/swaps/intents/status",
|
|
29988
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
29989
|
+
StatusResponseSchema,
|
|
29990
|
+
config
|
|
29991
|
+
);
|
|
29992
|
+
}
|
|
29993
|
+
/**
|
|
29994
|
+
* Build an unsigned cancel-intent transaction. The `intent` field carries
|
|
29995
|
+
* `bigint` numerics — {@link toJsonBody} serializes them to decimal strings.
|
|
29996
|
+
*
|
|
29997
|
+
* @returns `Result<CancelIntentResponseV2>` — `{ tx }`.
|
|
29998
|
+
*/
|
|
29999
|
+
async cancelIntent(body, config) {
|
|
30000
|
+
const txSchema = rawTxSchemaForChainKey(body.srcChainKey);
|
|
30001
|
+
return this.request(
|
|
30002
|
+
"/swaps/intents/cancel",
|
|
30003
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
30004
|
+
makeCancelIntentResponseSchema(txSchema),
|
|
30005
|
+
config
|
|
30006
|
+
);
|
|
30007
|
+
}
|
|
30008
|
+
/**
|
|
30009
|
+
* Compute the keccak256 hash of an Intent struct. The `intent` field carries
|
|
30010
|
+
* `bigint` numerics — {@link toJsonBody} serializes them to decimal strings.
|
|
30011
|
+
*
|
|
30012
|
+
* @returns `Result<IntentHashResponseV2>` — `{ hash }`.
|
|
30013
|
+
*/
|
|
30014
|
+
async getIntentHash(body, config) {
|
|
30015
|
+
return this.request(
|
|
30016
|
+
"/swaps/intents/hash",
|
|
30017
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
30018
|
+
IntentHashResponseSchema,
|
|
30019
|
+
config
|
|
30020
|
+
);
|
|
30021
|
+
}
|
|
30022
|
+
/**
|
|
30023
|
+
* Long-poll the relayer until the fill packet lands on the destination chain.
|
|
30024
|
+
*
|
|
30025
|
+
* @returns `Result<IntentPacketResponseV2>` — delivered packet data.
|
|
30026
|
+
*/
|
|
30027
|
+
async getSolvedIntentPacket(body, config) {
|
|
30028
|
+
return this.request(
|
|
30029
|
+
"/swaps/intents/packet",
|
|
30030
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
30031
|
+
IntentPacketResponseSchema,
|
|
30032
|
+
config
|
|
30033
|
+
);
|
|
30034
|
+
}
|
|
30035
|
+
/**
|
|
30036
|
+
* Recover the relay extra data needed by `/swaps/intents/submit`. Provide
|
|
30037
|
+
* EITHER `txHash` OR `intent` (whose `bigint` numerics {@link toJsonBody} serializes).
|
|
30038
|
+
*
|
|
30039
|
+
* @returns `Result<IntentExtraDataResponseV2>` — `{ address, payload }`.
|
|
30040
|
+
*/
|
|
30041
|
+
async getIntentSubmitTxExtraData(body, config) {
|
|
30042
|
+
return this.request(
|
|
30043
|
+
"/swaps/intents/extra-data",
|
|
30044
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
30045
|
+
RelayExtraDataResponseSchema,
|
|
30046
|
+
config
|
|
30047
|
+
);
|
|
30048
|
+
}
|
|
30049
|
+
/**
|
|
30050
|
+
* Get the on-chain fill state for an intent by its hub-chain tx hash.
|
|
30051
|
+
*
|
|
30052
|
+
* @returns `Result<IntentStateV2>` — `{ exists, remainingInput, receivedOutput, pendingPayment }`.
|
|
30053
|
+
*/
|
|
30054
|
+
async getFilledIntent(txHash, config) {
|
|
30055
|
+
return this.request(`/swaps/intents/${txHash}/fill`, { method: "GET" }, IntentStateResponseSchema, config);
|
|
30056
|
+
}
|
|
30057
|
+
/**
|
|
30058
|
+
* Look up an Intent struct by its hub-chain creation tx hash.
|
|
30059
|
+
*
|
|
30060
|
+
* @returns `Result<GetIntentResponseV2>` — the decoded intent (bigint fields as decimal strings).
|
|
30061
|
+
*/
|
|
30062
|
+
async getIntent(txHash, config) {
|
|
30063
|
+
return this.request(`/swaps/intents/${txHash}`, { method: "GET" }, IntentResponseSchema, config);
|
|
30064
|
+
}
|
|
30065
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
30066
|
+
// Limit orders · gas · fees
|
|
30067
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
30068
|
+
/**
|
|
30069
|
+
* Build an unsigned create-limit-order-intent transaction (same as create-intent
|
|
30070
|
+
* but `deadline` is optional).
|
|
30071
|
+
*
|
|
30072
|
+
* @returns `Result<CreateLimitOrderResponseV2>` — `{ tx, intent, relayData }`.
|
|
30073
|
+
*/
|
|
30074
|
+
async createLimitOrderIntent(body, config) {
|
|
30075
|
+
const txSchema = rawTxSchemaForChainKey(body.srcChainKey);
|
|
30076
|
+
return this.request(
|
|
30077
|
+
"/swaps/limit-orders",
|
|
30078
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
30079
|
+
makeCreateIntentResponseSchema(txSchema),
|
|
30080
|
+
config
|
|
30081
|
+
);
|
|
30082
|
+
}
|
|
30083
|
+
/**
|
|
30084
|
+
* Estimate gas for a raw transaction on a spoke chain.
|
|
30085
|
+
*
|
|
30086
|
+
* @returns `Result<GasEstimateResponseV2>` — `{ gas }` (chain-specific shape).
|
|
30087
|
+
*/
|
|
30088
|
+
async estimateGas(body, config) {
|
|
30089
|
+
return this.request(
|
|
30090
|
+
"/swaps/gas/estimate",
|
|
30091
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
30092
|
+
GasEstimateResponseSchema,
|
|
30093
|
+
config
|
|
30094
|
+
);
|
|
30095
|
+
}
|
|
30096
|
+
/**
|
|
30097
|
+
* Compute the partner fee for a given input amount.
|
|
30098
|
+
*
|
|
30099
|
+
* @returns `Result<FeeResponseV2>` — `{ fee }` (decimal string).
|
|
30100
|
+
*/
|
|
30101
|
+
async getPartnerFee(query, config) {
|
|
30102
|
+
const queryParams = new URLSearchParams({ amount: query.amount });
|
|
30103
|
+
return this.request(
|
|
30104
|
+
`/swaps/fees/partner?${queryParams.toString()}`,
|
|
30105
|
+
{ method: "GET" },
|
|
30106
|
+
FeeResponseSchema,
|
|
30107
|
+
config
|
|
30108
|
+
);
|
|
30109
|
+
}
|
|
30110
|
+
/**
|
|
30111
|
+
* Compute the protocol (solver) fee for a given input amount.
|
|
30112
|
+
*
|
|
30113
|
+
* @returns `Result<FeeResponseV2>` — `{ fee }` (decimal string).
|
|
30114
|
+
*/
|
|
30115
|
+
async getSolverFee(query, config) {
|
|
30116
|
+
const queryParams = new URLSearchParams({ amount: query.amount });
|
|
30117
|
+
return this.request(
|
|
30118
|
+
`/swaps/fees/solver?${queryParams.toString()}`,
|
|
30119
|
+
{ method: "GET" },
|
|
30120
|
+
FeeResponseSchema,
|
|
30121
|
+
config
|
|
30122
|
+
);
|
|
30123
|
+
}
|
|
30124
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
30125
|
+
// Submit-tx state machine
|
|
30126
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
30127
|
+
/**
|
|
30128
|
+
* Submit a swap transaction to be processed (relay, post-execution, etc.). The
|
|
30129
|
+
* `intent` field carries `bigint` numerics — {@link toJsonBody} serializes them.
|
|
30130
|
+
* Idempotent on `(txHash, srcChainKey)`.
|
|
30131
|
+
*
|
|
30132
|
+
* @returns `Result<SubmitTxResponseV2>` — `{ success, data: { status, message } }`.
|
|
30133
|
+
*/
|
|
30134
|
+
async submitTx(body, config) {
|
|
30135
|
+
return this.request(
|
|
30136
|
+
"/swaps/submit-tx",
|
|
30137
|
+
{ method: "POST", body: toJsonBody(body) },
|
|
30138
|
+
SubmitTxResponseSchema,
|
|
30139
|
+
config
|
|
30140
|
+
);
|
|
30141
|
+
}
|
|
30142
|
+
/**
|
|
30143
|
+
* Get the processing status of a submitted swap transaction by `(txHash, srcChainKey)`.
|
|
30144
|
+
*
|
|
30145
|
+
* @returns `Result<SubmitTxStatusResponseV2>` — `{ success, data }` (processing state).
|
|
30146
|
+
*/
|
|
30147
|
+
async getSubmitTxStatus(query, config) {
|
|
30148
|
+
const queryParams = new URLSearchParams({ txHash: query.txHash, srcChainKey: query.srcChainKey });
|
|
30149
|
+
return this.request(
|
|
30150
|
+
`/swaps/submit-tx/status?${queryParams.toString()}`,
|
|
30151
|
+
{ method: "GET" },
|
|
30152
|
+
SubmitTxStatusResponseSchema,
|
|
30153
|
+
config
|
|
30154
|
+
);
|
|
30155
|
+
}
|
|
30156
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
30157
|
+
// Utilities (parity with BackendApiService)
|
|
30158
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
30159
|
+
/**
|
|
30160
|
+
* Merge additional headers into the service's default header set. Existing
|
|
30161
|
+
* keys are overwritten; keys absent from `headers` are preserved.
|
|
30162
|
+
*/
|
|
30163
|
+
setHeaders(headers) {
|
|
30164
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
30165
|
+
this.headers[key] = value;
|
|
30166
|
+
});
|
|
30167
|
+
}
|
|
30168
|
+
/** Return the base URL the service is currently pointing at. */
|
|
30169
|
+
getBaseURL() {
|
|
30170
|
+
return this.config.baseURL;
|
|
30171
|
+
}
|
|
30172
|
+
};
|
|
30173
|
+
|
|
30174
|
+
// src/backendApi/apiConfig.ts
|
|
30175
|
+
function isCustomApiConfig(config) {
|
|
30176
|
+
return "baseApiConfig" in config || "swapsApiConfig" in config;
|
|
30177
|
+
}
|
|
30178
|
+
function layerConfigs(...slices) {
|
|
30179
|
+
return slices.reduce(
|
|
30180
|
+
(acc, slice) => slice ? {
|
|
30181
|
+
baseURL: slice.baseURL ?? acc.baseURL,
|
|
30182
|
+
timeout: slice.timeout ?? acc.timeout,
|
|
30183
|
+
headers: { ...acc.headers, ...slice.headers }
|
|
30184
|
+
} : acc,
|
|
30185
|
+
{
|
|
30186
|
+
baseURL: DEFAULT_BACKEND_API_ENDPOINT,
|
|
30187
|
+
timeout: DEFAULT_BACKEND_API_TIMEOUT,
|
|
30188
|
+
headers: { ...DEFAULT_BACKEND_API_HEADERS }
|
|
30189
|
+
}
|
|
30190
|
+
);
|
|
30191
|
+
}
|
|
30192
|
+
function resolveBaseApiConfig(config) {
|
|
30193
|
+
if (isCustomApiConfig(config)) {
|
|
30194
|
+
return layerConfigs(config.baseApiConfig);
|
|
30195
|
+
}
|
|
30196
|
+
return layerConfigs(config);
|
|
30197
|
+
}
|
|
30198
|
+
function resolveSwapsApiConfig(config) {
|
|
30199
|
+
if (isCustomApiConfig(config)) {
|
|
30200
|
+
return layerConfigs(config.baseApiConfig, config.swapsApiConfig);
|
|
30201
|
+
}
|
|
30202
|
+
return layerConfigs(config);
|
|
30203
|
+
}
|
|
30204
|
+
var ChainKeySchema = v4__namespace.custom((input) => typeof input === "string");
|
|
30205
|
+
var SpokeChainKeySchema = v4__namespace.custom((input) => typeof input === "string");
|
|
30206
|
+
var AddressSchema2 = v4__namespace.custom((input) => typeof input === "string");
|
|
30207
|
+
var XTokenSchema = v4__namespace.object({
|
|
30208
|
+
symbol: v4__namespace.string(),
|
|
30209
|
+
name: v4__namespace.string(),
|
|
30210
|
+
decimals: v4__namespace.number(),
|
|
30211
|
+
address: v4__namespace.string(),
|
|
30212
|
+
chainKey: ChainKeySchema,
|
|
30213
|
+
hubAsset: AddressSchema2,
|
|
30214
|
+
vault: AddressSchema2,
|
|
30215
|
+
access: v4__namespace.optional(v4__namespace.picklist(["withdrawOnly", "depositOnly"]))
|
|
30216
|
+
});
|
|
30217
|
+
var IntentStructSchema = v4__namespace.object({
|
|
30218
|
+
intentId: v4__namespace.string(),
|
|
30219
|
+
creator: v4__namespace.string(),
|
|
30220
|
+
inputToken: v4__namespace.string(),
|
|
30221
|
+
outputToken: v4__namespace.string(),
|
|
30222
|
+
inputAmount: v4__namespace.string(),
|
|
30223
|
+
minOutputAmount: v4__namespace.string(),
|
|
30224
|
+
deadline: v4__namespace.string(),
|
|
30225
|
+
allowPartialFill: v4__namespace.boolean(),
|
|
30226
|
+
srcChain: v4__namespace.number(),
|
|
30227
|
+
dstChain: v4__namespace.number(),
|
|
30228
|
+
srcAddress: v4__namespace.string(),
|
|
30229
|
+
dstAddress: v4__namespace.string(),
|
|
30230
|
+
solver: v4__namespace.string(),
|
|
30231
|
+
data: v4__namespace.string()
|
|
30232
|
+
});
|
|
30233
|
+
var IntentResponseSchema2 = v4__namespace.object({
|
|
30234
|
+
intentHash: v4__namespace.string(),
|
|
30235
|
+
txHash: v4__namespace.string(),
|
|
30236
|
+
logIndex: v4__namespace.number(),
|
|
30237
|
+
chainId: v4__namespace.number(),
|
|
30238
|
+
blockNumber: v4__namespace.number(),
|
|
30239
|
+
open: v4__namespace.boolean(),
|
|
30240
|
+
intent: IntentStructSchema,
|
|
30241
|
+
events: v4__namespace.array(v4__namespace.unknown())
|
|
30242
|
+
});
|
|
30243
|
+
var UserIntentsResponseSchema = v4__namespace.object({
|
|
30244
|
+
total: v4__namespace.number(),
|
|
30245
|
+
offset: v4__namespace.number(),
|
|
30246
|
+
limit: v4__namespace.number(),
|
|
30247
|
+
items: v4__namespace.array(IntentResponseSchema2)
|
|
30248
|
+
});
|
|
30249
|
+
var OrderbookResponseSchema = v4__namespace.object({
|
|
30250
|
+
total: v4__namespace.number(),
|
|
30251
|
+
data: v4__namespace.array(
|
|
30252
|
+
v4__namespace.object({
|
|
30253
|
+
intentState: v4__namespace.object({
|
|
30254
|
+
exists: v4__namespace.boolean(),
|
|
30255
|
+
remainingInput: v4__namespace.string(),
|
|
30256
|
+
receivedOutput: v4__namespace.string(),
|
|
30257
|
+
pendingPayment: v4__namespace.boolean()
|
|
30258
|
+
}),
|
|
30259
|
+
intentData: v4__namespace.object({
|
|
30260
|
+
intentId: v4__namespace.string(),
|
|
30261
|
+
creator: v4__namespace.string(),
|
|
30262
|
+
inputToken: v4__namespace.string(),
|
|
30263
|
+
outputToken: v4__namespace.string(),
|
|
30264
|
+
inputAmount: v4__namespace.string(),
|
|
30265
|
+
minOutputAmount: v4__namespace.string(),
|
|
30266
|
+
deadline: v4__namespace.string(),
|
|
30267
|
+
allowPartialFill: v4__namespace.boolean(),
|
|
30268
|
+
srcChain: v4__namespace.number(),
|
|
30269
|
+
dstChain: v4__namespace.number(),
|
|
30270
|
+
srcAddress: v4__namespace.string(),
|
|
30271
|
+
dstAddress: v4__namespace.string(),
|
|
30272
|
+
solver: v4__namespace.string(),
|
|
30273
|
+
data: v4__namespace.string(),
|
|
30274
|
+
intentHash: v4__namespace.string(),
|
|
30275
|
+
txHash: v4__namespace.string(),
|
|
30276
|
+
blockNumber: v4__namespace.number()
|
|
30277
|
+
})
|
|
30278
|
+
})
|
|
30279
|
+
)
|
|
30280
|
+
});
|
|
30281
|
+
var MoneyMarketPositionSchema = v4__namespace.object({
|
|
30282
|
+
userAddress: v4__namespace.string(),
|
|
30283
|
+
positions: v4__namespace.array(
|
|
30284
|
+
v4__namespace.object({
|
|
30285
|
+
reserveAddress: v4__namespace.string(),
|
|
30286
|
+
aTokenAddress: v4__namespace.string(),
|
|
30287
|
+
variableDebtTokenAddress: v4__namespace.string(),
|
|
30288
|
+
aTokenBalance: v4__namespace.string(),
|
|
30289
|
+
variableDebtTokenBalance: v4__namespace.string(),
|
|
30290
|
+
blockNumber: v4__namespace.number()
|
|
30291
|
+
})
|
|
30292
|
+
)
|
|
30293
|
+
});
|
|
30294
|
+
var MoneyMarketAssetSchema = v4__namespace.object({
|
|
30295
|
+
reserveAddress: v4__namespace.string(),
|
|
30296
|
+
aTokenAddress: v4__namespace.string(),
|
|
30297
|
+
totalATokenBalance: v4__namespace.string(),
|
|
30298
|
+
variableDebtTokenAddress: v4__namespace.string(),
|
|
30299
|
+
totalVariableDebtTokenBalance: v4__namespace.string(),
|
|
30300
|
+
liquidityRate: v4__namespace.string(),
|
|
30301
|
+
symbol: v4__namespace.string(),
|
|
30302
|
+
totalSuppliers: v4__namespace.number(),
|
|
30303
|
+
totalBorrowers: v4__namespace.number(),
|
|
30304
|
+
variableBorrowRate: v4__namespace.string(),
|
|
30305
|
+
stableBorrowRate: v4__namespace.string(),
|
|
30306
|
+
liquidityIndex: v4__namespace.string(),
|
|
30307
|
+
variableBorrowIndex: v4__namespace.string(),
|
|
30308
|
+
blockNumber: v4__namespace.number()
|
|
30309
|
+
});
|
|
30310
|
+
var MoneyMarketAssetsSchema = v4__namespace.array(MoneyMarketAssetSchema);
|
|
30311
|
+
var MoneyMarketAssetBorrowersSchema = v4__namespace.object({
|
|
30312
|
+
borrowers: v4__namespace.array(v4__namespace.string()),
|
|
30313
|
+
total: v4__namespace.number(),
|
|
30314
|
+
offset: v4__namespace.number(),
|
|
30315
|
+
limit: v4__namespace.number()
|
|
30316
|
+
});
|
|
30317
|
+
var MoneyMarketAssetSuppliersSchema = v4__namespace.object({
|
|
30318
|
+
suppliers: v4__namespace.array(v4__namespace.string()),
|
|
30319
|
+
total: v4__namespace.number(),
|
|
30320
|
+
offset: v4__namespace.number(),
|
|
30321
|
+
limit: v4__namespace.number()
|
|
30322
|
+
});
|
|
30323
|
+
var MoneyMarketBorrowersSchema = v4__namespace.object({
|
|
30324
|
+
borrowers: v4__namespace.array(v4__namespace.string()),
|
|
30325
|
+
total: v4__namespace.number(),
|
|
30326
|
+
offset: v4__namespace.number(),
|
|
30327
|
+
limit: v4__namespace.number()
|
|
30328
|
+
});
|
|
30329
|
+
var GetChainsResponseSchema = v4__namespace.array(SpokeChainKeySchema);
|
|
30330
|
+
var TokensByChainMapSchema = v4__namespace.custom(
|
|
30331
|
+
(input) => typeof input === "object" && input !== null && Object.values(input).every((tokens) => Array.isArray(tokens) && tokens.every((t) => v4__namespace.is(XTokenSchema, t)))
|
|
30332
|
+
);
|
|
30333
|
+
var TokensListSchema = v4__namespace.array(XTokenSchema);
|
|
30334
|
+
var ReserveAssetsSchema = v4__namespace.array(AddressSchema2);
|
|
30335
|
+
|
|
30336
|
+
// src/backendApi/BackendApiService.ts
|
|
30337
|
+
var BackendApiService = class {
|
|
30338
|
+
// sub-services exposing domain-specific APIs
|
|
30339
|
+
swaps;
|
|
30340
|
+
// resolved base-API slice of the ApiConfig union (flat config, or its `baseApiConfig`)
|
|
30341
|
+
config;
|
|
30342
|
+
headers;
|
|
30343
|
+
logger;
|
|
30344
|
+
constructor(config, logger = consoleLogger) {
|
|
30345
|
+
this.config = resolveBaseApiConfig(config);
|
|
30346
|
+
this.headers = { ...this.config.headers };
|
|
30347
|
+
this.logger = logger;
|
|
30348
|
+
this.swaps = new SwapsApiService(resolveSwapsApiConfig(config), this.logger);
|
|
30349
|
+
}
|
|
29504
30350
|
/**
|
|
29505
30351
|
* Wraps {@link makeRequest} in a `Result<T>` so all errors are captured rather
|
|
29506
30352
|
* than propagated as thrown exceptions. Every public endpoint method delegates
|
|
29507
30353
|
* here instead of calling `makeRequest` directly.
|
|
29508
30354
|
*/
|
|
29509
|
-
|
|
30355
|
+
/**
|
|
30356
|
+
* Fold any per-call override (carried on `config` alongside `method`/`body`) over the service
|
|
30357
|
+
* defaults: baseURL truthy-fallback (an empty-string override defers to the default), timeout
|
|
30358
|
+
* nullish-fallback, headers merged (override wins per key). Mirrors the original makeRequest merge.
|
|
30359
|
+
*/
|
|
30360
|
+
resolveRequestConfig(config) {
|
|
30361
|
+
const { baseURL, timeout, headers, ...rest } = config;
|
|
30362
|
+
return {
|
|
30363
|
+
...rest,
|
|
30364
|
+
baseURL: baseURL || this.config.baseURL,
|
|
30365
|
+
timeout: timeout ?? this.config.timeout,
|
|
30366
|
+
headers: { ...this.headers, ...headers }
|
|
30367
|
+
};
|
|
30368
|
+
}
|
|
30369
|
+
/**
|
|
30370
|
+
* Wrap a thrown transport failure (HTTP_REQUEST_FAILED / REQUEST_TIMEOUT / network error) as the
|
|
30371
|
+
* canonical backend `SodaxError` — identical shape to SwapsApiService; the underlying failure is
|
|
30372
|
+
* preserved on `error.cause`.
|
|
30373
|
+
*/
|
|
30374
|
+
toExternalApiError(endpoint, error) {
|
|
30375
|
+
return new SodaxError(
|
|
30376
|
+
"EXTERNAL_API_ERROR",
|
|
30377
|
+
error instanceof Error ? error.message : `Backend API request to ${endpoint} failed`,
|
|
30378
|
+
{ feature: "backend", cause: error, context: { api: "backend", endpoint } }
|
|
30379
|
+
);
|
|
30380
|
+
}
|
|
30381
|
+
/**
|
|
30382
|
+
* Issue a request and validate the JSON body against `schema`, wrapping the result in `Result<T>`.
|
|
30383
|
+
* Mirrors {@link SwapsApiService}: a 2xx body that fails the schema is surfaced as
|
|
30384
|
+
* `EXTERNAL_API_ERROR` (`context.reason: 'invalid_response_shape'`) rather than returned untyped.
|
|
30385
|
+
* Every data/token/money-market method delegates here; the config/relay reads use
|
|
30386
|
+
* {@link requestUnvalidated} instead.
|
|
30387
|
+
*/
|
|
30388
|
+
async request(endpoint, config, schema) {
|
|
30389
|
+
try {
|
|
30390
|
+
const raw = await makeRequest({
|
|
30391
|
+
endpoint,
|
|
30392
|
+
config: this.resolveRequestConfig(config),
|
|
30393
|
+
logger: this.logger,
|
|
30394
|
+
serviceLabel: "BackendApiService"
|
|
30395
|
+
});
|
|
30396
|
+
const parsed = v4__namespace.safeParse(schema, raw);
|
|
30397
|
+
if (!parsed.success) {
|
|
30398
|
+
return {
|
|
30399
|
+
ok: false,
|
|
30400
|
+
error: new SodaxError("EXTERNAL_API_ERROR", `Invalid response shape from backend API for ${endpoint}`, {
|
|
30401
|
+
feature: "backend",
|
|
30402
|
+
context: { api: "backend", endpoint, reason: "invalid_response_shape", issues: v4__namespace.flatten(parsed.issues) }
|
|
30403
|
+
})
|
|
30404
|
+
};
|
|
30405
|
+
}
|
|
30406
|
+
return { ok: true, value: parsed.output };
|
|
30407
|
+
} catch (error) {
|
|
30408
|
+
return { ok: false, error: this.toExternalApiError(endpoint, error) };
|
|
30409
|
+
}
|
|
30410
|
+
}
|
|
30411
|
+
/**
|
|
30412
|
+
* Issue a request WITHOUT response-shape validation (passthrough typing). Reserved for the
|
|
30413
|
+
* config/relay reads whose shapes are too large/brittle to schema-validate (`SodaxConfig` via
|
|
30414
|
+
* `getAllConfig`, `SpokeChainConfigMap` via `getSpokeChainConfig`) or carry `bigint` values that
|
|
30415
|
+
* cannot survive JSON validation (`getRelayChainIdMap`). `ConfigService` version-gates and falls
|
|
30416
|
+
* back to packaged defaults, so it relies on no response-shape guarantee from these endpoints.
|
|
30417
|
+
*/
|
|
30418
|
+
async requestUnvalidated(endpoint, config) {
|
|
29510
30419
|
try {
|
|
29511
|
-
const value = await
|
|
30420
|
+
const value = await makeRequest({
|
|
30421
|
+
endpoint,
|
|
30422
|
+
config: this.resolveRequestConfig(config),
|
|
30423
|
+
logger: this.logger,
|
|
30424
|
+
serviceLabel: "BackendApiService"
|
|
30425
|
+
});
|
|
29512
30426
|
return { ok: true, value };
|
|
29513
30427
|
} catch (error) {
|
|
29514
|
-
return { ok: false, error };
|
|
30428
|
+
return { ok: false, error: this.toExternalApiError(endpoint, error) };
|
|
29515
30429
|
}
|
|
29516
30430
|
}
|
|
29517
30431
|
// Intent endpoints
|
|
@@ -29526,7 +30440,7 @@ var BackendApiService = class {
|
|
|
29526
30440
|
* open/closed state, token amounts, and any fill events.
|
|
29527
30441
|
*/
|
|
29528
30442
|
async getIntentByTxHash(txHash, config) {
|
|
29529
|
-
return this.request(`/intent/tx/${txHash}`, { ...config, method: "GET" });
|
|
30443
|
+
return this.request(`/intent/tx/${txHash}`, { ...config, method: "GET" }, IntentResponseSchema2);
|
|
29530
30444
|
}
|
|
29531
30445
|
/**
|
|
29532
30446
|
* Fetch a swap intent by its canonical intent hash.
|
|
@@ -29535,58 +30449,7 @@ var BackendApiService = class {
|
|
|
29535
30449
|
* @returns `Result<IntentResponse>` — on success, the full intent details.
|
|
29536
30450
|
*/
|
|
29537
30451
|
async getIntentByHash(intentHash, config) {
|
|
29538
|
-
return this.request(`/intent/${intentHash}`, { ...config, method: "GET" });
|
|
29539
|
-
}
|
|
29540
|
-
// Swap submit-tx endpoints
|
|
29541
|
-
/**
|
|
29542
|
-
* Submit a signed spoke-chain swap transaction to the backend for processing.
|
|
29543
|
-
*
|
|
29544
|
-
* The backend relays the transaction to the hub chain, posts execution data
|
|
29545
|
-
* to the solver, and advances the intent through its lifecycle. The response
|
|
29546
|
-
* shape is validated at runtime via a type guard; an invalid shape is
|
|
29547
|
-
* returned as `{ ok: false }`.
|
|
29548
|
-
*
|
|
29549
|
-
* @param params - The signed transaction hash, source chain key, sender wallet
|
|
29550
|
-
* address, intent data, and relay data required to process the swap.
|
|
29551
|
-
* @returns `Result<SubmitSwapTxResponse>` — on success, a confirmation object
|
|
29552
|
-
* with `success: true` and a human-readable `message`.
|
|
29553
|
-
*/
|
|
29554
|
-
async submitSwapTx(params, config) {
|
|
29555
|
-
const result = await this.request("/swaps/submit-tx", {
|
|
29556
|
-
...config,
|
|
29557
|
-
method: "POST",
|
|
29558
|
-
body: JSON.stringify(params)
|
|
29559
|
-
});
|
|
29560
|
-
if (!result.ok) return result;
|
|
29561
|
-
if (!isSubmitSwapTxResponse(result.value)) {
|
|
29562
|
-
return { ok: false, error: new Error("Invalid submitSwapTx response: unexpected response shape") };
|
|
29563
|
-
}
|
|
29564
|
-
return { ok: true, value: result.value };
|
|
29565
|
-
}
|
|
29566
|
-
/**
|
|
29567
|
-
* Poll the backend relay pipeline for the current status of a previously
|
|
29568
|
-
* submitted swap transaction.
|
|
29569
|
-
*
|
|
29570
|
-
* Status progresses through: `pending` → `verifying` → `verified` →
|
|
29571
|
-
* `relaying` → `relayed` → `posting_execution` → `executed` (or `failed`).
|
|
29572
|
-
*
|
|
29573
|
-
* @param params - Object containing the source-chain transaction hash and,
|
|
29574
|
-
* optionally, the source chain key to disambiguate cross-chain hashes.
|
|
29575
|
-
* @returns `Result<SubmitSwapTxStatusResponse>` — on success, includes the
|
|
29576
|
-
* current `status`, any `failureReason`, and (once executed) the
|
|
29577
|
-
* `dstIntentTxHash` on the hub chain.
|
|
29578
|
-
*/
|
|
29579
|
-
async getSubmitSwapTxStatus(params, config) {
|
|
29580
|
-
const queryParams = new URLSearchParams();
|
|
29581
|
-
queryParams.append("txHash", params.txHash);
|
|
29582
|
-
if (params.srcChainKey) queryParams.append("srcChainKey", params.srcChainKey);
|
|
29583
|
-
const endpoint = `/swaps/submit-tx/status?${queryParams.toString()}`;
|
|
29584
|
-
const result = await this.request(endpoint, { ...config, method: "GET" });
|
|
29585
|
-
if (!result.ok) return result;
|
|
29586
|
-
if (!isSubmitSwapTxStatusResponse(result.value)) {
|
|
29587
|
-
return { ok: false, error: new Error("Invalid submitSwapTxStatus response: unexpected response shape") };
|
|
29588
|
-
}
|
|
29589
|
-
return { ok: true, value: result.value };
|
|
30452
|
+
return this.request(`/intent/${intentHash}`, { ...config, method: "GET" }, IntentResponseSchema2);
|
|
29590
30453
|
}
|
|
29591
30454
|
// Solver endpoints
|
|
29592
30455
|
/**
|
|
@@ -29603,7 +30466,7 @@ var BackendApiService = class {
|
|
|
29603
30466
|
queryParams.append("limit", params.limit);
|
|
29604
30467
|
const queryString = queryParams.toString();
|
|
29605
30468
|
const endpoint = `/solver/orderbook?${queryString}`;
|
|
29606
|
-
return this.request(endpoint, { ...config, method: "GET" });
|
|
30469
|
+
return this.request(endpoint, { ...config, method: "GET" }, OrderbookResponseSchema);
|
|
29607
30470
|
}
|
|
29608
30471
|
/**
|
|
29609
30472
|
* Fetch all swap intents created by a specific wallet address, with optional
|
|
@@ -29629,7 +30492,7 @@ var BackendApiService = class {
|
|
|
29629
30492
|
if (offset) queryParams.append("offset", offset);
|
|
29630
30493
|
const queryString = queryParams.toString();
|
|
29631
30494
|
const endpoint = queryString.length > 0 ? `/intent/user/${userAddress}?${queryString}` : `/intent/user/${userAddress}`;
|
|
29632
|
-
return this.request(endpoint, { ...config, method: "GET" });
|
|
30495
|
+
return this.request(endpoint, { ...config, method: "GET" }, UserIntentsResponseSchema);
|
|
29633
30496
|
}
|
|
29634
30497
|
// Money Market endpoints
|
|
29635
30498
|
/**
|
|
@@ -29644,7 +30507,11 @@ var BackendApiService = class {
|
|
|
29644
30507
|
* position across all active reserves.
|
|
29645
30508
|
*/
|
|
29646
30509
|
async getMoneyMarketPosition(userAddress, config) {
|
|
29647
|
-
return this.request(
|
|
30510
|
+
return this.request(
|
|
30511
|
+
`/moneymarket/position/${userAddress}`,
|
|
30512
|
+
{ ...config, method: "GET" },
|
|
30513
|
+
MoneyMarketPositionSchema
|
|
30514
|
+
);
|
|
29648
30515
|
}
|
|
29649
30516
|
/**
|
|
29650
30517
|
* Fetch the on-chain state for every active money market reserve asset.
|
|
@@ -29653,7 +30520,7 @@ var BackendApiService = class {
|
|
|
29653
30520
|
* snapshots including interest rates, liquidity indices, and participant counts.
|
|
29654
30521
|
*/
|
|
29655
30522
|
async getAllMoneyMarketAssets(config) {
|
|
29656
|
-
return this.request("/moneymarket/asset/all", { ...config, method: "GET" });
|
|
30523
|
+
return this.request("/moneymarket/asset/all", { ...config, method: "GET" }, MoneyMarketAssetsSchema);
|
|
29657
30524
|
}
|
|
29658
30525
|
/**
|
|
29659
30526
|
* Fetch the on-chain state for a single money market reserve asset.
|
|
@@ -29663,7 +30530,11 @@ var BackendApiService = class {
|
|
|
29663
30530
|
* including interest rates, total balances, and liquidity indices.
|
|
29664
30531
|
*/
|
|
29665
30532
|
async getMoneyMarketAsset(reserveAddress, config) {
|
|
29666
|
-
return this.request(
|
|
30533
|
+
return this.request(
|
|
30534
|
+
`/moneymarket/asset/${reserveAddress}`,
|
|
30535
|
+
{ ...config, method: "GET" },
|
|
30536
|
+
MoneyMarketAssetSchema
|
|
30537
|
+
);
|
|
29667
30538
|
}
|
|
29668
30539
|
/**
|
|
29669
30540
|
* Fetch a paginated list of wallets that currently have an outstanding borrow
|
|
@@ -29680,7 +30551,7 @@ var BackendApiService = class {
|
|
|
29680
30551
|
queryParams.append("limit", params.limit);
|
|
29681
30552
|
const queryString = queryParams.toString();
|
|
29682
30553
|
const endpoint = `/moneymarket/asset/${reserveAddress}/borrowers?${queryString}`;
|
|
29683
|
-
return this.request(endpoint, { ...config, method: "GET" });
|
|
30554
|
+
return this.request(endpoint, { ...config, method: "GET" }, MoneyMarketAssetBorrowersSchema);
|
|
29684
30555
|
}
|
|
29685
30556
|
/**
|
|
29686
30557
|
* Fetch a paginated list of wallets that currently have an active supply
|
|
@@ -29697,7 +30568,7 @@ var BackendApiService = class {
|
|
|
29697
30568
|
queryParams.append("limit", params.limit);
|
|
29698
30569
|
const queryString = queryParams.toString();
|
|
29699
30570
|
const endpoint = `/moneymarket/asset/${reserveAddress}/suppliers?${queryString}`;
|
|
29700
|
-
return this.request(endpoint, { ...config, method: "GET" });
|
|
30571
|
+
return this.request(endpoint, { ...config, method: "GET" }, MoneyMarketAssetSuppliersSchema);
|
|
29701
30572
|
}
|
|
29702
30573
|
/**
|
|
29703
30574
|
* Fetch a paginated list of all wallet addresses that hold an active borrow
|
|
@@ -29713,7 +30584,7 @@ var BackendApiService = class {
|
|
|
29713
30584
|
queryParams.append("limit", params.limit);
|
|
29714
30585
|
const queryString = queryParams.toString();
|
|
29715
30586
|
const endpoint = `/moneymarket/borrowers?${queryString}`;
|
|
29716
|
-
return this.request(endpoint, { ...config, method: "GET" });
|
|
30587
|
+
return this.request(endpoint, { ...config, method: "GET" }, MoneyMarketBorrowersSchema);
|
|
29717
30588
|
}
|
|
29718
30589
|
/**
|
|
29719
30590
|
* Fetch the complete SODAX runtime configuration in a single request.
|
|
@@ -29726,7 +30597,7 @@ var BackendApiService = class {
|
|
|
29726
30597
|
* `config` is the current `SodaxConfig` used by all SDK services.
|
|
29727
30598
|
*/
|
|
29728
30599
|
async getAllConfig(config) {
|
|
29729
|
-
return this.
|
|
30600
|
+
return this.requestUnvalidated("/config/all", { ...config, method: "GET" });
|
|
29730
30601
|
}
|
|
29731
30602
|
/**
|
|
29732
30603
|
* Fetch the list of spoke chain keys that are currently supported by the
|
|
@@ -29739,7 +30610,7 @@ var BackendApiService = class {
|
|
|
29739
30610
|
* `SpokeChainKey` strings (e.g. `["ethereum", "arbitrum", "solana", …]`).
|
|
29740
30611
|
*/
|
|
29741
30612
|
async getChains(config) {
|
|
29742
|
-
return this.request("/config/spoke/chains", { ...config, method: "GET" });
|
|
30613
|
+
return this.request("/config/spoke/chains", { ...config, method: "GET" }, GetChainsResponseSchema);
|
|
29743
30614
|
}
|
|
29744
30615
|
/**
|
|
29745
30616
|
* Fetch the full map of tokens available for swapping, keyed by spoke chain.
|
|
@@ -29751,7 +30622,7 @@ var BackendApiService = class {
|
|
|
29751
30622
|
* supported spoke chain key to its list of swappable `XToken` definitions.
|
|
29752
30623
|
*/
|
|
29753
30624
|
async getSwapTokens(config) {
|
|
29754
|
-
return this.request("/config/swap/tokens", { ...config, method: "GET" });
|
|
30625
|
+
return this.request("/config/swap/tokens", { ...config, method: "GET" }, TokensByChainMapSchema);
|
|
29755
30626
|
}
|
|
29756
30627
|
/**
|
|
29757
30628
|
* Fetch the list of tokens available for swapping on a specific spoke chain.
|
|
@@ -29763,10 +30634,7 @@ var BackendApiService = class {
|
|
|
29763
30634
|
* array of `XToken` definitions supported for swapping on that chain.
|
|
29764
30635
|
*/
|
|
29765
30636
|
async getSwapTokensByChainId(chainId, config) {
|
|
29766
|
-
return this.request(`/config/swap/${chainId}/tokens`, {
|
|
29767
|
-
...config,
|
|
29768
|
-
method: "GET"
|
|
29769
|
-
});
|
|
30637
|
+
return this.request(`/config/swap/${chainId}/tokens`, { ...config, method: "GET" }, TokensListSchema);
|
|
29770
30638
|
}
|
|
29771
30639
|
/**
|
|
29772
30640
|
* Fetch the full map of tokens available in the money market (lending/borrowing),
|
|
@@ -29778,10 +30646,7 @@ var BackendApiService = class {
|
|
|
29778
30646
|
* each supported spoke chain key to its list of money-market `XToken` definitions.
|
|
29779
30647
|
*/
|
|
29780
30648
|
async getMoneyMarketTokens(config) {
|
|
29781
|
-
return this.request("/config/money-market/tokens", {
|
|
29782
|
-
...config,
|
|
29783
|
-
method: "GET"
|
|
29784
|
-
});
|
|
30649
|
+
return this.request("/config/money-market/tokens", { ...config, method: "GET" }, TokensByChainMapSchema);
|
|
29785
30650
|
}
|
|
29786
30651
|
/**
|
|
29787
30652
|
* Fetch the list of hub-chain reserve asset addresses registered in the
|
|
@@ -29795,10 +30660,11 @@ var BackendApiService = class {
|
|
|
29795
30660
|
* readonly array of reserve `Address` strings.
|
|
29796
30661
|
*/
|
|
29797
30662
|
async getMoneyMarketReserveAssets(config) {
|
|
29798
|
-
return this.request(
|
|
29799
|
-
|
|
29800
|
-
method: "GET"
|
|
29801
|
-
|
|
30663
|
+
return this.request(
|
|
30664
|
+
"/config/money-market/reserve-assets",
|
|
30665
|
+
{ ...config, method: "GET" },
|
|
30666
|
+
ReserveAssetsSchema
|
|
30667
|
+
);
|
|
29802
30668
|
}
|
|
29803
30669
|
/**
|
|
29804
30670
|
* Fetch the list of tokens available for lending/borrowing on a specific
|
|
@@ -29811,10 +30677,11 @@ var BackendApiService = class {
|
|
|
29811
30677
|
* readonly array of `XToken` definitions supported in the money market on that chain.
|
|
29812
30678
|
*/
|
|
29813
30679
|
async getMoneyMarketTokensByChainId(chainId, config) {
|
|
29814
|
-
return this.request(
|
|
29815
|
-
|
|
29816
|
-
method: "GET"
|
|
29817
|
-
|
|
30680
|
+
return this.request(
|
|
30681
|
+
`/config/money-market/${chainId}/tokens`,
|
|
30682
|
+
{ ...config, method: "GET" },
|
|
30683
|
+
TokensListSchema
|
|
30684
|
+
);
|
|
29818
30685
|
}
|
|
29819
30686
|
/**
|
|
29820
30687
|
* Fetch the mapping from spoke chain keys to the numeric chain IDs used by
|
|
@@ -29828,7 +30695,7 @@ var BackendApiService = class {
|
|
|
29828
30695
|
* `IntentRelayChainIdMap` record mapping each spoke chain key to its relay chain ID.
|
|
29829
30696
|
*/
|
|
29830
30697
|
async getRelayChainIdMap(config) {
|
|
29831
|
-
return this.
|
|
30698
|
+
return this.requestUnvalidated("/config/relay/chain-id-map", {
|
|
29832
30699
|
...config,
|
|
29833
30700
|
method: "GET"
|
|
29834
30701
|
});
|
|
@@ -29845,7 +30712,7 @@ var BackendApiService = class {
|
|
|
29845
30712
|
* `SpokeChainConfigMap` for all currently enabled spoke chains.
|
|
29846
30713
|
*/
|
|
29847
30714
|
async getSpokeChainConfig(config) {
|
|
29848
|
-
return this.
|
|
30715
|
+
return this.requestUnvalidated("/config/spoke/all-chains-configs", {
|
|
29849
30716
|
...config,
|
|
29850
30717
|
method: "GET"
|
|
29851
30718
|
});
|
|
@@ -29857,12 +30724,17 @@ var BackendApiService = class {
|
|
|
29857
30724
|
* without constructing a new service instance. Existing header keys are
|
|
29858
30725
|
* overwritten; keys absent from `headers` are preserved.
|
|
29859
30726
|
*
|
|
30727
|
+
* The headers are also fanned out to the sub-services (`swaps`), which hold
|
|
30728
|
+
* their own header copies — so a token set here applies to every request made
|
|
30729
|
+
* through this client, including `swaps.*`.
|
|
30730
|
+
*
|
|
29860
30731
|
* @param headers - Key-value pairs to add or overwrite in the default headers.
|
|
29861
30732
|
*/
|
|
29862
30733
|
setHeaders(headers) {
|
|
29863
30734
|
Object.entries(headers).forEach(([key, value]) => {
|
|
29864
30735
|
this.headers[key] = value;
|
|
29865
30736
|
});
|
|
30737
|
+
this.swaps.setHeaders(headers);
|
|
29866
30738
|
}
|
|
29867
30739
|
/**
|
|
29868
30740
|
* Return the base URL the service is currently pointing at.
|
|
@@ -38582,7 +39454,7 @@ var LeverageYieldService = class {
|
|
|
38582
39454
|
}
|
|
38583
39455
|
/** Looks up a vault by its `name` field. Returns `undefined` when not registered. */
|
|
38584
39456
|
getVault(name) {
|
|
38585
|
-
return this.listVaults().find((
|
|
39457
|
+
return this.listVaults().find((v6) => v6.name === name);
|
|
38586
39458
|
}
|
|
38587
39459
|
/**
|
|
38588
39460
|
* Looks up a registered vault by its on-chain proxy address (case-insensitive).
|
|
@@ -38590,7 +39462,7 @@ var LeverageYieldService = class {
|
|
|
38590
39462
|
*/
|
|
38591
39463
|
getVaultByAddress(address) {
|
|
38592
39464
|
const normalized = address.toLowerCase();
|
|
38593
|
-
return this.listVaults().find((
|
|
39465
|
+
return this.listVaults().find((v6) => v6.vault.toLowerCase() === normalized);
|
|
38594
39466
|
}
|
|
38595
39467
|
/**
|
|
38596
39468
|
* Resolves the intent `deadline`: returns the caller-supplied value verbatim, otherwise
|
|
@@ -39383,6 +40255,8 @@ var Sodax = class {
|
|
|
39383
40255
|
// ICX migration service enabling ICX migration to SODA
|
|
39384
40256
|
backendApi;
|
|
39385
40257
|
// backend API service enabling backend API endpoints
|
|
40258
|
+
api;
|
|
40259
|
+
// syntactic sugar for backend API service
|
|
39386
40260
|
bridge;
|
|
39387
40261
|
// Bridge service enabling cross-chain transfers
|
|
39388
40262
|
staking;
|
|
@@ -39405,8 +40279,10 @@ var Sodax = class {
|
|
|
39405
40279
|
const logger = resolveLogger(options?.logger);
|
|
39406
40280
|
const analytics = resolveAnalytics(options?.analytics);
|
|
39407
40281
|
const fee = options?.fee;
|
|
40282
|
+
const useBackendSubmitTx = options?.swapsOptions?.useBackendSubmitTx ?? false;
|
|
39408
40283
|
this.instanceConfig = options ? mergeSodaxConfig(sodaxConfig, options) : sodaxConfig;
|
|
39409
40284
|
this.backendApi = new BackendApiService(this.instanceConfig.api, logger);
|
|
40285
|
+
this.api = this.backendApi;
|
|
39410
40286
|
this.config = new ConfigService({
|
|
39411
40287
|
api: this.backendApi,
|
|
39412
40288
|
config: this.instanceConfig,
|
|
@@ -39420,7 +40296,9 @@ var Sodax = class {
|
|
|
39420
40296
|
this.swaps = new SwapService({
|
|
39421
40297
|
config: this.config,
|
|
39422
40298
|
hubProvider: this.hubProvider,
|
|
39423
|
-
spoke: this.spoke
|
|
40299
|
+
spoke: this.spoke,
|
|
40300
|
+
backendApi: this.backendApi,
|
|
40301
|
+
useBackendSubmitTx
|
|
39424
40302
|
});
|
|
39425
40303
|
this.moneyMarket = new MoneyMarketService({
|
|
39426
40304
|
config: this.config,
|
|
@@ -39620,6 +40498,7 @@ exports.StellarSpokeService = StellarSpokeService;
|
|
|
39620
40498
|
exports.SuiSpokeService = SuiSpokeService;
|
|
39621
40499
|
exports.SupportedMigrationTokens = SupportedMigrationTokens;
|
|
39622
40500
|
exports.SwapService = SwapService;
|
|
40501
|
+
exports.SwapsApiService = SwapsApiService;
|
|
39623
40502
|
exports.USD_DECIMALS = USD_DECIMALS;
|
|
39624
40503
|
exports.UiPoolDataProviderService = UiPoolDataProviderService;
|
|
39625
40504
|
exports.VAULT_TOKEN_DECIMALS = VAULT_TOKEN_DECIMALS;
|
|
@@ -39820,8 +40699,6 @@ exports.isStakingOrchestrationError = isStakingOrchestrationError;
|
|
|
39820
40699
|
exports.isStellarChainKey = isStellarChainKey;
|
|
39821
40700
|
exports.isStellarChainKeyType = isStellarChainKeyType;
|
|
39822
40701
|
exports.isStellarWalletProviderType = isStellarWalletProviderType;
|
|
39823
|
-
exports.isSubmitSwapTxResponse = isSubmitSwapTxResponse;
|
|
39824
|
-
exports.isSubmitSwapTxStatusResponse = isSubmitSwapTxStatusResponse;
|
|
39825
40702
|
exports.isSuiChainKey = isSuiChainKey;
|
|
39826
40703
|
exports.isSuiChainKeyType = isSuiChainKeyType;
|
|
39827
40704
|
exports.isSupportedBitcoinAddressType = isSupportedBitcoinAddressType;
|