@sodax/sdk 2.0.0-rc.12 → 2.0.0-rc.13
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 +961 -22
- package/dist/index.d.cts +479 -4
- package/dist/index.d.ts +479 -4
- package/dist/index.mjs +950 -24
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -197,7 +197,8 @@ var SODAX_FEATURES = [
|
|
|
197
197
|
"migration",
|
|
198
198
|
"dex",
|
|
199
199
|
"partner",
|
|
200
|
-
"recovery"
|
|
200
|
+
"recovery",
|
|
201
|
+
"leverageYield"
|
|
201
202
|
];
|
|
202
203
|
|
|
203
204
|
// src/shared/utils/tiny-invariant.ts
|
|
@@ -559,6 +560,27 @@ var SodaTokens = {
|
|
|
559
560
|
vault: "0x243b0c26c8b38793908d7C64e8510f21B19B4613"
|
|
560
561
|
}
|
|
561
562
|
};
|
|
563
|
+
var LsodaSymbols = ["lsodaWEETH", "lsodaWSTETH"];
|
|
564
|
+
var LsodaTokens = {
|
|
565
|
+
lsodaWEETH: {
|
|
566
|
+
symbol: "lsodaWEETH",
|
|
567
|
+
name: "Leveraged Soda weETH",
|
|
568
|
+
decimals: 18,
|
|
569
|
+
address: "0xD09de2f5070699A909c0FD32fb5A909d3886701D",
|
|
570
|
+
chainKey: ChainKeys.SONIC_MAINNET,
|
|
571
|
+
hubAsset: "0xD09de2f5070699A909c0FD32fb5A909d3886701D",
|
|
572
|
+
vault: "0xD09de2f5070699A909c0FD32fb5A909d3886701D"
|
|
573
|
+
},
|
|
574
|
+
lsodaWSTETH: {
|
|
575
|
+
symbol: "lsodaWSTETH",
|
|
576
|
+
name: "Leveraged Soda wstETH",
|
|
577
|
+
decimals: 18,
|
|
578
|
+
address: "0x136E5D1CEC5db1829E24941Eddd9C8640E02Ce7a",
|
|
579
|
+
chainKey: ChainKeys.SONIC_MAINNET,
|
|
580
|
+
hubAsset: "0x136E5D1CEC5db1829E24941Eddd9C8640E02Ce7a",
|
|
581
|
+
vault: "0x136E5D1CEC5db1829E24941Eddd9C8640E02Ce7a"
|
|
582
|
+
}
|
|
583
|
+
};
|
|
562
584
|
var sonicSupportedTokens = {
|
|
563
585
|
S: {
|
|
564
586
|
symbol: "S",
|
|
@@ -623,7 +645,8 @@ var sonicSupportedTokens = {
|
|
|
623
645
|
hubAsset: "0x7c7d53EEcda37a87ce0D5bf8E0b24512A48dC963",
|
|
624
646
|
vault: SodaTokens.sodaSODA.address
|
|
625
647
|
},
|
|
626
|
-
...SodaTokens
|
|
648
|
+
...SodaTokens,
|
|
649
|
+
...LsodaTokens
|
|
627
650
|
};
|
|
628
651
|
var redbellySupportedTokens = {
|
|
629
652
|
RBNT: {
|
|
@@ -3624,7 +3647,8 @@ var swapSupportedTokens = {
|
|
|
3624
3647
|
spokeChainConfig[ChainKeys.SONIC_MAINNET].supportedTokens.USDT,
|
|
3625
3648
|
spokeChainConfig[ChainKeys.SONIC_MAINNET].supportedTokens.wS,
|
|
3626
3649
|
spokeChainConfig[ChainKeys.SONIC_MAINNET].supportedTokens.SODA,
|
|
3627
|
-
...Object.values(SodaTokens)
|
|
3650
|
+
...Object.values(SodaTokens),
|
|
3651
|
+
...Object.values(LsodaTokens)
|
|
3628
3652
|
],
|
|
3629
3653
|
[ChainKeys.AVALANCHE_MAINNET]: [
|
|
3630
3654
|
spokeChainConfig[ChainKeys.AVALANCHE_MAINNET].supportedTokens.AVAX,
|
|
@@ -3864,6 +3888,41 @@ var swapsConfig = {
|
|
|
3864
3888
|
var getSupportedSolverTokens = (chainId) => swapSupportedTokens[chainId];
|
|
3865
3889
|
var isSwapSupportedToken = (chainId, token) => swapSupportedTokens[chainId].some((t) => t.address.toLowerCase() === token.toLowerCase());
|
|
3866
3890
|
|
|
3891
|
+
// ../types/dist/leverageYield/leverageYield.js
|
|
3892
|
+
var leverageYieldVaults = [
|
|
3893
|
+
{
|
|
3894
|
+
name: LsodaTokens.lsodaWEETH.symbol,
|
|
3895
|
+
vault: LsodaTokens.lsodaWEETH.vault,
|
|
3896
|
+
asset: SodaTokens.sodaWEETH.address,
|
|
3897
|
+
// sodaWEETH on Sonic
|
|
3898
|
+
borrowToken: SodaTokens.sodaETH.address,
|
|
3899
|
+
// sodaETH on Sonic
|
|
3900
|
+
lsdSource: {
|
|
3901
|
+
// DefiLlama pool for EtherFi's weETH on Ethereum (project: 'ether.fi-stake').
|
|
3902
|
+
poolId: "46bd2bdf-6d92-4066-b482-e885ee172264",
|
|
3903
|
+
fallbackAprPct: 3,
|
|
3904
|
+
label: "EtherFi (weETH)"
|
|
3905
|
+
}
|
|
3906
|
+
},
|
|
3907
|
+
{
|
|
3908
|
+
name: LsodaTokens.lsodaWSTETH.symbol,
|
|
3909
|
+
vault: LsodaTokens.lsodaWSTETH.vault,
|
|
3910
|
+
asset: SodaTokens.sodaWSTETH.address,
|
|
3911
|
+
// sodaWSTETH on Sonic
|
|
3912
|
+
borrowToken: SodaTokens.sodaETH.address,
|
|
3913
|
+
// sodaETH on Sonic
|
|
3914
|
+
lsdSource: {
|
|
3915
|
+
// DefiLlama pool for Lido's stETH on Ethereum (wstETH inherits this rate via redeem).
|
|
3916
|
+
poolId: "747c1d2a-c668-4682-b9f9-296708a3dd90",
|
|
3917
|
+
fallbackAprPct: 2.4,
|
|
3918
|
+
label: "Lido (stETH)"
|
|
3919
|
+
}
|
|
3920
|
+
}
|
|
3921
|
+
];
|
|
3922
|
+
var leverageYieldConfig = {
|
|
3923
|
+
vaults: leverageYieldVaults
|
|
3924
|
+
};
|
|
3925
|
+
|
|
3867
3926
|
// ../types/dist/sodax-config/sodax-config.js
|
|
3868
3927
|
var bridgeConfig = {
|
|
3869
3928
|
partnerFee: void 0
|
|
@@ -3875,6 +3934,7 @@ var sodaxConfig = {
|
|
|
3875
3934
|
moneyMarket: moneyMarketConfig,
|
|
3876
3935
|
bridge: bridgeConfig,
|
|
3877
3936
|
dex: dexConfig,
|
|
3937
|
+
leverageYield: leverageYieldConfig,
|
|
3878
3938
|
hub: hubConfig,
|
|
3879
3939
|
api: apiConfig,
|
|
3880
3940
|
solver: solverConfig,
|
|
@@ -4016,7 +4076,7 @@ function isValidWalletProviderForChainKey(chainKey, walletProvider) {
|
|
|
4016
4076
|
}
|
|
4017
4077
|
|
|
4018
4078
|
// ../types/dist/index.js
|
|
4019
|
-
var CONFIG_VERSION =
|
|
4079
|
+
var CONFIG_VERSION = 211;
|
|
4020
4080
|
function isEvmSpokeChainConfig(value) {
|
|
4021
4081
|
return typeof value === "object" && value !== null && value.chain.type === "EVM" && value.chain.key !== HUB_CHAIN_KEY;
|
|
4022
4082
|
}
|
|
@@ -22295,17 +22355,11 @@ var SuiSpokeService = class {
|
|
|
22295
22355
|
]
|
|
22296
22356
|
});
|
|
22297
22357
|
if (params.raw === true) {
|
|
22298
|
-
tx.setSender(from);
|
|
22299
|
-
const transactionRaw = await tx.build({
|
|
22300
|
-
client: this.publicClient,
|
|
22301
|
-
onlyTransactionKind: true
|
|
22302
|
-
});
|
|
22303
|
-
const transactionRawBase64String = Buffer.from(transactionRaw).toString("base64");
|
|
22304
22358
|
return {
|
|
22305
22359
|
from,
|
|
22306
22360
|
to: `${assetManager.packageId}::${assetManager.moduleId}::transfer`,
|
|
22307
22361
|
value: amount,
|
|
22308
|
-
data:
|
|
22362
|
+
data: tx.serialize()
|
|
22309
22363
|
};
|
|
22310
22364
|
}
|
|
22311
22365
|
return params.walletProvider.signAndExecuteTxn(tx);
|
|
@@ -22325,17 +22379,11 @@ var SuiSpokeService = class {
|
|
|
22325
22379
|
]
|
|
22326
22380
|
});
|
|
22327
22381
|
if (params.raw === true) {
|
|
22328
|
-
txb.setSender(from);
|
|
22329
|
-
const transactionRaw = await txb.build({
|
|
22330
|
-
client: this.publicClient,
|
|
22331
|
-
onlyTransactionKind: true
|
|
22332
|
-
});
|
|
22333
|
-
const transactionRawBase64String = Buffer.from(transactionRaw).toString("base64");
|
|
22334
22382
|
return {
|
|
22335
22383
|
from,
|
|
22336
22384
|
to: `${connection.packageId}::${connection.moduleId}::send_message_ua`,
|
|
22337
22385
|
value: 0n,
|
|
22338
|
-
data:
|
|
22386
|
+
data: txb.serialize()
|
|
22339
22387
|
};
|
|
22340
22388
|
}
|
|
22341
22389
|
return params.walletProvider.signAndExecuteTxn(txb);
|
|
@@ -22346,7 +22394,7 @@ var SuiSpokeService = class {
|
|
|
22346
22394
|
* @returns {Promise<bigint>} The estimated computation cost.
|
|
22347
22395
|
*/
|
|
22348
22396
|
async estimateGas({ tx }) {
|
|
22349
|
-
const txb = transactions.Transaction.
|
|
22397
|
+
const txb = transactions.Transaction.from(tx.data);
|
|
22350
22398
|
const result = await this.publicClient.devInspectTransactionBlock({
|
|
22351
22399
|
sender: tx.from,
|
|
22352
22400
|
transactionBlock: txb
|
|
@@ -22577,6 +22625,7 @@ var CustomStellarAccount = class {
|
|
|
22577
22625
|
decrementSequenceNumber() {
|
|
22578
22626
|
if (this.sequenceNumber > this.startingSequenceNumber) {
|
|
22579
22627
|
this.sequenceNumber--;
|
|
22628
|
+
return;
|
|
22580
22629
|
}
|
|
22581
22630
|
throw new Error(
|
|
22582
22631
|
`Sequence number cannot be decremented below the starting sequence number: ${this.startingSequenceNumber}`
|
|
@@ -22683,7 +22732,7 @@ var StellarSpokeService = class {
|
|
|
22683
22732
|
);
|
|
22684
22733
|
const assembledPriorityTx = stellarSdk.rpc.assembleTransaction(rawPriorityTx, simulation).build();
|
|
22685
22734
|
if (params.raw) {
|
|
22686
|
-
const transactionXdr =
|
|
22735
|
+
const transactionXdr = assembledPriorityTx.toXDR();
|
|
22687
22736
|
return {
|
|
22688
22737
|
from,
|
|
22689
22738
|
to: this.config.getChainConfig(srcChainKey).addresses.assetManager,
|
|
@@ -22800,7 +22849,7 @@ var StellarSpokeService = class {
|
|
|
22800
22849
|
);
|
|
22801
22850
|
const assembledPriorityTx = stellarSdk.rpc.assembleTransaction(rawPriorityTx, simulation).build();
|
|
22802
22851
|
if (params.raw) {
|
|
22803
|
-
const transactionXdr =
|
|
22852
|
+
const transactionXdr = assembledPriorityTx.toXDR();
|
|
22804
22853
|
return {
|
|
22805
22854
|
from,
|
|
22806
22855
|
to: this.config.getChainConfig(srcChainKey).addresses.assetManager,
|
|
@@ -37013,7 +37062,12 @@ var RecoveryService = class {
|
|
|
37013
37062
|
srcChainKey: chainKey,
|
|
37014
37063
|
field: "chainKey"
|
|
37015
37064
|
});
|
|
37016
|
-
const
|
|
37065
|
+
const leverageVaultAddresses = new Set(
|
|
37066
|
+
this.config.sodaxConfig.leverageYield.vaults.map((vault) => vault.vault.toLowerCase())
|
|
37067
|
+
);
|
|
37068
|
+
const entries = Object.values(chainConfig.supportedTokens).filter(
|
|
37069
|
+
(token) => viem.isAddress(token.hubAsset) && !leverageVaultAddresses.has(token.hubAsset.toLowerCase())
|
|
37070
|
+
);
|
|
37017
37071
|
if (entries.length === 0) {
|
|
37018
37072
|
return { ok: true, value: [] };
|
|
37019
37073
|
}
|
|
@@ -37115,6 +37169,871 @@ var RecoveryService = class {
|
|
|
37115
37169
|
}
|
|
37116
37170
|
};
|
|
37117
37171
|
|
|
37172
|
+
// src/leverageYield/errors.ts
|
|
37173
|
+
var leverageYieldInvariant = createInvariant("leverageYield");
|
|
37174
|
+
var LEVERAGE_YIELD_CODES = /* @__PURE__ */ new Set([
|
|
37175
|
+
"VALIDATION_FAILED",
|
|
37176
|
+
"INTENT_CREATION_FAILED",
|
|
37177
|
+
"APPROVE_FAILED",
|
|
37178
|
+
"ALLOWANCE_CHECK_FAILED",
|
|
37179
|
+
"LOOKUP_FAILED",
|
|
37180
|
+
"TX_VERIFICATION_FAILED",
|
|
37181
|
+
"TX_SUBMIT_FAILED",
|
|
37182
|
+
"RELAY_TIMEOUT",
|
|
37183
|
+
"RELAY_FAILED",
|
|
37184
|
+
"EXECUTION_FAILED",
|
|
37185
|
+
"EXTERNAL_API_ERROR",
|
|
37186
|
+
"UNKNOWN"
|
|
37187
|
+
]);
|
|
37188
|
+
var LEVERAGE_YIELD_POST_EXECUTION_CODES = /* @__PURE__ */ new Set([
|
|
37189
|
+
"EXECUTION_FAILED",
|
|
37190
|
+
"EXTERNAL_API_ERROR",
|
|
37191
|
+
"UNKNOWN"
|
|
37192
|
+
]);
|
|
37193
|
+
var LEVERAGE_YIELD_SWAP_CODES = /* @__PURE__ */ new Set([
|
|
37194
|
+
"VALIDATION_FAILED",
|
|
37195
|
+
"INTENT_CREATION_FAILED",
|
|
37196
|
+
"TX_VERIFICATION_FAILED",
|
|
37197
|
+
"TX_SUBMIT_FAILED",
|
|
37198
|
+
"RELAY_TIMEOUT",
|
|
37199
|
+
"RELAY_FAILED",
|
|
37200
|
+
"EXECUTION_FAILED",
|
|
37201
|
+
"EXTERNAL_API_ERROR",
|
|
37202
|
+
"UNKNOWN"
|
|
37203
|
+
]);
|
|
37204
|
+
var isLeverageYieldCreateIntentError = isCodeMember(CREATE_INTENT_CODES);
|
|
37205
|
+
var isLeverageYieldApproveError = isCodeMember(APPROVE_CODES);
|
|
37206
|
+
var isLeverageYieldAllowanceCheckError = isCodeMember(ALLOWANCE_CHECK_CODES);
|
|
37207
|
+
var isLeverageYieldLookupError = isCodeMember(LOOKUP_CODES);
|
|
37208
|
+
var isLeverageYieldPostExecutionError = isCodeMember(
|
|
37209
|
+
LEVERAGE_YIELD_POST_EXECUTION_CODES
|
|
37210
|
+
);
|
|
37211
|
+
var isLeverageYieldSwapError = isCodeMember(LEVERAGE_YIELD_SWAP_CODES);
|
|
37212
|
+
var isLeverageYieldError = isCodeMember(LEVERAGE_YIELD_CODES);
|
|
37213
|
+
|
|
37214
|
+
// src/leverageYield/LeverageYieldService.ts
|
|
37215
|
+
var leverageYieldVaultAbi = viem.parseAbi([
|
|
37216
|
+
"function asset() view returns (address)",
|
|
37217
|
+
"function getPositionDetails() view returns (uint256 collateral, uint256 debt, uint256 ltv, uint256 healthFactor, uint256 idleAsset)",
|
|
37218
|
+
// Used by getApr() — read-only metadata that doesn't change per pass.
|
|
37219
|
+
"function pool() view returns (address)",
|
|
37220
|
+
"function borrowToken() view returns (address)",
|
|
37221
|
+
"function targetLTV() view returns (uint256)"
|
|
37222
|
+
]);
|
|
37223
|
+
var INTENT_DEADLINE_BUFFER_SECONDS = 5 * 60;
|
|
37224
|
+
var ANY_SOLVER_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
37225
|
+
var MAX_WITHDRAW_DUST_BUFFER = 1000n;
|
|
37226
|
+
function pctToRay(aprPct) {
|
|
37227
|
+
return BigInt(Math.round(aprPct * 1e9)) * 10n ** 16n;
|
|
37228
|
+
}
|
|
37229
|
+
var DEFILLAMA_FETCH_TIMEOUT_MS = 1e4;
|
|
37230
|
+
var DEFILLAMA_FETCH_MAX_ATTEMPTS = 2;
|
|
37231
|
+
async function fetchWithTimeout(url, timeoutMs) {
|
|
37232
|
+
const controller = new AbortController();
|
|
37233
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
37234
|
+
try {
|
|
37235
|
+
return await fetch(url, { signal: controller.signal });
|
|
37236
|
+
} finally {
|
|
37237
|
+
clearTimeout(timeoutId);
|
|
37238
|
+
}
|
|
37239
|
+
}
|
|
37240
|
+
async function fetchDefillamaApr(poolId) {
|
|
37241
|
+
return retry(async () => {
|
|
37242
|
+
const response = await fetchWithTimeout(`https://yields.llama.fi/chart/${poolId}`, DEFILLAMA_FETCH_TIMEOUT_MS);
|
|
37243
|
+
if (!response.ok) throw new Error(`DefiLlama APR fetch failed: HTTP ${response.status}`);
|
|
37244
|
+
const json = await response.json();
|
|
37245
|
+
const series = json?.data;
|
|
37246
|
+
if (!Array.isArray(series) || series.length === 0) {
|
|
37247
|
+
throw new Error("DefiLlama APR response: empty time series");
|
|
37248
|
+
}
|
|
37249
|
+
const latest = series[series.length - 1]?.apy;
|
|
37250
|
+
if (typeof latest !== "number") throw new Error("DefiLlama APR: latest entry missing numeric apy");
|
|
37251
|
+
return latest;
|
|
37252
|
+
}, DEFILLAMA_FETCH_MAX_ATTEMPTS);
|
|
37253
|
+
}
|
|
37254
|
+
var LeverageYieldService = class {
|
|
37255
|
+
hubProvider;
|
|
37256
|
+
config;
|
|
37257
|
+
spoke;
|
|
37258
|
+
constructor({ hubProvider, config, spoke }) {
|
|
37259
|
+
this.hubProvider = hubProvider;
|
|
37260
|
+
this.config = config;
|
|
37261
|
+
this.spoke = spoke;
|
|
37262
|
+
}
|
|
37263
|
+
// ─── Registry ──────────────────────────────────────────────────────────
|
|
37264
|
+
/** Returns the static registry of known leverage-yield vaults. */
|
|
37265
|
+
listVaults() {
|
|
37266
|
+
return this.config.sodaxConfig.leverageYield.vaults;
|
|
37267
|
+
}
|
|
37268
|
+
/** Looks up a vault by its `name` field. Returns `undefined` when not registered. */
|
|
37269
|
+
getVault(name) {
|
|
37270
|
+
return this.listVaults().find((v) => v.name === name);
|
|
37271
|
+
}
|
|
37272
|
+
/**
|
|
37273
|
+
* Looks up a registered vault by its on-chain proxy address (case-insensitive).
|
|
37274
|
+
* Returns `undefined` when the address isn't in the registry.
|
|
37275
|
+
*/
|
|
37276
|
+
getVaultByAddress(address) {
|
|
37277
|
+
const normalized = address.toLowerCase();
|
|
37278
|
+
return this.listVaults().find((v) => v.vault.toLowerCase() === normalized);
|
|
37279
|
+
}
|
|
37280
|
+
/**
|
|
37281
|
+
* Resolves the intent `deadline`: returns the caller-supplied value verbatim, otherwise
|
|
37282
|
+
* derives a default from the hub-chain (Sonic) block timestamp plus
|
|
37283
|
+
* {@link INTENT_DEADLINE_BUFFER_SECONDS}. The deadline is enforced on-chain against the hub
|
|
37284
|
+
* block time, so the default is anchored to that block — never the client clock, which can
|
|
37285
|
+
* drift and produce an already-expired or over-extended deadline.
|
|
37286
|
+
*
|
|
37287
|
+
* Returns a {@link Result}: a `getBlock` RPC outage is a read failure, surfaced as
|
|
37288
|
+
* `LOOKUP_FAILED` (`method: 'resolveDeadline'`) rather than masquerading as an intent-build
|
|
37289
|
+
* failure. The `deposit` / `withdraw` callers forward it verbatim.
|
|
37290
|
+
*/
|
|
37291
|
+
async resolveDeadline(deadline, srcChainKey) {
|
|
37292
|
+
if (deadline !== void 0) return { ok: true, value: deadline };
|
|
37293
|
+
try {
|
|
37294
|
+
const block = await this.hubProvider.publicClient.getBlock({
|
|
37295
|
+
includeTransactions: false,
|
|
37296
|
+
blockTag: "latest"
|
|
37297
|
+
});
|
|
37298
|
+
return { ok: true, value: block.timestamp + BigInt(INTENT_DEADLINE_BUFFER_SECONDS) };
|
|
37299
|
+
} catch (error) {
|
|
37300
|
+
return { ok: false, error: lookupFailed("leverageYield", "resolveDeadline", error, { srcChainKey }) };
|
|
37301
|
+
}
|
|
37302
|
+
}
|
|
37303
|
+
/**
|
|
37304
|
+
* Builds the {@link LeverageYieldSwapPayload} for a leverage-yield deposit (any token → lsoda*).
|
|
37305
|
+
* The lsoda* output is delivered to the user's hub wallet on Sonic so a later
|
|
37306
|
+
* {@link LeverageYieldService.withdraw} can swap it back. Spread the result into
|
|
37307
|
+
* {@link LeverageYieldService.vaultSwap}: `vaultSwap({ ...payload, walletProvider })`.
|
|
37308
|
+
* An optional `partnerFee` is forwarded on the payload as the per-intent fee override.
|
|
37309
|
+
*
|
|
37310
|
+
* For `minOutputAmount`, quote via `sodax.swaps.getQuote` with the vault address as the
|
|
37311
|
+
* destination token (`token_dst`) — vault shares are solver-tradeable, so the generic swap
|
|
37312
|
+
* quote applies; then subtract your slippage tolerance.
|
|
37313
|
+
*/
|
|
37314
|
+
async deposit(params) {
|
|
37315
|
+
const baseCtx = { srcChainKey: params.srcChainKey, action: "deposit" };
|
|
37316
|
+
try {
|
|
37317
|
+
leverageYieldInvariant(params.inputAmount > 0n, "inputAmount must be greater than 0", {
|
|
37318
|
+
...baseCtx,
|
|
37319
|
+
field: "inputAmount"
|
|
37320
|
+
});
|
|
37321
|
+
leverageYieldInvariant(params.vault.length > 0, "Vault address is required", { ...baseCtx, field: "vault" });
|
|
37322
|
+
leverageYieldInvariant(params.inputToken.length > 0, "inputToken is required", {
|
|
37323
|
+
...baseCtx,
|
|
37324
|
+
field: "inputToken"
|
|
37325
|
+
});
|
|
37326
|
+
const hubWallet = await this.hubProvider.getUserHubWalletAddress(params.srcAddress, params.srcChainKey);
|
|
37327
|
+
const deadlineResult = await this.resolveDeadline(params.deadline, params.srcChainKey);
|
|
37328
|
+
if (!deadlineResult.ok) return deadlineResult;
|
|
37329
|
+
const deadline = deadlineResult.value;
|
|
37330
|
+
return {
|
|
37331
|
+
ok: true,
|
|
37332
|
+
value: {
|
|
37333
|
+
params: {
|
|
37334
|
+
inputToken: params.inputToken,
|
|
37335
|
+
outputToken: params.vault,
|
|
37336
|
+
inputAmount: params.inputAmount,
|
|
37337
|
+
minOutputAmount: params.minOutputAmount,
|
|
37338
|
+
deadline,
|
|
37339
|
+
allowPartialFill: false,
|
|
37340
|
+
srcChainKey: params.srcChainKey,
|
|
37341
|
+
dstChainKey: this.hubProvider.chainConfig.chain.key,
|
|
37342
|
+
srcAddress: params.srcAddress,
|
|
37343
|
+
dstAddress: hubWallet,
|
|
37344
|
+
solver: params.solver ?? ANY_SOLVER_ADDRESS,
|
|
37345
|
+
data: "0x"
|
|
37346
|
+
},
|
|
37347
|
+
// Per-intent fee override — only included when the caller supplies one, so the
|
|
37348
|
+
// payload stays free of undefined-valued keys.
|
|
37349
|
+
...params.partnerFee !== void 0 && { partnerFee: params.partnerFee }
|
|
37350
|
+
}
|
|
37351
|
+
};
|
|
37352
|
+
} catch (error) {
|
|
37353
|
+
if (isLeverageYieldCreateIntentError(error)) return { ok: false, error };
|
|
37354
|
+
return { ok: false, error: intentCreationFailed("leverageYield", error, baseCtx) };
|
|
37355
|
+
}
|
|
37356
|
+
}
|
|
37357
|
+
/**
|
|
37358
|
+
* Builds the {@link LeverageYieldSwapPayload} for a leverage-yield withdraw (lsoda* → any
|
|
37359
|
+
* token). The payload carries `hubWalletSwap: true` — {@link LeverageYieldService.vaultSwap}
|
|
37360
|
+
* then spends the lsoda* held in the user's hub wallet by authorising it via a
|
|
37361
|
+
* `Connection.sendMessage` the user signs on `srcChainKey`. Wrapped in a {@link Result} for
|
|
37362
|
+
* a call shape uniform with {@link LeverageYieldService.deposit}; async because the default
|
|
37363
|
+
* `deadline` is read from the hub block timestamp.
|
|
37364
|
+
*
|
|
37365
|
+
* For `minOutputAmount`, quote via `sodax.swaps.getQuote` with the vault address as the
|
|
37366
|
+
* source token (`token_src`) — vault shares are solver-tradeable, so the generic swap quote
|
|
37367
|
+
* applies; then subtract your slippage tolerance.
|
|
37368
|
+
*/
|
|
37369
|
+
async withdraw(params) {
|
|
37370
|
+
const baseCtx = { srcChainKey: params.srcChainKey, action: "withdraw" };
|
|
37371
|
+
try {
|
|
37372
|
+
leverageYieldInvariant(params.inputAmount > 0n, "inputAmount must be greater than 0", {
|
|
37373
|
+
...baseCtx,
|
|
37374
|
+
field: "inputAmount"
|
|
37375
|
+
});
|
|
37376
|
+
leverageYieldInvariant(params.vault.length > 0, "Vault address is required", { ...baseCtx, field: "vault" });
|
|
37377
|
+
leverageYieldInvariant(params.outputToken.length > 0, "outputToken is required", {
|
|
37378
|
+
...baseCtx,
|
|
37379
|
+
field: "outputToken"
|
|
37380
|
+
});
|
|
37381
|
+
const deadlineResult = await this.resolveDeadline(params.deadline, params.srcChainKey);
|
|
37382
|
+
if (!deadlineResult.ok) return deadlineResult;
|
|
37383
|
+
const deadline = deadlineResult.value;
|
|
37384
|
+
return {
|
|
37385
|
+
ok: true,
|
|
37386
|
+
value: {
|
|
37387
|
+
params: {
|
|
37388
|
+
inputToken: params.vault,
|
|
37389
|
+
outputToken: params.outputToken,
|
|
37390
|
+
inputAmount: params.inputAmount,
|
|
37391
|
+
minOutputAmount: params.minOutputAmount,
|
|
37392
|
+
deadline,
|
|
37393
|
+
allowPartialFill: false,
|
|
37394
|
+
srcChainKey: params.srcChainKey,
|
|
37395
|
+
dstChainKey: params.dstChainKey,
|
|
37396
|
+
srcAddress: params.srcAddress,
|
|
37397
|
+
dstAddress: params.recipient ?? params.srcAddress,
|
|
37398
|
+
solver: params.solver ?? ANY_SOLVER_ADDRESS,
|
|
37399
|
+
data: "0x"
|
|
37400
|
+
},
|
|
37401
|
+
hubWalletSwap: true
|
|
37402
|
+
}
|
|
37403
|
+
};
|
|
37404
|
+
} catch (error) {
|
|
37405
|
+
if (isLeverageYieldCreateIntentError(error)) return { ok: false, error };
|
|
37406
|
+
return { ok: false, error: intentCreationFailed("leverageYield", error, baseCtx) };
|
|
37407
|
+
}
|
|
37408
|
+
}
|
|
37409
|
+
/**
|
|
37410
|
+
* Creates a vault swap intent on the user's source spoke chain without submitting it to
|
|
37411
|
+
* the solver. Leverage-yield copy of the swap domain's `createIntent`, specialised for
|
|
37412
|
+
* vault flows — duplicated deliberately so the vault-specific execution modifiers
|
|
37413
|
+
* (`hubWalletSwap`, per-intent `partnerFee`) stay off the generic swap surface.
|
|
37414
|
+
*
|
|
37415
|
+
* Use {@link LeverageYieldService.vaultSwap} for the full end-to-end flow
|
|
37416
|
+
* (create → relay → notify solver); use this directly when you need the raw transaction
|
|
37417
|
+
* or drive the relay yourself (e.g. the backend submit-tx path). To complete a manual flow,
|
|
37418
|
+
* relay the returned `relayData` (the shared `relayTxAndWaitPacket` helper) and then call
|
|
37419
|
+
* {@link LeverageYieldService.notifySolver} with the hub-side intent tx hash.
|
|
37420
|
+
*
|
|
37421
|
+
* @param _params - Intent parameters, source chain key, wallet provider (when `raw: false`),
|
|
37422
|
+
* and optional `skipSimulation` / `hubWalletSwap` / `partnerFee`.
|
|
37423
|
+
* @returns A `Result<CreateVaultIntentResult<K, Raw>, LeverageYieldCreateIntentError>`.
|
|
37424
|
+
* On success contains:
|
|
37425
|
+
* - `tx` — chain-specific tx hash (executed) or raw tx data (raw mode).
|
|
37426
|
+
* - `intent` — the fully constructed `Intent` object augmented with `feeAmount`.
|
|
37427
|
+
* - `relayData` — `{ address, payload }` needed to submit the intent to the relayer.
|
|
37428
|
+
*
|
|
37429
|
+
* On failure `result.error` is a SodaxError with `VALIDATION_FAILED` (invariant
|
|
37430
|
+
* precondition), `INTENT_CREATION_FAILED` (spoke-side creation/deposit failed) or
|
|
37431
|
+
* `UNKNOWN` (defensive fallback).
|
|
37432
|
+
*/
|
|
37433
|
+
async createVaultIntent(_params) {
|
|
37434
|
+
const { params, skipSimulation, hubWalletSwap, partnerFee = this.config.swaps.partnerFee } = _params;
|
|
37435
|
+
const baseCtx = { srcChainKey: params.srcChainKey, dstChainKey: params.dstChainKey };
|
|
37436
|
+
try {
|
|
37437
|
+
leverageYieldInvariant(
|
|
37438
|
+
isUndefinedOrValidWalletProviderForChainKey(params.srcChainKey, _params.walletProvider),
|
|
37439
|
+
`Invalid wallet provider for chain key: ${params.srcChainKey}`,
|
|
37440
|
+
baseCtx
|
|
37441
|
+
);
|
|
37442
|
+
const hubChainKey = this.hubProvider.chainConfig.chain.key;
|
|
37443
|
+
const inputTokenChainKey = hubWalletSwap ? hubChainKey : params.srcChainKey;
|
|
37444
|
+
leverageYieldInvariant(
|
|
37445
|
+
this.config.isValidOriginalAssetAddress(inputTokenChainKey, params.inputToken),
|
|
37446
|
+
`Unsupported spoke chain token (srcChainKey: ${inputTokenChainKey}, inputToken: ${params.inputToken})`,
|
|
37447
|
+
{ ...baseCtx, field: "inputToken" }
|
|
37448
|
+
);
|
|
37449
|
+
leverageYieldInvariant(
|
|
37450
|
+
this.config.isValidOriginalAssetAddress(params.dstChainKey, params.outputToken),
|
|
37451
|
+
`Unsupported spoke chain token (params.dstChain: ${params.dstChainKey}, params.outputToken: ${params.outputToken})`,
|
|
37452
|
+
{ ...baseCtx, field: "outputToken" }
|
|
37453
|
+
);
|
|
37454
|
+
leverageYieldInvariant(
|
|
37455
|
+
this.config.isValidSpokeChainKey(params.srcChainKey),
|
|
37456
|
+
`Invalid spoke chain (srcChainKey): ${params.srcChainKey}`,
|
|
37457
|
+
{ ...baseCtx, field: "srcChainKey" }
|
|
37458
|
+
);
|
|
37459
|
+
leverageYieldInvariant(
|
|
37460
|
+
this.config.isValidSpokeChainKey(params.dstChainKey),
|
|
37461
|
+
`Invalid spoke chain (params.dstChain): ${params.dstChainKey}`,
|
|
37462
|
+
{ ...baseCtx, field: "dstChainKey" }
|
|
37463
|
+
);
|
|
37464
|
+
if (isBitcoinChainKey(params.dstChainKey) && params.outputToken === "BTC") {
|
|
37465
|
+
leverageYieldInvariant(
|
|
37466
|
+
params.minOutputAmount >= 546n,
|
|
37467
|
+
`Invalid minOutputAmount (params.minOutputAmount): ${params.minOutputAmount}`,
|
|
37468
|
+
{ ...baseCtx, field: "minOutputAmount" }
|
|
37469
|
+
);
|
|
37470
|
+
}
|
|
37471
|
+
const personalAddress = params.srcAddress;
|
|
37472
|
+
let walletAddress = personalAddress;
|
|
37473
|
+
if (isBitcoinChainKeyType(params.srcChainKey) && _params.raw === false) {
|
|
37474
|
+
leverageYieldInvariant(
|
|
37475
|
+
isBitcoinWalletProviderType(_params.walletProvider),
|
|
37476
|
+
`Invalid wallet provider for chain key: ${params.srcChainKey}`,
|
|
37477
|
+
baseCtx
|
|
37478
|
+
);
|
|
37479
|
+
walletAddress = await this.spoke.bitcoin.getEffectiveWalletAddress(personalAddress);
|
|
37480
|
+
await this.spoke.bitcoin.radfi.ensureRadfiAccessToken(_params.walletProvider);
|
|
37481
|
+
}
|
|
37482
|
+
const creatorHubWalletAddress = await this.hubProvider.getUserHubWalletAddress(walletAddress, params.srcChainKey);
|
|
37483
|
+
if (hubWalletSwap) {
|
|
37484
|
+
const [data2, intent2, feeAmount2] = EvmSolverService.constructCreateIntentData(
|
|
37485
|
+
{ ...params, srcChainKey: hubChainKey, srcAddress: creatorHubWalletAddress },
|
|
37486
|
+
creatorHubWalletAddress,
|
|
37487
|
+
this.config,
|
|
37488
|
+
partnerFee
|
|
37489
|
+
);
|
|
37490
|
+
const coreSendMessageParams = {
|
|
37491
|
+
srcChainKey: params.srcChainKey,
|
|
37492
|
+
// Personal address — NOT the resolved trading `walletAddress`. SpokeService.sendMessage
|
|
37493
|
+
// re-resolves the effective (Bitcoin trading) address itself; passing the already-resolved
|
|
37494
|
+
// trading address here would double-resolve it (getTradingWallet(tradingAddress) →
|
|
37495
|
+
// "Trading wallet not found"). The trading address is used only for the hub-wallet
|
|
37496
|
+
// derivation above (creatorHubWalletAddress). Mirrors MoneyMarketService borrow/withdraw.
|
|
37497
|
+
srcAddress: personalAddress,
|
|
37498
|
+
dstChainKey: hubChainKey,
|
|
37499
|
+
dstAddress: creatorHubWalletAddress,
|
|
37500
|
+
payload: data2,
|
|
37501
|
+
skipSimulation
|
|
37502
|
+
};
|
|
37503
|
+
const txResult2 = await this.spoke.sendMessage(
|
|
37504
|
+
_params.raw ? { ...coreSendMessageParams, raw: true } : {
|
|
37505
|
+
...coreSendMessageParams,
|
|
37506
|
+
raw: false,
|
|
37507
|
+
walletProvider: _params.walletProvider
|
|
37508
|
+
}
|
|
37509
|
+
);
|
|
37510
|
+
if (!txResult2.ok) {
|
|
37511
|
+
if (isLeverageYieldCreateIntentError(txResult2.error)) {
|
|
37512
|
+
return { ok: false, error: txResult2.error };
|
|
37513
|
+
}
|
|
37514
|
+
return { ok: false, error: intentCreationFailed("leverageYield", txResult2.error, baseCtx) };
|
|
37515
|
+
}
|
|
37516
|
+
return {
|
|
37517
|
+
ok: true,
|
|
37518
|
+
value: {
|
|
37519
|
+
tx: txResult2.value,
|
|
37520
|
+
intent: { ...intent2, feeAmount: feeAmount2 },
|
|
37521
|
+
relayData: { address: creatorHubWalletAddress, payload: data2 }
|
|
37522
|
+
}
|
|
37523
|
+
};
|
|
37524
|
+
}
|
|
37525
|
+
if (isHubChainKeyType(params.srcChainKey) && isSonicChainKeyType(params.srcChainKey)) {
|
|
37526
|
+
const coreSonicParams = {
|
|
37527
|
+
createIntentParams: params,
|
|
37528
|
+
creatorHubWalletAddress,
|
|
37529
|
+
solverConfig: this.config.solver,
|
|
37530
|
+
fee: partnerFee,
|
|
37531
|
+
hubProvider: this.hubProvider
|
|
37532
|
+
};
|
|
37533
|
+
const [txResult2, intent2, feeAmount2, data2] = await SonicSpokeService.createSwapIntent(
|
|
37534
|
+
_params.raw ? { ...coreSonicParams, raw: true } : {
|
|
37535
|
+
...coreSonicParams,
|
|
37536
|
+
raw: false,
|
|
37537
|
+
walletProvider: _params.walletProvider
|
|
37538
|
+
}
|
|
37539
|
+
);
|
|
37540
|
+
return {
|
|
37541
|
+
ok: true,
|
|
37542
|
+
value: {
|
|
37543
|
+
tx: txResult2,
|
|
37544
|
+
intent: { ...intent2, feeAmount: feeAmount2 },
|
|
37545
|
+
relayData: { address: intent2.creator, payload: data2 }
|
|
37546
|
+
}
|
|
37547
|
+
};
|
|
37548
|
+
}
|
|
37549
|
+
const [data, intent, feeAmount] = EvmSolverService.constructCreateIntentData(
|
|
37550
|
+
{
|
|
37551
|
+
...params,
|
|
37552
|
+
srcAddress: walletAddress
|
|
37553
|
+
},
|
|
37554
|
+
creatorHubWalletAddress,
|
|
37555
|
+
this.config,
|
|
37556
|
+
partnerFee
|
|
37557
|
+
);
|
|
37558
|
+
const coreDepositParams = {
|
|
37559
|
+
srcChainKey: params.srcChainKey,
|
|
37560
|
+
srcAddress: walletAddress,
|
|
37561
|
+
to: creatorHubWalletAddress,
|
|
37562
|
+
token: params.inputToken,
|
|
37563
|
+
amount: params.inputAmount,
|
|
37564
|
+
data,
|
|
37565
|
+
skipSimulation
|
|
37566
|
+
};
|
|
37567
|
+
const txResult = await this.spoke.deposit(
|
|
37568
|
+
_params.raw ? {
|
|
37569
|
+
...coreDepositParams,
|
|
37570
|
+
raw: true
|
|
37571
|
+
} : {
|
|
37572
|
+
...coreDepositParams,
|
|
37573
|
+
raw: false,
|
|
37574
|
+
walletProvider: _params.walletProvider
|
|
37575
|
+
}
|
|
37576
|
+
);
|
|
37577
|
+
if (!txResult.ok) {
|
|
37578
|
+
if (isLeverageYieldCreateIntentError(txResult.error)) {
|
|
37579
|
+
return { ok: false, error: txResult.error };
|
|
37580
|
+
}
|
|
37581
|
+
return {
|
|
37582
|
+
ok: false,
|
|
37583
|
+
error: intentCreationFailed("leverageYield", txResult.error, baseCtx)
|
|
37584
|
+
};
|
|
37585
|
+
}
|
|
37586
|
+
return {
|
|
37587
|
+
ok: true,
|
|
37588
|
+
value: {
|
|
37589
|
+
tx: txResult.value,
|
|
37590
|
+
intent: { ...intent, feeAmount },
|
|
37591
|
+
relayData: { address: intent.creator, payload: data }
|
|
37592
|
+
}
|
|
37593
|
+
};
|
|
37594
|
+
} catch (error) {
|
|
37595
|
+
if (isLeverageYieldCreateIntentError(error)) return { ok: false, error };
|
|
37596
|
+
return {
|
|
37597
|
+
ok: false,
|
|
37598
|
+
error: intentCreationFailed("leverageYield", error, baseCtx)
|
|
37599
|
+
};
|
|
37600
|
+
}
|
|
37601
|
+
}
|
|
37602
|
+
/**
|
|
37603
|
+
* Executes a full end-to-end leverage-yield vault swap (deposit or withdraw).
|
|
37604
|
+
* Leverage-yield copy of the swap domain's `swap()` orchestrator:
|
|
37605
|
+
* 1. Calls {@link LeverageYieldService.createVaultIntent} to submit the intent
|
|
37606
|
+
* transaction on the source spoke chain.
|
|
37607
|
+
* 2. Verifies the spoke transaction landed on-chain.
|
|
37608
|
+
* 3. For non-hub source chains: submits the spoke tx to the relayer and waits for the
|
|
37609
|
+
* relay packet to land on the hub (Sonic). Skipped when `srcChainKey` is the hub.
|
|
37610
|
+
* 4. Notifies the solver, triggering it to fill the intent.
|
|
37611
|
+
*
|
|
37612
|
+
* Spread a {@link LeverageYieldSwapPayload} from `deposit` / `withdraw` into this method
|
|
37613
|
+
* alongside the wallet provider: `vaultSwap({ ...payload, walletProvider })`.
|
|
37614
|
+
*
|
|
37615
|
+
* @returns A `Result<VaultSwapResponse, LeverageYieldSwapError>`. On success:
|
|
37616
|
+
* - `solverExecutionResponse` — solver acknowledgement (`{ answer: 'OK', intent_hash }`).
|
|
37617
|
+
* - `intent` — the on-chain intent object that was created.
|
|
37618
|
+
* - `intentDeliveryInfo` — source/destination chain keys, tx hashes, and user addresses.
|
|
37619
|
+
*
|
|
37620
|
+
* On failure `result.error` carries one of the create-intent codes plus
|
|
37621
|
+
* `TX_VERIFICATION_FAILED`, `TX_SUBMIT_FAILED`, `RELAY_TIMEOUT`, `RELAY_FAILED`,
|
|
37622
|
+
* `EXECUTION_FAILED`, `EXTERNAL_API_ERROR` or `UNKNOWN`.
|
|
37623
|
+
*/
|
|
37624
|
+
async vaultSwap(_params) {
|
|
37625
|
+
const { params } = _params;
|
|
37626
|
+
const srcChainKey = params.srcChainKey;
|
|
37627
|
+
const baseCtx = { srcChainKey, dstChainKey: params.dstChainKey, action: "vaultSwap" };
|
|
37628
|
+
try {
|
|
37629
|
+
const timeout = _params.timeout;
|
|
37630
|
+
const createIntentResult = await this.createVaultIntent(_params);
|
|
37631
|
+
if (!createIntentResult.ok) {
|
|
37632
|
+
return { ok: false, error: createIntentResult.error };
|
|
37633
|
+
}
|
|
37634
|
+
const { tx: spokeTxHash, intent, relayData } = createIntentResult.value;
|
|
37635
|
+
const verifyTxHashResult = await this.spoke.verifyTxHash({
|
|
37636
|
+
txHash: spokeTxHash,
|
|
37637
|
+
chainKey: srcChainKey
|
|
37638
|
+
});
|
|
37639
|
+
if (!verifyTxHashResult.ok) {
|
|
37640
|
+
return {
|
|
37641
|
+
ok: false,
|
|
37642
|
+
error: verifyFailed("leverageYield", verifyTxHashResult.error, baseCtx)
|
|
37643
|
+
};
|
|
37644
|
+
}
|
|
37645
|
+
let dstIntentTxHash;
|
|
37646
|
+
if (isHubChainKeyType(srcChainKey)) {
|
|
37647
|
+
dstIntentTxHash = spokeTxHash;
|
|
37648
|
+
} else {
|
|
37649
|
+
const packet = await relayTxAndWaitPacket({
|
|
37650
|
+
srcTxHash: spokeTxHash,
|
|
37651
|
+
data: relayData,
|
|
37652
|
+
chainKey: srcChainKey,
|
|
37653
|
+
relayerApiEndpoint: this.config.relay.relayerApiEndpoint,
|
|
37654
|
+
timeout
|
|
37655
|
+
});
|
|
37656
|
+
if (!packet.ok) {
|
|
37657
|
+
return {
|
|
37658
|
+
ok: false,
|
|
37659
|
+
error: mapRelayFailure(packet.error, { feature: "leverageYield", ...baseCtx })
|
|
37660
|
+
};
|
|
37661
|
+
}
|
|
37662
|
+
dstIntentTxHash = packet.value.dst_tx_hash;
|
|
37663
|
+
}
|
|
37664
|
+
const postExecResult = await this.notifySolver({
|
|
37665
|
+
intent_tx_hash: dstIntentTxHash
|
|
37666
|
+
});
|
|
37667
|
+
if (!postExecResult.ok) {
|
|
37668
|
+
return { ok: false, error: postExecResult.error };
|
|
37669
|
+
}
|
|
37670
|
+
return {
|
|
37671
|
+
ok: true,
|
|
37672
|
+
value: {
|
|
37673
|
+
solverExecutionResponse: postExecResult.value,
|
|
37674
|
+
intent,
|
|
37675
|
+
intentDeliveryInfo: {
|
|
37676
|
+
srcChainKey,
|
|
37677
|
+
srcTxHash: spokeTxHash,
|
|
37678
|
+
srcAddress: params.srcAddress,
|
|
37679
|
+
dstChainKey: params.dstChainKey,
|
|
37680
|
+
dstTxHash: dstIntentTxHash,
|
|
37681
|
+
dstAddress: params.dstAddress
|
|
37682
|
+
}
|
|
37683
|
+
}
|
|
37684
|
+
};
|
|
37685
|
+
} catch (error) {
|
|
37686
|
+
if (isLeverageYieldSwapError(error)) return { ok: false, error };
|
|
37687
|
+
return {
|
|
37688
|
+
ok: false,
|
|
37689
|
+
error: unknownFailed("leverageYield", error, baseCtx)
|
|
37690
|
+
};
|
|
37691
|
+
}
|
|
37692
|
+
}
|
|
37693
|
+
/**
|
|
37694
|
+
* Notifies the solver that the vault intent landed on the hub, triggering it to fill.
|
|
37695
|
+
* Leverage-yield copy of the swap domain's `postExecution` — emits only
|
|
37696
|
+
* `EXECUTION_FAILED` / `EXTERNAL_API_ERROR` / `UNKNOWN` (relay/verify codes appear only
|
|
37697
|
+
* on {@link LeverageYieldService.vaultSwap}, which owns the verify + relay steps).
|
|
37698
|
+
*
|
|
37699
|
+
* Called automatically by {@link LeverageYieldService.vaultSwap} after the relay packet
|
|
37700
|
+
* lands on the hub. Public so callers who created the intent via
|
|
37701
|
+
* {@link LeverageYieldService.createVaultIntent} and relayed it themselves can finish the
|
|
37702
|
+
* flow manually.
|
|
37703
|
+
*
|
|
37704
|
+
* @param request - `{ intent_tx_hash }` — the hub-chain (Sonic) tx hash where the intent
|
|
37705
|
+
* was registered (the relay packet's `dst_tx_hash`, or the spoke tx hash for hub-sourced
|
|
37706
|
+
* intents).
|
|
37707
|
+
*/
|
|
37708
|
+
async notifySolver(request) {
|
|
37709
|
+
try {
|
|
37710
|
+
const result = await SolverApiService.postExecution(request, this.config.solver, this.config.logger);
|
|
37711
|
+
if (result.ok) return result;
|
|
37712
|
+
const detail = result.error?.detail ?? {
|
|
37713
|
+
code: -999,
|
|
37714
|
+
// SolverIntentErrorCode.UNKNOWN
|
|
37715
|
+
message: "Solver returned malformed error response"
|
|
37716
|
+
};
|
|
37717
|
+
return {
|
|
37718
|
+
ok: false,
|
|
37719
|
+
error: new SodaxError("EXTERNAL_API_ERROR", detail.message, {
|
|
37720
|
+
feature: "leverageYield",
|
|
37721
|
+
context: {
|
|
37722
|
+
phase: "postExecution",
|
|
37723
|
+
api: "solver",
|
|
37724
|
+
solverCode: detail.code,
|
|
37725
|
+
solverDetail: detail
|
|
37726
|
+
}
|
|
37727
|
+
})
|
|
37728
|
+
};
|
|
37729
|
+
} catch (error) {
|
|
37730
|
+
if (isLeverageYieldPostExecutionError(error)) return { ok: false, error };
|
|
37731
|
+
return { ok: false, error: executionFailed("leverageYield", error, { phase: "postExecution" }) };
|
|
37732
|
+
}
|
|
37733
|
+
}
|
|
37734
|
+
/**
|
|
37735
|
+
* Approves the vault's underlying asset to the leverage vault on Sonic. For callers
|
|
37736
|
+
* interacting with the vault directly on the hub — the swap-style {@link
|
|
37737
|
+
* LeverageYieldService.deposit} flow handles its own approvals.
|
|
37738
|
+
*/
|
|
37739
|
+
async approve(params) {
|
|
37740
|
+
const baseCtx = { action: "approve" };
|
|
37741
|
+
try {
|
|
37742
|
+
leverageYieldInvariant(params.amount > 0n, "Amount must be greater than 0", { ...baseCtx, field: "amount" });
|
|
37743
|
+
leverageYieldInvariant(params.vault.length > 0, "Vault address is required", { ...baseCtx, field: "vault" });
|
|
37744
|
+
const assetResult = await this.getAsset(params.vault);
|
|
37745
|
+
if (!assetResult.ok) {
|
|
37746
|
+
return { ok: false, error: approveFailed("leverageYield", assetResult.error, baseCtx) };
|
|
37747
|
+
}
|
|
37748
|
+
const from = await params.walletProvider.getWalletAddress();
|
|
37749
|
+
const baseApprove = {
|
|
37750
|
+
token: assetResult.value,
|
|
37751
|
+
amount: params.amount,
|
|
37752
|
+
from,
|
|
37753
|
+
spender: params.vault
|
|
37754
|
+
};
|
|
37755
|
+
if (params.raw) {
|
|
37756
|
+
const tx2 = await Erc20Service.approve({ ...baseApprove, raw: true });
|
|
37757
|
+
return { ok: true, value: tx2 };
|
|
37758
|
+
}
|
|
37759
|
+
const tx = await Erc20Service.approve({
|
|
37760
|
+
...baseApprove,
|
|
37761
|
+
raw: false,
|
|
37762
|
+
walletProvider: params.walletProvider
|
|
37763
|
+
});
|
|
37764
|
+
return { ok: true, value: tx };
|
|
37765
|
+
} catch (error) {
|
|
37766
|
+
if (isLeverageYieldApproveError(error)) return { ok: false, error };
|
|
37767
|
+
return { ok: false, error: approveFailed("leverageYield", error, baseCtx) };
|
|
37768
|
+
}
|
|
37769
|
+
}
|
|
37770
|
+
/**
|
|
37771
|
+
* Reads on-chain allowance of the vault's underlying asset for `owner → vault`. Returns
|
|
37772
|
+
* `true` when the allowance covers `amount`. Use before a direct
|
|
37773
|
+
* {@link LeverageYieldService.deposit}.
|
|
37774
|
+
*/
|
|
37775
|
+
async isAllowanceValid(params) {
|
|
37776
|
+
const baseCtx = { action: "allowanceCheck" };
|
|
37777
|
+
try {
|
|
37778
|
+
leverageYieldInvariant(params.amount > 0n, "Amount must be greater than 0", { ...baseCtx, field: "amount" });
|
|
37779
|
+
const assetResult = await this.getAsset(params.vault);
|
|
37780
|
+
if (!assetResult.ok) {
|
|
37781
|
+
return { ok: false, error: allowanceCheckFailed("leverageYield", assetResult.error, baseCtx) };
|
|
37782
|
+
}
|
|
37783
|
+
const allowance = await this.hubProvider.publicClient.readContract({
|
|
37784
|
+
address: assetResult.value,
|
|
37785
|
+
abi: viem.erc20Abi,
|
|
37786
|
+
functionName: "allowance",
|
|
37787
|
+
args: [params.owner, params.vault]
|
|
37788
|
+
});
|
|
37789
|
+
return { ok: true, value: allowance >= params.amount };
|
|
37790
|
+
} catch (error) {
|
|
37791
|
+
if (isLeverageYieldAllowanceCheckError(error)) return { ok: false, error };
|
|
37792
|
+
return { ok: false, error: allowanceCheckFailed("leverageYield", error, baseCtx) };
|
|
37793
|
+
}
|
|
37794
|
+
}
|
|
37795
|
+
// ─── Reads ──────────────────────────────────────────────────────────────
|
|
37796
|
+
/** ERC-4626 `asset()` of the vault — the sodaWEETH-style underlying. */
|
|
37797
|
+
async getAsset(vault) {
|
|
37798
|
+
try {
|
|
37799
|
+
const value = await this.hubProvider.publicClient.readContract({
|
|
37800
|
+
address: vault,
|
|
37801
|
+
abi: leverageYieldVaultAbi,
|
|
37802
|
+
functionName: "asset"
|
|
37803
|
+
});
|
|
37804
|
+
return { ok: true, value };
|
|
37805
|
+
} catch (error) {
|
|
37806
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
37807
|
+
return { ok: false, error: lookupFailed("leverageYield", "getAsset", error) };
|
|
37808
|
+
}
|
|
37809
|
+
}
|
|
37810
|
+
/** Reads the vault's leveraged position snapshot via the non-standard `getPositionDetails`. */
|
|
37811
|
+
async getPosition(vault) {
|
|
37812
|
+
try {
|
|
37813
|
+
const [collateral, debt, ltv, healthFactor, idleAsset] = await this.hubProvider.publicClient.readContract({
|
|
37814
|
+
address: vault,
|
|
37815
|
+
abi: leverageYieldVaultAbi,
|
|
37816
|
+
functionName: "getPositionDetails"
|
|
37817
|
+
});
|
|
37818
|
+
return { ok: true, value: { collateral, debt, ltv, healthFactor, idleAsset } };
|
|
37819
|
+
} catch (error) {
|
|
37820
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
37821
|
+
return { ok: false, error: lookupFailed("leverageYield", "getPosition", error) };
|
|
37822
|
+
}
|
|
37823
|
+
}
|
|
37824
|
+
/**
|
|
37825
|
+
* Computes the steady-state APR of a leverage-yield vault from the AAVE supply/borrow
|
|
37826
|
+
* rates of its asset and borrowToken, scaled by the vault's target leverage. Matches the
|
|
37827
|
+
* convention used by leveraged-LSD vaults (Origami, Gearbox, etc.) — assumes constant
|
|
37828
|
+
* LTV at `targetLTV` and constant AAVE rates.
|
|
37829
|
+
*
|
|
37830
|
+
* Returns raw fields in RAY (1e27, AAVE's native rate scale) plus the leverage multiplier
|
|
37831
|
+
* in WAD (1e18). See {@link LeverageYieldApr} for the formula and caveats.
|
|
37832
|
+
*/
|
|
37833
|
+
async getApr(vault) {
|
|
37834
|
+
try {
|
|
37835
|
+
const [pool, asset, borrowToken, targetLtvBps] = await Promise.all([
|
|
37836
|
+
this.hubProvider.publicClient.readContract({
|
|
37837
|
+
address: vault,
|
|
37838
|
+
abi: leverageYieldVaultAbi,
|
|
37839
|
+
functionName: "pool"
|
|
37840
|
+
}),
|
|
37841
|
+
this.hubProvider.publicClient.readContract({
|
|
37842
|
+
address: vault,
|
|
37843
|
+
abi: leverageYieldVaultAbi,
|
|
37844
|
+
functionName: "asset"
|
|
37845
|
+
}),
|
|
37846
|
+
this.hubProvider.publicClient.readContract({
|
|
37847
|
+
address: vault,
|
|
37848
|
+
abi: leverageYieldVaultAbi,
|
|
37849
|
+
functionName: "borrowToken"
|
|
37850
|
+
}),
|
|
37851
|
+
this.hubProvider.publicClient.readContract({
|
|
37852
|
+
address: vault,
|
|
37853
|
+
abi: leverageYieldVaultAbi,
|
|
37854
|
+
functionName: "targetLTV"
|
|
37855
|
+
})
|
|
37856
|
+
]);
|
|
37857
|
+
const [assetReserve, borrowReserve] = await Promise.all([
|
|
37858
|
+
this.hubProvider.publicClient.readContract({
|
|
37859
|
+
address: pool,
|
|
37860
|
+
abi: poolAbi,
|
|
37861
|
+
functionName: "getReserveData",
|
|
37862
|
+
args: [asset]
|
|
37863
|
+
}),
|
|
37864
|
+
this.hubProvider.publicClient.readContract({
|
|
37865
|
+
address: pool,
|
|
37866
|
+
abi: poolAbi,
|
|
37867
|
+
functionName: "getReserveData",
|
|
37868
|
+
args: [borrowToken]
|
|
37869
|
+
})
|
|
37870
|
+
]);
|
|
37871
|
+
const supplyAprRay = assetReserve.currentLiquidityRate;
|
|
37872
|
+
const borrowAprRay = borrowReserve.currentVariableBorrowRate;
|
|
37873
|
+
const BPS = 10000n;
|
|
37874
|
+
const WAD2 = 1000000000000000000n;
|
|
37875
|
+
leverageYieldInvariant(targetLtvBps < BPS, `targetLTV (${targetLtvBps}) must be < 100% (10_000 bps)`, {
|
|
37876
|
+
method: "getApr",
|
|
37877
|
+
field: "targetLtvBps"
|
|
37878
|
+
});
|
|
37879
|
+
const leverageMultiplierWad = targetLtvBps * WAD2 / (BPS - targetLtvBps);
|
|
37880
|
+
const spreadRay = supplyAprRay - borrowAprRay;
|
|
37881
|
+
const netAprRay = supplyAprRay + spreadRay * leverageMultiplierWad / WAD2;
|
|
37882
|
+
return {
|
|
37883
|
+
ok: true,
|
|
37884
|
+
value: { supplyAprRay, borrowAprRay, targetLtvBps, leverageMultiplierWad, netAprRay }
|
|
37885
|
+
};
|
|
37886
|
+
} catch (error) {
|
|
37887
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
37888
|
+
return { ok: false, error: lookupFailed("leverageYield", "getApr", error) };
|
|
37889
|
+
}
|
|
37890
|
+
}
|
|
37891
|
+
/**
|
|
37892
|
+
* Off-chain LSD staking-APR for the vault's underlying asset. Looks the vault up in the
|
|
37893
|
+
* registry, hits DefiLlama's per-pool chart endpoint for the configured `poolId`, and on
|
|
37894
|
+
* any fetch failure returns the registry's hardcoded `fallbackAprPct` with `stale: true`.
|
|
37895
|
+
*
|
|
37896
|
+
* Always resolves to `{ ok: true, ... }` for a known vault — the fallback path replaces
|
|
37897
|
+
* the error, since a missing LSD APR shouldn't break the parent call. Returns
|
|
37898
|
+
* `{ aprRay: 0n, stale: true, label: 'no LSD source' }` for vaults without an
|
|
37899
|
+
* `lsdSource` configured (non-LSD strategies); callers can treat that as "skip LSD".
|
|
37900
|
+
*/
|
|
37901
|
+
async getLsdApr(vault) {
|
|
37902
|
+
try {
|
|
37903
|
+
const cfg = this.getVaultByAddress(vault);
|
|
37904
|
+
const source = cfg?.lsdSource;
|
|
37905
|
+
if (!source) {
|
|
37906
|
+
return { ok: true, value: { aprRay: 0n, label: "no LSD source", stale: true } };
|
|
37907
|
+
}
|
|
37908
|
+
try {
|
|
37909
|
+
const aprPct = await fetchDefillamaApr(source.poolId);
|
|
37910
|
+
return { ok: true, value: { aprRay: pctToRay(aprPct), label: source.label, stale: false } };
|
|
37911
|
+
} catch (fetchError) {
|
|
37912
|
+
this.config.logger.warn("[leverageYield] DefiLlama APR fetch failed; using fallbackAprPct", {
|
|
37913
|
+
vault,
|
|
37914
|
+
poolId: source.poolId,
|
|
37915
|
+
fallbackAprPct: source.fallbackAprPct,
|
|
37916
|
+
error: fetchError instanceof Error ? fetchError.message : String(fetchError)
|
|
37917
|
+
});
|
|
37918
|
+
return {
|
|
37919
|
+
ok: true,
|
|
37920
|
+
value: { aprRay: pctToRay(source.fallbackAprPct), label: `${source.label} (fallback)`, stale: true }
|
|
37921
|
+
};
|
|
37922
|
+
}
|
|
37923
|
+
} catch (error) {
|
|
37924
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
37925
|
+
return { ok: false, error: lookupFailed("leverageYield", "getLsdApr", error) };
|
|
37926
|
+
}
|
|
37927
|
+
}
|
|
37928
|
+
/**
|
|
37929
|
+
* Combined view of {@link getApr} + {@link getLsdApr}: re-applies the vault's leverage
|
|
37930
|
+
* formula with the LSD's native staking yield folded into the supply side, exposing the
|
|
37931
|
+
* **effective** net APR that LSD-backed strategies actually earn. The AAVE-only
|
|
37932
|
+
* `netAprRay` is preserved on the return value for callers who want to display both.
|
|
37933
|
+
*
|
|
37934
|
+
* effectiveSupply = supplyAprRay + lsdApr.aprRay
|
|
37935
|
+
* effectiveNet = effectiveSupply + leverage × (effectiveSupply − borrowAprRay)
|
|
37936
|
+
*
|
|
37937
|
+
* Fetches AAVE rates and the LSD APR in parallel for one round-trip's worth of latency.
|
|
37938
|
+
*/
|
|
37939
|
+
async getEffectiveApr(vault) {
|
|
37940
|
+
try {
|
|
37941
|
+
const [aprResult, lsdResult] = await Promise.all([this.getApr(vault), this.getLsdApr(vault)]);
|
|
37942
|
+
if (!aprResult.ok) return aprResult;
|
|
37943
|
+
if (!lsdResult.ok) return lsdResult;
|
|
37944
|
+
const apr = aprResult.value;
|
|
37945
|
+
const lsd = lsdResult.value;
|
|
37946
|
+
const effectiveSupplyAprRay = apr.supplyAprRay + lsd.aprRay;
|
|
37947
|
+
const spreadRay = effectiveSupplyAprRay - apr.borrowAprRay;
|
|
37948
|
+
const WAD2 = 1000000000000000000n;
|
|
37949
|
+
const effectiveNetAprRay = effectiveSupplyAprRay + spreadRay * apr.leverageMultiplierWad / WAD2;
|
|
37950
|
+
return {
|
|
37951
|
+
ok: true,
|
|
37952
|
+
value: { ...apr, lsdApr: lsd, effectiveSupplyAprRay, effectiveNetAprRay }
|
|
37953
|
+
};
|
|
37954
|
+
} catch (error) {
|
|
37955
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
37956
|
+
return { ok: false, error: lookupFailed("leverageYield", "getEffectiveApr", error) };
|
|
37957
|
+
}
|
|
37958
|
+
}
|
|
37959
|
+
/** Synchronously withdrawable assets for `owner` (clamped against leverage HF floor). */
|
|
37960
|
+
async getMaxWithdraw(vault, owner) {
|
|
37961
|
+
const inner = await Erc4626Service.getMaxWithdraw(vault, owner, this.hubProvider.publicClient);
|
|
37962
|
+
if (!inner.ok) return { ok: false, error: lookupFailed("leverageYield", "getMaxWithdraw", inner.error) };
|
|
37963
|
+
return { ok: true, value: inner.value };
|
|
37964
|
+
}
|
|
37965
|
+
/** Total underlying assets currently held by the vault (vault-asset units, 18 decimals) — TVL. */
|
|
37966
|
+
async getTotalAssets(vault) {
|
|
37967
|
+
const inner = await Erc4626Service.getTotalAssets(vault, this.hubProvider.publicClient);
|
|
37968
|
+
if (!inner.ok) return { ok: false, error: lookupFailed("leverageYield", "getTotalAssets", inner.error) };
|
|
37969
|
+
return { ok: true, value: inner.value };
|
|
37970
|
+
}
|
|
37971
|
+
/** Shares minted for a given asset deposit. */
|
|
37972
|
+
async previewDeposit(vault, assets) {
|
|
37973
|
+
const inner = await Erc4626Service.previewDeposit(vault, assets, this.hubProvider.publicClient);
|
|
37974
|
+
if (!inner.ok) return { ok: false, error: lookupFailed("leverageYield", "previewDeposit", inner.error) };
|
|
37975
|
+
return { ok: true, value: inner.value };
|
|
37976
|
+
}
|
|
37977
|
+
/** Shares burned for a given asset withdrawal. */
|
|
37978
|
+
async previewWithdraw(vault, assets) {
|
|
37979
|
+
const inner = await Erc4626Service.previewWithdraw(vault, assets, this.hubProvider.publicClient);
|
|
37980
|
+
if (!inner.ok) return { ok: false, error: lookupFailed("leverageYield", "previewWithdraw", inner.error) };
|
|
37981
|
+
return { ok: true, value: inner.value };
|
|
37982
|
+
}
|
|
37983
|
+
/** Assets received for a given share redemption. */
|
|
37984
|
+
async previewRedeem(vault, shares) {
|
|
37985
|
+
const inner = await Erc4626Service.previewRedeem(vault, shares, this.hubProvider.publicClient);
|
|
37986
|
+
if (!inner.ok) return { ok: false, error: lookupFailed("leverageYield", "previewRedeem", inner.error) };
|
|
37987
|
+
return { ok: true, value: inner.value };
|
|
37988
|
+
}
|
|
37989
|
+
/** Vault shares held by `owner`. */
|
|
37990
|
+
async getShareBalance(vault, owner) {
|
|
37991
|
+
try {
|
|
37992
|
+
const value = await this.hubProvider.publicClient.readContract({
|
|
37993
|
+
address: vault,
|
|
37994
|
+
abi: viem.erc20Abi,
|
|
37995
|
+
functionName: "balanceOf",
|
|
37996
|
+
args: [owner]
|
|
37997
|
+
});
|
|
37998
|
+
return { ok: true, value };
|
|
37999
|
+
} catch (error) {
|
|
38000
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38001
|
+
return { ok: false, error: lookupFailed("leverageYield", "getShareBalance", error) };
|
|
38002
|
+
}
|
|
38003
|
+
}
|
|
38004
|
+
/**
|
|
38005
|
+
* Convenience: resolves the user's hub wallet from `(srcChainKey, srcAddress)` and
|
|
38006
|
+
* returns its on-chain `maxWithdraw`, less {@link MAX_WITHDRAW_DUST_BUFFER}. The trim
|
|
38007
|
+
* keeps the value safe for an asset-denominated ERC-4626 `withdraw` — the raw
|
|
38008
|
+
* `maxWithdraw` can trip the round-up that asks for one more share than the user holds.
|
|
38009
|
+
*/
|
|
38010
|
+
async getMaxWithdrawForUser(vault, srcChainKey, srcAddress) {
|
|
38011
|
+
try {
|
|
38012
|
+
const hubWallet = await this.hubProvider.getUserHubWalletAddress(srcAddress, srcChainKey);
|
|
38013
|
+
const maxWithdrawResult = await this.getMaxWithdraw(vault, hubWallet);
|
|
38014
|
+
if (!maxWithdrawResult.ok) return maxWithdrawResult;
|
|
38015
|
+
const buffered = maxWithdrawResult.value > MAX_WITHDRAW_DUST_BUFFER ? maxWithdrawResult.value - MAX_WITHDRAW_DUST_BUFFER : 0n;
|
|
38016
|
+
return { ok: true, value: buffered };
|
|
38017
|
+
} catch (error) {
|
|
38018
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38019
|
+
return { ok: false, error: lookupFailed("leverageYield", "getMaxWithdrawForUser", error, { srcChainKey }) };
|
|
38020
|
+
}
|
|
38021
|
+
}
|
|
38022
|
+
/**
|
|
38023
|
+
* Convenience: resolves the user's hub wallet from `(srcChainKey, srcAddress)` and
|
|
38024
|
+
* returns its on-chain share balance.
|
|
38025
|
+
*/
|
|
38026
|
+
async getShareBalanceForUser(vault, srcChainKey, srcAddress) {
|
|
38027
|
+
try {
|
|
38028
|
+
const hubWallet = await this.hubProvider.getUserHubWalletAddress(srcAddress, srcChainKey);
|
|
38029
|
+
return await this.getShareBalance(vault, hubWallet);
|
|
38030
|
+
} catch (error) {
|
|
38031
|
+
if (isLeverageYieldLookupError(error)) return { ok: false, error };
|
|
38032
|
+
return { ok: false, error: lookupFailed("leverageYield", "getShareBalanceForUser", error, { srcChainKey }) };
|
|
38033
|
+
}
|
|
38034
|
+
}
|
|
38035
|
+
};
|
|
38036
|
+
|
|
37118
38037
|
// src/shared/entities/Sodax.ts
|
|
37119
38038
|
var Sodax = class {
|
|
37120
38039
|
instanceConfig;
|
|
@@ -37136,6 +38055,8 @@ var Sodax = class {
|
|
|
37136
38055
|
// Recovery service for withdrawing stuck hub-wallet assets back to a spoke chain
|
|
37137
38056
|
dex;
|
|
37138
38057
|
// Dex service enabling DEX operations
|
|
38058
|
+
leverageYield;
|
|
38059
|
+
// Leverage-yield service: cross-chain deposits / withdrawals into ERC-4626 leverage vaults on Sonic
|
|
37139
38060
|
config;
|
|
37140
38061
|
// Config service enabling configuration data fetching from the backend API or fallbacking to default values
|
|
37141
38062
|
hubProvider;
|
|
@@ -37181,6 +38102,11 @@ var Sodax = class {
|
|
|
37181
38102
|
config: this.config,
|
|
37182
38103
|
spoke: this.spoke
|
|
37183
38104
|
});
|
|
38105
|
+
this.leverageYield = new LeverageYieldService({
|
|
38106
|
+
hubProvider: this.hubProvider,
|
|
38107
|
+
config: this.config,
|
|
38108
|
+
spoke: this.spoke
|
|
38109
|
+
});
|
|
37184
38110
|
}
|
|
37185
38111
|
/**
|
|
37186
38112
|
* Initializes the Sodax instance with dynamic configuration.
|
|
@@ -37289,8 +38215,11 @@ exports.IntentsAbi = IntentsAbi;
|
|
|
37289
38215
|
exports.LOOKUP_CODES = LOOKUP_CODES;
|
|
37290
38216
|
exports.LTV_PRECISION = LTV_PRECISION;
|
|
37291
38217
|
exports.LendingPoolService = LendingPoolService;
|
|
38218
|
+
exports.LeverageYieldService = LeverageYieldService;
|
|
37292
38219
|
exports.LockupMultiplier = LockupMultiplier;
|
|
37293
38220
|
exports.LockupPeriod = LockupPeriod;
|
|
38221
|
+
exports.LsodaSymbols = LsodaSymbols;
|
|
38222
|
+
exports.LsodaTokens = LsodaTokens;
|
|
37294
38223
|
exports.MAX_UINT256 = MAX_UINT256;
|
|
37295
38224
|
exports.MigrationService = MigrationService;
|
|
37296
38225
|
exports.MintPositionEventAbi = MintPositionEventAbi;
|
|
@@ -37475,6 +38404,13 @@ exports.isInjectiveChainKeyType = isInjectiveChainKeyType;
|
|
|
37475
38404
|
exports.isJsonRpcPayloadResponse = isJsonRpcPayloadResponse;
|
|
37476
38405
|
exports.isLegacybnUSDChainId = isLegacybnUSDChainId;
|
|
37477
38406
|
exports.isLegacybnUSDToken = isLegacybnUSDToken;
|
|
38407
|
+
exports.isLeverageYieldAllowanceCheckError = isLeverageYieldAllowanceCheckError;
|
|
38408
|
+
exports.isLeverageYieldApproveError = isLeverageYieldApproveError;
|
|
38409
|
+
exports.isLeverageYieldCreateIntentError = isLeverageYieldCreateIntentError;
|
|
38410
|
+
exports.isLeverageYieldError = isLeverageYieldError;
|
|
38411
|
+
exports.isLeverageYieldLookupError = isLeverageYieldLookupError;
|
|
38412
|
+
exports.isLeverageYieldPostExecutionError = isLeverageYieldPostExecutionError;
|
|
38413
|
+
exports.isLeverageYieldSwapError = isLeverageYieldSwapError;
|
|
37478
38414
|
exports.isMigrateOrchestrationError = isMigrateOrchestrationError;
|
|
37479
38415
|
exports.isMigrationAllowanceCheckError = isMigrationAllowanceCheckError;
|
|
37480
38416
|
exports.isMigrationApproveError = isMigrationApproveError;
|
|
@@ -37541,6 +38477,9 @@ exports.isUndefinedOrValidWalletProviderForChainKey = isUndefinedOrValidWalletPr
|
|
|
37541
38477
|
exports.isUnifiedBnUSDMigrateParams = isUnifiedBnUSDMigrateParams;
|
|
37542
38478
|
exports.isValidWalletProviderForChainKey = isValidWalletProviderForChainKey;
|
|
37543
38479
|
exports.kaiaSupportedTokens = kaiaSupportedTokens;
|
|
38480
|
+
exports.leverageYieldConfig = leverageYieldConfig;
|
|
38481
|
+
exports.leverageYieldInvariant = leverageYieldInvariant;
|
|
38482
|
+
exports.leverageYieldVaults = leverageYieldVaults;
|
|
37544
38483
|
exports.lightlinkSupportedTokens = lightlinkSupportedTokens;
|
|
37545
38484
|
exports.lookupFailed = lookupFailed;
|
|
37546
38485
|
exports.mapRelayFailure = mapRelayFailure;
|