@strkfarm/sdk 2.0.0-dev.5 → 2.0.0-dev.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +190 -36
- package/dist/cli.mjs +188 -34
- package/dist/index.browser.global.js +118889 -92229
- package/dist/index.browser.mjs +13381 -11153
- package/dist/index.d.ts +2284 -1938
- package/dist/index.js +13794 -11360
- package/dist/index.mjs +14253 -11843
- package/package.json +59 -60
- package/src/data/avnu.abi.json +840 -0
- package/src/data/ekubo-price-fethcer.abi.json +265 -0
- package/src/data/redeem-request-nft.abi.json +752 -0
- package/src/data/universal-vault.abi.json +8 -7
- package/src/dataTypes/_bignumber.ts +13 -4
- package/src/dataTypes/bignumber.browser.ts +10 -1
- package/src/dataTypes/bignumber.node.ts +10 -1
- package/src/dataTypes/index.ts +3 -2
- package/src/dataTypes/mynumber.ts +141 -0
- package/src/global.ts +280 -233
- package/src/index.browser.ts +2 -1
- package/src/interfaces/common.tsx +229 -6
- package/src/modules/apollo-client-config.ts +28 -0
- package/src/modules/avnu.ts +21 -12
- package/src/modules/ekubo-pricer.ts +99 -0
- package/src/modules/ekubo-quoter.ts +48 -30
- package/src/modules/erc20.ts +17 -0
- package/src/modules/harvests.ts +43 -29
- package/src/modules/index.ts +2 -1
- package/src/modules/pragma.ts +23 -8
- package/src/modules/pricer-avnu-api.ts +114 -0
- package/src/modules/pricer-from-api.ts +159 -15
- package/src/modules/pricer-lst.ts +1 -1
- package/src/modules/pricer-quote-utils.ts +54 -0
- package/src/modules/pricer.ts +157 -54
- package/src/modules/pricerBase.ts +2 -1
- package/src/modules/zkLend.ts +3 -2
- package/src/node/deployer.ts +36 -1
- package/src/node/pricer-redis.ts +3 -1
- package/src/strategies/base-strategy.ts +168 -16
- package/src/strategies/constants.ts +8 -3
- package/src/strategies/ekubo-cl-vault.tsx +1048 -355
- package/src/strategies/factory.ts +199 -0
- package/src/strategies/index.ts +5 -3
- package/src/strategies/registry.ts +262 -0
- package/src/strategies/sensei.ts +354 -10
- package/src/strategies/svk-strategy.ts +292 -31
- package/src/strategies/token-boosted-xstrk-carry-strategy.tsx +1261 -0
- package/src/strategies/types.ts +4 -0
- package/src/strategies/universal-adapters/adapter-utils.ts +4 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +196 -272
- package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
- package/src/strategies/universal-adapters/common-adapter.ts +206 -203
- package/src/strategies/universal-adapters/index.ts +10 -8
- package/src/strategies/universal-adapters/svk-troves-adapter.ts +511 -0
- package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
- package/src/strategies/universal-adapters/vesu-adapter.ts +120 -82
- package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +525 -0
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +866 -860
- package/src/strategies/universal-adapters/vesu-position-common.ts +258 -0
- package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
- package/src/strategies/universal-lst-muliplier-strategy.tsx +895 -416
- package/src/strategies/universal-strategy.tsx +1332 -1173
- package/src/strategies/vesu-rebalance.tsx +254 -153
- package/src/strategies/yoloVault.ts +1096 -0
- package/src/utils/cacheClass.ts +11 -2
- package/src/utils/health-factor-math.ts +33 -1
- package/src/utils/index.ts +3 -1
- package/src/utils/logger.browser.ts +22 -4
- package/src/utils/logger.node.ts +259 -24
- package/src/utils/starknet-call-parser.ts +1036 -0
- package/src/utils/strategy-utils.ts +61 -0
- package/src/modules/ExtendedWrapperSDk/index.ts +0 -62
- package/src/modules/ExtendedWrapperSDk/types.ts +0 -311
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +0 -395
- package/src/strategies/universal-adapters/extended-adapter.ts +0 -662
- package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +0 -34
- package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +0 -77
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +0 -49
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +0 -372
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +0 -1140
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
import { ContractAddr, Web3Number } from "@/dataTypes";
|
|
2
|
+
import { IProtocol, Protocols, TokenInfo } from "@/interfaces";
|
|
3
|
+
import {
|
|
4
|
+
APYType,
|
|
5
|
+
BaseAdapter,
|
|
6
|
+
BaseAdapterConfig,
|
|
7
|
+
ManageCall,
|
|
8
|
+
PositionAmount,
|
|
9
|
+
PositionAPY,
|
|
10
|
+
PositionInfo,
|
|
11
|
+
SupportedPosition,
|
|
12
|
+
} from "./baseAdapter";
|
|
13
|
+
import { TokenMarketData } from "@/modules";
|
|
14
|
+
import {
|
|
15
|
+
SIMPLE_SANITIZER,
|
|
16
|
+
VESU_V2_MODIFY_POSITION_SANITIZER,
|
|
17
|
+
toBigInt,
|
|
18
|
+
} from "./adapter-utils";
|
|
19
|
+
import { CairoCustomEnum, hash, uint256 } from "starknet";
|
|
20
|
+
import {
|
|
21
|
+
VesuAdapter,
|
|
22
|
+
getVesuSingletonAddress,
|
|
23
|
+
} from "./vesu-adapter";
|
|
24
|
+
import {
|
|
25
|
+
VesuPositionCommonContext,
|
|
26
|
+
getVesuCommonAPY,
|
|
27
|
+
getVesuCommonMaxDeposit,
|
|
28
|
+
getVesuCommonMaxWithdraw,
|
|
29
|
+
getVesuCommonPosition,
|
|
30
|
+
} from "./vesu-position-common";
|
|
31
|
+
import { logger } from "@/utils";
|
|
32
|
+
import { HealthFactorMath } from "@/utils/health-factor-math";
|
|
33
|
+
|
|
34
|
+
type SignedDelta = {
|
|
35
|
+
amount: Web3Number;
|
|
36
|
+
isNegative: boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export interface VesuModifyPositionDepositParams {
|
|
40
|
+
amount: Web3Number;
|
|
41
|
+
debtAmount?: Web3Number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface VesuModifyPositionWithdrawParams {
|
|
45
|
+
amount: Web3Number;
|
|
46
|
+
debtAmount?: Web3Number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface VesuModifyPositionAdapterConfig extends BaseAdapterConfig {
|
|
50
|
+
poolId: ContractAddr;
|
|
51
|
+
collateral: TokenInfo;
|
|
52
|
+
debt: TokenInfo;
|
|
53
|
+
targetLtv: number;
|
|
54
|
+
maxLtv: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class VesuModifyPositionAdapter extends BaseAdapter<
|
|
58
|
+
VesuModifyPositionDepositParams,
|
|
59
|
+
VesuModifyPositionWithdrawParams
|
|
60
|
+
> {
|
|
61
|
+
readonly config: VesuModifyPositionAdapterConfig;
|
|
62
|
+
readonly _vesuAdapter: VesuAdapter;
|
|
63
|
+
private readonly _tokenMarketData: TokenMarketData;
|
|
64
|
+
|
|
65
|
+
constructor(config: VesuModifyPositionAdapterConfig) {
|
|
66
|
+
super(config, VesuModifyPositionAdapter.name, Protocols.VESU);
|
|
67
|
+
this.config = config;
|
|
68
|
+
this._vesuAdapter = new VesuAdapter({
|
|
69
|
+
poolId: config.poolId,
|
|
70
|
+
collateral: config.collateral,
|
|
71
|
+
debt: config.debt,
|
|
72
|
+
vaultAllocator: config.vaultAllocator,
|
|
73
|
+
id: "",
|
|
74
|
+
});
|
|
75
|
+
this._vesuAdapter.networkConfig = this.config.networkConfig;
|
|
76
|
+
this._vesuAdapter.pricer = this.config.pricer;
|
|
77
|
+
this._tokenMarketData = new TokenMarketData(
|
|
78
|
+
this.config.pricer,
|
|
79
|
+
this.config.networkConfig,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private _prepareVesuAdapter() {
|
|
84
|
+
this._vesuAdapter.networkConfig = this.config.networkConfig;
|
|
85
|
+
this._vesuAdapter.pricer = this.config.pricer;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private _getTargetHealthFactor(): number {
|
|
89
|
+
if (this.config.targetLtv <= 0) {
|
|
90
|
+
throw new Error(`Target LTV is less than or equal to 0: ${this.config.targetLtv}`);
|
|
91
|
+
}
|
|
92
|
+
if (this.config.targetLtv >= this._getEffectiveMaxLtv(this.config.maxLtv)) {
|
|
93
|
+
throw new Error(`Target LTV is greater than or equal to max LTV: ${this.config.targetLtv} >= ${this._getEffectiveMaxLtv(this.config.maxLtv)}`);
|
|
94
|
+
}
|
|
95
|
+
return this.config.maxLtv / this.config.targetLtv;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private _getPositionCommonContext(): VesuPositionCommonContext {
|
|
99
|
+
return {
|
|
100
|
+
adapterName: VesuModifyPositionAdapter.name,
|
|
101
|
+
protocol: this.protocol,
|
|
102
|
+
poolId: this.config.poolId,
|
|
103
|
+
collateral: this.config.collateral,
|
|
104
|
+
debt: this.config.debt,
|
|
105
|
+
networkConfig: this.config.networkConfig,
|
|
106
|
+
pricer: this.config.pricer,
|
|
107
|
+
vesuAdapter: this._vesuAdapter,
|
|
108
|
+
tokenMarketData: this._tokenMarketData,
|
|
109
|
+
targetHealthFactor: this._getTargetHealthFactor(),
|
|
110
|
+
getCache: this.getCache.bind(this),
|
|
111
|
+
setCache: this.setCache.bind(this),
|
|
112
|
+
getUSDValue: this.getUSDValue.bind(this),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private _getEffectiveMaxLtv(onchainLtv: number): number {
|
|
117
|
+
return Math.min(onchainLtv, this.config.maxLtv);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private _toSigned(amount: Web3Number, isNegative: boolean): SignedDelta {
|
|
121
|
+
if (amount.isZero()) {
|
|
122
|
+
return { amount: Web3Number.fromWei(0, amount.decimals), isNegative: false };
|
|
123
|
+
}
|
|
124
|
+
return { amount: amount.abs(), isNegative };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private _depositApproveProofReadableId(): string {
|
|
128
|
+
return `vmp_ad_c_${this.config.poolId.shortString()}_${this.config.collateral.symbol}_${this.config.debt.symbol}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private _depositModifyProofReadableId(): string {
|
|
132
|
+
return `vmp_dep_${this.config.poolId.shortString()}_${this.config.collateral.symbol}_${this.config.debt.symbol}`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private _withdrawApproveProofReadableId(): string {
|
|
136
|
+
return `vmp_aw_d_${this.config.poolId.shortString()}_${this.config.collateral.symbol}_${this.config.debt.symbol}`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private _withdrawModifyProofReadableId(): string {
|
|
140
|
+
return `vmp_wdr_${this.config.poolId.shortString()}_${this.config.collateral.symbol}_${this.config.debt.symbol}`;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private _clampWithdrawCollateral(
|
|
144
|
+
collateralDelta: SignedDelta,
|
|
145
|
+
currentCollateral: Web3Number,
|
|
146
|
+
): SignedDelta {
|
|
147
|
+
if (!collateralDelta.isNegative) {
|
|
148
|
+
return collateralDelta;
|
|
149
|
+
}
|
|
150
|
+
if (collateralDelta.amount.greaterThan(currentCollateral)) {
|
|
151
|
+
return this._toSigned(currentCollateral, true);
|
|
152
|
+
}
|
|
153
|
+
return collateralDelta;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private _clampRepayDebt(debtDelta: SignedDelta, currentDebt: Web3Number): SignedDelta {
|
|
157
|
+
if (!debtDelta.isNegative) {
|
|
158
|
+
return debtDelta;
|
|
159
|
+
}
|
|
160
|
+
if (debtDelta.amount.greaterThan(currentDebt)) {
|
|
161
|
+
return this._toSigned(currentDebt, true);
|
|
162
|
+
}
|
|
163
|
+
return debtDelta;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private _normalizeDebtAmountFromHelper(helperAmount: Web3Number): Web3Number {
|
|
167
|
+
return new Web3Number(
|
|
168
|
+
helperAmount.abs().toFixed(this.config.debt.decimals),
|
|
169
|
+
this.config.debt.decimals,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private async _getState() {
|
|
174
|
+
const [positions, ltvConfig, prices] = await Promise.all([
|
|
175
|
+
this._vesuAdapter.getPositions(this.config.networkConfig),
|
|
176
|
+
this._vesuAdapter.getLTVConfig(this.config.networkConfig),
|
|
177
|
+
this._vesuAdapter.getAssetPrices(),
|
|
178
|
+
]);
|
|
179
|
+
return {
|
|
180
|
+
currentCollateral: positions[0].amount,
|
|
181
|
+
currentDebt: positions[1].amount,
|
|
182
|
+
onchainLtv: ltvConfig,
|
|
183
|
+
collateralPrice: prices.collateralPrice,
|
|
184
|
+
debtPrice: prices.debtPrice,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private async _buildDefaultDepositDeltas(
|
|
189
|
+
params: VesuModifyPositionDepositParams,
|
|
190
|
+
): Promise<{ collateral: SignedDelta; debt: SignedDelta }> {
|
|
191
|
+
const state = await this._getState();
|
|
192
|
+
const collateralToAdd = params.amount;
|
|
193
|
+
const effectiveMaxLtv = this._getEffectiveMaxLtv(state.onchainLtv);
|
|
194
|
+
const helperOutput = HealthFactorMath.getMaxDebtAmount(
|
|
195
|
+
state.currentCollateral.plus(collateralToAdd),
|
|
196
|
+
state.collateralPrice,
|
|
197
|
+
effectiveMaxLtv,
|
|
198
|
+
this._getTargetHealthFactor(),
|
|
199
|
+
state.debtPrice,
|
|
200
|
+
this.config.debt,
|
|
201
|
+
);
|
|
202
|
+
if (!helperOutput || helperOutput.lessThan(0)) {
|
|
203
|
+
throw new Error(`Failed to calculate default deposit debt delta: ${helperOutput?.toNumber()}`);
|
|
204
|
+
}
|
|
205
|
+
// Fixed :
|
|
206
|
+
// getMaxDebtAmount returns the TOTAL target debt at the new collateral level.
|
|
207
|
+
// Subtract current debt to get the incremental borrow delta.
|
|
208
|
+
const normalizedDebtAmount = this._normalizeDebtAmountFromHelper(
|
|
209
|
+
helperOutput,
|
|
210
|
+
).minus(state.currentDebt);
|
|
211
|
+
if (normalizedDebtAmount.lessThan(0)) {
|
|
212
|
+
logger.warn(`VesuModifyPositionAdapter: deposit debt delta is negative (${normalizedDebtAmount.toNumber()}), clamping to zero`);
|
|
213
|
+
return {
|
|
214
|
+
collateral: this._toSigned(collateralToAdd, false),
|
|
215
|
+
debt: this._toSigned(Web3Number.fromWei(0, this.config.debt.decimals), false),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
collateral: this._toSigned(collateralToAdd, false),
|
|
220
|
+
debt: this._toSigned(normalizedDebtAmount, false),
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private async _buildDefaultWithdrawDeltas(
|
|
225
|
+
params: VesuModifyPositionWithdrawParams,
|
|
226
|
+
): Promise<{ collateral: SignedDelta; debt: SignedDelta }> {
|
|
227
|
+
const state = await this._getState();
|
|
228
|
+
const collateralToWithdraw = params.amount;
|
|
229
|
+
const effectiveMaxLtv = this._getEffectiveMaxLtv(state.onchainLtv);
|
|
230
|
+
const helperOutput = HealthFactorMath.getMaxDebtAmount(
|
|
231
|
+
state.currentCollateral.minus(collateralToWithdraw),
|
|
232
|
+
state.collateralPrice,
|
|
233
|
+
effectiveMaxLtv,
|
|
234
|
+
this._getTargetHealthFactor(),
|
|
235
|
+
state.debtPrice,
|
|
236
|
+
this.config.debt,
|
|
237
|
+
);
|
|
238
|
+
if (!helperOutput || helperOutput.lessThan(0)) {
|
|
239
|
+
throw new Error(`Failed to calculate max debt amount for withdraw: ${helperOutput?.toNumber()}`);
|
|
240
|
+
}
|
|
241
|
+
const normalizedDebtAmount = this._normalizeDebtAmountFromHelper(
|
|
242
|
+
helperOutput,
|
|
243
|
+
).minus(state.currentDebt); // debt to repay.
|
|
244
|
+
|
|
245
|
+
if (normalizedDebtAmount.greaterThan(0)) { // > 0 means borrow
|
|
246
|
+
throw new Error(`Failed to calculate default withdraw debt delta: ${normalizedDebtAmount?.toNumber()}`);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
let collateral = this._toSigned(collateralToWithdraw, true);
|
|
250
|
+
let debt = this._toSigned(normalizedDebtAmount, true);
|
|
251
|
+
collateral = this._clampWithdrawCollateral(collateral, state.currentCollateral);
|
|
252
|
+
debt = this._clampRepayDebt(debt, state.currentDebt);
|
|
253
|
+
return { collateral, debt };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private _amountStruct(delta: SignedDelta) {
|
|
257
|
+
return {
|
|
258
|
+
denomination: new CairoCustomEnum({ Assets: {} }),
|
|
259
|
+
value: {
|
|
260
|
+
abs: uint256.bnToUint256(delta.amount.toWei()),
|
|
261
|
+
is_negative: delta.amount.isZero() ? false : delta.isNegative,
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private async _getModifyPositionCall(
|
|
267
|
+
collateralDelta: SignedDelta,
|
|
268
|
+
debtDelta: SignedDelta,
|
|
269
|
+
proofReadableId: string,
|
|
270
|
+
): Promise<ManageCall> {
|
|
271
|
+
const { contract, isV2 } = this._vesuAdapter.getVesuSingletonContract(
|
|
272
|
+
this.config.networkConfig,
|
|
273
|
+
this.config.poolId,
|
|
274
|
+
);
|
|
275
|
+
const { addr } = getVesuSingletonAddress(this.config.poolId);
|
|
276
|
+
const call = contract.populate("modify_position", {
|
|
277
|
+
params: isV2
|
|
278
|
+
? {
|
|
279
|
+
collateral_asset: this.config.collateral.address.toBigInt(),
|
|
280
|
+
debt_asset: this.config.debt.address.toBigInt(),
|
|
281
|
+
user: this.config.vaultAllocator.toBigInt(),
|
|
282
|
+
collateral: this._amountStruct(collateralDelta),
|
|
283
|
+
debt: this._amountStruct(debtDelta),
|
|
284
|
+
}
|
|
285
|
+
: {
|
|
286
|
+
pool_id: this.config.poolId.toBigInt(),
|
|
287
|
+
collateral_asset: this.config.collateral.address.toBigInt(),
|
|
288
|
+
debt_asset: this.config.debt.address.toBigInt(),
|
|
289
|
+
user: this.config.vaultAllocator.toBigInt(),
|
|
290
|
+
collateral: this._amountStruct(collateralDelta),
|
|
291
|
+
debt: this._amountStruct(debtDelta),
|
|
292
|
+
data: [0],
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
return {
|
|
296
|
+
proofReadableId,
|
|
297
|
+
sanitizer: isV2 ? VESU_V2_MODIFY_POSITION_SANITIZER : SIMPLE_SANITIZER,
|
|
298
|
+
call: {
|
|
299
|
+
contractAddress: addr,
|
|
300
|
+
selector: hash.getSelectorFromName("modify_position"),
|
|
301
|
+
calldata: call.calldata as bigint[],
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private _getApproveCall(
|
|
307
|
+
token: TokenInfo,
|
|
308
|
+
amount: Web3Number,
|
|
309
|
+
proofReadableId: string,
|
|
310
|
+
): ManageCall {
|
|
311
|
+
const { addr } = getVesuSingletonAddress(this.config.poolId);
|
|
312
|
+
const amount256 = uint256.bnToUint256(amount.toWei());
|
|
313
|
+
return {
|
|
314
|
+
proofReadableId,
|
|
315
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
316
|
+
call: {
|
|
317
|
+
contractAddress: token.address,
|
|
318
|
+
selector: hash.getSelectorFromName("approve"),
|
|
319
|
+
calldata: [
|
|
320
|
+
addr.toBigInt(),
|
|
321
|
+
toBigInt(amount256.low.toString()),
|
|
322
|
+
toBigInt(amount256.high.toString()),
|
|
323
|
+
],
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
protected async getAPY(_supportedPosition: SupportedPosition): Promise<PositionAPY> {
|
|
329
|
+
return getVesuCommonAPY(this._getPositionCommonContext(), _supportedPosition);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
protected async getPosition(supportedPosition: SupportedPosition): Promise<PositionAmount> {
|
|
333
|
+
return getVesuCommonPosition(this._getPositionCommonContext(), supportedPosition);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
async maxDeposit(amount?: Web3Number): Promise<PositionInfo> {
|
|
337
|
+
const { collateralPosition, debtPosition: debtPosition } = await getVesuCommonMaxDeposit(this._getPositionCommonContext(), amount);
|
|
338
|
+
// since this is not multiply adapter, max allow collateral is directly max allowed deposit
|
|
339
|
+
const netAPY =
|
|
340
|
+
(collateralPosition.apy.apy * collateralPosition.usdValue - debtPosition.apy.apy * debtPosition.usdValue) /
|
|
341
|
+
(collateralPosition.usdValue - debtPosition.usdValue);
|
|
342
|
+
return {
|
|
343
|
+
...collateralPosition,
|
|
344
|
+
apy: { apy: netAPY, type: APYType.BASE },
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async maxWithdraw(): Promise<PositionInfo> {
|
|
349
|
+
const { collateralPosition, debtPosition } = await getVesuCommonMaxWithdraw(this._getPositionCommonContext());
|
|
350
|
+
const netAPY =
|
|
351
|
+
(collateralPosition.apy.apy * collateralPosition.usdValue - debtPosition.apy.apy * debtPosition.usdValue) /
|
|
352
|
+
(collateralPosition.usdValue - debtPosition.usdValue);
|
|
353
|
+
return {
|
|
354
|
+
...collateralPosition,
|
|
355
|
+
apy: { apy: netAPY, type: APYType.BASE },
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
protected _getDepositLeaf(): {
|
|
360
|
+
target: ContractAddr;
|
|
361
|
+
method: string;
|
|
362
|
+
packedArguments: bigint[];
|
|
363
|
+
sanitizer: ContractAddr;
|
|
364
|
+
id: string;
|
|
365
|
+
}[] {
|
|
366
|
+
const { addr, isV2 } = getVesuSingletonAddress(this.config.poolId);
|
|
367
|
+
const modifyPackedArguments = isV2
|
|
368
|
+
? [
|
|
369
|
+
this.config.collateral.address.toBigInt(),
|
|
370
|
+
this.config.debt.address.toBigInt(),
|
|
371
|
+
this.config.vaultAllocator.toBigInt(),
|
|
372
|
+
]
|
|
373
|
+
: [
|
|
374
|
+
this.config.poolId.toBigInt(),
|
|
375
|
+
this.config.collateral.address.toBigInt(),
|
|
376
|
+
this.config.debt.address.toBigInt(),
|
|
377
|
+
this.config.vaultAllocator.toBigInt(),
|
|
378
|
+
1n,
|
|
379
|
+
0n,
|
|
380
|
+
];
|
|
381
|
+
|
|
382
|
+
return [
|
|
383
|
+
{
|
|
384
|
+
target: this.config.collateral.address,
|
|
385
|
+
method: "approve",
|
|
386
|
+
packedArguments: [addr.toBigInt()],
|
|
387
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
388
|
+
id: this._depositApproveProofReadableId(),
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
target: addr,
|
|
392
|
+
method: "modify_position",
|
|
393
|
+
packedArguments: modifyPackedArguments,
|
|
394
|
+
sanitizer: isV2 ? VESU_V2_MODIFY_POSITION_SANITIZER : SIMPLE_SANITIZER,
|
|
395
|
+
id: this._depositModifyProofReadableId(),
|
|
396
|
+
},
|
|
397
|
+
];
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
protected _getWithdrawLeaf(): {
|
|
401
|
+
target: ContractAddr;
|
|
402
|
+
method: string;
|
|
403
|
+
packedArguments: bigint[];
|
|
404
|
+
sanitizer: ContractAddr;
|
|
405
|
+
id: string;
|
|
406
|
+
}[] {
|
|
407
|
+
const { addr, isV2 } = getVesuSingletonAddress(this.config.poolId);
|
|
408
|
+
const modifyPackedArguments = isV2
|
|
409
|
+
? [
|
|
410
|
+
this.config.collateral.address.toBigInt(),
|
|
411
|
+
this.config.debt.address.toBigInt(),
|
|
412
|
+
this.config.vaultAllocator.toBigInt(),
|
|
413
|
+
]
|
|
414
|
+
: [
|
|
415
|
+
this.config.poolId.toBigInt(),
|
|
416
|
+
this.config.collateral.address.toBigInt(),
|
|
417
|
+
this.config.debt.address.toBigInt(),
|
|
418
|
+
this.config.vaultAllocator.toBigInt(),
|
|
419
|
+
1n,
|
|
420
|
+
0n,
|
|
421
|
+
];
|
|
422
|
+
|
|
423
|
+
return [
|
|
424
|
+
{
|
|
425
|
+
target: this.config.debt.address,
|
|
426
|
+
method: "approve",
|
|
427
|
+
packedArguments: [addr.toBigInt()],
|
|
428
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
429
|
+
id: this._withdrawApproveProofReadableId(),
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
target: addr,
|
|
433
|
+
method: "modify_position",
|
|
434
|
+
packedArguments: modifyPackedArguments,
|
|
435
|
+
sanitizer: isV2 ? VESU_V2_MODIFY_POSITION_SANITIZER : SIMPLE_SANITIZER,
|
|
436
|
+
id: this._withdrawModifyProofReadableId(),
|
|
437
|
+
},
|
|
438
|
+
];
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
async getDepositCall(params: VesuModifyPositionDepositParams): Promise<ManageCall[]> {
|
|
442
|
+
const state = await this._getState();
|
|
443
|
+
|
|
444
|
+
let collateralDelta: SignedDelta;
|
|
445
|
+
let debtDelta: SignedDelta;
|
|
446
|
+
|
|
447
|
+
if (params.debtAmount === undefined) {
|
|
448
|
+
const defaults = await this._buildDefaultDepositDeltas(params);
|
|
449
|
+
collateralDelta = defaults.collateral;
|
|
450
|
+
debtDelta = defaults.debt;
|
|
451
|
+
} else {
|
|
452
|
+
collateralDelta = this._toSigned(params.amount, false);
|
|
453
|
+
debtDelta = this._toSigned(params.debtAmount!, false);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
debtDelta = this._clampRepayDebt(debtDelta, state.currentDebt);
|
|
457
|
+
if (collateralDelta.isNegative || debtDelta.isNegative) {
|
|
458
|
+
throw new Error("Invalid deposit call");
|
|
459
|
+
}
|
|
460
|
+
const collateralApproveAmount = collateralDelta.amount;
|
|
461
|
+
|
|
462
|
+
logger.verbose(`getDepositCall: collateralApproveAmount=${collateralApproveAmount.toNumber()}, debtApproveAmount=${debtDelta.amount.toNumber()}`);
|
|
463
|
+
return [
|
|
464
|
+
...(collateralApproveAmount.gt(0)
|
|
465
|
+
? [this._getApproveCall(this.config.collateral, collateralApproveAmount, this._depositApproveProofReadableId())]
|
|
466
|
+
: []),
|
|
467
|
+
await this._getModifyPositionCall(collateralDelta, debtDelta, this._depositModifyProofReadableId()),
|
|
468
|
+
];
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
async getWithdrawCall(params: VesuModifyPositionWithdrawParams): Promise<ManageCall[]> {
|
|
472
|
+
const state = await this._getState();
|
|
473
|
+
|
|
474
|
+
let collateralDelta: SignedDelta;
|
|
475
|
+
let debtDelta: SignedDelta;
|
|
476
|
+
|
|
477
|
+
if (params.debtAmount === undefined) {
|
|
478
|
+
const defaults = await this._buildDefaultWithdrawDeltas(params);
|
|
479
|
+
collateralDelta = defaults.collateral;
|
|
480
|
+
debtDelta = defaults.debt;
|
|
481
|
+
} else {
|
|
482
|
+
collateralDelta = this._toSigned(params.amount, true);
|
|
483
|
+
debtDelta = this._toSigned(params.debtAmount!, true);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
collateralDelta = this._clampWithdrawCollateral(collateralDelta, state.currentCollateral);
|
|
487
|
+
debtDelta = this._clampRepayDebt(debtDelta, state.currentDebt);
|
|
488
|
+
if ((!collateralDelta.amount.isZero() && !collateralDelta.isNegative) || (!debtDelta.amount.isZero() && !debtDelta.isNegative)) {
|
|
489
|
+
throw new Error(`Invalid withdraw call: collateralDelta=${collateralDelta.amount.toNumber()} [${collateralDelta.isNegative ? "-" : "+"}], debtDelta=${debtDelta.amount.toNumber()} [${debtDelta.isNegative ? "-" : "+"}]`);
|
|
490
|
+
}
|
|
491
|
+
const debtApproveAmount = debtDelta.amount;
|
|
492
|
+
|
|
493
|
+
return [
|
|
494
|
+
...(debtApproveAmount.gt(0)
|
|
495
|
+
? [this._getApproveCall(this.config.debt, debtApproveAmount, this._withdrawApproveProofReadableId())]
|
|
496
|
+
: []),
|
|
497
|
+
await this._getModifyPositionCall(collateralDelta, debtDelta, this._withdrawModifyProofReadableId()),
|
|
498
|
+
];
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
async getHealthFactor(): Promise<number> {
|
|
502
|
+
this._prepareVesuAdapter();
|
|
503
|
+
return this._vesuAdapter.getHealthFactor();
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Simulates a deposit of `depositAmount` collateral and returns how much
|
|
508
|
+
* debt (STRK) would be incrementally borrowed to reach the target LTV.
|
|
509
|
+
* Used upstream to size the AVNU swap call in the same transaction batch.
|
|
510
|
+
*/
|
|
511
|
+
async getExpectedDepositDebtDelta(depositAmount: Web3Number): Promise<Web3Number> {
|
|
512
|
+
const defaults = await this._buildDefaultDepositDeltas({ amount: depositAmount });
|
|
513
|
+
return defaults.debt.amount;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Simulates a withdrawal of `withdrawAmount` collateral and returns the
|
|
518
|
+
* incremental debt delta needed to keep the target health factor.
|
|
519
|
+
* Positive means borrow, negative means repay.
|
|
520
|
+
*/
|
|
521
|
+
async getExpectedWithdrawDebtDelta(withdrawAmount: Web3Number): Promise<Web3Number> {
|
|
522
|
+
const defaults = await this._buildDefaultWithdrawDeltas({ amount: withdrawAmount });
|
|
523
|
+
return defaults.debt.amount;
|
|
524
|
+
}
|
|
525
|
+
}
|