@suilend/sdk 3.0.8 → 5.0.0
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/_generated/_dependencies/source/0x1/ascii/structs.d.ts +4 -4
- package/_generated/_dependencies/source/0x1/ascii/structs.js +42 -41
- package/_generated/_dependencies/source/0x1/option/structs.js +22 -26
- package/_generated/_dependencies/source/0x1/type-name/structs.d.ts +3 -3
- package/_generated/_dependencies/source/0x1/type-name/structs.js +21 -25
- package/_generated/_dependencies/source/0x2/bag/structs.d.ts +5 -5
- package/_generated/_dependencies/source/0x2/bag/structs.js +22 -25
- package/_generated/_dependencies/source/0x2/balance/structs.d.ts +4 -4
- package/_generated/_dependencies/source/0x2/balance/structs.js +42 -41
- package/_generated/_dependencies/source/0x2/object/structs.d.ts +5 -5
- package/_generated/_dependencies/source/0x2/object/structs.js +42 -41
- package/_generated/_dependencies/source/0x2/object-table/structs.d.ts +5 -5
- package/_generated/_dependencies/source/0x2/object-table/structs.js +22 -25
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/i64/structs.d.ts +3 -3
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/i64/structs.js +22 -25
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price/structs.d.ts +9 -9
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price/structs.js +24 -25
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-feed/structs.d.ts +21 -21
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-feed/structs.js +23 -25
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs.d.ts +2 -2
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs.js +21 -25
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-info/structs.d.ts +52 -52
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-info/structs.js +45 -41
- package/_generated/_framework/vector.js +9 -6
- package/_generated/suilend/cell/structs.d.ts +1 -1
- package/_generated/suilend/cell/structs.js +21 -25
- package/_generated/suilend/decimal/structs.d.ts +2 -2
- package/_generated/suilend/decimal/structs.js +21 -25
- package/_generated/suilend/lending-market/structs.d.ts +129 -129
- package/_generated/suilend/lending-market/structs.js +391 -265
- package/_generated/suilend/liquidity-mining/structs.d.ts +44 -44
- package/_generated/suilend/liquidity-mining/structs.js +122 -89
- package/_generated/suilend/obligation/structs.d.ts +98 -98
- package/_generated/suilend/obligation/structs.js +194 -121
- package/_generated/suilend/rate-limiter/structs.d.ts +12 -12
- package/_generated/suilend/rate-limiter/structs.js +46 -41
- package/_generated/suilend/reserve/structs.d.ts +128 -128
- package/_generated/suilend/reserve/structs.js +243 -153
- package/_generated/suilend/reserve-config/structs.d.ts +30 -30
- package/_generated/suilend/reserve-config/structs.js +60 -41
- package/api/events.js +5 -14
- package/client.js +267 -319
- package/lib/initialize.d.ts +85 -3
- package/lib/initialize.js +119 -52
- package/lib/liquidityMining.js +15 -19
- package/lib/pyth.d.ts +16 -0
- package/lib/pyth.js +30 -15
- package/lib/pythAdapter.js +96 -112
- package/lib/strategyOwnerCap.js +8 -17
- package/margin/margin/admin_cap.d.ts +2 -2
- package/margin/margin/deps/std/type_name.d.ts +1 -1
- package/margin/margin/deps/suilend/lending_market.d.ts +2 -2
- package/margin/margin/market.d.ts +11 -11
- package/margin/margin/market.js +22 -22
- package/margin/margin/permissions.js +14 -14
- package/margin/margin/position.d.ts +47 -47
- package/margin/margin/position.js +10 -10
- package/margin/margin/router.d.ts +5 -5
- package/margin/margin/router.js +16 -16
- package/margin/margin/version.d.ts +1 -1
- package/margin/utils/index.js +22 -36
- package/package.json +1 -1
- package/parsers/apiReserveAssetDataEvent.js +4 -1
- package/parsers/lendingMarket.js +3 -4
- package/parsers/reserve.js +4 -1
- package/strategies.js +188 -204
- package/swap/quote.d.ts +1 -1
- package/swap/quote.js +28 -39
- package/swap/transaction.js +17 -26
- package/utils/events.js +20 -32
- package/utils/obligation.js +111 -135
- package/utils/simulate.d.ts +68 -1
- package/utils/simulate.js +149 -31
package/strategies.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { bcs } from "@mysten/bcs";
|
|
11
2
|
import { Transaction, } from "@mysten/sui/transactions";
|
|
12
3
|
import { SUI_DECIMALS } from "@mysten/sui/utils";
|
|
@@ -14,7 +5,7 @@ import BigNumber from "bignumber.js";
|
|
|
14
5
|
import { BN } from "bn.js";
|
|
15
6
|
import cloneDeep from "lodash/cloneDeep.js";
|
|
16
7
|
import { LstClient, SPRING_SUI_UPGRADE_CAP_ID, getLatestPackageId as getLatestSpringSuiPackageId, } from "@suilend/springsui-sdk";
|
|
17
|
-
import { API_URL, MAX_U64, MS_PER_YEAR, NORMALIZED_AUSD_COINTYPE, NORMALIZED_SUI_COINTYPE, NORMALIZED_USDC_COINTYPE, NORMALIZED_sSUI_COINTYPE, NORMALIZED_suiUSDT_COINTYPE, NORMALIZED_suiWBTC_COINTYPE, NORMALIZED_xBTC_COINTYPE, getSpendableCoin, isSui, } from "@suilend/sui-
|
|
8
|
+
import { API_URL, MAX_U64, MS_PER_YEAR, NORMALIZED_AUSD_COINTYPE, NORMALIZED_SUI_COINTYPE, NORMALIZED_USDC_COINTYPE, NORMALIZED_sSUI_COINTYPE, NORMALIZED_suiUSDT_COINTYPE, NORMALIZED_suiWBTC_COINTYPE, NORMALIZED_xBTC_COINTYPE, getSpendableCoin, isSui, } from "@suilend/sui-core";
|
|
18
9
|
import { getNetAprPercent } from "./lib/index.js";
|
|
19
10
|
import { getRewardsMap } from "./lib/liquidityMining.js";
|
|
20
11
|
import { STRATEGY_TYPE_INFO_MAP, StrategyType, strategyBorrow, strategyClaimRewardsAndMergeCoins, strategyDeposit, strategyWithdraw, } from "./lib/strategyOwnerCap.js";
|
|
@@ -158,11 +149,9 @@ export const hasStrategyPosition = (obligation) => obligation.deposits.length >
|
|
|
158
149
|
// SUI
|
|
159
150
|
export const getStrategySuiReserve = (
|
|
160
151
|
// AppContext
|
|
161
|
-
reserveMap) =>
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
};
|
|
165
|
-
export const fetchStrategyLstMap = (suiGrpcClient) => __awaiter(void 0, void 0, void 0, function* () {
|
|
152
|
+
reserveMap) => reserveMap[NORMALIZED_SUI_COINTYPE] ??
|
|
153
|
+
{ price: new BigNumber(1) };
|
|
154
|
+
export const fetchStrategyLstMap = async (suiGrpcClient) => {
|
|
166
155
|
try {
|
|
167
156
|
const lstCoinTypes = Array.from(new Set([
|
|
168
157
|
...Object.values(STRATEGY_TYPE_INFO_MAP)
|
|
@@ -171,26 +160,27 @@ export const fetchStrategyLstMap = (suiGrpcClient) => __awaiter(void 0, void 0,
|
|
|
171
160
|
// LSTs that will be/are/have been used as rewards
|
|
172
161
|
NORMALIZED_sSUI_COINTYPE,
|
|
173
162
|
]));
|
|
174
|
-
const publishedAt =
|
|
163
|
+
const publishedAt = await getLatestSpringSuiPackageId(suiGrpcClient, SPRING_SUI_UPGRADE_CAP_ID);
|
|
175
164
|
const lstInfoUrl = `${API_URL}/springsui/lst-info?${new URLSearchParams({
|
|
176
165
|
coinTypes: lstCoinTypes.join(","),
|
|
177
166
|
})}`;
|
|
178
|
-
const lstInfoRes =
|
|
179
|
-
const lstInfoJson =
|
|
180
|
-
if (
|
|
167
|
+
const lstInfoRes = await fetch(lstInfoUrl);
|
|
168
|
+
const lstInfoJson = await lstInfoRes.json();
|
|
169
|
+
if (lstInfoRes?.statusCode === 500)
|
|
181
170
|
throw new Error("Failed to fetch LST info");
|
|
182
171
|
const lstInfoMap = Object.fromEntries(Object.entries(lstInfoJson).map(([lstCoinType, lstInfo]) => {
|
|
183
172
|
return [lstCoinType, lstInfo];
|
|
184
173
|
}));
|
|
185
|
-
const result = Object.fromEntries(
|
|
186
|
-
var _a, _b, _c, _d;
|
|
174
|
+
const result = Object.fromEntries(await Promise.all(lstCoinTypes.map(async (lstCoinType) => {
|
|
187
175
|
const lstInfo = lstInfoMap[lstCoinType];
|
|
188
|
-
const lstClient =
|
|
189
|
-
const mintFeePercent = new BigNumber(
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
176
|
+
const lstClient = await LstClient.initialize(suiGrpcClient, lstInfo.LIQUID_STAKING_INFO, publishedAt);
|
|
177
|
+
const mintFeePercent = new BigNumber(lstInfo.liquidStakingInfo.feeConfig.element?.suiMintFeeBps.toString() ??
|
|
178
|
+
0).div(100);
|
|
179
|
+
const redeemFeePercent = new BigNumber(lstInfo.liquidStakingInfo.feeConfig.element?.redeemFeeBps.toString() ??
|
|
180
|
+
0).div(100);
|
|
181
|
+
const res = await fetch(`${API_URL}/springsui/historical-rates?coinType=${lstCoinType}×tamps=${Math.floor(Date.now() / 1000)}`);
|
|
182
|
+
const json = await res.json();
|
|
183
|
+
if (json?.statusCode === 500)
|
|
194
184
|
throw new Error(`Failed to fetch historical LST to SUI exchange rates for ${lstCoinType}`);
|
|
195
185
|
const suiToLstExchangeRate = !new BigNumber(json[0].value).eq(0)
|
|
196
186
|
? new BigNumber(1).div(new BigNumber(json[0].value))
|
|
@@ -207,18 +197,17 @@ export const fetchStrategyLstMap = (suiGrpcClient) => __awaiter(void 0, void 0,
|
|
|
207
197
|
lstToSuiExchangeRate,
|
|
208
198
|
},
|
|
209
199
|
];
|
|
210
|
-
})))
|
|
200
|
+
})));
|
|
211
201
|
return result;
|
|
212
202
|
}
|
|
213
203
|
catch (err) {
|
|
214
204
|
console.error(err);
|
|
215
205
|
}
|
|
216
|
-
}
|
|
206
|
+
};
|
|
217
207
|
export const getStrategyLstMintFee = (
|
|
218
208
|
// Strategy
|
|
219
209
|
lstMap, lstCoinType, suiAmount) => {
|
|
220
|
-
|
|
221
|
-
const mintFeePercent = (_b = (_a = lstMap === null || lstMap === void 0 ? void 0 : lstMap[lstCoinType]) === null || _a === void 0 ? void 0 : _a.mintFeePercent) !== null && _b !== void 0 ? _b : new BigNumber(0);
|
|
210
|
+
const mintFeePercent = lstMap?.[lstCoinType]?.mintFeePercent ?? new BigNumber(0);
|
|
222
211
|
return suiAmount
|
|
223
212
|
.times(mintFeePercent.div(100))
|
|
224
213
|
.decimalPlaces(SUI_DECIMALS, BigNumber.ROUND_UP);
|
|
@@ -226,9 +215,8 @@ lstMap, lstCoinType, suiAmount) => {
|
|
|
226
215
|
export const getStrategyLstRedeemFee = (
|
|
227
216
|
// Strategy
|
|
228
217
|
lstMap, lstCoinType, lstAmount) => {
|
|
229
|
-
|
|
230
|
-
const
|
|
231
|
-
const redeemFeePercent = (_d = (_c = lstMap === null || lstMap === void 0 ? void 0 : lstMap[lstCoinType]) === null || _c === void 0 ? void 0 : _c.redeemFeePercent) !== null && _d !== void 0 ? _d : new BigNumber(0);
|
|
218
|
+
const lstToSuiExchangeRate = lstMap?.[lstCoinType]?.lstToSuiExchangeRate ?? new BigNumber(1);
|
|
219
|
+
const redeemFeePercent = lstMap?.[lstCoinType]?.redeemFeePercent ?? new BigNumber(0);
|
|
232
220
|
const suiAmount = lstAmount.times(lstToSuiExchangeRate);
|
|
233
221
|
return suiAmount
|
|
234
222
|
.times(redeemFeePercent.div(100))
|
|
@@ -394,7 +382,6 @@ export const getStrategyDepositedAmount = (
|
|
|
394
382
|
reserveMap,
|
|
395
383
|
// Strategy
|
|
396
384
|
lstMap, strategyType, obligation) => {
|
|
397
|
-
var _a, _b;
|
|
398
385
|
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
399
386
|
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
400
387
|
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
@@ -407,7 +394,7 @@ lstMap, strategyType, obligation) => {
|
|
|
407
394
|
resultSui = resultSui.plus(deposit.depositedAmount);
|
|
408
395
|
}
|
|
409
396
|
else if (Object.keys(lstMap).includes(deposit.coinType)) {
|
|
410
|
-
const lstToSuiExchangeRate =
|
|
397
|
+
const lstToSuiExchangeRate = lstMap?.[deposit.coinType]?.lstToSuiExchangeRate ?? new BigNumber(1);
|
|
411
398
|
// const redeemFeePercent =
|
|
412
399
|
// lstMap?.[deposit.coinType]?.redeemFeePercent ?? new BigNumber(0);
|
|
413
400
|
resultSui = resultSui.plus(deposit.depositedAmount.times(lstToSuiExchangeRate));
|
|
@@ -502,7 +489,6 @@ export const getStrategyStepMaxWithdrawnAmount = (
|
|
|
502
489
|
reserveMap,
|
|
503
490
|
// Strategy
|
|
504
491
|
lstMap, strategyType, deposits, borrowedAmount, withdrawCoinType) => {
|
|
505
|
-
var _a, _b;
|
|
506
492
|
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
507
493
|
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
508
494
|
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
@@ -520,7 +506,8 @@ lstMap, strategyType, deposits, borrowedAmount, withdrawCoinType) => {
|
|
|
520
506
|
.div(withdrawReserve.minPrice)
|
|
521
507
|
.div(withdrawReserve.config.openLtvPct / 100)
|
|
522
508
|
: MAX_U64, // Infinity
|
|
523
|
-
|
|
509
|
+
deposits.find((deposit) => deposit.coinType === withdrawReserve.coinType)
|
|
510
|
+
?.depositedAmount ?? new BigNumber(0)).decimalPlaces(withdrawReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
524
511
|
};
|
|
525
512
|
// Simulate
|
|
526
513
|
export const strategySimulateLoopToExposure = (
|
|
@@ -528,21 +515,21 @@ export const strategySimulateLoopToExposure = (
|
|
|
528
515
|
reserveMap,
|
|
529
516
|
// Strategy
|
|
530
517
|
lstMap, strategyType, _deposits, _borrowedAmount, _targetBorrowedAmount, _targetExposure) => {
|
|
531
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
532
518
|
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
533
519
|
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
534
520
|
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
535
|
-
const loopingDepositReserve = (
|
|
521
|
+
const loopingDepositReserve = (depositReserves.lst ?? depositReserves.base); // Must have base if no LST
|
|
536
522
|
//
|
|
537
523
|
let deposits = cloneDeep(_deposits);
|
|
538
524
|
let borrowedAmount = _borrowedAmount;
|
|
539
525
|
const tvlAmountUsd = getStrategyTvlAmount(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount)).times(defaultCurrencyReserve.price);
|
|
540
|
-
const targetBorrowedAmount = _targetBorrowedAmount
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
526
|
+
const targetBorrowedAmount = _targetBorrowedAmount ??
|
|
527
|
+
tvlAmountUsd
|
|
528
|
+
.times(_targetExposure.minus(1))
|
|
529
|
+
.div(borrowReserve.price)
|
|
530
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
544
531
|
// Base+LST or LST only
|
|
545
|
-
if (loopingDepositReserve.coinType ===
|
|
532
|
+
if (loopingDepositReserve.coinType === depositReserves.lst?.coinType) {
|
|
546
533
|
for (let i = 0; i < 30; i++) {
|
|
547
534
|
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
548
535
|
const pendingBorrowedAmount = targetBorrowedAmount.minus(borrowedAmount);
|
|
@@ -554,7 +541,8 @@ lstMap, strategyType, _deposits, _borrowedAmount, _targetBorrowedAmount, _target
|
|
|
554
541
|
.times(0.9) // 10% buffer
|
|
555
542
|
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
556
543
|
const stepMaxDepositedAmount = new BigNumber(stepMaxBorrowedAmount.minus(getStrategyLstMintFee(lstMap, loopingDepositReserve.coinType, stepMaxBorrowedAmount)))
|
|
557
|
-
.times(
|
|
544
|
+
.times(lstMap?.[depositReserves.lst.coinType]?.suiToLstExchangeRate ??
|
|
545
|
+
new BigNumber(1))
|
|
558
546
|
.decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
559
547
|
// 1.2) Borrow
|
|
560
548
|
const stepBorrowedAmount = BigNumber.min(pendingBorrowedAmount, stepMaxBorrowedAmount).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
@@ -565,7 +553,8 @@ lstMap, strategyType, _deposits, _borrowedAmount, _targetBorrowedAmount, _target
|
|
|
565
553
|
// 2.1) Stake SUI for LST
|
|
566
554
|
// 2.2) Deposit
|
|
567
555
|
const stepDepositedAmount = new BigNumber(stepBorrowedAmount.minus(getStrategyLstMintFee(lstMap, loopingDepositReserve.coinType, stepBorrowedAmount)))
|
|
568
|
-
.times(
|
|
556
|
+
.times(lstMap?.[depositReserves.lst.coinType]?.suiToLstExchangeRate ??
|
|
557
|
+
new BigNumber(1))
|
|
569
558
|
.decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
570
559
|
const isMaxDeposit = stepDepositedAmount.eq(stepMaxDepositedAmount);
|
|
571
560
|
// 2.3) Update state
|
|
@@ -576,7 +565,7 @@ lstMap, strategyType, _deposits, _borrowedAmount, _targetBorrowedAmount, _target
|
|
|
576
565
|
}
|
|
577
566
|
}
|
|
578
567
|
// Base only
|
|
579
|
-
else if (loopingDepositReserve.coinType ===
|
|
568
|
+
else if (loopingDepositReserve.coinType === depositReserves.base?.coinType) {
|
|
580
569
|
const borrowToBaseExchangeRate = new BigNumber(1); // Assume 1:1 exchange rate
|
|
581
570
|
for (let i = 0; i < 30; i++) {
|
|
582
571
|
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
@@ -624,11 +613,10 @@ export const strategySimulateDeposit = (
|
|
|
624
613
|
reserveMap,
|
|
625
614
|
// Strategy
|
|
626
615
|
lstMap, strategyType, _deposits, _borrowedAmount, deposit) => {
|
|
627
|
-
var _a, _b, _c, _d;
|
|
628
616
|
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
629
617
|
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
630
618
|
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
631
|
-
const depositReserve = (
|
|
619
|
+
const depositReserve = (depositReserves.base ?? depositReserves.lst); // Must have LST if no base
|
|
632
620
|
//
|
|
633
621
|
let deposits = cloneDeep(_deposits);
|
|
634
622
|
const borrowedAmount = _borrowedAmount;
|
|
@@ -637,7 +625,8 @@ lstMap, strategyType, _deposits, _borrowedAmount, deposit) => {
|
|
|
637
625
|
if (isSui(deposit.coinType)) {
|
|
638
626
|
if (depositReserves.lst === undefined)
|
|
639
627
|
throw new Error("LST reserve not found");
|
|
640
|
-
const suiToLstExchangeRate =
|
|
628
|
+
const suiToLstExchangeRate = lstMap?.[depositReserves.lst.coinType]?.suiToLstExchangeRate ??
|
|
629
|
+
new BigNumber(1);
|
|
641
630
|
const suiAmount = deposit.depositedAmount;
|
|
642
631
|
const lstAmount = new BigNumber(suiAmount
|
|
643
632
|
.minus(getStrategyLstMintFee(lstMap, depositReserves.lst.coinType, suiAmount))
|
|
@@ -652,7 +641,7 @@ lstMap, strategyType, _deposits, _borrowedAmount, deposit) => {
|
|
|
652
641
|
});
|
|
653
642
|
}
|
|
654
643
|
// 1.2) LST
|
|
655
|
-
else if (deposit.coinType ===
|
|
644
|
+
else if (deposit.coinType === depositReserves.lst?.coinType) {
|
|
656
645
|
// 1.2.1) Split coins
|
|
657
646
|
// 1.2.2) Deposit LST (1x exposure)
|
|
658
647
|
// 1.2.3) Update state
|
|
@@ -708,26 +697,26 @@ lstMap, strategyType, _deposits, _borrowedAmount, deposit, targetExposure) => {
|
|
|
708
697
|
};
|
|
709
698
|
// Stats
|
|
710
699
|
// Stats - Global TVL
|
|
711
|
-
export const fetchStrategyGlobalTvlAmountUsdMap = () =>
|
|
700
|
+
export const fetchStrategyGlobalTvlAmountUsdMap = async () => {
|
|
712
701
|
try {
|
|
713
702
|
const url = `${API_URL}/strategies/tvl`;
|
|
714
|
-
const res =
|
|
715
|
-
const json =
|
|
716
|
-
if (
|
|
703
|
+
const res = await fetch(url);
|
|
704
|
+
const json = await res.json();
|
|
705
|
+
if (json?.statusCode === 500)
|
|
717
706
|
throw new Error("Failed to fetch Strategies TVL");
|
|
718
707
|
const result = Object.values(StrategyType).reduce((acc, strategyType) => {
|
|
719
708
|
const entry = json.strategies.find((s) => `${s.strategyType}` === strategyType);
|
|
720
709
|
const tvlUsd = entry
|
|
721
710
|
? new BigNumber(entry.tvlUsd)
|
|
722
711
|
: null;
|
|
723
|
-
return
|
|
712
|
+
return { ...acc, [strategyType]: tvlUsd };
|
|
724
713
|
}, {});
|
|
725
714
|
return result;
|
|
726
715
|
}
|
|
727
716
|
catch (err) {
|
|
728
717
|
console.error(err);
|
|
729
718
|
}
|
|
730
|
-
}
|
|
719
|
+
};
|
|
731
720
|
// Stats - Unclaimed rewards
|
|
732
721
|
export const getStrategyUnclaimedRewardsAmount = (
|
|
733
722
|
// AppContext
|
|
@@ -744,16 +733,15 @@ lstMap, strategyType, obligation) => {
|
|
|
744
733
|
return new BigNumber(0);
|
|
745
734
|
const rewardsMap = getRewardsMap(obligation, rewardMap, rewardCoinMetadataMap);
|
|
746
735
|
const resultSui = Object.entries(rewardsMap).reduce((acc, [coinType, { amount }]) => {
|
|
747
|
-
var _a, _b, _c;
|
|
748
736
|
if (isSui(coinType)) {
|
|
749
737
|
return acc.plus(amount);
|
|
750
738
|
}
|
|
751
739
|
else if (Object.keys(lstMap).includes(coinType)) {
|
|
752
|
-
const lstToSuiExchangeRate =
|
|
740
|
+
const lstToSuiExchangeRate = lstMap?.[coinType]?.lstToSuiExchangeRate ?? new BigNumber(1);
|
|
753
741
|
return acc.plus(amount.times(lstToSuiExchangeRate));
|
|
754
742
|
}
|
|
755
743
|
else {
|
|
756
|
-
const price =
|
|
744
|
+
const price = rewardPriceMap[coinType] ?? new BigNumber(0);
|
|
757
745
|
const priceSui = price.div(getStrategySuiReserve(reserveMap).price);
|
|
758
746
|
return acc.plus(amount.times(priceSui));
|
|
759
747
|
}
|
|
@@ -834,7 +822,6 @@ export const getStrategyLiquidationPrice = (
|
|
|
834
822
|
reserveMap,
|
|
835
823
|
// Strategy
|
|
836
824
|
lstMap, strategyType, obligation, exposure) => {
|
|
837
|
-
var _a;
|
|
838
825
|
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
839
826
|
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
840
827
|
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
@@ -868,17 +855,16 @@ lstMap, strategyType, obligation, exposure) => {
|
|
|
868
855
|
return null;
|
|
869
856
|
const result = new BigNumber(baseDeposit.depositedAmount
|
|
870
857
|
.times(depositReserves.base.price)
|
|
871
|
-
.times(+depositReserves.base.config.closeLtvPct / 100)).div(new BigNumber(borrow.borrowedAmount.times(borrowReserve.config.borrowWeightBps.div(10000))).minus((
|
|
858
|
+
.times(+depositReserves.base.config.closeLtvPct / 100)).div(new BigNumber(borrow.borrowedAmount.times(borrowReserve.config.borrowWeightBps.div(10000))).minus((lstDeposit?.depositedAmount ?? new BigNumber(0)).times(+depositReserves.lst.config.closeLtvPct / 100)));
|
|
872
859
|
return result;
|
|
873
860
|
};
|
|
874
861
|
// --------------------------------
|
|
875
|
-
export const strategyLoopToExposureTx = (
|
|
862
|
+
export const strategyLoopToExposureTx = async (
|
|
876
863
|
// AppContext
|
|
877
864
|
reserveMap,
|
|
878
865
|
// Strategy
|
|
879
866
|
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, _targetBorrowedAmount, _targetExposure, // Must be defined if _targetBorrowedAmount is undefined
|
|
880
|
-
transaction) =>
|
|
881
|
-
var _a, _b, _c, _d, _e;
|
|
867
|
+
transaction) => {
|
|
882
868
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
883
869
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
884
870
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
@@ -895,24 +881,25 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
895
881
|
depositedAmount: d.depositedAmount.toFixed(20),
|
|
896
882
|
})),
|
|
897
883
|
_borrowedAmount: _borrowedAmount.toFixed(20),
|
|
898
|
-
_targetBorrowedAmount: _targetBorrowedAmount
|
|
899
|
-
_targetExposure: _targetExposure
|
|
884
|
+
_targetBorrowedAmount: _targetBorrowedAmount?.toFixed(20),
|
|
885
|
+
_targetExposure: _targetExposure?.toFixed(20),
|
|
900
886
|
}, null, 2));
|
|
901
|
-
const loopingDepositReserve = (
|
|
887
|
+
const loopingDepositReserve = (depositReserves.lst ?? depositReserves.base); // Must have base if no LST
|
|
902
888
|
//
|
|
903
889
|
let deposits = cloneDeep(_deposits);
|
|
904
890
|
let borrowedAmount = _borrowedAmount;
|
|
905
891
|
const tvlAmountUsd = getStrategyTvlAmount(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount)).times(defaultCurrencyReserve.price);
|
|
906
|
-
const targetBorrowedAmount = _targetBorrowedAmount
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
892
|
+
const targetBorrowedAmount = _targetBorrowedAmount ??
|
|
893
|
+
tvlAmountUsd
|
|
894
|
+
.times(_targetExposure.minus(1))
|
|
895
|
+
.div(borrowReserve.price)
|
|
896
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
910
897
|
console.log(`[loopStrategyToExposure] processed_args |`, JSON.stringify({
|
|
911
898
|
tvlAmountUsd: tvlAmountUsd.toFixed(20),
|
|
912
899
|
targetBorrowedAmount: targetBorrowedAmount.toFixed(20),
|
|
913
900
|
}));
|
|
914
901
|
// Base+LST or LST only
|
|
915
|
-
if (loopingDepositReserve.coinType ===
|
|
902
|
+
if (loopingDepositReserve.coinType === depositReserves.lst?.coinType) {
|
|
916
903
|
for (let i = 0; i < 30; i++) {
|
|
917
904
|
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
918
905
|
const pendingBorrowedAmount = targetBorrowedAmount.minus(borrowedAmount);
|
|
@@ -933,7 +920,7 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
933
920
|
.times(0.9) // 10% buffer
|
|
934
921
|
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
935
922
|
const stepMaxDepositedAmount = new BigNumber(stepMaxBorrowedAmount.minus(getStrategyLstMintFee(lstMap, loopingDepositReserve.coinType, stepMaxBorrowedAmount)))
|
|
936
|
-
.times(
|
|
923
|
+
.times(lst?.suiToLstExchangeRate ?? 1)
|
|
937
924
|
.decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
938
925
|
console.log(`[loopStrategyToExposure] ${i} borrow_sui.max |`, JSON.stringify({
|
|
939
926
|
stepMaxBorrowedAmount: stepMaxBorrowedAmount.toFixed(20),
|
|
@@ -966,7 +953,7 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
966
953
|
const stepLstCoin = lst.client.mint(transaction, borrowedCoin);
|
|
967
954
|
// 2.2) Deposit
|
|
968
955
|
const stepDepositedAmount = new BigNumber(stepBorrowedAmount.minus(getStrategyLstMintFee(lstMap, loopingDepositReserve.coinType, stepBorrowedAmount)))
|
|
969
|
-
.times(
|
|
956
|
+
.times(lst?.suiToLstExchangeRate ?? 1)
|
|
970
957
|
.decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
971
958
|
const isMaxDeposit = stepDepositedAmount.eq(stepMaxDepositedAmount);
|
|
972
959
|
console.log(`[loopStrategyToExposure] ${i} deposit_lst.deposit |`, JSON.stringify({
|
|
@@ -989,8 +976,8 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
989
976
|
}
|
|
990
977
|
}
|
|
991
978
|
// Base only
|
|
992
|
-
else if (loopingDepositReserve.coinType ===
|
|
993
|
-
const exchangeRateRouters =
|
|
979
|
+
else if (loopingDepositReserve.coinType === depositReserves.base?.coinType) {
|
|
980
|
+
const exchangeRateRouters = await cetusSdk.findRouters({
|
|
994
981
|
from: borrowReserve.coinType,
|
|
995
982
|
target: loopingDepositReserve.coinType,
|
|
996
983
|
amount: new BN(new BigNumber(0.1)
|
|
@@ -1051,7 +1038,7 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
1051
1038
|
}, null, 2));
|
|
1052
1039
|
// 2) Deposit base
|
|
1053
1040
|
// 2.1) Swap borrows for base
|
|
1054
|
-
const routers =
|
|
1041
|
+
const routers = await cetusSdk.findRouters({
|
|
1055
1042
|
from: borrowReserve.coinType,
|
|
1056
1043
|
target: loopingDepositReserve.coinType,
|
|
1057
1044
|
amount: new BN(stepBorrowedAmount
|
|
@@ -1066,7 +1053,7 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
1066
1053
|
const slippagePercent = 1;
|
|
1067
1054
|
let stepBaseCoin;
|
|
1068
1055
|
try {
|
|
1069
|
-
stepBaseCoin = (
|
|
1056
|
+
stepBaseCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
1070
1057
|
router: routers,
|
|
1071
1058
|
inputCoin: stepBorrowedCoin,
|
|
1072
1059
|
slippage: slippagePercent / 100,
|
|
@@ -1112,14 +1099,13 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
1112
1099
|
throw new Error("No LST or base reserve found"); // Should not happen
|
|
1113
1100
|
}
|
|
1114
1101
|
return { deposits, borrowedAmount, transaction };
|
|
1115
|
-
}
|
|
1116
|
-
export const strategyUnloopToExposureTx = (
|
|
1102
|
+
};
|
|
1103
|
+
export const strategyUnloopToExposureTx = async (
|
|
1117
1104
|
// AppContext
|
|
1118
1105
|
reserveMap,
|
|
1119
1106
|
// Strategy
|
|
1120
1107
|
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, _targetBorrowedAmount, _targetExposure, // Must be defined if _targetBorrowedAmount is undefined
|
|
1121
|
-
transaction, dryRunTransaction) =>
|
|
1122
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
1108
|
+
transaction, dryRunTransaction) => {
|
|
1123
1109
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
1124
1110
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
1125
1111
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
@@ -1136,27 +1122,27 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1136
1122
|
depositedAmount: d.depositedAmount.toFixed(20),
|
|
1137
1123
|
})),
|
|
1138
1124
|
_borrowedAmount: _borrowedAmount.toFixed(20),
|
|
1139
|
-
_targetBorrowedAmount: _targetBorrowedAmount
|
|
1140
|
-
_targetExposure: _targetExposure
|
|
1125
|
+
_targetBorrowedAmount: _targetBorrowedAmount?.toFixed(20),
|
|
1126
|
+
_targetExposure: _targetExposure?.toFixed(20),
|
|
1141
1127
|
}, null, 2));
|
|
1142
|
-
const depositReserve = (
|
|
1143
|
-
const loopingDepositReserve = (
|
|
1128
|
+
const depositReserve = (depositReserves.base ?? depositReserves.lst); // Must have LST if no base
|
|
1129
|
+
const loopingDepositReserve = (depositReserves.lst ?? depositReserves.base); // Must have base if no LST
|
|
1144
1130
|
//
|
|
1145
1131
|
let deposits = cloneDeep(_deposits);
|
|
1146
1132
|
let borrowedAmount = _borrowedAmount;
|
|
1147
1133
|
const tvlAmountUsd = getStrategyTvlAmount(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount)).times(defaultCurrencyReserve.price);
|
|
1148
|
-
const targetBorrowedAmount = _targetBorrowedAmount
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1134
|
+
const targetBorrowedAmount = _targetBorrowedAmount ??
|
|
1135
|
+
tvlAmountUsd
|
|
1136
|
+
.times(_targetExposure.minus(1))
|
|
1137
|
+
.div(borrowReserve.price)
|
|
1138
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1152
1139
|
console.log(`[unloopStrategyToExposure] processed_args |`, JSON.stringify({
|
|
1153
1140
|
tvlAmountUsd: tvlAmountUsd.toFixed(20),
|
|
1154
1141
|
targetBorrowedAmount: targetBorrowedAmount.toFixed(20),
|
|
1155
1142
|
}));
|
|
1156
1143
|
if (borrowedAmount.eq(targetBorrowedAmount))
|
|
1157
1144
|
return { deposits, borrowedAmount, transaction };
|
|
1158
|
-
const fullyRepayBorrowsUsingLst = (maxWithdrawRemainingLstAndRedepositAsBase) =>
|
|
1159
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
1145
|
+
const fullyRepayBorrowsUsingLst = async (maxWithdrawRemainingLstAndRedepositAsBase) => {
|
|
1160
1146
|
if (depositReserves.lst === undefined)
|
|
1161
1147
|
throw new Error("LST reserve not found");
|
|
1162
1148
|
const borrowedAmountUsd = borrowedAmount.times(borrowReserve.price);
|
|
@@ -1174,10 +1160,11 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1174
1160
|
}));
|
|
1175
1161
|
// 1) Withdraw LST
|
|
1176
1162
|
const lstWithdrawnAmount = fullRepaymentAmount
|
|
1177
|
-
.div(1 - +(
|
|
1178
|
-
.div(
|
|
1163
|
+
.div(1 - +(lst?.redeemFeePercent ?? 0) / 100) // Potential rounding issue (max 1 MIST)
|
|
1164
|
+
.div(lst?.lstToSuiExchangeRate ?? 1)
|
|
1179
1165
|
.decimalPlaces(depositReserves.lst.token.decimals, BigNumber.ROUND_DOWN);
|
|
1180
|
-
if ((
|
|
1166
|
+
if ((deposits.find((d) => d.coinType === depositReserves.lst.coinType)
|
|
1167
|
+
?.depositedAmount ?? new BigNumber(0)).lt(lstWithdrawnAmount))
|
|
1181
1168
|
throw new Error("Not enough LST deposited");
|
|
1182
1169
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingLst] withdraw_lst |`, JSON.stringify({
|
|
1183
1170
|
lstWithdrawnAmount: lstWithdrawnAmount.toFixed(20),
|
|
@@ -1206,7 +1193,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1206
1193
|
const fullRepaymentCoin = lst.client.redeem(transaction, withdrawnLstCoin);
|
|
1207
1194
|
// 3) Repay borrows
|
|
1208
1195
|
// 3.1) Repay
|
|
1209
|
-
const repaidAmount = new BigNumber(new BigNumber(lstWithdrawnAmount.times(
|
|
1196
|
+
const repaidAmount = new BigNumber(new BigNumber(lstWithdrawnAmount.times(lst?.lstToSuiExchangeRate ?? 1)).minus(getStrategyLstRedeemFee(lstMap, depositReserves.lst.coinType, lstWithdrawnAmount))).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1210
1197
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingLst] repay_borrows.repay |`, JSON.stringify({
|
|
1211
1198
|
repaidAmount: repaidAmount.toFixed(20),
|
|
1212
1199
|
}, null, 2));
|
|
@@ -1214,7 +1201,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1214
1201
|
const txCopy = Transaction.from(transaction);
|
|
1215
1202
|
suilendClient.repay(obligationId, borrowReserve.coinType, fullRepaymentCoin, txCopy);
|
|
1216
1203
|
txCopy.transferObjects([fullRepaymentCoin], _address); // Transfer remaining SUI to user
|
|
1217
|
-
|
|
1204
|
+
await dryRunTransaction(txCopy); // Throws error if fails
|
|
1218
1205
|
transaction = txCopy;
|
|
1219
1206
|
}
|
|
1220
1207
|
catch (err) {
|
|
@@ -1237,7 +1224,8 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1237
1224
|
if (depositReserves.base === undefined)
|
|
1238
1225
|
throw new Error("Base reserve not found");
|
|
1239
1226
|
// 1) MAX withdraw LST
|
|
1240
|
-
const remainingLstWithdrawnAmount = (
|
|
1227
|
+
const remainingLstWithdrawnAmount = (deposits.find((d) => d.coinType === depositReserves.lst.coinType)
|
|
1228
|
+
?.depositedAmount ?? new BigNumber(0)).decimalPlaces(depositReserves.lst.token.decimals, BigNumber.ROUND_DOWN);
|
|
1241
1229
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingLst] max_withdraw_lst |`, JSON.stringify({
|
|
1242
1230
|
remainingLstWithdrawnAmount: remainingLstWithdrawnAmount.toFixed(20),
|
|
1243
1231
|
}));
|
|
@@ -1257,7 +1245,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1257
1245
|
}, null, 2));
|
|
1258
1246
|
// 2) Swap LST for base and redeposit
|
|
1259
1247
|
// 2.1) Get routers
|
|
1260
|
-
const routers =
|
|
1248
|
+
const routers = await cetusSdk.findRouters({
|
|
1261
1249
|
from: depositReserves.lst.coinType,
|
|
1262
1250
|
target: depositReserves.base.coinType,
|
|
1263
1251
|
amount: new BN(remainingLstWithdrawnAmount
|
|
@@ -1282,7 +1270,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1282
1270
|
// 2.2) Swap
|
|
1283
1271
|
let swapCoin;
|
|
1284
1272
|
try {
|
|
1285
|
-
swapCoin = (
|
|
1273
|
+
swapCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
1286
1274
|
router: routers,
|
|
1287
1275
|
inputCoin: withdrawnRemainingLstCoin,
|
|
1288
1276
|
slippage: 100 / 100,
|
|
@@ -1296,9 +1284,8 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1296
1284
|
// 3) Deposit base
|
|
1297
1285
|
strategyDeposit(strategyType, swapCoin, depositReserves.base.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserves.base.coinType), transaction);
|
|
1298
1286
|
}
|
|
1299
|
-
}
|
|
1300
|
-
const fullyRepayBorrowsUsingBase = () =>
|
|
1301
|
-
var _a, _b;
|
|
1287
|
+
};
|
|
1288
|
+
const fullyRepayBorrowsUsingBase = async () => {
|
|
1302
1289
|
if (depositReserves.base === undefined)
|
|
1303
1290
|
throw new Error("Base reserve not found");
|
|
1304
1291
|
const borrowedAmountUsd = borrowedAmount.times(borrowReserve.price);
|
|
@@ -1321,7 +1308,8 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1321
1308
|
// 1.2) Update state
|
|
1322
1309
|
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
1323
1310
|
coinType: depositReserves.lst.coinType,
|
|
1324
|
-
depositedAmount: (
|
|
1311
|
+
depositedAmount: (deposits.find((d) => d.coinType === depositReserves.lst.coinType)
|
|
1312
|
+
?.depositedAmount ?? new BigNumber(0)).times(-1),
|
|
1325
1313
|
});
|
|
1326
1314
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingBase] max_withdraw_lst.update_state |`, JSON.stringify({
|
|
1327
1315
|
deposits: deposits.map((d) => ({
|
|
@@ -1365,7 +1353,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1365
1353
|
}, null, 2));
|
|
1366
1354
|
// 3) Swap base for borrow
|
|
1367
1355
|
// 3.1) Get routers
|
|
1368
|
-
const routers =
|
|
1356
|
+
const routers = await cetusSdk.findRouters({
|
|
1369
1357
|
from: depositReserves.base.coinType,
|
|
1370
1358
|
target: borrowReserve.coinType,
|
|
1371
1359
|
amount: new BN(baseWithdrawnAmount
|
|
@@ -1390,7 +1378,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1390
1378
|
// 3.2) Swap
|
|
1391
1379
|
let swapCoin;
|
|
1392
1380
|
try {
|
|
1393
|
-
swapCoin = (
|
|
1381
|
+
swapCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
1394
1382
|
router: routers,
|
|
1395
1383
|
inputCoin: withdrawnBaseCoin,
|
|
1396
1384
|
slippage: 1 / 100,
|
|
@@ -1411,7 +1399,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1411
1399
|
const txCopy = Transaction.from(transaction);
|
|
1412
1400
|
suilendClient.repay(obligationId, borrowReserve.coinType, swapCoin, txCopy);
|
|
1413
1401
|
txCopy.transferObjects([swapCoin], _address); // Transfer remaining to user
|
|
1414
|
-
|
|
1402
|
+
await dryRunTransaction(txCopy); // Throws error if fails
|
|
1415
1403
|
transaction = txCopy;
|
|
1416
1404
|
}
|
|
1417
1405
|
catch (err) {
|
|
@@ -1429,7 +1417,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1429
1417
|
borrowedAmount: borrowedAmount.toFixed(20),
|
|
1430
1418
|
}, null, 2));
|
|
1431
1419
|
// 5) Swap remaining to base and redeposit (not possible because coin is a mutable reference (?))
|
|
1432
|
-
}
|
|
1420
|
+
};
|
|
1433
1421
|
for (let i = 0; i < 30; i++) {
|
|
1434
1422
|
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
1435
1423
|
const pendingBorrowedAmount = borrowedAmount.minus(targetBorrowedAmount);
|
|
@@ -1443,19 +1431,19 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1443
1431
|
pendingBorrowedAmount: pendingBorrowedAmount.toFixed(20),
|
|
1444
1432
|
}, null, 2));
|
|
1445
1433
|
// Base+LST or LST only
|
|
1446
|
-
if (loopingDepositReserve.coinType ===
|
|
1434
|
+
if (loopingDepositReserve.coinType === depositReserves.lst?.coinType) {
|
|
1447
1435
|
// Target: 1x leverage
|
|
1448
1436
|
if (targetBorrowedAmount.eq(0)) {
|
|
1449
1437
|
if (pendingBorrowedAmount.lt(0))
|
|
1450
1438
|
break; // Fully repaid already
|
|
1451
|
-
if (depositReserve.coinType ===
|
|
1439
|
+
if (depositReserve.coinType === depositReserves.base?.coinType) {
|
|
1452
1440
|
const lstDeposit = deposits.find((d) => d.coinType === depositReserves.lst.coinType);
|
|
1453
1441
|
// Ran out of LST
|
|
1454
1442
|
if (lstDeposit.depositedAmount.lte(STRATEGY_E)) {
|
|
1455
1443
|
// 1. MAX withdraws LST (transferred to user as SUI)
|
|
1456
1444
|
// 2. Withdraws base to cover borrows
|
|
1457
1445
|
// - Leftover transferred to user as borrow coinType, e.g. SUI or suiWBTC
|
|
1458
|
-
|
|
1446
|
+
await fullyRepayBorrowsUsingBase();
|
|
1459
1447
|
break;
|
|
1460
1448
|
}
|
|
1461
1449
|
// Borrows almost fully repaid
|
|
@@ -1464,7 +1452,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1464
1452
|
// 1. Withdraws LST to cover borrows
|
|
1465
1453
|
// - Leftover transferred to user as borrow coinType, e.g. SUI or suiWBTC
|
|
1466
1454
|
// 2. MAX withdraws remaining LST and redeposits as base
|
|
1467
|
-
|
|
1455
|
+
await fullyRepayBorrowsUsingLst(true);
|
|
1468
1456
|
break;
|
|
1469
1457
|
}
|
|
1470
1458
|
catch (err) {
|
|
@@ -1473,7 +1461,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1473
1461
|
// 1. MAX withdraws LST (transferred to user as SUI)
|
|
1474
1462
|
// 2. Withdraws base to cover borrows
|
|
1475
1463
|
// - Leftover transferred to user as borrow coinType, e.g. SUI or suiWBTC
|
|
1476
|
-
|
|
1464
|
+
await fullyRepayBorrowsUsingBase();
|
|
1477
1465
|
break;
|
|
1478
1466
|
}
|
|
1479
1467
|
}
|
|
@@ -1482,7 +1470,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1482
1470
|
if (pendingBorrowedAmount.lte(STRATEGY_E)) {
|
|
1483
1471
|
// 1. Withdraws LST to cover borrows
|
|
1484
1472
|
// - Leftover transferred to user as borrow coinType, e.g. SUI or suiWBTC
|
|
1485
|
-
|
|
1473
|
+
await fullyRepayBorrowsUsingLst(false);
|
|
1486
1474
|
break;
|
|
1487
1475
|
}
|
|
1488
1476
|
}
|
|
@@ -1496,15 +1484,15 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1496
1484
|
const stepMaxWithdrawnAmount = getStrategyStepMaxWithdrawnAmount(reserveMap, lstMap, strategyType, deposits, borrowedAmount, loopingDepositReserve.coinType)
|
|
1497
1485
|
.times(0.9) // 10% buffer
|
|
1498
1486
|
.decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1499
|
-
const stepMaxRepaidAmount = new BigNumber(new BigNumber(stepMaxWithdrawnAmount.times(
|
|
1487
|
+
const stepMaxRepaidAmount = new BigNumber(new BigNumber(stepMaxWithdrawnAmount.times(lst?.lstToSuiExchangeRate ?? 1)).minus(getStrategyLstRedeemFee(lstMap, loopingDepositReserve.coinType, stepMaxWithdrawnAmount))).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1500
1488
|
console.log(`[unloopStrategyToExposure] ${i} withdraw_lst.max |`, JSON.stringify({
|
|
1501
1489
|
stepMaxWithdrawnAmount: stepMaxWithdrawnAmount.toFixed(20),
|
|
1502
1490
|
stepMaxRepaidAmount: stepMaxRepaidAmount.toFixed(20),
|
|
1503
1491
|
}, null, 2));
|
|
1504
1492
|
// 1.2) Withdraw
|
|
1505
1493
|
const stepWithdrawnAmount = BigNumber.min(pendingBorrowedAmount, stepMaxRepaidAmount)
|
|
1506
|
-
.times(1 - +(
|
|
1507
|
-
.div(
|
|
1494
|
+
.times(1 - +(lst?.redeemFeePercent ?? 0) / 100) // Potential rounding issue (max 1 MIST)
|
|
1495
|
+
.div(lst?.lstToSuiExchangeRate ?? 1)
|
|
1508
1496
|
.decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1509
1497
|
const isMaxWithdraw = stepWithdrawnAmount.eq(stepMaxWithdrawnAmount);
|
|
1510
1498
|
console.log(`[unloopStrategyToExposure] ${i} withdraw_lst.withdraw |`, JSON.stringify({
|
|
@@ -1534,7 +1522,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1534
1522
|
const stepSuiCoin = lst.client.redeem(transaction, stepWithdrawnCoin);
|
|
1535
1523
|
// 3) Repay SUI
|
|
1536
1524
|
// 3.1) Repay
|
|
1537
|
-
const stepRepaidAmount = new BigNumber(new BigNumber(stepWithdrawnAmount.times(
|
|
1525
|
+
const stepRepaidAmount = new BigNumber(new BigNumber(stepWithdrawnAmount.times(lst?.lstToSuiExchangeRate ?? 1)).minus(getStrategyLstRedeemFee(lstMap, loopingDepositReserve.coinType, stepWithdrawnAmount))).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1538
1526
|
const isMaxRepay = stepRepaidAmount.eq(stepMaxRepaidAmount);
|
|
1539
1527
|
console.log(`[unloopStrategyToExposure] ${i} repay_sui.repay |`, JSON.stringify({
|
|
1540
1528
|
stepRepaidAmount: stepRepaidAmount.toFixed(20),
|
|
@@ -1544,7 +1532,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1544
1532
|
const txCopy = Transaction.from(transaction);
|
|
1545
1533
|
suilendClient.repay(obligationId, borrowReserve.coinType, stepSuiCoin, txCopy);
|
|
1546
1534
|
txCopy.transferObjects([stepSuiCoin], _address);
|
|
1547
|
-
|
|
1535
|
+
await dryRunTransaction(txCopy); // Throws error if fails
|
|
1548
1536
|
transaction = txCopy;
|
|
1549
1537
|
}
|
|
1550
1538
|
catch (err) {
|
|
@@ -1563,8 +1551,8 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1563
1551
|
}, null, 2));
|
|
1564
1552
|
}
|
|
1565
1553
|
// Base only
|
|
1566
|
-
else if (loopingDepositReserve.coinType ===
|
|
1567
|
-
const exchangeRateRouters =
|
|
1554
|
+
else if (loopingDepositReserve.coinType === depositReserves.base?.coinType) {
|
|
1555
|
+
const exchangeRateRouters = await cetusSdk.findRouters({
|
|
1568
1556
|
from: loopingDepositReserve.coinType,
|
|
1569
1557
|
target: borrowReserve.coinType,
|
|
1570
1558
|
amount: new BN(new BigNumber(0.1)
|
|
@@ -1585,7 +1573,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1585
1573
|
if (pendingBorrowedAmount.lte(STRATEGY_E)) {
|
|
1586
1574
|
// 1. Withdraws base to cover borrows
|
|
1587
1575
|
// - Leftover transferred to user as borrow coinType, e.g. SUI or suiWBTC
|
|
1588
|
-
|
|
1576
|
+
await fullyRepayBorrowsUsingBase();
|
|
1589
1577
|
break;
|
|
1590
1578
|
}
|
|
1591
1579
|
}
|
|
@@ -1638,7 +1626,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1638
1626
|
borrowedAmount: borrowedAmount.toFixed(20),
|
|
1639
1627
|
}, null, 2));
|
|
1640
1628
|
// 2) Swap base for borrows
|
|
1641
|
-
const routers =
|
|
1629
|
+
const routers = await cetusSdk.findRouters({
|
|
1642
1630
|
from: loopingDepositReserve.coinType,
|
|
1643
1631
|
target: borrowReserve.coinType,
|
|
1644
1632
|
amount: new BN(stepWithdrawnAmount
|
|
@@ -1653,7 +1641,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1653
1641
|
const slippagePercent = 1;
|
|
1654
1642
|
let stepBorrowCoin;
|
|
1655
1643
|
try {
|
|
1656
|
-
stepBorrowCoin = (
|
|
1644
|
+
stepBorrowCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
1657
1645
|
router: routers,
|
|
1658
1646
|
inputCoin: stepWithdrawnCoin,
|
|
1659
1647
|
slippage: slippagePercent / 100,
|
|
@@ -1692,7 +1680,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1692
1680
|
const txCopy = Transaction.from(transaction);
|
|
1693
1681
|
suilendClient.repay(obligationId, borrowReserve.coinType, stepBorrowCoin, txCopy);
|
|
1694
1682
|
txCopy.transferObjects([stepBorrowCoin], _address);
|
|
1695
|
-
|
|
1683
|
+
await dryRunTransaction(txCopy); // Throws error if fails
|
|
1696
1684
|
transaction = txCopy;
|
|
1697
1685
|
}
|
|
1698
1686
|
catch (err) {
|
|
@@ -1715,13 +1703,12 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1715
1703
|
}
|
|
1716
1704
|
}
|
|
1717
1705
|
return { deposits, borrowedAmount, transaction };
|
|
1718
|
-
}
|
|
1719
|
-
export const strategyDepositTx = (
|
|
1706
|
+
};
|
|
1707
|
+
export const strategyDepositTx = async (
|
|
1720
1708
|
// AppContext
|
|
1721
1709
|
reserveMap,
|
|
1722
1710
|
// Strategy
|
|
1723
|
-
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, deposit, transaction, dryRunTransaction) =>
|
|
1724
|
-
var _a, _b, _c;
|
|
1711
|
+
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, deposit, transaction, dryRunTransaction) => {
|
|
1725
1712
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
1726
1713
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
1727
1714
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
@@ -1743,7 +1730,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1743
1730
|
depositedAmount: deposit.depositedAmount.toFixed(20),
|
|
1744
1731
|
},
|
|
1745
1732
|
}, null, 2));
|
|
1746
|
-
const depositReserve = (
|
|
1733
|
+
const depositReserve = (depositReserves.base ?? depositReserves.lst); // Must have LST if no base
|
|
1747
1734
|
//
|
|
1748
1735
|
let deposits = cloneDeep(_deposits);
|
|
1749
1736
|
const borrowedAmount = _borrowedAmount;
|
|
@@ -1755,7 +1742,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1755
1742
|
const suiAmount = deposit.depositedAmount;
|
|
1756
1743
|
const lstAmount = new BigNumber(suiAmount
|
|
1757
1744
|
.minus(getStrategyLstMintFee(lstMap, depositReserves.lst.coinType, suiAmount))
|
|
1758
|
-
.times(
|
|
1745
|
+
.times(lst?.suiToLstExchangeRate ?? 1)).decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
1759
1746
|
// 1.1.1) Split coins
|
|
1760
1747
|
const suiCoin = transaction.splitCoins(transaction.gas, [
|
|
1761
1748
|
suiAmount
|
|
@@ -1774,9 +1761,9 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1774
1761
|
});
|
|
1775
1762
|
}
|
|
1776
1763
|
// 1.2) LST
|
|
1777
|
-
else if (deposit.coinType ===
|
|
1764
|
+
else if (deposit.coinType === depositReserves.lst?.coinType) {
|
|
1778
1765
|
// 1.2.1) Split coins
|
|
1779
|
-
const lstCoin =
|
|
1766
|
+
const lstCoin = await getSpendableCoin(suiGrpcClient, _address, depositReserves.lst.coinType, deposit.depositedAmount
|
|
1780
1767
|
.times(10 ** LST_DECIMALS)
|
|
1781
1768
|
.integerValue(BigNumber.ROUND_DOWN)
|
|
1782
1769
|
.toString(), transaction);
|
|
@@ -1789,13 +1776,13 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1789
1776
|
else {
|
|
1790
1777
|
const otherReserve = reserveMap[deposit.coinType];
|
|
1791
1778
|
// 1.3.1) Split coins
|
|
1792
|
-
const otherCoin =
|
|
1779
|
+
const otherCoin = await getSpendableCoin(suiGrpcClient, _address, otherReserve.coinType, deposit.depositedAmount
|
|
1793
1780
|
.times(10 ** otherReserve.token.decimals)
|
|
1794
1781
|
.integerValue(BigNumber.ROUND_DOWN)
|
|
1795
1782
|
.toString(), transaction);
|
|
1796
1783
|
// 1.3.2) If the deposit coin is the same as the borrow coin, swap to base first
|
|
1797
1784
|
if (deposit.coinType === borrowReserve.coinType && depositReserve) {
|
|
1798
|
-
const routers =
|
|
1785
|
+
const routers = await cetusSdk.findRouters({
|
|
1799
1786
|
from: otherReserve.coinType,
|
|
1800
1787
|
target: depositReserve.coinType,
|
|
1801
1788
|
amount: new BN(deposit.depositedAmount
|
|
@@ -1810,7 +1797,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1810
1797
|
const slippagePercent = 1;
|
|
1811
1798
|
let baseCoin;
|
|
1812
1799
|
try {
|
|
1813
|
-
baseCoin = (
|
|
1800
|
+
baseCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
1814
1801
|
router: routers,
|
|
1815
1802
|
inputCoin: otherCoin,
|
|
1816
1803
|
slippage: slippagePercent / 100,
|
|
@@ -1845,12 +1832,12 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1845
1832
|
borrowedAmount: borrowedAmount.toFixed(20),
|
|
1846
1833
|
}, null, 2));
|
|
1847
1834
|
return { deposits, borrowedAmount, transaction };
|
|
1848
|
-
}
|
|
1849
|
-
export const strategyDepositAndLoopToExposureTx = (
|
|
1835
|
+
};
|
|
1836
|
+
export const strategyDepositAndLoopToExposureTx = async (
|
|
1850
1837
|
// AppContext
|
|
1851
1838
|
reserveMap,
|
|
1852
1839
|
// Strategy
|
|
1853
|
-
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, deposit, targetExposure, transaction, dryRunTransaction) =>
|
|
1840
|
+
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, deposit, targetExposure, transaction, dryRunTransaction) => {
|
|
1854
1841
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
1855
1842
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
1856
1843
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
@@ -1878,7 +1865,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1878
1865
|
let borrowedAmount = _borrowedAmount;
|
|
1879
1866
|
// 1) Deposit (1x exposure)
|
|
1880
1867
|
// 1.1) Deposit
|
|
1881
|
-
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } =
|
|
1868
|
+
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = await strategyDepositTx(reserveMap, lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, deposit, transaction, dryRunTransaction);
|
|
1882
1869
|
// 1.2) Update state
|
|
1883
1870
|
deposits = newDeposits;
|
|
1884
1871
|
borrowedAmount = newBorrowedAmount;
|
|
@@ -1886,7 +1873,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1886
1873
|
if (targetExposure.gt(1)) {
|
|
1887
1874
|
// 2) Loop to target exposure
|
|
1888
1875
|
// 2.1) Loop
|
|
1889
|
-
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, } =
|
|
1876
|
+
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, } = await strategyLoopToExposureTx(reserveMap, lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, undefined, // Don't pass targetBorrowedAmount
|
|
1890
1877
|
targetExposure, // Pass targetExposure
|
|
1891
1878
|
transaction);
|
|
1892
1879
|
// 2.2) Update state
|
|
@@ -1895,13 +1882,12 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1895
1882
|
transaction = newTransaction2;
|
|
1896
1883
|
}
|
|
1897
1884
|
return { deposits, borrowedAmount, transaction };
|
|
1898
|
-
}
|
|
1899
|
-
export const strategyWithdrawTx = (
|
|
1885
|
+
};
|
|
1886
|
+
export const strategyWithdrawTx = async (
|
|
1900
1887
|
// AppContext
|
|
1901
1888
|
reserveMap,
|
|
1902
1889
|
// Strategy
|
|
1903
|
-
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, withdraw, transaction, dryRunTransaction, returnWithdrawnCoin) =>
|
|
1904
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1890
|
+
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, withdraw, transaction, dryRunTransaction, returnWithdrawnCoin) => {
|
|
1905
1891
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
1906
1892
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
1907
1893
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
@@ -1924,22 +1910,22 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1924
1910
|
},
|
|
1925
1911
|
returnWithdrawnCoin,
|
|
1926
1912
|
}, null, 2));
|
|
1927
|
-
const depositReserve = (
|
|
1913
|
+
const depositReserve = (depositReserves.base ?? depositReserves.lst); // Must have LST if no base
|
|
1928
1914
|
//
|
|
1929
1915
|
let deposits = cloneDeep(_deposits);
|
|
1930
1916
|
let borrowedAmount = _borrowedAmount;
|
|
1931
|
-
const withdrawnAmount = (depositReserve.coinType ===
|
|
1917
|
+
const withdrawnAmount = (depositReserve.coinType === depositReserves.base?.coinType
|
|
1932
1918
|
? withdraw.withdrawnAmount
|
|
1933
1919
|
: isSui(withdraw.coinType)
|
|
1934
1920
|
? withdraw.withdrawnAmount
|
|
1935
|
-
.div(1 - +(
|
|
1936
|
-
.div(
|
|
1921
|
+
.div(1 - +(lst?.redeemFeePercent ?? 0) / 100) // Potential rounding issue (max 1 MIST)
|
|
1922
|
+
.div(lst?.lstToSuiExchangeRate ?? 1)
|
|
1937
1923
|
: withdraw.withdrawnAmount).decimalPlaces(depositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1938
1924
|
const withdrawnAmountUsd = withdrawnAmount
|
|
1939
1925
|
.times(depositReserve.price)
|
|
1940
|
-
.times(depositReserve.coinType ===
|
|
1926
|
+
.times(depositReserve.coinType === depositReserves.base?.coinType
|
|
1941
1927
|
? 1
|
|
1942
|
-
: new BigNumber(
|
|
1928
|
+
: new BigNumber(lst?.lstToSuiExchangeRate ?? 1).times(1 - +(lst?.redeemFeePercent ?? 0) / 100));
|
|
1943
1929
|
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
1944
1930
|
const tvlAmountUsd = getStrategyTvlAmount(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount)).times(defaultCurrencyReserve.price);
|
|
1945
1931
|
const targetTvlAmountUsd = tvlAmountUsd.minus(withdrawnAmountUsd);
|
|
@@ -1959,7 +1945,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
1959
1945
|
// 1) Unloop to targetBorrowedAmount borrows
|
|
1960
1946
|
// 1.1) Unloop
|
|
1961
1947
|
if (borrowedAmount.gt(targetBorrowedAmount)) {
|
|
1962
|
-
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } =
|
|
1948
|
+
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = await strategyUnloopToExposureTx(reserveMap, lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, targetBorrowedAmount, // Pass targetBorrowedAmount
|
|
1963
1949
|
undefined, // Don't pass targetExposure
|
|
1964
1950
|
transaction, dryRunTransaction);
|
|
1965
1951
|
// 1.2) Update state
|
|
@@ -2007,9 +1993,9 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2007
1993
|
if (returnWithdrawnCoin)
|
|
2008
1994
|
return { deposits, borrowedAmount, transaction, withdrawnCoin };
|
|
2009
1995
|
else {
|
|
2010
|
-
if (depositReserve.coinType ===
|
|
1996
|
+
if (depositReserve.coinType === depositReserves.base?.coinType) {
|
|
2011
1997
|
if (withdraw.coinType !== depositReserve.coinType) {
|
|
2012
|
-
const routers =
|
|
1998
|
+
const routers = await cetusSdk.findRouters({
|
|
2013
1999
|
from: depositReserve.coinType,
|
|
2014
2000
|
target: withdraw.coinType,
|
|
2015
2001
|
amount: new BN(withdrawnAmount
|
|
@@ -2024,7 +2010,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2024
2010
|
const slippagePercent = 1;
|
|
2025
2011
|
let swappedCoin;
|
|
2026
2012
|
try {
|
|
2027
|
-
swappedCoin = (
|
|
2013
|
+
swappedCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
2028
2014
|
router: routers,
|
|
2029
2015
|
inputCoin: withdrawnCoin,
|
|
2030
2016
|
slippage: slippagePercent / 100,
|
|
@@ -2055,13 +2041,12 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2055
2041
|
}
|
|
2056
2042
|
}
|
|
2057
2043
|
return { deposits, borrowedAmount, transaction };
|
|
2058
|
-
}
|
|
2059
|
-
export const strategyMaxWithdrawTx = (
|
|
2044
|
+
};
|
|
2045
|
+
export const strategyMaxWithdrawTx = async (
|
|
2060
2046
|
// AppContext
|
|
2061
2047
|
reserveMap, rewardsMap,
|
|
2062
2048
|
// Strategy
|
|
2063
|
-
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, withdrawCoinType, transaction, dryRunTransaction) =>
|
|
2064
|
-
var _a, _b, _c, _d;
|
|
2049
|
+
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, withdrawCoinType, transaction, dryRunTransaction) => {
|
|
2065
2050
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
2066
2051
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
2067
2052
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
@@ -2081,14 +2066,14 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2081
2066
|
_borrowedAmount: _borrowedAmount.toFixed(20),
|
|
2082
2067
|
withdrawCoinType,
|
|
2083
2068
|
}, null, 2));
|
|
2084
|
-
const depositReserve = (
|
|
2069
|
+
const depositReserve = (depositReserves.base ?? depositReserves.lst); // Must have LST if no base
|
|
2085
2070
|
//
|
|
2086
2071
|
let deposits = cloneDeep(_deposits);
|
|
2087
2072
|
let borrowedAmount = _borrowedAmount;
|
|
2088
2073
|
// 1) Unloop to 1x (base+LST: no LST and no borrows, LST: no borrows)
|
|
2089
2074
|
if (borrowedAmount.gt(0)) {
|
|
2090
2075
|
// 1.1) Unloop
|
|
2091
|
-
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } =
|
|
2076
|
+
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = await strategyUnloopToExposureTx(reserveMap, lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, undefined, // Don't pass targetBorrowedAmount
|
|
2092
2077
|
new BigNumber(1), // Pass targetExposure
|
|
2093
2078
|
transaction, dryRunTransaction);
|
|
2094
2079
|
// 1.2) Update state
|
|
@@ -2104,7 +2089,8 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2104
2089
|
}, null, 2));
|
|
2105
2090
|
}
|
|
2106
2091
|
// 2) MAX withdraw base or LST
|
|
2107
|
-
const estimatedWithdrawnAmount =
|
|
2092
|
+
const estimatedWithdrawnAmount = deposits.find((d) => d.coinType === depositReserve.coinType)
|
|
2093
|
+
?.depositedAmount ?? new BigNumber(0);
|
|
2108
2094
|
const [withdrawnCoin] = strategyWithdraw(strategyType, depositReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserve.coinType), BigInt(MAX_U64.toString()), transaction);
|
|
2109
2095
|
// 2.2) Update state
|
|
2110
2096
|
deposits = [];
|
|
@@ -2116,9 +2102,9 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2116
2102
|
borrowedAmount: borrowedAmount.toFixed(20),
|
|
2117
2103
|
}, null, 2));
|
|
2118
2104
|
// 3) Transfer coin to user
|
|
2119
|
-
if (depositReserve.coinType ===
|
|
2105
|
+
if (depositReserve.coinType === depositReserves.base?.coinType) {
|
|
2120
2106
|
if (withdrawCoinType !== depositReserve.coinType) {
|
|
2121
|
-
const routers =
|
|
2107
|
+
const routers = await cetusSdk.findRouters({
|
|
2122
2108
|
from: depositReserve.coinType,
|
|
2123
2109
|
target: withdrawCoinType,
|
|
2124
2110
|
amount: new BN(estimatedWithdrawnAmount
|
|
@@ -2133,7 +2119,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2133
2119
|
const slippagePercent = 1;
|
|
2134
2120
|
let swappedCoin;
|
|
2135
2121
|
try {
|
|
2136
|
-
swappedCoin = (
|
|
2122
|
+
swappedCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
2137
2123
|
router: routers,
|
|
2138
2124
|
inputCoin: withdrawnCoin,
|
|
2139
2125
|
slippage: slippagePercent / 100,
|
|
@@ -2176,13 +2162,12 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2176
2162
|
}
|
|
2177
2163
|
}
|
|
2178
2164
|
return { deposits, borrowedAmount, transaction };
|
|
2179
|
-
}
|
|
2180
|
-
export const strategyAdjustRepayTx = (
|
|
2165
|
+
};
|
|
2166
|
+
export const strategyAdjustRepayTx = async (
|
|
2181
2167
|
// AppContext
|
|
2182
2168
|
reserveMap,
|
|
2183
2169
|
// Strategy
|
|
2184
|
-
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, flashLoanBorrowedAmount, transaction, dryRunTransaction) =>
|
|
2185
|
-
var _a, _b, _c, _d, _e;
|
|
2170
|
+
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, flashLoanBorrowedAmount, transaction, dryRunTransaction) => {
|
|
2186
2171
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
2187
2172
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
2188
2173
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
@@ -2245,7 +2230,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2245
2230
|
});
|
|
2246
2231
|
// 2) Swap flash loaned base for borrow
|
|
2247
2232
|
// 2.1) Get routers
|
|
2248
|
-
const routers =
|
|
2233
|
+
const routers = await cetusSdk.findRouters({
|
|
2249
2234
|
from: depositReserves.base.coinType,
|
|
2250
2235
|
target: borrowReserve.coinType,
|
|
2251
2236
|
amount: new BN(flashLoanBorrowedAmount
|
|
@@ -2270,7 +2255,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2270
2255
|
// 2.2) Swap
|
|
2271
2256
|
let swapCoin;
|
|
2272
2257
|
try {
|
|
2273
|
-
swapCoin = (
|
|
2258
|
+
swapCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
2274
2259
|
router: routers,
|
|
2275
2260
|
inputCoin: flashLoanBorrowedCoin,
|
|
2276
2261
|
slippage: 1 / 100,
|
|
@@ -2301,15 +2286,15 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2301
2286
|
typeArguments: [],
|
|
2302
2287
|
arguments: [receipt],
|
|
2303
2288
|
});
|
|
2304
|
-
const dryRunResults =
|
|
2289
|
+
const dryRunResults = await dryRunTransaction(transaction);
|
|
2305
2290
|
const flashLoanRepayAmount = new BigNumber(bcs
|
|
2306
2291
|
.u64()
|
|
2307
|
-
.parse(
|
|
2292
|
+
.parse(dryRunResults.commandResults?.[receiptDebts.Result]?.returnValues?.[flashLoanObj.borrowA ? 0 : 1]?.bcs ?? new Uint8Array([0])))
|
|
2308
2293
|
.div(10 ** depositReserves.base.token.decimals)
|
|
2309
2294
|
.decimalPlaces(depositReserves.base.token.decimals, BigNumber.ROUND_UP);
|
|
2310
2295
|
// 5.1) Withdraw base + fee
|
|
2311
2296
|
const withdrawnAmount = flashLoanRepayAmount;
|
|
2312
|
-
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, withdrawnCoin, } =
|
|
2297
|
+
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, withdrawnCoin, } = await strategyWithdrawTx(reserveMap, lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, {
|
|
2313
2298
|
coinType: depositReserves.base.coinType,
|
|
2314
2299
|
withdrawnAmount,
|
|
2315
2300
|
}, transaction, dryRunTransaction, true);
|
|
@@ -2345,13 +2330,12 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2345
2330
|
throw new Error("Invalid flash loan provider");
|
|
2346
2331
|
}
|
|
2347
2332
|
return { deposits, borrowedAmount, transaction };
|
|
2348
|
-
}
|
|
2349
|
-
export const strategyDepositAdjustWithdrawTx = (
|
|
2333
|
+
};
|
|
2334
|
+
export const strategyDepositAdjustWithdrawTx = async (
|
|
2350
2335
|
// AppContext
|
|
2351
2336
|
reserveMap,
|
|
2352
2337
|
// Strategy
|
|
2353
|
-
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, flashLoanBorrowedAmount, transaction, dryRunTransaction) =>
|
|
2354
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
2338
|
+
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, flashLoanBorrowedAmount, transaction, dryRunTransaction) => {
|
|
2355
2339
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
2356
2340
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
2357
2341
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
@@ -2371,7 +2355,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2371
2355
|
_borrowedAmount: _borrowedAmount.toFixed(20),
|
|
2372
2356
|
flashLoanBorrowedAmount: flashLoanBorrowedAmount.toFixed(20),
|
|
2373
2357
|
}, null, 2));
|
|
2374
|
-
const depositReserve = (
|
|
2358
|
+
const depositReserve = (depositReserves.base ?? depositReserves.lst); // Must have LST if no base
|
|
2375
2359
|
//
|
|
2376
2360
|
let deposits = cloneDeep(_deposits);
|
|
2377
2361
|
let borrowedAmount = _borrowedAmount;
|
|
@@ -2380,12 +2364,12 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2380
2364
|
const flashLoanCoinType = flashLoanObj.borrowA
|
|
2381
2365
|
? flashLoanObj.coinTypeA
|
|
2382
2366
|
: flashLoanObj.coinTypeB;
|
|
2383
|
-
const flashLoanCoinReserve =
|
|
2367
|
+
const flashLoanCoinReserve = reserveMap[flashLoanCoinType] ?? depositReserve;
|
|
2384
2368
|
const needsFlashLoanCoinSwap = flashLoanCoinType !== depositReserve.coinType;
|
|
2385
|
-
if (depositReserve.coinType ===
|
|
2369
|
+
if (depositReserve.coinType === depositReserves.lst?.coinType) {
|
|
2386
2370
|
// TODO: Account for LST mint fees
|
|
2387
2371
|
flashLoanBorrowedAmount = flashLoanBorrowedAmount
|
|
2388
|
-
.times(
|
|
2372
|
+
.times(lst?.lstToSuiExchangeRate ?? 1)
|
|
2389
2373
|
.decimalPlaces(SUI_DECIMALS, BigNumber.ROUND_UP);
|
|
2390
2374
|
}
|
|
2391
2375
|
let flashLoanBorrowAmountForLoan = flashLoanBorrowedAmount;
|
|
@@ -2404,7 +2388,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2404
2388
|
transaction.pure.u64(flashLoanObj.borrowA
|
|
2405
2389
|
? flashLoanBorrowAmountForLoan
|
|
2406
2390
|
.times(10 **
|
|
2407
|
-
(depositReserve.coinType ===
|
|
2391
|
+
(depositReserve.coinType === depositReserves.lst?.coinType
|
|
2408
2392
|
? SUI_DECIMALS
|
|
2409
2393
|
: depositReserve.token.decimals))
|
|
2410
2394
|
.integerValue(BigNumber.ROUND_DOWN)
|
|
@@ -2414,7 +2398,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2414
2398
|
? 0
|
|
2415
2399
|
: flashLoanBorrowAmountForLoan
|
|
2416
2400
|
.times(10 **
|
|
2417
|
-
(depositReserve.coinType ===
|
|
2401
|
+
(depositReserve.coinType === depositReserves.lst?.coinType
|
|
2418
2402
|
? SUI_DECIMALS
|
|
2419
2403
|
: flashLoanCoinReserve.token.decimals))
|
|
2420
2404
|
.integerValue(BigNumber.ROUND_DOWN)
|
|
@@ -2429,9 +2413,9 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2429
2413
|
// 2) Deposit additional (to get back up to 100% health, so the user can then unloop back down to the max leverage shown in the UI)
|
|
2430
2414
|
// 2.1) Deposit
|
|
2431
2415
|
let depositedAmount = flashLoanBorrowedAmount;
|
|
2432
|
-
if (depositReserve.coinType ===
|
|
2416
|
+
if (depositReserve.coinType === depositReserves.lst?.coinType)
|
|
2433
2417
|
depositedAmount = new BigNumber(depositedAmount.minus(getStrategyLstMintFee(lstMap, depositReserve.coinType, depositedAmount)))
|
|
2434
|
-
.times(
|
|
2418
|
+
.times(lst?.suiToLstExchangeRate ?? 1)
|
|
2435
2419
|
.decimalPlaces(depositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
2436
2420
|
let flashLoanBorrowedCoin = transaction.moveCall({
|
|
2437
2421
|
target: "0x2::coin::from_balance",
|
|
@@ -2440,10 +2424,10 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2440
2424
|
],
|
|
2441
2425
|
arguments: [flashLoanObj.borrowA ? borrowedBalanceA : borrowedBalanceB],
|
|
2442
2426
|
});
|
|
2443
|
-
if (depositReserve.coinType ===
|
|
2427
|
+
if (depositReserve.coinType === depositReserves.lst?.coinType)
|
|
2444
2428
|
flashLoanBorrowedCoin = lst.client.mint(transaction, flashLoanBorrowedCoin);
|
|
2445
2429
|
if (needsFlashLoanCoinSwap) {
|
|
2446
|
-
const depositRouters =
|
|
2430
|
+
const depositRouters = await cetusSdk.findRouters({
|
|
2447
2431
|
from: flashLoanCoinType,
|
|
2448
2432
|
target: depositReserve.coinType,
|
|
2449
2433
|
amount: new BN(flashLoanBorrowAmountForLoan
|
|
@@ -2456,7 +2440,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2456
2440
|
if (!depositRouters)
|
|
2457
2441
|
throw new Error("No swap quote found");
|
|
2458
2442
|
try {
|
|
2459
|
-
flashLoanBorrowedCoin = (
|
|
2443
|
+
flashLoanBorrowedCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
2460
2444
|
router: depositRouters,
|
|
2461
2445
|
inputCoin: flashLoanBorrowedCoin,
|
|
2462
2446
|
slippage: 1 / 100,
|
|
@@ -2476,7 +2460,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2476
2460
|
});
|
|
2477
2461
|
// 3) Unloop to max exposure
|
|
2478
2462
|
// 3.1) Unloop
|
|
2479
|
-
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } =
|
|
2463
|
+
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = await strategyUnloopToExposureTx(reserveMap, lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, undefined, // Don't pass targetBorrowedAmount
|
|
2480
2464
|
depositAdjustWithdrawExposure, // Pass targetExposure
|
|
2481
2465
|
transaction, dryRunTransaction);
|
|
2482
2466
|
// 3.2) Update state
|
|
@@ -2489,10 +2473,10 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2489
2473
|
typeArguments: [],
|
|
2490
2474
|
arguments: [receipt],
|
|
2491
2475
|
});
|
|
2492
|
-
const dryRunResults =
|
|
2476
|
+
const dryRunResults = await dryRunTransaction(transaction);
|
|
2493
2477
|
const flashLoanRepayAmount = new BigNumber(bcs
|
|
2494
2478
|
.u64()
|
|
2495
|
-
.parse(
|
|
2479
|
+
.parse(dryRunResults.commandResults?.[receiptDebts.Result]?.returnValues?.[flashLoanObj.borrowA ? 0 : 1]?.bcs ?? new Uint8Array([0])))
|
|
2496
2480
|
.div(10 ** flashLoanCoinReserve.token.decimals)
|
|
2497
2481
|
.decimalPlaces(flashLoanCoinReserve.token.decimals, BigNumber.ROUND_UP);
|
|
2498
2482
|
// 4.1) Withdraw additional + fee
|
|
@@ -2501,11 +2485,11 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2501
2485
|
withdrawnAmount = flashLoanRepayAmount
|
|
2502
2486
|
.times(1.01) // Buffer for swap slippage
|
|
2503
2487
|
.decimalPlaces(depositReserve.token.decimals, BigNumber.ROUND_UP);
|
|
2504
|
-
else if (depositReserve.coinType ===
|
|
2488
|
+
else if (depositReserve.coinType === depositReserves.lst?.coinType)
|
|
2505
2489
|
withdrawnAmount = withdrawnAmount
|
|
2506
|
-
.div(1 - +(
|
|
2490
|
+
.div(1 - +(lst?.redeemFeePercent ?? 0) / 100) // Potential rounding issue (max 1 MIST)
|
|
2507
2491
|
.decimalPlaces(depositReserve.token.decimals, BigNumber.ROUND_UP);
|
|
2508
|
-
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, withdrawnCoin, } =
|
|
2492
|
+
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, withdrawnCoin, } = await strategyWithdrawTx(reserveMap, lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, {
|
|
2509
2493
|
coinType: depositReserve.coinType,
|
|
2510
2494
|
withdrawnAmount,
|
|
2511
2495
|
}, transaction, dryRunTransaction, true);
|
|
@@ -2517,10 +2501,10 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2517
2501
|
transaction = newTransaction2;
|
|
2518
2502
|
// 4.3) Repay flash loan
|
|
2519
2503
|
let flashLoanRepayCoin = withdrawnCoin;
|
|
2520
|
-
if (depositReserve.coinType ===
|
|
2504
|
+
if (depositReserve.coinType === depositReserves.lst?.coinType)
|
|
2521
2505
|
flashLoanRepayCoin = lst.client.redeem(transaction, flashLoanRepayCoin);
|
|
2522
2506
|
if (needsFlashLoanCoinSwap) {
|
|
2523
|
-
const repayRouters =
|
|
2507
|
+
const repayRouters = await cetusSdk.findRouters({
|
|
2524
2508
|
from: depositReserve.coinType,
|
|
2525
2509
|
target: flashLoanCoinType,
|
|
2526
2510
|
amount: new BN(withdrawnAmount
|
|
@@ -2533,7 +2517,7 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2533
2517
|
if (!repayRouters)
|
|
2534
2518
|
throw new Error("No swap quote found");
|
|
2535
2519
|
try {
|
|
2536
|
-
flashLoanRepayCoin = (
|
|
2520
|
+
flashLoanRepayCoin = (await cetusSdk.fixableRouterSwapV3({
|
|
2537
2521
|
router: repayRouters,
|
|
2538
2522
|
inputCoin: flashLoanRepayCoin,
|
|
2539
2523
|
slippage: 1 / 100,
|
|
@@ -2569,12 +2553,12 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2569
2553
|
throw new Error("Invalid flash loan provider");
|
|
2570
2554
|
}
|
|
2571
2555
|
return { deposits, borrowedAmount, transaction };
|
|
2572
|
-
}
|
|
2573
|
-
export const strategyAdjustTx = (
|
|
2556
|
+
};
|
|
2557
|
+
export const strategyAdjustTx = async (
|
|
2574
2558
|
// AppContext
|
|
2575
2559
|
reserveMap,
|
|
2576
2560
|
// Strategy
|
|
2577
|
-
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligation, _deposits, _borrowedAmount, targetExposure, transaction, dryRunTransaction) =>
|
|
2561
|
+
lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligation, _deposits, _borrowedAmount, targetExposure, transaction, dryRunTransaction) => {
|
|
2578
2562
|
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
2579
2563
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
2580
2564
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
@@ -2608,4 +2592,4 @@ lstMap, strategyType, suiGrpcClient, suilendClient, cetusSdk, cetusPartnerId, _a
|
|
|
2608
2592
|
transaction, dryRunTransaction);
|
|
2609
2593
|
else
|
|
2610
2594
|
return { deposits, borrowedAmount, transaction };
|
|
2611
|
-
}
|
|
2595
|
+
};
|