@suilend/sdk 1.1.99 → 2.0.1
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 +7 -7
- package/_generated/_dependencies/source/0x1/ascii/structs.js +35 -75
- package/_generated/_dependencies/source/0x1/index.js +3 -6
- package/_generated/_dependencies/source/0x1/option/structs.d.ts +3 -3
- package/_generated/_dependencies/source/0x1/option/structs.js +31 -69
- package/_generated/_dependencies/source/0x1/type-name/structs.d.ts +5 -5
- package/_generated/_dependencies/source/0x1/type-name/structs.js +20 -25
- package/_generated/_dependencies/source/0x2/bag/structs.d.ts +7 -7
- package/_generated/_dependencies/source/0x2/bag/structs.js +24 -29
- package/_generated/_dependencies/source/0x2/balance/structs.d.ts +7 -7
- package/_generated/_dependencies/source/0x2/balance/structs.js +49 -56
- package/_generated/_dependencies/source/0x2/index.js +3 -6
- package/_generated/_dependencies/source/0x2/object/structs.d.ts +8 -8
- package/_generated/_dependencies/source/0x2/object/structs.js +34 -41
- package/_generated/_dependencies/source/0x2/object-table/structs.d.ts +7 -7
- package/_generated/_dependencies/source/0x2/object-table/structs.js +31 -36
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/i64/structs.d.ts +5 -5
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/i64/structs.js +23 -28
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/index.js +4 -7
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price/structs.d.ts +11 -11
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price/structs.js +32 -37
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-feed/structs.d.ts +23 -23
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-feed/structs.js +29 -34
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs.d.ts +4 -4
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-identifier/structs.js +21 -59
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-info/structs.d.ts +55 -55
- package/_generated/_dependencies/source/0x8d97f1cd6ac663735be08d1d2b6d02a159e711586461306ce60a2b7a6a565a9e/price-info/structs.js +46 -53
- package/_generated/_framework/reified.d.ts +2 -2
- package/_generated/_framework/reified.js +27 -40
- package/_generated/_framework/util.js +26 -40
- package/_generated/_framework/vector.d.ts +4 -4
- package/_generated/_framework/vector.js +16 -21
- package/_generated/suilend/cell/structs.d.ts +4 -4
- package/_generated/suilend/cell/structs.js +31 -36
- package/_generated/suilend/decimal/structs.d.ts +4 -4
- package/_generated/suilend/decimal/structs.js +19 -24
- package/_generated/suilend/index.js +8 -12
- package/_generated/suilend/lending-market/functions.d.ts +1 -0
- package/_generated/suilend/lending-market/functions.js +271 -302
- package/_generated/suilend/lending-market/structs.d.ts +146 -146
- package/_generated/suilend/lending-market/structs.js +549 -617
- package/_generated/suilend/lending-market-registry/functions.js +7 -11
- package/_generated/suilend/liquidity-mining/structs.d.ts +50 -50
- package/_generated/suilend/liquidity-mining/structs.js +159 -205
- package/_generated/suilend/obligation/structs.d.ts +106 -106
- package/_generated/suilend/obligation/structs.js +313 -363
- package/_generated/suilend/rate-limiter/functions.js +23 -31
- package/_generated/suilend/rate-limiter/structs.d.ts +15 -15
- package/_generated/suilend/rate-limiter/structs.js +49 -56
- package/_generated/suilend/reserve/structs.d.ts +139 -139
- package/_generated/suilend/reserve/structs.js +397 -451
- package/_generated/suilend/reserve-config/functions.js +149 -190
- package/_generated/suilend/reserve-config/structs.d.ts +33 -33
- package/_generated/suilend/reserve-config/structs.js +109 -149
- package/api/events.js +1 -5
- package/api/index.js +1 -17
- package/client.d.ts +10 -10
- package/client.js +118 -128
- package/index.js +7 -23
- package/lib/constants.js +3 -9
- package/lib/index.js +5 -21
- package/lib/initialize.d.ts +3 -3
- package/lib/initialize.js +103 -140
- package/lib/liquidityMining.d.ts +3 -3
- package/lib/liquidityMining.js +57 -72
- package/lib/pyth.js +9 -14
- package/lib/strategyOwnerCap.js +106 -119
- package/lib/transactions.js +2 -7
- package/lib/types.js +4 -7
- package/mmt.js +2 -5
- package/package.json +1 -1
- package/parsers/apiReserveAssetDataEvent.js +25 -33
- package/parsers/index.js +5 -21
- package/parsers/lendingMarket.d.ts +1 -1
- package/parsers/lendingMarket.js +12 -19
- package/parsers/obligation.js +19 -26
- package/parsers/rateLimiter.js +11 -19
- package/parsers/reserve.d.ts +1 -1
- package/parsers/reserve.js +42 -85
- package/strategies.d.ts +11 -11
- package/strategies.js +547 -586
- package/swap/index.js +2 -18
- package/swap/quote.js +57 -65
- package/swap/transaction.d.ts +2 -2
- package/swap/transaction.js +40 -35
- package/utils/events.d.ts +3 -3
- package/utils/events.js +18 -35
- package/utils/index.js +16 -40
- package/utils/obligation.d.ts +4 -4
- package/utils/obligation.js +17 -60
- package/utils/simulate.js +118 -143
package/strategies.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,116 +7,111 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
const mmt_1 = require("./mmt");
|
|
28
|
-
const utils_2 = require("./utils");
|
|
29
|
-
exports.STRATEGY_E = 10 ** -7;
|
|
30
|
-
exports.LST_DECIMALS = 9;
|
|
31
|
-
var StrategyFlashLoanProvider;
|
|
10
|
+
import { bcs } from "@mysten/bcs";
|
|
11
|
+
import { Transaction, } from "@mysten/sui/transactions";
|
|
12
|
+
import { SUI_DECIMALS } from "@mysten/sui/utils";
|
|
13
|
+
import BigNumber from "bignumber.js";
|
|
14
|
+
import { BN } from "bn.js";
|
|
15
|
+
import { cloneDeep } from "lodash";
|
|
16
|
+
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, getAllCoins, isSui, mergeAllCoins, } from "@suilend/sui-fe";
|
|
18
|
+
import { getNetAprPercent } from "./lib";
|
|
19
|
+
import { getRewardsMap } from "./lib/liquidityMining";
|
|
20
|
+
import { STRATEGY_TYPE_INFO_MAP, StrategyType, strategyBorrow, strategyClaimRewardsAndSwapForCoinType, strategyDeposit, strategyWithdraw, } from "./lib/strategyOwnerCap";
|
|
21
|
+
import { MMT_CONTRACT_PACKAGE_ID, MMT_VERSION_OBJECT_ID } from "./mmt";
|
|
22
|
+
import { getWeightedBorrowsUsd } from "./utils";
|
|
23
|
+
export const STRATEGY_E = 10 ** -7;
|
|
24
|
+
export const LST_DECIMALS = 9;
|
|
25
|
+
export var StrategyFlashLoanProvider;
|
|
32
26
|
(function (StrategyFlashLoanProvider) {
|
|
33
27
|
StrategyFlashLoanProvider["MMT"] = "mmt";
|
|
34
|
-
})(StrategyFlashLoanProvider || (
|
|
35
|
-
|
|
36
|
-
[
|
|
28
|
+
})(StrategyFlashLoanProvider || (StrategyFlashLoanProvider = {}));
|
|
29
|
+
export const STRATEGY_TYPE_FLASH_LOAN_OBJ_MAP = {
|
|
30
|
+
[StrategyType.sSUI_SUI_LOOPING]: {
|
|
37
31
|
provider: StrategyFlashLoanProvider.MMT,
|
|
38
32
|
poolId: "0x9c92c5b8e9d83e485fb4c86804ac8b920bb0beaace5e61a5b0239218f627f8e9", // xSUI-SUI 0.01% https://app.mmt.finance/liquidity/0x9c92c5b8e9d83e485fb4c86804ac8b920bb0beaace5e61a5b0239218f627f8e9
|
|
39
33
|
coinTypeA: "0x2b6602099970374cf58a2a1b9d96f005fccceb81e92eb059873baf420eb6c717::x_sui::X_SUI",
|
|
40
|
-
coinTypeB:
|
|
34
|
+
coinTypeB: NORMALIZED_SUI_COINTYPE,
|
|
41
35
|
borrowA: false,
|
|
42
36
|
feePercent: 0.01,
|
|
43
37
|
},
|
|
44
|
-
[
|
|
38
|
+
[StrategyType.stratSUI_SUI_LOOPING]: {
|
|
45
39
|
provider: StrategyFlashLoanProvider.MMT,
|
|
46
40
|
poolId: "0x9c92c5b8e9d83e485fb4c86804ac8b920bb0beaace5e61a5b0239218f627f8e9", // xSUI-SUI 0.01% https://app.mmt.finance/liquidity/0x9c92c5b8e9d83e485fb4c86804ac8b920bb0beaace5e61a5b0239218f627f8e9
|
|
47
41
|
coinTypeA: "0x2b6602099970374cf58a2a1b9d96f005fccceb81e92eb059873baf420eb6c717::x_sui::X_SUI",
|
|
48
|
-
coinTypeB:
|
|
42
|
+
coinTypeB: NORMALIZED_SUI_COINTYPE,
|
|
49
43
|
borrowA: false,
|
|
50
44
|
feePercent: 0.01,
|
|
51
45
|
},
|
|
52
|
-
[
|
|
46
|
+
[StrategyType.USDC_sSUI_SUI_LOOPING]: {
|
|
53
47
|
provider: StrategyFlashLoanProvider.MMT,
|
|
54
48
|
poolId: "0x737ec6a4d3ed0c7e6cc18d8ba04e7ffd4806b726c97efd89867597368c4d06a9", // suiUSDT-USDC 0.001% https://app.mmt.finance/liquidity/0x737ec6a4d3ed0c7e6cc18d8ba04e7ffd4806b726c97efd89867597368c4d06a9
|
|
55
|
-
coinTypeA:
|
|
56
|
-
coinTypeB:
|
|
49
|
+
coinTypeA: NORMALIZED_suiUSDT_COINTYPE,
|
|
50
|
+
coinTypeB: NORMALIZED_USDC_COINTYPE,
|
|
57
51
|
borrowA: false,
|
|
58
52
|
feePercent: 0.001,
|
|
59
53
|
},
|
|
60
|
-
[
|
|
54
|
+
[StrategyType.AUSD_sSUI_SUI_LOOPING]: {
|
|
61
55
|
provider: StrategyFlashLoanProvider.MMT,
|
|
62
56
|
poolId: "0x900f25b27d2b1686886277d763223988d802f3b6152d02872c382d4dce05e25b", // AUSD-USDC 0.01% https://app.mmt.finance/liquidity/0x900f25b27d2b1686886277d763223988d802f3b6152d02872c382d4dce05e25b
|
|
63
|
-
coinTypeA:
|
|
64
|
-
coinTypeB:
|
|
57
|
+
coinTypeA: NORMALIZED_AUSD_COINTYPE,
|
|
58
|
+
coinTypeB: NORMALIZED_USDC_COINTYPE,
|
|
65
59
|
borrowA: true,
|
|
66
60
|
feePercent: 0.01,
|
|
67
61
|
},
|
|
68
|
-
[
|
|
62
|
+
[StrategyType.xBTC_sSUI_SUI_LOOPING]: {
|
|
69
63
|
provider: StrategyFlashLoanProvider.MMT,
|
|
70
64
|
poolId: "0x57a662791cea065610455797dfd2751a3c10d929455d3ea88154a2b40cf6614e", // xBTC-suiWBTC 0.01% https://app.mmt.finance/liquidity/0x57a662791cea065610455797dfd2751a3c10d929455d3ea88154a2b40cf6614e
|
|
71
|
-
coinTypeA:
|
|
72
|
-
coinTypeB:
|
|
65
|
+
coinTypeA: NORMALIZED_xBTC_COINTYPE,
|
|
66
|
+
coinTypeB: NORMALIZED_suiWBTC_COINTYPE,
|
|
73
67
|
borrowA: true,
|
|
74
68
|
feePercent: 0.01,
|
|
75
69
|
},
|
|
76
|
-
[
|
|
70
|
+
[StrategyType.xBTC_suiWBTC_LOOPING]: {
|
|
77
71
|
provider: StrategyFlashLoanProvider.MMT,
|
|
78
72
|
poolId: "0x57a662791cea065610455797dfd2751a3c10d929455d3ea88154a2b40cf6614e", // xBTC-suiWBTC 0.01% https://app.mmt.finance/liquidity/0x57a662791cea065610455797dfd2751a3c10d929455d3ea88154a2b40cf6614e
|
|
79
|
-
coinTypeA:
|
|
80
|
-
coinTypeB:
|
|
73
|
+
coinTypeA: NORMALIZED_xBTC_COINTYPE,
|
|
74
|
+
coinTypeB: NORMALIZED_suiWBTC_COINTYPE,
|
|
81
75
|
borrowA: true,
|
|
82
76
|
feePercent: 0.01,
|
|
83
77
|
},
|
|
84
|
-
[
|
|
78
|
+
[StrategyType.suiUSDT_sSUI_SUI_LOOPING]: {
|
|
85
79
|
provider: StrategyFlashLoanProvider.MMT,
|
|
86
80
|
poolId: "0x737ec6a4d3ed0c7e6cc18d8ba04e7ffd4806b726c97efd89867597368c4d06a9", // suiUSDT-USDC 0.001% https://app.mmt.finance/liquidity/0x737ec6a4d3ed0c7e6cc18d8ba04e7ffd4806b726c97efd89867597368c4d06a9
|
|
87
|
-
coinTypeA:
|
|
88
|
-
coinTypeB:
|
|
81
|
+
coinTypeA: NORMALIZED_suiUSDT_COINTYPE,
|
|
82
|
+
coinTypeB: NORMALIZED_USDC_COINTYPE,
|
|
89
83
|
borrowA: true,
|
|
90
84
|
feePercent: 0.001,
|
|
91
85
|
},
|
|
92
|
-
[
|
|
86
|
+
[StrategyType.AUSD_USDC_LOOPING]: {
|
|
93
87
|
provider: StrategyFlashLoanProvider.MMT,
|
|
94
88
|
poolId: "0x900f25b27d2b1686886277d763223988d802f3b6152d02872c382d4dce05e25b", // AUSD-USDC 0.01% https://app.mmt.finance/liquidity/0x900f25b27d2b1686886277d763223988d802f3b6152d02872c382d4dce05e25b
|
|
95
|
-
coinTypeA:
|
|
96
|
-
coinTypeB:
|
|
89
|
+
coinTypeA: NORMALIZED_AUSD_COINTYPE,
|
|
90
|
+
coinTypeB: NORMALIZED_USDC_COINTYPE,
|
|
97
91
|
borrowA: true,
|
|
98
92
|
feePercent: 0.01,
|
|
99
93
|
},
|
|
100
|
-
[
|
|
94
|
+
[StrategyType.AUSD_suiUSDT_LOOPING]: {
|
|
101
95
|
provider: StrategyFlashLoanProvider.MMT,
|
|
102
96
|
poolId: "0x900f25b27d2b1686886277d763223988d802f3b6152d02872c382d4dce05e25b", // AUSD-USDC 0.01% https://app.mmt.finance/liquidity/0x900f25b27d2b1686886277d763223988d802f3b6152d02872c382d4dce05e25b
|
|
103
|
-
coinTypeA:
|
|
104
|
-
coinTypeB:
|
|
97
|
+
coinTypeA: NORMALIZED_AUSD_COINTYPE,
|
|
98
|
+
coinTypeB: NORMALIZED_USDC_COINTYPE,
|
|
105
99
|
borrowA: true,
|
|
106
100
|
feePercent: 0.01,
|
|
107
101
|
},
|
|
108
|
-
[
|
|
102
|
+
[StrategyType.USDC_suiUSDT_LOOPING]: {
|
|
109
103
|
provider: StrategyFlashLoanProvider.MMT,
|
|
110
104
|
poolId: "0x737ec6a4d3ed0c7e6cc18d8ba04e7ffd4806b726c97efd89867597368c4d06a9", // suiUSDT-USDC 0.001% https://app.mmt.finance/liquidity/0x737ec6a4d3ed0c7e6cc18d8ba04e7ffd4806b726c97efd89867597368c4d06a9
|
|
111
|
-
coinTypeA:
|
|
112
|
-
coinTypeB:
|
|
105
|
+
coinTypeA: NORMALIZED_suiUSDT_COINTYPE,
|
|
106
|
+
coinTypeB: NORMALIZED_USDC_COINTYPE,
|
|
113
107
|
borrowA: false,
|
|
114
108
|
feePercent: 0.001,
|
|
115
109
|
},
|
|
116
110
|
};
|
|
117
|
-
const getReserveSafeDepositLimit = (reserve) => {
|
|
111
|
+
export const getReserveSafeDepositLimit = (reserve) => {
|
|
118
112
|
// Calculate safe deposit limit (subtract 10 mins of deposit APR from cap)
|
|
119
113
|
const tenMinsDepositAprPercent = reserve.depositAprPercent
|
|
120
|
-
.div(
|
|
114
|
+
.div(MS_PER_YEAR)
|
|
121
115
|
.times(10 * 60 * 1000);
|
|
122
116
|
const safeDepositLimit = reserve.config.depositLimit.minus(reserve.depositedAmount.times(tenMinsDepositAprPercent.div(100)));
|
|
123
117
|
const safeDepositLimitUsd = reserve.config.depositLimitUsd.minus(reserve.depositedAmount
|
|
@@ -125,9 +119,8 @@ const getReserveSafeDepositLimit = (reserve) => {
|
|
|
125
119
|
.times(tenMinsDepositAprPercent.div(100)));
|
|
126
120
|
return { safeDepositLimit, safeDepositLimitUsd };
|
|
127
121
|
};
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
const deposits = (0, lodash_1.cloneDeep)(_deposits);
|
|
122
|
+
export const addOrInsertStrategyDeposit = (_deposits, deposit) => {
|
|
123
|
+
const deposits = cloneDeep(_deposits);
|
|
131
124
|
const existingDeposit = deposits.find((d) => d.coinType === deposit.coinType);
|
|
132
125
|
if (existingDeposit)
|
|
133
126
|
existingDeposit.depositedAmount = existingDeposit.depositedAmount.plus(deposit.depositedAmount);
|
|
@@ -135,26 +128,23 @@ const addOrInsertStrategyDeposit = (_deposits, deposit) => {
|
|
|
135
128
|
deposits.push(deposit);
|
|
136
129
|
return deposits;
|
|
137
130
|
};
|
|
138
|
-
exports.addOrInsertStrategyDeposit = addOrInsertStrategyDeposit;
|
|
139
131
|
// Obligations
|
|
140
|
-
const hasStrategyPosition = (obligation) => obligation.deposits.length > 0;
|
|
141
|
-
exports.hasStrategyPosition = hasStrategyPosition;
|
|
132
|
+
export const hasStrategyPosition = (obligation) => obligation.deposits.length > 0;
|
|
142
133
|
// SUI
|
|
143
|
-
const getStrategySuiReserve = (
|
|
134
|
+
export const getStrategySuiReserve = (
|
|
144
135
|
// AppContext
|
|
145
|
-
reserveMap) => reserveMap[
|
|
146
|
-
|
|
147
|
-
const fetchStrategyLstMap = (suiClient) => __awaiter(void 0, void 0, void 0, function* () {
|
|
136
|
+
reserveMap) => reserveMap[NORMALIZED_SUI_COINTYPE];
|
|
137
|
+
export const fetchStrategyLstMap = (suiClient) => __awaiter(void 0, void 0, void 0, function* () {
|
|
148
138
|
try {
|
|
149
139
|
const lstCoinTypes = Array.from(new Set([
|
|
150
|
-
...Object.values(
|
|
140
|
+
...Object.values(STRATEGY_TYPE_INFO_MAP)
|
|
151
141
|
.map(({ depositLstCoinType }) => depositLstCoinType)
|
|
152
142
|
.filter(Boolean),
|
|
153
143
|
// LSTs that will be/are/have been used as rewards
|
|
154
|
-
|
|
144
|
+
NORMALIZED_sSUI_COINTYPE,
|
|
155
145
|
]));
|
|
156
|
-
const publishedAt = yield (
|
|
157
|
-
const lstInfoUrl = `${
|
|
146
|
+
const publishedAt = yield getLatestSpringSuiPackageId(suiClient, SPRING_SUI_UPGRADE_CAP_ID);
|
|
147
|
+
const lstInfoUrl = `${API_URL}/springsui/lst-info?${new URLSearchParams({
|
|
158
148
|
coinTypes: lstCoinTypes.join(","),
|
|
159
149
|
})}`;
|
|
160
150
|
const lstInfoRes = yield fetch(lstInfoUrl);
|
|
@@ -167,17 +157,17 @@ const fetchStrategyLstMap = (suiClient) => __awaiter(void 0, void 0, void 0, fun
|
|
|
167
157
|
const result = Object.fromEntries(yield Promise.all(lstCoinTypes.map((lstCoinType) => __awaiter(void 0, void 0, void 0, function* () {
|
|
168
158
|
var _a, _b, _c, _d;
|
|
169
159
|
const lstInfo = lstInfoMap[lstCoinType];
|
|
170
|
-
const lstClient = yield
|
|
171
|
-
const mintFeePercent = new
|
|
172
|
-
const redeemFeePercent = new
|
|
173
|
-
const res = yield fetch(`${
|
|
160
|
+
const lstClient = yield LstClient.initialize(suiClient, lstInfo.LIQUID_STAKING_INFO, publishedAt);
|
|
161
|
+
const mintFeePercent = new BigNumber((_b = (_a = lstInfo.liquidStakingInfo.feeConfig.element) === null || _a === void 0 ? void 0 : _a.suiMintFeeBps.toString()) !== null && _b !== void 0 ? _b : 0).div(100);
|
|
162
|
+
const redeemFeePercent = new BigNumber((_d = (_c = lstInfo.liquidStakingInfo.feeConfig.element) === null || _c === void 0 ? void 0 : _c.redeemFeeBps.toString()) !== null && _d !== void 0 ? _d : 0).div(100);
|
|
163
|
+
const res = yield fetch(`${API_URL}/springsui/historical-rates?coinType=${lstCoinType}×tamps=${Math.floor(Date.now() / 1000)}`);
|
|
174
164
|
const json = yield res.json();
|
|
175
165
|
if ((json === null || json === void 0 ? void 0 : json.statusCode) === 500)
|
|
176
166
|
throw new Error(`Failed to fetch historical LST to SUI exchange rates for ${lstCoinType}`);
|
|
177
|
-
const suiToLstExchangeRate = !new
|
|
178
|
-
? new
|
|
179
|
-
: new
|
|
180
|
-
const lstToSuiExchangeRate = new
|
|
167
|
+
const suiToLstExchangeRate = !new BigNumber(json[0].value).eq(0)
|
|
168
|
+
? new BigNumber(1).div(new BigNumber(json[0].value))
|
|
169
|
+
: new BigNumber(1);
|
|
170
|
+
const lstToSuiExchangeRate = new BigNumber(json[0].value);
|
|
181
171
|
return [
|
|
182
172
|
lstCoinType,
|
|
183
173
|
{
|
|
@@ -196,89 +186,86 @@ const fetchStrategyLstMap = (suiClient) => __awaiter(void 0, void 0, void 0, fun
|
|
|
196
186
|
console.error(err);
|
|
197
187
|
}
|
|
198
188
|
});
|
|
199
|
-
|
|
200
|
-
const getStrategyLstMintFee = (
|
|
189
|
+
export const getStrategyLstMintFee = (
|
|
201
190
|
// Strategy
|
|
202
191
|
lstMap, lstCoinType, suiAmount) => {
|
|
203
192
|
var _a, _b;
|
|
204
|
-
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
|
|
193
|
+
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);
|
|
205
194
|
return suiAmount
|
|
206
195
|
.times(mintFeePercent.div(100))
|
|
207
|
-
.decimalPlaces(
|
|
196
|
+
.decimalPlaces(SUI_DECIMALS, BigNumber.ROUND_UP);
|
|
208
197
|
};
|
|
209
|
-
|
|
210
|
-
const getStrategyLstRedeemFee = (
|
|
198
|
+
export const getStrategyLstRedeemFee = (
|
|
211
199
|
// Strategy
|
|
212
200
|
lstMap, lstCoinType, lstAmount) => {
|
|
213
201
|
var _a, _b, _c, _d;
|
|
214
|
-
const lstToSuiExchangeRate = (_b = (_a = lstMap === null || lstMap === void 0 ? void 0 : lstMap[lstCoinType]) === null || _a === void 0 ? void 0 : _a.lstToSuiExchangeRate) !== null && _b !== void 0 ? _b : new
|
|
215
|
-
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
|
|
202
|
+
const lstToSuiExchangeRate = (_b = (_a = lstMap === null || lstMap === void 0 ? void 0 : lstMap[lstCoinType]) === null || _a === void 0 ? void 0 : _a.lstToSuiExchangeRate) !== null && _b !== void 0 ? _b : new BigNumber(1);
|
|
203
|
+
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);
|
|
216
204
|
const suiAmount = lstAmount.times(lstToSuiExchangeRate);
|
|
217
205
|
return suiAmount
|
|
218
206
|
.times(redeemFeePercent.div(100))
|
|
219
|
-
.decimalPlaces(
|
|
207
|
+
.decimalPlaces(SUI_DECIMALS, BigNumber.ROUND_UP);
|
|
220
208
|
};
|
|
221
|
-
exports.getStrategyLstRedeemFee = getStrategyLstRedeemFee;
|
|
222
209
|
// Exposure map
|
|
223
|
-
|
|
224
|
-
[
|
|
225
|
-
min: new
|
|
226
|
-
max: new
|
|
227
|
-
default: new
|
|
210
|
+
export const STRATEGY_TYPE_EXPOSURE_MAP = {
|
|
211
|
+
[StrategyType.sSUI_SUI_LOOPING]: {
|
|
212
|
+
min: new BigNumber(1),
|
|
213
|
+
max: new BigNumber(3), // Actual max: 1 / (1 - (sSUI Open LTV %)) = 3.333x, where sSUI Open LTV % = 70%
|
|
214
|
+
default: new BigNumber(3),
|
|
228
215
|
},
|
|
229
|
-
[
|
|
230
|
-
min: new
|
|
231
|
-
max: new
|
|
232
|
-
default: new
|
|
216
|
+
[StrategyType.stratSUI_SUI_LOOPING]: {
|
|
217
|
+
min: new BigNumber(1),
|
|
218
|
+
max: new BigNumber(3), // Actual max: 1 / (1 - (sSUI Open LTV %)) = 3.333x, where sSUI Open LTV % = 70%
|
|
219
|
+
default: new BigNumber(3),
|
|
233
220
|
},
|
|
234
|
-
[
|
|
235
|
-
min: new
|
|
236
|
-
max: new
|
|
237
|
-
default: new
|
|
221
|
+
[StrategyType.USDC_sSUI_SUI_LOOPING]: {
|
|
222
|
+
min: new BigNumber(1),
|
|
223
|
+
max: new BigNumber(3), // Actual max: 1 + (USDC Open LTV %) * (1 / (1 - (sSUI Open LTV %))) = 3.5666x, where USDC Open LTV % = 77% and sSUI Open LTV % = 70%
|
|
224
|
+
default: new BigNumber(3),
|
|
238
225
|
},
|
|
239
|
-
[
|
|
240
|
-
min: new
|
|
241
|
-
max: new
|
|
242
|
-
default: new
|
|
226
|
+
[StrategyType.AUSD_sSUI_SUI_LOOPING]: {
|
|
227
|
+
min: new BigNumber(1),
|
|
228
|
+
max: new BigNumber(3), // Actual max: 1 + (AUSD Open LTV %) * (1 / (1 - (sSUI Open LTV %))) = 3.5666x, where AUSD Open LTV % = 77% and sSUI Open LTV % = 70%
|
|
229
|
+
default: new BigNumber(3),
|
|
243
230
|
},
|
|
244
|
-
[
|
|
245
|
-
min: new
|
|
246
|
-
max: new
|
|
247
|
-
default: new
|
|
231
|
+
[StrategyType.xBTC_sSUI_SUI_LOOPING]: {
|
|
232
|
+
min: new BigNumber(1),
|
|
233
|
+
max: new BigNumber(2.5), // Actual max: 1 + (xBTC Open LTV %) * (1 / (1 - (sSUI Open LTV %))) = 3x, where xBTC Open LTV % = 60% and sSUI Open LTV % = 70%
|
|
234
|
+
default: new BigNumber(2.5),
|
|
248
235
|
},
|
|
249
|
-
[
|
|
250
|
-
min: new
|
|
251
|
-
max: new
|
|
252
|
-
default: new
|
|
236
|
+
[StrategyType.xBTC_suiWBTC_LOOPING]: {
|
|
237
|
+
min: new BigNumber(1),
|
|
238
|
+
max: new BigNumber(2.2), // Actual max: 1 / (1 - (xBTC Open LTV %)) = 2.5x, where xBTC Open LTV % = 60%
|
|
239
|
+
default: new BigNumber(2.2),
|
|
253
240
|
},
|
|
254
|
-
[
|
|
255
|
-
min: new
|
|
256
|
-
max: new
|
|
257
|
-
default: new
|
|
241
|
+
[StrategyType.suiUSDT_sSUI_SUI_LOOPING]: {
|
|
242
|
+
min: new BigNumber(1),
|
|
243
|
+
max: new BigNumber(3), // Actual max: 1 + (suiUSDT Open LTV %) * (1 / (1 - (sSUI Open LTV %))) = 3.5666x, where suiUSDT Open LTV % = 77% and sSUI Open LTV % = 70%
|
|
244
|
+
default: new BigNumber(3),
|
|
258
245
|
},
|
|
259
|
-
[
|
|
260
|
-
min: new
|
|
261
|
-
max: new
|
|
262
|
-
default: new
|
|
246
|
+
[StrategyType.AUSD_USDC_LOOPING]: {
|
|
247
|
+
min: new BigNumber(1),
|
|
248
|
+
max: new BigNumber(4), // Actual max: 1 / (1 - (AUSD Open LTV %)) = 4.347x, where AUSD Open LTV % = 77%
|
|
249
|
+
default: new BigNumber(4),
|
|
263
250
|
},
|
|
264
|
-
[
|
|
265
|
-
min: new
|
|
266
|
-
max: new
|
|
267
|
-
default: new
|
|
251
|
+
[StrategyType.AUSD_suiUSDT_LOOPING]: {
|
|
252
|
+
min: new BigNumber(1),
|
|
253
|
+
max: new BigNumber(4), // Actual max: 1 / (1 - (AUSD Open LTV %)) = 4.347x, where AUSD Open LTV % = 77%
|
|
254
|
+
default: new BigNumber(4),
|
|
268
255
|
},
|
|
269
|
-
[
|
|
270
|
-
min: new
|
|
271
|
-
max: new
|
|
272
|
-
default: new
|
|
256
|
+
[StrategyType.USDC_suiUSDT_LOOPING]: {
|
|
257
|
+
min: new BigNumber(1),
|
|
258
|
+
max: new BigNumber(4), // Actual max: 1 / (1 - (USDC Open LTV %)) = 4.347x, where USDC Open LTV % = 77%
|
|
259
|
+
default: new BigNumber(4),
|
|
273
260
|
},
|
|
274
261
|
};
|
|
275
262
|
// Reserves
|
|
276
|
-
const getStrategyDepositReserves = (
|
|
263
|
+
export const getStrategyDepositReserves = (
|
|
277
264
|
// AppContext
|
|
278
265
|
reserveMap,
|
|
279
266
|
// Strategy
|
|
280
267
|
strategyType) => {
|
|
281
|
-
const strategyTypeInfo =
|
|
268
|
+
const strategyTypeInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
282
269
|
return {
|
|
283
270
|
base: strategyTypeInfo.depositBaseCoinType
|
|
284
271
|
? reserveMap[strategyTypeInfo.depositBaseCoinType]
|
|
@@ -288,36 +275,33 @@ strategyType) => {
|
|
|
288
275
|
: undefined,
|
|
289
276
|
};
|
|
290
277
|
};
|
|
291
|
-
|
|
292
|
-
const getStrategyBorrowReserve = (
|
|
278
|
+
export const getStrategyBorrowReserve = (
|
|
293
279
|
// AppContext
|
|
294
280
|
reserveMap,
|
|
295
281
|
// Strategy
|
|
296
282
|
strategyType) => {
|
|
297
|
-
const strategyTypeInfo =
|
|
283
|
+
const strategyTypeInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
298
284
|
return reserveMap[strategyTypeInfo.borrowCoinType];
|
|
299
285
|
};
|
|
300
|
-
|
|
301
|
-
const getStrategyDefaultCurrencyReserve = (
|
|
286
|
+
export const getStrategyDefaultCurrencyReserve = (
|
|
302
287
|
// AppContext
|
|
303
288
|
reserveMap,
|
|
304
289
|
// Strategy
|
|
305
290
|
strategyType) => {
|
|
306
|
-
const defaultCurrencyCoinType =
|
|
291
|
+
const defaultCurrencyCoinType = STRATEGY_TYPE_INFO_MAP[strategyType].defaultCurrencyCoinType;
|
|
307
292
|
return reserveMap[defaultCurrencyCoinType];
|
|
308
293
|
};
|
|
309
|
-
exports.getStrategyDefaultCurrencyReserve = getStrategyDefaultCurrencyReserve;
|
|
310
294
|
// Calculations
|
|
311
|
-
const getStrategySimulatedObligation = (
|
|
295
|
+
export const getStrategySimulatedObligation = (
|
|
312
296
|
// AppContext
|
|
313
297
|
reserveMap,
|
|
314
298
|
// Strategy
|
|
315
299
|
lstMap, strategyType, deposits, _borrowedAmount) => {
|
|
316
|
-
const depositReserves =
|
|
317
|
-
const borrowReserve =
|
|
318
|
-
const defaultCurrencyReserve =
|
|
300
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
301
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
302
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
319
303
|
//
|
|
320
|
-
const borrowedAmount =
|
|
304
|
+
const borrowedAmount = BigNumber.max(new BigNumber(0), _borrowedAmount); // Can't be negative
|
|
321
305
|
const obligation = {
|
|
322
306
|
deposits: deposits.reduce((acc, deposit) => {
|
|
323
307
|
const depositReserve = reserveMap[deposit.coinType];
|
|
@@ -343,74 +327,72 @@ lstMap, strategyType, deposits, _borrowedAmount) => {
|
|
|
343
327
|
.reduce((acc, deposit) => {
|
|
344
328
|
const depositReserve = reserveMap[deposit.coinType];
|
|
345
329
|
return acc.plus(deposit.depositedAmount.times(depositReserve.price));
|
|
346
|
-
}, new
|
|
330
|
+
}, new BigNumber(0))
|
|
347
331
|
.minus(borrowedAmount.times(borrowReserve.price)),
|
|
348
|
-
weightedBorrowsUsd: new
|
|
349
|
-
maxPriceWeightedBorrowsUsd: new
|
|
332
|
+
weightedBorrowsUsd: new BigNumber(borrowedAmount.times(borrowReserve.price)).times(borrowReserve.config.borrowWeightBps.div(10000)),
|
|
333
|
+
maxPriceWeightedBorrowsUsd: new BigNumber(borrowedAmount.times(borrowReserve.maxPrice)).times(borrowReserve.config.borrowWeightBps.div(10000)),
|
|
350
334
|
minPriceBorrowLimitUsd: deposits.reduce((acc, deposit) => {
|
|
351
335
|
const depositReserve = reserveMap[deposit.coinType];
|
|
352
336
|
return acc.plus(deposit.depositedAmount
|
|
353
337
|
.times(depositReserve.minPrice)
|
|
354
338
|
.times(depositReserve.config.openLtvPct / 100));
|
|
355
|
-
}, new
|
|
339
|
+
}, new BigNumber(0)), // Not capped to $30m
|
|
356
340
|
unhealthyBorrowValueUsd: deposits.reduce((acc, deposit) => {
|
|
357
341
|
const depositReserve = reserveMap[deposit.coinType];
|
|
358
342
|
return acc.plus(deposit.depositedAmount
|
|
359
343
|
.times(depositReserve.price)
|
|
360
344
|
.times(depositReserve.config.closeLtvPct / 100));
|
|
361
|
-
}, new
|
|
345
|
+
}, new BigNumber(0)),
|
|
362
346
|
};
|
|
363
347
|
return obligation;
|
|
364
348
|
};
|
|
365
|
-
|
|
366
|
-
const getStrategyDepositedAmount = (
|
|
349
|
+
export const getStrategyDepositedAmount = (
|
|
367
350
|
// AppContext
|
|
368
351
|
reserveMap,
|
|
369
352
|
// Strategy
|
|
370
353
|
lstMap, strategyType, obligation) => {
|
|
371
354
|
var _a, _b;
|
|
372
|
-
const depositReserves =
|
|
373
|
-
const borrowReserve =
|
|
374
|
-
const defaultCurrencyReserve =
|
|
355
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
356
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
357
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
375
358
|
//
|
|
376
|
-
if (!obligation || !
|
|
377
|
-
return new
|
|
378
|
-
let resultSui = new
|
|
359
|
+
if (!obligation || !hasStrategyPosition(obligation))
|
|
360
|
+
return new BigNumber(0);
|
|
361
|
+
let resultSui = new BigNumber(0);
|
|
379
362
|
for (const deposit of obligation.deposits) {
|
|
380
|
-
if (
|
|
363
|
+
if (isSui(deposit.coinType)) {
|
|
381
364
|
resultSui = resultSui.plus(deposit.depositedAmount);
|
|
382
365
|
}
|
|
383
366
|
else if (Object.keys(lstMap).includes(deposit.coinType)) {
|
|
384
|
-
const lstToSuiExchangeRate = (_b = (_a = lstMap === null || lstMap === void 0 ? void 0 : lstMap[deposit.coinType]) === null || _a === void 0 ? void 0 : _a.lstToSuiExchangeRate) !== null && _b !== void 0 ? _b : new
|
|
367
|
+
const lstToSuiExchangeRate = (_b = (_a = lstMap === null || lstMap === void 0 ? void 0 : lstMap[deposit.coinType]) === null || _a === void 0 ? void 0 : _a.lstToSuiExchangeRate) !== null && _b !== void 0 ? _b : new BigNumber(1);
|
|
385
368
|
// const redeemFeePercent =
|
|
386
369
|
// lstMap?.[deposit.coinType]?.redeemFeePercent ?? new BigNumber(0);
|
|
387
370
|
resultSui = resultSui.plus(deposit.depositedAmount.times(lstToSuiExchangeRate));
|
|
388
371
|
}
|
|
389
372
|
else {
|
|
390
373
|
const depositReserve = reserveMap[deposit.coinType];
|
|
391
|
-
const priceSui = depositReserve.price.div(
|
|
374
|
+
const priceSui = depositReserve.price.div(getStrategySuiReserve(reserveMap).price);
|
|
392
375
|
resultSui = resultSui.plus(deposit.depositedAmount.times(priceSui));
|
|
393
376
|
}
|
|
394
377
|
}
|
|
395
|
-
const resultUsd = resultSui.times(
|
|
396
|
-
const resultDefaultCurrency = new
|
|
378
|
+
const resultUsd = resultSui.times(getStrategySuiReserve(reserveMap).price);
|
|
379
|
+
const resultDefaultCurrency = new BigNumber(resultUsd.div(defaultCurrencyReserve.price)).decimalPlaces(defaultCurrencyReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
397
380
|
return resultDefaultCurrency;
|
|
398
381
|
};
|
|
399
|
-
|
|
400
|
-
const getStrategyBorrowedAmount = (
|
|
382
|
+
export const getStrategyBorrowedAmount = (
|
|
401
383
|
// AppContext
|
|
402
384
|
reserveMap,
|
|
403
385
|
// Strategy
|
|
404
386
|
lstMap, strategyType, obligation) => {
|
|
405
|
-
const depositReserves =
|
|
406
|
-
const borrowReserve =
|
|
407
|
-
const defaultCurrencyReserve =
|
|
387
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
388
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
389
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
408
390
|
//
|
|
409
|
-
if (!obligation || !
|
|
410
|
-
return new
|
|
411
|
-
let resultSui = new
|
|
391
|
+
if (!obligation || !hasStrategyPosition(obligation))
|
|
392
|
+
return new BigNumber(0);
|
|
393
|
+
let resultSui = new BigNumber(0);
|
|
412
394
|
for (const borrow of obligation.borrows) {
|
|
413
|
-
if (
|
|
395
|
+
if (isSui(borrow.coinType)) {
|
|
414
396
|
resultSui = resultSui.plus(borrow.borrowedAmount);
|
|
415
397
|
}
|
|
416
398
|
else if (Object.keys(lstMap).includes(borrow.coinType)) {
|
|
@@ -418,138 +400,133 @@ lstMap, strategyType, obligation) => {
|
|
|
418
400
|
continue;
|
|
419
401
|
}
|
|
420
402
|
else {
|
|
421
|
-
const priceSui = borrowReserve.price.div(
|
|
403
|
+
const priceSui = borrowReserve.price.div(getStrategySuiReserve(reserveMap).price);
|
|
422
404
|
resultSui = resultSui.plus(borrow.borrowedAmount.times(priceSui));
|
|
423
405
|
}
|
|
424
406
|
}
|
|
425
|
-
const resultUsd = resultSui.times(
|
|
426
|
-
const resultDefaultCurrency = new
|
|
407
|
+
const resultUsd = resultSui.times(getStrategySuiReserve(reserveMap).price);
|
|
408
|
+
const resultDefaultCurrency = new BigNumber(resultUsd.div(defaultCurrencyReserve.price)).decimalPlaces(defaultCurrencyReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
427
409
|
return resultDefaultCurrency;
|
|
428
410
|
};
|
|
429
|
-
|
|
430
|
-
const getStrategyTvlAmount = (
|
|
411
|
+
export const getStrategyTvlAmount = (
|
|
431
412
|
// AppContext
|
|
432
413
|
reserveMap,
|
|
433
414
|
// Strategy
|
|
434
415
|
lstMap, strategyType, obligation) => {
|
|
435
|
-
if (!obligation || !
|
|
436
|
-
return new
|
|
437
|
-
return
|
|
416
|
+
if (!obligation || !hasStrategyPosition(obligation))
|
|
417
|
+
return new BigNumber(0);
|
|
418
|
+
return getStrategyDepositedAmount(reserveMap, lstMap, strategyType, obligation).minus(getStrategyBorrowedAmount(reserveMap, lstMap, strategyType, obligation));
|
|
438
419
|
};
|
|
439
|
-
|
|
440
|
-
const getStrategyExposure = (
|
|
420
|
+
export const getStrategyExposure = (
|
|
441
421
|
// AppContext
|
|
442
422
|
reserveMap,
|
|
443
423
|
// StrategyContext
|
|
444
424
|
lstMap, strategyType, obligation) => {
|
|
445
|
-
const depositReserves =
|
|
446
|
-
const borrowReserve =
|
|
447
|
-
const defaultCurrencyReserve =
|
|
425
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
426
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
427
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
448
428
|
//
|
|
449
|
-
if (!obligation || !
|
|
450
|
-
return new
|
|
451
|
-
const depositedAmountUsd =
|
|
452
|
-
const borrowedAmountUsd =
|
|
429
|
+
if (!obligation || !hasStrategyPosition(obligation))
|
|
430
|
+
return new BigNumber(0);
|
|
431
|
+
const depositedAmountUsd = getStrategyDepositedAmount(reserveMap, lstMap, strategyType, obligation).times(defaultCurrencyReserve.price);
|
|
432
|
+
const borrowedAmountUsd = getStrategyBorrowedAmount(reserveMap, lstMap, strategyType, obligation).times(defaultCurrencyReserve.price);
|
|
453
433
|
return depositedAmountUsd.eq(0)
|
|
454
|
-
? new
|
|
434
|
+
? new BigNumber(0)
|
|
455
435
|
: depositedAmountUsd.div(depositedAmountUsd.minus(borrowedAmountUsd));
|
|
456
436
|
};
|
|
457
|
-
|
|
458
|
-
const getStrategyStepMaxBorrowedAmount = (
|
|
437
|
+
export const getStrategyStepMaxBorrowedAmount = (
|
|
459
438
|
// AppContext
|
|
460
439
|
reserveMap,
|
|
461
440
|
// Strategy
|
|
462
441
|
lstMap, strategyType, deposits, borrowedAmount) => {
|
|
463
|
-
const depositReserves =
|
|
464
|
-
const borrowReserve =
|
|
465
|
-
const defaultCurrencyReserve =
|
|
442
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
443
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
444
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
466
445
|
//
|
|
467
|
-
const obligation =
|
|
446
|
+
const obligation = getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount);
|
|
468
447
|
const borrowFeePercent = borrowReserve.config.borrowFeeBps / 100;
|
|
469
448
|
// "Borrows cannot exceed borrow limit"
|
|
470
449
|
return !obligation ||
|
|
471
450
|
obligation.maxPriceWeightedBorrowsUsd.gt(obligation.minPriceBorrowLimitUsd)
|
|
472
|
-
? new
|
|
451
|
+
? new BigNumber(0)
|
|
473
452
|
: obligation.minPriceBorrowLimitUsd
|
|
474
453
|
.minus(obligation.maxPriceWeightedBorrowsUsd)
|
|
475
454
|
.div(borrowReserve.maxPrice.times(borrowReserve.config.borrowWeightBps.div(10000)))
|
|
476
455
|
.div(1 + borrowFeePercent / 100);
|
|
477
456
|
};
|
|
478
|
-
|
|
479
|
-
const getStrategyStepMaxWithdrawnAmount = (
|
|
457
|
+
export const getStrategyStepMaxWithdrawnAmount = (
|
|
480
458
|
// AppContext
|
|
481
459
|
reserveMap,
|
|
482
460
|
// Strategy
|
|
483
461
|
lstMap, strategyType, deposits, borrowedAmount, withdrawCoinType) => {
|
|
484
462
|
var _a, _b;
|
|
485
|
-
const depositReserves =
|
|
486
|
-
const borrowReserve =
|
|
487
|
-
const defaultCurrencyReserve =
|
|
463
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
464
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
465
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
488
466
|
const withdrawReserve = reserveMap[withdrawCoinType];
|
|
489
467
|
//
|
|
490
|
-
const obligation =
|
|
491
|
-
return
|
|
468
|
+
const obligation = getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount);
|
|
469
|
+
return BigNumber.min(
|
|
492
470
|
// "Withdraw is unhealthy"
|
|
493
471
|
!obligation ||
|
|
494
472
|
obligation.maxPriceWeightedBorrowsUsd.gt(obligation.minPriceBorrowLimitUsd)
|
|
495
|
-
? new
|
|
473
|
+
? new BigNumber(0)
|
|
496
474
|
: withdrawReserve.config.openLtvPct > 0
|
|
497
475
|
? obligation.minPriceBorrowLimitUsd
|
|
498
476
|
.minus(obligation.maxPriceWeightedBorrowsUsd)
|
|
499
477
|
.div(withdrawReserve.minPrice)
|
|
500
478
|
.div(withdrawReserve.config.openLtvPct / 100)
|
|
501
|
-
:
|
|
502
|
-
(_b = (_a = deposits.find((deposit) => deposit.coinType === withdrawReserve.coinType)) === null || _a === void 0 ? void 0 : _a.depositedAmount) !== null && _b !== void 0 ? _b : new
|
|
479
|
+
: MAX_U64, // Infinity
|
|
480
|
+
(_b = (_a = deposits.find((deposit) => deposit.coinType === withdrawReserve.coinType)) === null || _a === void 0 ? void 0 : _a.depositedAmount) !== null && _b !== void 0 ? _b : new BigNumber(0)).decimalPlaces(withdrawReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
503
481
|
};
|
|
504
|
-
exports.getStrategyStepMaxWithdrawnAmount = getStrategyStepMaxWithdrawnAmount;
|
|
505
482
|
// Simulate
|
|
506
|
-
const strategySimulateLoopToExposure = (
|
|
483
|
+
export const strategySimulateLoopToExposure = (
|
|
507
484
|
// AppContext
|
|
508
485
|
reserveMap,
|
|
509
486
|
// Strategy
|
|
510
487
|
lstMap, strategyType, _deposits, _borrowedAmount, _targetBorrowedAmount, _targetExposure) => {
|
|
511
488
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
512
|
-
const depositReserves =
|
|
513
|
-
const borrowReserve =
|
|
514
|
-
const defaultCurrencyReserve =
|
|
489
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
490
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
491
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
515
492
|
const loopingDepositReserve = ((_a = depositReserves.lst) !== null && _a !== void 0 ? _a : depositReserves.base); // Must have base if no LST
|
|
516
493
|
//
|
|
517
|
-
let deposits =
|
|
494
|
+
let deposits = cloneDeep(_deposits);
|
|
518
495
|
let borrowedAmount = _borrowedAmount;
|
|
519
|
-
const tvlAmountUsd =
|
|
496
|
+
const tvlAmountUsd = getStrategyTvlAmount(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount)).times(defaultCurrencyReserve.price);
|
|
520
497
|
const targetBorrowedAmount = _targetBorrowedAmount !== null && _targetBorrowedAmount !== void 0 ? _targetBorrowedAmount : tvlAmountUsd
|
|
521
498
|
.times(_targetExposure.minus(1))
|
|
522
499
|
.div(borrowReserve.price)
|
|
523
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
500
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
524
501
|
// Base+LST or LST only
|
|
525
502
|
if (loopingDepositReserve.coinType === ((_b = depositReserves.lst) === null || _b === void 0 ? void 0 : _b.coinType)) {
|
|
526
503
|
for (let i = 0; i < 30; i++) {
|
|
527
|
-
const exposure =
|
|
504
|
+
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
528
505
|
const pendingBorrowedAmount = targetBorrowedAmount.minus(borrowedAmount);
|
|
529
|
-
if (pendingBorrowedAmount.lte(
|
|
506
|
+
if (pendingBorrowedAmount.lte(STRATEGY_E))
|
|
530
507
|
break;
|
|
531
508
|
// 1) Borrow SUI
|
|
532
509
|
// 1.1) Max
|
|
533
|
-
const stepMaxBorrowedAmount =
|
|
510
|
+
const stepMaxBorrowedAmount = getStrategyStepMaxBorrowedAmount(reserveMap, lstMap, strategyType, deposits, borrowedAmount)
|
|
534
511
|
.times(0.9) // 10% buffer
|
|
535
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
536
|
-
const stepMaxDepositedAmount = new
|
|
537
|
-
.times((_d = (_c = lstMap === null || lstMap === void 0 ? void 0 : lstMap[depositReserves.lst.coinType]) === null || _c === void 0 ? void 0 : _c.suiToLstExchangeRate) !== null && _d !== void 0 ? _d : new
|
|
538
|
-
.decimalPlaces(
|
|
512
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
513
|
+
const stepMaxDepositedAmount = new BigNumber(stepMaxBorrowedAmount.minus(getStrategyLstMintFee(lstMap, loopingDepositReserve.coinType, stepMaxBorrowedAmount)))
|
|
514
|
+
.times((_d = (_c = lstMap === null || lstMap === void 0 ? void 0 : lstMap[depositReserves.lst.coinType]) === null || _c === void 0 ? void 0 : _c.suiToLstExchangeRate) !== null && _d !== void 0 ? _d : new BigNumber(1))
|
|
515
|
+
.decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
539
516
|
// 1.2) Borrow
|
|
540
|
-
const stepBorrowedAmount =
|
|
517
|
+
const stepBorrowedAmount = BigNumber.min(pendingBorrowedAmount, stepMaxBorrowedAmount).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
541
518
|
const isMaxBorrow = stepBorrowedAmount.eq(stepMaxBorrowedAmount);
|
|
542
519
|
// 1.3) Update state
|
|
543
520
|
borrowedAmount = borrowedAmount.plus(stepBorrowedAmount);
|
|
544
521
|
// 2) Deposit LST
|
|
545
522
|
// 2.1) Stake SUI for LST
|
|
546
523
|
// 2.2) Deposit
|
|
547
|
-
const stepDepositedAmount = new
|
|
548
|
-
.times((_f = (_e = lstMap === null || lstMap === void 0 ? void 0 : lstMap[depositReserves.lst.coinType]) === null || _e === void 0 ? void 0 : _e.suiToLstExchangeRate) !== null && _f !== void 0 ? _f : new
|
|
549
|
-
.decimalPlaces(
|
|
524
|
+
const stepDepositedAmount = new BigNumber(stepBorrowedAmount.minus(getStrategyLstMintFee(lstMap, loopingDepositReserve.coinType, stepBorrowedAmount)))
|
|
525
|
+
.times((_f = (_e = lstMap === null || lstMap === void 0 ? void 0 : lstMap[depositReserves.lst.coinType]) === null || _e === void 0 ? void 0 : _e.suiToLstExchangeRate) !== null && _f !== void 0 ? _f : new BigNumber(1))
|
|
526
|
+
.decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
550
527
|
const isMaxDeposit = stepDepositedAmount.eq(stepMaxDepositedAmount);
|
|
551
528
|
// 2.3) Update state
|
|
552
|
-
deposits =
|
|
529
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
553
530
|
coinType: loopingDepositReserve.coinType,
|
|
554
531
|
depositedAmount: stepDepositedAmount,
|
|
555
532
|
});
|
|
@@ -557,22 +534,22 @@ lstMap, strategyType, _deposits, _borrowedAmount, _targetBorrowedAmount, _target
|
|
|
557
534
|
}
|
|
558
535
|
// Base only
|
|
559
536
|
else if (loopingDepositReserve.coinType === ((_g = depositReserves.base) === null || _g === void 0 ? void 0 : _g.coinType)) {
|
|
560
|
-
const borrowToBaseExchangeRate = new
|
|
537
|
+
const borrowToBaseExchangeRate = new BigNumber(1); // Assume 1:1 exchange rate
|
|
561
538
|
for (let i = 0; i < 30; i++) {
|
|
562
|
-
const exposure =
|
|
539
|
+
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
563
540
|
const pendingBorrowedAmount = targetBorrowedAmount.minus(borrowedAmount);
|
|
564
|
-
if (pendingBorrowedAmount.lte(
|
|
541
|
+
if (pendingBorrowedAmount.lte(STRATEGY_E))
|
|
565
542
|
break;
|
|
566
543
|
// 1) Borrow
|
|
567
544
|
// 1.1) Max
|
|
568
|
-
const stepMaxBorrowedAmount =
|
|
545
|
+
const stepMaxBorrowedAmount = getStrategyStepMaxBorrowedAmount(reserveMap, lstMap, strategyType, deposits, borrowedAmount)
|
|
569
546
|
.times(0.9) // 10% buffer
|
|
570
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
547
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
571
548
|
const stepMaxDepositedAmount = stepMaxBorrowedAmount
|
|
572
549
|
.times(borrowToBaseExchangeRate)
|
|
573
|
-
.decimalPlaces(loopingDepositReserve.token.decimals,
|
|
550
|
+
.decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
574
551
|
// 1.2) Borrow
|
|
575
|
-
const stepBorrowedAmount =
|
|
552
|
+
const stepBorrowedAmount = BigNumber.min(pendingBorrowedAmount, stepMaxBorrowedAmount).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
576
553
|
const isMaxBorrow = stepBorrowedAmount.eq(stepMaxBorrowedAmount);
|
|
577
554
|
// 1.3) Update state
|
|
578
555
|
borrowedAmount = borrowedAmount.plus(stepBorrowedAmount);
|
|
@@ -581,10 +558,10 @@ lstMap, strategyType, _deposits, _borrowedAmount, _targetBorrowedAmount, _target
|
|
|
581
558
|
// 2.2) Deposit
|
|
582
559
|
const stepDepositedAmount = stepBorrowedAmount
|
|
583
560
|
.times(borrowToBaseExchangeRate)
|
|
584
|
-
.decimalPlaces(loopingDepositReserve.token.decimals,
|
|
561
|
+
.decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
585
562
|
const isMaxDeposit = stepDepositedAmount.eq(stepMaxDepositedAmount);
|
|
586
563
|
// 2.3) Update state
|
|
587
|
-
deposits =
|
|
564
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
588
565
|
coinType: loopingDepositReserve.coinType,
|
|
589
566
|
depositedAmount: stepDepositedAmount,
|
|
590
567
|
});
|
|
@@ -596,38 +573,37 @@ lstMap, strategyType, _deposits, _borrowedAmount, _targetBorrowedAmount, _target
|
|
|
596
573
|
return {
|
|
597
574
|
deposits,
|
|
598
575
|
borrowedAmount,
|
|
599
|
-
obligation:
|
|
576
|
+
obligation: getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount),
|
|
600
577
|
};
|
|
601
578
|
};
|
|
602
|
-
|
|
603
|
-
const strategySimulateDeposit = (
|
|
579
|
+
export const strategySimulateDeposit = (
|
|
604
580
|
// AppContext
|
|
605
581
|
reserveMap,
|
|
606
582
|
// Strategy
|
|
607
583
|
lstMap, strategyType, _deposits, _borrowedAmount, deposit) => {
|
|
608
584
|
var _a, _b, _c, _d;
|
|
609
|
-
const depositReserves =
|
|
610
|
-
const borrowReserve =
|
|
611
|
-
const defaultCurrencyReserve =
|
|
585
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
586
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
587
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
612
588
|
const depositReserve = ((_a = depositReserves.base) !== null && _a !== void 0 ? _a : depositReserves.lst); // Must have LST if no base
|
|
613
589
|
//
|
|
614
|
-
let deposits =
|
|
590
|
+
let deposits = cloneDeep(_deposits);
|
|
615
591
|
const borrowedAmount = _borrowedAmount;
|
|
616
592
|
// 1) Deposit
|
|
617
593
|
// 1.1) SUI
|
|
618
|
-
if (
|
|
594
|
+
if (isSui(deposit.coinType)) {
|
|
619
595
|
if (depositReserves.lst === undefined)
|
|
620
596
|
throw new Error("LST reserve not found");
|
|
621
|
-
const suiToLstExchangeRate = (_c = (_b = lstMap === null || lstMap === void 0 ? void 0 : lstMap[depositReserves.lst.coinType]) === null || _b === void 0 ? void 0 : _b.suiToLstExchangeRate) !== null && _c !== void 0 ? _c : new
|
|
597
|
+
const suiToLstExchangeRate = (_c = (_b = lstMap === null || lstMap === void 0 ? void 0 : lstMap[depositReserves.lst.coinType]) === null || _b === void 0 ? void 0 : _b.suiToLstExchangeRate) !== null && _c !== void 0 ? _c : new BigNumber(1);
|
|
622
598
|
const suiAmount = deposit.depositedAmount;
|
|
623
|
-
const lstAmount = new
|
|
624
|
-
.minus(
|
|
625
|
-
.times(suiToLstExchangeRate)).decimalPlaces(
|
|
599
|
+
const lstAmount = new BigNumber(suiAmount
|
|
600
|
+
.minus(getStrategyLstMintFee(lstMap, depositReserves.lst.coinType, suiAmount))
|
|
601
|
+
.times(suiToLstExchangeRate)).decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
626
602
|
// 1.1.1) Split coins
|
|
627
603
|
// 1.1.2) Stake SUI for LST
|
|
628
604
|
// 1.1.3) Deposit LST (1x exposure)
|
|
629
605
|
// 1.1.4) Update state
|
|
630
|
-
deposits =
|
|
606
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
631
607
|
coinType: depositReserves.lst.coinType,
|
|
632
608
|
depositedAmount: lstAmount,
|
|
633
609
|
});
|
|
@@ -637,37 +613,36 @@ lstMap, strategyType, _deposits, _borrowedAmount, deposit) => {
|
|
|
637
613
|
// 1.2.1) Split coins
|
|
638
614
|
// 1.2.2) Deposit LST (1x exposure)
|
|
639
615
|
// 1.2.3) Update state
|
|
640
|
-
deposits =
|
|
616
|
+
deposits = addOrInsertStrategyDeposit(deposits, deposit);
|
|
641
617
|
}
|
|
642
618
|
// 1.3) Other
|
|
643
619
|
else {
|
|
644
620
|
// 1.3.1) Split coins
|
|
645
621
|
// 1.3.2) Deposit other (1x exposure)
|
|
646
622
|
// 1.3.3) Update state
|
|
647
|
-
deposits =
|
|
623
|
+
deposits = addOrInsertStrategyDeposit(deposits, deposit);
|
|
648
624
|
}
|
|
649
625
|
return {
|
|
650
626
|
deposits,
|
|
651
627
|
borrowedAmount,
|
|
652
|
-
obligation:
|
|
628
|
+
obligation: getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount),
|
|
653
629
|
};
|
|
654
630
|
};
|
|
655
|
-
|
|
656
|
-
const strategySimulateDepositAndLoopToExposure = (
|
|
631
|
+
export const strategySimulateDepositAndLoopToExposure = (
|
|
657
632
|
// AppContext
|
|
658
633
|
reserveMap,
|
|
659
634
|
// Strategy
|
|
660
635
|
lstMap, strategyType, _deposits, _borrowedAmount, deposit, targetExposure) => {
|
|
661
|
-
const depositReserves =
|
|
662
|
-
const borrowReserve =
|
|
663
|
-
const defaultCurrencyReserve =
|
|
636
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
637
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
638
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
664
639
|
//
|
|
665
|
-
let deposits =
|
|
640
|
+
let deposits = cloneDeep(_deposits);
|
|
666
641
|
let borrowedAmount = _borrowedAmount;
|
|
667
|
-
let obligation =
|
|
642
|
+
let obligation = getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount);
|
|
668
643
|
// 1) Deposit (1x exposure)
|
|
669
644
|
// 1.1) Deposit
|
|
670
|
-
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, obligation: newObligation, } =
|
|
645
|
+
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, obligation: newObligation, } = strategySimulateDeposit(reserveMap, lstMap, strategyType, deposits, borrowedAmount, deposit);
|
|
671
646
|
// 1.2) Update state
|
|
672
647
|
deposits = newDeposits;
|
|
673
648
|
borrowedAmount = newBorrowedAmount;
|
|
@@ -675,7 +650,7 @@ lstMap, strategyType, _deposits, _borrowedAmount, deposit, targetExposure) => {
|
|
|
675
650
|
if (targetExposure.gt(1)) {
|
|
676
651
|
// 2) Loop to target exposure
|
|
677
652
|
// 2.1) Loop
|
|
678
|
-
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, obligation: newObligation2, } =
|
|
653
|
+
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, obligation: newObligation2, } = strategySimulateLoopToExposure(reserveMap, lstMap, strategyType, deposits, borrowedAmount, undefined, // Don't pass targetBorrowedAmount
|
|
679
654
|
targetExposure);
|
|
680
655
|
// 2.2) Update state
|
|
681
656
|
deposits = newDeposits2;
|
|
@@ -688,20 +663,19 @@ lstMap, strategyType, _deposits, _borrowedAmount, deposit, targetExposure) => {
|
|
|
688
663
|
obligation,
|
|
689
664
|
};
|
|
690
665
|
};
|
|
691
|
-
exports.strategySimulateDepositAndLoopToExposure = strategySimulateDepositAndLoopToExposure;
|
|
692
666
|
// Stats
|
|
693
667
|
// Stats - Global TVL
|
|
694
|
-
const fetchStrategyGlobalTvlAmountUsdMap = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
668
|
+
export const fetchStrategyGlobalTvlAmountUsdMap = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
695
669
|
try {
|
|
696
|
-
const url = `${
|
|
670
|
+
const url = `${API_URL}/strategies/tvl`;
|
|
697
671
|
const res = yield fetch(url);
|
|
698
672
|
const json = yield res.json();
|
|
699
673
|
if ((json === null || json === void 0 ? void 0 : json.statusCode) === 500)
|
|
700
674
|
throw new Error("Failed to fetch Strategies TVL");
|
|
701
|
-
const result = Object.values(
|
|
675
|
+
const result = Object.values(StrategyType).reduce((acc, strategyType) => {
|
|
702
676
|
const entry = json.strategies.find((s) => `${s.strategyType}` === strategyType);
|
|
703
677
|
const tvlUsd = entry
|
|
704
|
-
? new
|
|
678
|
+
? new BigNumber(entry.tvlUsd)
|
|
705
679
|
: null;
|
|
706
680
|
return Object.assign(Object.assign({}, acc), { [strategyType]: tvlUsd });
|
|
707
681
|
}, {});
|
|
@@ -711,136 +685,133 @@ const fetchStrategyGlobalTvlAmountUsdMap = () => __awaiter(void 0, void 0, void
|
|
|
711
685
|
console.error(err);
|
|
712
686
|
}
|
|
713
687
|
});
|
|
714
|
-
exports.fetchStrategyGlobalTvlAmountUsdMap = fetchStrategyGlobalTvlAmountUsdMap;
|
|
715
688
|
// Stats - Unclaimed rewards
|
|
716
|
-
const getStrategyUnclaimedRewardsAmount = (
|
|
689
|
+
export const getStrategyUnclaimedRewardsAmount = (
|
|
717
690
|
// AppContext
|
|
718
691
|
reserveMap, rewardPriceMap, rewardCoinMetadataMap,
|
|
719
692
|
// UserContext
|
|
720
693
|
rewardMap,
|
|
721
694
|
// Strategy
|
|
722
695
|
lstMap, strategyType, obligation) => {
|
|
723
|
-
const depositReserves =
|
|
724
|
-
const borrowReserve =
|
|
725
|
-
const defaultCurrencyReserve =
|
|
696
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
697
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
698
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
726
699
|
//
|
|
727
|
-
if (!obligation || !
|
|
728
|
-
return new
|
|
729
|
-
const rewardsMap =
|
|
700
|
+
if (!obligation || !hasStrategyPosition(obligation))
|
|
701
|
+
return new BigNumber(0);
|
|
702
|
+
const rewardsMap = getRewardsMap(obligation, rewardMap, rewardCoinMetadataMap);
|
|
730
703
|
const resultSui = Object.entries(rewardsMap).reduce((acc, [coinType, { amount }]) => {
|
|
731
704
|
var _a, _b, _c;
|
|
732
|
-
if (
|
|
705
|
+
if (isSui(coinType)) {
|
|
733
706
|
return acc.plus(amount);
|
|
734
707
|
}
|
|
735
708
|
else if (Object.keys(lstMap).includes(coinType)) {
|
|
736
|
-
const lstToSuiExchangeRate = (_b = (_a = lstMap === null || lstMap === void 0 ? void 0 : lstMap[coinType]) === null || _a === void 0 ? void 0 : _a.lstToSuiExchangeRate) !== null && _b !== void 0 ? _b : new
|
|
709
|
+
const lstToSuiExchangeRate = (_b = (_a = lstMap === null || lstMap === void 0 ? void 0 : lstMap[coinType]) === null || _a === void 0 ? void 0 : _a.lstToSuiExchangeRate) !== null && _b !== void 0 ? _b : new BigNumber(1);
|
|
737
710
|
return acc.plus(amount.times(lstToSuiExchangeRate));
|
|
738
711
|
}
|
|
739
712
|
else {
|
|
740
|
-
const price = (_c = rewardPriceMap[coinType]) !== null && _c !== void 0 ? _c : new
|
|
741
|
-
const priceSui = price.div(
|
|
713
|
+
const price = (_c = rewardPriceMap[coinType]) !== null && _c !== void 0 ? _c : new BigNumber(0);
|
|
714
|
+
const priceSui = price.div(getStrategySuiReserve(reserveMap).price);
|
|
742
715
|
return acc.plus(amount.times(priceSui));
|
|
743
716
|
}
|
|
744
|
-
}, new
|
|
745
|
-
const resultUsd = resultSui.times(
|
|
746
|
-
const resultDefaultCurrency = new
|
|
717
|
+
}, new BigNumber(0));
|
|
718
|
+
const resultUsd = resultSui.times(getStrategySuiReserve(reserveMap).price);
|
|
719
|
+
const resultDefaultCurrency = new BigNumber(resultUsd.div(defaultCurrencyReserve.price)).decimalPlaces(defaultCurrencyReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
747
720
|
return resultDefaultCurrency;
|
|
748
721
|
};
|
|
749
|
-
exports.getStrategyUnclaimedRewardsAmount = getStrategyUnclaimedRewardsAmount;
|
|
750
722
|
// Stats - History
|
|
751
723
|
// Stats - Historical TVL
|
|
752
724
|
// Stats - APR
|
|
753
|
-
const getStrategyAprPercent = (
|
|
725
|
+
export const getStrategyAprPercent = (
|
|
754
726
|
// AppContext
|
|
755
727
|
reserveMap, lstStatsMap,
|
|
756
728
|
// UserContext
|
|
757
729
|
rewardMap,
|
|
758
730
|
// Strategy
|
|
759
731
|
lstMap, strategyType, obligation, exposure) => {
|
|
760
|
-
const depositReserves =
|
|
761
|
-
const borrowReserve =
|
|
762
|
-
const defaultCurrencyReserve =
|
|
732
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
733
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
734
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
763
735
|
//
|
|
764
736
|
let _obligation;
|
|
765
|
-
if (!!obligation &&
|
|
737
|
+
if (!!obligation && hasStrategyPosition(obligation)) {
|
|
766
738
|
_obligation = obligation;
|
|
767
739
|
}
|
|
768
740
|
else {
|
|
769
741
|
if (exposure === undefined)
|
|
770
|
-
return new
|
|
771
|
-
_obligation =
|
|
742
|
+
return new BigNumber(0); // Not shown in UI
|
|
743
|
+
_obligation = strategySimulateDepositAndLoopToExposure(reserveMap, lstMap, strategyType, [], new BigNumber(0), {
|
|
772
744
|
coinType: defaultCurrencyReserve.coinType,
|
|
773
|
-
depositedAmount: new
|
|
745
|
+
depositedAmount: new BigNumber(1), // Any number will do
|
|
774
746
|
}, exposure).obligation;
|
|
775
747
|
}
|
|
776
|
-
return
|
|
748
|
+
return getNetAprPercent(_obligation, rewardMap, lstStatsMap, undefined, // sdeUsdAprPercent
|
|
749
|
+
undefined, // eThirdAprPercent
|
|
777
750
|
!obligation ||
|
|
778
|
-
!
|
|
751
|
+
!hasStrategyPosition(obligation) ||
|
|
779
752
|
obligation.deposits.some((d) => !d.userRewardManager));
|
|
780
753
|
};
|
|
781
|
-
exports.getStrategyAprPercent = getStrategyAprPercent;
|
|
782
754
|
// Stats - Health
|
|
783
|
-
const getStrategyHealthPercent = (
|
|
755
|
+
export const getStrategyHealthPercent = (
|
|
784
756
|
// AppContext
|
|
785
757
|
reserveMap,
|
|
786
758
|
// Strategy
|
|
787
759
|
lstMap, strategyType, obligation, exposure) => {
|
|
788
|
-
const depositReserves =
|
|
789
|
-
const borrowReserve =
|
|
790
|
-
const defaultCurrencyReserve =
|
|
760
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
761
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
762
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
791
763
|
//
|
|
792
764
|
let _obligation;
|
|
793
|
-
if (!!obligation &&
|
|
765
|
+
if (!!obligation && hasStrategyPosition(obligation)) {
|
|
794
766
|
_obligation = obligation;
|
|
795
767
|
}
|
|
796
768
|
else {
|
|
797
769
|
if (exposure === undefined)
|
|
798
|
-
return new
|
|
799
|
-
_obligation =
|
|
770
|
+
return new BigNumber(0); // Not shown in UI
|
|
771
|
+
_obligation = strategySimulateDepositAndLoopToExposure(reserveMap, lstMap, strategyType, [], new BigNumber(0), {
|
|
800
772
|
coinType: defaultCurrencyReserve.coinType,
|
|
801
|
-
depositedAmount: new
|
|
773
|
+
depositedAmount: new BigNumber(1), // Any number will do
|
|
802
774
|
}, exposure).obligation;
|
|
803
775
|
}
|
|
804
|
-
const weightedBorrowsUsd =
|
|
776
|
+
const weightedBorrowsUsd = getWeightedBorrowsUsd(_obligation);
|
|
805
777
|
const borrowLimitUsd = _obligation.minPriceBorrowLimitUsd.times(depositReserves.base !== undefined
|
|
806
778
|
? 0.99 // 1% buffer
|
|
807
779
|
: 1);
|
|
808
780
|
const liquidationThresholdUsd = _obligation.unhealthyBorrowValueUsd;
|
|
809
781
|
if (weightedBorrowsUsd.lte(borrowLimitUsd))
|
|
810
|
-
return new
|
|
811
|
-
return new
|
|
782
|
+
return new BigNumber(100);
|
|
783
|
+
return new BigNumber(100).minus(new BigNumber(weightedBorrowsUsd.minus(borrowLimitUsd))
|
|
812
784
|
.div(liquidationThresholdUsd.minus(borrowLimitUsd))
|
|
813
785
|
.times(100));
|
|
814
786
|
};
|
|
815
|
-
exports.getStrategyHealthPercent = getStrategyHealthPercent;
|
|
816
787
|
// Stats - Liquidation price
|
|
817
|
-
const getStrategyLiquidationPrice = (
|
|
788
|
+
export const getStrategyLiquidationPrice = (
|
|
818
789
|
// AppContext
|
|
819
790
|
reserveMap,
|
|
820
791
|
// Strategy
|
|
821
792
|
lstMap, strategyType, obligation, exposure) => {
|
|
822
793
|
var _a;
|
|
823
|
-
const depositReserves =
|
|
824
|
-
const borrowReserve =
|
|
825
|
-
const defaultCurrencyReserve =
|
|
794
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
795
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
796
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
826
797
|
//
|
|
827
798
|
if (![
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
799
|
+
StrategyType.USDC_sSUI_SUI_LOOPING,
|
|
800
|
+
StrategyType.AUSD_sSUI_SUI_LOOPING,
|
|
801
|
+
StrategyType.xBTC_sSUI_SUI_LOOPING,
|
|
802
|
+
StrategyType.suiUSDT_sSUI_SUI_LOOPING,
|
|
832
803
|
].includes(strategyType))
|
|
833
|
-
return new
|
|
804
|
+
return new BigNumber(0); // Not shown in UI
|
|
834
805
|
let _obligation;
|
|
835
|
-
if (!!obligation &&
|
|
806
|
+
if (!!obligation && hasStrategyPosition(obligation)) {
|
|
836
807
|
_obligation = obligation;
|
|
837
808
|
}
|
|
838
809
|
else {
|
|
839
810
|
if (exposure === undefined)
|
|
840
|
-
return new
|
|
841
|
-
_obligation =
|
|
811
|
+
return new BigNumber(0); // Not shown in UI
|
|
812
|
+
_obligation = strategySimulateDepositAndLoopToExposure(reserveMap, lstMap, strategyType, [], new BigNumber(0), {
|
|
842
813
|
coinType: defaultCurrencyReserve.coinType,
|
|
843
|
-
depositedAmount: new
|
|
814
|
+
depositedAmount: new BigNumber(1), // Any number will do
|
|
844
815
|
}, exposure).obligation;
|
|
845
816
|
}
|
|
846
817
|
const baseDeposit = _obligation.deposits.find((d) => d.coinType === depositReserves.base.coinType);
|
|
@@ -850,27 +821,26 @@ lstMap, strategyType, obligation, exposure) => {
|
|
|
850
821
|
const borrow = _obligation.borrows[0];
|
|
851
822
|
if (!borrow || borrow.borrowedAmount.eq(0))
|
|
852
823
|
return null;
|
|
853
|
-
const result = new
|
|
824
|
+
const result = new BigNumber(baseDeposit.depositedAmount
|
|
854
825
|
.times(depositReserves.base.price)
|
|
855
|
-
.times(+depositReserves.base.config.closeLtvPct / 100)).div(new
|
|
826
|
+
.times(+depositReserves.base.config.closeLtvPct / 100)).div(new BigNumber(borrow.borrowedAmount.times(borrowReserve.config.borrowWeightBps.div(10000))).minus(((_a = lstDeposit === null || lstDeposit === void 0 ? void 0 : lstDeposit.depositedAmount) !== null && _a !== void 0 ? _a : new BigNumber(0)).times(+depositReserves.lst.config.closeLtvPct / 100)));
|
|
856
827
|
return result;
|
|
857
828
|
};
|
|
858
|
-
exports.getStrategyLiquidationPrice = getStrategyLiquidationPrice;
|
|
859
829
|
// --------------------------------
|
|
860
|
-
const strategyLoopToExposureTx = (
|
|
830
|
+
export const strategyLoopToExposureTx = (
|
|
861
831
|
// AppContext
|
|
862
832
|
reserveMap,
|
|
863
833
|
// Strategy
|
|
864
834
|
lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, _targetBorrowedAmount, _targetExposure, // Must be defined if _targetBorrowedAmount is undefined
|
|
865
835
|
transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
866
836
|
var _a, _b, _c, _d, _e;
|
|
867
|
-
const strategyInfo =
|
|
837
|
+
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
868
838
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
869
839
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
870
840
|
: undefined;
|
|
871
|
-
const depositReserves =
|
|
872
|
-
const borrowReserve =
|
|
873
|
-
const defaultCurrencyReserve =
|
|
841
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
842
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
843
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
874
844
|
console.log(`[loopStrategyToExposure] args |`, JSON.stringify({
|
|
875
845
|
_address,
|
|
876
846
|
strategyOwnerCapId,
|
|
@@ -885,13 +855,13 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
885
855
|
}, null, 2));
|
|
886
856
|
const loopingDepositReserve = ((_a = depositReserves.lst) !== null && _a !== void 0 ? _a : depositReserves.base); // Must have base if no LST
|
|
887
857
|
//
|
|
888
|
-
let deposits =
|
|
858
|
+
let deposits = cloneDeep(_deposits);
|
|
889
859
|
let borrowedAmount = _borrowedAmount;
|
|
890
|
-
const tvlAmountUsd =
|
|
860
|
+
const tvlAmountUsd = getStrategyTvlAmount(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount)).times(defaultCurrencyReserve.price);
|
|
891
861
|
const targetBorrowedAmount = _targetBorrowedAmount !== null && _targetBorrowedAmount !== void 0 ? _targetBorrowedAmount : tvlAmountUsd
|
|
892
862
|
.times(_targetExposure.minus(1))
|
|
893
863
|
.div(borrowReserve.price)
|
|
894
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
864
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
895
865
|
console.log(`[loopStrategyToExposure] processed_args |`, JSON.stringify({
|
|
896
866
|
tvlAmountUsd: tvlAmountUsd.toFixed(20),
|
|
897
867
|
targetBorrowedAmount: targetBorrowedAmount.toFixed(20),
|
|
@@ -899,7 +869,7 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
899
869
|
// Base+LST or LST only
|
|
900
870
|
if (loopingDepositReserve.coinType === ((_b = depositReserves.lst) === null || _b === void 0 ? void 0 : _b.coinType)) {
|
|
901
871
|
for (let i = 0; i < 30; i++) {
|
|
902
|
-
const exposure =
|
|
872
|
+
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
903
873
|
const pendingBorrowedAmount = targetBorrowedAmount.minus(borrowedAmount);
|
|
904
874
|
console.log(`[loopStrategyToExposure] ${i} start |`, JSON.stringify({
|
|
905
875
|
deposits: deposits.map((d) => ({
|
|
@@ -910,30 +880,30 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
910
880
|
exposure: exposure.toFixed(20),
|
|
911
881
|
pendingBorrowedAmount: pendingBorrowedAmount.toFixed(20),
|
|
912
882
|
}, null, 2));
|
|
913
|
-
if (pendingBorrowedAmount.lte(
|
|
883
|
+
if (pendingBorrowedAmount.lte(STRATEGY_E))
|
|
914
884
|
break;
|
|
915
885
|
// 1) Borrow SUI
|
|
916
886
|
// 1.1) Max
|
|
917
|
-
const stepMaxBorrowedAmount =
|
|
887
|
+
const stepMaxBorrowedAmount = getStrategyStepMaxBorrowedAmount(reserveMap, lstMap, strategyType, deposits, borrowedAmount)
|
|
918
888
|
.times(0.9) // 10% buffer
|
|
919
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
920
|
-
const stepMaxDepositedAmount = new
|
|
889
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
890
|
+
const stepMaxDepositedAmount = new BigNumber(stepMaxBorrowedAmount.minus(getStrategyLstMintFee(lstMap, loopingDepositReserve.coinType, stepMaxBorrowedAmount)))
|
|
921
891
|
.times((_c = lst === null || lst === void 0 ? void 0 : lst.suiToLstExchangeRate) !== null && _c !== void 0 ? _c : 1)
|
|
922
|
-
.decimalPlaces(
|
|
892
|
+
.decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
923
893
|
console.log(`[loopStrategyToExposure] ${i} borrow_sui.max |`, JSON.stringify({
|
|
924
894
|
stepMaxBorrowedAmount: stepMaxBorrowedAmount.toFixed(20),
|
|
925
895
|
stepMaxDepositedAmount: stepMaxDepositedAmount.toFixed(20),
|
|
926
896
|
}, null, 2));
|
|
927
897
|
// 1.2) Borrow
|
|
928
|
-
const stepBorrowedAmount =
|
|
898
|
+
const stepBorrowedAmount = BigNumber.min(pendingBorrowedAmount, stepMaxBorrowedAmount).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
929
899
|
const isMaxBorrow = stepBorrowedAmount.eq(stepMaxBorrowedAmount);
|
|
930
900
|
console.log(`[loopStrategyToExposure] ${i} borrow_sui.borrow |`, JSON.stringify({
|
|
931
901
|
stepBorrowedAmount: stepBorrowedAmount.toFixed(20),
|
|
932
902
|
isMaxBorrow,
|
|
933
903
|
}, null, 2));
|
|
934
|
-
const [borrowedCoin] =
|
|
904
|
+
const [borrowedCoin] = strategyBorrow(borrowReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(borrowReserve.coinType), BigInt(stepBorrowedAmount
|
|
935
905
|
.times(10 ** borrowReserve.token.decimals)
|
|
936
|
-
.integerValue(
|
|
906
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
937
907
|
.toString()), transaction);
|
|
938
908
|
// 1.3) Update state
|
|
939
909
|
borrowedAmount = borrowedAmount.plus(stepBorrowedAmount);
|
|
@@ -948,17 +918,17 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
948
918
|
// 2.1) Stake SUI for LST
|
|
949
919
|
const stepLstCoin = lst.client.mint(transaction, borrowedCoin);
|
|
950
920
|
// 2.2) Deposit
|
|
951
|
-
const stepDepositedAmount = new
|
|
921
|
+
const stepDepositedAmount = new BigNumber(stepBorrowedAmount.minus(getStrategyLstMintFee(lstMap, loopingDepositReserve.coinType, stepBorrowedAmount)))
|
|
952
922
|
.times((_d = lst === null || lst === void 0 ? void 0 : lst.suiToLstExchangeRate) !== null && _d !== void 0 ? _d : 1)
|
|
953
|
-
.decimalPlaces(
|
|
923
|
+
.decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
954
924
|
const isMaxDeposit = stepDepositedAmount.eq(stepMaxDepositedAmount);
|
|
955
925
|
console.log(`[loopStrategyToExposure] ${i} deposit_lst.deposit |`, JSON.stringify({
|
|
956
926
|
stepDepositedAmount: stepDepositedAmount.toFixed(20),
|
|
957
927
|
isMaxDeposit,
|
|
958
928
|
}, null, 2));
|
|
959
|
-
|
|
929
|
+
strategyDeposit(stepLstCoin, loopingDepositReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(loopingDepositReserve.coinType), transaction);
|
|
960
930
|
// 2.3) Update state
|
|
961
|
-
deposits =
|
|
931
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
962
932
|
coinType: loopingDepositReserve.coinType,
|
|
963
933
|
depositedAmount: stepDepositedAmount,
|
|
964
934
|
});
|
|
@@ -976,18 +946,18 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
976
946
|
const exchangeRateRouters = yield cetusSdk.findRouters({
|
|
977
947
|
from: borrowReserve.coinType,
|
|
978
948
|
target: loopingDepositReserve.coinType,
|
|
979
|
-
amount: new
|
|
949
|
+
amount: new BN(new BigNumber(0.1)
|
|
980
950
|
.times(10 ** borrowReserve.token.decimals)
|
|
981
|
-
.integerValue(
|
|
951
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
982
952
|
.toString()),
|
|
983
953
|
byAmountIn: true,
|
|
984
954
|
splitCount: 0, // Use direct swap to avoid split algo
|
|
985
955
|
});
|
|
986
956
|
if (!exchangeRateRouters)
|
|
987
957
|
throw new Error("No swap quote found");
|
|
988
|
-
const borrowToBaseExchangeRate = new
|
|
958
|
+
const borrowToBaseExchangeRate = new BigNumber(new BigNumber(exchangeRateRouters.amountOut.toString()).div(10 ** loopingDepositReserve.token.decimals)).div(new BigNumber(exchangeRateRouters.amountIn.toString()).div(10 ** borrowReserve.token.decimals));
|
|
989
959
|
for (let i = 0; i < 30; i++) {
|
|
990
|
-
const exposure =
|
|
960
|
+
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
991
961
|
const pendingBorrowedAmount = targetBorrowedAmount.minus(borrowedAmount);
|
|
992
962
|
console.log(`[loopStrategyToExposure] ${i} start |`, JSON.stringify({
|
|
993
963
|
deposits: deposits.map((d) => ({
|
|
@@ -998,28 +968,28 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
998
968
|
exposure: exposure.toFixed(20),
|
|
999
969
|
pendingBorrowedAmount: pendingBorrowedAmount.toFixed(20),
|
|
1000
970
|
}, null, 2));
|
|
1001
|
-
if (pendingBorrowedAmount.lte(
|
|
971
|
+
if (pendingBorrowedAmount.lte(STRATEGY_E))
|
|
1002
972
|
break;
|
|
1003
973
|
// 1) Borrow
|
|
1004
974
|
// 1.1) Max
|
|
1005
|
-
const stepMaxBorrowedAmount =
|
|
975
|
+
const stepMaxBorrowedAmount = getStrategyStepMaxBorrowedAmount(reserveMap, lstMap, strategyType, deposits, borrowedAmount)
|
|
1006
976
|
.times(0.9) // 10% buffer
|
|
1007
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
1008
|
-
const stepMaxDepositedAmount = new
|
|
977
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
978
|
+
const stepMaxDepositedAmount = new BigNumber(stepMaxBorrowedAmount.times(borrowToBaseExchangeRate)).decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1009
979
|
console.log(`[loopStrategyToExposure] ${i} borrow.max |`, JSON.stringify({
|
|
1010
980
|
stepMaxBorrowedAmount: stepMaxBorrowedAmount.toFixed(20),
|
|
1011
981
|
stepMaxDepositedAmount: stepMaxDepositedAmount.toFixed(20),
|
|
1012
982
|
}, null, 2));
|
|
1013
983
|
// 1.2) Borrow
|
|
1014
|
-
const stepBorrowedAmount =
|
|
984
|
+
const stepBorrowedAmount = BigNumber.min(pendingBorrowedAmount, stepMaxBorrowedAmount).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1015
985
|
const isMaxBorrow = stepBorrowedAmount.eq(stepMaxBorrowedAmount);
|
|
1016
986
|
console.log(`[loopStrategyToExposure] ${i} borrow.borrow |`, JSON.stringify({
|
|
1017
987
|
stepBorrowedAmount: stepBorrowedAmount.toFixed(20),
|
|
1018
988
|
isMaxBorrow,
|
|
1019
989
|
}, null, 2));
|
|
1020
|
-
const [stepBorrowedCoin] =
|
|
990
|
+
const [stepBorrowedCoin] = strategyBorrow(borrowReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(borrowReserve.coinType), BigInt(stepBorrowedAmount
|
|
1021
991
|
.times(10 ** borrowReserve.token.decimals)
|
|
1022
|
-
.integerValue(
|
|
992
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1023
993
|
.toString()), transaction);
|
|
1024
994
|
// 1.3) Update state
|
|
1025
995
|
borrowedAmount = borrowedAmount.plus(stepBorrowedAmount);
|
|
@@ -1035,9 +1005,9 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
1035
1005
|
const routers = yield cetusSdk.findRouters({
|
|
1036
1006
|
from: borrowReserve.coinType,
|
|
1037
1007
|
target: loopingDepositReserve.coinType,
|
|
1038
|
-
amount: new
|
|
1008
|
+
amount: new BN(stepBorrowedAmount
|
|
1039
1009
|
.times(10 ** borrowReserve.token.decimals)
|
|
1040
|
-
.integerValue(
|
|
1010
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1041
1011
|
.toString()), // Estimate for loop 2 onwards (don't know exact out amount, we are not accounting for swap fees, etc)
|
|
1042
1012
|
byAmountIn: true,
|
|
1043
1013
|
splitCount: 0, // Use direct swap to avoid split algo
|
|
@@ -1047,13 +1017,13 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
1047
1017
|
const slippagePercent = 1;
|
|
1048
1018
|
let stepBaseCoin;
|
|
1049
1019
|
try {
|
|
1050
|
-
stepBaseCoin = yield cetusSdk.fixableRouterSwapV3({
|
|
1020
|
+
stepBaseCoin = (yield cetusSdk.fixableRouterSwapV3({
|
|
1051
1021
|
router: routers,
|
|
1052
1022
|
inputCoin: stepBorrowedCoin,
|
|
1053
1023
|
slippage: slippagePercent / 100,
|
|
1054
1024
|
txb: transaction,
|
|
1055
1025
|
partner: cetusPartnerId,
|
|
1056
|
-
});
|
|
1026
|
+
}));
|
|
1057
1027
|
}
|
|
1058
1028
|
catch (err) {
|
|
1059
1029
|
throw new Error("No swap quote found");
|
|
@@ -1062,21 +1032,21 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
1062
1032
|
inCoinType: borrowReserve.coinType,
|
|
1063
1033
|
outCoinType: loopingDepositReserve.coinType,
|
|
1064
1034
|
amountIn: stepBorrowedAmount.toFixed(20),
|
|
1065
|
-
amountOut: new
|
|
1035
|
+
amountOut: new BigNumber(routers.amountOut.toString())
|
|
1066
1036
|
.div(10 ** loopingDepositReserve.token.decimals)
|
|
1067
|
-
.decimalPlaces(loopingDepositReserve.token.decimals,
|
|
1037
|
+
.decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN)
|
|
1068
1038
|
.toFixed(20),
|
|
1069
1039
|
}, null, 2), routers);
|
|
1070
1040
|
// 2.2) Deposit
|
|
1071
|
-
const stepDepositedAmount = new
|
|
1041
|
+
const stepDepositedAmount = new BigNumber(new BigNumber(routers.amountOut.toString()).div(10 ** loopingDepositReserve.token.decimals)).decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1072
1042
|
const isMaxDeposit = stepDepositedAmount.eq(stepMaxDepositedAmount);
|
|
1073
1043
|
console.log(`[loopStrategyToExposure] ${i} deposit.deposit |`, JSON.stringify({
|
|
1074
1044
|
stepDepositedAmount: stepDepositedAmount.toFixed(20),
|
|
1075
1045
|
isMaxDeposit,
|
|
1076
1046
|
}, null, 2));
|
|
1077
|
-
|
|
1047
|
+
strategyDeposit(stepBaseCoin, loopingDepositReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(loopingDepositReserve.coinType), transaction);
|
|
1078
1048
|
// 2.3) Update state
|
|
1079
|
-
deposits =
|
|
1049
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
1080
1050
|
coinType: loopingDepositReserve.coinType,
|
|
1081
1051
|
depositedAmount: stepDepositedAmount,
|
|
1082
1052
|
});
|
|
@@ -1094,21 +1064,20 @@ transaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
1094
1064
|
}
|
|
1095
1065
|
return { deposits, borrowedAmount, transaction };
|
|
1096
1066
|
});
|
|
1097
|
-
|
|
1098
|
-
const strategyUnloopToExposureTx = (
|
|
1067
|
+
export const strategyUnloopToExposureTx = (
|
|
1099
1068
|
// AppContext
|
|
1100
1069
|
reserveMap,
|
|
1101
1070
|
// Strategy
|
|
1102
1071
|
lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, _targetBorrowedAmount, _targetExposure, // Must be defined if _targetBorrowedAmount is undefined
|
|
1103
1072
|
transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1104
1073
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
1105
|
-
const strategyInfo =
|
|
1074
|
+
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
1106
1075
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
1107
1076
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
1108
1077
|
: undefined;
|
|
1109
|
-
const depositReserves =
|
|
1110
|
-
const borrowReserve =
|
|
1111
|
-
const defaultCurrencyReserve =
|
|
1078
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
1079
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
1080
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
1112
1081
|
console.log(`[unloopStrategyToExposure] args |`, JSON.stringify({
|
|
1113
1082
|
_address,
|
|
1114
1083
|
strategyOwnerCapId,
|
|
@@ -1124,13 +1093,13 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1124
1093
|
const depositReserve = ((_a = depositReserves.base) !== null && _a !== void 0 ? _a : depositReserves.lst); // Must have LST if no base
|
|
1125
1094
|
const loopingDepositReserve = ((_b = depositReserves.lst) !== null && _b !== void 0 ? _b : depositReserves.base); // Must have base if no LST
|
|
1126
1095
|
//
|
|
1127
|
-
let deposits =
|
|
1096
|
+
let deposits = cloneDeep(_deposits);
|
|
1128
1097
|
let borrowedAmount = _borrowedAmount;
|
|
1129
|
-
const tvlAmountUsd =
|
|
1098
|
+
const tvlAmountUsd = getStrategyTvlAmount(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount)).times(defaultCurrencyReserve.price);
|
|
1130
1099
|
const targetBorrowedAmount = _targetBorrowedAmount !== null && _targetBorrowedAmount !== void 0 ? _targetBorrowedAmount : tvlAmountUsd
|
|
1131
1100
|
.times(_targetExposure.minus(1))
|
|
1132
1101
|
.div(borrowReserve.price)
|
|
1133
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
1102
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1134
1103
|
console.log(`[unloopStrategyToExposure] processed_args |`, JSON.stringify({
|
|
1135
1104
|
tvlAmountUsd: tvlAmountUsd.toFixed(20),
|
|
1136
1105
|
targetBorrowedAmount: targetBorrowedAmount.toFixed(20),
|
|
@@ -1143,13 +1112,13 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1143
1112
|
throw new Error("LST reserve not found");
|
|
1144
1113
|
const borrowedAmountUsd = borrowedAmount.times(borrowReserve.price);
|
|
1145
1114
|
const fullRepaymentAmount = (borrowedAmountUsd.lt(0.1)
|
|
1146
|
-
? new
|
|
1115
|
+
? new BigNumber(0.1).div(borrowReserve.price) // $0.1 in borrow coinType
|
|
1147
1116
|
: borrowedAmountUsd.lt(1)
|
|
1148
1117
|
? borrowedAmount.times(1.1) // 10% buffer
|
|
1149
1118
|
: borrowedAmountUsd.lt(10)
|
|
1150
1119
|
? borrowedAmount.times(1.01) // 1% buffer
|
|
1151
1120
|
: borrowedAmount.times(1.001)) // 0.1% buffer
|
|
1152
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
1121
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1153
1122
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingLst] |`, JSON.stringify({
|
|
1154
1123
|
borrowedAmount: borrowedAmount.toFixed(20),
|
|
1155
1124
|
fullRepaymentAmount: fullRepaymentAmount.toFixed(20),
|
|
@@ -1158,22 +1127,22 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1158
1127
|
const lstWithdrawnAmount = fullRepaymentAmount
|
|
1159
1128
|
.div(1 - +((_a = lst === null || lst === void 0 ? void 0 : lst.redeemFeePercent) !== null && _a !== void 0 ? _a : 0) / 100) // Potential rounding issue (max 1 MIST)
|
|
1160
1129
|
.div((_b = lst === null || lst === void 0 ? void 0 : lst.lstToSuiExchangeRate) !== null && _b !== void 0 ? _b : 1)
|
|
1161
|
-
.decimalPlaces(depositReserves.lst.token.decimals,
|
|
1162
|
-
if (((_d = (_c = deposits.find((d) => d.coinType === depositReserves.lst.coinType)) === null || _c === void 0 ? void 0 : _c.depositedAmount) !== null && _d !== void 0 ? _d : new
|
|
1130
|
+
.decimalPlaces(depositReserves.lst.token.decimals, BigNumber.ROUND_DOWN);
|
|
1131
|
+
if (((_d = (_c = deposits.find((d) => d.coinType === depositReserves.lst.coinType)) === null || _c === void 0 ? void 0 : _c.depositedAmount) !== null && _d !== void 0 ? _d : new BigNumber(0)).lt(lstWithdrawnAmount))
|
|
1163
1132
|
throw new Error("Not enough LST deposited");
|
|
1164
1133
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingLst] withdraw_lst |`, JSON.stringify({
|
|
1165
1134
|
lstWithdrawnAmount: lstWithdrawnAmount.toFixed(20),
|
|
1166
1135
|
}));
|
|
1167
1136
|
// 1.1) Withdraw
|
|
1168
|
-
const [withdrawnLstCoin] =
|
|
1169
|
-
.times(10 **
|
|
1170
|
-
.integerValue(
|
|
1137
|
+
const [withdrawnLstCoin] = strategyWithdraw(depositReserves.lst.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserves.lst.coinType), BigInt(new BigNumber(lstWithdrawnAmount
|
|
1138
|
+
.times(10 ** LST_DECIMALS)
|
|
1139
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1171
1140
|
.toString())
|
|
1172
1141
|
.div(depositReserves.lst.cTokenExchangeRate)
|
|
1173
|
-
.integerValue(
|
|
1142
|
+
.integerValue(BigNumber.ROUND_UP)
|
|
1174
1143
|
.toString()), transaction);
|
|
1175
1144
|
// 1.2) Update state
|
|
1176
|
-
deposits =
|
|
1145
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
1177
1146
|
coinType: depositReserves.lst.coinType,
|
|
1178
1147
|
depositedAmount: lstWithdrawnAmount.times(-1),
|
|
1179
1148
|
});
|
|
@@ -1188,12 +1157,12 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1188
1157
|
const fullRepaymentCoin = lst.client.redeem(transaction, withdrawnLstCoin);
|
|
1189
1158
|
// 3) Repay borrows
|
|
1190
1159
|
// 3.1) Repay
|
|
1191
|
-
const repaidAmount = new
|
|
1160
|
+
const repaidAmount = new BigNumber(new BigNumber(lstWithdrawnAmount.times((_e = lst === null || lst === void 0 ? void 0 : lst.lstToSuiExchangeRate) !== null && _e !== void 0 ? _e : 1)).minus(getStrategyLstRedeemFee(lstMap, depositReserves.lst.coinType, lstWithdrawnAmount))).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1192
1161
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingLst] repay_borrows.repay |`, JSON.stringify({
|
|
1193
1162
|
repaidAmount: repaidAmount.toFixed(20),
|
|
1194
1163
|
}, null, 2));
|
|
1195
1164
|
try {
|
|
1196
|
-
const txCopy =
|
|
1165
|
+
const txCopy = Transaction.from(transaction);
|
|
1197
1166
|
suilendClient.repay(obligationId, borrowReserve.coinType, fullRepaymentCoin, txCopy);
|
|
1198
1167
|
txCopy.transferObjects([fullRepaymentCoin], _address); // Transfer remaining SUI to user
|
|
1199
1168
|
yield dryRunTransaction(txCopy); // Throws error if fails
|
|
@@ -1205,7 +1174,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1205
1174
|
transaction.transferObjects([fullRepaymentCoin], _address); // Transfer SUI to user
|
|
1206
1175
|
}
|
|
1207
1176
|
// 2.3) Update state
|
|
1208
|
-
borrowedAmount =
|
|
1177
|
+
borrowedAmount = BigNumber.max(borrowedAmount.minus(repaidAmount), new BigNumber(0));
|
|
1209
1178
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingLst] repay_borrows.update_state |`, JSON.stringify({
|
|
1210
1179
|
deposits: deposits.map((d) => ({
|
|
1211
1180
|
coinType: d.coinType,
|
|
@@ -1219,14 +1188,14 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1219
1188
|
if (depositReserves.base === undefined)
|
|
1220
1189
|
throw new Error("Base reserve not found");
|
|
1221
1190
|
// 1) MAX withdraw LST
|
|
1222
|
-
const remainingLstWithdrawnAmount = ((_g = (_f = deposits.find((d) => d.coinType === depositReserves.lst.coinType)) === null || _f === void 0 ? void 0 : _f.depositedAmount) !== null && _g !== void 0 ? _g : new
|
|
1191
|
+
const remainingLstWithdrawnAmount = ((_g = (_f = deposits.find((d) => d.coinType === depositReserves.lst.coinType)) === null || _f === void 0 ? void 0 : _f.depositedAmount) !== null && _g !== void 0 ? _g : new BigNumber(0)).decimalPlaces(depositReserves.lst.token.decimals, BigNumber.ROUND_DOWN);
|
|
1223
1192
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingLst] max_withdraw_lst |`, JSON.stringify({
|
|
1224
1193
|
remainingLstWithdrawnAmount: remainingLstWithdrawnAmount.toFixed(20),
|
|
1225
1194
|
}));
|
|
1226
1195
|
// 1.1) MAX Withdraw
|
|
1227
|
-
const [withdrawnRemainingLstCoin] =
|
|
1196
|
+
const [withdrawnRemainingLstCoin] = strategyWithdraw(depositReserves.lst.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserves.lst.coinType), BigInt(MAX_U64.toString()), transaction);
|
|
1228
1197
|
// 1.2) Update state
|
|
1229
|
-
deposits =
|
|
1198
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
1230
1199
|
coinType: depositReserves.lst.coinType,
|
|
1231
1200
|
depositedAmount: remainingLstWithdrawnAmount.times(-1), // Should be 0 after this
|
|
1232
1201
|
});
|
|
@@ -1242,9 +1211,9 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1242
1211
|
const routers = yield cetusSdk.findRouters({
|
|
1243
1212
|
from: depositReserves.lst.coinType,
|
|
1244
1213
|
target: depositReserves.base.coinType,
|
|
1245
|
-
amount: new
|
|
1214
|
+
amount: new BN(remainingLstWithdrawnAmount
|
|
1246
1215
|
.times(10 ** depositReserves.lst.token.decimals)
|
|
1247
|
-
.integerValue(
|
|
1216
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1248
1217
|
.toString()),
|
|
1249
1218
|
byAmountIn: true,
|
|
1250
1219
|
});
|
|
@@ -1252,31 +1221,31 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1252
1221
|
throw new Error("No swap quote found");
|
|
1253
1222
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingLst] swap_lst_for_base.get_routers`, {
|
|
1254
1223
|
routers,
|
|
1255
|
-
amountIn: new
|
|
1224
|
+
amountIn: new BigNumber(routers.amountIn.toString())
|
|
1256
1225
|
.div(10 ** depositReserves.lst.token.decimals)
|
|
1257
|
-
.decimalPlaces(depositReserves.lst.token.decimals,
|
|
1226
|
+
.decimalPlaces(depositReserves.lst.token.decimals, BigNumber.ROUND_DOWN)
|
|
1258
1227
|
.toFixed(20),
|
|
1259
|
-
amountOut: new
|
|
1228
|
+
amountOut: new BigNumber(routers.amountOut.toString())
|
|
1260
1229
|
.div(10 ** depositReserves.base.token.decimals)
|
|
1261
|
-
.decimalPlaces(depositReserves.base.token.decimals,
|
|
1230
|
+
.decimalPlaces(depositReserves.base.token.decimals, BigNumber.ROUND_DOWN)
|
|
1262
1231
|
.toFixed(20),
|
|
1263
1232
|
});
|
|
1264
1233
|
// 2.2) Swap
|
|
1265
1234
|
let swapCoin;
|
|
1266
1235
|
try {
|
|
1267
|
-
swapCoin = yield cetusSdk.fixableRouterSwapV3({
|
|
1236
|
+
swapCoin = (yield cetusSdk.fixableRouterSwapV3({
|
|
1268
1237
|
router: routers,
|
|
1269
1238
|
inputCoin: withdrawnRemainingLstCoin,
|
|
1270
1239
|
slippage: 100 / 100,
|
|
1271
1240
|
txb: transaction,
|
|
1272
1241
|
partner: cetusPartnerId,
|
|
1273
|
-
});
|
|
1242
|
+
}));
|
|
1274
1243
|
}
|
|
1275
1244
|
catch (err) {
|
|
1276
1245
|
throw new Error("No swap quote found");
|
|
1277
1246
|
}
|
|
1278
1247
|
// 3) Deposit base
|
|
1279
|
-
|
|
1248
|
+
strategyDeposit(swapCoin, depositReserves.base.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserves.base.coinType), transaction);
|
|
1280
1249
|
}
|
|
1281
1250
|
});
|
|
1282
1251
|
const fullyRepayBorrowsUsingBase = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1285,13 +1254,13 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1285
1254
|
throw new Error("Base reserve not found");
|
|
1286
1255
|
const borrowedAmountUsd = borrowedAmount.times(borrowReserve.price);
|
|
1287
1256
|
const fullRepaymentAmount = (borrowedAmountUsd.lt(0.1)
|
|
1288
|
-
? new
|
|
1257
|
+
? new BigNumber(0.1).div(borrowReserve.price) // $0.1 in borrow coinType
|
|
1289
1258
|
: borrowedAmountUsd.lt(1)
|
|
1290
1259
|
? borrowedAmount.times(1.1) // 10% buffer
|
|
1291
1260
|
: borrowedAmountUsd.lt(10)
|
|
1292
1261
|
? borrowedAmount.times(1.01) // 1% buffer
|
|
1293
1262
|
: borrowedAmount.times(1.001)) // 0.1% buffer
|
|
1294
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
1263
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1295
1264
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingBase] |`, JSON.stringify({
|
|
1296
1265
|
borrowedAmount: borrowedAmount.toFixed(20),
|
|
1297
1266
|
fullRepaymentAmount: fullRepaymentAmount.toFixed(20),
|
|
@@ -1299,11 +1268,11 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1299
1268
|
// 1) MAX withdraw LST
|
|
1300
1269
|
if (depositReserves.lst !== undefined) {
|
|
1301
1270
|
// 1.1) MAX withdraw
|
|
1302
|
-
const [withdrawnMaxLstCoin] =
|
|
1271
|
+
const [withdrawnMaxLstCoin] = strategyWithdraw(depositReserves.lst.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserves.lst.coinType), BigInt(MAX_U64.toString()), transaction);
|
|
1303
1272
|
// 1.2) Update state
|
|
1304
|
-
deposits =
|
|
1273
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
1305
1274
|
coinType: depositReserves.lst.coinType,
|
|
1306
|
-
depositedAmount: ((_b = (_a = deposits.find((d) => d.coinType === depositReserves.lst.coinType)) === null || _a === void 0 ? void 0 : _a.depositedAmount) !== null && _b !== void 0 ? _b : new
|
|
1275
|
+
depositedAmount: ((_b = (_a = deposits.find((d) => d.coinType === depositReserves.lst.coinType)) === null || _a === void 0 ? void 0 : _a.depositedAmount) !== null && _b !== void 0 ? _b : new BigNumber(0)).times(-1),
|
|
1307
1276
|
});
|
|
1308
1277
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingBase] max_withdraw_lst.update_state |`, JSON.stringify({
|
|
1309
1278
|
deposits: deposits.map((d) => ({
|
|
@@ -1318,23 +1287,23 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1318
1287
|
transaction.transferObjects([suiCoin], _address);
|
|
1319
1288
|
}
|
|
1320
1289
|
// 2) Withdraw base
|
|
1321
|
-
const baseWithdrawnAmount = new
|
|
1290
|
+
const baseWithdrawnAmount = new BigNumber(fullRepaymentAmount.times(borrowReserve.price))
|
|
1322
1291
|
.div(depositReserves.base.price)
|
|
1323
1292
|
.times(1.03) // 3% buffer
|
|
1324
|
-
.decimalPlaces(depositReserves.base.token.decimals,
|
|
1293
|
+
.decimalPlaces(depositReserves.base.token.decimals, BigNumber.ROUND_UP);
|
|
1325
1294
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingBase] withdraw_base |`, JSON.stringify({
|
|
1326
1295
|
baseWithdrawnAmount: baseWithdrawnAmount.toFixed(20),
|
|
1327
1296
|
}, null, 2));
|
|
1328
1297
|
// 2.1) Withdraw
|
|
1329
|
-
const [withdrawnBaseCoin] =
|
|
1298
|
+
const [withdrawnBaseCoin] = strategyWithdraw(depositReserves.base.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserves.base.coinType), BigInt(new BigNumber(baseWithdrawnAmount
|
|
1330
1299
|
.times(10 ** depositReserves.base.token.decimals)
|
|
1331
|
-
.integerValue(
|
|
1300
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1332
1301
|
.toString())
|
|
1333
1302
|
.div(depositReserves.base.cTokenExchangeRate)
|
|
1334
|
-
.integerValue(
|
|
1303
|
+
.integerValue(BigNumber.ROUND_UP)
|
|
1335
1304
|
.toString()), transaction);
|
|
1336
1305
|
// 2.2) Update state
|
|
1337
|
-
deposits =
|
|
1306
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
1338
1307
|
coinType: depositReserves.base.coinType,
|
|
1339
1308
|
depositedAmount: baseWithdrawnAmount.times(-1),
|
|
1340
1309
|
});
|
|
@@ -1350,9 +1319,9 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1350
1319
|
const routers = yield cetusSdk.findRouters({
|
|
1351
1320
|
from: depositReserves.base.coinType,
|
|
1352
1321
|
target: borrowReserve.coinType,
|
|
1353
|
-
amount: new
|
|
1322
|
+
amount: new BN(baseWithdrawnAmount
|
|
1354
1323
|
.times(10 ** depositReserves.base.token.decimals)
|
|
1355
|
-
.integerValue(
|
|
1324
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1356
1325
|
.toString()),
|
|
1357
1326
|
byAmountIn: true,
|
|
1358
1327
|
});
|
|
@@ -1360,25 +1329,25 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1360
1329
|
throw new Error("No swap quote found");
|
|
1361
1330
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingBase] swap_base_for_borrows.get_routers`, {
|
|
1362
1331
|
routers,
|
|
1363
|
-
amountIn: new
|
|
1332
|
+
amountIn: new BigNumber(routers.amountIn.toString())
|
|
1364
1333
|
.div(10 ** depositReserves.base.token.decimals)
|
|
1365
|
-
.decimalPlaces(depositReserves.base.token.decimals,
|
|
1334
|
+
.decimalPlaces(depositReserves.base.token.decimals, BigNumber.ROUND_DOWN)
|
|
1366
1335
|
.toFixed(20),
|
|
1367
|
-
amountOut: new
|
|
1336
|
+
amountOut: new BigNumber(routers.amountOut.toString())
|
|
1368
1337
|
.div(10 ** borrowReserve.token.decimals)
|
|
1369
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
1338
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN)
|
|
1370
1339
|
.toFixed(20),
|
|
1371
1340
|
});
|
|
1372
1341
|
// 3.2) Swap
|
|
1373
1342
|
let swapCoin;
|
|
1374
1343
|
try {
|
|
1375
|
-
swapCoin = yield cetusSdk.fixableRouterSwapV3({
|
|
1344
|
+
swapCoin = (yield cetusSdk.fixableRouterSwapV3({
|
|
1376
1345
|
router: routers,
|
|
1377
1346
|
inputCoin: withdrawnBaseCoin,
|
|
1378
1347
|
slippage: 1 / 100,
|
|
1379
1348
|
txb: transaction,
|
|
1380
1349
|
partner: cetusPartnerId,
|
|
1381
|
-
});
|
|
1350
|
+
}));
|
|
1382
1351
|
}
|
|
1383
1352
|
catch (err) {
|
|
1384
1353
|
throw new Error("No swap quote found");
|
|
@@ -1390,7 +1359,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1390
1359
|
repaidAmount: repaidAmount.toFixed(20),
|
|
1391
1360
|
}, null, 2));
|
|
1392
1361
|
try {
|
|
1393
|
-
const txCopy =
|
|
1362
|
+
const txCopy = Transaction.from(transaction);
|
|
1394
1363
|
suilendClient.repay(obligationId, borrowReserve.coinType, swapCoin, txCopy);
|
|
1395
1364
|
txCopy.transferObjects([swapCoin], _address); // Transfer remaining to user
|
|
1396
1365
|
yield dryRunTransaction(txCopy); // Throws error if fails
|
|
@@ -1402,7 +1371,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1402
1371
|
transaction.transferObjects([swapCoin], _address); // Transfer to user
|
|
1403
1372
|
}
|
|
1404
1373
|
// 4.2) Update state
|
|
1405
|
-
borrowedAmount =
|
|
1374
|
+
borrowedAmount = BigNumber.max(borrowedAmount.minus(repaidAmount), new BigNumber(0));
|
|
1406
1375
|
console.log(`[unloopStrategyToExposure.fullyRepayBorrowsUsingBase] repay_borrows.update_state |`, JSON.stringify({
|
|
1407
1376
|
deposits: deposits.map((d) => ({
|
|
1408
1377
|
coinType: d.coinType,
|
|
@@ -1413,7 +1382,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1413
1382
|
// 5) Swap remaining to base and redeposit (not possible because coin is a mutable reference (?))
|
|
1414
1383
|
});
|
|
1415
1384
|
for (let i = 0; i < 30; i++) {
|
|
1416
|
-
const exposure =
|
|
1385
|
+
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
1417
1386
|
const pendingBorrowedAmount = borrowedAmount.minus(targetBorrowedAmount);
|
|
1418
1387
|
console.log(`[unloopStrategyToExposure] ${i} start |`, JSON.stringify({
|
|
1419
1388
|
deposits: deposits.map((d) => ({
|
|
@@ -1433,7 +1402,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1433
1402
|
if (depositReserve.coinType === ((_d = depositReserves.base) === null || _d === void 0 ? void 0 : _d.coinType)) {
|
|
1434
1403
|
const lstDeposit = deposits.find((d) => d.coinType === depositReserves.lst.coinType);
|
|
1435
1404
|
// Ran out of LST
|
|
1436
|
-
if (lstDeposit.depositedAmount.lte(
|
|
1405
|
+
if (lstDeposit.depositedAmount.lte(STRATEGY_E)) {
|
|
1437
1406
|
// 1. MAX withdraws LST (transferred to user as SUI)
|
|
1438
1407
|
// 2. Withdraws base to cover borrows
|
|
1439
1408
|
// - Leftover transferred to user as borrow coinType, e.g. SUI or suiWBTC
|
|
@@ -1441,7 +1410,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1441
1410
|
break;
|
|
1442
1411
|
}
|
|
1443
1412
|
// Borrows almost fully repaid
|
|
1444
|
-
if (pendingBorrowedAmount.lte(
|
|
1413
|
+
if (pendingBorrowedAmount.lte(STRATEGY_E)) {
|
|
1445
1414
|
try {
|
|
1446
1415
|
// 1. Withdraws LST to cover borrows
|
|
1447
1416
|
// - Leftover transferred to user as borrow coinType, e.g. SUI or suiWBTC
|
|
@@ -1461,7 +1430,7 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1461
1430
|
}
|
|
1462
1431
|
else {
|
|
1463
1432
|
// Borrows almost fully repaid
|
|
1464
|
-
if (pendingBorrowedAmount.lte(
|
|
1433
|
+
if (pendingBorrowedAmount.lte(STRATEGY_E)) {
|
|
1465
1434
|
// 1. Withdraws LST to cover borrows
|
|
1466
1435
|
// - Leftover transferred to user as borrow coinType, e.g. SUI or suiWBTC
|
|
1467
1436
|
yield fullyRepayBorrowsUsingLst(false);
|
|
@@ -1470,38 +1439,38 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1470
1439
|
}
|
|
1471
1440
|
}
|
|
1472
1441
|
else {
|
|
1473
|
-
if (pendingBorrowedAmount.lte(
|
|
1442
|
+
if (pendingBorrowedAmount.lte(STRATEGY_E))
|
|
1474
1443
|
break;
|
|
1475
1444
|
}
|
|
1476
1445
|
// 1) Withdraw LST
|
|
1477
1446
|
// 1.1) Max
|
|
1478
|
-
const stepMaxWithdrawnAmount =
|
|
1447
|
+
const stepMaxWithdrawnAmount = getStrategyStepMaxWithdrawnAmount(reserveMap, lstMap, strategyType, deposits, borrowedAmount, loopingDepositReserve.coinType)
|
|
1479
1448
|
.times(0.9) // 10% buffer
|
|
1480
|
-
.decimalPlaces(loopingDepositReserve.token.decimals,
|
|
1481
|
-
const stepMaxRepaidAmount = new
|
|
1449
|
+
.decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1450
|
+
const stepMaxRepaidAmount = new BigNumber(new BigNumber(stepMaxWithdrawnAmount.times((_e = lst === null || lst === void 0 ? void 0 : lst.lstToSuiExchangeRate) !== null && _e !== void 0 ? _e : 1)).minus(getStrategyLstRedeemFee(lstMap, loopingDepositReserve.coinType, stepMaxWithdrawnAmount))).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1482
1451
|
console.log(`[unloopStrategyToExposure] ${i} withdraw_lst.max |`, JSON.stringify({
|
|
1483
1452
|
stepMaxWithdrawnAmount: stepMaxWithdrawnAmount.toFixed(20),
|
|
1484
1453
|
stepMaxRepaidAmount: stepMaxRepaidAmount.toFixed(20),
|
|
1485
1454
|
}, null, 2));
|
|
1486
1455
|
// 1.2) Withdraw
|
|
1487
|
-
const stepWithdrawnAmount =
|
|
1456
|
+
const stepWithdrawnAmount = BigNumber.min(pendingBorrowedAmount, stepMaxRepaidAmount)
|
|
1488
1457
|
.times(1 - +((_f = lst === null || lst === void 0 ? void 0 : lst.redeemFeePercent) !== null && _f !== void 0 ? _f : 0) / 100) // Potential rounding issue (max 1 MIST)
|
|
1489
1458
|
.div((_g = lst === null || lst === void 0 ? void 0 : lst.lstToSuiExchangeRate) !== null && _g !== void 0 ? _g : 1)
|
|
1490
|
-
.decimalPlaces(loopingDepositReserve.token.decimals,
|
|
1459
|
+
.decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1491
1460
|
const isMaxWithdraw = stepWithdrawnAmount.eq(stepMaxWithdrawnAmount);
|
|
1492
1461
|
console.log(`[unloopStrategyToExposure] ${i} withdraw_lst.withdraw |`, JSON.stringify({
|
|
1493
1462
|
stepWithdrawnAmount: stepWithdrawnAmount.toFixed(20),
|
|
1494
1463
|
isMaxWithdraw,
|
|
1495
1464
|
}, null, 2));
|
|
1496
|
-
const [stepWithdrawnCoin] =
|
|
1465
|
+
const [stepWithdrawnCoin] = strategyWithdraw(loopingDepositReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(loopingDepositReserve.coinType), BigInt(new BigNumber(stepWithdrawnAmount
|
|
1497
1466
|
.times(10 ** loopingDepositReserve.token.decimals)
|
|
1498
|
-
.integerValue(
|
|
1467
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1499
1468
|
.toString())
|
|
1500
1469
|
.div(loopingDepositReserve.cTokenExchangeRate)
|
|
1501
|
-
.integerValue(
|
|
1470
|
+
.integerValue(BigNumber.ROUND_UP)
|
|
1502
1471
|
.toString()), transaction);
|
|
1503
1472
|
// 1.3) Update state
|
|
1504
|
-
deposits =
|
|
1473
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
1505
1474
|
coinType: loopingDepositReserve.coinType,
|
|
1506
1475
|
depositedAmount: stepWithdrawnAmount.times(-1),
|
|
1507
1476
|
});
|
|
@@ -1516,14 +1485,14 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1516
1485
|
const stepSuiCoin = lst.client.redeem(transaction, stepWithdrawnCoin);
|
|
1517
1486
|
// 3) Repay SUI
|
|
1518
1487
|
// 3.1) Repay
|
|
1519
|
-
const stepRepaidAmount = new
|
|
1488
|
+
const stepRepaidAmount = new BigNumber(new BigNumber(stepWithdrawnAmount.times((_h = lst === null || lst === void 0 ? void 0 : lst.lstToSuiExchangeRate) !== null && _h !== void 0 ? _h : 1)).minus(getStrategyLstRedeemFee(lstMap, loopingDepositReserve.coinType, stepWithdrawnAmount))).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1520
1489
|
const isMaxRepay = stepRepaidAmount.eq(stepMaxRepaidAmount);
|
|
1521
1490
|
console.log(`[unloopStrategyToExposure] ${i} repay_sui.repay |`, JSON.stringify({
|
|
1522
1491
|
stepRepaidAmount: stepRepaidAmount.toFixed(20),
|
|
1523
1492
|
isMaxRepay,
|
|
1524
1493
|
}, null, 2));
|
|
1525
1494
|
try {
|
|
1526
|
-
const txCopy =
|
|
1495
|
+
const txCopy = Transaction.from(transaction);
|
|
1527
1496
|
suilendClient.repay(obligationId, borrowReserve.coinType, stepSuiCoin, txCopy);
|
|
1528
1497
|
txCopy.transferObjects([stepSuiCoin], _address);
|
|
1529
1498
|
yield dryRunTransaction(txCopy); // Throws error if fails
|
|
@@ -1549,22 +1518,22 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1549
1518
|
const exchangeRateRouters = yield cetusSdk.findRouters({
|
|
1550
1519
|
from: loopingDepositReserve.coinType,
|
|
1551
1520
|
target: borrowReserve.coinType,
|
|
1552
|
-
amount: new
|
|
1521
|
+
amount: new BN(new BigNumber(0.1)
|
|
1553
1522
|
.times(10 ** loopingDepositReserve.token.decimals)
|
|
1554
|
-
.integerValue(
|
|
1523
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1555
1524
|
.toString()),
|
|
1556
1525
|
byAmountIn: true,
|
|
1557
1526
|
splitCount: 0, // Use direct swap to avoid split algo
|
|
1558
1527
|
});
|
|
1559
1528
|
if (!exchangeRateRouters)
|
|
1560
1529
|
throw new Error("No swap quote found");
|
|
1561
|
-
const baseToBorrowExchangeRate = new
|
|
1530
|
+
const baseToBorrowExchangeRate = new BigNumber(new BigNumber(exchangeRateRouters.amountOut.toString()).div(10 ** borrowReserve.token.decimals)).div(new BigNumber(exchangeRateRouters.amountIn.toString()).div(10 ** loopingDepositReserve.token.decimals));
|
|
1562
1531
|
// Target: 1x leverage
|
|
1563
1532
|
if (targetBorrowedAmount.eq(0)) {
|
|
1564
1533
|
if (pendingBorrowedAmount.lt(0))
|
|
1565
1534
|
break; // Fully repaid already
|
|
1566
1535
|
// Borrows almost fully repaid
|
|
1567
|
-
if (pendingBorrowedAmount.lte(
|
|
1536
|
+
if (pendingBorrowedAmount.lte(STRATEGY_E)) {
|
|
1568
1537
|
// 1. Withdraws base to cover borrows
|
|
1569
1538
|
// - Leftover transferred to user as borrow coinType, e.g. SUI or suiWBTC
|
|
1570
1539
|
yield fullyRepayBorrowsUsingBase();
|
|
@@ -1572,37 +1541,37 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1572
1541
|
}
|
|
1573
1542
|
}
|
|
1574
1543
|
else {
|
|
1575
|
-
if (pendingBorrowedAmount.lte(
|
|
1544
|
+
if (pendingBorrowedAmount.lte(STRATEGY_E))
|
|
1576
1545
|
break;
|
|
1577
1546
|
}
|
|
1578
1547
|
// 1) Withdraw base
|
|
1579
1548
|
// 1.1) Max
|
|
1580
|
-
const stepMaxWithdrawnAmount =
|
|
1549
|
+
const stepMaxWithdrawnAmount = getStrategyStepMaxWithdrawnAmount(reserveMap, lstMap, strategyType, deposits, borrowedAmount, loopingDepositReserve.coinType)
|
|
1581
1550
|
.times(0.9) // 10% buffer
|
|
1582
|
-
.decimalPlaces(loopingDepositReserve.token.decimals,
|
|
1583
|
-
const stepMaxRepaidAmount = new
|
|
1551
|
+
.decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1552
|
+
const stepMaxRepaidAmount = new BigNumber(stepMaxWithdrawnAmount.times(baseToBorrowExchangeRate)).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1584
1553
|
console.log(`[unloopStrategyToExposure] ${i} withdraw_base.max |`, JSON.stringify({
|
|
1585
1554
|
stepMaxWithdrawnAmount: stepMaxWithdrawnAmount.toFixed(20),
|
|
1586
1555
|
stepMaxRepaidAmount: stepMaxRepaidAmount.toFixed(20),
|
|
1587
1556
|
}, null, 2));
|
|
1588
1557
|
// 1.2) Withdraw
|
|
1589
|
-
const stepWithdrawnAmount =
|
|
1558
|
+
const stepWithdrawnAmount = BigNumber.min(pendingBorrowedAmount, stepMaxRepaidAmount)
|
|
1590
1559
|
.div(baseToBorrowExchangeRate)
|
|
1591
|
-
.decimalPlaces(loopingDepositReserve.token.decimals,
|
|
1560
|
+
.decimalPlaces(loopingDepositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1592
1561
|
const isMaxWithdraw = stepWithdrawnAmount.eq(stepMaxWithdrawnAmount);
|
|
1593
1562
|
console.log(`[unloopStrategyToExposure] ${i} withdraw_base.withdraw |`, JSON.stringify({
|
|
1594
1563
|
stepWithdrawnAmount: stepWithdrawnAmount.toFixed(20),
|
|
1595
1564
|
isMaxWithdraw,
|
|
1596
1565
|
}, null, 2));
|
|
1597
|
-
const [stepWithdrawnCoin] =
|
|
1566
|
+
const [stepWithdrawnCoin] = strategyWithdraw(loopingDepositReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(loopingDepositReserve.coinType), BigInt(new BigNumber(stepWithdrawnAmount
|
|
1598
1567
|
.times(10 ** loopingDepositReserve.token.decimals)
|
|
1599
|
-
.integerValue(
|
|
1568
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1600
1569
|
.toString())
|
|
1601
1570
|
.div(loopingDepositReserve.cTokenExchangeRate)
|
|
1602
|
-
.integerValue(
|
|
1571
|
+
.integerValue(BigNumber.ROUND_UP)
|
|
1603
1572
|
.toString()), transaction);
|
|
1604
1573
|
// 1.3) Update state
|
|
1605
|
-
deposits =
|
|
1574
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
1606
1575
|
coinType: loopingDepositReserve.coinType,
|
|
1607
1576
|
depositedAmount: stepWithdrawnAmount.times(-1),
|
|
1608
1577
|
});
|
|
@@ -1617,9 +1586,9 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1617
1586
|
const routers = yield cetusSdk.findRouters({
|
|
1618
1587
|
from: loopingDepositReserve.coinType,
|
|
1619
1588
|
target: borrowReserve.coinType,
|
|
1620
|
-
amount: new
|
|
1589
|
+
amount: new BN(stepWithdrawnAmount
|
|
1621
1590
|
.times(10 ** loopingDepositReserve.token.decimals)
|
|
1622
|
-
.integerValue(
|
|
1591
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1623
1592
|
.toString()), // Estimate for loop 2 onwards (don't know exact out amount, we are not accounting for swap fees, etc)
|
|
1624
1593
|
byAmountIn: true,
|
|
1625
1594
|
splitCount: 0, // Use direct swap to avoid split algo
|
|
@@ -1629,13 +1598,13 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1629
1598
|
const slippagePercent = 1;
|
|
1630
1599
|
let stepBorrowCoin;
|
|
1631
1600
|
try {
|
|
1632
|
-
stepBorrowCoin = yield cetusSdk.fixableRouterSwapV3({
|
|
1601
|
+
stepBorrowCoin = (yield cetusSdk.fixableRouterSwapV3({
|
|
1633
1602
|
router: routers,
|
|
1634
1603
|
inputCoin: stepWithdrawnCoin,
|
|
1635
1604
|
slippage: slippagePercent / 100,
|
|
1636
1605
|
txb: transaction,
|
|
1637
1606
|
partner: cetusPartnerId,
|
|
1638
|
-
});
|
|
1607
|
+
}));
|
|
1639
1608
|
}
|
|
1640
1609
|
catch (err) {
|
|
1641
1610
|
throw new Error("No swap quote found");
|
|
@@ -1644,21 +1613,21 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1644
1613
|
inCoinType: loopingDepositReserve.coinType,
|
|
1645
1614
|
outCoinType: borrowReserve.coinType,
|
|
1646
1615
|
amountIn: stepWithdrawnAmount.toFixed(20),
|
|
1647
|
-
amountOut: new
|
|
1616
|
+
amountOut: new BigNumber(routers.amountOut.toString())
|
|
1648
1617
|
.div(10 ** borrowReserve.token.decimals)
|
|
1649
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
1618
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN)
|
|
1650
1619
|
.toFixed(20),
|
|
1651
1620
|
}, null, 2), routers);
|
|
1652
1621
|
// 3) Repay borrows
|
|
1653
1622
|
// 3.1) Repay
|
|
1654
|
-
const stepRepaidAmount = new
|
|
1623
|
+
const stepRepaidAmount = new BigNumber(new BigNumber(routers.amountOut.toString()).div(10 ** borrowReserve.token.decimals)).decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1655
1624
|
const isMaxRepay = stepRepaidAmount.eq(stepMaxRepaidAmount);
|
|
1656
1625
|
console.log(`[unloopStrategyToExposure] ${i} repay_borrows.repay |`, JSON.stringify({
|
|
1657
1626
|
stepRepaidAmount: stepRepaidAmount.toFixed(20),
|
|
1658
1627
|
isMaxRepay,
|
|
1659
1628
|
}, null, 2));
|
|
1660
1629
|
try {
|
|
1661
|
-
const txCopy =
|
|
1630
|
+
const txCopy = Transaction.from(transaction);
|
|
1662
1631
|
suilendClient.repay(obligationId, borrowReserve.coinType, stepBorrowCoin, txCopy);
|
|
1663
1632
|
txCopy.transferObjects([stepBorrowCoin], _address);
|
|
1664
1633
|
yield dryRunTransaction(txCopy); // Throws error if fails
|
|
@@ -1685,20 +1654,19 @@ transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1685
1654
|
}
|
|
1686
1655
|
return { deposits, borrowedAmount, transaction };
|
|
1687
1656
|
});
|
|
1688
|
-
|
|
1689
|
-
const strategyDepositTx = (
|
|
1657
|
+
export const strategyDepositTx = (
|
|
1690
1658
|
// AppContext
|
|
1691
1659
|
reserveMap,
|
|
1692
1660
|
// Strategy
|
|
1693
1661
|
lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, deposit, transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1694
1662
|
var _a, _b, _c;
|
|
1695
|
-
const strategyInfo =
|
|
1663
|
+
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
1696
1664
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
1697
1665
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
1698
1666
|
: undefined;
|
|
1699
|
-
const depositReserves =
|
|
1700
|
-
const borrowReserve =
|
|
1701
|
-
const defaultCurrencyReserve =
|
|
1667
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
1668
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
1669
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
1702
1670
|
console.log(`[strategyDepositTx] args |`, JSON.stringify({
|
|
1703
1671
|
_address,
|
|
1704
1672
|
strategyOwnerCapId,
|
|
@@ -1715,30 +1683,30 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1715
1683
|
}, null, 2));
|
|
1716
1684
|
const depositReserve = ((_a = depositReserves.base) !== null && _a !== void 0 ? _a : depositReserves.lst); // Must have LST if no base
|
|
1717
1685
|
//
|
|
1718
|
-
let deposits =
|
|
1686
|
+
let deposits = cloneDeep(_deposits);
|
|
1719
1687
|
const borrowedAmount = _borrowedAmount;
|
|
1720
1688
|
// 1) Deposit
|
|
1721
1689
|
// 1.1) SUI
|
|
1722
|
-
if (
|
|
1690
|
+
if (isSui(deposit.coinType)) {
|
|
1723
1691
|
if (depositReserves.lst === undefined)
|
|
1724
1692
|
throw new Error("LST reserve not found");
|
|
1725
1693
|
const suiAmount = deposit.depositedAmount;
|
|
1726
|
-
const lstAmount = new
|
|
1727
|
-
.minus(
|
|
1728
|
-
.times((_b = lst === null || lst === void 0 ? void 0 : lst.suiToLstExchangeRate) !== null && _b !== void 0 ? _b : 1)).decimalPlaces(
|
|
1694
|
+
const lstAmount = new BigNumber(suiAmount
|
|
1695
|
+
.minus(getStrategyLstMintFee(lstMap, depositReserves.lst.coinType, suiAmount))
|
|
1696
|
+
.times((_b = lst === null || lst === void 0 ? void 0 : lst.suiToLstExchangeRate) !== null && _b !== void 0 ? _b : 1)).decimalPlaces(LST_DECIMALS, BigNumber.ROUND_DOWN);
|
|
1729
1697
|
// 1.1.1) Split coins
|
|
1730
1698
|
const suiCoin = transaction.splitCoins(transaction.gas, [
|
|
1731
1699
|
suiAmount
|
|
1732
|
-
.times(10 **
|
|
1733
|
-
.integerValue(
|
|
1700
|
+
.times(10 ** SUI_DECIMALS)
|
|
1701
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1734
1702
|
.toString(),
|
|
1735
1703
|
]);
|
|
1736
1704
|
// 1.1.2) Stake SUI for LST
|
|
1737
1705
|
const lstCoin = lst.client.mint(transaction, suiCoin);
|
|
1738
1706
|
// 1.1.3) Deposit LST (1x exposure)
|
|
1739
|
-
|
|
1707
|
+
strategyDeposit(lstCoin, depositReserves.lst.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserves.lst.coinType), transaction);
|
|
1740
1708
|
// 1.1.4) Update state
|
|
1741
|
-
deposits =
|
|
1709
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
1742
1710
|
coinType: depositReserves.lst.coinType,
|
|
1743
1711
|
depositedAmount: lstAmount,
|
|
1744
1712
|
});
|
|
@@ -1746,35 +1714,35 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1746
1714
|
// 1.2) LST
|
|
1747
1715
|
else if (deposit.coinType === ((_c = depositReserves.lst) === null || _c === void 0 ? void 0 : _c.coinType)) {
|
|
1748
1716
|
// 1.2.1) Split coins
|
|
1749
|
-
const allCoinsLst = yield
|
|
1750
|
-
const mergeCoinLst =
|
|
1717
|
+
const allCoinsLst = yield getAllCoins(suiClient, _address, depositReserves.lst.coinType);
|
|
1718
|
+
const mergeCoinLst = mergeAllCoins(depositReserves.lst.coinType, transaction, allCoinsLst);
|
|
1751
1719
|
const lstCoin = transaction.splitCoins(transaction.object(mergeCoinLst.coinObjectId), [
|
|
1752
1720
|
BigInt(deposit.depositedAmount
|
|
1753
|
-
.times(10 **
|
|
1754
|
-
.integerValue(
|
|
1721
|
+
.times(10 ** LST_DECIMALS)
|
|
1722
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1755
1723
|
.toString()),
|
|
1756
1724
|
]);
|
|
1757
1725
|
// 1.2.2) Deposit LST (1x exposure)
|
|
1758
|
-
|
|
1726
|
+
strategyDeposit(lstCoin, depositReserves.lst.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserves.lst.coinType), transaction);
|
|
1759
1727
|
// 1.2.3) Update state
|
|
1760
|
-
deposits =
|
|
1728
|
+
deposits = addOrInsertStrategyDeposit(deposits, deposit);
|
|
1761
1729
|
// 1.3) Other
|
|
1762
1730
|
}
|
|
1763
1731
|
else {
|
|
1764
1732
|
const otherReserve = reserveMap[deposit.coinType];
|
|
1765
1733
|
// 1.3.1) Split coins
|
|
1766
|
-
const allCoinsOther = yield
|
|
1767
|
-
const mergeCoinOther =
|
|
1734
|
+
const allCoinsOther = yield getAllCoins(suiClient, _address, otherReserve.coinType);
|
|
1735
|
+
const mergeCoinOther = mergeAllCoins(otherReserve.coinType, transaction, allCoinsOther);
|
|
1768
1736
|
const otherCoin = transaction.splitCoins(transaction.object(mergeCoinOther.coinObjectId), [
|
|
1769
1737
|
BigInt(deposit.depositedAmount
|
|
1770
1738
|
.times(10 ** otherReserve.token.decimals)
|
|
1771
|
-
.integerValue(
|
|
1739
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1772
1740
|
.toString()),
|
|
1773
1741
|
]);
|
|
1774
1742
|
// 1.3.2) Deposit other (1x exposure)
|
|
1775
|
-
|
|
1743
|
+
strategyDeposit(otherCoin, otherReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(otherReserve.coinType), transaction);
|
|
1776
1744
|
// 1.3.3) Update state
|
|
1777
|
-
deposits =
|
|
1745
|
+
deposits = addOrInsertStrategyDeposit(deposits, deposit);
|
|
1778
1746
|
}
|
|
1779
1747
|
console.log(`[deposit] deposit |`, JSON.stringify({
|
|
1780
1748
|
deposits: deposits.map((d) => ({
|
|
@@ -1785,19 +1753,18 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1785
1753
|
}, null, 2));
|
|
1786
1754
|
return { deposits, borrowedAmount, transaction };
|
|
1787
1755
|
});
|
|
1788
|
-
|
|
1789
|
-
const strategyDepositAndLoopToExposureTx = (
|
|
1756
|
+
export const strategyDepositAndLoopToExposureTx = (
|
|
1790
1757
|
// AppContext
|
|
1791
1758
|
reserveMap,
|
|
1792
1759
|
// Strategy
|
|
1793
1760
|
lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, deposit, targetExposure, transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1794
|
-
const strategyInfo =
|
|
1761
|
+
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
1795
1762
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
1796
1763
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
1797
1764
|
: undefined;
|
|
1798
|
-
const depositReserves =
|
|
1799
|
-
const borrowReserve =
|
|
1800
|
-
const defaultCurrencyReserve =
|
|
1765
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
1766
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
1767
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
1801
1768
|
console.log(`[depositAndLoopToExposure] args |`, JSON.stringify({
|
|
1802
1769
|
_address,
|
|
1803
1770
|
strategyOwnerCapId,
|
|
@@ -1814,11 +1781,11 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1814
1781
|
targetExposure: targetExposure.toFixed(20),
|
|
1815
1782
|
}, null, 2));
|
|
1816
1783
|
//
|
|
1817
|
-
let deposits =
|
|
1784
|
+
let deposits = cloneDeep(_deposits);
|
|
1818
1785
|
let borrowedAmount = _borrowedAmount;
|
|
1819
1786
|
// 1) Deposit (1x exposure)
|
|
1820
1787
|
// 1.1) Deposit
|
|
1821
|
-
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = yield
|
|
1788
|
+
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = yield strategyDepositTx(reserveMap, lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, deposit, transaction, dryRunTransaction);
|
|
1822
1789
|
// 1.2) Update state
|
|
1823
1790
|
deposits = newDeposits;
|
|
1824
1791
|
borrowedAmount = newBorrowedAmount;
|
|
@@ -1826,7 +1793,7 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1826
1793
|
if (targetExposure.gt(1)) {
|
|
1827
1794
|
// 2) Loop to target exposure
|
|
1828
1795
|
// 2.1) Loop
|
|
1829
|
-
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, } = yield
|
|
1796
|
+
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, } = yield strategyLoopToExposureTx(reserveMap, lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, undefined, // Don't pass targetBorrowedAmount
|
|
1830
1797
|
targetExposure, // Pass targetExposure
|
|
1831
1798
|
transaction);
|
|
1832
1799
|
// 2.2) Update state
|
|
@@ -1836,20 +1803,19 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1836
1803
|
}
|
|
1837
1804
|
return { deposits, borrowedAmount, transaction };
|
|
1838
1805
|
});
|
|
1839
|
-
|
|
1840
|
-
const strategyWithdrawTx = (
|
|
1806
|
+
export const strategyWithdrawTx = (
|
|
1841
1807
|
// AppContext
|
|
1842
1808
|
reserveMap,
|
|
1843
1809
|
// Strategy
|
|
1844
1810
|
lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, withdraw, transaction, dryRunTransaction, returnWithdrawnCoin) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1845
1811
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1846
|
-
const strategyInfo =
|
|
1812
|
+
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
1847
1813
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
1848
1814
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
1849
1815
|
: undefined;
|
|
1850
|
-
const depositReserves =
|
|
1851
|
-
const borrowReserve =
|
|
1852
|
-
const defaultCurrencyReserve =
|
|
1816
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
1817
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
1818
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
1853
1819
|
console.log(`[strategyWithdraw] args |`, JSON.stringify({
|
|
1854
1820
|
_address,
|
|
1855
1821
|
strategyOwnerCapId,
|
|
@@ -1867,27 +1833,27 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1867
1833
|
}, null, 2));
|
|
1868
1834
|
const depositReserve = ((_a = depositReserves.base) !== null && _a !== void 0 ? _a : depositReserves.lst); // Must have LST if no base
|
|
1869
1835
|
//
|
|
1870
|
-
let deposits =
|
|
1836
|
+
let deposits = cloneDeep(_deposits);
|
|
1871
1837
|
let borrowedAmount = _borrowedAmount;
|
|
1872
1838
|
const withdrawnAmount = (depositReserve.coinType === ((_b = depositReserves.base) === null || _b === void 0 ? void 0 : _b.coinType)
|
|
1873
1839
|
? withdraw.withdrawnAmount
|
|
1874
|
-
:
|
|
1840
|
+
: isSui(withdraw.coinType)
|
|
1875
1841
|
? withdraw.withdrawnAmount
|
|
1876
1842
|
.div(1 - +((_c = lst === null || lst === void 0 ? void 0 : lst.redeemFeePercent) !== null && _c !== void 0 ? _c : 0) / 100) // Potential rounding issue (max 1 MIST)
|
|
1877
1843
|
.div((_d = lst === null || lst === void 0 ? void 0 : lst.lstToSuiExchangeRate) !== null && _d !== void 0 ? _d : 1)
|
|
1878
|
-
: withdraw.withdrawnAmount).decimalPlaces(depositReserve.token.decimals,
|
|
1844
|
+
: withdraw.withdrawnAmount).decimalPlaces(depositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1879
1845
|
const withdrawnAmountUsd = withdrawnAmount
|
|
1880
1846
|
.times(depositReserve.price)
|
|
1881
1847
|
.times(depositReserve.coinType === ((_e = depositReserves.base) === null || _e === void 0 ? void 0 : _e.coinType)
|
|
1882
1848
|
? 1
|
|
1883
|
-
: new
|
|
1884
|
-
const exposure =
|
|
1885
|
-
const tvlAmountUsd =
|
|
1849
|
+
: new BigNumber((_f = lst === null || lst === void 0 ? void 0 : lst.lstToSuiExchangeRate) !== null && _f !== void 0 ? _f : 1).times(1 - +((_g = lst === null || lst === void 0 ? void 0 : lst.redeemFeePercent) !== null && _g !== void 0 ? _g : 0) / 100));
|
|
1850
|
+
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
1851
|
+
const tvlAmountUsd = getStrategyTvlAmount(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount)).times(defaultCurrencyReserve.price);
|
|
1886
1852
|
const targetTvlAmountUsd = tvlAmountUsd.minus(withdrawnAmountUsd);
|
|
1887
1853
|
const targetBorrowedAmount = targetTvlAmountUsd
|
|
1888
1854
|
.times(exposure.minus(1))
|
|
1889
1855
|
.div(borrowReserve.price)
|
|
1890
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
1856
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
1891
1857
|
console.log(`[withdraw] processed_args |`, JSON.stringify({
|
|
1892
1858
|
depositReserve_coinType: depositReserve.coinType,
|
|
1893
1859
|
withdrawnAmount: withdrawnAmount.toFixed(20),
|
|
@@ -1900,7 +1866,7 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1900
1866
|
// 1) Unloop to targetBorrowedAmount borrows
|
|
1901
1867
|
// 1.1) Unloop
|
|
1902
1868
|
if (borrowedAmount.gt(targetBorrowedAmount)) {
|
|
1903
|
-
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = yield
|
|
1869
|
+
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = yield strategyUnloopToExposureTx(reserveMap, lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, targetBorrowedAmount, // Pass targetBorrowedAmount
|
|
1904
1870
|
undefined, // Don't pass targetExposure
|
|
1905
1871
|
transaction, dryRunTransaction);
|
|
1906
1872
|
// 1.2) Update state
|
|
@@ -1918,20 +1884,20 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1918
1884
|
}
|
|
1919
1885
|
// 2) Withdraw base or LST
|
|
1920
1886
|
// 2.1) Withdraw
|
|
1921
|
-
const [withdrawnCoin] =
|
|
1887
|
+
const [withdrawnCoin] = strategyWithdraw(depositReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserve.coinType), BigInt(new BigNumber(withdrawnAmount
|
|
1922
1888
|
.times(10 ** depositReserve.token.decimals)
|
|
1923
|
-
.integerValue(
|
|
1889
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
1924
1890
|
.toString())
|
|
1925
1891
|
.div(depositReserve.cTokenExchangeRate)
|
|
1926
|
-
.integerValue(
|
|
1892
|
+
.integerValue(BigNumber.ROUND_UP)
|
|
1927
1893
|
.toString()), transaction);
|
|
1928
1894
|
// 2.2) Update state
|
|
1929
|
-
deposits =
|
|
1895
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
1930
1896
|
coinType: depositReserve.coinType,
|
|
1931
1897
|
depositedAmount: withdrawnAmount.times(-1),
|
|
1932
1898
|
});
|
|
1933
|
-
const newExposure =
|
|
1934
|
-
const newTvlAmountUsd =
|
|
1899
|
+
const newExposure = getStrategyExposure(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount));
|
|
1900
|
+
const newTvlAmountUsd = getStrategyTvlAmount(reserveMap, lstMap, strategyType, getStrategySimulatedObligation(reserveMap, lstMap, strategyType, deposits, borrowedAmount)).times(defaultCurrencyReserve.price);
|
|
1935
1901
|
console.log(`[withdraw] withdraw.update_state |`, JSON.stringify({
|
|
1936
1902
|
deposits: deposits.map((d) => ({
|
|
1937
1903
|
coinType: d.coinType,
|
|
@@ -1953,7 +1919,7 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1953
1919
|
transaction.transferObjects([withdrawnCoin], _address);
|
|
1954
1920
|
}
|
|
1955
1921
|
else {
|
|
1956
|
-
if (
|
|
1922
|
+
if (isSui(withdraw.coinType)) {
|
|
1957
1923
|
// 3.1) Unstake LST for SUI
|
|
1958
1924
|
const suiWithdrawnCoin = lst.client.redeem(transaction, withdrawnCoin);
|
|
1959
1925
|
// 3.2) Transfer SUI to user
|
|
@@ -1967,20 +1933,19 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1967
1933
|
}
|
|
1968
1934
|
return { deposits, borrowedAmount, transaction };
|
|
1969
1935
|
});
|
|
1970
|
-
|
|
1971
|
-
const strategyMaxWithdrawTx = (
|
|
1936
|
+
export const strategyMaxWithdrawTx = (
|
|
1972
1937
|
// AppContext
|
|
1973
1938
|
reserveMap, rewardPriceMap, rewardsMap,
|
|
1974
1939
|
// Strategy
|
|
1975
1940
|
lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, withdrawCoinType, transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1976
1941
|
var _a, _b;
|
|
1977
|
-
const strategyInfo =
|
|
1942
|
+
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
1978
1943
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
1979
1944
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
1980
1945
|
: undefined;
|
|
1981
|
-
const depositReserves =
|
|
1982
|
-
const borrowReserve =
|
|
1983
|
-
const defaultCurrencyReserve =
|
|
1946
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
1947
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
1948
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
1984
1949
|
const hasClaimableRewards = Object.values(rewardsMap).some(({ amount }) => amount.gt(0));
|
|
1985
1950
|
console.log(`[strategyMaxWithdraw] args |`, JSON.stringify({
|
|
1986
1951
|
_address,
|
|
@@ -1995,13 +1960,13 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
1995
1960
|
}, null, 2));
|
|
1996
1961
|
const depositReserve = ((_a = depositReserves.base) !== null && _a !== void 0 ? _a : depositReserves.lst); // Must have LST if no base
|
|
1997
1962
|
//
|
|
1998
|
-
let deposits =
|
|
1963
|
+
let deposits = cloneDeep(_deposits);
|
|
1999
1964
|
let borrowedAmount = _borrowedAmount;
|
|
2000
1965
|
// 1) Unloop to 1x (base+LST: no LST and no borrows, LST: no borrows)
|
|
2001
1966
|
if (borrowedAmount.gt(0)) {
|
|
2002
1967
|
// 1.1) Unloop
|
|
2003
|
-
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = yield
|
|
2004
|
-
new
|
|
1968
|
+
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = yield strategyUnloopToExposureTx(reserveMap, lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, undefined, // Don't pass targetBorrowedAmount
|
|
1969
|
+
new BigNumber(1), // Pass targetExposure
|
|
2005
1970
|
transaction, dryRunTransaction);
|
|
2006
1971
|
// 1.2) Update state
|
|
2007
1972
|
deposits = newDeposits;
|
|
@@ -2016,7 +1981,7 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2016
1981
|
}, null, 2));
|
|
2017
1982
|
}
|
|
2018
1983
|
// 2) MAX withdraw base or LST
|
|
2019
|
-
const [withdrawnCoin] =
|
|
1984
|
+
const [withdrawnCoin] = strategyWithdraw(depositReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserve.coinType), BigInt(MAX_U64.toString()), transaction);
|
|
2020
1985
|
// 2.2) Update state
|
|
2021
1986
|
deposits = [];
|
|
2022
1987
|
console.log(`[strategyMaxWithdraw] max_withdraw.update_state |`, JSON.stringify({
|
|
@@ -2032,7 +1997,7 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2032
1997
|
transaction.transferObjects([withdrawnCoin], _address);
|
|
2033
1998
|
}
|
|
2034
1999
|
else {
|
|
2035
|
-
if (
|
|
2000
|
+
if (isSui(withdrawCoinType)) {
|
|
2036
2001
|
// 3.1) Unstake LST for SUI
|
|
2037
2002
|
const suiWithdrawnCoin = lst.client.redeem(transaction, withdrawnCoin);
|
|
2038
2003
|
// 3.2) Transfer SUI to user
|
|
@@ -2046,8 +2011,8 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2046
2011
|
// 4) Claim rewards, swap for withdrawCoinType, and transfer to user
|
|
2047
2012
|
if (hasClaimableRewards) {
|
|
2048
2013
|
try {
|
|
2049
|
-
const txCopy =
|
|
2050
|
-
yield
|
|
2014
|
+
const txCopy = Transaction.from(transaction);
|
|
2015
|
+
yield strategyClaimRewardsAndSwapForCoinType(_address, cetusSdk, cetusPartnerId, rewardsMap, rewardPriceMap, reserveMap[withdrawCoinType], strategyOwnerCapId, false, // isDepositing (false = transfer to user)
|
|
2051
2016
|
txCopy);
|
|
2052
2017
|
yield dryRunTransaction(txCopy); // Throws error if fails
|
|
2053
2018
|
transaction = txCopy;
|
|
@@ -2059,21 +2024,20 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2059
2024
|
}
|
|
2060
2025
|
return { deposits, borrowedAmount, transaction };
|
|
2061
2026
|
});
|
|
2062
|
-
|
|
2063
|
-
const strategyAdjustRepayTx = (
|
|
2027
|
+
export const strategyAdjustRepayTx = (
|
|
2064
2028
|
// AppContext
|
|
2065
2029
|
reserveMap,
|
|
2066
2030
|
// Strategy
|
|
2067
2031
|
lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, flashLoanBorrowedAmount, transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
2068
2032
|
var _a, _b, _c, _d;
|
|
2069
|
-
const strategyInfo =
|
|
2033
|
+
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
2070
2034
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
2071
2035
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
2072
2036
|
: undefined;
|
|
2073
|
-
const depositReserves =
|
|
2074
|
-
const borrowReserve =
|
|
2075
|
-
const defaultCurrencyReserve =
|
|
2076
|
-
const adjustRepayExposure =
|
|
2037
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
2038
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
2039
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
2040
|
+
const adjustRepayExposure = STRATEGY_TYPE_EXPOSURE_MAP[strategyType].min;
|
|
2077
2041
|
console.log(`[strategyAdjustRepay] args |`, JSON.stringify({
|
|
2078
2042
|
_address,
|
|
2079
2043
|
strategyOwnerCapId,
|
|
@@ -2089,30 +2053,30 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2089
2053
|
if (!depositReserves.base)
|
|
2090
2054
|
throw new Error("Base reserve not found");
|
|
2091
2055
|
//
|
|
2092
|
-
let deposits =
|
|
2056
|
+
let deposits = cloneDeep(_deposits);
|
|
2093
2057
|
let borrowedAmount = _borrowedAmount;
|
|
2094
2058
|
// 1) Flash loan base
|
|
2095
|
-
const flashLoanObj =
|
|
2059
|
+
const flashLoanObj = STRATEGY_TYPE_FLASH_LOAN_OBJ_MAP[strategyType];
|
|
2096
2060
|
let borrowedBalanceA, borrowedBalanceB, receipt;
|
|
2097
2061
|
if (flashLoanObj.provider === StrategyFlashLoanProvider.MMT) {
|
|
2098
2062
|
[borrowedBalanceA, borrowedBalanceB, receipt] = transaction.moveCall({
|
|
2099
|
-
target: `${
|
|
2063
|
+
target: `${MMT_CONTRACT_PACKAGE_ID}::trade::flash_loan`,
|
|
2100
2064
|
typeArguments: [flashLoanObj.coinTypeA, flashLoanObj.coinTypeB],
|
|
2101
2065
|
arguments: [
|
|
2102
2066
|
transaction.object(flashLoanObj.poolId),
|
|
2103
2067
|
transaction.pure.u64(flashLoanObj.borrowA
|
|
2104
2068
|
? flashLoanBorrowedAmount
|
|
2105
2069
|
.times(10 ** depositReserves.base.token.decimals)
|
|
2106
|
-
.integerValue(
|
|
2070
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
2107
2071
|
.toString()
|
|
2108
2072
|
: 0),
|
|
2109
2073
|
transaction.pure.u64(flashLoanObj.borrowA
|
|
2110
2074
|
? 0
|
|
2111
2075
|
: flashLoanBorrowedAmount
|
|
2112
2076
|
.times(10 ** depositReserves.base.token.decimals)
|
|
2113
|
-
.integerValue(
|
|
2077
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
2114
2078
|
.toString()),
|
|
2115
|
-
transaction.object(
|
|
2079
|
+
transaction.object(MMT_VERSION_OBJECT_ID),
|
|
2116
2080
|
],
|
|
2117
2081
|
});
|
|
2118
2082
|
}
|
|
@@ -2131,9 +2095,9 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2131
2095
|
const routers = yield cetusSdk.findRouters({
|
|
2132
2096
|
from: depositReserves.base.coinType,
|
|
2133
2097
|
target: borrowReserve.coinType,
|
|
2134
|
-
amount: new
|
|
2098
|
+
amount: new BN(flashLoanBorrowedAmount
|
|
2135
2099
|
.times(10 ** depositReserves.base.token.decimals)
|
|
2136
|
-
.integerValue(
|
|
2100
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
2137
2101
|
.toString()),
|
|
2138
2102
|
byAmountIn: true,
|
|
2139
2103
|
});
|
|
@@ -2141,25 +2105,25 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2141
2105
|
throw new Error("No swap quote found");
|
|
2142
2106
|
console.log(`[strategyAdjustRepay] swap_flash_loan_base_for_borrows.get_routers`, {
|
|
2143
2107
|
routers,
|
|
2144
|
-
amountIn: new
|
|
2108
|
+
amountIn: new BigNumber(routers.amountIn.toString())
|
|
2145
2109
|
.div(10 ** depositReserves.base.token.decimals)
|
|
2146
|
-
.decimalPlaces(depositReserves.base.token.decimals,
|
|
2110
|
+
.decimalPlaces(depositReserves.base.token.decimals, BigNumber.ROUND_DOWN)
|
|
2147
2111
|
.toFixed(20),
|
|
2148
|
-
amountOut: new
|
|
2112
|
+
amountOut: new BigNumber(routers.amountOut.toString())
|
|
2149
2113
|
.div(10 ** borrowReserve.token.decimals)
|
|
2150
|
-
.decimalPlaces(borrowReserve.token.decimals,
|
|
2114
|
+
.decimalPlaces(borrowReserve.token.decimals, BigNumber.ROUND_DOWN)
|
|
2151
2115
|
.toFixed(20),
|
|
2152
2116
|
});
|
|
2153
2117
|
// 2.2) Swap
|
|
2154
2118
|
let swapCoin;
|
|
2155
2119
|
try {
|
|
2156
|
-
swapCoin = yield cetusSdk.fixableRouterSwapV3({
|
|
2120
|
+
swapCoin = (yield cetusSdk.fixableRouterSwapV3({
|
|
2157
2121
|
router: routers,
|
|
2158
2122
|
inputCoin: flashLoanBorrowedCoin,
|
|
2159
2123
|
slippage: 1 / 100,
|
|
2160
2124
|
txb: transaction,
|
|
2161
2125
|
partner: cetusPartnerId,
|
|
2162
|
-
});
|
|
2126
|
+
}));
|
|
2163
2127
|
}
|
|
2164
2128
|
catch (err) {
|
|
2165
2129
|
throw new Error("No swap quote found");
|
|
@@ -2169,7 +2133,7 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2169
2133
|
suilendClient.repay(obligationId, borrowReserve.coinType, swapCoin, transaction);
|
|
2170
2134
|
transaction.transferObjects([swapCoin], _address); // Transfer remaining to user
|
|
2171
2135
|
// 3.2) Update state
|
|
2172
|
-
borrowedAmount = new
|
|
2136
|
+
borrowedAmount = new BigNumber(0);
|
|
2173
2137
|
console.log(`[strategyAdjustRepay] repay_borrows.update_state |`, JSON.stringify({
|
|
2174
2138
|
deposits: deposits.map((d) => ({
|
|
2175
2139
|
coinType: d.coinType,
|
|
@@ -2180,19 +2144,19 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2180
2144
|
// 4) Swap remaining to base and redeposit (not possible because coin is a mutable reference (?))
|
|
2181
2145
|
// 5) Repay flash loan + fee
|
|
2182
2146
|
const receiptDebts = transaction.moveCall({
|
|
2183
|
-
target: `${
|
|
2147
|
+
target: `${MMT_CONTRACT_PACKAGE_ID}::trade::flash_receipt_debts`,
|
|
2184
2148
|
typeArguments: [],
|
|
2185
2149
|
arguments: [receipt],
|
|
2186
2150
|
});
|
|
2187
2151
|
const dryRunResults = yield dryRunTransaction(transaction);
|
|
2188
|
-
const flashLoanRepayAmount = new
|
|
2152
|
+
const flashLoanRepayAmount = new BigNumber(bcs
|
|
2189
2153
|
.u64()
|
|
2190
2154
|
.parse(new Uint8Array((_d = (_c = (_b = (_a = dryRunResults.results) === null || _a === void 0 ? void 0 : _a.find((r, index) => index === receiptDebts.Result)) === null || _b === void 0 ? void 0 : _b.returnValues) === null || _c === void 0 ? void 0 : _c[flashLoanObj.borrowA ? 0 : 1][0]) !== null && _d !== void 0 ? _d : [0])))
|
|
2191
2155
|
.div(10 ** depositReserves.base.token.decimals)
|
|
2192
|
-
.decimalPlaces(depositReserves.base.token.decimals,
|
|
2156
|
+
.decimalPlaces(depositReserves.base.token.decimals, BigNumber.ROUND_UP);
|
|
2193
2157
|
// 5.1) Withdraw base + fee
|
|
2194
2158
|
const withdrawnAmount = flashLoanRepayAmount;
|
|
2195
|
-
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, withdrawnCoin, } = yield
|
|
2159
|
+
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, withdrawnCoin, } = yield strategyWithdrawTx(reserveMap, lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, {
|
|
2196
2160
|
coinType: depositReserves.base.coinType,
|
|
2197
2161
|
withdrawnAmount,
|
|
2198
2162
|
}, transaction, dryRunTransaction, true);
|
|
@@ -2213,14 +2177,14 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2213
2177
|
});
|
|
2214
2178
|
if (flashLoanObj.provider === StrategyFlashLoanProvider.MMT) {
|
|
2215
2179
|
transaction.moveCall({
|
|
2216
|
-
target: `${
|
|
2180
|
+
target: `${MMT_CONTRACT_PACKAGE_ID}::trade::repay_flash_loan`,
|
|
2217
2181
|
typeArguments: [flashLoanObj.coinTypeA, flashLoanObj.coinTypeB],
|
|
2218
2182
|
arguments: [
|
|
2219
2183
|
transaction.object(flashLoanObj.poolId),
|
|
2220
2184
|
receipt,
|
|
2221
2185
|
flashLoanObj.borrowA ? flashLoanRepayBalance : borrowedBalanceA,
|
|
2222
2186
|
flashLoanObj.borrowA ? borrowedBalanceB : flashLoanRepayBalance,
|
|
2223
|
-
transaction.object(
|
|
2187
|
+
transaction.object(MMT_VERSION_OBJECT_ID),
|
|
2224
2188
|
],
|
|
2225
2189
|
});
|
|
2226
2190
|
}
|
|
@@ -2229,21 +2193,20 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2229
2193
|
}
|
|
2230
2194
|
return { deposits, borrowedAmount, transaction };
|
|
2231
2195
|
});
|
|
2232
|
-
|
|
2233
|
-
const strategyDepositAdjustWithdrawTx = (
|
|
2196
|
+
export const strategyDepositAdjustWithdrawTx = (
|
|
2234
2197
|
// AppContext
|
|
2235
2198
|
reserveMap,
|
|
2236
2199
|
// Strategy
|
|
2237
2200
|
lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, _deposits, _borrowedAmount, flashLoanBorrowedAmount, transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
2238
2201
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
2239
|
-
const strategyInfo =
|
|
2202
|
+
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
2240
2203
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
2241
2204
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
2242
2205
|
: undefined;
|
|
2243
|
-
const depositReserves =
|
|
2244
|
-
const borrowReserve =
|
|
2245
|
-
const defaultCurrencyReserve =
|
|
2246
|
-
const depositAdjustWithdrawExposure =
|
|
2206
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
2207
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
2208
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
2209
|
+
const depositAdjustWithdrawExposure = STRATEGY_TYPE_EXPOSURE_MAP[strategyType].max;
|
|
2247
2210
|
console.log(`[strategyDepositAdjustWithdraw] args |`, JSON.stringify({
|
|
2248
2211
|
_address,
|
|
2249
2212
|
strategyOwnerCapId,
|
|
@@ -2257,20 +2220,20 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2257
2220
|
}, null, 2));
|
|
2258
2221
|
const depositReserve = ((_a = depositReserves.base) !== null && _a !== void 0 ? _a : depositReserves.lst); // Must have LST if no base
|
|
2259
2222
|
//
|
|
2260
|
-
let deposits =
|
|
2223
|
+
let deposits = cloneDeep(_deposits);
|
|
2261
2224
|
let borrowedAmount = _borrowedAmount;
|
|
2262
2225
|
// 1) Flash loan base/LST
|
|
2263
|
-
const flashLoanObj =
|
|
2226
|
+
const flashLoanObj = STRATEGY_TYPE_FLASH_LOAN_OBJ_MAP[strategyType];
|
|
2264
2227
|
if (depositReserve.coinType === ((_b = depositReserves.lst) === null || _b === void 0 ? void 0 : _b.coinType)) {
|
|
2265
2228
|
// TODO: Account for LST mint fees
|
|
2266
2229
|
flashLoanBorrowedAmount = flashLoanBorrowedAmount
|
|
2267
2230
|
.times((_c = lst === null || lst === void 0 ? void 0 : lst.lstToSuiExchangeRate) !== null && _c !== void 0 ? _c : 1)
|
|
2268
|
-
.decimalPlaces(
|
|
2231
|
+
.decimalPlaces(SUI_DECIMALS, BigNumber.ROUND_UP);
|
|
2269
2232
|
}
|
|
2270
2233
|
let borrowedBalanceA, borrowedBalanceB, receipt;
|
|
2271
2234
|
if (flashLoanObj.provider === StrategyFlashLoanProvider.MMT) {
|
|
2272
2235
|
[borrowedBalanceA, borrowedBalanceB, receipt] = transaction.moveCall({
|
|
2273
|
-
target: `${
|
|
2236
|
+
target: `${MMT_CONTRACT_PACKAGE_ID}::trade::flash_loan`,
|
|
2274
2237
|
typeArguments: [flashLoanObj.coinTypeA, flashLoanObj.coinTypeB],
|
|
2275
2238
|
arguments: [
|
|
2276
2239
|
transaction.object(flashLoanObj.poolId),
|
|
@@ -2278,9 +2241,9 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2278
2241
|
? flashLoanBorrowedAmount
|
|
2279
2242
|
.times(10 **
|
|
2280
2243
|
(depositReserve.coinType === ((_d = depositReserves.lst) === null || _d === void 0 ? void 0 : _d.coinType)
|
|
2281
|
-
?
|
|
2244
|
+
? SUI_DECIMALS
|
|
2282
2245
|
: depositReserve.token.decimals))
|
|
2283
|
-
.integerValue(
|
|
2246
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
2284
2247
|
.toString()
|
|
2285
2248
|
: 0),
|
|
2286
2249
|
transaction.pure.u64(flashLoanObj.borrowA
|
|
@@ -2288,11 +2251,11 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2288
2251
|
: flashLoanBorrowedAmount
|
|
2289
2252
|
.times(10 **
|
|
2290
2253
|
(depositReserve.coinType === ((_e = depositReserves.lst) === null || _e === void 0 ? void 0 : _e.coinType)
|
|
2291
|
-
?
|
|
2254
|
+
? SUI_DECIMALS
|
|
2292
2255
|
: depositReserve.token.decimals))
|
|
2293
|
-
.integerValue(
|
|
2256
|
+
.integerValue(BigNumber.ROUND_DOWN)
|
|
2294
2257
|
.toString()),
|
|
2295
|
-
transaction.object(
|
|
2258
|
+
transaction.object(MMT_VERSION_OBJECT_ID),
|
|
2296
2259
|
],
|
|
2297
2260
|
});
|
|
2298
2261
|
}
|
|
@@ -2303,9 +2266,9 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2303
2266
|
// 2.1) Deposit
|
|
2304
2267
|
let depositedAmount = flashLoanBorrowedAmount;
|
|
2305
2268
|
if (depositReserve.coinType === ((_f = depositReserves.lst) === null || _f === void 0 ? void 0 : _f.coinType))
|
|
2306
|
-
depositedAmount = new
|
|
2269
|
+
depositedAmount = new BigNumber(depositedAmount.minus(getStrategyLstMintFee(lstMap, depositReserve.coinType, depositedAmount)))
|
|
2307
2270
|
.times((_g = lst === null || lst === void 0 ? void 0 : lst.suiToLstExchangeRate) !== null && _g !== void 0 ? _g : 1)
|
|
2308
|
-
.decimalPlaces(depositReserve.token.decimals,
|
|
2271
|
+
.decimalPlaces(depositReserve.token.decimals, BigNumber.ROUND_DOWN);
|
|
2309
2272
|
let flashLoanBorrowedCoin = transaction.moveCall({
|
|
2310
2273
|
target: "0x2::coin::from_balance",
|
|
2311
2274
|
typeArguments: [
|
|
@@ -2315,15 +2278,15 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2315
2278
|
});
|
|
2316
2279
|
if (depositReserve.coinType === ((_h = depositReserves.lst) === null || _h === void 0 ? void 0 : _h.coinType))
|
|
2317
2280
|
flashLoanBorrowedCoin = lst.client.mint(transaction, flashLoanBorrowedCoin);
|
|
2318
|
-
|
|
2281
|
+
strategyDeposit(flashLoanBorrowedCoin, depositReserve.coinType, strategyOwnerCapId, suilendClient.findReserveArrayIndex(depositReserve.coinType), transaction);
|
|
2319
2282
|
// 2.2) Update state
|
|
2320
|
-
deposits =
|
|
2283
|
+
deposits = addOrInsertStrategyDeposit(deposits, {
|
|
2321
2284
|
coinType: depositReserve.coinType,
|
|
2322
2285
|
depositedAmount,
|
|
2323
2286
|
});
|
|
2324
2287
|
// 3) Unloop to max exposure
|
|
2325
2288
|
// 3.1) Unloop
|
|
2326
|
-
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = yield
|
|
2289
|
+
const { deposits: newDeposits, borrowedAmount: newBorrowedAmount, transaction: newTransaction, } = yield strategyUnloopToExposureTx(reserveMap, lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, undefined, // Don't pass targetBorrowedAmount
|
|
2327
2290
|
depositAdjustWithdrawExposure, // Pass targetExposure
|
|
2328
2291
|
transaction, dryRunTransaction);
|
|
2329
2292
|
// 3.2) Update state
|
|
@@ -2332,23 +2295,23 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2332
2295
|
transaction = newTransaction;
|
|
2333
2296
|
// 4) Repay flash loan + fee
|
|
2334
2297
|
const receiptDebts = transaction.moveCall({
|
|
2335
|
-
target: `${
|
|
2298
|
+
target: `${MMT_CONTRACT_PACKAGE_ID}::trade::flash_receipt_debts`,
|
|
2336
2299
|
typeArguments: [],
|
|
2337
2300
|
arguments: [receipt],
|
|
2338
2301
|
});
|
|
2339
2302
|
const dryRunResults = yield dryRunTransaction(transaction);
|
|
2340
|
-
const flashLoanRepayAmount = new
|
|
2303
|
+
const flashLoanRepayAmount = new BigNumber(bcs
|
|
2341
2304
|
.u64()
|
|
2342
2305
|
.parse(new Uint8Array((_m = (_l = (_k = (_j = dryRunResults.results) === null || _j === void 0 ? void 0 : _j.find((r, index) => index === receiptDebts.Result)) === null || _k === void 0 ? void 0 : _k.returnValues) === null || _l === void 0 ? void 0 : _l[flashLoanObj.borrowA ? 0 : 1][0]) !== null && _m !== void 0 ? _m : [0])))
|
|
2343
2306
|
.div(10 ** depositReserve.token.decimals)
|
|
2344
|
-
.decimalPlaces(depositReserve.token.decimals,
|
|
2307
|
+
.decimalPlaces(depositReserve.token.decimals, BigNumber.ROUND_UP);
|
|
2345
2308
|
// 4.1) Withdraw additional + fee
|
|
2346
2309
|
let withdrawnAmount = flashLoanRepayAmount;
|
|
2347
2310
|
if (depositReserve.coinType === ((_o = depositReserves.lst) === null || _o === void 0 ? void 0 : _o.coinType))
|
|
2348
2311
|
withdrawnAmount = withdrawnAmount
|
|
2349
2312
|
.div(1 - +((_p = lst === null || lst === void 0 ? void 0 : lst.redeemFeePercent) !== null && _p !== void 0 ? _p : 0) / 100) // Potential rounding issue (max 1 MIST)
|
|
2350
|
-
.decimalPlaces(depositReserve.token.decimals,
|
|
2351
|
-
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, withdrawnCoin, } = yield
|
|
2313
|
+
.decimalPlaces(depositReserve.token.decimals, BigNumber.ROUND_UP);
|
|
2314
|
+
const { deposits: newDeposits2, borrowedAmount: newBorrowedAmount2, transaction: newTransaction2, withdrawnCoin, } = yield strategyWithdrawTx(reserveMap, lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligationId, deposits, borrowedAmount, {
|
|
2352
2315
|
coinType: depositReserve.coinType,
|
|
2353
2316
|
withdrawnAmount,
|
|
2354
2317
|
}, transaction, dryRunTransaction, true);
|
|
@@ -2371,14 +2334,14 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2371
2334
|
});
|
|
2372
2335
|
if (flashLoanObj.provider === StrategyFlashLoanProvider.MMT) {
|
|
2373
2336
|
transaction.moveCall({
|
|
2374
|
-
target: `${
|
|
2337
|
+
target: `${MMT_CONTRACT_PACKAGE_ID}::trade::repay_flash_loan`,
|
|
2375
2338
|
typeArguments: [flashLoanObj.coinTypeA, flashLoanObj.coinTypeB],
|
|
2376
2339
|
arguments: [
|
|
2377
2340
|
transaction.object(flashLoanObj.poolId),
|
|
2378
2341
|
receipt,
|
|
2379
2342
|
flashLoanObj.borrowA ? flashLoanRepayBalance : borrowedBalanceA,
|
|
2380
2343
|
flashLoanObj.borrowA ? borrowedBalanceB : flashLoanRepayBalance,
|
|
2381
|
-
transaction.object(
|
|
2344
|
+
transaction.object(MMT_VERSION_OBJECT_ID),
|
|
2382
2345
|
],
|
|
2383
2346
|
});
|
|
2384
2347
|
}
|
|
@@ -2387,20 +2350,19 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2387
2350
|
}
|
|
2388
2351
|
return { deposits, borrowedAmount, transaction };
|
|
2389
2352
|
});
|
|
2390
|
-
|
|
2391
|
-
const strategyAdjustTx = (
|
|
2353
|
+
export const strategyAdjustTx = (
|
|
2392
2354
|
// AppContext
|
|
2393
2355
|
reserveMap,
|
|
2394
2356
|
// Strategy
|
|
2395
2357
|
lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligation, _deposits, _borrowedAmount, targetExposure, transaction, dryRunTransaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
2396
|
-
const strategyInfo =
|
|
2358
|
+
const strategyInfo = STRATEGY_TYPE_INFO_MAP[strategyType];
|
|
2397
2359
|
const lst = strategyInfo.depositLstCoinType !== undefined
|
|
2398
2360
|
? lstMap[strategyInfo.depositLstCoinType]
|
|
2399
2361
|
: undefined;
|
|
2400
|
-
const depositReserves =
|
|
2401
|
-
const borrowReserve =
|
|
2402
|
-
const defaultCurrencyReserve =
|
|
2403
|
-
const exposure =
|
|
2362
|
+
const depositReserves = getStrategyDepositReserves(reserveMap, strategyType);
|
|
2363
|
+
const borrowReserve = getStrategyBorrowReserve(reserveMap, strategyType);
|
|
2364
|
+
const defaultCurrencyReserve = getStrategyDefaultCurrencyReserve(reserveMap, strategyType);
|
|
2365
|
+
const exposure = getStrategyExposure(reserveMap, lstMap, strategyType, obligation);
|
|
2404
2366
|
console.log(`[strategyAdjust] args |`, JSON.stringify({
|
|
2405
2367
|
_address,
|
|
2406
2368
|
strategyOwnerCapId,
|
|
@@ -2413,18 +2375,17 @@ lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _addre
|
|
|
2413
2375
|
targetExposure: targetExposure.toFixed(20),
|
|
2414
2376
|
}, null, 2));
|
|
2415
2377
|
//
|
|
2416
|
-
const deposits =
|
|
2378
|
+
const deposits = cloneDeep(_deposits);
|
|
2417
2379
|
const borrowedAmount = _borrowedAmount;
|
|
2418
2380
|
// 1) Loop or unloop to target exposure
|
|
2419
2381
|
if (targetExposure.gt(exposure))
|
|
2420
|
-
return
|
|
2382
|
+
return strategyLoopToExposureTx(reserveMap, lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligation.id, deposits, borrowedAmount, undefined, // Don't pass targetBorrowedAmount
|
|
2421
2383
|
targetExposure, // Pass targetExposure
|
|
2422
2384
|
transaction);
|
|
2423
2385
|
else if (targetExposure.lt(exposure))
|
|
2424
|
-
return
|
|
2386
|
+
return strategyUnloopToExposureTx(reserveMap, lstMap, strategyType, suiClient, suilendClient, cetusSdk, cetusPartnerId, _address, strategyOwnerCapId, obligation.id, deposits, borrowedAmount, undefined, // Don't pass targetBorrowedAmount
|
|
2425
2387
|
targetExposure, // Pass targetExposure
|
|
2426
2388
|
transaction, dryRunTransaction);
|
|
2427
2389
|
else
|
|
2428
2390
|
return { deposits, borrowedAmount, transaction };
|
|
2429
2391
|
});
|
|
2430
|
-
exports.strategyAdjustTx = strategyAdjustTx;
|