@strkfarm/sdk 2.0.0-dev.21 → 2.0.0-dev.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.global.js +887 -262
- package/dist/index.browser.mjs +813 -188
- package/dist/index.d.ts +24 -2
- package/dist/index.js +814 -188
- package/dist/index.mjs +813 -188
- package/package.json +1 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +2 -1
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +1 -0
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +32 -2
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +1144 -337
|
@@ -8,12 +8,21 @@ import {
|
|
|
8
8
|
UNIVERSAL_MANAGE_IDS,
|
|
9
9
|
UniversalStrategySettings,
|
|
10
10
|
} from "../universal-strategy";
|
|
11
|
-
import { calculateExtendedLevergae } from "./utils/helper";
|
|
11
|
+
import { calculateDebtAmount, calculateDeltaDebtAmount, calculateExtendedLevergae } from "./utils/helper";
|
|
12
12
|
import { logger } from "@/utils";
|
|
13
13
|
import { AUDIT_URL } from "../universal-lst-muliplier-strategy";
|
|
14
14
|
import { getNoRiskTags } from "@/interfaces";
|
|
15
15
|
import { _riskFactor } from "../universal-lst-muliplier-strategy";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
BUFFER_USDC_IN_WITHDRAWAL,
|
|
18
|
+
LIMIT_BALANCE,
|
|
19
|
+
LIMIT_BALANCE_VALUE,
|
|
20
|
+
MAX_LTV_BTC_USDC,
|
|
21
|
+
MINIMUM_EXTENDED_POSITION_SIZE,
|
|
22
|
+
USDC_TOKEN_DECIMALS,
|
|
23
|
+
WALLET_ADDRESS,
|
|
24
|
+
WBTC_TOKEN_DECIMALS,
|
|
25
|
+
} from "./utils/constants";
|
|
17
26
|
import { CycleType } from "./types/transaction-metadata";
|
|
18
27
|
import { PricerBase } from "@/modules/pricerBase";
|
|
19
28
|
import { ContractAddr, Web3Number } from "@/dataTypes";
|
|
@@ -22,7 +31,10 @@ import { ERC20 } from "@/modules";
|
|
|
22
31
|
import { Balance, OrderSide } from "@/modules/ExtendedWrapperSDk";
|
|
23
32
|
import { Protocols } from "@/interfaces";
|
|
24
33
|
import { MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP } from "./utils/constants";
|
|
25
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
getInvestmentSteps,
|
|
36
|
+
getFAQs,
|
|
37
|
+
} from "../universal-lst-muliplier-strategy";
|
|
26
38
|
import { getContractDetails } from "../universal-strategy";
|
|
27
39
|
import { highlightTextWithLinks } from "@/interfaces";
|
|
28
40
|
import { PositionInfo } from "../universal-adapters";
|
|
@@ -50,13 +62,15 @@ import {
|
|
|
50
62
|
calculateAmountDistribution,
|
|
51
63
|
calculateAmountDistributionForWithdrawal,
|
|
52
64
|
calculateVesuLeverage,
|
|
53
|
-
calculateVesUPositionSizeGivenExtended
|
|
65
|
+
calculateVesUPositionSizeGivenExtended,
|
|
54
66
|
} from "./utils/helper";
|
|
55
67
|
import { SingleTokenInfo } from "../base-strategy";
|
|
56
68
|
import { Call } from "starknet";
|
|
57
69
|
import { PositionTypeAvnuExtended } from "../universal-strategy";
|
|
58
|
-
import {
|
|
59
|
-
|
|
70
|
+
import {
|
|
71
|
+
TransactionMetadata,
|
|
72
|
+
TransactionResult,
|
|
73
|
+
} from "./types/transaction-metadata";
|
|
60
74
|
|
|
61
75
|
export interface VesuExtendedStrategySettings
|
|
62
76
|
extends UniversalStrategySettings {
|
|
@@ -71,10 +85,11 @@ export interface VesuExtendedStrategySettings
|
|
|
71
85
|
}
|
|
72
86
|
|
|
73
87
|
export class VesuExtendedMultiplierStrategy<
|
|
74
|
-
|
|
75
|
-
>
|
|
88
|
+
S extends VesuExtendedStrategySettings
|
|
89
|
+
>
|
|
76
90
|
extends SVKStrategy<S>
|
|
77
|
-
implements Operations
|
|
91
|
+
implements Operations
|
|
92
|
+
{
|
|
78
93
|
constructor(
|
|
79
94
|
config: IConfig,
|
|
80
95
|
pricer: PricerBase,
|
|
@@ -122,8 +137,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
122
137
|
usdceToken.decimals
|
|
123
138
|
);
|
|
124
139
|
const price = await this.pricer.getPrice(usdceToken.symbol);
|
|
125
|
-
const usdValue =
|
|
126
|
-
Number(balance.toFixed(usdceToken.decimals)) * price.price;
|
|
140
|
+
const usdValue = Number(balance.toFixed(usdceToken.decimals)) * price.price;
|
|
127
141
|
return {
|
|
128
142
|
tokenInfo: usdceToken,
|
|
129
143
|
amount: balance,
|
|
@@ -131,7 +145,6 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
131
145
|
};
|
|
132
146
|
}
|
|
133
147
|
|
|
134
|
-
|
|
135
148
|
async getUnusedBalanceWBTC(): Promise<SingleTokenInfo> {
|
|
136
149
|
const collateralToken = this.metadata.additionalInfo.borrowable_assets[0]!;
|
|
137
150
|
const balance = await new ERC20(this.config).balanceOf(
|
|
@@ -182,9 +195,12 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
182
195
|
return extendedAdapter.adapter as ExtendedAdapter;
|
|
183
196
|
}
|
|
184
197
|
|
|
185
|
-
async moveAssetsToVaultAllocator(
|
|
186
|
-
|
|
187
|
-
|
|
198
|
+
async moveAssetsToVaultAllocator(
|
|
199
|
+
amount: Web3Number,
|
|
200
|
+
extendedAdapter: ExtendedAdapter
|
|
201
|
+
): Promise<{
|
|
202
|
+
calls: Call[];
|
|
203
|
+
status: boolean;
|
|
188
204
|
}> {
|
|
189
205
|
try {
|
|
190
206
|
const usdceToken = Global.getDefaultTokens().find(
|
|
@@ -195,12 +211,22 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
195
211
|
WALLET_ADDRESS,
|
|
196
212
|
usdceToken.decimals
|
|
197
213
|
);
|
|
198
|
-
logger.info(
|
|
214
|
+
logger.info(
|
|
215
|
+
`${VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator walletBalance: ${walletBalance}`
|
|
216
|
+
);
|
|
199
217
|
const amountToBeTransferred = amount.minimum(walletBalance);
|
|
200
|
-
logger.info(
|
|
201
|
-
|
|
218
|
+
logger.info(
|
|
219
|
+
`${
|
|
220
|
+
VesuExtendedMultiplierStrategy.name
|
|
221
|
+
}::moveAssetsToVaultAllocator amountToBeTransferred: ${amountToBeTransferred.toNumber()}`
|
|
222
|
+
);
|
|
223
|
+
|
|
202
224
|
if (amountToBeTransferred.lessThan(0)) {
|
|
203
|
-
logger.error(
|
|
225
|
+
logger.error(
|
|
226
|
+
`${
|
|
227
|
+
VesuExtendedMultiplierStrategy.name
|
|
228
|
+
}::moveAssetsToVaultAllocator amountToBeTransferred is less than 0: ${amountToBeTransferred.toNumber()}`
|
|
229
|
+
);
|
|
204
230
|
return {
|
|
205
231
|
calls: [],
|
|
206
232
|
status: false,
|
|
@@ -246,12 +272,19 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
246
272
|
collateralPrice: number;
|
|
247
273
|
debtPrice: number;
|
|
248
274
|
vesuLeverage: number;
|
|
275
|
+
debtAmountToBeRepaid: Web3Number;
|
|
249
276
|
}> {
|
|
250
277
|
try {
|
|
251
|
-
logger.info(
|
|
278
|
+
logger.info(
|
|
279
|
+
`${VesuExtendedMultiplierStrategy.name}::shouldInvest starting`
|
|
280
|
+
);
|
|
252
281
|
const vesuAdapter = await this.getVesuAdapter();
|
|
253
282
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
254
|
-
logger.info(
|
|
283
|
+
logger.info(
|
|
284
|
+
`${
|
|
285
|
+
VesuExtendedMultiplierStrategy.name
|
|
286
|
+
}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`
|
|
287
|
+
);
|
|
255
288
|
|
|
256
289
|
if (!vesuAdapter) {
|
|
257
290
|
logger.error(
|
|
@@ -265,6 +298,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
265
298
|
collateralPrice: 0,
|
|
266
299
|
debtPrice: 0,
|
|
267
300
|
vesuLeverage: 0,
|
|
301
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
268
302
|
};
|
|
269
303
|
}
|
|
270
304
|
if (!extendedAdapter) {
|
|
@@ -279,6 +313,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
279
313
|
collateralPrice: 0,
|
|
280
314
|
debtPrice: 0,
|
|
281
315
|
vesuLeverage: 0,
|
|
316
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
282
317
|
};
|
|
283
318
|
}
|
|
284
319
|
if (!extendedAdapter.client) {
|
|
@@ -293,10 +328,13 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
293
328
|
collateralPrice: 0,
|
|
294
329
|
debtPrice: 0,
|
|
295
330
|
vesuLeverage: 0,
|
|
331
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
296
332
|
};
|
|
297
333
|
}
|
|
298
334
|
|
|
299
|
-
logger.info(
|
|
335
|
+
logger.info(
|
|
336
|
+
`${VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`
|
|
337
|
+
);
|
|
300
338
|
const balance = await this.getUnusedBalance();
|
|
301
339
|
|
|
302
340
|
if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
|
|
@@ -311,14 +349,23 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
311
349
|
collateralPrice: 0,
|
|
312
350
|
debtPrice: 0,
|
|
313
351
|
vesuLeverage: 0,
|
|
352
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
314
353
|
};
|
|
315
354
|
}
|
|
316
|
-
logger.info(
|
|
317
|
-
|
|
355
|
+
logger.info(
|
|
356
|
+
`${VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`
|
|
357
|
+
);
|
|
358
|
+
const usdcBalanceOnExtended =
|
|
359
|
+
await extendedAdapter.getExtendedDepositAmount();
|
|
318
360
|
|
|
319
361
|
if (usdcBalanceOnExtended) {
|
|
320
|
-
const availableForWithdrawal = parseFloat(
|
|
321
|
-
|
|
362
|
+
const availableForWithdrawal = parseFloat(
|
|
363
|
+
usdcBalanceOnExtended.availableForWithdrawal
|
|
364
|
+
);
|
|
365
|
+
if (
|
|
366
|
+
!Number.isFinite(availableForWithdrawal) ||
|
|
367
|
+
availableForWithdrawal < 0
|
|
368
|
+
) {
|
|
322
369
|
logger.error(
|
|
323
370
|
`Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
324
371
|
);
|
|
@@ -330,13 +377,18 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
330
377
|
collateralPrice: 0,
|
|
331
378
|
debtPrice: 0,
|
|
332
379
|
vesuLeverage: 0,
|
|
380
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
333
381
|
};
|
|
334
382
|
}
|
|
335
383
|
}
|
|
336
384
|
|
|
337
385
|
/** The LIMIT_BALANCE is the bffer amount to keep in the investing Cycle */
|
|
338
|
-
const amountToInvest = new Web3Number(
|
|
339
|
-
|
|
386
|
+
const amountToInvest = new Web3Number(
|
|
387
|
+
balance.usdValue,
|
|
388
|
+
USDC_TOKEN_DECIMALS
|
|
389
|
+
)
|
|
390
|
+
.plus(usdcBalanceOnExtended?.availableForTrade ?? 0)
|
|
391
|
+
.multipliedBy(1 - LIMIT_BALANCE);
|
|
340
392
|
|
|
341
393
|
const amountToInvestNumber = amountToInvest.toNumber();
|
|
342
394
|
if (!Number.isFinite(amountToInvestNumber)) {
|
|
@@ -351,10 +403,14 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
351
403
|
collateralPrice: 0,
|
|
352
404
|
debtPrice: 0,
|
|
353
405
|
vesuLeverage: 0,
|
|
406
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
354
407
|
};
|
|
355
408
|
}
|
|
356
409
|
|
|
357
|
-
logger.info(
|
|
410
|
+
logger.info(
|
|
411
|
+
`${VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`
|
|
412
|
+
);
|
|
413
|
+
|
|
358
414
|
if (amountToInvest.lessThan(LIMIT_BALANCE_VALUE)) {
|
|
359
415
|
return {
|
|
360
416
|
shouldInvest: false,
|
|
@@ -364,6 +420,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
364
420
|
collateralPrice: 0,
|
|
365
421
|
debtPrice: 0,
|
|
366
422
|
vesuLeverage: 0,
|
|
423
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
367
424
|
};
|
|
368
425
|
}
|
|
369
426
|
|
|
@@ -378,18 +435,18 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
378
435
|
collateralPrice: 0,
|
|
379
436
|
debtPrice: 0,
|
|
380
437
|
vesuLeverage: 0,
|
|
438
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
381
439
|
};
|
|
382
440
|
}
|
|
383
|
-
const { collateralTokenAmount } =
|
|
441
|
+
const { collateralTokenAmount, debtTokenAmount } =
|
|
384
442
|
await vesuAdapter.vesuAdapter.getAssetPrices();
|
|
385
443
|
|
|
386
|
-
const {
|
|
387
|
-
collateralPrice,
|
|
388
|
-
debtPrice
|
|
389
|
-
} = await this.getAssetPrices();
|
|
444
|
+
const { collateralPrice, debtPrice } = await this.getAssetPrices();
|
|
390
445
|
|
|
391
|
-
|
|
392
|
-
|
|
446
|
+
if (
|
|
447
|
+
!Number.isFinite(collateralPrice.price) ||
|
|
448
|
+
collateralPrice.price <= 0
|
|
449
|
+
) {
|
|
393
450
|
logger.error(
|
|
394
451
|
`Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
|
|
395
452
|
);
|
|
@@ -401,6 +458,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
401
458
|
collateralPrice: 0,
|
|
402
459
|
debtPrice: 0,
|
|
403
460
|
vesuLeverage: 0,
|
|
461
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
404
462
|
};
|
|
405
463
|
}
|
|
406
464
|
if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
|
|
@@ -415,12 +473,35 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
415
473
|
collateralPrice: 0,
|
|
416
474
|
debtPrice: 0,
|
|
417
475
|
vesuLeverage: 0,
|
|
476
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
418
477
|
};
|
|
419
478
|
}
|
|
420
479
|
|
|
480
|
+
const debtAmountToBeRepaid = calculateDeltaDebtAmount(
|
|
481
|
+
MAX_LTV_BTC_USDC,
|
|
482
|
+
collateralTokenAmount,
|
|
483
|
+
debtTokenAmount,
|
|
484
|
+
collateralPrice.price,
|
|
485
|
+
debtPrice.price,
|
|
486
|
+
this.metadata.additionalInfo.targetHealthFactor
|
|
487
|
+
);
|
|
488
|
+
if (!debtAmountToBeRepaid) {
|
|
489
|
+
logger.error("error calculating debt amount to be repaid");
|
|
490
|
+
return {
|
|
491
|
+
shouldInvest: false,
|
|
492
|
+
vesuAmount: new Web3Number(0, 0),
|
|
493
|
+
extendedAmount: new Web3Number(0, 0),
|
|
494
|
+
extendedLeverage: 0,
|
|
495
|
+
collateralPrice: 0,
|
|
496
|
+
debtPrice: 0,
|
|
497
|
+
vesuLeverage: 0,
|
|
498
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
const amountToInvestAfterRepayingDebt = amountToInvest.minus(debtAmountToBeRepaid);
|
|
421
502
|
const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } =
|
|
422
503
|
await calculateAmountDistribution(
|
|
423
|
-
|
|
504
|
+
amountToInvestAfterRepayingDebt.toNumber(),
|
|
424
505
|
extendedAdapter.client,
|
|
425
506
|
extendedAdapter.config.extendedMarketName,
|
|
426
507
|
collateralPrice.price,
|
|
@@ -445,9 +526,14 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
445
526
|
collateralPrice: 0,
|
|
446
527
|
debtPrice: 0,
|
|
447
528
|
vesuLeverage: 0,
|
|
529
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
448
530
|
};
|
|
449
531
|
}
|
|
450
|
-
logger.info(
|
|
532
|
+
logger.info(
|
|
533
|
+
`${
|
|
534
|
+
VesuExtendedMultiplierStrategy.name
|
|
535
|
+
}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`
|
|
536
|
+
);
|
|
451
537
|
return {
|
|
452
538
|
shouldInvest: true,
|
|
453
539
|
vesuAmount: vesu_amount,
|
|
@@ -456,6 +542,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
456
542
|
vesuLeverage: vesu_leverage,
|
|
457
543
|
collateralPrice: collateralPrice.price,
|
|
458
544
|
debtPrice: debtPrice.price,
|
|
545
|
+
debtAmountToBeRepaid: debtAmountToBeRepaid,
|
|
459
546
|
};
|
|
460
547
|
} catch (err) {
|
|
461
548
|
logger.error(`error deciding invest: ${err}`);
|
|
@@ -467,11 +554,15 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
467
554
|
collateralPrice: 0,
|
|
468
555
|
debtPrice: 0,
|
|
469
556
|
vesuLeverage: 0,
|
|
557
|
+
debtAmountToBeRepaid: new Web3Number(0, 0),
|
|
470
558
|
};
|
|
471
559
|
}
|
|
472
560
|
}
|
|
473
561
|
|
|
474
|
-
async shouldMoveAssets(
|
|
562
|
+
async shouldMoveAssets(
|
|
563
|
+
extendedAmount: Web3Number,
|
|
564
|
+
vesuAmount: Web3Number
|
|
565
|
+
): Promise<TransactionResult[]> {
|
|
475
566
|
try {
|
|
476
567
|
const vesuAdapter = await this.getVesuAdapter();
|
|
477
568
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
@@ -488,37 +579,58 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
488
579
|
return [];
|
|
489
580
|
}
|
|
490
581
|
const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
|
|
491
|
-
|
|
492
|
-
|
|
582
|
+
/**
|
|
583
|
+
* Trade is the correct metric, since we can close position for some vesu amount, otherwise underutilisation of funds will be a huge issue
|
|
584
|
+
*/
|
|
585
|
+
const usdcAmountOnExtendedAvailableForTrade = parseFloat(
|
|
586
|
+
extendedHoldings.availableForTrade
|
|
493
587
|
);
|
|
494
588
|
|
|
495
|
-
logger.info(
|
|
589
|
+
logger.info(
|
|
590
|
+
`${
|
|
591
|
+
VesuExtendedMultiplierStrategy.name
|
|
592
|
+
}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForTrade}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`
|
|
593
|
+
);
|
|
496
594
|
|
|
497
595
|
let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
498
596
|
let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
499
597
|
|
|
500
|
-
if (
|
|
501
|
-
|
|
598
|
+
if (
|
|
599
|
+
extendedAmount.isNegative() &&
|
|
600
|
+
extendedAmount
|
|
601
|
+
.abs()
|
|
602
|
+
.greaterThan(extendedAdapter.minimumExtendedMovementAmount)
|
|
603
|
+
) {
|
|
604
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(
|
|
605
|
+
extendedAmount.abs()
|
|
606
|
+
);
|
|
502
607
|
}
|
|
503
608
|
|
|
504
609
|
// Calculate remaining Extended difference (target vs current)
|
|
505
610
|
// If extendedAmount was negative, we've already accounted for that withdrawal
|
|
506
611
|
// So we calculate based on what Extended will be after that withdrawal
|
|
507
612
|
const extendedTargetAmount = extendedAmount.abs(); // Use absolute value as target
|
|
508
|
-
let projectedExtendedBalance =
|
|
613
|
+
let projectedExtendedBalance = usdcAmountOnExtendedAvailableForTrade;
|
|
509
614
|
|
|
510
615
|
if (extendedAmount.isNegative()) {
|
|
511
|
-
projectedExtendedBalance =
|
|
616
|
+
projectedExtendedBalance =
|
|
617
|
+
projectedExtendedBalance - extendedAmount.abs().toNumber();
|
|
512
618
|
}
|
|
513
619
|
|
|
514
|
-
const extendedAmountDifference = extendedTargetAmount.minus(
|
|
620
|
+
const extendedAmountDifference = extendedTargetAmount.minus(
|
|
621
|
+
projectedExtendedBalance
|
|
622
|
+
);
|
|
515
623
|
const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
|
|
516
624
|
|
|
517
625
|
// Track additional Extended movements
|
|
518
626
|
if (extendedAmountDifference.lessThan(0)) {
|
|
519
|
-
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(
|
|
627
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(
|
|
628
|
+
extendedAmountDifferenceAbs
|
|
629
|
+
);
|
|
520
630
|
} else if (extendedAmountDifference.greaterThan(0)) {
|
|
521
|
-
totalExtendedDeposit = totalExtendedDeposit.plus(
|
|
631
|
+
totalExtendedDeposit = totalExtendedDeposit.plus(
|
|
632
|
+
extendedAmountDifference
|
|
633
|
+
);
|
|
522
634
|
}
|
|
523
635
|
|
|
524
636
|
const vesuTargetAmount = vesuAmount.abs();
|
|
@@ -529,19 +641,31 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
529
641
|
let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
|
|
530
642
|
const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
|
|
531
643
|
|
|
532
|
-
logger.info(
|
|
533
|
-
|
|
644
|
+
logger.info(
|
|
645
|
+
`${
|
|
646
|
+
VesuExtendedMultiplierStrategy.name
|
|
647
|
+
}::shouldMoveAssets calculated movements - Extended withdrawal: ${totalExtendedWithdrawal.toNumber()}, Extended deposit: ${totalExtendedDeposit.toNumber()}, Extended diff: ${extendedAmountDifference.toNumber()}, Projected wallet: ${projectedWalletBalance.toNumber()}, Vesu diff: ${vesuAmountDifference.toNumber()}`
|
|
648
|
+
);
|
|
534
649
|
let transactionResults: TransactionResult[] = [];
|
|
535
650
|
|
|
536
651
|
// Handle negative extendedAmount (initial withdrawal needed)
|
|
537
|
-
if (
|
|
652
|
+
if (
|
|
653
|
+
extendedAmount.isNegative() &&
|
|
654
|
+
extendedAmount
|
|
655
|
+
.abs()
|
|
656
|
+
.greaterThan(extendedAdapter.minimumExtendedMovementAmount)
|
|
657
|
+
) {
|
|
538
658
|
try {
|
|
539
|
-
const {
|
|
659
|
+
const {
|
|
660
|
+
calls: extendedCalls,
|
|
661
|
+
status: extendedStatus,
|
|
662
|
+
transactionMetadata: extendedTransactionMetadata,
|
|
663
|
+
} = await this.moveAssets(
|
|
540
664
|
{
|
|
541
665
|
to: Protocols.VAULT.name,
|
|
542
666
|
from: Protocols.EXTENDED.name,
|
|
543
667
|
amount: extendedAmount.abs(),
|
|
544
|
-
cycleType: CycleType.INVESTMENT
|
|
668
|
+
cycleType: CycleType.INVESTMENT,
|
|
545
669
|
},
|
|
546
670
|
extendedAdapter,
|
|
547
671
|
vesuAdapter
|
|
@@ -554,30 +678,73 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
554
678
|
...extendedTransactionMetadata,
|
|
555
679
|
transactionType: "DEPOSIT",
|
|
556
680
|
},
|
|
557
|
-
})
|
|
681
|
+
});
|
|
558
682
|
} else {
|
|
559
|
-
return [
|
|
683
|
+
return [
|
|
684
|
+
this.createTransactionResult(
|
|
685
|
+
[],
|
|
686
|
+
false,
|
|
687
|
+
{
|
|
688
|
+
from: Protocols.EXTENDED.name,
|
|
689
|
+
to: Protocols.VAULT.name,
|
|
690
|
+
amount: extendedAmount.abs(),
|
|
691
|
+
},
|
|
692
|
+
"NONE",
|
|
693
|
+
CycleType.INVESTMENT
|
|
694
|
+
),
|
|
695
|
+
];
|
|
560
696
|
}
|
|
561
697
|
} catch (err) {
|
|
562
698
|
logger.error(`Failed moving assets to vault: ${err}`);
|
|
563
|
-
return [
|
|
699
|
+
return [
|
|
700
|
+
this.createTransactionResult(
|
|
701
|
+
[],
|
|
702
|
+
false,
|
|
703
|
+
{
|
|
704
|
+
from: Protocols.EXTENDED.name,
|
|
705
|
+
to: Protocols.VAULT.name,
|
|
706
|
+
amount: extendedAmount.abs(),
|
|
707
|
+
},
|
|
708
|
+
"NONE",
|
|
709
|
+
CycleType.INVESTMENT
|
|
710
|
+
),
|
|
711
|
+
];
|
|
564
712
|
}
|
|
565
713
|
}
|
|
566
714
|
|
|
567
|
-
if (
|
|
715
|
+
if (
|
|
716
|
+
vesuAmount.isNegative() &&
|
|
717
|
+
vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)
|
|
718
|
+
) {
|
|
568
719
|
try {
|
|
569
|
-
const {
|
|
720
|
+
const {
|
|
721
|
+
calls: vesuCalls,
|
|
722
|
+
status: vesuStatus,
|
|
723
|
+
transactionMetadata: vesuTransactionMetadata,
|
|
724
|
+
} = await this.moveAssets(
|
|
570
725
|
{
|
|
571
726
|
to: Protocols.EXTENDED.name,
|
|
572
727
|
from: Protocols.VESU.name,
|
|
573
728
|
amount: vesuAmount.abs(),
|
|
574
|
-
cycleType: CycleType.INVESTMENT
|
|
729
|
+
cycleType: CycleType.INVESTMENT,
|
|
575
730
|
},
|
|
576
731
|
extendedAdapter,
|
|
577
732
|
vesuAdapter
|
|
578
733
|
);
|
|
579
734
|
if (!vesuStatus) {
|
|
580
|
-
return [
|
|
735
|
+
return [
|
|
736
|
+
this.createTransactionResult(
|
|
737
|
+
[],
|
|
738
|
+
false,
|
|
739
|
+
{
|
|
740
|
+
from: Protocols.VESU.name,
|
|
741
|
+
to: Protocols.EXTENDED.name,
|
|
742
|
+
amount: vesuAmount.abs(),
|
|
743
|
+
},
|
|
744
|
+
"NONE",
|
|
745
|
+
CycleType.INVESTMENT
|
|
746
|
+
),
|
|
747
|
+
];
|
|
581
748
|
}
|
|
582
749
|
transactionResults.push({
|
|
583
750
|
status: vesuStatus,
|
|
@@ -585,24 +752,46 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
585
752
|
transactionMetadata: {
|
|
586
753
|
...vesuTransactionMetadata,
|
|
587
754
|
transactionType: "DEPOSIT",
|
|
588
|
-
}
|
|
589
|
-
})
|
|
755
|
+
},
|
|
756
|
+
});
|
|
590
757
|
} catch (err) {
|
|
591
|
-
logger.error(
|
|
592
|
-
|
|
758
|
+
logger.error(
|
|
759
|
+
`Failed moving assets to extended via vault allocator: ${err}`
|
|
760
|
+
);
|
|
761
|
+
return [
|
|
762
|
+
this.createTransactionResult(
|
|
763
|
+
[],
|
|
764
|
+
false,
|
|
765
|
+
{
|
|
766
|
+
from: Protocols.VESU.name,
|
|
767
|
+
to: Protocols.EXTENDED.name,
|
|
768
|
+
amount: vesuAmount.abs(),
|
|
769
|
+
},
|
|
770
|
+
"NONE",
|
|
771
|
+
CycleType.INVESTMENT
|
|
772
|
+
),
|
|
773
|
+
];
|
|
593
774
|
}
|
|
594
775
|
}
|
|
595
776
|
|
|
596
777
|
// Handle Extended adjustments based on calculated difference
|
|
597
|
-
if (
|
|
778
|
+
if (
|
|
779
|
+
extendedAmountDifferenceAbs.greaterThan(
|
|
780
|
+
extendedAdapter.minimumExtendedMovementAmount
|
|
781
|
+
)
|
|
782
|
+
) {
|
|
598
783
|
if (extendedAmountDifference.greaterThan(0)) {
|
|
599
784
|
try {
|
|
600
|
-
const {
|
|
785
|
+
const {
|
|
786
|
+
calls: extendedCalls,
|
|
787
|
+
status: extendedStatus,
|
|
788
|
+
transactionMetadata: extendedTransactionMetadata,
|
|
789
|
+
} = await this.moveAssets(
|
|
601
790
|
{
|
|
602
791
|
to: Protocols.EXTENDED.name,
|
|
603
792
|
from: Protocols.VAULT.name,
|
|
604
793
|
amount: extendedAmountDifference,
|
|
605
|
-
cycleType: CycleType.INVESTMENT
|
|
794
|
+
cycleType: CycleType.INVESTMENT,
|
|
606
795
|
},
|
|
607
796
|
extendedAdapter,
|
|
608
797
|
vesuAdapter
|
|
@@ -611,24 +800,54 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
611
800
|
transactionResults.push({
|
|
612
801
|
status: extendedStatus,
|
|
613
802
|
calls: extendedCalls,
|
|
614
|
-
transactionMetadata: extendedTransactionMetadata
|
|
615
|
-
})
|
|
803
|
+
transactionMetadata: extendedTransactionMetadata,
|
|
804
|
+
});
|
|
616
805
|
} else {
|
|
617
|
-
logger.error(
|
|
618
|
-
|
|
806
|
+
logger.error(
|
|
807
|
+
`Failed to move assets to extended - operation returned false status`
|
|
808
|
+
);
|
|
809
|
+
return [
|
|
810
|
+
this.createTransactionResult(
|
|
811
|
+
[],
|
|
812
|
+
false,
|
|
813
|
+
{
|
|
814
|
+
from: Protocols.VAULT.name,
|
|
815
|
+
to: Protocols.EXTENDED.name,
|
|
816
|
+
amount: extendedAmountDifference,
|
|
817
|
+
},
|
|
818
|
+
"NONE",
|
|
819
|
+
CycleType.INVESTMENT
|
|
820
|
+
),
|
|
821
|
+
];
|
|
619
822
|
}
|
|
620
823
|
} catch (err) {
|
|
621
824
|
logger.error(`Failed moving assets to extended: ${err}`);
|
|
622
|
-
return [
|
|
825
|
+
return [
|
|
826
|
+
this.createTransactionResult(
|
|
827
|
+
[],
|
|
828
|
+
false,
|
|
829
|
+
{
|
|
830
|
+
from: Protocols.VAULT.name,
|
|
831
|
+
to: Protocols.EXTENDED.name,
|
|
832
|
+
amount: extendedAmountDifference,
|
|
833
|
+
},
|
|
834
|
+
"NONE",
|
|
835
|
+
CycleType.INVESTMENT
|
|
836
|
+
),
|
|
837
|
+
];
|
|
623
838
|
}
|
|
624
839
|
} else if (extendedAmountDifference.lessThan(0)) {
|
|
625
840
|
try {
|
|
626
|
-
const {
|
|
841
|
+
const {
|
|
842
|
+
calls: extendedCalls,
|
|
843
|
+
status: extendedStatus,
|
|
844
|
+
transactionMetadata: extendedTransactionMetadata,
|
|
845
|
+
} = await this.moveAssets(
|
|
627
846
|
{
|
|
628
847
|
to: Protocols.VAULT.name,
|
|
629
848
|
from: Protocols.EXTENDED.name,
|
|
630
849
|
amount: extendedAmountDifferenceAbs,
|
|
631
|
-
cycleType: CycleType.INVESTMENT
|
|
850
|
+
cycleType: CycleType.INVESTMENT,
|
|
632
851
|
},
|
|
633
852
|
extendedAdapter,
|
|
634
853
|
vesuAdapter
|
|
@@ -640,21 +859,51 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
640
859
|
transactionMetadata: {
|
|
641
860
|
...extendedTransactionMetadata,
|
|
642
861
|
transactionType: "DEPOSIT",
|
|
643
|
-
}
|
|
644
|
-
})
|
|
862
|
+
},
|
|
863
|
+
});
|
|
645
864
|
} else {
|
|
646
|
-
logger.error(
|
|
647
|
-
|
|
865
|
+
logger.error(
|
|
866
|
+
`Failed to withdraw from extended - operation returned false status`
|
|
867
|
+
);
|
|
868
|
+
return [
|
|
869
|
+
this.createTransactionResult(
|
|
870
|
+
[],
|
|
871
|
+
false,
|
|
872
|
+
{
|
|
873
|
+
from: Protocols.EXTENDED.name,
|
|
874
|
+
to: Protocols.VAULT.name,
|
|
875
|
+
amount: extendedAmountDifferenceAbs,
|
|
876
|
+
},
|
|
877
|
+
"NONE",
|
|
878
|
+
CycleType.INVESTMENT
|
|
879
|
+
),
|
|
880
|
+
];
|
|
648
881
|
}
|
|
649
882
|
} catch (err) {
|
|
650
883
|
logger.error(`Failed moving assets from extended to vault: ${err}`);
|
|
651
|
-
return [
|
|
884
|
+
return [
|
|
885
|
+
this.createTransactionResult(
|
|
886
|
+
[],
|
|
887
|
+
false,
|
|
888
|
+
{
|
|
889
|
+
from: Protocols.EXTENDED.name,
|
|
890
|
+
to: Protocols.VAULT.name,
|
|
891
|
+
amount: extendedAmountDifferenceAbs,
|
|
892
|
+
},
|
|
893
|
+
"NONE",
|
|
894
|
+
CycleType.INVESTMENT
|
|
895
|
+
),
|
|
896
|
+
];
|
|
652
897
|
}
|
|
653
898
|
}
|
|
654
899
|
}
|
|
655
900
|
|
|
656
901
|
// Handle Vesu adjustments based on calculated difference (already adjusted for Extended movements)
|
|
657
|
-
if (
|
|
902
|
+
if (
|
|
903
|
+
vesuAmountDifferenceAbs.greaterThan(
|
|
904
|
+
vesuAdapter.minimumVesuMovementAmount
|
|
905
|
+
)
|
|
906
|
+
) {
|
|
658
907
|
if (vesuAmountDifference.lessThanOrEqualTo(0)) {
|
|
659
908
|
logger.warn(
|
|
660
909
|
`Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
|
|
@@ -662,19 +911,37 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
662
911
|
} else {
|
|
663
912
|
// Move assets from Extended to Vault (which will then go to Vesu)
|
|
664
913
|
try {
|
|
665
|
-
const {
|
|
914
|
+
const {
|
|
915
|
+
calls: vesuCalls,
|
|
916
|
+
status: vesuStatus,
|
|
917
|
+
transactionMetadata: vesuTransactionMetadata,
|
|
918
|
+
} = await this.moveAssets(
|
|
666
919
|
{
|
|
667
920
|
to: Protocols.VAULT.name,
|
|
668
921
|
from: Protocols.EXTENDED.name,
|
|
669
922
|
amount: vesuAmountDifference,
|
|
670
|
-
cycleType: CycleType.INVESTMENT
|
|
923
|
+
cycleType: CycleType.INVESTMENT,
|
|
671
924
|
},
|
|
672
925
|
extendedAdapter,
|
|
673
926
|
vesuAdapter
|
|
674
927
|
);
|
|
675
928
|
if (!vesuStatus) {
|
|
676
|
-
logger.error(
|
|
677
|
-
|
|
929
|
+
logger.error(
|
|
930
|
+
`Failed to move assets to vesu - operation returned false status`
|
|
931
|
+
);
|
|
932
|
+
return [
|
|
933
|
+
this.createTransactionResult(
|
|
934
|
+
[],
|
|
935
|
+
false,
|
|
936
|
+
{
|
|
937
|
+
from: Protocols.EXTENDED.name,
|
|
938
|
+
to: Protocols.VAULT.name,
|
|
939
|
+
amount: vesuAmountDifference,
|
|
940
|
+
},
|
|
941
|
+
"NONE",
|
|
942
|
+
CycleType.INVESTMENT
|
|
943
|
+
),
|
|
944
|
+
];
|
|
678
945
|
}
|
|
679
946
|
transactionResults.push({
|
|
680
947
|
status: vesuStatus,
|
|
@@ -682,19 +949,42 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
682
949
|
transactionMetadata: {
|
|
683
950
|
...vesuTransactionMetadata,
|
|
684
951
|
transactionType: "DEPOSIT",
|
|
685
|
-
}
|
|
686
|
-
})
|
|
952
|
+
},
|
|
953
|
+
});
|
|
687
954
|
} catch (err) {
|
|
688
955
|
logger.error(`Failed moving assets to vault: ${err}`);
|
|
689
|
-
return [
|
|
956
|
+
return [
|
|
957
|
+
this.createTransactionResult(
|
|
958
|
+
[],
|
|
959
|
+
false,
|
|
960
|
+
{
|
|
961
|
+
from: Protocols.EXTENDED.name,
|
|
962
|
+
to: Protocols.VAULT.name,
|
|
963
|
+
amount: vesuAmountDifference,
|
|
964
|
+
},
|
|
965
|
+
"NONE",
|
|
966
|
+
CycleType.INVESTMENT
|
|
967
|
+
),
|
|
968
|
+
];
|
|
690
969
|
}
|
|
691
970
|
}
|
|
692
971
|
}
|
|
693
|
-
|
|
694
972
|
return transactionResults;
|
|
695
973
|
} catch (err) {
|
|
696
974
|
logger.error(`Failed moving assets to vesu: ${err}`);
|
|
697
|
-
return [
|
|
975
|
+
return [
|
|
976
|
+
this.createTransactionResult(
|
|
977
|
+
[],
|
|
978
|
+
false,
|
|
979
|
+
{
|
|
980
|
+
from: Protocols.EXTENDED.name,
|
|
981
|
+
to: Protocols.VAULT.name,
|
|
982
|
+
amount: new Web3Number(0, USDC_TOKEN_DECIMALS),
|
|
983
|
+
},
|
|
984
|
+
"NONE",
|
|
985
|
+
CycleType.INVESTMENT
|
|
986
|
+
),
|
|
987
|
+
];
|
|
698
988
|
}
|
|
699
989
|
}
|
|
700
990
|
|
|
@@ -705,7 +995,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
705
995
|
calls: Call[],
|
|
706
996
|
status: boolean,
|
|
707
997
|
params: { from: string; to: string; amount: Web3Number },
|
|
708
|
-
transactionType:
|
|
998
|
+
transactionType: "DEPOSIT" | "WITHDRAWAL" | "NONE",
|
|
709
999
|
cycleType: CycleType
|
|
710
1000
|
): TransactionResult {
|
|
711
1001
|
if (status) {
|
|
@@ -717,14 +1007,34 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
717
1007
|
protocolTo: params.to,
|
|
718
1008
|
transactionType: transactionType,
|
|
719
1009
|
usdAmount: params.amount.abs().toFixed(),
|
|
720
|
-
status:
|
|
721
|
-
cycleType: cycleType
|
|
722
|
-
}
|
|
1010
|
+
status: "PENDING",
|
|
1011
|
+
cycleType: cycleType,
|
|
1012
|
+
},
|
|
723
1013
|
};
|
|
724
1014
|
}
|
|
725
|
-
return {
|
|
1015
|
+
return {
|
|
1016
|
+
calls: [],
|
|
1017
|
+
status: false,
|
|
1018
|
+
transactionMetadata: {
|
|
1019
|
+
protocolFrom: "",
|
|
1020
|
+
protocolTo: "",
|
|
1021
|
+
transactionType: "DEPOSIT",
|
|
1022
|
+
usdAmount: "0",
|
|
1023
|
+
status: "FAILED",
|
|
1024
|
+
cycleType: cycleType,
|
|
1025
|
+
},
|
|
1026
|
+
};
|
|
726
1027
|
}
|
|
727
1028
|
|
|
1029
|
+
/**
|
|
1030
|
+
* This method is used to move assets between protocols
|
|
1031
|
+
* @param params - The parameters for the move assets operation
|
|
1032
|
+
* @param extendedAdapter - The extended adapter
|
|
1033
|
+
* @param vesuAdapter - The vesu adapter
|
|
1034
|
+
* @returns The transaction result
|
|
1035
|
+
* If Extended amount is greater than amount of withdrawal from extended, then we need to open a long position
|
|
1036
|
+
* so that the amount of withdrawal from extended is fullfilled
|
|
1037
|
+
*/
|
|
728
1038
|
async moveAssets(
|
|
729
1039
|
params: {
|
|
730
1040
|
amount: Web3Number;
|
|
@@ -733,7 +1043,7 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
733
1043
|
cycleType: CycleType;
|
|
734
1044
|
},
|
|
735
1045
|
extendedAdapter: ExtendedAdapter,
|
|
736
|
-
vesuAdapter: VesuMultiplyAdapter
|
|
1046
|
+
vesuAdapter: VesuMultiplyAdapter
|
|
737
1047
|
): Promise<TransactionResult> {
|
|
738
1048
|
try {
|
|
739
1049
|
// Validate amount is positive before starting operations
|
|
@@ -741,40 +1051,53 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
741
1051
|
logger.error(
|
|
742
1052
|
`Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
|
|
743
1053
|
);
|
|
744
|
-
return this.createTransactionResult(
|
|
1054
|
+
return this.createTransactionResult(
|
|
1055
|
+
[],
|
|
1056
|
+
false,
|
|
1057
|
+
params,
|
|
1058
|
+
"NONE",
|
|
1059
|
+
params.cycleType
|
|
1060
|
+
);
|
|
745
1061
|
}
|
|
746
1062
|
|
|
747
1063
|
// Check minimum movement amounts before starting operations
|
|
748
|
-
const amountAbs = params.amount.abs();
|
|
749
|
-
if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
}
|
|
757
|
-
if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
}
|
|
1064
|
+
// const amountAbs = params.amount.abs();
|
|
1065
|
+
// if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
|
|
1066
|
+
// if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
1067
|
+
// logger.warn(
|
|
1068
|
+
// `Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
|
|
1069
|
+
// );
|
|
1070
|
+
// return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
1071
|
+
// }
|
|
1072
|
+
// }
|
|
1073
|
+
// if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
|
|
1074
|
+
// if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
|
|
1075
|
+
// logger.warn(
|
|
1076
|
+
// `Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
|
|
1077
|
+
// );
|
|
1078
|
+
// return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
1079
|
+
// }
|
|
1080
|
+
// }
|
|
765
1081
|
|
|
766
1082
|
const avnuAdapter = await this.getAvnuAdapter();
|
|
767
1083
|
if (!avnuAdapter) {
|
|
768
1084
|
logger.error(`avnu adapter not found: ${avnuAdapter}`);
|
|
769
|
-
return this.createTransactionResult(
|
|
1085
|
+
return this.createTransactionResult(
|
|
1086
|
+
[],
|
|
1087
|
+
false,
|
|
1088
|
+
params,
|
|
1089
|
+
"NONE",
|
|
1090
|
+
params.cycleType
|
|
1091
|
+
);
|
|
770
1092
|
}
|
|
771
1093
|
logger.info(`moveAssets params, ${JSON.stringify(params)}`);
|
|
772
1094
|
const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
|
|
773
|
-
const {
|
|
774
|
-
collateralPrice,
|
|
775
|
-
} = await this.getAssetPrices();
|
|
1095
|
+
const { collateralPrice } = await this.getAssetPrices();
|
|
776
1096
|
|
|
777
|
-
if (
|
|
1097
|
+
if (
|
|
1098
|
+
params.to === Protocols.EXTENDED.name &&
|
|
1099
|
+
params.from === Protocols.VAULT.name
|
|
1100
|
+
) {
|
|
778
1101
|
const proofsInfo = extendedAdapter.getProofs(
|
|
779
1102
|
true,
|
|
780
1103
|
this.getMerkleTree()
|
|
@@ -786,84 +1109,204 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
786
1109
|
await proofsInfo.callConstructor({ amount: params.amount })
|
|
787
1110
|
);
|
|
788
1111
|
calls.push(call);
|
|
789
|
-
return this.createTransactionResult(
|
|
790
|
-
|
|
1112
|
+
return this.createTransactionResult(
|
|
1113
|
+
calls,
|
|
1114
|
+
true,
|
|
1115
|
+
params,
|
|
1116
|
+
"DEPOSIT",
|
|
1117
|
+
params.cycleType
|
|
1118
|
+
);
|
|
1119
|
+
} else if (
|
|
1120
|
+
params.to === Protocols.VAULT.name &&
|
|
1121
|
+
params.from === Protocols.EXTENDED.name
|
|
1122
|
+
) {
|
|
791
1123
|
const extendedLeverage = calculateExtendedLevergae();
|
|
792
|
-
const extendedHoldings =
|
|
1124
|
+
const extendedHoldings =
|
|
1125
|
+
await extendedAdapter.getExtendedDepositAmount();
|
|
793
1126
|
if (!extendedHoldings) {
|
|
794
1127
|
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
795
|
-
return this.createTransactionResult(
|
|
1128
|
+
return this.createTransactionResult(
|
|
1129
|
+
[],
|
|
1130
|
+
false,
|
|
1131
|
+
params,
|
|
1132
|
+
"NONE",
|
|
1133
|
+
params.cycleType
|
|
1134
|
+
);
|
|
796
1135
|
}
|
|
797
1136
|
const extendedHoldingAmount = new Web3Number(
|
|
798
1137
|
extendedHoldings.availableForWithdrawal,
|
|
799
1138
|
USDC_TOKEN_DECIMALS
|
|
800
1139
|
);
|
|
801
|
-
logger.info(
|
|
1140
|
+
logger.info(
|
|
1141
|
+
`${
|
|
1142
|
+
VesuExtendedMultiplierStrategy.name
|
|
1143
|
+
}::moveAssets extendedHoldingAmount: ${extendedHoldingAmount.toNumber()}`
|
|
1144
|
+
);
|
|
802
1145
|
if (params.amount.abs().greaterThan(extendedHoldingAmount)) {
|
|
803
|
-
const leftAmountAfterWithdrawalAmountInAccount =
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
1146
|
+
const leftAmountAfterWithdrawalAmountInAccount = new Web3Number(
|
|
1147
|
+
Math.ceil(
|
|
1148
|
+
params.amount.abs().minus(extendedHoldingAmount).toNumber()
|
|
1149
|
+
),
|
|
1150
|
+
USDC_TOKEN_DECIMALS
|
|
1151
|
+
);
|
|
1152
|
+
logger.info(
|
|
1153
|
+
`${
|
|
1154
|
+
VesuExtendedMultiplierStrategy.name
|
|
1155
|
+
}::moveAssets leftAmountAfterWithdrawalAmountInAccount: ${leftAmountAfterWithdrawalAmountInAccount.toNumber()}`
|
|
1156
|
+
);
|
|
1157
|
+
let priceOfBTC;
|
|
1158
|
+
const { ask, bid, status } =
|
|
1159
|
+
await extendedAdapter.fetchOrderBookBTCUSDC();
|
|
1160
|
+
const price = ask.plus(bid).dividedBy(2);
|
|
1161
|
+
if (status) {
|
|
1162
|
+
priceOfBTC = price;
|
|
1163
|
+
} else {
|
|
1164
|
+
logger.error(`error fetching order book btc usdc: ${status}`);
|
|
1165
|
+
priceOfBTC = collateralPrice.price;
|
|
1166
|
+
}
|
|
1167
|
+
const btcAmount =
|
|
1168
|
+
leftAmountAfterWithdrawalAmountInAccount.dividedBy(priceOfBTC);
|
|
1169
|
+
/**
|
|
1170
|
+
* If amount for withdrawal is greater than the amount in extended available for withdrawal,
|
|
1171
|
+
* then we need to open a long position depending on the difference between the two
|
|
1172
|
+
*/
|
|
1173
|
+
const openLongPosition = btcAmount
|
|
1174
|
+
.multipliedBy(3)
|
|
1175
|
+
.greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)
|
|
1176
|
+
? await extendedAdapter.createOrder(
|
|
1177
|
+
extendedLeverage.toString(),
|
|
1178
|
+
btcAmount.toNumber(),
|
|
1179
|
+
OrderSide.BUY
|
|
1180
|
+
)
|
|
1181
|
+
: await extendedAdapter.createOrder(
|
|
1182
|
+
extendedLeverage.toString(),
|
|
1183
|
+
0.000034, // just in case amount falls short then we need to create a withdrawal
|
|
1184
|
+
OrderSide.BUY
|
|
1185
|
+
);
|
|
815
1186
|
if (!openLongPosition) {
|
|
816
1187
|
logger.error(`error opening long position: ${openLongPosition}`);
|
|
817
1188
|
}
|
|
818
|
-
const updatedHoldings =
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
1189
|
+
const updatedHoldings =
|
|
1190
|
+
await extendedAdapter.getExtendedDepositAmount();
|
|
1191
|
+
if (
|
|
1192
|
+
!updatedHoldings ||
|
|
1193
|
+
new Web3Number(
|
|
1194
|
+
updatedHoldings.availableForWithdrawal,
|
|
1195
|
+
USDC_TOKEN_DECIMALS
|
|
1196
|
+
).lessThan(params.amount.abs())
|
|
1197
|
+
) {
|
|
1198
|
+
logger.error(
|
|
1199
|
+
`Insufficient balance after opening position. Available: ${
|
|
1200
|
+
updatedHoldings?.availableForWithdrawal
|
|
1201
|
+
}, Needed: ${params.amount.abs()}`
|
|
1202
|
+
);
|
|
1203
|
+
return this.createTransactionResult(
|
|
1204
|
+
[],
|
|
1205
|
+
false,
|
|
1206
|
+
params,
|
|
1207
|
+
"NONE",
|
|
1208
|
+
params.cycleType
|
|
1209
|
+
);
|
|
822
1210
|
}
|
|
823
1211
|
}
|
|
824
1212
|
const {
|
|
825
1213
|
status: withdrawalFromExtendedStatus,
|
|
826
1214
|
receivedTxnHash: withdrawalFromExtendedTxnHash,
|
|
827
|
-
} =
|
|
828
|
-
await extendedAdapter.withdrawFromExtended(params.amount);
|
|
1215
|
+
} = await extendedAdapter.withdrawFromExtended(params.amount);
|
|
829
1216
|
/**
|
|
830
1217
|
* This logic needs fixing
|
|
831
1218
|
*/
|
|
832
|
-
logger.info(
|
|
1219
|
+
logger.info(
|
|
1220
|
+
`withdrawalFromExtendedStatus: ${withdrawalFromExtendedStatus}, withdrawalFromExtendedTxnHash: ${withdrawalFromExtendedTxnHash}`
|
|
1221
|
+
);
|
|
833
1222
|
if (withdrawalFromExtendedStatus && withdrawalFromExtendedTxnHash) {
|
|
834
1223
|
/**
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
const extendedHoldings =
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
1224
|
+
* We need to move assets from my wallet back to vault contract
|
|
1225
|
+
*/
|
|
1226
|
+
const extendedHoldings =
|
|
1227
|
+
await extendedAdapter.getExtendedDepositAmount();
|
|
1228
|
+
logger.info(
|
|
1229
|
+
`extendedHoldings after withdrawal ${extendedHoldings?.availableForWithdrawal}`
|
|
1230
|
+
);
|
|
1231
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
1232
|
+
const { calls, status } = await this.moveAssetsToVaultAllocator(
|
|
1233
|
+
params.amount,
|
|
1234
|
+
extendedAdapter
|
|
1235
|
+
);
|
|
841
1236
|
if (calls.length > 0 && status) {
|
|
842
|
-
return this.createTransactionResult(
|
|
1237
|
+
return this.createTransactionResult(
|
|
1238
|
+
calls,
|
|
1239
|
+
true,
|
|
1240
|
+
params,
|
|
1241
|
+
"WITHDRAWAL",
|
|
1242
|
+
params.cycleType
|
|
1243
|
+
);
|
|
843
1244
|
} else {
|
|
844
1245
|
/**
|
|
845
1246
|
* This is a fallback scenario, where the funds were withdrawn from extended, but didn't get transferred to the wallet
|
|
846
1247
|
* We need to return a successful transaction result, but with no calls
|
|
847
1248
|
* Db update will be handled by the risk engine for this specific case
|
|
848
1249
|
*/
|
|
849
|
-
return this.createTransactionResult(
|
|
1250
|
+
return this.createTransactionResult(
|
|
1251
|
+
[],
|
|
1252
|
+
true,
|
|
1253
|
+
params,
|
|
1254
|
+
"WITHDRAWAL",
|
|
1255
|
+
params.cycleType
|
|
1256
|
+
);
|
|
850
1257
|
}
|
|
851
|
-
} else if (
|
|
852
|
-
|
|
853
|
-
|
|
1258
|
+
} else if (
|
|
1259
|
+
withdrawalFromExtendedStatus &&
|
|
1260
|
+
!withdrawalFromExtendedTxnHash
|
|
1261
|
+
) {
|
|
1262
|
+
logger.error(
|
|
1263
|
+
"withdrawal from extended successful, but funds didn't get transferred to the wallet"
|
|
1264
|
+
);
|
|
1265
|
+
return this.createTransactionResult(
|
|
1266
|
+
[],
|
|
1267
|
+
true,
|
|
1268
|
+
params,
|
|
1269
|
+
"WITHDRAWAL",
|
|
1270
|
+
params.cycleType
|
|
1271
|
+
);
|
|
854
1272
|
} else {
|
|
855
1273
|
logger.error("withdrawal from extended failed");
|
|
856
|
-
return this.createTransactionResult(
|
|
1274
|
+
return this.createTransactionResult(
|
|
1275
|
+
[],
|
|
1276
|
+
false,
|
|
1277
|
+
params,
|
|
1278
|
+
"NONE",
|
|
1279
|
+
params.cycleType
|
|
1280
|
+
);
|
|
857
1281
|
}
|
|
858
|
-
} else if (
|
|
859
|
-
|
|
1282
|
+
} else if (
|
|
1283
|
+
params.to === Protocols.VAULT.name &&
|
|
1284
|
+
params.from === Protocols.VESU.name
|
|
1285
|
+
) {
|
|
1286
|
+
const isPriceDifferenceBetweenAvnuAndExtended =
|
|
1287
|
+
await this.checkPriceDifferenceBetweenAvnuAndExtended(
|
|
1288
|
+
extendedAdapter,
|
|
1289
|
+
vesuAdapter,
|
|
1290
|
+
avnuAdapter,
|
|
1291
|
+
PositionTypeAvnuExtended.CLOSE
|
|
1292
|
+
);
|
|
860
1293
|
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
861
|
-
logger.warn(
|
|
862
|
-
|
|
1294
|
+
logger.warn(
|
|
1295
|
+
`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`
|
|
1296
|
+
);
|
|
1297
|
+
return this.createTransactionResult(
|
|
1298
|
+
[],
|
|
1299
|
+
false,
|
|
1300
|
+
params,
|
|
1301
|
+
"NONE",
|
|
1302
|
+
params.cycleType
|
|
1303
|
+
);
|
|
863
1304
|
}
|
|
864
|
-
//withdraw from vesu
|
|
1305
|
+
//withdraw from vesu
|
|
865
1306
|
const vesuAmountInBTC = new Web3Number(
|
|
866
|
-
params.amount
|
|
1307
|
+
params.amount
|
|
1308
|
+
.dividedBy(collateralPrice.price)
|
|
1309
|
+
.toFixed(WBTC_TOKEN_DECIMALS),
|
|
867
1310
|
collateralToken.decimals
|
|
868
1311
|
);
|
|
869
1312
|
const proofsInfo = vesuAdapter.getProofs(false, this.getMerkleTree());
|
|
@@ -874,19 +1317,45 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
874
1317
|
await proofsInfo.callConstructor({ amount: vesuAmountInBTC })
|
|
875
1318
|
);
|
|
876
1319
|
calls.push(call);
|
|
877
|
-
const swapProofsInfo = avnuAdapter.getProofs(
|
|
1320
|
+
const swapProofsInfo = avnuAdapter.getProofs(
|
|
1321
|
+
false,
|
|
1322
|
+
this.getMerkleTree()
|
|
1323
|
+
);
|
|
878
1324
|
const swapProofGroups = swapProofsInfo.proofs;
|
|
879
1325
|
const swapCall = this.getManageCall(
|
|
880
1326
|
swapProofGroups,
|
|
881
1327
|
await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
|
|
882
1328
|
);
|
|
883
1329
|
calls.push(swapCall);
|
|
884
|
-
return this.createTransactionResult(
|
|
885
|
-
|
|
886
|
-
|
|
1330
|
+
return this.createTransactionResult(
|
|
1331
|
+
calls,
|
|
1332
|
+
true,
|
|
1333
|
+
params,
|
|
1334
|
+
"WITHDRAWAL",
|
|
1335
|
+
params.cycleType
|
|
1336
|
+
);
|
|
1337
|
+
} else if (
|
|
1338
|
+
params.to === Protocols.EXTENDED.name &&
|
|
1339
|
+
params.from === Protocols.VESU.name
|
|
1340
|
+
) {
|
|
1341
|
+
const isPriceDifferenceBetweenAvnuAndExtended =
|
|
1342
|
+
await this.checkPriceDifferenceBetweenAvnuAndExtended(
|
|
1343
|
+
extendedAdapter,
|
|
1344
|
+
vesuAdapter,
|
|
1345
|
+
avnuAdapter,
|
|
1346
|
+
PositionTypeAvnuExtended.CLOSE
|
|
1347
|
+
);
|
|
887
1348
|
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
888
|
-
logger.warn(
|
|
889
|
-
|
|
1349
|
+
logger.warn(
|
|
1350
|
+
`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`
|
|
1351
|
+
);
|
|
1352
|
+
return this.createTransactionResult(
|
|
1353
|
+
[],
|
|
1354
|
+
false,
|
|
1355
|
+
params,
|
|
1356
|
+
"NONE",
|
|
1357
|
+
params.cycleType
|
|
1358
|
+
);
|
|
890
1359
|
}
|
|
891
1360
|
const vesuAmountInBTC = new Web3Number(
|
|
892
1361
|
params.amount.dividedBy(collateralPrice.price).toNumber(),
|
|
@@ -900,7 +1369,10 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
900
1369
|
await proofsInfo.callConstructor({ amount: vesuAmountInBTC })
|
|
901
1370
|
);
|
|
902
1371
|
calls.push(call);
|
|
903
|
-
const swapProofsInfo = avnuAdapter.getProofs(
|
|
1372
|
+
const swapProofsInfo = avnuAdapter.getProofs(
|
|
1373
|
+
false,
|
|
1374
|
+
this.getMerkleTree()
|
|
1375
|
+
);
|
|
904
1376
|
const swapProofGroups = swapProofsInfo.proofs;
|
|
905
1377
|
const swapCall = this.getManageCall(
|
|
906
1378
|
swapProofGroups,
|
|
@@ -918,13 +1390,33 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
918
1390
|
await proofsInfoDeposit.callConstructor({ amount: params.amount })
|
|
919
1391
|
);
|
|
920
1392
|
calls.push(callDeposit);
|
|
921
|
-
return this.createTransactionResult(
|
|
1393
|
+
return this.createTransactionResult(
|
|
1394
|
+
calls,
|
|
1395
|
+
true,
|
|
1396
|
+
params,
|
|
1397
|
+
"DEPOSIT",
|
|
1398
|
+
params.cycleType
|
|
1399
|
+
);
|
|
922
1400
|
}
|
|
923
|
-
logger.error(
|
|
924
|
-
|
|
1401
|
+
logger.error(
|
|
1402
|
+
`Unsupported assets movement: ${params.from} to ${params.to}`
|
|
1403
|
+
);
|
|
1404
|
+
return this.createTransactionResult(
|
|
1405
|
+
[],
|
|
1406
|
+
false,
|
|
1407
|
+
params,
|
|
1408
|
+
"NONE",
|
|
1409
|
+
params.cycleType
|
|
1410
|
+
);
|
|
925
1411
|
} catch (err) {
|
|
926
1412
|
logger.error(`error moving assets: ${err}`);
|
|
927
|
-
return this.createTransactionResult(
|
|
1413
|
+
return this.createTransactionResult(
|
|
1414
|
+
[],
|
|
1415
|
+
false,
|
|
1416
|
+
params,
|
|
1417
|
+
"NONE",
|
|
1418
|
+
params.cycleType
|
|
1419
|
+
);
|
|
928
1420
|
}
|
|
929
1421
|
}
|
|
930
1422
|
|
|
@@ -933,14 +1425,33 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
933
1425
|
/**
|
|
934
1426
|
* Just a demo function, not used in the risk engine
|
|
935
1427
|
*/
|
|
936
|
-
return this.createTransactionResult(
|
|
1428
|
+
return this.createTransactionResult(
|
|
1429
|
+
[],
|
|
1430
|
+
false,
|
|
1431
|
+
{
|
|
1432
|
+
from: Protocols.VAULT.name,
|
|
1433
|
+
to: Protocols.VAULT.name,
|
|
1434
|
+
amount: new Web3Number(0, 0),
|
|
1435
|
+
},
|
|
1436
|
+
"NONE",
|
|
1437
|
+
CycleType.INVESTMENT
|
|
1438
|
+
);
|
|
937
1439
|
} catch (err) {
|
|
938
1440
|
logger.error(`error handling deposit: ${err}`);
|
|
939
|
-
return this.createTransactionResult(
|
|
1441
|
+
return this.createTransactionResult(
|
|
1442
|
+
[],
|
|
1443
|
+
false,
|
|
1444
|
+
{
|
|
1445
|
+
from: Protocols.VAULT.name,
|
|
1446
|
+
to: Protocols.VAULT.name,
|
|
1447
|
+
amount: new Web3Number(0, 0),
|
|
1448
|
+
},
|
|
1449
|
+
"NONE",
|
|
1450
|
+
CycleType.INVESTMENT
|
|
1451
|
+
);
|
|
940
1452
|
}
|
|
941
1453
|
}
|
|
942
1454
|
|
|
943
|
-
|
|
944
1455
|
/**
|
|
945
1456
|
* Check if the price difference between avnu and extended is within the acceptable range to enhance the position size or close the position
|
|
946
1457
|
* @param extendedAdapter - the extended adapter
|
|
@@ -949,13 +1460,18 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
949
1460
|
* @param positionType - the position type (open or close)
|
|
950
1461
|
* @returns true if the price difference is within the acceptable range, false otherwise
|
|
951
1462
|
*/
|
|
952
|
-
async checkPriceDifferenceBetweenAvnuAndExtended(
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
1463
|
+
async checkPriceDifferenceBetweenAvnuAndExtended(
|
|
1464
|
+
extendedAdapter: ExtendedAdapter,
|
|
1465
|
+
vesuAdapter: VesuMultiplyAdapter,
|
|
1466
|
+
avnuAdapter: AvnuAdapter,
|
|
1467
|
+
positionType: PositionTypeAvnuExtended
|
|
1468
|
+
): Promise<boolean> {
|
|
1469
|
+
const { ask, bid } = await extendedAdapter.fetchOrderBookBTCUSDC();
|
|
956
1470
|
const price = ask.plus(bid).dividedBy(2);
|
|
957
1471
|
const btcToken = vesuAdapter.config.supportedPositions[0].asset;
|
|
958
|
-
const btcPriceAvnu = await avnuAdapter.getPriceOfToken(
|
|
1472
|
+
const btcPriceAvnu = await avnuAdapter.getPriceOfToken(
|
|
1473
|
+
btcToken.address.toString()
|
|
1474
|
+
);
|
|
959
1475
|
|
|
960
1476
|
if (!btcPriceAvnu) {
|
|
961
1477
|
logger.error(`error getting btc price avnu: ${btcPriceAvnu}`);
|
|
@@ -963,19 +1479,34 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
963
1479
|
}
|
|
964
1480
|
logger.info(`price: ${price}`);
|
|
965
1481
|
logger.info(`btcPriceAvnu: ${btcPriceAvnu}`);
|
|
966
|
-
const priceDifference = new Web3Number(
|
|
1482
|
+
const priceDifference = new Web3Number(
|
|
1483
|
+
price.minus(btcPriceAvnu).toFixed(2),
|
|
1484
|
+
0
|
|
1485
|
+
);
|
|
967
1486
|
logger.info(`priceDifference: ${priceDifference}`);
|
|
968
1487
|
if (priceDifference.isNegative()) {
|
|
969
1488
|
return false;
|
|
970
1489
|
}
|
|
971
1490
|
if (positionType === PositionTypeAvnuExtended.OPEN) {
|
|
972
|
-
logger.info(
|
|
973
|
-
|
|
1491
|
+
logger.info(
|
|
1492
|
+
`price difference between avnu and extended for open position: ${priceDifference.toNumber()}, minimumExtendedPriceDifferenceForSwapOpen: ${
|
|
1493
|
+
avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen
|
|
1494
|
+
}`
|
|
1495
|
+
);
|
|
1496
|
+
const result = priceDifference.greaterThanOrEqualTo(
|
|
1497
|
+
avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen
|
|
1498
|
+
); // 500 for now
|
|
974
1499
|
logger.info(`result: ${result}`);
|
|
975
1500
|
return result;
|
|
976
1501
|
} else {
|
|
977
|
-
logger.info(
|
|
978
|
-
|
|
1502
|
+
logger.info(
|
|
1503
|
+
`price difference between avnu and extended for close position: ${priceDifference.toNumber()}, maximumExtendedPriceDifferenceForSwapClosing: ${
|
|
1504
|
+
avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing
|
|
1505
|
+
}`
|
|
1506
|
+
);
|
|
1507
|
+
const result = priceDifference.lessThanOrEqualTo(
|
|
1508
|
+
avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing
|
|
1509
|
+
); // 1000 for now
|
|
979
1510
|
logger.info(`result: ${result}`);
|
|
980
1511
|
return result;
|
|
981
1512
|
}
|
|
@@ -989,16 +1520,30 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
989
1520
|
async handleWithdraw(amount: Web3Number): Promise<TransactionResult[]> {
|
|
990
1521
|
try {
|
|
991
1522
|
const usdcBalanceVaultAllocator = await this.getUnusedBalance();
|
|
992
|
-
const usdcBalanceDifference = amount
|
|
1523
|
+
const usdcBalanceDifference = amount
|
|
1524
|
+
.plus(BUFFER_USDC_IN_WITHDRAWAL)
|
|
1525
|
+
.minus(usdcBalanceVaultAllocator.usdValue);
|
|
993
1526
|
logger.info(`usdcBalanceDifference, ${usdcBalanceDifference.toNumber()}`);
|
|
994
1527
|
let calls: Call[] = [];
|
|
995
1528
|
let status: boolean = true;
|
|
996
1529
|
if (usdcBalanceDifference.lessThan(0)) {
|
|
997
1530
|
const withdrawCall = await this.getBringLiquidityCall({
|
|
998
|
-
amount: usdcBalanceVaultAllocator.amount
|
|
999
|
-
})
|
|
1531
|
+
amount: usdcBalanceVaultAllocator.amount,
|
|
1532
|
+
});
|
|
1000
1533
|
calls.push(withdrawCall);
|
|
1001
|
-
return [
|
|
1534
|
+
return [
|
|
1535
|
+
this.createTransactionResult(
|
|
1536
|
+
calls,
|
|
1537
|
+
true,
|
|
1538
|
+
{
|
|
1539
|
+
from: Protocols.VAULT.name,
|
|
1540
|
+
to: Protocols.NONE.name,
|
|
1541
|
+
amount: amount,
|
|
1542
|
+
},
|
|
1543
|
+
"WITHDRAWAL",
|
|
1544
|
+
CycleType.WITHDRAWAL
|
|
1545
|
+
),
|
|
1546
|
+
];
|
|
1002
1547
|
}
|
|
1003
1548
|
const vesuAdapter = await this.getVesuAdapter();
|
|
1004
1549
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
@@ -1007,19 +1552,41 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
1007
1552
|
logger.error(
|
|
1008
1553
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
1009
1554
|
);
|
|
1010
|
-
return [
|
|
1555
|
+
return [
|
|
1556
|
+
this.createTransactionResult(
|
|
1557
|
+
calls,
|
|
1558
|
+
status,
|
|
1559
|
+
{
|
|
1560
|
+
from: Protocols.VAULT.name,
|
|
1561
|
+
to: Protocols.NONE.name,
|
|
1562
|
+
amount: amount,
|
|
1563
|
+
},
|
|
1564
|
+
"NONE",
|
|
1565
|
+
CycleType.WITHDRAWAL
|
|
1566
|
+
),
|
|
1567
|
+
];
|
|
1011
1568
|
}
|
|
1012
1569
|
let transactionResults: TransactionResult[] = [];
|
|
1013
1570
|
const { collateralTokenAmount } =
|
|
1014
1571
|
await vesuAdapter.vesuAdapter.getAssetPrices();
|
|
1015
|
-
const {
|
|
1016
|
-
collateralPrice
|
|
1017
|
-
} = await this.getAssetPrices();
|
|
1572
|
+
const { collateralPrice } = await this.getAssetPrices();
|
|
1018
1573
|
const extendedPositon = await extendedAdapter.getAllOpenPositions();
|
|
1019
1574
|
if (!extendedPositon) {
|
|
1020
1575
|
status = false;
|
|
1021
1576
|
logger.error("error getting extended position", extendedPositon);
|
|
1022
|
-
return [
|
|
1577
|
+
return [
|
|
1578
|
+
this.createTransactionResult(
|
|
1579
|
+
calls,
|
|
1580
|
+
status,
|
|
1581
|
+
{
|
|
1582
|
+
from: Protocols.VAULT.name,
|
|
1583
|
+
to: Protocols.NONE.name,
|
|
1584
|
+
amount: amount,
|
|
1585
|
+
},
|
|
1586
|
+
"NONE",
|
|
1587
|
+
CycleType.WITHDRAWAL
|
|
1588
|
+
),
|
|
1589
|
+
];
|
|
1023
1590
|
}
|
|
1024
1591
|
const amountDistributionForWithdrawal =
|
|
1025
1592
|
await calculateAmountDistributionForWithdrawal(
|
|
@@ -1033,17 +1600,33 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
1033
1600
|
logger.error(
|
|
1034
1601
|
`error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
|
|
1035
1602
|
);
|
|
1036
|
-
return [
|
|
1603
|
+
return [
|
|
1604
|
+
this.createTransactionResult(
|
|
1605
|
+
calls,
|
|
1606
|
+
status,
|
|
1607
|
+
{
|
|
1608
|
+
from: Protocols.VAULT.name,
|
|
1609
|
+
to: Protocols.NONE.name,
|
|
1610
|
+
amount: amount,
|
|
1611
|
+
},
|
|
1612
|
+
"NONE",
|
|
1613
|
+
CycleType.WITHDRAWAL
|
|
1614
|
+
),
|
|
1615
|
+
];
|
|
1037
1616
|
}
|
|
1038
1617
|
const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
|
|
1039
1618
|
|
|
1040
1619
|
if (status && vesu_amount.greaterThan(0)) {
|
|
1041
|
-
const {
|
|
1620
|
+
const {
|
|
1621
|
+
calls: vesuCalls,
|
|
1622
|
+
status: vesuStatus,
|
|
1623
|
+
transactionMetadata: vesuTransactionMetadata,
|
|
1624
|
+
} = await this.moveAssets(
|
|
1042
1625
|
{
|
|
1043
1626
|
amount: vesu_amount,
|
|
1044
1627
|
from: Protocols.VESU.name,
|
|
1045
1628
|
to: Protocols.VAULT.name,
|
|
1046
|
-
cycleType: CycleType.WITHDRAWAL
|
|
1629
|
+
cycleType: CycleType.WITHDRAWAL,
|
|
1047
1630
|
},
|
|
1048
1631
|
extendedAdapter,
|
|
1049
1632
|
vesuAdapter
|
|
@@ -1052,16 +1635,20 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
1052
1635
|
transactionResults.push({
|
|
1053
1636
|
status: vesuStatus,
|
|
1054
1637
|
calls: vesuCalls,
|
|
1055
|
-
transactionMetadata: vesuTransactionMetadata
|
|
1056
|
-
})
|
|
1638
|
+
transactionMetadata: vesuTransactionMetadata,
|
|
1639
|
+
});
|
|
1057
1640
|
}
|
|
1058
1641
|
if (status && extended_amount.greaterThan(0)) {
|
|
1059
|
-
const {
|
|
1642
|
+
const {
|
|
1643
|
+
calls: extendedCalls,
|
|
1644
|
+
status: extendedStatus,
|
|
1645
|
+
transactionMetadata: extendedTransactionMetadata,
|
|
1646
|
+
} = await this.moveAssets(
|
|
1060
1647
|
{
|
|
1061
1648
|
amount: extended_amount,
|
|
1062
1649
|
from: Protocols.EXTENDED.name,
|
|
1063
1650
|
to: Protocols.VAULT.name,
|
|
1064
|
-
cycleType: CycleType.WITHDRAWAL
|
|
1651
|
+
cycleType: CycleType.WITHDRAWAL,
|
|
1065
1652
|
},
|
|
1066
1653
|
extendedAdapter,
|
|
1067
1654
|
vesuAdapter
|
|
@@ -1071,16 +1658,30 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
1071
1658
|
transactionResults.push({
|
|
1072
1659
|
status: extendedStatus,
|
|
1073
1660
|
calls: extendedCalls,
|
|
1074
|
-
transactionMetadata: extendedTransactionMetadata
|
|
1075
|
-
})
|
|
1661
|
+
transactionMetadata: extendedTransactionMetadata,
|
|
1662
|
+
});
|
|
1076
1663
|
} else {
|
|
1077
|
-
logger.error(
|
|
1078
|
-
|
|
1664
|
+
logger.error(
|
|
1665
|
+
"error moving assets to vault: extendedStatus: ${extendedStatus}"
|
|
1666
|
+
);
|
|
1667
|
+
return [
|
|
1668
|
+
this.createTransactionResult(
|
|
1669
|
+
[],
|
|
1670
|
+
status,
|
|
1671
|
+
{
|
|
1672
|
+
from: Protocols.VAULT.name,
|
|
1673
|
+
to: Protocols.NONE.name,
|
|
1674
|
+
amount: amount,
|
|
1675
|
+
},
|
|
1676
|
+
"NONE",
|
|
1677
|
+
CycleType.WITHDRAWAL
|
|
1678
|
+
),
|
|
1679
|
+
];
|
|
1079
1680
|
}
|
|
1080
1681
|
}
|
|
1081
1682
|
const withdrawCall = await this.getBringLiquidityCall({
|
|
1082
|
-
amount: amount
|
|
1083
|
-
})
|
|
1683
|
+
amount: amount,
|
|
1684
|
+
});
|
|
1084
1685
|
logger.info("withdraw call", withdrawCall);
|
|
1085
1686
|
transactionResults.push({
|
|
1086
1687
|
status: status,
|
|
@@ -1090,18 +1691,34 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
1090
1691
|
protocolTo: Protocols.NONE.name,
|
|
1091
1692
|
transactionType: "WITHDRAWAL",
|
|
1092
1693
|
usdAmount: amount.toFixed(),
|
|
1093
|
-
status:
|
|
1094
|
-
cycleType: CycleType.WITHDRAWAL
|
|
1095
|
-
}
|
|
1096
|
-
})
|
|
1694
|
+
status: "PENDING",
|
|
1695
|
+
cycleType: CycleType.WITHDRAWAL,
|
|
1696
|
+
},
|
|
1697
|
+
});
|
|
1097
1698
|
return transactionResults;
|
|
1098
1699
|
} catch (err) {
|
|
1099
1700
|
logger.error(`error handling withdrawal: ${err}`);
|
|
1100
|
-
return [
|
|
1701
|
+
return [
|
|
1702
|
+
this.createTransactionResult(
|
|
1703
|
+
[],
|
|
1704
|
+
false,
|
|
1705
|
+
{
|
|
1706
|
+
from: Protocols.VAULT.name,
|
|
1707
|
+
to: Protocols.NONE.name,
|
|
1708
|
+
amount: amount,
|
|
1709
|
+
},
|
|
1710
|
+
"NONE",
|
|
1711
|
+
CycleType.WITHDRAWAL
|
|
1712
|
+
),
|
|
1713
|
+
];
|
|
1101
1714
|
}
|
|
1102
1715
|
}
|
|
1103
1716
|
|
|
1104
|
-
async getAUM(): Promise<{
|
|
1717
|
+
async getAUM(): Promise<{
|
|
1718
|
+
net: SingleTokenInfo;
|
|
1719
|
+
prevAum: Web3Number;
|
|
1720
|
+
splits: PositionInfo[];
|
|
1721
|
+
}> {
|
|
1105
1722
|
const allPositions: PositionInfo[] = [];
|
|
1106
1723
|
for (let adapter of this.metadata.additionalInfo.adapters) {
|
|
1107
1724
|
const positions = await adapter.adapter.getPositions();
|
|
@@ -1125,34 +1742,49 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
1125
1742
|
usdValue: netAUM.toNumber() * assetPrice.price,
|
|
1126
1743
|
apy: { apy: netAUM.toNumber() * assetPrice.price, type: APYType.BASE },
|
|
1127
1744
|
remarks: AUMTypes.FINALISED,
|
|
1128
|
-
protocol: Protocols.NONE // just placeholder
|
|
1745
|
+
protocol: Protocols.NONE, // just placeholder
|
|
1129
1746
|
};
|
|
1130
1747
|
|
|
1131
1748
|
const estimatedAUMDelta: PositionInfo = {
|
|
1132
1749
|
tokenInfo: this.asset(),
|
|
1133
|
-
amount: Web3Number.fromWei(
|
|
1750
|
+
amount: Web3Number.fromWei("0", this.asset().decimals),
|
|
1134
1751
|
usdValue: 0,
|
|
1135
1752
|
apy: { apy: 0, type: APYType.BASE },
|
|
1136
1753
|
remarks: AUMTypes.DEFISPRING,
|
|
1137
|
-
protocol: Protocols.NONE // just placeholder
|
|
1754
|
+
protocol: Protocols.NONE, // just placeholder
|
|
1138
1755
|
};
|
|
1139
1756
|
|
|
1140
1757
|
return {
|
|
1141
1758
|
net: {
|
|
1142
1759
|
tokenInfo: this.asset(),
|
|
1143
1760
|
amount: netAUM,
|
|
1144
|
-
usdValue: netAUM.toNumber() * assetPrice.price
|
|
1145
|
-
},
|
|
1761
|
+
usdValue: netAUM.toNumber() * assetPrice.price,
|
|
1762
|
+
},
|
|
1763
|
+
prevAum: prevAum,
|
|
1764
|
+
splits: [realAUM, estimatedAUMDelta],
|
|
1146
1765
|
};
|
|
1147
1766
|
}
|
|
1148
1767
|
|
|
1149
|
-
async processTransactionDataFromSDK(
|
|
1768
|
+
async processTransactionDataFromSDK(
|
|
1769
|
+
txnData: TransactionResult<any>[]
|
|
1770
|
+
): Promise<{
|
|
1771
|
+
callsToBeExecutedFinal: Call[];
|
|
1772
|
+
txnMetadata: TransactionMetadata[];
|
|
1773
|
+
} | null> {
|
|
1150
1774
|
try {
|
|
1151
|
-
const txnsToBeExecuted = txnData.filter(txn => {
|
|
1152
|
-
return
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1775
|
+
const txnsToBeExecuted = txnData.filter((txn) => {
|
|
1776
|
+
return (
|
|
1777
|
+
txn.transactionMetadata.transactionType !== "NONE" &&
|
|
1778
|
+
txn.transactionMetadata.protocolFrom !== "" &&
|
|
1779
|
+
txn.transactionMetadata.protocolTo !== ""
|
|
1780
|
+
);
|
|
1781
|
+
});
|
|
1782
|
+
const callsToBeExecutedFinal = txnsToBeExecuted.flatMap(
|
|
1783
|
+
(txn) => txn.calls
|
|
1784
|
+
);
|
|
1785
|
+
const txnMetadata = txnsToBeExecuted.map(
|
|
1786
|
+
(txn) => txn.transactionMetadata
|
|
1787
|
+
);
|
|
1156
1788
|
return { callsToBeExecutedFinal, txnMetadata };
|
|
1157
1789
|
} catch (err) {
|
|
1158
1790
|
logger.error(`error processing transaction data from SDK: ${err}`);
|
|
@@ -1160,18 +1792,23 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
1160
1792
|
}
|
|
1161
1793
|
}
|
|
1162
1794
|
|
|
1163
|
-
async processTransactionMetadata(
|
|
1795
|
+
async processTransactionMetadata(
|
|
1796
|
+
txnMetadata: TransactionMetadata[],
|
|
1797
|
+
extendedIntentFulfilled: boolean
|
|
1798
|
+
): Promise<TransactionMetadata[] | null> {
|
|
1164
1799
|
try {
|
|
1165
|
-
const txnMetadataNew = txnMetadata.map(txn => {
|
|
1166
|
-
const isExtendedProtocol =
|
|
1800
|
+
const txnMetadataNew = txnMetadata.map((txn) => {
|
|
1801
|
+
const isExtendedProtocol =
|
|
1802
|
+
txn.protocolFrom === Protocols.EXTENDED.name ||
|
|
1803
|
+
txn.protocolTo === Protocols.EXTENDED.name;
|
|
1167
1804
|
// Only update status for extended protocol transactions since thsoe only cause delays
|
|
1168
1805
|
if (isExtendedProtocol) {
|
|
1169
|
-
txn.status = extendedIntentFulfilled ?
|
|
1806
|
+
txn.status = extendedIntentFulfilled ? "COMPLETED" : "PENDING";
|
|
1170
1807
|
} else {
|
|
1171
|
-
txn.status =
|
|
1808
|
+
txn.status = "COMPLETED";
|
|
1172
1809
|
}
|
|
1173
1810
|
return txn;
|
|
1174
|
-
})
|
|
1811
|
+
});
|
|
1175
1812
|
return txnMetadataNew;
|
|
1176
1813
|
} catch (err) {
|
|
1177
1814
|
logger.error(`error processing transaction data from SDK: ${err}`);
|
|
@@ -1185,23 +1822,43 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
1185
1822
|
if (!vesuAdapter || !extendedAdapter) {
|
|
1186
1823
|
return new Web3Number(0, 0);
|
|
1187
1824
|
}
|
|
1188
|
-
const extendedFundingRate = new Web3Number(
|
|
1825
|
+
const extendedFundingRate = new Web3Number(
|
|
1826
|
+
(await extendedAdapter.getNetAPY()).toFixed(4),
|
|
1827
|
+
0
|
|
1828
|
+
);
|
|
1189
1829
|
const extendedPositions = await extendedAdapter.getAllOpenPositions();
|
|
1190
1830
|
if (!extendedPositions || extendedPositions.length === 0) {
|
|
1191
1831
|
logger.info(`no extended positions found`);
|
|
1192
1832
|
return new Web3Number(0, 0);
|
|
1193
1833
|
}
|
|
1194
|
-
const extendePositionSizeUSD = new Web3Number(
|
|
1834
|
+
const extendePositionSizeUSD = new Web3Number(
|
|
1835
|
+
extendedPositions[0].value || 0,
|
|
1836
|
+
0
|
|
1837
|
+
);
|
|
1195
1838
|
const vesuPositions = await vesuAdapter.getPositions();
|
|
1196
1839
|
const vesuSupplyApy = vesuPositions[0].apy.apy;
|
|
1197
|
-
const vesuCollateralSizeUSD = new Web3Number(
|
|
1198
|
-
|
|
1199
|
-
|
|
1840
|
+
const vesuCollateralSizeUSD = new Web3Number(
|
|
1841
|
+
vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS),
|
|
1842
|
+
USDC_TOKEN_DECIMALS
|
|
1843
|
+
);
|
|
1844
|
+
const vesuDebtSizeUSD = new Web3Number(
|
|
1845
|
+
vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS),
|
|
1846
|
+
USDC_TOKEN_DECIMALS
|
|
1847
|
+
);
|
|
1848
|
+
const num1 = extendePositionSizeUSD.multipliedBy(extendedFundingRate);
|
|
1200
1849
|
const num2 = vesuCollateralSizeUSD.multipliedBy(vesuSupplyApy);
|
|
1201
|
-
const num3 = vesuDebtSizeUSD.abs()
|
|
1850
|
+
const num3 = vesuDebtSizeUSD.abs();
|
|
1202
1851
|
const maxBorrowApy = num1.plus(num2).minus(0.1).dividedBy(num3);
|
|
1203
|
-
const vesuMaxBorrowableAmount =
|
|
1204
|
-
|
|
1852
|
+
const vesuMaxBorrowableAmount =
|
|
1853
|
+
await vesuAdapter.vesuAdapter.getMaxBorrowableByInterestRate(
|
|
1854
|
+
this.config,
|
|
1855
|
+
vesuAdapter.config.debt,
|
|
1856
|
+
maxBorrowApy.toNumber()
|
|
1857
|
+
);
|
|
1858
|
+
return new Web3Number(
|
|
1859
|
+
vesuMaxBorrowableAmount.toFixed(USDC_TOKEN_DECIMALS),
|
|
1860
|
+
USDC_TOKEN_DECIMALS
|
|
1861
|
+
);
|
|
1205
1862
|
}
|
|
1206
1863
|
|
|
1207
1864
|
async getVesuHealthFactors(): Promise<number[]> {
|
|
@@ -1211,83 +1868,124 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
1211
1868
|
return [0, 0];
|
|
1212
1869
|
}
|
|
1213
1870
|
const vesuPositions = await vesuAdapter.getPositions();
|
|
1214
|
-
const vesuCollateralSizeUSD = new Web3Number(
|
|
1215
|
-
|
|
1871
|
+
const vesuCollateralSizeUSD = new Web3Number(
|
|
1872
|
+
vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS),
|
|
1873
|
+
0
|
|
1874
|
+
);
|
|
1875
|
+
const vesuDebtSizeUSD = new Web3Number(
|
|
1876
|
+
vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS),
|
|
1877
|
+
0
|
|
1878
|
+
);
|
|
1216
1879
|
const actualLtv = vesuDebtSizeUSD.dividedBy(vesuCollateralSizeUSD).abs();
|
|
1217
1880
|
logger.info(`actualLtv: ${actualLtv.toNumber()}`);
|
|
1218
|
-
const maxLtv = new Web3Number(
|
|
1219
|
-
|
|
1881
|
+
const maxLtv = new Web3Number(
|
|
1882
|
+
await vesuAdapter.vesuAdapter.getLTVConfig(this.config),
|
|
1883
|
+
4
|
|
1884
|
+
);
|
|
1885
|
+
const healthFactor = new Web3Number(
|
|
1886
|
+
maxLtv.dividedBy(actualLtv).toFixed(4),
|
|
1887
|
+
4
|
|
1888
|
+
);
|
|
1220
1889
|
logger.info(`healthFactor: ${healthFactor.toNumber()}`);
|
|
1221
1890
|
const extendedBalance = await extendedAdapter.getExtendedDepositAmount();
|
|
1222
1891
|
if (!extendedBalance) {
|
|
1223
1892
|
return [0, 0];
|
|
1224
1893
|
}
|
|
1225
|
-
const extendedLeverage = new Web3Number(
|
|
1894
|
+
const extendedLeverage = new Web3Number(
|
|
1895
|
+
(Number(extendedBalance.marginRatio) * 100).toFixed(4),
|
|
1896
|
+
4
|
|
1897
|
+
);
|
|
1226
1898
|
logger.info(`extendedLeverage: ${extendedLeverage.toNumber()}`);
|
|
1227
1899
|
return [healthFactor.toNumber(), extendedLeverage.toNumber()];
|
|
1228
1900
|
}
|
|
1229
1901
|
|
|
1230
|
-
async netAPY(): Promise<{
|
|
1902
|
+
async netAPY(): Promise<{
|
|
1903
|
+
net: number;
|
|
1904
|
+
splits: { apy: number; id: string }[];
|
|
1905
|
+
}> {
|
|
1231
1906
|
const allPositions: PositionInfo[] = [];
|
|
1232
1907
|
for (let adapter of this.metadata.additionalInfo.adapters) {
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
}
|
|
1908
|
+
if (adapter.adapter.name !== ExtendedAdapter.name) {
|
|
1909
|
+
let positions = await adapter.adapter.getPositions();
|
|
1910
|
+
if (positions.length > 0) {
|
|
1911
|
+
allPositions.push(...positions);
|
|
1238
1912
|
}
|
|
1239
1913
|
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1914
|
+
}
|
|
1915
|
+
const extendedAdapter = await this.getExtendedAdapter();
|
|
1916
|
+
if (!extendedAdapter) {
|
|
1242
1917
|
return {
|
|
1243
1918
|
net: 0,
|
|
1244
|
-
splits: []
|
|
1245
|
-
}
|
|
1919
|
+
splits: [],
|
|
1920
|
+
};
|
|
1246
1921
|
}
|
|
1247
|
-
let vesuPositions = allPositions.filter(
|
|
1248
|
-
|
|
1922
|
+
let vesuPositions = allPositions.filter(
|
|
1923
|
+
(item) => item.protocol === Protocols.VESU
|
|
1924
|
+
);
|
|
1925
|
+
vesuPositions.map((item) => {
|
|
1249
1926
|
item.apy.apy = item.apy.apy * 0.1;
|
|
1250
|
-
})
|
|
1927
|
+
});
|
|
1251
1928
|
const extendedPositions = await extendedAdapter.getAllOpenPositions();
|
|
1252
|
-
const usdcToken = Global.getDefaultTokens().find(
|
|
1253
|
-
|
|
1929
|
+
const usdcToken = Global.getDefaultTokens().find(
|
|
1930
|
+
(token) => token.symbol === "USDC"
|
|
1931
|
+
);
|
|
1932
|
+
if (!extendedPositions || !usdcToken) {
|
|
1254
1933
|
return {
|
|
1255
1934
|
net: 0,
|
|
1256
|
-
splits: []
|
|
1257
|
-
}
|
|
1935
|
+
splits: [],
|
|
1936
|
+
};
|
|
1258
1937
|
}
|
|
1259
1938
|
const extendedPosition = extendedPositions[0] || 0;
|
|
1260
|
-
const extendedEquity =
|
|
1939
|
+
const extendedEquity =
|
|
1940
|
+
(await extendedAdapter.getExtendedDepositAmount())?.equity || 0;
|
|
1261
1941
|
const extendedApy = await extendedAdapter.getNetAPY();
|
|
1262
|
-
const totalHoldingsUSDValue =
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1942
|
+
const totalHoldingsUSDValue =
|
|
1943
|
+
allPositions.reduce((acc, curr) => acc + curr.usdValue, 0) +
|
|
1944
|
+
Number(extendedEquity);
|
|
1945
|
+
console.log(totalHoldingsUSDValue);
|
|
1946
|
+
const extendedPositionSizeMultipliedByApy =
|
|
1947
|
+
Number(extendedPosition.value) * extendedApy;
|
|
1948
|
+
let weightedAPYs =
|
|
1949
|
+
allPositions.reduce(
|
|
1950
|
+
(acc, curr) => acc + curr.apy.apy * curr.usdValue,
|
|
1951
|
+
0
|
|
1952
|
+
) + extendedPositionSizeMultipliedByApy;
|
|
1953
|
+
console.log(weightedAPYs);
|
|
1267
1954
|
const netAPY = weightedAPYs / totalHoldingsUSDValue;
|
|
1268
|
-
console.log(netAPY)
|
|
1955
|
+
console.log(netAPY);
|
|
1269
1956
|
allPositions.push({
|
|
1270
1957
|
tokenInfo: usdcToken,
|
|
1271
1958
|
amount: new Web3Number(extendedPosition.size, 0),
|
|
1272
1959
|
usdValue: Number(extendedEquity),
|
|
1273
1960
|
apy: { apy: extendedApy, type: APYType.BASE },
|
|
1274
1961
|
remarks: AUMTypes.FINALISED,
|
|
1275
|
-
protocol: Protocols.EXTENDED
|
|
1276
|
-
})
|
|
1962
|
+
protocol: Protocols.EXTENDED,
|
|
1963
|
+
});
|
|
1277
1964
|
return {
|
|
1278
1965
|
net: netAPY,
|
|
1279
|
-
splits: allPositions.map(p => ({
|
|
1966
|
+
splits: allPositions.map((p) => ({
|
|
1967
|
+
apy: p.apy.apy,
|
|
1968
|
+
id: p.remarks ?? "",
|
|
1969
|
+
})),
|
|
1280
1970
|
};
|
|
1281
1971
|
}
|
|
1282
1972
|
|
|
1283
|
-
async getWalletHoldings(): Promise<
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
const
|
|
1973
|
+
async getWalletHoldings(): Promise<
|
|
1974
|
+
{
|
|
1975
|
+
tokenInfo: TokenInfo;
|
|
1976
|
+
amount: Web3Number;
|
|
1977
|
+
usdValue: number;
|
|
1978
|
+
}[]
|
|
1979
|
+
> {
|
|
1980
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
1981
|
+
(token) => token.symbol === "USDCe"
|
|
1982
|
+
);
|
|
1983
|
+
const wbtcToken = Global.getDefaultTokens().find(
|
|
1984
|
+
(token) => token.symbol === "WBTC"
|
|
1985
|
+
);
|
|
1986
|
+
const usdcToken = Global.getDefaultTokens().find(
|
|
1987
|
+
(token) => token.symbol === "USDC"
|
|
1988
|
+
);
|
|
1291
1989
|
if (!usdceToken || !wbtcToken || !usdcToken) {
|
|
1292
1990
|
return [];
|
|
1293
1991
|
}
|
|
@@ -1309,23 +2007,29 @@ export class VesuExtendedMultiplierStrategy<
|
|
|
1309
2007
|
);
|
|
1310
2008
|
const price = await this.pricer.getPrice(usdceToken.symbol);
|
|
1311
2009
|
const wbtcPrice = await this.pricer.getPrice(wbtcToken.symbol);
|
|
1312
|
-
const usdceUsdValue =
|
|
1313
|
-
|
|
1314
|
-
const
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
2010
|
+
const usdceUsdValue =
|
|
2011
|
+
Number(usdceWalletBalance.toFixed(usdceToken.decimals)) * price.price;
|
|
2012
|
+
const usdcUsdValue =
|
|
2013
|
+
Number(usdcWalletBalance.toFixed(usdcToken.decimals)) * price.price;
|
|
2014
|
+
const wbtcUsdValue =
|
|
2015
|
+
Number(wbtcWalletBalance.toFixed(wbtcToken.decimals)) * wbtcPrice.price;
|
|
2016
|
+
return [
|
|
2017
|
+
{
|
|
2018
|
+
tokenInfo: usdceToken,
|
|
2019
|
+
amount: usdceWalletBalance,
|
|
2020
|
+
usdValue: usdceUsdValue,
|
|
2021
|
+
},
|
|
2022
|
+
{
|
|
2023
|
+
tokenInfo: usdcToken,
|
|
2024
|
+
amount: usdcWalletBalance,
|
|
2025
|
+
usdValue: usdcUsdValue,
|
|
2026
|
+
},
|
|
2027
|
+
{
|
|
2028
|
+
tokenInfo: wbtcToken,
|
|
2029
|
+
amount: wbtcWalletBalance,
|
|
2030
|
+
usdValue: wbtcUsdValue,
|
|
2031
|
+
},
|
|
2032
|
+
];
|
|
1329
2033
|
}
|
|
1330
2034
|
}
|
|
1331
2035
|
|
|
@@ -1341,7 +2045,7 @@ function getLooperSettings(
|
|
|
1341
2045
|
minimumVesuMovementAmount: number,
|
|
1342
2046
|
minimumExtendedRetriesDelayForOrderStatus: number,
|
|
1343
2047
|
minimumExtendedPriceDifferenceForSwapOpen: number,
|
|
1344
|
-
maximumExtendedPriceDifferenceForSwapClosing: number
|
|
2048
|
+
maximumExtendedPriceDifferenceForSwapClosing: number
|
|
1345
2049
|
) {
|
|
1346
2050
|
vaultSettings.leafAdapters = [];
|
|
1347
2051
|
|
|
@@ -1370,15 +2074,15 @@ function getLooperSettings(
|
|
|
1370
2074
|
avnuContract: AVNU_MIDDLEWARE,
|
|
1371
2075
|
slippage: 0.01,
|
|
1372
2076
|
baseUrl: AVNU_QUOTE_URL,
|
|
1373
|
-
minimumExtendedPriceDifferenceForSwapOpen:
|
|
1374
|
-
|
|
2077
|
+
minimumExtendedPriceDifferenceForSwapOpen:
|
|
2078
|
+
minimumExtendedPriceDifferenceForSwapOpen,
|
|
2079
|
+
maximumExtendedPriceDifferenceForSwapClosing:
|
|
2080
|
+
maximumExtendedPriceDifferenceForSwapClosing,
|
|
1375
2081
|
});
|
|
1376
2082
|
|
|
1377
2083
|
const extendedAdapter = new ExtendedAdapter({
|
|
1378
2084
|
...baseAdapterConfig,
|
|
1379
|
-
supportedPositions: [
|
|
1380
|
-
{ asset: usdcToken, isDebt: true },
|
|
1381
|
-
],
|
|
2085
|
+
supportedPositions: [{ asset: usdcToken, isDebt: true }],
|
|
1382
2086
|
vaultIdExtended: vaultIdExtended,
|
|
1383
2087
|
extendedContract: EXTENDED_CONTRACT,
|
|
1384
2088
|
extendedBackendWriteUrl: extendedBackendWriteUrl,
|
|
@@ -1441,11 +2145,11 @@ function getLooperSettings(
|
|
|
1441
2145
|
});
|
|
1442
2146
|
|
|
1443
2147
|
vaultSettings.leafAdapters.push(() => vesuMultiplyAdapter.getDepositLeaf());
|
|
2148
|
+
vaultSettings.leafAdapters.push(() => vesuMultiplyAdapter.getWithdrawLeaf());
|
|
2149
|
+
vaultSettings.leafAdapters.push(() => extendedAdapter.getDepositLeaf());
|
|
1444
2150
|
vaultSettings.leafAdapters.push(() =>
|
|
1445
|
-
|
|
2151
|
+
extendedAdapter.getSwapFromLegacyLeaf()
|
|
1446
2152
|
);
|
|
1447
|
-
vaultSettings.leafAdapters.push(() => extendedAdapter.getDepositLeaf());
|
|
1448
|
-
vaultSettings.leafAdapters.push(() => extendedAdapter.getSwapFromLegacyLeaf());
|
|
1449
2153
|
vaultSettings.leafAdapters.push(() => avnuAdapter.getDepositLeaf());
|
|
1450
2154
|
vaultSettings.leafAdapters.push(() => avnuAdapter.getWithdrawLeaf());
|
|
1451
2155
|
vaultSettings.leafAdapters.push(
|
|
@@ -1466,7 +2170,6 @@ function getLooperSettings(
|
|
|
1466
2170
|
return vaultSettings;
|
|
1467
2171
|
}
|
|
1468
2172
|
|
|
1469
|
-
|
|
1470
2173
|
function getDescription(tokenSymbol: string, underlyingSymbol: string) {
|
|
1471
2174
|
return VaultDescription(tokenSymbol, underlyingSymbol);
|
|
1472
2175
|
}
|
|
@@ -1486,26 +2189,64 @@ export default function VaultDescription(
|
|
|
1486
2189
|
|
|
1487
2190
|
return (
|
|
1488
2191
|
<div style={containerStyle}>
|
|
1489
|
-
<h1 style={{ fontSize: "18px", marginBottom: "10px" }}>
|
|
2192
|
+
<h1 style={{ fontSize: "18px", marginBottom: "10px" }}>
|
|
2193
|
+
Liquidation risk managed leverged {lstSymbol} Vault
|
|
2194
|
+
</h1>
|
|
1490
2195
|
<p style={{ fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }}>
|
|
1491
|
-
This Levered Endur {lstSymbol} vault is a tokenized leveraged Vault,
|
|
1492
|
-
|
|
1493
|
-
|
|
2196
|
+
This Levered Endur {lstSymbol} vault is a tokenized leveraged Vault,
|
|
2197
|
+
auto-compounding strategy that takes upto 5x leverage on {lstSymbol} by
|
|
2198
|
+
borrow {underlyingSymbol}. Borrowed amount is swapped to {lstSymbol} to
|
|
2199
|
+
create leverage. Depositors receive vault shares that represent a
|
|
2200
|
+
proportional claim on the underlying assets and accrued yield.
|
|
1494
2201
|
</p>
|
|
1495
2202
|
|
|
1496
2203
|
<p style={{ fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }}>
|
|
1497
|
-
This vault uses Vesu for lending and borrowing. The oracle used by this
|
|
1498
|
-
{" "}
|
|
2204
|
+
This vault uses Vesu for lending and borrowing. The oracle used by this
|
|
2205
|
+
pool is a{" "}
|
|
2206
|
+
{highlightTextWithLinks("conversion rate oracle", [
|
|
2207
|
+
{
|
|
2208
|
+
highlight: "conversion rate oracle",
|
|
2209
|
+
link: "https://docs.pragma.build/starknet/development#conversion-rate",
|
|
2210
|
+
},
|
|
2211
|
+
])}{" "}
|
|
2212
|
+
which is resilient to liquidity issues and price volatility, hence
|
|
2213
|
+
reducing the risk of liquidation. However, overtime, if left
|
|
2214
|
+
un-monitored, debt can increase enough to trigger a liquidation. But no
|
|
2215
|
+
worries, our continuous monitoring systems look for situations with
|
|
2216
|
+
reduced health factor and balance collateral/debt to bring it back to
|
|
2217
|
+
safe levels. With Troves, you can have a peaceful sleep.
|
|
1499
2218
|
</p>
|
|
1500
2219
|
|
|
1501
|
-
<div
|
|
2220
|
+
<div
|
|
2221
|
+
style={{
|
|
2222
|
+
backgroundColor: "#222",
|
|
2223
|
+
padding: "10px",
|
|
2224
|
+
borderRadius: "8px",
|
|
2225
|
+
marginBottom: "20px",
|
|
2226
|
+
border: "1px solid #444",
|
|
2227
|
+
}}
|
|
2228
|
+
>
|
|
1502
2229
|
<p style={{ fontSize: "13px", color: "#ccc" }}>
|
|
1503
|
-
<strong>Withdrawals:</strong> Requests can take up to
|
|
2230
|
+
<strong>Withdrawals:</strong> Requests can take up to{" "}
|
|
2231
|
+
<strong>1-2 hours</strong> to process as the vault unwinds and settles
|
|
2232
|
+
routing.
|
|
1504
2233
|
</p>
|
|
1505
2234
|
</div>
|
|
1506
|
-
<div
|
|
2235
|
+
<div
|
|
2236
|
+
style={{
|
|
2237
|
+
backgroundColor: "#222",
|
|
2238
|
+
padding: "10px",
|
|
2239
|
+
borderRadius: "8px",
|
|
2240
|
+
marginBottom: "20px",
|
|
2241
|
+
border: "1px solid #444",
|
|
2242
|
+
}}
|
|
2243
|
+
>
|
|
1507
2244
|
<p style={{ fontSize: "13px", color: "#ccc" }}>
|
|
1508
|
-
<strong>Debt limits:</strong> Pools on Vesu have debt caps that are
|
|
2245
|
+
<strong>Debt limits:</strong> Pools on Vesu have debt caps that are
|
|
2246
|
+
gradually increased over time. Until caps are raised, deposited Tokens
|
|
2247
|
+
remain in the vault, generating a shared net return for all
|
|
2248
|
+
depositors. There is no additional fee taken by Troves on Yield
|
|
2249
|
+
token's APY, its only on added gain.
|
|
1509
2250
|
</p>
|
|
1510
2251
|
</div>
|
|
1511
2252
|
{/* <div style={{ backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }}>
|
|
@@ -1518,11 +2259,21 @@ export default function VaultDescription(
|
|
|
1518
2259
|
}
|
|
1519
2260
|
|
|
1520
2261
|
const re7UsdcPrimeDevansh: VesuExtendedStrategySettings = {
|
|
1521
|
-
vaultAddress: ContractAddr.from(
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
2262
|
+
vaultAddress: ContractAddr.from(
|
|
2263
|
+
"0x058905be22d6a81792df79425dc9641cf3e1b77f36748631b7d7e5d713a32b55"
|
|
2264
|
+
),
|
|
2265
|
+
manager: ContractAddr.from(
|
|
2266
|
+
"0x02648d703783feb2d967cf0520314cb5aa800d69a9426f3e3b317395af44de16"
|
|
2267
|
+
),
|
|
2268
|
+
vaultAllocator: ContractAddr.from(
|
|
2269
|
+
"0x07d533c838eab6a4d854dd3aea96a55993fccd35821921970d00bde946b63b6f"
|
|
2270
|
+
),
|
|
2271
|
+
redeemRequestNFT: ContractAddr.from(
|
|
2272
|
+
"0x01ef91f08fb99729c00f82fc6e0ece37917bcc43952596c19996259dc8adbbba"
|
|
2273
|
+
),
|
|
2274
|
+
aumOracle: ContractAddr.from(
|
|
2275
|
+
"0x030b6acfec162f5d6e72b8a4d2798aedce78fb39de78a8f549f7cd277ae8bc8d"
|
|
2276
|
+
),
|
|
1526
2277
|
leafAdapters: [],
|
|
1527
2278
|
adapters: [],
|
|
1528
2279
|
targetHealthFactor: 1.4,
|
|
@@ -1534,34 +2285,88 @@ const re7UsdcPrimeDevansh: VesuExtendedStrategySettings = {
|
|
|
1534
2285
|
"0.001",
|
|
1535
2286
|
Global.getDefaultTokens().find((token) => token.symbol === "WBTC")!.decimals
|
|
1536
2287
|
),
|
|
1537
|
-
borrowable_assets: [
|
|
2288
|
+
borrowable_assets: [
|
|
2289
|
+
Global.getDefaultTokens().find((token) => token.symbol === "WBTC")!,
|
|
2290
|
+
],
|
|
1538
2291
|
minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP,
|
|
1539
2292
|
walletAddress: WALLET_ADDRESS,
|
|
1540
|
-
}
|
|
2293
|
+
};
|
|
1541
2294
|
|
|
1542
|
-
export const VesuExtendedTestStrategies = (
|
|
2295
|
+
export const VesuExtendedTestStrategies = (
|
|
2296
|
+
extendedBackendReadUrl: string,
|
|
2297
|
+
extendedBackendWriteUrl: string,
|
|
2298
|
+
vaultIdExtended: number,
|
|
2299
|
+
minimumExtendedMovementAmount: number,
|
|
2300
|
+
minimumVesuMovementAmount: number,
|
|
2301
|
+
minimumExtendedRetriesDelayForOrderStatus: number,
|
|
2302
|
+
minimumExtendedPriceDifferenceForSwapOpen: number,
|
|
2303
|
+
maximumExtendedPriceDifferenceForSwapClosing: number
|
|
2304
|
+
): IStrategyMetadata<VesuExtendedStrategySettings>[] => {
|
|
1543
2305
|
return [
|
|
1544
|
-
getStrategySettingsVesuExtended(
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
2306
|
+
getStrategySettingsVesuExtended(
|
|
2307
|
+
"WBTC",
|
|
2308
|
+
"USDC",
|
|
2309
|
+
re7UsdcPrimeDevansh,
|
|
2310
|
+
false,
|
|
2311
|
+
false,
|
|
2312
|
+
extendedBackendReadUrl,
|
|
2313
|
+
extendedBackendWriteUrl,
|
|
2314
|
+
vaultIdExtended,
|
|
2315
|
+
minimumExtendedMovementAmount,
|
|
2316
|
+
minimumVesuMovementAmount,
|
|
2317
|
+
minimumExtendedRetriesDelayForOrderStatus,
|
|
2318
|
+
minimumExtendedPriceDifferenceForSwapOpen,
|
|
2319
|
+
maximumExtendedPriceDifferenceForSwapClosing
|
|
2320
|
+
),
|
|
2321
|
+
];
|
|
2322
|
+
};
|
|
2323
|
+
|
|
2324
|
+
function getStrategySettingsVesuExtended(
|
|
2325
|
+
lstSymbol: string,
|
|
2326
|
+
underlyingSymbol: string,
|
|
2327
|
+
addresses: VesuExtendedStrategySettings,
|
|
2328
|
+
isPreview: boolean = false,
|
|
2329
|
+
isLST: boolean,
|
|
2330
|
+
extendedBackendReadUrl: string,
|
|
2331
|
+
extendedBackendWriteUrl: string,
|
|
2332
|
+
vaultIdExtended: number,
|
|
2333
|
+
minimumExtendedMovementAmount: number,
|
|
2334
|
+
minimumVesuMovementAmount: number,
|
|
2335
|
+
minimumExtendedRetriesDelayForOrderStatus: number,
|
|
2336
|
+
minimumExtendedPriceDifferenceForSwapOpen: number,
|
|
2337
|
+
maximumExtendedPriceDifferenceForSwapClosing: number
|
|
2338
|
+
): IStrategyMetadata<VesuExtendedStrategySettings> {
|
|
1551
2339
|
return {
|
|
1552
2340
|
name: `Extended Test ${underlyingSymbol}`,
|
|
1553
2341
|
description: getDescription(lstSymbol, underlyingSymbol),
|
|
1554
2342
|
address: addresses.vaultAddress,
|
|
1555
2343
|
launchBlock: 0,
|
|
1556
|
-
type:
|
|
1557
|
-
depositTokens: [
|
|
1558
|
-
|
|
2344
|
+
type: "Other",
|
|
2345
|
+
depositTokens: [
|
|
2346
|
+
Global.getDefaultTokens().find(
|
|
2347
|
+
(token) => token.symbol === underlyingSymbol
|
|
2348
|
+
)!,
|
|
2349
|
+
],
|
|
2350
|
+
additionalInfo: getLooperSettings(
|
|
2351
|
+
lstSymbol,
|
|
2352
|
+
underlyingSymbol,
|
|
2353
|
+
addresses,
|
|
2354
|
+
VesuPools.Re7USDCPrime,
|
|
2355
|
+
extendedBackendReadUrl,
|
|
2356
|
+
extendedBackendWriteUrl,
|
|
2357
|
+
vaultIdExtended,
|
|
2358
|
+
minimumExtendedMovementAmount,
|
|
2359
|
+
minimumVesuMovementAmount,
|
|
2360
|
+
minimumExtendedRetriesDelayForOrderStatus,
|
|
2361
|
+
minimumExtendedPriceDifferenceForSwapOpen,
|
|
2362
|
+
maximumExtendedPriceDifferenceForSwapClosing
|
|
2363
|
+
),
|
|
1559
2364
|
risk: {
|
|
1560
2365
|
riskFactor: _riskFactor,
|
|
1561
2366
|
netRisk:
|
|
1562
2367
|
_riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
|
|
1563
2368
|
_riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
1564
|
-
notARisks: getNoRiskTags(_riskFactor)
|
|
2369
|
+
notARisks: getNoRiskTags(_riskFactor),
|
|
1565
2370
|
},
|
|
1566
2371
|
auditUrl: AUDIT_URL,
|
|
1567
2372
|
protocols: [Protocols.ENDUR, Protocols.VESU],
|
|
@@ -1570,6 +2375,8 @@ function getStrategySettingsVesuExtended(lstSymbol: string, underlyingSymbol: st
|
|
|
1570
2375
|
faqs: getFAQs(lstSymbol, underlyingSymbol, isLST),
|
|
1571
2376
|
investmentSteps: getInvestmentSteps(lstSymbol, underlyingSymbol),
|
|
1572
2377
|
isPreview: isPreview,
|
|
1573
|
-
apyMethodology: isLST
|
|
1574
|
-
|
|
1575
|
-
|
|
2378
|
+
apyMethodology: isLST
|
|
2379
|
+
? "Current annualized APY in terms of base asset of the LST. There is no additional fee taken by Troves on LST APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown."
|
|
2380
|
+
: "Current annualized APY in terms of base asset of the Yield Token. There is no additional fee taken by Troves on yield token APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown.",
|
|
2381
|
+
};
|
|
2382
|
+
}
|