@strkfarm/sdk 2.0.0-dev.2 → 2.0.0-dev.21

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.
@@ -1,15 +1,43 @@
1
1
  import { ContractAddr, Web3Number } from "@/dataTypes";
2
2
  import { IConfig, Protocols, TokenInfo } from "@/interfaces";
3
3
  import { PricerBase } from "@/modules/pricerBase";
4
- import { BaseAdapter, BaseAdapterConfig, SupportedPosition, PositionInfo, PositionAPY, APYType, ManageCall, AdapterLeafType, GenerateCallFn, DepositParams, WithdrawParams, PositionAmount } from "./baseAdapter";
5
- import { SIMPLE_SANITIZER, SIMPLE_SANITIZER_V2, toBigInt, VESU_SINGLETON, VESU_V2_MODIFY_POSITION_SANITIZER } from "./adapter-utils";
4
+ import {
5
+ BaseAdapter,
6
+ BaseAdapterConfig,
7
+ SupportedPosition,
8
+ PositionInfo,
9
+ PositionAPY,
10
+ APYType,
11
+ ManageCall,
12
+ AdapterLeafType,
13
+ GenerateCallFn,
14
+ DepositParams,
15
+ WithdrawParams,
16
+ PositionAmount,
17
+ } from "./baseAdapter";
18
+ import {
19
+ SIMPLE_SANITIZER,
20
+ SIMPLE_SANITIZER_V2,
21
+ toBigInt,
22
+ VESU_SINGLETON,
23
+ VESU_V2_MODIFY_POSITION_SANITIZER,
24
+ } from "./adapter-utils";
6
25
  import { hash, uint256, Contract, CairoCustomEnum, num } from "starknet";
7
- import { VesuAdapter, VesuMultiplyCallParams, VesuModifyDelegationCallParams, getVesuSingletonAddress, VesuPools, Swap, IncreaseLeverParams, DecreaseLeverParams } from "./vesu-adapter";
26
+ import {
27
+ VesuAdapter,
28
+ VesuMultiplyCallParams,
29
+ VesuModifyDelegationCallParams,
30
+ getVesuSingletonAddress,
31
+ VesuPools,
32
+ Swap,
33
+ IncreaseLeverParams,
34
+ DecreaseLeverParams,
35
+ } from "./vesu-adapter";
8
36
  import { logger } from "@/utils";
9
37
  import { WALLET_ADDRESS } from "../vesu-extended-strategy/utils/constants";
10
- import VesuMultiplyAbi from '@/data/vesu-multiple.abi.json';
11
- import VesuSingletonAbi from '../../data/vesu-singleton.abi.json';
12
- import VesuPoolV2Abi from '@/data/vesu-pool-v2.abi.json';
38
+ import VesuMultiplyAbi from "@/data/vesu-multiple.abi.json";
39
+ import VesuSingletonAbi from "../../data/vesu-singleton.abi.json";
40
+ import VesuPoolV2Abi from "@/data/vesu-pool-v2.abi.json";
13
41
  import { EkuboQuoter, TokenMarketData } from "@/modules";
14
42
  import { calculateDebtReductionAmountForWithdrawal } from "../vesu-extended-strategy/utils/helper";
15
43
  import { HealthFactorMath } from "@/utils/health-factor-math";
@@ -22,13 +50,17 @@ export interface VesuMultiplyAdapterConfig extends BaseAdapterConfig {
22
50
  targetHealthFactor: number;
23
51
  minHealthFactor: number;
24
52
  quoteAmountToFetchPrice: Web3Number;
53
+ minimumVesuMovementAmount: number;
25
54
  }
26
55
 
27
- export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawParams> {
56
+ export class VesuMultiplyAdapter extends BaseAdapter<
57
+ DepositParams,
58
+ WithdrawParams
59
+ > {
28
60
  readonly config: VesuMultiplyAdapterConfig;
29
61
  readonly vesuAdapter: VesuAdapter;
30
62
  readonly tokenMarketData: TokenMarketData;
31
-
63
+ readonly minimumVesuMovementAmount: number;
32
64
  constructor(config: VesuMultiplyAdapterConfig) {
33
65
  super(config, VesuMultiplyAdapter.name, Protocols.VESU);
34
66
  this.config = config;
@@ -37,15 +69,28 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
37
69
  collateral: config.collateral,
38
70
  debt: config.debt,
39
71
  vaultAllocator: config.vaultAllocator,
40
- id: ''
72
+ id: "",
41
73
  });
42
- this.tokenMarketData = new TokenMarketData(this.config.pricer, this.config.networkConfig);
74
+ this.minimumVesuMovementAmount = config.minimumVesuMovementAmount ?? 5; //5 usdc
75
+ this.tokenMarketData = new TokenMarketData(
76
+ this.config.pricer,
77
+ this.config.networkConfig
78
+ );
43
79
  }
44
80
 
45
- protected async getAPY(supportedPosition: SupportedPosition): Promise<PositionAPY> {
81
+ protected async getAPY(
82
+ supportedPosition: SupportedPosition
83
+ ): Promise<PositionAPY> {
46
84
  const CACHE_KEY = `apy_${this.config.poolId.address}_${supportedPosition.asset.symbol}`;
47
85
  const cacheData = this.getCache<PositionAPY>(CACHE_KEY);
48
- console.log(`${VesuMultiplyAdapter.name}::getAPY cacheData: ${JSON.stringify(cacheData)}`, this.vesuAdapter.config.poolId.shortString(), this.vesuAdapter.config.collateral.symbol, this.vesuAdapter.config.debt.symbol);
86
+ console.log(
87
+ `${VesuMultiplyAdapter.name}::getAPY cacheData: ${JSON.stringify(
88
+ cacheData
89
+ )}`,
90
+ this.vesuAdapter.config.poolId.shortString(),
91
+ this.vesuAdapter.config.collateral.symbol,
92
+ this.vesuAdapter.config.debt.symbol
93
+ );
49
94
  if (cacheData) {
50
95
  return cacheData;
51
96
  }
@@ -53,24 +98,30 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
53
98
  // Get Vesu pools to find APY for the asset
54
99
  const allVesuPools = await VesuAdapter.getVesuPools();
55
100
  const asset = supportedPosition.asset;
56
- const pool = allVesuPools.pools.find(p => this.vesuAdapter.config.poolId.eqString(num.getHexString(p.id)));
101
+ const pool = allVesuPools.pools.find((p) =>
102
+ this.vesuAdapter.config.poolId.eqString(num.getHexString(p.id))
103
+ );
57
104
  if (!pool) {
58
- logger.warn(`VesuMultiplyAdapter: Pool not found for token ${asset.symbol}`);
105
+ logger.warn(
106
+ `VesuMultiplyAdapter: Pool not found for token ${asset.symbol}`
107
+ );
59
108
  return {
60
109
  apy: 0,
61
- type: APYType.BASE
110
+ type: APYType.BASE,
62
111
  };
63
112
  }
64
113
  // Find the asset stats for our token
65
- const assetStats = pool.assets.find((a: any) =>
66
- a.symbol.toLowerCase() === asset.symbol.toLowerCase()
114
+ const assetStats = pool.assets.find(
115
+ (a: any) => a.symbol.toLowerCase() === asset.symbol.toLowerCase()
67
116
  )?.stats;
68
117
 
69
118
  if (!assetStats) {
70
- logger.warn(`VesuMultiplyAdapter: Asset stats not found for token ${asset.symbol}`);
119
+ logger.warn(
120
+ `VesuMultiplyAdapter: Asset stats not found for token ${asset.symbol}`
121
+ );
71
122
  return {
72
123
  apy: 0,
73
- type: APYType.BASE
124
+ type: APYType.BASE,
74
125
  };
75
126
  }
76
127
  // Get appropriate APY based on position type
@@ -79,15 +130,21 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
79
130
  // For debt positions, use borrow APY
80
131
  apy = Number(assetStats.borrowApr?.value || 0) / 1e18;
81
132
 
82
- // todo
133
+ // todo
83
134
  // Account for rewards on debt token
84
135
  } else {
85
136
  // For collateral positions, use supply APY
86
137
  const isAssetBTC = asset.symbol.toLowerCase().includes("btc");
87
- const baseAPY = Number(isAssetBTC ? assetStats.btcFiSupplyApr?.value + assetStats.supplyApy?.value : assetStats.supplyApy?.value || 0) / 1e18;
138
+ const baseAPY =
139
+ Number(
140
+ isAssetBTC
141
+ ? assetStats.btcFiSupplyApr?.value + assetStats.supplyApy?.value
142
+ : assetStats.supplyApy?.value || 0
143
+ ) / 1e18;
88
144
 
89
145
  // account for reward yield (like STRK rewards)
90
- const rewardAPY = Number(assetStats.defiSpringSupplyApr?.value || "0") / 1e18;
146
+ const rewardAPY =
147
+ Number(assetStats.defiSpringSupplyApr?.value || "0") / 1e18;
91
148
 
92
149
  // account for base yield of LST
93
150
  const isSupported = this.tokenMarketData.isAPYSupported(asset);
@@ -99,13 +156,16 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
99
156
  }
100
157
  const result = {
101
158
  apy,
102
- type: supportedPosition.isDebt ? APYType.BASE : APYType.BASE
159
+ type: supportedPosition.isDebt ? APYType.BASE : APYType.BASE,
103
160
  };
104
161
 
105
162
  this.setCache(CACHE_KEY, result, 300000); // Cache for 5 minutes
106
163
  return result;
107
164
  } catch (error) {
108
- logger.error(`VesuMultiplyAdapter: Error getting APY for ${supportedPosition.asset.symbol}:`, error);
165
+ logger.error(
166
+ `VesuMultiplyAdapter: Error getting APY for ${supportedPosition.asset.symbol}:`,
167
+ error
168
+ );
109
169
  // return {
110
170
  // apy: 0,
111
171
  // type: APYType.BASE
@@ -114,7 +174,9 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
114
174
  }
115
175
  }
116
176
 
117
- protected async getPosition(supportedPosition: SupportedPosition): Promise<PositionAmount> {
177
+ protected async getPosition(
178
+ supportedPosition: SupportedPosition
179
+ ): Promise<PositionAmount> {
118
180
  const CACHE_KEY = `position_${this.config.poolId.address}_${supportedPosition.asset.symbol}`;
119
181
  const cacheData = this.getCache<PositionAmount>(CACHE_KEY);
120
182
  if (cacheData) {
@@ -125,19 +187,23 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
125
187
  // Use VesuAdapter to get positions
126
188
  this.vesuAdapter.networkConfig = this.config.networkConfig;
127
189
  this.vesuAdapter.pricer = this.config.pricer;
128
-
129
- const positions = await this.vesuAdapter.getPositions(this.config.networkConfig);
130
-
190
+
191
+ const positions = await this.vesuAdapter.getPositions(
192
+ this.config.networkConfig
193
+ );
194
+
131
195
  // Find the position for our asset
132
- let position = positions.find(p =>
196
+ let position = positions.find((p) =>
133
197
  p.token.address.eq(supportedPosition.asset.address)
134
198
  );
135
199
 
136
200
  if (!position) {
137
- logger.warn(`VesuMultiplyAdapter: Position not found for token ${supportedPosition.asset.symbol}`);
201
+ logger.warn(
202
+ `VesuMultiplyAdapter: Position not found for token ${supportedPosition.asset.symbol}`
203
+ );
138
204
  return {
139
- amount: new Web3Number('0', supportedPosition.asset.decimals),
140
- remarks: "Position not found"
205
+ amount: new Web3Number("0", supportedPosition.asset.decimals),
206
+ remarks: "Position not found",
141
207
  };
142
208
  }
143
209
 
@@ -149,7 +215,10 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
149
215
  this.setCache(CACHE_KEY, position, 60000); // Cache for 1 minute
150
216
  return position;
151
217
  } catch (error) {
152
- logger.error(`VesuMultiplyAdapter: Error getting position for ${supportedPosition.asset.symbol}:`, error);
218
+ logger.error(
219
+ `VesuMultiplyAdapter: Error getting position for ${supportedPosition.asset.symbol}:`,
220
+ error
221
+ );
153
222
  // return new Web3Number('0', supportedPosition.asset.decimals);
154
223
  throw error;
155
224
  }
@@ -157,7 +226,10 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
157
226
 
158
227
  async maxBorrowableAPY(): Promise<number> {
159
228
  // get collateral APY
160
- const collateralAPY = await this.getAPY({ asset: this.config.collateral, isDebt: false });
229
+ const collateralAPY = await this.getAPY({
230
+ asset: this.config.collateral,
231
+ isDebt: false,
232
+ });
161
233
  const apy = collateralAPY.apy * 0.8;
162
234
  return apy;
163
235
  }
@@ -170,58 +242,92 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
170
242
  // Get current positions
171
243
  this.vesuAdapter.networkConfig = this.config.networkConfig;
172
244
  this.vesuAdapter.pricer = this.config.pricer;
173
-
174
- const positions = await this.vesuAdapter.getPositions(this.config.networkConfig);
175
- const collateralPosition = positions.find(p => p.token.address.eq(collateral.address));
176
- const debtPosition = positions.find(p => p.token.address.eq(debt.address));
245
+
246
+ const positions = await this.vesuAdapter.getPositions(
247
+ this.config.networkConfig
248
+ );
249
+ const collateralPosition = positions.find((p) =>
250
+ p.token.address.eq(collateral.address)
251
+ );
252
+ const debtPosition = positions.find((p) =>
253
+ p.token.address.eq(debt.address)
254
+ );
177
255
 
178
256
  if (!collateralPosition || !debtPosition) {
179
- throw new Error('Could not find current positions');
257
+ throw new Error("Could not find current positions");
180
258
  }
181
259
 
182
260
  // Calculate max borrowable amount
183
261
  const maxBorrowableAPY = await this.maxBorrowableAPY();
184
- const maxBorrowable = await this.vesuAdapter.getMaxBorrowableByInterestRate(
185
- this.config.networkConfig,
186
- debt,
187
- maxBorrowableAPY
262
+ const maxBorrowable =
263
+ await this.vesuAdapter.getMaxBorrowableByInterestRate(
264
+ this.config.networkConfig,
265
+ debt,
266
+ maxBorrowableAPY
267
+ );
268
+ logger.verbose(
269
+ `VesuMultiplyAdapter: Max borrowable: ${maxBorrowable.toNumber()}`
270
+ );
271
+ const debtCap = await this.vesuAdapter.getDebtCap(
272
+ this.config.networkConfig
188
273
  );
189
- logger.verbose(`VesuMultiplyAdapter: Max borrowable: ${maxBorrowable.toNumber()}`);
190
- const debtCap = await this.vesuAdapter.getDebtCap(this.config.networkConfig);
191
274
  logger.verbose(`VesuMultiplyAdapter: Debt cap: ${debtCap.toNumber()}`);
192
275
  const actualMaxBorrowable = maxBorrowable.minimum(debtCap);
193
- logger.verbose(`VesuMultiplyAdapter: Actual max borrowable: ${actualMaxBorrowable.toNumber()}`);
276
+ logger.verbose(
277
+ `VesuMultiplyAdapter: Actual max borrowable: ${actualMaxBorrowable.toNumber()}`
278
+ );
194
279
 
195
280
  // Calculate max collateral that can be deposited based on LTV
196
- const maxLTV = await this.vesuAdapter.getLTVConfig(this.config.networkConfig);
197
- const collateralPrice = await this.config.pricer.getPrice(collateral.symbol);
281
+ const maxLTV = await this.vesuAdapter.getLTVConfig(
282
+ this.config.networkConfig
283
+ );
284
+ const collateralPrice = await this.config.pricer.getPrice(
285
+ collateral.symbol
286
+ );
198
287
  if (collateralPrice.price === 0) {
199
- throw new Error('Collateral price is 0');
288
+ throw new Error("Collateral price is 0");
200
289
  }
201
290
  const debtPrice = await this.config.pricer.getPrice(debt.symbol);
202
291
  if (debtPrice.price === 0) {
203
- throw new Error('Debt price is 0');
292
+ throw new Error("Debt price is 0");
204
293
  }
205
- const maxCollateralFromDebt = HealthFactorMath.getMinCollateralRequiredOnLooping(
206
- actualMaxBorrowable,
207
- debtPrice.price,
208
- this.config.targetHealthFactor,
209
- maxLTV,
210
- collateralPrice.price,
211
- collateral
212
- )
294
+ const maxCollateralFromDebt =
295
+ HealthFactorMath.getMinCollateralRequiredOnLooping(
296
+ actualMaxBorrowable,
297
+ debtPrice.price,
298
+ this.config.targetHealthFactor,
299
+ maxLTV,
300
+ collateralPrice.price,
301
+ collateral
302
+ );
213
303
 
214
- const maxDepositAmount = amount ? amount.minimum(maxCollateralFromDebt) : maxCollateralFromDebt;
304
+ const maxDepositAmount = amount
305
+ ? amount.minimum(maxCollateralFromDebt)
306
+ : maxCollateralFromDebt;
215
307
  const usdValue = await this.getUSDValue(collateral, maxDepositAmount);
216
- logger.verbose(`VesuMultiplyAdapter: Max deposit::USD value: ${usdValue}, amount: ${maxDepositAmount.toNumber()}`);
217
- const apys = await Promise.all([this.getAPY({ asset: collateral, isDebt: false }), this.getAPY({ asset: debt, isDebt: true })]);
218
- logger.verbose(`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`);
308
+ logger.verbose(
309
+ `VesuMultiplyAdapter: Max deposit::USD value: ${usdValue}, amount: ${maxDepositAmount.toNumber()}`
310
+ );
311
+ const apys = await Promise.all([
312
+ this.getAPY({ asset: collateral, isDebt: false }),
313
+ this.getAPY({ asset: debt, isDebt: true }),
314
+ ]);
315
+ logger.verbose(
316
+ `VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
317
+ );
219
318
 
220
319
  const borrowAmountUSD = actualMaxBorrowable.multipliedBy(debtPrice.price);
221
- logger.verbose(`VesuMultiplyAdapter: Borrow amount: ${actualMaxBorrowable.toNumber()}, borrow amount USD: ${borrowAmountUSD.toNumber()}`);
320
+ logger.verbose(
321
+ `VesuMultiplyAdapter: Borrow amount: ${actualMaxBorrowable.toNumber()}, borrow amount USD: ${borrowAmountUSD.toNumber()}`
322
+ );
222
323
  const netCollateralUSD = usdValue + borrowAmountUSD.toNumber();
223
- const netAPY = (apys[0].apy * netCollateralUSD + apys[1].apy * borrowAmountUSD.toNumber()) / (usdValue);
224
- logger.verbose(`VesuMultiplyAdapter: Max deposit amount: ${maxDepositAmount.toNumber()}, netAPY: ${netAPY}`);
324
+ const netAPY =
325
+ (apys[0].apy * netCollateralUSD +
326
+ apys[1].apy * borrowAmountUSD.toNumber()) /
327
+ usdValue;
328
+ logger.verbose(
329
+ `VesuMultiplyAdapter: Max deposit amount: ${maxDepositAmount.toNumber()}, netAPY: ${netAPY}`
330
+ );
225
331
  return {
226
332
  tokenInfo: collateral,
227
333
  amount: maxDepositAmount,
@@ -229,12 +335,15 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
229
335
  remarks: "Max deposit based on available debt capacity",
230
336
  apy: {
231
337
  apy: netAPY,
232
- type: APYType.BASE
338
+ type: APYType.BASE,
233
339
  },
234
- protocol: this.protocol
340
+ protocol: this.protocol,
235
341
  };
236
342
  } catch (error) {
237
- logger.error(`VesuMultiplyAdapter: Error calculating max deposit:`, error);
343
+ logger.error(
344
+ `VesuMultiplyAdapter: Error calculating max deposit:`,
345
+ error
346
+ );
238
347
  throw error;
239
348
  }
240
349
  }
@@ -247,28 +356,50 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
247
356
  // Calculate how much can be withdrawn without affecting health factor too much
248
357
  this.vesuAdapter.networkConfig = this.config.networkConfig;
249
358
  this.vesuAdapter.pricer = this.config.pricer;
250
-
251
- const positions = await this.vesuAdapter.getPositions(this.config.networkConfig);
252
- const collateralPosition = positions.find(p => p.token.address.eq(collateral.address));
253
- const debtPosition = positions.find(p => p.token.address.eq(this.config.debt.address));
359
+
360
+ const positions = await this.vesuAdapter.getPositions(
361
+ this.config.networkConfig
362
+ );
363
+ const collateralPosition = positions.find((p) =>
364
+ p.token.address.eq(collateral.address)
365
+ );
366
+ const debtPosition = positions.find((p) =>
367
+ p.token.address.eq(this.config.debt.address)
368
+ );
254
369
 
255
370
  if (!collateralPosition || !debtPosition) {
256
- throw new Error('Could not find current positions');
371
+ throw new Error("Could not find current positions");
257
372
  }
258
373
 
259
374
  // Calculate max withdrawable (conservative approach)
260
- const collateralPrice = collateralPosition.usdValue / collateralPosition.amount.toNumber();
375
+ const collateralPrice =
376
+ collateralPosition.usdValue / collateralPosition.amount.toNumber();
261
377
  const debtInCollateral = debtPosition.usdValue / collateralPrice;
262
378
  const maxWithdrawable = collateralPosition.amount.minus(debtInCollateral);
263
379
 
264
- const result = maxWithdrawable.greaterThan(0) ? maxWithdrawable : new Web3Number('0', collateral.decimals);
380
+ const result = maxWithdrawable.greaterThan(0)
381
+ ? maxWithdrawable
382
+ : new Web3Number("0", collateral.decimals);
265
383
  const usdValue = await this.getUSDValue(collateral, result);
266
384
  const debtUSD = debtPosition.usdValue;
267
- logger.verbose(`VesuMultiplyAdapter: Debt USD: ${debtUSD}, collateral USD: ${usdValue}`);
268
- const apys = await Promise.all([this.getAPY({ asset: collateral, isDebt: false }), this.getAPY({ asset: debt, isDebt: true })]);
269
- logger.verbose(`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`);
270
- const netAPY = (usdValue - debtUSD) > 0 ? (apys[0].apy * usdValue + apys[1].apy * debtUSD) / (usdValue - debtUSD) : 0;
271
- logger.verbose(`VesuMultiplyAdapter: Max withdraw amount: ${result.toNumber()}, netAPY: ${netAPY}`);
385
+ logger.verbose(
386
+ `VesuMultiplyAdapter: Debt USD: ${debtUSD}, collateral USD: ${usdValue}`
387
+ );
388
+ const apys = await Promise.all([
389
+ this.getAPY({ asset: collateral, isDebt: false }),
390
+ this.getAPY({ asset: debt, isDebt: true }),
391
+ ]);
392
+ logger.verbose(
393
+ `VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
394
+ );
395
+ const netAPY =
396
+ usdValue - debtUSD > 0
397
+ ? (apys[0].apy * usdValue + apys[1].apy * debtUSD) /
398
+ (usdValue - debtUSD)
399
+ : 0;
400
+ logger.verbose(
401
+ `VesuMultiplyAdapter: Max withdraw amount: ${result.toNumber()}, netAPY: ${netAPY}`
402
+ );
272
403
  return {
273
404
  tokenInfo: collateral,
274
405
  amount: result,
@@ -276,58 +407,71 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
276
407
  remarks: "Max withdraw based on health factor",
277
408
  apy: {
278
409
  apy: netAPY,
279
- type: APYType.BASE
410
+ type: APYType.BASE,
280
411
  },
281
- protocol: this.protocol
412
+ protocol: this.protocol,
282
413
  };
283
414
  } catch (error) {
284
- logger.error(`VesuMultiplyAdapter: Error calculating max withdraw:`, error);
415
+ logger.error(
416
+ `VesuMultiplyAdapter: Error calculating max withdraw:`,
417
+ error
418
+ );
285
419
  throw error;
286
420
  }
287
421
  }
288
422
 
289
423
  protected _getDepositLeaf(): {
290
- target: ContractAddr,
291
- method: string,
292
- packedArguments: bigint[],
293
- sanitizer: ContractAddr,
294
- id: string
424
+ target: ContractAddr;
425
+ method: string;
426
+ packedArguments: bigint[];
427
+ sanitizer: ContractAddr;
428
+ id: string;
295
429
  }[] {
296
430
  const collateral = this.config.collateral;
297
431
  const debt = this.config.debt;
298
- const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(this.config.poolId);
299
- const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
432
+ const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
433
+ this.config.poolId
434
+ );
435
+ const vesuMultiply = isV2
436
+ ? this.vesuAdapter.VESU_MULTIPLY
437
+ : this.vesuAdapter.VESU_MULTIPLY_V1;
300
438
 
301
439
  return [
302
440
  // Approval step for collateral
303
441
  {
304
442
  target: collateral.address,
305
- method: 'approve',
443
+ method: "approve",
306
444
  packedArguments: [
307
445
  vesuMultiply.toBigInt(), // spender
308
446
  ],
309
447
  sanitizer: SIMPLE_SANITIZER,
310
448
  // amc = approve multiply collateral
311
- id: `amc_${this.config.poolId.shortString()}_${collateral.symbol}_${debt.symbol}`
449
+ id: `amc_${this.config.poolId.shortString()}_${collateral.symbol}_${
450
+ debt.symbol
451
+ }`,
312
452
  },
313
453
  // Switch delegation on
314
454
  {
315
455
  target: vesuSingleton,
316
- method: 'modify_delegation',
317
- packedArguments: isV2 ? [
318
- vesuMultiply.toBigInt(), // delegatee
319
- ] : [
320
- this.config.poolId.toBigInt(),
321
- vesuMultiply.toBigInt(), // delegatee
322
- ],
456
+ method: "modify_delegation",
457
+ packedArguments: isV2
458
+ ? [
459
+ vesuMultiply.toBigInt(), // delegatee
460
+ ]
461
+ : [
462
+ this.config.poolId.toBigInt(),
463
+ vesuMultiply.toBigInt(), // delegatee
464
+ ],
323
465
  sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
324
466
  // sd1 = switch delegation on
325
- id: `sd1_${this.config.poolId.shortString()}_${collateral.symbol}_${debt.symbol}`
467
+ id: `sd1_${this.config.poolId.shortString()}_${collateral.symbol}_${
468
+ debt.symbol
469
+ }`,
326
470
  },
327
471
  // Vesu multiply call
328
472
  {
329
473
  target: vesuMultiply,
330
- method: 'modify_lever',
474
+ method: "modify_lever",
331
475
  packedArguments: [
332
476
  this.config.poolId.toBigInt(),
333
477
  collateral.address.toBigInt(),
@@ -336,34 +480,44 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
336
480
  ],
337
481
  sanitizer: SIMPLE_SANITIZER_V2,
338
482
  // vm = vesu multiply
339
- id: `vm_${this.config.poolId.shortString()}_${collateral.symbol}_${debt.symbol}`
483
+ id: `vm_${this.config.poolId.shortString()}_${collateral.symbol}_${
484
+ debt.symbol
485
+ }`,
340
486
  },
341
487
  // Switch delegation off
342
488
  {
343
489
  target: vesuSingleton,
344
- method: 'modify_delegation',
345
- packedArguments: isV2 ? [
346
- vesuMultiply.toBigInt(), // delegatee
347
- ] : [
348
- this.config.poolId.toBigInt(),
349
- vesuMultiply.toBigInt(), // delegatee
350
- ],
490
+ method: "modify_delegation",
491
+ packedArguments: isV2
492
+ ? [
493
+ vesuMultiply.toBigInt(), // delegatee
494
+ ]
495
+ : [
496
+ this.config.poolId.toBigInt(),
497
+ vesuMultiply.toBigInt(), // delegatee
498
+ ],
351
499
  sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
352
500
  // sd2 = switch delegation off
353
- id: `sd2_${this.config.poolId.shortString()}_${collateral.symbol}_${debt.symbol}`
354
- }
501
+ id: `sd2_${this.config.poolId.shortString()}_${collateral.symbol}_${
502
+ debt.symbol
503
+ }`,
504
+ },
355
505
  ];
356
506
  }
357
507
 
358
508
  protected _getWithdrawLeaf(): {
359
- target: ContractAddr,
360
- method: string,
361
- packedArguments: bigint[],
362
- sanitizer: ContractAddr,
363
- id: string
509
+ target: ContractAddr;
510
+ method: string;
511
+ packedArguments: bigint[];
512
+ sanitizer: ContractAddr;
513
+ id: string;
364
514
  }[] {
365
- const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(this.config.poolId);
366
- const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
515
+ const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
516
+ this.config.poolId
517
+ );
518
+ const vesuMultiply = isV2
519
+ ? this.vesuAdapter.VESU_MULTIPLY
520
+ : this.vesuAdapter.VESU_MULTIPLY_V1;
367
521
  const collateral = this.config.collateral;
368
522
  const debt = this.config.debt;
369
523
 
@@ -371,21 +525,25 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
371
525
  // Switch delegation on
372
526
  {
373
527
  target: vesuSingleton,
374
- method: 'modify_delegation',
375
- packedArguments: isV2 ? [
376
- vesuMultiply.toBigInt(), // delegatee
377
- ] : [
378
- this.config.poolId.toBigInt(),
379
- vesuMultiply.toBigInt(), // delegatee
380
- ],
528
+ method: "modify_delegation",
529
+ packedArguments: isV2
530
+ ? [
531
+ vesuMultiply.toBigInt(), // delegatee
532
+ ]
533
+ : [
534
+ this.config.poolId.toBigInt(),
535
+ vesuMultiply.toBigInt(), // delegatee
536
+ ],
381
537
  sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
382
538
  // sdow = switch delegation on withdraw
383
- id: `sdow_${this.config.poolId.shortString()}_${collateral.symbol}_${debt.symbol}`
539
+ id: `sdow_${this.config.poolId.shortString()}_${collateral.symbol}_${
540
+ debt.symbol
541
+ }`,
384
542
  },
385
543
  // Vesu multiply call
386
544
  {
387
545
  target: vesuMultiply,
388
- method: 'modify_lever',
546
+ method: "modify_lever",
389
547
  packedArguments: [
390
548
  this.config.poolId.toBigInt(),
391
549
  this.config.collateral.address.toBigInt(),
@@ -394,59 +552,85 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
394
552
  ],
395
553
  sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
396
554
  // vmw = vesu multiply withdraw
397
- id: `vmw_${this.config.poolId.shortString()}_${collateral.symbol}_${debt.symbol}`
555
+ id: `vmw_${this.config.poolId.shortString()}_${collateral.symbol}_${
556
+ debt.symbol
557
+ }`,
398
558
  },
399
559
  // Switch delegation off
400
560
  {
401
561
  target: vesuSingleton,
402
- method: 'modify_delegation',
403
- packedArguments: isV2 ? [
404
- vesuMultiply.toBigInt(), // delegatee
405
- ] : [
406
- this.config.poolId.toBigInt(),
407
- vesuMultiply.toBigInt(), // delegatee
408
- ],
562
+ method: "modify_delegation",
563
+ packedArguments: isV2
564
+ ? [
565
+ vesuMultiply.toBigInt(), // delegatee
566
+ ]
567
+ : [
568
+ this.config.poolId.toBigInt(),
569
+ vesuMultiply.toBigInt(), // delegatee
570
+ ],
409
571
  sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
410
572
  // sdofw = switch delegation off withdraw
411
- id: `sdofw_${this.config.poolId.shortString()}_${collateral.symbol}_${debt.symbol}`
412
- }
573
+ id: `sdofw_${this.config.poolId.shortString()}_${collateral.symbol}_${
574
+ debt.symbol
575
+ }`,
576
+ },
413
577
  ];
414
578
  }
415
579
 
416
580
  getDepositAdapter(): AdapterLeafType<DepositParams> {
417
581
  const leafConfigs = this._getDepositLeaf();
418
- const leaves = leafConfigs.map(config => {
582
+ const leaves = leafConfigs.map((config) => {
419
583
  const { target, method, packedArguments, sanitizer, id } = config;
420
- const leaf = this.constructSimpleLeafData({
421
- id: id,
422
- target,
423
- method,
424
- packedArguments
425
- }, sanitizer);
584
+ const leaf = this.constructSimpleLeafData(
585
+ {
586
+ id: id,
587
+ target,
588
+ method,
589
+ packedArguments,
590
+ },
591
+ sanitizer
592
+ );
426
593
  return leaf;
427
594
  });
428
- return { leaves, callConstructor: this.getDepositCall.bind(this) as unknown as GenerateCallFn<DepositParams> };
595
+ return {
596
+ leaves,
597
+ callConstructor: this.getDepositCall.bind(
598
+ this
599
+ ) as unknown as GenerateCallFn<DepositParams>,
600
+ };
429
601
  }
430
602
 
431
603
  getWithdrawAdapter(): AdapterLeafType<WithdrawParams> {
432
604
  const leafConfigs = this._getWithdrawLeaf();
433
- const leaves = leafConfigs.map(config => {
605
+ const leaves = leafConfigs.map((config) => {
434
606
  const { target, method, packedArguments, sanitizer, id } = config;
435
- const leaf = this.constructSimpleLeafData({
436
- id: id,
437
- target,
438
- method,
439
- packedArguments
440
- }, sanitizer);
607
+ const leaf = this.constructSimpleLeafData(
608
+ {
609
+ id: id,
610
+ target,
611
+ method,
612
+ packedArguments,
613
+ },
614
+ sanitizer
615
+ );
441
616
  return leaf;
442
617
  });
443
- return { leaves, callConstructor: this.getWithdrawCall.bind(this) as unknown as GenerateCallFn<WithdrawParams> };
618
+ return {
619
+ leaves,
620
+ callConstructor: this.getWithdrawCall.bind(
621
+ this
622
+ ) as unknown as GenerateCallFn<WithdrawParams>,
623
+ };
444
624
  }
445
625
 
446
626
  async getDepositCall(params: DepositParams): Promise<ManageCall[]> {
447
627
  const collateral = this.config.collateral;
448
- const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(this.config.poolId);
449
- const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
628
+ const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
629
+ this.config.poolId
630
+ );
631
+ const vesuMultiply = isV2
632
+ ? this.vesuAdapter.VESU_MULTIPLY
633
+ : this.vesuAdapter.VESU_MULTIPLY_V1;
450
634
 
451
635
  const uint256MarginAmount = uint256.bnToUint256(params.amount.toWei());
452
636
 
@@ -456,61 +640,69 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
456
640
  sanitizer: SIMPLE_SANITIZER,
457
641
  call: {
458
642
  contractAddress: collateral.address,
459
- selector: hash.getSelectorFromName('approve'),
643
+ selector: hash.getSelectorFromName("approve"),
460
644
  calldata: [
461
645
  vesuMultiply.toBigInt(), // spender
462
646
  toBigInt(uint256MarginAmount.low.toString()), // amount low
463
647
  toBigInt(uint256MarginAmount.high.toString()), // amount high
464
- ]
465
- }
648
+ ],
649
+ },
466
650
  },
467
651
  // Switch delegation on
468
652
  {
469
653
  sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
470
654
  call: {
471
655
  contractAddress: vesuSingleton,
472
- selector: hash.getSelectorFromName('modify_delegation'),
473
- calldata: isV2 ? [
474
- vesuMultiply.toBigInt(), // delegatee
475
- BigInt(1), // delegation: true
476
- ] : [
477
- this.config.poolId.toBigInt(),
478
- vesuMultiply.toBigInt(), // delegatee
479
- BigInt(1), // delegation: true
480
- ]
481
- }
656
+ selector: hash.getSelectorFromName("modify_delegation"),
657
+ calldata: isV2
658
+ ? [
659
+ vesuMultiply.toBigInt(), // delegatee
660
+ BigInt(1), // delegation: true
661
+ ]
662
+ : [
663
+ this.config.poolId.toBigInt(),
664
+ vesuMultiply.toBigInt(), // delegatee
665
+ BigInt(1), // delegation: true
666
+ ],
667
+ },
482
668
  },
483
669
  // Vesu multiply call
484
670
  {
485
671
  sanitizer: SIMPLE_SANITIZER_V2,
486
672
  call: {
487
673
  contractAddress: vesuMultiply,
488
- selector: hash.getSelectorFromName('modify_lever'),
489
- calldata: await this.getMultiplyCallCalldata(params, true)
490
- }
674
+ selector: hash.getSelectorFromName("modify_lever"),
675
+ calldata: await this.getMultiplyCallCalldata(params, true),
676
+ },
491
677
  },
492
678
  // Switch delegation off
493
679
  {
494
680
  sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
495
681
  call: {
496
682
  contractAddress: vesuSingleton,
497
- selector: hash.getSelectorFromName('modify_delegation'),
498
- calldata: isV2 ? [
499
- vesuMultiply.toBigInt(), // delegatee
500
- BigInt(0), // delegation: false
501
- ] : [
502
- this.config.poolId.toBigInt(),
503
- vesuMultiply.toBigInt(), // delegatee
504
- BigInt(0), // delegation: false
505
- ]
506
- }
507
- }
683
+ selector: hash.getSelectorFromName("modify_delegation"),
684
+ calldata: isV2
685
+ ? [
686
+ vesuMultiply.toBigInt(), // delegatee
687
+ BigInt(0), // delegation: false
688
+ ]
689
+ : [
690
+ this.config.poolId.toBigInt(),
691
+ vesuMultiply.toBigInt(), // delegatee
692
+ BigInt(0), // delegation: false
693
+ ],
694
+ },
695
+ },
508
696
  ];
509
697
  }
510
698
 
511
699
  async getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]> {
512
- const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(this.config.poolId);
513
- const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
700
+ const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
701
+ this.config.poolId
702
+ );
703
+ const vesuMultiply = isV2
704
+ ? this.vesuAdapter.VESU_MULTIPLY
705
+ : this.vesuAdapter.VESU_MULTIPLY_V1;
514
706
 
515
707
  return [
516
708
  // Switch delegation on
@@ -518,118 +710,191 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
518
710
  sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
519
711
  call: {
520
712
  contractAddress: vesuSingleton,
521
- selector: hash.getSelectorFromName('modify_delegation'),
522
- calldata: isV2 ? [
523
- vesuMultiply.toBigInt(), // delegatee
524
- BigInt(1), // delegation: true
525
- ] : [
526
- this.config.poolId.toBigInt(),
527
- vesuMultiply.toBigInt(), // delegatee
528
- BigInt(1), // delegation: true
529
- ]
530
- }
713
+ selector: hash.getSelectorFromName("modify_delegation"),
714
+ calldata: isV2
715
+ ? [
716
+ vesuMultiply.toBigInt(), // delegatee
717
+ BigInt(1), // delegation: true
718
+ ]
719
+ : [
720
+ this.config.poolId.toBigInt(),
721
+ vesuMultiply.toBigInt(), // delegatee
722
+ BigInt(1), // delegation: true
723
+ ],
724
+ },
531
725
  },
532
726
  // Vesu multiply call
533
727
  {
534
728
  sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
535
729
  call: {
536
730
  contractAddress: vesuMultiply,
537
- selector: hash.getSelectorFromName('modify_lever'),
538
- calldata: await this.getWithdrawalCalldata(params)
539
- }
731
+ selector: hash.getSelectorFromName("modify_lever"),
732
+ calldata: await this.getWithdrawalCalldata(params),
733
+ },
540
734
  },
541
735
  // Switch delegation off
542
736
  {
543
737
  sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
544
738
  call: {
545
739
  contractAddress: vesuSingleton,
546
- selector: hash.getSelectorFromName('modify_delegation'),
547
- calldata: isV2 ? [
548
- vesuMultiply.toBigInt(), // delegatee
549
- BigInt(0), // delegation: false
550
- ] : [
551
- this.config.poolId.toBigInt(),
552
- vesuMultiply.toBigInt(), // delegatee
553
- BigInt(0), // delegation: false
554
- ]
555
- }
556
- }
740
+ selector: hash.getSelectorFromName("modify_delegation"),
741
+ calldata: isV2
742
+ ? [
743
+ vesuMultiply.toBigInt(), // delegatee
744
+ BigInt(0), // delegation: false
745
+ ]
746
+ : [
747
+ this.config.poolId.toBigInt(),
748
+ vesuMultiply.toBigInt(), // delegatee
749
+ BigInt(0), // delegation: false
750
+ ],
751
+ },
752
+ },
557
753
  ];
558
754
  }
559
755
 
560
- private async getMultiplyCallCalldata(params: DepositParams | WithdrawParams, isDeposit: boolean): Promise<bigint[]> {
561
- logger.verbose(`${VesuMultiplyAdapter.name}::getMultiplyCallCalldata params: ${JSON.stringify(params)}, isDeposit: ${isDeposit}, collateral: ${this.config.collateral.symbol}, debt: ${this.config.debt.symbol}`);
756
+ private async getMultiplyCallCalldata(
757
+ params: DepositParams | WithdrawParams,
758
+ isDeposit: boolean
759
+ ): Promise<bigint[]> {
760
+ logger.verbose(
761
+ `${
762
+ VesuMultiplyAdapter.name
763
+ }::getMultiplyCallCalldata params: ${JSON.stringify(
764
+ params
765
+ )}, isDeposit: ${isDeposit}, collateral: ${
766
+ this.config.collateral.symbol
767
+ }, debt: ${this.config.debt.symbol}`
768
+ );
562
769
  const { isV2 } = getVesuSingletonAddress(this.config.poolId);
563
- const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
564
-
770
+ const vesuMultiply = isV2
771
+ ? this.vesuAdapter.VESU_MULTIPLY
772
+ : this.vesuAdapter.VESU_MULTIPLY_V1;
773
+
565
774
  // Create a temporary contract instance to populate the call
566
775
  const multiplyContract = new Contract({
567
- abi: VesuMultiplyAbi,
568
- address: vesuMultiply.address,
569
- providerOrAccount: this.config.networkConfig.provider
776
+ abi: VesuMultiplyAbi,
777
+ address: vesuMultiply.address,
778
+ providerOrAccount: this.config.networkConfig.provider,
570
779
  });
571
780
 
572
781
  // Configure swaps based on the operation
573
782
  let leverSwap: Swap[] = [];
574
783
  let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
575
784
 
576
- const existingPositions = await this.vesuAdapter.getPositions(this.config.networkConfig);
577
- const collateralisation = await this.vesuAdapter.getCollateralization(this.config.networkConfig);
785
+ const existingPositions = await this.vesuAdapter.getPositions(
786
+ this.config.networkConfig
787
+ );
788
+ const collateralisation = await this.vesuAdapter.getCollateralization(
789
+ this.config.networkConfig
790
+ );
578
791
  const existingCollateralInfo = existingPositions[0];
579
792
  const existingDebtInfo = existingPositions[1];
580
793
  const isDexPriceRequired = existingDebtInfo.token.symbol !== "USDC";
581
- logger.debug(`${VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(existingCollateralInfo)},
582
- existingDebtInfo: ${JSON.stringify(existingDebtInfo)}, collateralisation: ${JSON.stringify(collateralisation)}`);
794
+ logger.debug(`${
795
+ VesuMultiplyAdapter.name
796
+ }::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(
797
+ existingCollateralInfo
798
+ )},
799
+ existingDebtInfo: ${JSON.stringify(
800
+ existingDebtInfo
801
+ )}, collateralisation: ${JSON.stringify(collateralisation)}`);
583
802
 
584
803
  // - Prices as seen by Vesu contracts, ideal for HF math
585
- // Price 1 is ok as fallback bcz that would relatively price the
804
+ // Price 1 is ok as fallback bcz that would relatively price the
586
805
  // collateral and debt as equal.
587
- const collateralPrice = collateralisation[0].usdValue > 0 ?
588
- collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() :
589
- (await this.config.pricer.getPrice(this.config.collateral.symbol)).price;
590
- const debtPrice = collateralisation[1].usdValue > 0 ?
591
- collateralisation[1].usdValue / existingDebtInfo.amount.toNumber() :
592
- (await this.config.pricer.getPrice(this.config.debt.symbol)).price;
593
- logger.debug(`${VesuMultiplyAdapter.name}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`);
594
-
595
- const legLTV = await this.vesuAdapter.getLTVConfig(this.config.networkConfig);
596
- const ekuboQuoter = new EkuboQuoter(this.config.networkConfig, this.config.pricer);
597
- const dexPrice = isDexPriceRequired ? await ekuboQuoter.getDexPrice(this.config.collateral, this.config.debt, this.config.quoteAmountToFetchPrice) : 1;
598
- logger.verbose(`${VesuMultiplyAdapter.name}::getVesuMultiplyCall dexPrice: ${dexPrice}, ltv: ${legLTV}`);
806
+ const collateralPrice =
807
+ collateralisation[0].usdValue > 0
808
+ ? collateralisation[0].usdValue /
809
+ existingCollateralInfo.amount.toNumber()
810
+ : (await this.config.pricer.getPrice(this.config.collateral.symbol))
811
+ .price;
812
+ const debtPrice =
813
+ collateralisation[1].usdValue > 0
814
+ ? collateralisation[1].usdValue / existingDebtInfo.amount.toNumber()
815
+ : (await this.config.pricer.getPrice(this.config.debt.symbol)).price;
816
+ logger.debug(
817
+ `${VesuMultiplyAdapter.name}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`
818
+ );
819
+
820
+ const legLTV = await this.vesuAdapter.getLTVConfig(
821
+ this.config.networkConfig
822
+ );
823
+ const ekuboQuoter = new EkuboQuoter(
824
+ this.config.networkConfig,
825
+ this.config.pricer
826
+ );
827
+ const dexPrice = isDexPriceRequired
828
+ ? await ekuboQuoter.getDexPrice(
829
+ this.config.collateral,
830
+ this.config.debt,
831
+ this.config.quoteAmountToFetchPrice
832
+ )
833
+ : 1;
834
+ logger.verbose(
835
+ `${VesuMultiplyAdapter.name}::getVesuMultiplyCall dexPrice: ${dexPrice}, ltv: ${legLTV}`
836
+ );
599
837
 
600
838
  // compute optimal amount of collateral and debt post addition/removal
601
839
  // target hf = collateral * collateralPrice * ltv / debt * debtPrice
602
- // assuming X to be the usd amount of debt borrowed or repaied (negative).
840
+ // assuming X to be the usd amount of debt borrowed or repaied (negative).
603
841
  // target hf = (((collateral + legDepositAmount) * collateralPrice + X)) * ltv / (debt * debtPrice + X)
604
842
  // => X * target hf = (((collateral + legDepositAmount) * collateralPrice + X)) * ltv - (debt * debtPrice * target hf)
605
843
  // => X * (target hf - ltv)= ((collateral + legDepositAmount) * collateralPrice * ltv) - (debt * debtPrice * target hf)
606
844
  // => X = (((collateral + legDepositAmount) * collateralPrice * ltv) - (debt * debtPrice * target hf)) / (target hf - ltv)
607
845
 
608
- const addedCollateral = params.amount
609
- .multipliedBy(isDeposit ? 1 : -1)
610
- logger.verbose(`${VesuMultiplyAdapter.name}::getVesuMultiplyCall addedCollateral: ${addedCollateral}`);
611
- const numeratorPart1 = (existingCollateralInfo.amount.plus((addedCollateral))).multipliedBy(collateralPrice).multipliedBy(legLTV);
612
- logger.verbose(`${VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}`);
613
- const numeratorPart2 = existingDebtInfo.amount.multipliedBy(debtPrice).multipliedBy(this.config.targetHealthFactor);
614
- logger.verbose(`${VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart2: ${numeratorPart2}`);
615
- const denominatorPart = this.config.targetHealthFactor - (legLTV / dexPrice); // TODO Write reason for this. this dexPrice is some custom thing. this dexPrice is probably exchange rate (1 xWBTC in WBTC terms)
616
- logger.verbose(`${VesuMultiplyAdapter.name}::getVesuMultiplyCall denominatorPart: ${denominatorPart}`);
617
- const x_debt_usd = numeratorPart1.minus(numeratorPart2).dividedBy(denominatorPart);
618
- logger.verbose(`${VesuMultiplyAdapter.name}::getVesuMultiplyCall x_debt_usd: ${x_debt_usd}`);
619
- logger.debug(`${VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}, numeratorPart2: ${numeratorPart2}, denominatorPart: ${denominatorPart}`);
846
+ const addedCollateral = params.amount.multipliedBy(isDeposit ? 1 : -1);
847
+ logger.verbose(
848
+ `${VesuMultiplyAdapter.name}::getVesuMultiplyCall addedCollateral: ${addedCollateral}`
849
+ );
850
+ const numeratorPart1 = existingCollateralInfo.amount
851
+ .plus(addedCollateral)
852
+ .multipliedBy(collateralPrice)
853
+ .multipliedBy(legLTV);
854
+ logger.verbose(
855
+ `${VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}`
856
+ );
857
+ const numeratorPart2 = existingDebtInfo.amount
858
+ .multipliedBy(debtPrice)
859
+ .multipliedBy(this.config.targetHealthFactor);
860
+ logger.verbose(
861
+ `${VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart2: ${numeratorPart2}`
862
+ );
863
+ const denominatorPart = this.config.targetHealthFactor - legLTV / dexPrice; // TODO Write reason for this. this dexPrice is some custom thing. this dexPrice is probably exchange rate (1 xWBTC in WBTC terms)
864
+ logger.verbose(
865
+ `${VesuMultiplyAdapter.name}::getVesuMultiplyCall denominatorPart: ${denominatorPart}`
866
+ );
867
+ const x_debt_usd = numeratorPart1
868
+ .minus(numeratorPart2)
869
+ .dividedBy(denominatorPart);
870
+ logger.verbose(
871
+ `${VesuMultiplyAdapter.name}::getVesuMultiplyCall x_debt_usd: ${x_debt_usd}`
872
+ );
873
+ logger.debug(
874
+ `${VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}, numeratorPart2: ${numeratorPart2}, denominatorPart: ${denominatorPart}`
875
+ );
620
876
 
621
877
  // both in underlying
622
878
  // debtAmount in debt units
623
- let debtAmount = new Web3Number(x_debt_usd.dividedBy(debtPrice).toFixed(this.config.debt.decimals), this.config.debt.decimals);
879
+ let debtAmount = new Web3Number(
880
+ x_debt_usd.dividedBy(debtPrice).toFixed(this.config.debt.decimals),
881
+ this.config.debt.decimals
882
+ );
624
883
  const marginAmount = addedCollateral;
625
884
  const collateralToken = this.config.collateral;
626
885
  const debtToken = this.config.debt;
627
- const debtAmountInCollateralUnits = new Web3Number(debtAmount.multipliedBy(debtPrice).dividedBy(collateralPrice).multipliedBy(10 ** collateralToken.decimals).toFixed(0), collateralToken.decimals);
628
-
886
+ const debtAmountInCollateralUnits = new Web3Number(
887
+ debtAmount
888
+ .multipliedBy(debtPrice)
889
+ .dividedBy(collateralPrice)
890
+ .multipliedBy(10 ** collateralToken.decimals)
891
+ .toFixed(0),
892
+ collateralToken.decimals
893
+ );
894
+
629
895
  // increase multiply lever or not
630
896
  const isIncrease = debtAmount.greaterThanOrEqualTo(0);
631
897
 
632
-
633
898
  // due to directional limitations in multiply contract
634
899
  if (isIncrease && debtAmount.lessThan(0)) {
635
900
  // we are increasing lever but math says reduce debt
@@ -640,23 +905,37 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
640
905
  // - so just set debt 0
641
906
  debtAmount = Web3Number.fromWei(0, this.config.debt.decimals);
642
907
  }
643
- logger.verbose(`${VesuMultiplyAdapter.name}::getVesuMultiplyCall debtAmount: ${debtAmount}, marginAmount: ${marginAmount}`);
908
+ logger.verbose(
909
+ `${VesuMultiplyAdapter.name}::getVesuMultiplyCall debtAmount: ${debtAmount}, marginAmount: ${marginAmount}`
910
+ );
644
911
  if (!debtAmount.isZero()) {
645
912
  // Get swap quote for leverage operation
646
913
  // Determine swap direction based on operation type
647
-
648
- try {
914
+
915
+ try {
649
916
  const swapQuote = await ekuboQuoter.getQuote(
650
917
  collateralToken.address.address,
651
918
  debtToken.address.address,
652
- debtAmountInCollateralUnits.multipliedBy(-1)// negative for exact amount out
919
+ debtAmountInCollateralUnits.multipliedBy(-1) // negative for exact amount out
653
920
  );
654
-
921
+
655
922
  // todo add better slip checks
656
923
  // Check price impact
657
- if (swapQuote.price_impact < 0.01) { // 1% max price impact
924
+ if (swapQuote.price_impact < 0.01) {
925
+ // 1% max price impact
658
926
  // from and toToken param position reversed, to fetch the required quote and keep things generalised
659
- leverSwap = ekuboQuoter.getVesuMultiplyQuote(swapQuote, debtToken, collateralToken);
927
+
928
+ leverSwap = debtAmount.isNegative()
929
+ ? ekuboQuoter.getVesuMultiplyQuote(
930
+ swapQuote,
931
+ collateralToken,
932
+ debtToken
933
+ )
934
+ : ekuboQuoter.getVesuMultiplyQuote(
935
+ swapQuote,
936
+ debtToken,
937
+ collateralToken
938
+ );
660
939
  //console.log("leverSwap", leverSwap[-1].token_amount);
661
940
  //console.log(JSON.stringify(leverSwap));
662
941
  // Calculate limit amount with slippage protection
@@ -672,215 +951,309 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
672
951
  // For decrease: maximum amount of collateral used
673
952
  // from collateral token to debt token
674
953
  //leverSwapLimitAmount = await ekuboQuoter.getSwapLimitAmount(collateralToken, debtToken, debtAmountInCollateralUnits.multipliedBy(-1), MAX_SLIPPAGE);
675
- leverSwapLimitAmount = debtAmount.abs().multipliedBy(1 - MAX_SLIPPAGE);
954
+ leverSwapLimitAmount = debtAmount
955
+ .abs()
956
+ .multipliedBy(1 - MAX_SLIPPAGE);
676
957
  //console.log("anotherleverSwapLimitAmount", anotherleverSwapLimitAmount, leverSwapLimitAmount);
677
958
  } else {
678
- leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
959
+ leverSwapLimitAmount = Web3Number.fromWei(
960
+ 0,
961
+ this.config.debt.decimals
962
+ );
679
963
  }
680
964
  await new Promise((resolve) => setTimeout(resolve, 10000));
681
965
  //console.log("leverSwapLimitAmount", leverSwapLimitAmount);
682
966
  } else {
683
- throw new Error(`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`);
967
+ throw new Error(
968
+ `VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
969
+ );
684
970
  }
685
971
  } catch (error) {
686
- throw new Error(`VesuMultiplyAdapter: Failed to get swap quote: ${error}`);
972
+ throw new Error(
973
+ `VesuMultiplyAdapter: Failed to get swap quote: ${error}`
974
+ );
687
975
  }
688
976
  }
689
-
690
- const multiplyParams = await this.getLeverParams(isIncrease, params, leverSwap, leverSwapLimitAmount);
691
- const call = multiplyContract.populate('modify_lever', {
692
- modify_lever_params: this.formatMultiplyParams(isIncrease, multiplyParams)
977
+
978
+ const multiplyParams = await this.getLeverParams(
979
+ isIncrease,
980
+ params,
981
+ leverSwap,
982
+ leverSwapLimitAmount
983
+ );
984
+ const call = multiplyContract.populate("modify_lever", {
985
+ modify_lever_params: this.formatMultiplyParams(
986
+ isIncrease,
987
+ multiplyParams
988
+ ),
693
989
  });
694
990
 
695
991
  return call.calldata as bigint[];
696
992
  }
697
993
 
698
- private async getLeverParams(isIncrease: boolean, params: DepositParams | WithdrawParams, leverSwap: Swap[], leverSwapLimitAmount: Web3Number): Promise<IncreaseLeverParams | DecreaseLeverParams> {
699
- const multiplyParams: IncreaseLeverParams | DecreaseLeverParams = isIncrease ? {
700
- user: this.config.vaultAllocator,
701
- pool_id: this.config.poolId,
702
- collateral_asset: this.config.collateral.address,
703
- debt_asset: this.config.debt.address,
704
- recipient: this.config.vaultAllocator,
705
- add_margin: params.amount, // multiplied by collateral decimals in format
706
- margin_swap: [],
707
- margin_swap_limit_amount: Web3Number.fromWei(0, this.config.collateral.decimals),
708
- lever_swap: leverSwap,
709
- lever_swap_limit_amount: leverSwapLimitAmount
710
- } : {
711
- user: this.config.vaultAllocator,
712
- pool_id: this.config.poolId,
713
- collateral_asset: this.config.collateral.address,
714
- debt_asset: this.config.debt.address,
715
- recipient: this.config.vaultAllocator,
716
- sub_margin: params.amount,
717
- lever_swap: leverSwap,
718
- lever_swap_limit_amount: leverSwapLimitAmount,
719
- lever_swap_weights: [],
720
- withdraw_swap: [],
721
- withdraw_swap_limit_amount: Web3Number.fromWei(0, this.config.collateral.decimals),
722
- withdraw_swap_weights: [],
723
- close_position: false
724
- };
994
+ private async getLeverParams(
995
+ isIncrease: boolean,
996
+ params: DepositParams | WithdrawParams,
997
+ leverSwap: Swap[],
998
+ leverSwapLimitAmount: Web3Number
999
+ ): Promise<IncreaseLeverParams | DecreaseLeverParams> {
1000
+ const multiplyParams: IncreaseLeverParams | DecreaseLeverParams = isIncrease
1001
+ ? {
1002
+ user: this.config.vaultAllocator,
1003
+ pool_id: this.config.poolId,
1004
+ collateral_asset: this.config.collateral.address,
1005
+ debt_asset: this.config.debt.address,
1006
+ recipient: this.config.vaultAllocator,
1007
+ add_margin: params.amount, // multiplied by collateral decimals in format
1008
+ margin_swap: [],
1009
+ margin_swap_limit_amount: Web3Number.fromWei(
1010
+ 0,
1011
+ this.config.collateral.decimals
1012
+ ),
1013
+ lever_swap: leverSwap,
1014
+ lever_swap_limit_amount: leverSwapLimitAmount,
1015
+ }
1016
+ : {
1017
+ user: this.config.vaultAllocator,
1018
+ pool_id: this.config.poolId,
1019
+ collateral_asset: this.config.collateral.address,
1020
+ debt_asset: this.config.debt.address,
1021
+ recipient: this.config.vaultAllocator,
1022
+ sub_margin: params.amount,
1023
+ lever_swap: leverSwap,
1024
+ lever_swap_limit_amount: leverSwapLimitAmount,
1025
+ lever_swap_weights: [],
1026
+ withdraw_swap: [],
1027
+ withdraw_swap_limit_amount: Web3Number.fromWei(
1028
+ 0,
1029
+ this.config.collateral.decimals
1030
+ ),
1031
+ withdraw_swap_weights: [],
1032
+ close_position: false,
1033
+ };
725
1034
  return multiplyParams;
726
1035
  }
727
1036
 
728
- private async getWithdrawalCalldata(params: WithdrawParams): Promise<bigint[]> {
1037
+ private async getWithdrawalCalldata(
1038
+ params: WithdrawParams
1039
+ ): Promise<bigint[]> {
729
1040
  //params.amount must be in btc here
730
1041
  const { isV2 } = getVesuSingletonAddress(this.config.poolId);
731
- const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
1042
+ const vesuMultiply = isV2
1043
+ ? this.vesuAdapter.VESU_MULTIPLY
1044
+ : this.vesuAdapter.VESU_MULTIPLY_V1;
732
1045
  const multiplyContract = new Contract({
733
- abi: VesuMultiplyAbi,
734
- address: vesuMultiply.address,
735
- providerOrAccount: this.config.networkConfig.provider
1046
+ abi: VesuMultiplyAbi,
1047
+ address: vesuMultiply.address,
1048
+ providerOrAccount: this.config.networkConfig.provider,
736
1049
  });
737
1050
  let leverSwap: Swap[] = [];
738
1051
  let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
739
- const existingPositions = await this.vesuAdapter.getPositions(this.config.networkConfig);
1052
+ const existingPositions = await this.vesuAdapter.getPositions(
1053
+ this.config.networkConfig
1054
+ );
740
1055
  const existingCollateralInfo = existingPositions[0];
741
1056
  const existingDebtInfo = existingPositions[1];
742
1057
  const collateralToken = this.config.collateral;
743
1058
  const debtToken = this.config.debt;
744
- const collateralPrice = await this.config.pricer.getPrice(collateralToken.symbol);
1059
+ const collateralPrice = await this.config.pricer.getPrice(
1060
+ collateralToken.symbol
1061
+ );
745
1062
  const debtPrice = await this.config.pricer.getPrice(debtToken.symbol);
746
1063
  // the debt amount is negative as we are reducing debt to withdraw
747
1064
  const { deltadebtAmountUnits: debtAmountToRepay } =
748
- calculateDebtReductionAmountForWithdrawal(
749
- existingDebtInfo.amount,
750
- existingCollateralInfo.amount,
751
- MAX_LIQUIDATION_RATIO,
752
- params.amount,
753
- collateralPrice.price,
754
- debtPrice.price,
755
- debtToken.decimals
756
- );
1065
+ calculateDebtReductionAmountForWithdrawal(
1066
+ existingDebtInfo.amount,
1067
+ existingCollateralInfo.amount,
1068
+ MAX_LIQUIDATION_RATIO,
1069
+ params.amount,
1070
+ collateralPrice.price,
1071
+ debtPrice.price,
1072
+ debtToken.decimals
1073
+ );
757
1074
  //console.log("debtAmountToRepay", debtAmountToRepay);
758
- if(!debtAmountToRepay) {
1075
+ if (!debtAmountToRepay) {
759
1076
  throw new Error("error calculating debt amount to repay");
760
1077
  }
761
- const ekuboQuoter = new EkuboQuoter(this.config.networkConfig, this.config.pricer);
762
- const debtInDebtUnits = new Web3Number(debtAmountToRepay, debtToken.decimals).dividedBy(debtPrice.price).multipliedBy(10 ** debtToken.decimals);
1078
+ const ekuboQuoter = new EkuboQuoter(
1079
+ this.config.networkConfig,
1080
+ this.config.pricer
1081
+ );
1082
+ const debtInDebtUnits = new Web3Number(
1083
+ debtAmountToRepay,
1084
+ debtToken.decimals
1085
+ )
1086
+ .dividedBy(debtPrice.price)
1087
+ .multipliedBy(10 ** debtToken.decimals);
763
1088
  const swapQuote = await ekuboQuoter.getQuote(
764
1089
  debtToken.address.address,
765
1090
  collateralToken.address.address,
766
1091
  debtInDebtUnits
767
- )
1092
+ );
768
1093
  const MAX_SLIPPAGE = 0.002; // 0.2% slippag
769
- if(swapQuote.price_impact < 0.0025) {
770
- leverSwap = ekuboQuoter.getVesuMultiplyQuote(swapQuote, collateralToken, debtToken);
1094
+ if (swapQuote.price_impact < 0.0025) {
1095
+ leverSwap = ekuboQuoter.getVesuMultiplyQuote(
1096
+ swapQuote,
1097
+ collateralToken,
1098
+ debtToken
1099
+ );
771
1100
  } else {
772
- logger.error(`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`);
1101
+ logger.error(
1102
+ `VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
1103
+ );
773
1104
  }
774
1105
 
775
- leverSwapLimitAmount = new Web3Number(debtAmountToRepay, debtToken.decimals).abs().multipliedBy(1 + MAX_SLIPPAGE);
1106
+ leverSwapLimitAmount = new Web3Number(debtAmountToRepay, debtToken.decimals)
1107
+ .abs()
1108
+ .multipliedBy(1 + MAX_SLIPPAGE);
776
1109
  //leverSwapLimitAmount = await ekuboQuoter.getSwapLimitAmount(debtToken, collateralToken, debtInCollateralUnits, MAX_SLIPPAGE);
777
- const multiplyParams = await this.getLeverParams(false, params, leverSwap, leverSwapLimitAmount);
778
- const call = multiplyContract.populate('modify_lever', {
779
- modify_lever_params: this.formatMultiplyParams(false, multiplyParams)
1110
+ const multiplyParams = await this.getLeverParams(
1111
+ false,
1112
+ params,
1113
+ leverSwap,
1114
+ leverSwapLimitAmount
1115
+ );
1116
+ const call = multiplyContract.populate("modify_lever", {
1117
+ modify_lever_params: this.formatMultiplyParams(false, multiplyParams),
780
1118
  });
781
1119
  return call.calldata as bigint[];
782
1120
  }
783
1121
 
784
- formatMultiplyParams(isIncrease: boolean, params: IncreaseLeverParams | DecreaseLeverParams) {
1122
+ formatMultiplyParams(
1123
+ isIncrease: boolean,
1124
+ params: IncreaseLeverParams | DecreaseLeverParams
1125
+ ) {
785
1126
  if (isIncrease) {
786
1127
  const _params = params as IncreaseLeverParams;
787
1128
  return {
788
- action: new CairoCustomEnum({ IncreaseLever: {
1129
+ action: new CairoCustomEnum({
1130
+ IncreaseLever: {
1131
+ pool_id: _params.pool_id.toBigInt(),
1132
+ collateral_asset: _params.collateral_asset.toBigInt(),
1133
+ debt_asset: _params.debt_asset.toBigInt(),
1134
+ user: _params.user.toBigInt(),
1135
+ add_margin: BigInt(_params.add_margin.toWei()),
1136
+ margin_swap: _params.margin_swap.map((swap) => ({
1137
+ route: swap.route.map((route) => ({
1138
+ pool_key: {
1139
+ token0: route.pool_key.token0.toBigInt(),
1140
+ token1: route.pool_key.token1.toBigInt(),
1141
+ fee: route.pool_key.fee,
1142
+ tick_spacing: route.pool_key.tick_spacing,
1143
+ extension: BigInt(
1144
+ num.hexToDecimalString(route.pool_key.extension)
1145
+ ),
1146
+ },
1147
+ sqrt_ratio_limit: uint256.bnToUint256(
1148
+ route.sqrt_ratio_limit.toWei()
1149
+ ),
1150
+ skip_ahead: BigInt(100),
1151
+ })),
1152
+ token_amount: {
1153
+ token: swap.token_amount.token.toBigInt(),
1154
+ amount: swap.token_amount.amount.toI129(),
1155
+ },
1156
+ })),
1157
+ margin_swap_limit_amount: BigInt(
1158
+ _params.margin_swap_limit_amount.toWei()
1159
+ ),
1160
+ lever_swap: _params.lever_swap.map((swap) => ({
1161
+ route: swap.route.map((route) => ({
1162
+ pool_key: {
1163
+ token0: route.pool_key.token0.toBigInt(),
1164
+ token1: route.pool_key.token1.toBigInt(),
1165
+ fee: route.pool_key.fee,
1166
+ tick_spacing: route.pool_key.tick_spacing,
1167
+ extension: BigInt(
1168
+ num.hexToDecimalString(route.pool_key.extension)
1169
+ ),
1170
+ },
1171
+ sqrt_ratio_limit: uint256.bnToUint256(
1172
+ route.sqrt_ratio_limit.toWei()
1173
+ ),
1174
+ skip_ahead: BigInt(0),
1175
+ })),
1176
+ token_amount: {
1177
+ token: swap.token_amount.token.toBigInt(),
1178
+ amount: swap.token_amount.amount.toI129(),
1179
+ },
1180
+ })),
1181
+ lever_swap_limit_amount: BigInt(
1182
+ _params.lever_swap_limit_amount.toWei()
1183
+ ),
1184
+ },
1185
+ }),
1186
+ };
1187
+ }
1188
+
1189
+ const _params = params as DecreaseLeverParams;
1190
+ return {
1191
+ action: new CairoCustomEnum({
1192
+ DecreaseLever: {
789
1193
  pool_id: _params.pool_id.toBigInt(),
790
1194
  collateral_asset: _params.collateral_asset.toBigInt(),
791
1195
  debt_asset: _params.debt_asset.toBigInt(),
792
1196
  user: _params.user.toBigInt(),
793
- add_margin: BigInt(_params.add_margin.toWei()),
794
- margin_swap: _params.margin_swap.map(swap => ({
795
- route: swap.route.map(route => ({
1197
+ sub_margin: BigInt(_params.sub_margin.toWei()),
1198
+ recipient: _params.recipient.toBigInt(),
1199
+ lever_swap: _params.lever_swap.map((swap) => ({
1200
+ route: swap.route.map((route) => ({
796
1201
  pool_key: {
797
1202
  token0: route.pool_key.token0.toBigInt(),
798
1203
  token1: route.pool_key.token1.toBigInt(),
799
1204
  fee: route.pool_key.fee,
800
1205
  tick_spacing: route.pool_key.tick_spacing,
801
- extension: BigInt(num.hexToDecimalString(route.pool_key.extension)),
1206
+ extension: ContractAddr.from(
1207
+ route.pool_key.extension
1208
+ ).toBigInt(),
802
1209
  },
803
- sqrt_ratio_limit: uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
804
- skip_ahead: BigInt(100)
1210
+ sqrt_ratio_limit: uint256.bnToUint256(
1211
+ route.sqrt_ratio_limit.toWei()
1212
+ ),
1213
+ skip_ahead: BigInt(route.skip_ahead.toWei()),
805
1214
  })),
806
1215
  token_amount: {
807
1216
  token: swap.token_amount.token.toBigInt(),
808
- amount: swap.token_amount.amount.toI129()
809
- }
1217
+ amount: swap.token_amount.amount.toI129(),
1218
+ },
810
1219
  })),
811
- margin_swap_limit_amount: BigInt(_params.margin_swap_limit_amount.toWei()),
812
- lever_swap: _params.lever_swap.map(swap => ({
813
- route: swap.route.map(route => ({
1220
+ lever_swap_limit_amount: BigInt(
1221
+ _params.lever_swap_limit_amount.toWei()
1222
+ ),
1223
+ lever_swap_weights: _params.lever_swap_weights.map((weight) =>
1224
+ BigInt(weight.toWei())
1225
+ ),
1226
+ withdraw_swap: _params.withdraw_swap.map((swap) => ({
1227
+ route: swap.route.map((route) => ({
814
1228
  pool_key: {
815
1229
  token0: route.pool_key.token0.toBigInt(),
816
1230
  token1: route.pool_key.token1.toBigInt(),
817
1231
  fee: route.pool_key.fee,
818
1232
  tick_spacing: route.pool_key.tick_spacing,
819
- extension: BigInt(num.hexToDecimalString(route.pool_key.extension)),
1233
+ extension: ContractAddr.from(
1234
+ route.pool_key.extension
1235
+ ).toBigInt(),
820
1236
  },
821
- sqrt_ratio_limit: uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
822
- skip_ahead: BigInt(0)
1237
+ sqrt_ratio_limit: uint256.bnToUint256(
1238
+ route.sqrt_ratio_limit.toWei()
1239
+ ),
1240
+ skip_ahead: BigInt(route.skip_ahead.toWei()),
823
1241
  })),
824
1242
  token_amount: {
825
1243
  token: swap.token_amount.token.toBigInt(),
826
- amount: swap.token_amount.amount.toI129()
827
- }
828
- })),
829
- lever_swap_limit_amount: BigInt(_params.lever_swap_limit_amount.toWei()),
830
- } }),
831
- }
832
- }
833
-
834
- const _params = params as DecreaseLeverParams;
835
- return {
836
- action: new CairoCustomEnum({ DecreaseLever: {
837
- pool_id: _params.pool_id.toBigInt(),
838
- collateral_asset: _params.collateral_asset.toBigInt(),
839
- debt_asset: _params.debt_asset.toBigInt(),
840
- user: _params.user.toBigInt(),
841
- sub_margin: BigInt(_params.sub_margin.toWei()),
842
- recipient: _params.recipient.toBigInt(),
843
- lever_swap: _params.lever_swap.map(swap => ({
844
- route: swap.route.map(route => ({
845
- pool_key: {
846
- token0: route.pool_key.token0.toBigInt(),
847
- token1: route.pool_key.token1.toBigInt(),
848
- fee: route.pool_key.fee,
849
- tick_spacing: route.pool_key.tick_spacing,
850
- extension: ContractAddr.from(route.pool_key.extension).toBigInt(),
851
- },
852
- sqrt_ratio_limit: uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
853
- skip_ahead: BigInt(route.skip_ahead.toWei())
854
- })),
855
- token_amount: {
856
- token: swap.token_amount.token.toBigInt(),
857
- amount: swap.token_amount.amount.toI129()
858
- }
859
- })),
860
- lever_swap_limit_amount: BigInt(_params.lever_swap_limit_amount.toWei()),
861
- lever_swap_weights: _params.lever_swap_weights.map(weight => BigInt(weight.toWei())),
862
- withdraw_swap: _params.withdraw_swap.map(swap => ({
863
- route: swap.route.map(route => ({
864
- pool_key: {
865
- token0: route.pool_key.token0.toBigInt(),
866
- token1: route.pool_key.token1.toBigInt(),
867
- fee: route.pool_key.fee,
868
- tick_spacing: route.pool_key.tick_spacing,
869
- extension: ContractAddr.from(route.pool_key.extension).toBigInt(),
1244
+ amount: swap.token_amount.amount.toI129(),
870
1245
  },
871
- sqrt_ratio_limit: uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
872
- skip_ahead: BigInt(route.skip_ahead.toWei())
873
1246
  })),
874
- token_amount: {
875
- token: swap.token_amount.token.toBigInt(),
876
- amount: swap.token_amount.amount.toI129()
877
- }
878
- })),
879
- withdraw_swap_limit_amount: BigInt(_params.withdraw_swap_limit_amount.toWei()),
880
- withdraw_swap_weights: _params.withdraw_swap_weights.map(weight => BigInt(weight.toWei())),
881
- close_position: _params.close_position,
882
- }}),
883
- }
1247
+ withdraw_swap_limit_amount: BigInt(
1248
+ _params.withdraw_swap_limit_amount.toWei()
1249
+ ),
1250
+ withdraw_swap_weights: _params.withdraw_swap_weights.map((weight) =>
1251
+ BigInt(weight.toWei())
1252
+ ),
1253
+ close_position: _params.close_position,
1254
+ },
1255
+ }),
1256
+ };
884
1257
  }
885
1258
 
886
1259
  async getHealthFactor(): Promise<number> {
@@ -890,15 +1263,19 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
890
1263
 
891
1264
  async getNetAPY(): Promise<number> {
892
1265
  const positions = await this.getPositions();
893
- logger.verbose(`${this.name}::getNetAPY: positions: ${JSON.stringify(positions)}`);
894
- const allZero = positions.every(p => p.usdValue === 0);
1266
+ logger.verbose(
1267
+ `${this.name}::getNetAPY: positions: ${JSON.stringify(positions)}`
1268
+ );
1269
+ const allZero = positions.every((p) => p.usdValue === 0);
895
1270
 
896
1271
  // in case of zero positions, apy will come zero/NaN
897
1272
  // bcz of net 0 zero weights
898
1273
  if (allZero) {
899
1274
  // use approx dummy usd values to compute netAPY
900
1275
  const collateralUSD = 1000;
901
- const maxLTV = await this.vesuAdapter.getLTVConfig(this.config.networkConfig);
1276
+ const maxLTV = await this.vesuAdapter.getLTVConfig(
1277
+ this.config.networkConfig
1278
+ );
902
1279
  const targetHF = this.config.targetHealthFactor;
903
1280
  const maxDebt = HealthFactorMath.getMaxDebtAmountOnLooping(
904
1281
  new Web3Number(collateralUSD, this.config.collateral.decimals),
@@ -907,17 +1284,22 @@ export class VesuMultiplyAdapter extends BaseAdapter<DepositParams, WithdrawPara
907
1284
  targetHF,
908
1285
  1, // assume price 1 for simplicity
909
1286
  this.config.debt
910
- )
1287
+ );
911
1288
 
912
1289
  // debt is also added to collateral bcz, we assume debt is swapped to collateral
913
1290
  const debtUSD = maxDebt.multipliedBy(1); // assume price 1 for simplicity
914
- const netAPY = (positions[0].apy.apy * (collateralUSD + debtUSD.toNumber()) + positions[1].apy.apy * debtUSD.toNumber()) / (collateralUSD);
1291
+ const netAPY =
1292
+ (positions[0].apy.apy * (collateralUSD + debtUSD.toNumber()) +
1293
+ positions[1].apy.apy * debtUSD.toNumber()) /
1294
+ collateralUSD;
915
1295
  return netAPY;
916
1296
  }
917
1297
 
918
1298
  // Return true APY
919
1299
  const netAmount = positions.reduce((acc, curr) => acc + curr.usdValue, 0);
920
- const netAPY = positions.reduce((acc, curr) => acc + curr.apy.apy * curr.usdValue, 0) / netAmount;
1300
+ const netAPY =
1301
+ positions.reduce((acc, curr) => acc + curr.apy.apy * curr.usdValue, 0) /
1302
+ netAmount;
921
1303
  logger.verbose(`${this.name}::getNetAPY: netAPY: ${netAPY}`);
922
1304
  return netAPY;
923
1305
  }