@strkfarm/sdk 2.0.0-dev.1 → 2.0.0-dev.10
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 +1314 -384
- package/dist/index.browser.mjs +1314 -384
- package/dist/index.d.ts +48 -9
- package/dist/index.js +1315 -384
- package/dist/index.mjs +1314 -384
- package/package.json +1 -1
- package/src/dataTypes/address.ts +1 -1
- package/src/modules/ekubo-quoter.ts +1 -12
- package/src/strategies/universal-adapters/avnu-adapter.ts +11 -14
- package/src/strategies/universal-adapters/extended-adapter.ts +514 -86
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +790 -408
- package/src/strategies/universal-lst-muliplier-strategy.tsx +2 -1
- package/src/strategies/universal-strategy.tsx +5 -0
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +8 -2
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +3 -1
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +21 -25
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +533 -115
|
@@ -28684,6 +28684,7 @@ ${r2}}` : "}", l2;
|
|
|
28684
28684
|
OrderType: () => OrderType,
|
|
28685
28685
|
PRICE_ROUTER: () => PRICE_ROUTER,
|
|
28686
28686
|
PositionSide: () => PositionSide,
|
|
28687
|
+
PositionTypeAvnuExtended: () => PositionTypeAvnuExtended,
|
|
28687
28688
|
Pragma: () => Pragma,
|
|
28688
28689
|
Pricer: () => Pricer,
|
|
28689
28690
|
PricerBase: () => PricerBase,
|
|
@@ -55997,20 +55998,13 @@ ${JSON.stringify(data, null, 2)}`;
|
|
|
55997
55998
|
async getDexPrice(baseToken, quoteToken, amount) {
|
|
55998
55999
|
const lstTokenInfo = baseToken;
|
|
55999
56000
|
const lstUnderlyingTokenInfo = quoteToken;
|
|
56000
|
-
console.log("lstTokenInfo", lstTokenInfo);
|
|
56001
|
-
console.log("lstUnderlyingTokenInfo", lstUnderlyingTokenInfo);
|
|
56002
|
-
console.log("amount", amount);
|
|
56003
56001
|
const quote = await this.getQuote(
|
|
56004
56002
|
lstTokenInfo.address.address,
|
|
56005
56003
|
lstUnderlyingTokenInfo.address.address,
|
|
56006
56004
|
amount
|
|
56007
56005
|
);
|
|
56008
|
-
console.log("quote", quote);
|
|
56009
56006
|
const outputAmount = Web3Number.fromWei(quote.total_calculated, lstUnderlyingTokenInfo.decimals);
|
|
56010
|
-
console.log("outputAmount", outputAmount);
|
|
56011
|
-
console.log("amount", amount);
|
|
56012
56007
|
const price = outputAmount.toNumber() / amount.toNumber();
|
|
56013
|
-
console.log("price", price);
|
|
56014
56008
|
logger2.verbose(`${_EkuboQuoter.name}:: LST Dex Price: ${price}`);
|
|
56015
56009
|
return price;
|
|
56016
56010
|
}
|
|
@@ -56029,16 +56023,12 @@ ${JSON.stringify(data, null, 2)}`;
|
|
|
56029
56023
|
// debt collateral
|
|
56030
56024
|
async getSwapLimitAmount(fromToken, toToken, amount, max_slippage = 2e-3) {
|
|
56031
56025
|
const isExactAmountIn = amount.greaterThanOrEqualTo(0);
|
|
56032
|
-
console.log("isExactAmountIn", isExactAmountIn);
|
|
56033
56026
|
logger2.verbose(`${_EkuboQuoter.name}::getSwapLimitAmount isExactAmountIn: ${isExactAmountIn}, fromToken: ${fromToken.symbol}, toToken: ${toToken.symbol}, amount: ${amount}`);
|
|
56034
56027
|
const isYieldToken = this.tokenMarketData.isAPYSupported(toToken);
|
|
56035
56028
|
console.log("isYieldToken", isYieldToken);
|
|
56036
56029
|
const baseToken = isExactAmountIn ? toToken : fromToken;
|
|
56037
56030
|
const quoteToken = isExactAmountIn ? fromToken : toToken;
|
|
56038
|
-
console.log("baseToken", baseToken);
|
|
56039
|
-
console.log("quoteToken", quoteToken);
|
|
56040
56031
|
const dexPrice = await this.getDexPrice(baseToken, quoteToken, amount);
|
|
56041
|
-
console.log("dexPrice", dexPrice);
|
|
56042
56032
|
const trueExchangeRate = isYieldToken ? await this.tokenMarketData.getTruePrice(baseToken) : dexPrice;
|
|
56043
56033
|
console.log("trueExchangeRate", trueExchangeRate);
|
|
56044
56034
|
if (isExactAmountIn) {
|
|
@@ -92375,6 +92365,7 @@ spurious results.`);
|
|
|
92375
92365
|
var AVNU_API = "https://starknet.api.avnu.fi/swap/v2/quotes";
|
|
92376
92366
|
var USDC_TOKEN_DECIMALS = 6;
|
|
92377
92367
|
var USDC_TOKEN_ADDRESS = "0x053C91253BC9682c04929cA02ED00b3E423f6710D2ee7e0D5EBB06F3eCF368A8";
|
|
92368
|
+
var BUFFER_USDC_IN_WITHDRAWAL = 5;
|
|
92378
92369
|
var WBTC_TOKEN_ADDRESS = "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac";
|
|
92379
92370
|
var WBTC_TOKEN_DECIMALS = 8;
|
|
92380
92371
|
var MAINTENANCE_MARGIN = 0.01;
|
|
@@ -92390,7 +92381,8 @@ spurious results.`);
|
|
|
92390
92381
|
var MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
|
|
92391
92382
|
var MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
|
|
92392
92383
|
var EXTEND_MARKET_NAME = "BTC-USD";
|
|
92393
|
-
var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ??
|
|
92384
|
+
var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 0.05);
|
|
92385
|
+
var LIMIT_BALANCE_VALUE = 10;
|
|
92394
92386
|
var REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 18e4);
|
|
92395
92387
|
var WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18e6);
|
|
92396
92388
|
var INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 18e4);
|
|
@@ -92408,8 +92400,6 @@ spurious results.`);
|
|
|
92408
92400
|
var MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING = Number(process.env.MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING ?? 1);
|
|
92409
92401
|
var MINIMUM_EXTENDED_POSITION_SIZE = 1e-4;
|
|
92410
92402
|
var MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP = 1e-5;
|
|
92411
|
-
var MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = 700;
|
|
92412
|
-
var MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = -100;
|
|
92413
92403
|
|
|
92414
92404
|
// src/strategies/vesu-extended-strategy/utils/helper.ts
|
|
92415
92405
|
var returnFormattedAmount = (amount, toTokenDecimals) => {
|
|
@@ -92429,8 +92419,7 @@ spurious results.`);
|
|
|
92429
92419
|
vesu_leverage: 0
|
|
92430
92420
|
};
|
|
92431
92421
|
}
|
|
92432
|
-
const
|
|
92433
|
-
const extendedExposureUSD = extendedBTCExposure.multipliedBy(collateralPrice);
|
|
92422
|
+
const extendedExposureUSD = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].value, WBTC_TOKEN_DECIMALS) : new Web3Number(0, WBTC_TOKEN_DECIMALS);
|
|
92434
92423
|
const vesuBTCExposureUSD = collateralUnits.multipliedBy(collateralPrice);
|
|
92435
92424
|
const numerator1 = vesu_leverage * amount + vesuBTCExposureUSD.toNumber();
|
|
92436
92425
|
const numerator2 = extendedExposureUSD.toNumber();
|
|
@@ -92466,8 +92455,7 @@ spurious results.`);
|
|
|
92466
92455
|
logger2.error("error getting extended positions");
|
|
92467
92456
|
return null;
|
|
92468
92457
|
}
|
|
92469
|
-
const
|
|
92470
|
-
const extendedExposureUSD = extendedBTCExposure.multipliedBy(collateralPrice);
|
|
92458
|
+
const extendedExposureUSD = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].value, USDC_TOKEN_DECIMALS) : new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
92471
92459
|
const vesuExposureUSD = collateralUnits.multipliedBy(collateralPrice);
|
|
92472
92460
|
if (vesuExposureUSD.lessThan(0)) {
|
|
92473
92461
|
return {
|
|
@@ -92485,9 +92473,14 @@ spurious results.`);
|
|
|
92485
92473
|
vesu_leverage
|
|
92486
92474
|
};
|
|
92487
92475
|
}
|
|
92476
|
+
console.log("the vesu exposure usd is", vesuExposureUSD.toNumber());
|
|
92477
|
+
console.log("the extended exposure usd is", extendedExposureUSD.toNumber());
|
|
92478
|
+
console.log("the amount in usdc is", amountInUsdc.toNumber());
|
|
92479
|
+
console.log("the extended leverage is", extended_leverage);
|
|
92480
|
+
console.log("the vesu leverage is", vesu_leverage);
|
|
92488
92481
|
const numerator1 = amountInUsdc.multipliedBy(extended_leverage);
|
|
92489
|
-
const numerator2 = vesuExposureUSD
|
|
92490
|
-
const numerator3 = extendedExposureUSD.multipliedBy(
|
|
92482
|
+
const numerator2 = vesuExposureUSD;
|
|
92483
|
+
const numerator3 = extendedExposureUSD.multipliedBy(-1);
|
|
92491
92484
|
const finalNumerator = numerator1.plus(numerator2).plus(numerator3);
|
|
92492
92485
|
const denominator = extended_leverage + vesu_leverage;
|
|
92493
92486
|
const vesuAmountInUSDC = finalNumerator.dividedBy(denominator);
|
|
@@ -92497,6 +92490,7 @@ spurious results.`);
|
|
|
92497
92490
|
"the extended amount in usdc is",
|
|
92498
92491
|
extendedAmountInUSDC.toNumber()
|
|
92499
92492
|
);
|
|
92493
|
+
await new Promise((resolve) => setTimeout(resolve, 1e4));
|
|
92500
92494
|
return {
|
|
92501
92495
|
vesu_amount: vesuAmountInUSDC,
|
|
92502
92496
|
extended_amount: extendedAmountInUSDC,
|
|
@@ -92518,10 +92512,10 @@ spurious results.`);
|
|
|
92518
92512
|
const extended_leverage_max = 1 / (MAINTENANCE_MARGIN + MAX_PRICE_DROP_PERCENTAGE);
|
|
92519
92513
|
return Math.floor(extended_leverage_max);
|
|
92520
92514
|
};
|
|
92521
|
-
var calculateDebtAmount = (collateralAmount, debtAmount, debtPrice, maxLtv =
|
|
92515
|
+
var calculateDebtAmount = (collateralAmount, debtAmount, debtPrice, maxLtv = MAX_LIQUIDATION_RATIO, addedAmount, collateralPrice, isDeposit) => {
|
|
92522
92516
|
try {
|
|
92523
|
-
const
|
|
92524
|
-
const numerator1 = collateralAmount.plus(
|
|
92517
|
+
const addedCollateral = addedAmount.multipliedBy(isDeposit ? 1 : -1);
|
|
92518
|
+
const numerator1 = collateralAmount.plus(addedCollateral).multipliedBy(collateralPrice).multipliedBy(maxLtv);
|
|
92525
92519
|
const numerator2 = debtAmount.multipliedBy(debtPrice).multipliedBy(TARGET_HF);
|
|
92526
92520
|
const denominator = TARGET_HF - maxLtv;
|
|
92527
92521
|
const x_debt_usd = numerator1.minus(numerator2).dividedBy(denominator);
|
|
@@ -92556,16 +92550,16 @@ spurious results.`);
|
|
|
92556
92550
|
const extendedHoldings = await client.getHoldings();
|
|
92557
92551
|
const extended_leverage = calculateExtendedLevergae();
|
|
92558
92552
|
const latestPosition = (await client.getPositions()).data.pop();
|
|
92559
|
-
console.log("the latest position is", latestPosition, extendedHoldings);
|
|
92560
92553
|
if (!extendedHoldings || !latestPosition) {
|
|
92561
92554
|
logger2.error(`error getting extended position: extendedHoldings=${extendedHoldings}, latestPosition=${latestPosition}`);
|
|
92562
92555
|
return null;
|
|
92563
92556
|
}
|
|
92564
|
-
const positionValueInUSD = latestPosition.value;
|
|
92557
|
+
const positionValueInUSD = new Web3Number(latestPosition.value, USDC_TOKEN_DECIMALS);
|
|
92565
92558
|
const equity = extendedHoldings.data.equity;
|
|
92566
|
-
const deposit =
|
|
92567
|
-
return new Web3Number(
|
|
92559
|
+
const deposit = positionValueInUSD.dividedBy(extended_leverage).minus(equity).toFixed(2);
|
|
92560
|
+
return new Web3Number(deposit, USDC_TOKEN_DECIMALS);
|
|
92568
92561
|
} catch (err2) {
|
|
92562
|
+
logger2.error(`error calculating amount deposit on extended when incurring losses: ${err2}`);
|
|
92569
92563
|
return null;
|
|
92570
92564
|
}
|
|
92571
92565
|
};
|
|
@@ -92643,21 +92637,36 @@ spurious results.`);
|
|
|
92643
92637
|
vaultAllocator: config3.vaultAllocator,
|
|
92644
92638
|
id: ""
|
|
92645
92639
|
});
|
|
92646
|
-
this.
|
|
92640
|
+
this.minimumVesuMovementAmount = config3.minimumVesuMovementAmount ?? 5;
|
|
92641
|
+
this.tokenMarketData = new TokenMarketData(
|
|
92642
|
+
this.config.pricer,
|
|
92643
|
+
this.config.networkConfig
|
|
92644
|
+
);
|
|
92647
92645
|
}
|
|
92648
92646
|
async getAPY(supportedPosition) {
|
|
92649
92647
|
const CACHE_KEY = `apy_${this.config.poolId.address}_${supportedPosition.asset.symbol}`;
|
|
92650
92648
|
const cacheData = this.getCache(CACHE_KEY);
|
|
92651
|
-
console.log(
|
|
92649
|
+
console.log(
|
|
92650
|
+
`${_VesuMultiplyAdapter.name}::getAPY cacheData: ${JSON.stringify(
|
|
92651
|
+
cacheData
|
|
92652
|
+
)}`,
|
|
92653
|
+
this.vesuAdapter.config.poolId.shortString(),
|
|
92654
|
+
this.vesuAdapter.config.collateral.symbol,
|
|
92655
|
+
this.vesuAdapter.config.debt.symbol
|
|
92656
|
+
);
|
|
92652
92657
|
if (cacheData) {
|
|
92653
92658
|
return cacheData;
|
|
92654
92659
|
}
|
|
92655
92660
|
try {
|
|
92656
92661
|
const allVesuPools = await VesuAdapter.getVesuPools();
|
|
92657
92662
|
const asset = supportedPosition.asset;
|
|
92658
|
-
const pool = allVesuPools.pools.find(
|
|
92663
|
+
const pool = allVesuPools.pools.find(
|
|
92664
|
+
(p) => this.vesuAdapter.config.poolId.eqString(num_exports.getHexString(p.id))
|
|
92665
|
+
);
|
|
92659
92666
|
if (!pool) {
|
|
92660
|
-
logger2.warn(
|
|
92667
|
+
logger2.warn(
|
|
92668
|
+
`VesuMultiplyAdapter: Pool not found for token ${asset.symbol}`
|
|
92669
|
+
);
|
|
92661
92670
|
return {
|
|
92662
92671
|
apy: 0,
|
|
92663
92672
|
type: "base" /* BASE */
|
|
@@ -92667,7 +92676,9 @@ spurious results.`);
|
|
|
92667
92676
|
(a) => a.symbol.toLowerCase() === asset.symbol.toLowerCase()
|
|
92668
92677
|
)?.stats;
|
|
92669
92678
|
if (!assetStats) {
|
|
92670
|
-
logger2.warn(
|
|
92679
|
+
logger2.warn(
|
|
92680
|
+
`VesuMultiplyAdapter: Asset stats not found for token ${asset.symbol}`
|
|
92681
|
+
);
|
|
92671
92682
|
return {
|
|
92672
92683
|
apy: 0,
|
|
92673
92684
|
type: "base" /* BASE */
|
|
@@ -92678,7 +92689,9 @@ spurious results.`);
|
|
|
92678
92689
|
apy = Number(assetStats.borrowApr?.value || 0) / 1e18;
|
|
92679
92690
|
} else {
|
|
92680
92691
|
const isAssetBTC = asset.symbol.toLowerCase().includes("btc");
|
|
92681
|
-
const baseAPY = Number(
|
|
92692
|
+
const baseAPY = Number(
|
|
92693
|
+
isAssetBTC ? assetStats.btcFiSupplyApr?.value + assetStats.supplyApy?.value : assetStats.supplyApy?.value || 0
|
|
92694
|
+
) / 1e18;
|
|
92682
92695
|
const rewardAPY = Number(assetStats.defiSpringSupplyApr?.value || "0") / 1e18;
|
|
92683
92696
|
const isSupported = this.tokenMarketData.isAPYSupported(asset);
|
|
92684
92697
|
apy = baseAPY + rewardAPY;
|
|
@@ -92694,7 +92707,10 @@ spurious results.`);
|
|
|
92694
92707
|
this.setCache(CACHE_KEY, result2, 3e5);
|
|
92695
92708
|
return result2;
|
|
92696
92709
|
} catch (error2) {
|
|
92697
|
-
logger2.error(
|
|
92710
|
+
logger2.error(
|
|
92711
|
+
`VesuMultiplyAdapter: Error getting APY for ${supportedPosition.asset.symbol}:`,
|
|
92712
|
+
error2
|
|
92713
|
+
);
|
|
92698
92714
|
throw error2;
|
|
92699
92715
|
}
|
|
92700
92716
|
}
|
|
@@ -92707,12 +92723,16 @@ spurious results.`);
|
|
|
92707
92723
|
try {
|
|
92708
92724
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
92709
92725
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
92710
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
92726
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
92727
|
+
this.config.networkConfig
|
|
92728
|
+
);
|
|
92711
92729
|
let position = positions.find(
|
|
92712
92730
|
(p) => p.token.address.eq(supportedPosition.asset.address)
|
|
92713
92731
|
);
|
|
92714
92732
|
if (!position) {
|
|
92715
|
-
logger2.warn(
|
|
92733
|
+
logger2.warn(
|
|
92734
|
+
`VesuMultiplyAdapter: Position not found for token ${supportedPosition.asset.symbol}`
|
|
92735
|
+
);
|
|
92716
92736
|
return {
|
|
92717
92737
|
amount: new Web3Number("0", supportedPosition.asset.decimals),
|
|
92718
92738
|
remarks: "Position not found"
|
|
@@ -92725,12 +92745,18 @@ spurious results.`);
|
|
|
92725
92745
|
this.setCache(CACHE_KEY, position, 6e4);
|
|
92726
92746
|
return position;
|
|
92727
92747
|
} catch (error2) {
|
|
92728
|
-
logger2.error(
|
|
92748
|
+
logger2.error(
|
|
92749
|
+
`VesuMultiplyAdapter: Error getting position for ${supportedPosition.asset.symbol}:`,
|
|
92750
|
+
error2
|
|
92751
|
+
);
|
|
92729
92752
|
throw error2;
|
|
92730
92753
|
}
|
|
92731
92754
|
}
|
|
92732
92755
|
async maxBorrowableAPY() {
|
|
92733
|
-
const collateralAPY = await this.getAPY({
|
|
92756
|
+
const collateralAPY = await this.getAPY({
|
|
92757
|
+
asset: this.config.collateral,
|
|
92758
|
+
isDebt: false
|
|
92759
|
+
});
|
|
92734
92760
|
const apy = collateralAPY.apy * 0.8;
|
|
92735
92761
|
return apy;
|
|
92736
92762
|
}
|
|
@@ -92740,9 +92766,15 @@ spurious results.`);
|
|
|
92740
92766
|
try {
|
|
92741
92767
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
92742
92768
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
92743
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
92744
|
-
|
|
92745
|
-
|
|
92769
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
92770
|
+
this.config.networkConfig
|
|
92771
|
+
);
|
|
92772
|
+
const collateralPosition = positions.find(
|
|
92773
|
+
(p) => p.token.address.eq(collateral.address)
|
|
92774
|
+
);
|
|
92775
|
+
const debtPosition = positions.find(
|
|
92776
|
+
(p) => p.token.address.eq(debt.address)
|
|
92777
|
+
);
|
|
92746
92778
|
if (!collateralPosition || !debtPosition) {
|
|
92747
92779
|
throw new Error("Could not find current positions");
|
|
92748
92780
|
}
|
|
@@ -92752,13 +92784,23 @@ spurious results.`);
|
|
|
92752
92784
|
debt,
|
|
92753
92785
|
maxBorrowableAPY
|
|
92754
92786
|
);
|
|
92755
|
-
logger2.verbose(
|
|
92756
|
-
|
|
92787
|
+
logger2.verbose(
|
|
92788
|
+
`VesuMultiplyAdapter: Max borrowable: ${maxBorrowable.toNumber()}`
|
|
92789
|
+
);
|
|
92790
|
+
const debtCap = await this.vesuAdapter.getDebtCap(
|
|
92791
|
+
this.config.networkConfig
|
|
92792
|
+
);
|
|
92757
92793
|
logger2.verbose(`VesuMultiplyAdapter: Debt cap: ${debtCap.toNumber()}`);
|
|
92758
92794
|
const actualMaxBorrowable = maxBorrowable.minimum(debtCap);
|
|
92759
|
-
logger2.verbose(
|
|
92760
|
-
|
|
92761
|
-
|
|
92795
|
+
logger2.verbose(
|
|
92796
|
+
`VesuMultiplyAdapter: Actual max borrowable: ${actualMaxBorrowable.toNumber()}`
|
|
92797
|
+
);
|
|
92798
|
+
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
92799
|
+
this.config.networkConfig
|
|
92800
|
+
);
|
|
92801
|
+
const collateralPrice = await this.config.pricer.getPrice(
|
|
92802
|
+
collateral.symbol
|
|
92803
|
+
);
|
|
92762
92804
|
if (collateralPrice.price === 0) {
|
|
92763
92805
|
throw new Error("Collateral price is 0");
|
|
92764
92806
|
}
|
|
@@ -92776,14 +92818,25 @@ spurious results.`);
|
|
|
92776
92818
|
);
|
|
92777
92819
|
const maxDepositAmount = amount ? amount.minimum(maxCollateralFromDebt) : maxCollateralFromDebt;
|
|
92778
92820
|
const usdValue = await this.getUSDValue(collateral, maxDepositAmount);
|
|
92779
|
-
logger2.verbose(
|
|
92780
|
-
|
|
92781
|
-
|
|
92821
|
+
logger2.verbose(
|
|
92822
|
+
`VesuMultiplyAdapter: Max deposit::USD value: ${usdValue}, amount: ${maxDepositAmount.toNumber()}`
|
|
92823
|
+
);
|
|
92824
|
+
const apys = await Promise.all([
|
|
92825
|
+
this.getAPY({ asset: collateral, isDebt: false }),
|
|
92826
|
+
this.getAPY({ asset: debt, isDebt: true })
|
|
92827
|
+
]);
|
|
92828
|
+
logger2.verbose(
|
|
92829
|
+
`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
|
|
92830
|
+
);
|
|
92782
92831
|
const borrowAmountUSD = actualMaxBorrowable.multipliedBy(debtPrice.price);
|
|
92783
|
-
logger2.verbose(
|
|
92832
|
+
logger2.verbose(
|
|
92833
|
+
`VesuMultiplyAdapter: Borrow amount: ${actualMaxBorrowable.toNumber()}, borrow amount USD: ${borrowAmountUSD.toNumber()}`
|
|
92834
|
+
);
|
|
92784
92835
|
const netCollateralUSD = usdValue + borrowAmountUSD.toNumber();
|
|
92785
92836
|
const netAPY = (apys[0].apy * netCollateralUSD + apys[1].apy * borrowAmountUSD.toNumber()) / usdValue;
|
|
92786
|
-
logger2.verbose(
|
|
92837
|
+
logger2.verbose(
|
|
92838
|
+
`VesuMultiplyAdapter: Max deposit amount: ${maxDepositAmount.toNumber()}, netAPY: ${netAPY}`
|
|
92839
|
+
);
|
|
92787
92840
|
return {
|
|
92788
92841
|
tokenInfo: collateral,
|
|
92789
92842
|
amount: maxDepositAmount,
|
|
@@ -92796,7 +92849,10 @@ spurious results.`);
|
|
|
92796
92849
|
protocol: this.protocol
|
|
92797
92850
|
};
|
|
92798
92851
|
} catch (error2) {
|
|
92799
|
-
logger2.error(
|
|
92852
|
+
logger2.error(
|
|
92853
|
+
`VesuMultiplyAdapter: Error calculating max deposit:`,
|
|
92854
|
+
error2
|
|
92855
|
+
);
|
|
92800
92856
|
throw error2;
|
|
92801
92857
|
}
|
|
92802
92858
|
}
|
|
@@ -92806,9 +92862,15 @@ spurious results.`);
|
|
|
92806
92862
|
try {
|
|
92807
92863
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
92808
92864
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
92809
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
92810
|
-
|
|
92811
|
-
|
|
92865
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
92866
|
+
this.config.networkConfig
|
|
92867
|
+
);
|
|
92868
|
+
const collateralPosition = positions.find(
|
|
92869
|
+
(p) => p.token.address.eq(collateral.address)
|
|
92870
|
+
);
|
|
92871
|
+
const debtPosition = positions.find(
|
|
92872
|
+
(p) => p.token.address.eq(this.config.debt.address)
|
|
92873
|
+
);
|
|
92812
92874
|
if (!collateralPosition || !debtPosition) {
|
|
92813
92875
|
throw new Error("Could not find current positions");
|
|
92814
92876
|
}
|
|
@@ -92818,11 +92880,20 @@ spurious results.`);
|
|
|
92818
92880
|
const result2 = maxWithdrawable.greaterThan(0) ? maxWithdrawable : new Web3Number("0", collateral.decimals);
|
|
92819
92881
|
const usdValue = await this.getUSDValue(collateral, result2);
|
|
92820
92882
|
const debtUSD = debtPosition.usdValue;
|
|
92821
|
-
logger2.verbose(
|
|
92822
|
-
|
|
92823
|
-
|
|
92883
|
+
logger2.verbose(
|
|
92884
|
+
`VesuMultiplyAdapter: Debt USD: ${debtUSD}, collateral USD: ${usdValue}`
|
|
92885
|
+
);
|
|
92886
|
+
const apys = await Promise.all([
|
|
92887
|
+
this.getAPY({ asset: collateral, isDebt: false }),
|
|
92888
|
+
this.getAPY({ asset: debt, isDebt: true })
|
|
92889
|
+
]);
|
|
92890
|
+
logger2.verbose(
|
|
92891
|
+
`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
|
|
92892
|
+
);
|
|
92824
92893
|
const netAPY = usdValue - debtUSD > 0 ? (apys[0].apy * usdValue + apys[1].apy * debtUSD) / (usdValue - debtUSD) : 0;
|
|
92825
|
-
logger2.verbose(
|
|
92894
|
+
logger2.verbose(
|
|
92895
|
+
`VesuMultiplyAdapter: Max withdraw amount: ${result2.toNumber()}, netAPY: ${netAPY}`
|
|
92896
|
+
);
|
|
92826
92897
|
return {
|
|
92827
92898
|
tokenInfo: collateral,
|
|
92828
92899
|
amount: result2,
|
|
@@ -92835,14 +92906,19 @@ spurious results.`);
|
|
|
92835
92906
|
protocol: this.protocol
|
|
92836
92907
|
};
|
|
92837
92908
|
} catch (error2) {
|
|
92838
|
-
logger2.error(
|
|
92909
|
+
logger2.error(
|
|
92910
|
+
`VesuMultiplyAdapter: Error calculating max withdraw:`,
|
|
92911
|
+
error2
|
|
92912
|
+
);
|
|
92839
92913
|
throw error2;
|
|
92840
92914
|
}
|
|
92841
92915
|
}
|
|
92842
92916
|
_getDepositLeaf() {
|
|
92843
92917
|
const collateral = this.config.collateral;
|
|
92844
92918
|
const debt = this.config.debt;
|
|
92845
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
92919
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
92920
|
+
this.config.poolId
|
|
92921
|
+
);
|
|
92846
92922
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
92847
92923
|
return [
|
|
92848
92924
|
// Approval step for collateral
|
|
@@ -92906,7 +92982,9 @@ spurious results.`);
|
|
|
92906
92982
|
];
|
|
92907
92983
|
}
|
|
92908
92984
|
_getWithdrawLeaf() {
|
|
92909
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
92985
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
92986
|
+
this.config.poolId
|
|
92987
|
+
);
|
|
92910
92988
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
92911
92989
|
const collateral = this.config.collateral;
|
|
92912
92990
|
const debt = this.config.debt;
|
|
@@ -92937,7 +93015,7 @@ spurious results.`);
|
|
|
92937
93015
|
this.config.debt.address.toBigInt(),
|
|
92938
93016
|
this.config.vaultAllocator.toBigInt()
|
|
92939
93017
|
],
|
|
92940
|
-
sanitizer: SIMPLE_SANITIZER_V2,
|
|
93018
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
|
|
92941
93019
|
// vmw = vesu multiply withdraw
|
|
92942
93020
|
id: `vmw_${this.config.poolId.shortString()}_${collateral.symbol}_${debt.symbol}`
|
|
92943
93021
|
},
|
|
@@ -92963,33 +93041,51 @@ spurious results.`);
|
|
|
92963
93041
|
const leafConfigs = this._getDepositLeaf();
|
|
92964
93042
|
const leaves = leafConfigs.map((config3) => {
|
|
92965
93043
|
const { target, method, packedArguments, sanitizer, id } = config3;
|
|
92966
|
-
const leaf = this.constructSimpleLeafData(
|
|
92967
|
-
|
|
92968
|
-
|
|
92969
|
-
|
|
92970
|
-
|
|
92971
|
-
|
|
93044
|
+
const leaf = this.constructSimpleLeafData(
|
|
93045
|
+
{
|
|
93046
|
+
id,
|
|
93047
|
+
target,
|
|
93048
|
+
method,
|
|
93049
|
+
packedArguments
|
|
93050
|
+
},
|
|
93051
|
+
sanitizer
|
|
93052
|
+
);
|
|
92972
93053
|
return leaf;
|
|
92973
93054
|
});
|
|
92974
|
-
return {
|
|
93055
|
+
return {
|
|
93056
|
+
leaves,
|
|
93057
|
+
callConstructor: this.getDepositCall.bind(
|
|
93058
|
+
this
|
|
93059
|
+
)
|
|
93060
|
+
};
|
|
92975
93061
|
}
|
|
92976
93062
|
getWithdrawAdapter() {
|
|
92977
93063
|
const leafConfigs = this._getWithdrawLeaf();
|
|
92978
93064
|
const leaves = leafConfigs.map((config3) => {
|
|
92979
93065
|
const { target, method, packedArguments, sanitizer, id } = config3;
|
|
92980
|
-
const leaf = this.constructSimpleLeafData(
|
|
92981
|
-
|
|
92982
|
-
|
|
92983
|
-
|
|
92984
|
-
|
|
92985
|
-
|
|
93066
|
+
const leaf = this.constructSimpleLeafData(
|
|
93067
|
+
{
|
|
93068
|
+
id,
|
|
93069
|
+
target,
|
|
93070
|
+
method,
|
|
93071
|
+
packedArguments
|
|
93072
|
+
},
|
|
93073
|
+
sanitizer
|
|
93074
|
+
);
|
|
92986
93075
|
return leaf;
|
|
92987
93076
|
});
|
|
92988
|
-
return {
|
|
93077
|
+
return {
|
|
93078
|
+
leaves,
|
|
93079
|
+
callConstructor: this.getWithdrawCall.bind(
|
|
93080
|
+
this
|
|
93081
|
+
)
|
|
93082
|
+
};
|
|
92989
93083
|
}
|
|
92990
93084
|
async getDepositCall(params) {
|
|
92991
93085
|
const collateral = this.config.collateral;
|
|
92992
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
93086
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
93087
|
+
this.config.poolId
|
|
93088
|
+
);
|
|
92993
93089
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
92994
93090
|
const uint256MarginAmount = uint256_exports.bnToUint256(params.amount.toWei());
|
|
92995
93091
|
return [
|
|
@@ -93061,7 +93157,9 @@ spurious results.`);
|
|
|
93061
93157
|
];
|
|
93062
93158
|
}
|
|
93063
93159
|
async getWithdrawCall(params) {
|
|
93064
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
93160
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
93161
|
+
this.config.poolId
|
|
93162
|
+
);
|
|
93065
93163
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
93066
93164
|
return [
|
|
93067
93165
|
// Switch delegation on
|
|
@@ -93086,7 +93184,7 @@ spurious results.`);
|
|
|
93086
93184
|
},
|
|
93087
93185
|
// Vesu multiply call
|
|
93088
93186
|
{
|
|
93089
|
-
sanitizer: SIMPLE_SANITIZER_V2,
|
|
93187
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
|
|
93090
93188
|
call: {
|
|
93091
93189
|
contractAddress: vesuMultiply,
|
|
93092
93190
|
selector: hash_exports.getSelectorFromName("modify_lever"),
|
|
@@ -93116,7 +93214,11 @@ spurious results.`);
|
|
|
93116
93214
|
];
|
|
93117
93215
|
}
|
|
93118
93216
|
async getMultiplyCallCalldata(params, isDeposit) {
|
|
93119
|
-
logger2.verbose(
|
|
93217
|
+
logger2.verbose(
|
|
93218
|
+
`${_VesuMultiplyAdapter.name}::getMultiplyCallCalldata params: ${JSON.stringify(
|
|
93219
|
+
params
|
|
93220
|
+
)}, isDeposit: ${isDeposit}, collateral: ${this.config.collateral.symbol}, debt: ${this.config.debt.symbol}`
|
|
93221
|
+
);
|
|
93120
93222
|
const { isV2 } = getVesuSingletonAddress(this.config.poolId);
|
|
93121
93223
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
93122
93224
|
const multiplyContract = new Contract({
|
|
@@ -93126,42 +93228,83 @@ spurious results.`);
|
|
|
93126
93228
|
});
|
|
93127
93229
|
let leverSwap = [];
|
|
93128
93230
|
let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
93129
|
-
const existingPositions = await this.vesuAdapter.getPositions(
|
|
93130
|
-
|
|
93231
|
+
const existingPositions = await this.vesuAdapter.getPositions(
|
|
93232
|
+
this.config.networkConfig
|
|
93233
|
+
);
|
|
93234
|
+
const collateralisation = await this.vesuAdapter.getCollateralization(
|
|
93235
|
+
this.config.networkConfig
|
|
93236
|
+
);
|
|
93131
93237
|
const existingCollateralInfo = existingPositions[0];
|
|
93132
93238
|
const existingDebtInfo = existingPositions[1];
|
|
93133
93239
|
const isDexPriceRequired = existingDebtInfo.token.symbol !== "USDC";
|
|
93134
|
-
logger2.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(
|
|
93135
|
-
|
|
93240
|
+
logger2.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(
|
|
93241
|
+
existingCollateralInfo
|
|
93242
|
+
)},
|
|
93243
|
+
existingDebtInfo: ${JSON.stringify(
|
|
93244
|
+
existingDebtInfo
|
|
93245
|
+
)}, collateralisation: ${JSON.stringify(collateralisation)}`);
|
|
93136
93246
|
const collateralPrice = collateralisation[0].usdValue > 0 ? collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() : (await this.config.pricer.getPrice(this.config.collateral.symbol)).price;
|
|
93137
93247
|
const debtPrice = collateralisation[1].usdValue > 0 ? collateralisation[1].usdValue / existingDebtInfo.amount.toNumber() : (await this.config.pricer.getPrice(this.config.debt.symbol)).price;
|
|
93138
|
-
logger2.debug(
|
|
93139
|
-
|
|
93140
|
-
|
|
93141
|
-
const
|
|
93142
|
-
|
|
93248
|
+
logger2.debug(
|
|
93249
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`
|
|
93250
|
+
);
|
|
93251
|
+
const legLTV = await this.vesuAdapter.getLTVConfig(
|
|
93252
|
+
this.config.networkConfig
|
|
93253
|
+
);
|
|
93254
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
93255
|
+
this.config.networkConfig,
|
|
93256
|
+
this.config.pricer
|
|
93257
|
+
);
|
|
93258
|
+
const dexPrice = isDexPriceRequired ? await ekuboQuoter.getDexPrice(
|
|
93259
|
+
this.config.collateral,
|
|
93260
|
+
this.config.debt,
|
|
93261
|
+
this.config.quoteAmountToFetchPrice
|
|
93262
|
+
) : 1;
|
|
93263
|
+
logger2.verbose(
|
|
93264
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall dexPrice: ${dexPrice}, ltv: ${legLTV}`
|
|
93265
|
+
);
|
|
93143
93266
|
const addedCollateral = params.amount.multipliedBy(isDeposit ? 1 : -1);
|
|
93144
|
-
logger2.verbose(
|
|
93267
|
+
logger2.verbose(
|
|
93268
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall addedCollateral: ${addedCollateral}`
|
|
93269
|
+
);
|
|
93145
93270
|
const numeratorPart1 = existingCollateralInfo.amount.plus(addedCollateral).multipliedBy(collateralPrice).multipliedBy(legLTV);
|
|
93146
|
-
logger2.verbose(
|
|
93271
|
+
logger2.verbose(
|
|
93272
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}`
|
|
93273
|
+
);
|
|
93147
93274
|
const numeratorPart2 = existingDebtInfo.amount.multipliedBy(debtPrice).multipliedBy(this.config.targetHealthFactor);
|
|
93148
|
-
logger2.verbose(
|
|
93275
|
+
logger2.verbose(
|
|
93276
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart2: ${numeratorPart2}`
|
|
93277
|
+
);
|
|
93149
93278
|
const denominatorPart = this.config.targetHealthFactor - legLTV / dexPrice;
|
|
93150
|
-
logger2.verbose(
|
|
93279
|
+
logger2.verbose(
|
|
93280
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall denominatorPart: ${denominatorPart}`
|
|
93281
|
+
);
|
|
93151
93282
|
const x_debt_usd = numeratorPart1.minus(numeratorPart2).dividedBy(denominatorPart);
|
|
93152
|
-
logger2.verbose(
|
|
93153
|
-
|
|
93154
|
-
|
|
93283
|
+
logger2.verbose(
|
|
93284
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall x_debt_usd: ${x_debt_usd}`
|
|
93285
|
+
);
|
|
93286
|
+
logger2.debug(
|
|
93287
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}, numeratorPart2: ${numeratorPart2}, denominatorPart: ${denominatorPart}`
|
|
93288
|
+
);
|
|
93289
|
+
let debtAmount = new Web3Number(
|
|
93290
|
+
x_debt_usd.dividedBy(debtPrice).toFixed(this.config.debt.decimals),
|
|
93291
|
+
this.config.debt.decimals
|
|
93292
|
+
);
|
|
93155
93293
|
const marginAmount = addedCollateral;
|
|
93156
93294
|
const collateralToken = this.config.collateral;
|
|
93157
93295
|
const debtToken = this.config.debt;
|
|
93158
|
-
const debtAmountInCollateralUnits = new Web3Number(
|
|
93296
|
+
const debtAmountInCollateralUnits = new Web3Number(
|
|
93297
|
+
debtAmount.multipliedBy(debtPrice).dividedBy(collateralPrice).multipliedBy(10 ** collateralToken.decimals).toFixed(0),
|
|
93298
|
+
collateralToken.decimals
|
|
93299
|
+
);
|
|
93159
93300
|
const isIncrease = debtAmount.greaterThanOrEqualTo(0);
|
|
93160
93301
|
if (isIncrease && debtAmount.lessThan(0)) {
|
|
93161
93302
|
} else if (!isIncrease && debtAmount.greaterThan(0)) {
|
|
93162
93303
|
debtAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
93163
93304
|
}
|
|
93164
|
-
logger2.verbose(
|
|
93305
|
+
logger2.verbose(
|
|
93306
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall debtAmount: ${debtAmount}, marginAmount: ${marginAmount}`
|
|
93307
|
+
);
|
|
93165
93308
|
if (!debtAmount.isZero()) {
|
|
93166
93309
|
try {
|
|
93167
93310
|
const swapQuote = await ekuboQuoter.getQuote(
|
|
@@ -93171,32 +93314,49 @@ spurious results.`);
|
|
|
93171
93314
|
// negative for exact amount out
|
|
93172
93315
|
);
|
|
93173
93316
|
if (swapQuote.price_impact < 0.01) {
|
|
93174
|
-
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
93317
|
+
leverSwap = debtAmount.isNegative() ? ekuboQuoter.getVesuMultiplyQuote(
|
|
93318
|
+
swapQuote,
|
|
93319
|
+
collateralToken,
|
|
93320
|
+
debtToken
|
|
93321
|
+
) : ekuboQuoter.getVesuMultiplyQuote(
|
|
93322
|
+
swapQuote,
|
|
93323
|
+
debtToken,
|
|
93324
|
+
collateralToken
|
|
93325
|
+
);
|
|
93175
93326
|
const MAX_SLIPPAGE = 2e-3;
|
|
93176
93327
|
if (debtAmount.greaterThan(0)) {
|
|
93177
|
-
|
|
93178
|
-
leverSwapLimitAmount = await ekuboQuoter.getSwapLimitAmount(debtToken, collateralToken, debtAmount, MAX_SLIPPAGE);
|
|
93179
|
-
const anotherleverSwapLimitAmount = debtAmount.multipliedBy(1 + MAX_SLIPPAGE);
|
|
93180
|
-
console.log("anotherleverSwapLimitAmount", anotherleverSwapLimitAmount, leverSwapLimitAmount);
|
|
93328
|
+
leverSwapLimitAmount = debtAmount.multipliedBy(1 + MAX_SLIPPAGE);
|
|
93181
93329
|
} else if (debtAmount.lessThan(0)) {
|
|
93182
|
-
leverSwapLimitAmount =
|
|
93183
|
-
const anotherleverSwapLimitAmount = debtAmount.abs().multipliedBy(1 - MAX_SLIPPAGE);
|
|
93184
|
-
console.log("anotherleverSwapLimitAmount", anotherleverSwapLimitAmount, leverSwapLimitAmount);
|
|
93330
|
+
leverSwapLimitAmount = debtAmount.abs().multipliedBy(1 - MAX_SLIPPAGE);
|
|
93185
93331
|
} else {
|
|
93186
|
-
leverSwapLimitAmount = Web3Number.fromWei(
|
|
93332
|
+
leverSwapLimitAmount = Web3Number.fromWei(
|
|
93333
|
+
0,
|
|
93334
|
+
this.config.debt.decimals
|
|
93335
|
+
);
|
|
93187
93336
|
}
|
|
93188
93337
|
await new Promise((resolve) => setTimeout(resolve, 1e4));
|
|
93189
|
-
console.log("leverSwapLimitAmount", leverSwapLimitAmount);
|
|
93190
93338
|
} else {
|
|
93191
|
-
throw new Error(
|
|
93339
|
+
throw new Error(
|
|
93340
|
+
`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
|
|
93341
|
+
);
|
|
93192
93342
|
}
|
|
93193
93343
|
} catch (error2) {
|
|
93194
|
-
throw new Error(
|
|
93344
|
+
throw new Error(
|
|
93345
|
+
`VesuMultiplyAdapter: Failed to get swap quote: ${error2}`
|
|
93346
|
+
);
|
|
93195
93347
|
}
|
|
93196
93348
|
}
|
|
93197
|
-
const multiplyParams = await this.getLeverParams(
|
|
93349
|
+
const multiplyParams = await this.getLeverParams(
|
|
93350
|
+
isIncrease,
|
|
93351
|
+
params,
|
|
93352
|
+
leverSwap,
|
|
93353
|
+
leverSwapLimitAmount
|
|
93354
|
+
);
|
|
93198
93355
|
const call = multiplyContract.populate("modify_lever", {
|
|
93199
|
-
modify_lever_params: this.formatMultiplyParams(
|
|
93356
|
+
modify_lever_params: this.formatMultiplyParams(
|
|
93357
|
+
isIncrease,
|
|
93358
|
+
multiplyParams
|
|
93359
|
+
)
|
|
93200
93360
|
});
|
|
93201
93361
|
return call.calldata;
|
|
93202
93362
|
}
|
|
@@ -93210,7 +93370,10 @@ spurious results.`);
|
|
|
93210
93370
|
add_margin: params.amount,
|
|
93211
93371
|
// multiplied by collateral decimals in format
|
|
93212
93372
|
margin_swap: [],
|
|
93213
|
-
margin_swap_limit_amount: Web3Number.fromWei(
|
|
93373
|
+
margin_swap_limit_amount: Web3Number.fromWei(
|
|
93374
|
+
0,
|
|
93375
|
+
this.config.collateral.decimals
|
|
93376
|
+
),
|
|
93214
93377
|
lever_swap: leverSwap,
|
|
93215
93378
|
lever_swap_limit_amount: leverSwapLimitAmount
|
|
93216
93379
|
} : {
|
|
@@ -93224,7 +93387,10 @@ spurious results.`);
|
|
|
93224
93387
|
lever_swap_limit_amount: leverSwapLimitAmount,
|
|
93225
93388
|
lever_swap_weights: [],
|
|
93226
93389
|
withdraw_swap: [],
|
|
93227
|
-
withdraw_swap_limit_amount: Web3Number.fromWei(
|
|
93390
|
+
withdraw_swap_limit_amount: Web3Number.fromWei(
|
|
93391
|
+
0,
|
|
93392
|
+
this.config.collateral.decimals
|
|
93393
|
+
),
|
|
93228
93394
|
withdraw_swap_weights: [],
|
|
93229
93395
|
close_position: false
|
|
93230
93396
|
};
|
|
@@ -93240,12 +93406,16 @@ spurious results.`);
|
|
|
93240
93406
|
});
|
|
93241
93407
|
let leverSwap = [];
|
|
93242
93408
|
let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
93243
|
-
const existingPositions = await this.vesuAdapter.getPositions(
|
|
93409
|
+
const existingPositions = await this.vesuAdapter.getPositions(
|
|
93410
|
+
this.config.networkConfig
|
|
93411
|
+
);
|
|
93244
93412
|
const existingCollateralInfo = existingPositions[0];
|
|
93245
93413
|
const existingDebtInfo = existingPositions[1];
|
|
93246
93414
|
const collateralToken = this.config.collateral;
|
|
93247
93415
|
const debtToken = this.config.debt;
|
|
93248
|
-
const collateralPrice = await this.config.pricer.getPrice(
|
|
93416
|
+
const collateralPrice = await this.config.pricer.getPrice(
|
|
93417
|
+
collateralToken.symbol
|
|
93418
|
+
);
|
|
93249
93419
|
const debtPrice = await this.config.pricer.getPrice(debtToken.symbol);
|
|
93250
93420
|
const { deltadebtAmountUnits: debtAmountToRepay } = calculateDebtReductionAmountForWithdrawal(
|
|
93251
93421
|
existingDebtInfo.amount,
|
|
@@ -93256,27 +93426,41 @@ spurious results.`);
|
|
|
93256
93426
|
debtPrice.price,
|
|
93257
93427
|
debtToken.decimals
|
|
93258
93428
|
);
|
|
93259
|
-
console.log("debtAmountToRepay", debtAmountToRepay);
|
|
93260
93429
|
if (!debtAmountToRepay) {
|
|
93261
93430
|
throw new Error("error calculating debt amount to repay");
|
|
93262
93431
|
}
|
|
93263
|
-
const ekuboQuoter = new EkuboQuoter(
|
|
93264
|
-
|
|
93265
|
-
|
|
93432
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
93433
|
+
this.config.networkConfig,
|
|
93434
|
+
this.config.pricer
|
|
93435
|
+
);
|
|
93436
|
+
const debtInDebtUnits = new Web3Number(
|
|
93437
|
+
debtAmountToRepay,
|
|
93438
|
+
debtToken.decimals
|
|
93439
|
+
).dividedBy(debtPrice.price).multipliedBy(10 ** debtToken.decimals);
|
|
93266
93440
|
const swapQuote = await ekuboQuoter.getQuote(
|
|
93267
93441
|
debtToken.address.address,
|
|
93268
93442
|
collateralToken.address.address,
|
|
93269
93443
|
debtInDebtUnits
|
|
93270
93444
|
);
|
|
93271
93445
|
const MAX_SLIPPAGE = 2e-3;
|
|
93272
|
-
if (swapQuote.price_impact <
|
|
93273
|
-
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
93446
|
+
if (swapQuote.price_impact < 25e-4) {
|
|
93447
|
+
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
93448
|
+
swapQuote,
|
|
93449
|
+
collateralToken,
|
|
93450
|
+
debtToken
|
|
93451
|
+
);
|
|
93274
93452
|
} else {
|
|
93275
|
-
logger2.error(
|
|
93453
|
+
logger2.error(
|
|
93454
|
+
`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
|
|
93455
|
+
);
|
|
93276
93456
|
}
|
|
93277
|
-
|
|
93278
|
-
|
|
93279
|
-
|
|
93457
|
+
leverSwapLimitAmount = new Web3Number(debtAmountToRepay, debtToken.decimals).abs().multipliedBy(1 + MAX_SLIPPAGE);
|
|
93458
|
+
const multiplyParams = await this.getLeverParams(
|
|
93459
|
+
false,
|
|
93460
|
+
params,
|
|
93461
|
+
leverSwap,
|
|
93462
|
+
leverSwapLimitAmount
|
|
93463
|
+
);
|
|
93280
93464
|
const call = multiplyContract.populate("modify_lever", {
|
|
93281
93465
|
modify_lever_params: this.formatMultiplyParams(false, multiplyParams)
|
|
93282
93466
|
});
|
|
@@ -93286,100 +93470,132 @@ spurious results.`);
|
|
|
93286
93470
|
if (isIncrease) {
|
|
93287
93471
|
const _params2 = params;
|
|
93288
93472
|
return {
|
|
93289
|
-
action: new CairoCustomEnum({
|
|
93290
|
-
|
|
93291
|
-
|
|
93292
|
-
|
|
93293
|
-
|
|
93294
|
-
|
|
93295
|
-
|
|
93473
|
+
action: new CairoCustomEnum({
|
|
93474
|
+
IncreaseLever: {
|
|
93475
|
+
pool_id: _params2.pool_id.toBigInt(),
|
|
93476
|
+
collateral_asset: _params2.collateral_asset.toBigInt(),
|
|
93477
|
+
debt_asset: _params2.debt_asset.toBigInt(),
|
|
93478
|
+
user: _params2.user.toBigInt(),
|
|
93479
|
+
add_margin: BigInt(_params2.add_margin.toWei()),
|
|
93480
|
+
margin_swap: _params2.margin_swap.map((swap) => ({
|
|
93481
|
+
route: swap.route.map((route) => ({
|
|
93482
|
+
pool_key: {
|
|
93483
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
93484
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
93485
|
+
fee: route.pool_key.fee,
|
|
93486
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
93487
|
+
extension: BigInt(
|
|
93488
|
+
num_exports.hexToDecimalString(route.pool_key.extension)
|
|
93489
|
+
)
|
|
93490
|
+
},
|
|
93491
|
+
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93492
|
+
route.sqrt_ratio_limit.toWei()
|
|
93493
|
+
),
|
|
93494
|
+
skip_ahead: BigInt(100)
|
|
93495
|
+
})),
|
|
93496
|
+
token_amount: {
|
|
93497
|
+
token: swap.token_amount.token.toBigInt(),
|
|
93498
|
+
amount: swap.token_amount.amount.toI129()
|
|
93499
|
+
}
|
|
93500
|
+
})),
|
|
93501
|
+
margin_swap_limit_amount: BigInt(
|
|
93502
|
+
_params2.margin_swap_limit_amount.toWei()
|
|
93503
|
+
),
|
|
93504
|
+
lever_swap: _params2.lever_swap.map((swap) => ({
|
|
93505
|
+
route: swap.route.map((route) => ({
|
|
93506
|
+
pool_key: {
|
|
93507
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
93508
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
93509
|
+
fee: route.pool_key.fee,
|
|
93510
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
93511
|
+
extension: BigInt(
|
|
93512
|
+
num_exports.hexToDecimalString(route.pool_key.extension)
|
|
93513
|
+
)
|
|
93514
|
+
},
|
|
93515
|
+
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93516
|
+
route.sqrt_ratio_limit.toWei()
|
|
93517
|
+
),
|
|
93518
|
+
skip_ahead: BigInt(0)
|
|
93519
|
+
})),
|
|
93520
|
+
token_amount: {
|
|
93521
|
+
token: swap.token_amount.token.toBigInt(),
|
|
93522
|
+
amount: swap.token_amount.amount.toI129()
|
|
93523
|
+
}
|
|
93524
|
+
})),
|
|
93525
|
+
lever_swap_limit_amount: BigInt(
|
|
93526
|
+
_params2.lever_swap_limit_amount.toWei()
|
|
93527
|
+
)
|
|
93528
|
+
}
|
|
93529
|
+
})
|
|
93530
|
+
};
|
|
93531
|
+
}
|
|
93532
|
+
const _params = params;
|
|
93533
|
+
return {
|
|
93534
|
+
action: new CairoCustomEnum({
|
|
93535
|
+
DecreaseLever: {
|
|
93536
|
+
pool_id: _params.pool_id.toBigInt(),
|
|
93537
|
+
collateral_asset: _params.collateral_asset.toBigInt(),
|
|
93538
|
+
debt_asset: _params.debt_asset.toBigInt(),
|
|
93539
|
+
user: _params.user.toBigInt(),
|
|
93540
|
+
sub_margin: BigInt(_params.sub_margin.toWei()),
|
|
93541
|
+
recipient: _params.recipient.toBigInt(),
|
|
93542
|
+
lever_swap: _params.lever_swap.map((swap) => ({
|
|
93296
93543
|
route: swap.route.map((route) => ({
|
|
93297
93544
|
pool_key: {
|
|
93298
93545
|
token0: route.pool_key.token0.toBigInt(),
|
|
93299
93546
|
token1: route.pool_key.token1.toBigInt(),
|
|
93300
93547
|
fee: route.pool_key.fee,
|
|
93301
93548
|
tick_spacing: route.pool_key.tick_spacing,
|
|
93302
|
-
extension:
|
|
93549
|
+
extension: ContractAddr.from(
|
|
93550
|
+
route.pool_key.extension
|
|
93551
|
+
).toBigInt()
|
|
93303
93552
|
},
|
|
93304
|
-
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93305
|
-
|
|
93553
|
+
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93554
|
+
route.sqrt_ratio_limit.toWei()
|
|
93555
|
+
),
|
|
93556
|
+
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
93306
93557
|
})),
|
|
93307
93558
|
token_amount: {
|
|
93308
93559
|
token: swap.token_amount.token.toBigInt(),
|
|
93309
93560
|
amount: swap.token_amount.amount.toI129()
|
|
93310
93561
|
}
|
|
93311
93562
|
})),
|
|
93312
|
-
|
|
93313
|
-
|
|
93563
|
+
lever_swap_limit_amount: BigInt(
|
|
93564
|
+
_params.lever_swap_limit_amount.toWei()
|
|
93565
|
+
),
|
|
93566
|
+
lever_swap_weights: _params.lever_swap_weights.map(
|
|
93567
|
+
(weight) => BigInt(weight.toWei())
|
|
93568
|
+
),
|
|
93569
|
+
withdraw_swap: _params.withdraw_swap.map((swap) => ({
|
|
93314
93570
|
route: swap.route.map((route) => ({
|
|
93315
93571
|
pool_key: {
|
|
93316
93572
|
token0: route.pool_key.token0.toBigInt(),
|
|
93317
93573
|
token1: route.pool_key.token1.toBigInt(),
|
|
93318
93574
|
fee: route.pool_key.fee,
|
|
93319
93575
|
tick_spacing: route.pool_key.tick_spacing,
|
|
93320
|
-
extension:
|
|
93576
|
+
extension: ContractAddr.from(
|
|
93577
|
+
route.pool_key.extension
|
|
93578
|
+
).toBigInt()
|
|
93321
93579
|
},
|
|
93322
|
-
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93323
|
-
|
|
93580
|
+
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93581
|
+
route.sqrt_ratio_limit.toWei()
|
|
93582
|
+
),
|
|
93583
|
+
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
93324
93584
|
})),
|
|
93325
93585
|
token_amount: {
|
|
93326
93586
|
token: swap.token_amount.token.toBigInt(),
|
|
93327
93587
|
amount: swap.token_amount.amount.toI129()
|
|
93328
93588
|
}
|
|
93329
93589
|
})),
|
|
93330
|
-
|
|
93331
|
-
|
|
93332
|
-
|
|
93333
|
-
|
|
93334
|
-
|
|
93335
|
-
|
|
93336
|
-
|
|
93337
|
-
|
|
93338
|
-
|
|
93339
|
-
debt_asset: _params.debt_asset.toBigInt(),
|
|
93340
|
-
user: _params.user.toBigInt(),
|
|
93341
|
-
sub_margin: BigInt(_params.sub_margin.toWei()),
|
|
93342
|
-
recipient: _params.recipient.toBigInt(),
|
|
93343
|
-
lever_swap: _params.lever_swap.map((swap) => ({
|
|
93344
|
-
route: swap.route.map((route) => ({
|
|
93345
|
-
pool_key: {
|
|
93346
|
-
token0: route.pool_key.token0.toBigInt(),
|
|
93347
|
-
token1: route.pool_key.token1.toBigInt(),
|
|
93348
|
-
fee: route.pool_key.fee,
|
|
93349
|
-
tick_spacing: route.pool_key.tick_spacing,
|
|
93350
|
-
extension: ContractAddr.from(route.pool_key.extension).toBigInt()
|
|
93351
|
-
},
|
|
93352
|
-
sqrt_ratio_limit: uint256_exports.bnToUint256(route.sqrt_ratio_limit.toWei()),
|
|
93353
|
-
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
93354
|
-
})),
|
|
93355
|
-
token_amount: {
|
|
93356
|
-
token: swap.token_amount.token.toBigInt(),
|
|
93357
|
-
amount: swap.token_amount.amount.toI129()
|
|
93358
|
-
}
|
|
93359
|
-
})),
|
|
93360
|
-
lever_swap_limit_amount: BigInt(_params.lever_swap_limit_amount.toWei()),
|
|
93361
|
-
lever_swap_weights: _params.lever_swap_weights.map((weight) => BigInt(weight.toWei())),
|
|
93362
|
-
withdraw_swap: _params.withdraw_swap.map((swap) => ({
|
|
93363
|
-
route: swap.route.map((route) => ({
|
|
93364
|
-
pool_key: {
|
|
93365
|
-
token0: route.pool_key.token0.toBigInt(),
|
|
93366
|
-
token1: route.pool_key.token1.toBigInt(),
|
|
93367
|
-
fee: route.pool_key.fee,
|
|
93368
|
-
tick_spacing: route.pool_key.tick_spacing,
|
|
93369
|
-
extension: ContractAddr.from(route.pool_key.extension).toBigInt()
|
|
93370
|
-
},
|
|
93371
|
-
sqrt_ratio_limit: uint256_exports.bnToUint256(route.sqrt_ratio_limit.toWei()),
|
|
93372
|
-
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
93373
|
-
})),
|
|
93374
|
-
token_amount: {
|
|
93375
|
-
token: swap.token_amount.token.toBigInt(),
|
|
93376
|
-
amount: swap.token_amount.amount.toI129()
|
|
93377
|
-
}
|
|
93378
|
-
})),
|
|
93379
|
-
withdraw_swap_limit_amount: BigInt(_params.withdraw_swap_limit_amount.toWei()),
|
|
93380
|
-
withdraw_swap_weights: _params.withdraw_swap_weights.map((weight) => BigInt(weight.toWei())),
|
|
93381
|
-
close_position: _params.close_position
|
|
93382
|
-
} })
|
|
93590
|
+
withdraw_swap_limit_amount: BigInt(
|
|
93591
|
+
_params.withdraw_swap_limit_amount.toWei()
|
|
93592
|
+
),
|
|
93593
|
+
withdraw_swap_weights: _params.withdraw_swap_weights.map(
|
|
93594
|
+
(weight) => BigInt(weight.toWei())
|
|
93595
|
+
),
|
|
93596
|
+
close_position: _params.close_position
|
|
93597
|
+
}
|
|
93598
|
+
})
|
|
93383
93599
|
};
|
|
93384
93600
|
}
|
|
93385
93601
|
async getHealthFactor() {
|
|
@@ -93388,11 +93604,15 @@ spurious results.`);
|
|
|
93388
93604
|
}
|
|
93389
93605
|
async getNetAPY() {
|
|
93390
93606
|
const positions = await this.getPositions();
|
|
93391
|
-
logger2.verbose(
|
|
93607
|
+
logger2.verbose(
|
|
93608
|
+
`${this.name}::getNetAPY: positions: ${JSON.stringify(positions)}`
|
|
93609
|
+
);
|
|
93392
93610
|
const allZero = positions.every((p) => p.usdValue === 0);
|
|
93393
93611
|
if (allZero) {
|
|
93394
93612
|
const collateralUSD = 1e3;
|
|
93395
|
-
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
93613
|
+
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
93614
|
+
this.config.networkConfig
|
|
93615
|
+
);
|
|
93396
93616
|
const targetHF = this.config.targetHealthFactor;
|
|
93397
93617
|
const maxDebt = HealthFactorMath.getMaxDebtAmountOnLooping(
|
|
93398
93618
|
new Web3Number(collateralUSD, this.config.collateral.decimals),
|
|
@@ -93426,12 +93646,17 @@ spurious results.`);
|
|
|
93426
93646
|
timeout: this.config.extendedTimeout,
|
|
93427
93647
|
retries: this.config.extendedRetries
|
|
93428
93648
|
});
|
|
93649
|
+
this.minimumExtendedMovementAmount = this.config.minimumExtendedMovementAmount ?? 5;
|
|
93429
93650
|
this.client = client;
|
|
93651
|
+
this.retryDelayForOrderStatus = this.config.retryDelayForOrderStatus ?? 3e3;
|
|
93430
93652
|
}
|
|
93431
93653
|
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
93432
93654
|
async getAPY(supportedPosition) {
|
|
93433
93655
|
const side = supportedPosition.isDebt ? "LONG" : "SHORT";
|
|
93434
|
-
const fundingRates = await this.client.getFundingRates(
|
|
93656
|
+
const fundingRates = await this.client.getFundingRates(
|
|
93657
|
+
this.config.extendedMarketName,
|
|
93658
|
+
side
|
|
93659
|
+
);
|
|
93435
93660
|
if (fundingRates.status !== "OK") {
|
|
93436
93661
|
logger2.error("error getting funding rates", fundingRates);
|
|
93437
93662
|
return { apy: 0, type: "base" /* BASE */ };
|
|
@@ -93475,14 +93700,14 @@ spurious results.`);
|
|
|
93475
93700
|
});
|
|
93476
93701
|
}
|
|
93477
93702
|
_getDepositLeaf() {
|
|
93478
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
93703
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
93704
|
+
(token) => token.symbol === "USDCe"
|
|
93705
|
+
);
|
|
93479
93706
|
return [
|
|
93480
93707
|
{
|
|
93481
93708
|
target: this.config.supportedPositions[0].asset.address,
|
|
93482
93709
|
method: "approve",
|
|
93483
|
-
packedArguments: [
|
|
93484
|
-
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()
|
|
93485
|
-
],
|
|
93710
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
93486
93711
|
id: `extended_approve_${this.config.supportedPositions[0].asset.symbol}`,
|
|
93487
93712
|
sanitizer: AVNU_LEGACY_SANITIZER
|
|
93488
93713
|
},
|
|
@@ -93509,17 +93734,62 @@ spurious results.`);
|
|
|
93509
93734
|
}
|
|
93510
93735
|
];
|
|
93511
93736
|
}
|
|
93737
|
+
getSwapFromLegacyLeaf() {
|
|
93738
|
+
const leafConfigs = this._getSwapFromLegacyLeaf();
|
|
93739
|
+
const leaves = leafConfigs.map((config3) => {
|
|
93740
|
+
const { target, method, packedArguments, sanitizer, id } = config3;
|
|
93741
|
+
const leaf = this.constructSimpleLeafData(
|
|
93742
|
+
{
|
|
93743
|
+
id,
|
|
93744
|
+
target,
|
|
93745
|
+
method,
|
|
93746
|
+
packedArguments
|
|
93747
|
+
},
|
|
93748
|
+
sanitizer
|
|
93749
|
+
);
|
|
93750
|
+
return leaf;
|
|
93751
|
+
});
|
|
93752
|
+
return {
|
|
93753
|
+
leaves,
|
|
93754
|
+
callConstructor: this.getSwapFromLegacyCall.bind(
|
|
93755
|
+
this
|
|
93756
|
+
)
|
|
93757
|
+
};
|
|
93758
|
+
}
|
|
93759
|
+
_getSwapFromLegacyLeaf() {
|
|
93760
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
93761
|
+
(token) => token.symbol === "USDCe"
|
|
93762
|
+
);
|
|
93763
|
+
return [
|
|
93764
|
+
{
|
|
93765
|
+
target: usdceToken.address,
|
|
93766
|
+
method: "approve",
|
|
93767
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
93768
|
+
id: `extendedswaplegacyapprove_${usdceToken.symbol}`,
|
|
93769
|
+
sanitizer: AVNU_LEGACY_SANITIZER
|
|
93770
|
+
},
|
|
93771
|
+
{
|
|
93772
|
+
target: AVNU_EXCHANGE_FOR_LEGACY_USDC,
|
|
93773
|
+
method: "swap_to_new",
|
|
93774
|
+
packedArguments: [],
|
|
93775
|
+
id: `extended_swap_to_new_${usdceToken.symbol}`,
|
|
93776
|
+
sanitizer: AVNU_LEGACY_SANITIZER
|
|
93777
|
+
}
|
|
93778
|
+
];
|
|
93779
|
+
}
|
|
93512
93780
|
_getWithdrawLeaf() {
|
|
93513
93781
|
return [];
|
|
93514
93782
|
}
|
|
93515
93783
|
async getDepositCall(params) {
|
|
93516
93784
|
try {
|
|
93517
93785
|
const usdcToken = this.config.supportedPositions[0].asset;
|
|
93518
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
93519
|
-
|
|
93520
|
-
|
|
93786
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
93787
|
+
(token) => token.symbol === "USDCe"
|
|
93788
|
+
);
|
|
93789
|
+
const salt = Math.floor(Math.random() * 10 ** usdcToken.decimals);
|
|
93790
|
+
const amount = uint256_exports.bnToUint256(
|
|
93791
|
+
params.amount.multipliedBy(10).toWei()
|
|
93521
93792
|
);
|
|
93522
|
-
const amount = uint256_exports.bnToUint256(params.amount.multipliedBy(10).toWei());
|
|
93523
93793
|
const quotes = await this.config.avnuAdapter.getQuotesAvnu(
|
|
93524
93794
|
usdcToken.address.toString(),
|
|
93525
93795
|
usdceToken.address.toString(),
|
|
@@ -93532,7 +93802,9 @@ spurious results.`);
|
|
|
93532
93802
|
logger2.error("error getting quotes from avnu");
|
|
93533
93803
|
return [];
|
|
93534
93804
|
}
|
|
93535
|
-
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
93805
|
+
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
93806
|
+
quotes
|
|
93807
|
+
);
|
|
93536
93808
|
const swapCallData = getCalldata[0];
|
|
93537
93809
|
return [
|
|
93538
93810
|
{
|
|
@@ -93589,6 +93861,76 @@ spurious results.`);
|
|
|
93589
93861
|
return [];
|
|
93590
93862
|
}
|
|
93591
93863
|
}
|
|
93864
|
+
getProofsForFromLegacySwap(tree) {
|
|
93865
|
+
let proofGroups = [];
|
|
93866
|
+
const ids = this.getSwapFromLegacyLeaf().leaves.map((l) => l.readableId);
|
|
93867
|
+
for (const [i, v] of tree.entries()) {
|
|
93868
|
+
if (ids.includes(v.readableId)) {
|
|
93869
|
+
proofGroups.push(tree.getProof(i));
|
|
93870
|
+
}
|
|
93871
|
+
}
|
|
93872
|
+
if (proofGroups.length != ids.length) {
|
|
93873
|
+
throw new Error(`Not all proofs found for IDs: ${ids.join(", ")}`);
|
|
93874
|
+
}
|
|
93875
|
+
return {
|
|
93876
|
+
proofs: proofGroups,
|
|
93877
|
+
callConstructor: this.getSwapFromLegacyCall.bind(this)
|
|
93878
|
+
};
|
|
93879
|
+
}
|
|
93880
|
+
async getSwapFromLegacyCall(params) {
|
|
93881
|
+
try {
|
|
93882
|
+
const usdcToken = this.config.supportedPositions[0].asset;
|
|
93883
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
93884
|
+
(token) => token.symbol === "USDCe"
|
|
93885
|
+
);
|
|
93886
|
+
const amount = uint256_exports.bnToUint256(
|
|
93887
|
+
params.amount.multipliedBy(10).toWei()
|
|
93888
|
+
);
|
|
93889
|
+
const quotes = await this.config.avnuAdapter.getQuotesAvnu(
|
|
93890
|
+
usdceToken.address.toString(),
|
|
93891
|
+
usdcToken.address.toString(),
|
|
93892
|
+
params.amount.toNumber(),
|
|
93893
|
+
this.config.avnuAdapter.config.vaultAllocator.address.toString(),
|
|
93894
|
+
usdcToken.decimals,
|
|
93895
|
+
false
|
|
93896
|
+
);
|
|
93897
|
+
if (!quotes) {
|
|
93898
|
+
logger2.error("error getting quotes from avnu");
|
|
93899
|
+
return [];
|
|
93900
|
+
}
|
|
93901
|
+
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
93902
|
+
quotes
|
|
93903
|
+
);
|
|
93904
|
+
const swapCallData = getCalldata[0];
|
|
93905
|
+
return [
|
|
93906
|
+
{
|
|
93907
|
+
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
93908
|
+
call: {
|
|
93909
|
+
contractAddress: usdceToken.address,
|
|
93910
|
+
selector: hash_exports.getSelectorFromName("approve"),
|
|
93911
|
+
calldata: [
|
|
93912
|
+
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
|
|
93913
|
+
toBigInt3(amount.low.toString()),
|
|
93914
|
+
// amount low
|
|
93915
|
+
toBigInt3(amount.high.toString())
|
|
93916
|
+
// amount high
|
|
93917
|
+
]
|
|
93918
|
+
}
|
|
93919
|
+
},
|
|
93920
|
+
{
|
|
93921
|
+
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
93922
|
+
call: {
|
|
93923
|
+
contractAddress: AVNU_EXCHANGE_FOR_LEGACY_USDC,
|
|
93924
|
+
selector: hash_exports.getSelectorFromName("swap_to_new"),
|
|
93925
|
+
calldata: swapCallData
|
|
93926
|
+
}
|
|
93927
|
+
}
|
|
93928
|
+
];
|
|
93929
|
+
} catch (error2) {
|
|
93930
|
+
logger2.error(`Error creating Deposit Call: ${error2}`);
|
|
93931
|
+
return [];
|
|
93932
|
+
}
|
|
93933
|
+
}
|
|
93592
93934
|
//Swap wbtc to usdc
|
|
93593
93935
|
async getWithdrawCall(params) {
|
|
93594
93936
|
try {
|
|
@@ -93604,13 +93946,60 @@ spurious results.`);
|
|
|
93604
93946
|
async withdrawFromExtended(amount) {
|
|
93605
93947
|
try {
|
|
93606
93948
|
if (!this.client) {
|
|
93607
|
-
|
|
93949
|
+
logger2.error("Client not initialized");
|
|
93950
|
+
return false;
|
|
93608
93951
|
}
|
|
93609
|
-
|
|
93610
|
-
|
|
93611
|
-
|
|
93612
|
-
|
|
93952
|
+
if (amount.lessThanOrEqualTo(0)) {
|
|
93953
|
+
logger2.error(
|
|
93954
|
+
`Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
|
|
93955
|
+
);
|
|
93956
|
+
return false;
|
|
93957
|
+
}
|
|
93958
|
+
if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
|
|
93959
|
+
logger2.warn(
|
|
93960
|
+
`Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
|
|
93961
|
+
);
|
|
93962
|
+
return false;
|
|
93963
|
+
}
|
|
93964
|
+
const holdings = await this.getExtendedDepositAmount();
|
|
93965
|
+
if (!holdings) {
|
|
93966
|
+
logger2.error(
|
|
93967
|
+
"Cannot get holdings - unable to validate withdrawal amount"
|
|
93968
|
+
);
|
|
93969
|
+
return false;
|
|
93613
93970
|
}
|
|
93971
|
+
const availableForWithdrawal = parseFloat(
|
|
93972
|
+
holdings.availableForWithdrawal
|
|
93973
|
+
);
|
|
93974
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
93975
|
+
logger2.error(
|
|
93976
|
+
`Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
93977
|
+
);
|
|
93978
|
+
return false;
|
|
93979
|
+
}
|
|
93980
|
+
const withdrawalAmount = amount.toNumber();
|
|
93981
|
+
if (withdrawalAmount > availableForWithdrawal) {
|
|
93982
|
+
logger2.error(
|
|
93983
|
+
`Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
|
|
93984
|
+
);
|
|
93985
|
+
return false;
|
|
93986
|
+
}
|
|
93987
|
+
logger2.info(
|
|
93988
|
+
`Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
|
|
93989
|
+
);
|
|
93990
|
+
const withdrawalRequest = await this.client.withdrawUSDC(
|
|
93991
|
+
amount.toFixed(2)
|
|
93992
|
+
);
|
|
93993
|
+
if (withdrawalRequest.status === "OK") {
|
|
93994
|
+
const withdrawalStatus = await this.getDepositOrWithdrawalStatus(
|
|
93995
|
+
withdrawalRequest.data,
|
|
93996
|
+
"WITHDRAWAL" /* WITHDRAWAL */
|
|
93997
|
+
);
|
|
93998
|
+
return withdrawalStatus;
|
|
93999
|
+
}
|
|
94000
|
+
logger2.error(
|
|
94001
|
+
`Withdrawal request failed with status: ${withdrawalRequest.status}`
|
|
94002
|
+
);
|
|
93614
94003
|
return false;
|
|
93615
94004
|
} catch (error2) {
|
|
93616
94005
|
logger2.error(`Error creating Withdraw Call: ${error2}`);
|
|
@@ -93621,21 +94010,44 @@ spurious results.`);
|
|
|
93621
94010
|
return Promise.resolve(1);
|
|
93622
94011
|
}
|
|
93623
94012
|
async getExtendedDepositAmount() {
|
|
93624
|
-
|
|
93625
|
-
|
|
93626
|
-
|
|
93627
|
-
|
|
93628
|
-
|
|
93629
|
-
|
|
93630
|
-
|
|
93631
|
-
|
|
93632
|
-
|
|
93633
|
-
|
|
93634
|
-
|
|
93635
|
-
|
|
94013
|
+
try {
|
|
94014
|
+
if (this.client === null) {
|
|
94015
|
+
logger2.error("error initializing client - client is null");
|
|
94016
|
+
return void 0;
|
|
94017
|
+
}
|
|
94018
|
+
const result2 = await this.client.getHoldings();
|
|
94019
|
+
if (!result2) {
|
|
94020
|
+
logger2.error("error getting holdings - API returned null/undefined");
|
|
94021
|
+
return void 0;
|
|
94022
|
+
}
|
|
94023
|
+
if (result2.status && result2.status !== "OK") {
|
|
94024
|
+
logger2.error(
|
|
94025
|
+
`error getting holdings - API returned status: ${result2.status}`
|
|
94026
|
+
);
|
|
94027
|
+
return void 0;
|
|
94028
|
+
}
|
|
94029
|
+
const holdings = result2.data;
|
|
94030
|
+
if (!holdings) {
|
|
94031
|
+
logger2.warn(
|
|
94032
|
+
"holdings data is null/undefined - treating as zero balance"
|
|
94033
|
+
);
|
|
94034
|
+
return {
|
|
94035
|
+
collateral_name: "",
|
|
94036
|
+
balance: "0",
|
|
94037
|
+
equity: "0",
|
|
94038
|
+
availableForTrade: "0",
|
|
94039
|
+
availableForWithdrawal: "0",
|
|
94040
|
+
unrealisedPnl: "0",
|
|
94041
|
+
initialMargin: "0",
|
|
94042
|
+
marginRatio: "0",
|
|
94043
|
+
updatedTime: Date.now()
|
|
94044
|
+
};
|
|
94045
|
+
}
|
|
94046
|
+
return holdings;
|
|
94047
|
+
} catch (error2) {
|
|
94048
|
+
logger2.error(`error getting holdings - exception: ${error2}`);
|
|
93636
94049
|
return void 0;
|
|
93637
94050
|
}
|
|
93638
|
-
return holdings;
|
|
93639
94051
|
}
|
|
93640
94052
|
async setLeverage(leverage, marketName) {
|
|
93641
94053
|
if (this.client === null) {
|
|
@@ -93677,21 +94089,24 @@ spurious results.`);
|
|
|
93677
94089
|
return result2.data;
|
|
93678
94090
|
}
|
|
93679
94091
|
async getOrderStatus(orderId, marketName) {
|
|
93680
|
-
|
|
93681
|
-
|
|
93682
|
-
|
|
93683
|
-
|
|
93684
|
-
|
|
93685
|
-
|
|
93686
|
-
|
|
94092
|
+
try {
|
|
94093
|
+
if (this.client === null) {
|
|
94094
|
+
logger2.error("error initializing client");
|
|
94095
|
+
return null;
|
|
94096
|
+
}
|
|
94097
|
+
const orderhistory = await this.getOrderHistory(marketName);
|
|
94098
|
+
if (!orderhistory || orderhistory.length === 0) {
|
|
94099
|
+
return null;
|
|
94100
|
+
}
|
|
94101
|
+
const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
|
|
94102
|
+
if (order) {
|
|
94103
|
+
return order;
|
|
94104
|
+
}
|
|
93687
94105
|
return null;
|
|
93688
|
-
}
|
|
93689
|
-
|
|
93690
|
-
if (!order) {
|
|
93691
|
-
logger2.error(`error getting order: ${order}`);
|
|
94106
|
+
} catch (error2) {
|
|
94107
|
+
logger2.error(`error getting order status: ${error2}`);
|
|
93692
94108
|
return null;
|
|
93693
94109
|
}
|
|
93694
|
-
return order;
|
|
93695
94110
|
}
|
|
93696
94111
|
async fetchOrderBookBTCUSDC() {
|
|
93697
94112
|
try {
|
|
@@ -93742,14 +94157,40 @@ spurious results.`);
|
|
|
93742
94157
|
logger2.error("error depositing or setting leverage");
|
|
93743
94158
|
return null;
|
|
93744
94159
|
}
|
|
93745
|
-
const
|
|
93746
|
-
if (
|
|
94160
|
+
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
94161
|
+
if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
|
|
94162
|
+
logger2.error(
|
|
94163
|
+
`Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
|
|
94164
|
+
);
|
|
93747
94165
|
return null;
|
|
93748
94166
|
}
|
|
93749
|
-
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
93750
94167
|
const spread3 = ask.minus(bid);
|
|
93751
|
-
|
|
93752
|
-
|
|
94168
|
+
const midPrice = ask.plus(bid).div(2);
|
|
94169
|
+
const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
|
|
94170
|
+
const priceAdjustmentMultiplier = Math.min(
|
|
94171
|
+
0.2 * attempt,
|
|
94172
|
+
MAX_PRICE_DEVIATION_MULTIPLIER
|
|
94173
|
+
);
|
|
94174
|
+
const priceAdjustment = spread3.times(priceAdjustmentMultiplier);
|
|
94175
|
+
let price = midPrice;
|
|
94176
|
+
if (side === "SELL" /* SELL */) {
|
|
94177
|
+
price = midPrice.minus(priceAdjustment);
|
|
94178
|
+
} else {
|
|
94179
|
+
price = midPrice.plus(priceAdjustment);
|
|
94180
|
+
}
|
|
94181
|
+
const maxDeviation = midPrice.times(0.5);
|
|
94182
|
+
if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
|
|
94183
|
+
logger2.error(
|
|
94184
|
+
`Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
|
|
94185
|
+
);
|
|
94186
|
+
if (attempt >= maxAttempts) {
|
|
94187
|
+
return null;
|
|
94188
|
+
}
|
|
94189
|
+
price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
|
|
94190
|
+
}
|
|
94191
|
+
logger2.info(
|
|
94192
|
+
`createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
|
|
94193
|
+
);
|
|
93753
94194
|
const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
|
|
93754
94195
|
this.config.extendedPrecision
|
|
93755
94196
|
);
|
|
@@ -93760,14 +94201,57 @@ spurious results.`);
|
|
|
93760
94201
|
price.toFixed(0),
|
|
93761
94202
|
side
|
|
93762
94203
|
);
|
|
93763
|
-
if (!result2) {
|
|
94204
|
+
if (!result2 || !result2.position_id) {
|
|
94205
|
+
logger2.error("Failed to create order - no position_id returned");
|
|
93764
94206
|
return null;
|
|
93765
94207
|
}
|
|
93766
|
-
|
|
93767
|
-
|
|
93768
|
-
|
|
94208
|
+
const positionId = result2.position_id;
|
|
94209
|
+
logger2.info(
|
|
94210
|
+
`Order created with position_id: ${positionId}. Waiting for API to update...`
|
|
94211
|
+
);
|
|
94212
|
+
let openOrder = await this.getOrderStatus(
|
|
94213
|
+
positionId,
|
|
94214
|
+
this.config.extendedMarketName
|
|
94215
|
+
);
|
|
94216
|
+
const maxStatusRetries = 3;
|
|
94217
|
+
const statusRetryDelay = 5e3;
|
|
94218
|
+
if (!openOrder) {
|
|
94219
|
+
logger2.warn(
|
|
94220
|
+
`Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
|
|
94221
|
+
);
|
|
94222
|
+
for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
|
|
94223
|
+
await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
|
|
94224
|
+
openOrder = await this.getOrderStatus(
|
|
94225
|
+
positionId,
|
|
94226
|
+
this.config.extendedMarketName
|
|
94227
|
+
);
|
|
94228
|
+
if (openOrder) {
|
|
94229
|
+
logger2.info(
|
|
94230
|
+
`Order ${positionId} found after ${statusRetry} status retry(ies)`
|
|
94231
|
+
);
|
|
94232
|
+
break;
|
|
94233
|
+
}
|
|
94234
|
+
logger2.warn(
|
|
94235
|
+
`Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
|
|
94236
|
+
);
|
|
94237
|
+
}
|
|
94238
|
+
}
|
|
94239
|
+
if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
|
|
94240
|
+
logger2.info(
|
|
94241
|
+
`Order ${positionId} successfully filled with quantity ${openOrder.qty}`
|
|
94242
|
+
);
|
|
94243
|
+
return {
|
|
94244
|
+
position_id: positionId,
|
|
94245
|
+
btc_exposure: openOrder.qty
|
|
94246
|
+
};
|
|
94247
|
+
} else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
|
|
94248
|
+
logger2.warn(
|
|
94249
|
+
`Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
|
|
94250
|
+
);
|
|
93769
94251
|
if (attempt >= maxAttempts) {
|
|
93770
|
-
logger2.error(
|
|
94252
|
+
logger2.error(
|
|
94253
|
+
`Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
|
|
94254
|
+
);
|
|
93771
94255
|
return null;
|
|
93772
94256
|
} else {
|
|
93773
94257
|
const backoff = 2e3 * attempt;
|
|
@@ -93781,16 +94265,21 @@ spurious results.`);
|
|
|
93781
94265
|
);
|
|
93782
94266
|
}
|
|
93783
94267
|
} else {
|
|
94268
|
+
logger2.warn(
|
|
94269
|
+
`Order ${positionId} not found in API after ${maxStatusRetries} status retries (API update delayed ~30s). We got position_id from creation, so order exists. Returning position_id - status will be checked in next loop iteration.`
|
|
94270
|
+
);
|
|
93784
94271
|
return {
|
|
93785
|
-
position_id:
|
|
93786
|
-
btc_exposure:
|
|
94272
|
+
position_id: positionId,
|
|
94273
|
+
btc_exposure: amount_in_token
|
|
93787
94274
|
};
|
|
93788
94275
|
}
|
|
93789
94276
|
} catch (err2) {
|
|
93790
|
-
logger2.error(
|
|
94277
|
+
logger2.error(
|
|
94278
|
+
`createShortOrder failed on attempt ${attempt}: ${err2.message}`
|
|
94279
|
+
);
|
|
93791
94280
|
if (attempt < maxAttempts) {
|
|
93792
94281
|
const backoff = 1200 * attempt;
|
|
93793
|
-
|
|
94282
|
+
logger2.info(`Retrying after ${backoff}ms...`);
|
|
93794
94283
|
await new Promise((resolve) => setTimeout(resolve, backoff));
|
|
93795
94284
|
return this.createOrder(
|
|
93796
94285
|
leverage,
|
|
@@ -93821,34 +94310,106 @@ spurious results.`);
|
|
|
93821
94310
|
}
|
|
93822
94311
|
return null;
|
|
93823
94312
|
} catch (err2) {
|
|
93824
|
-
|
|
94313
|
+
logger2.error(`Error opening short extended position, ${err2}`);
|
|
93825
94314
|
return null;
|
|
93826
94315
|
}
|
|
93827
94316
|
}
|
|
93828
94317
|
async getDepositOrWithdrawalStatus(orderId, operationsType) {
|
|
93829
|
-
|
|
93830
|
-
|
|
93831
|
-
|
|
93832
|
-
|
|
93833
|
-
|
|
93834
|
-
|
|
93835
|
-
|
|
93836
|
-
|
|
93837
|
-
if (
|
|
93838
|
-
|
|
94318
|
+
const maxAttempts = 15;
|
|
94319
|
+
const retryDelayMs = 3e4;
|
|
94320
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
94321
|
+
try {
|
|
94322
|
+
let transferHistory = await this.client.getAssetOperations({
|
|
94323
|
+
operationsType: [operationsType],
|
|
94324
|
+
operationsStatus: ["COMPLETED" /* COMPLETED */]
|
|
94325
|
+
});
|
|
94326
|
+
if (operationsType === "DEPOSIT" /* DEPOSIT */) {
|
|
94327
|
+
const myTransferStatus = transferHistory.data.find(
|
|
94328
|
+
(operation) => operation.transactionHash === orderId
|
|
94329
|
+
);
|
|
94330
|
+
if (!myTransferStatus) {
|
|
94331
|
+
if (attempt < maxAttempts) {
|
|
94332
|
+
logger2.info(
|
|
94333
|
+
`Deposit operation not found for transactionHash ${orderId}, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
94334
|
+
);
|
|
94335
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
94336
|
+
continue;
|
|
94337
|
+
}
|
|
94338
|
+
logger2.warn(
|
|
94339
|
+
`Deposit operation not found for transactionHash ${orderId} after ${maxAttempts} attempts`
|
|
94340
|
+
);
|
|
94341
|
+
return false;
|
|
94342
|
+
}
|
|
94343
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
94344
|
+
logger2.info(
|
|
94345
|
+
`Deposit operation ${orderId} completed successfully`
|
|
94346
|
+
);
|
|
94347
|
+
return true;
|
|
94348
|
+
} else {
|
|
94349
|
+
if (attempt < maxAttempts) {
|
|
94350
|
+
logger2.info(
|
|
94351
|
+
`Deposit operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
94352
|
+
);
|
|
94353
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
94354
|
+
continue;
|
|
94355
|
+
}
|
|
94356
|
+
logger2.warn(
|
|
94357
|
+
`Deposit operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
94358
|
+
);
|
|
94359
|
+
return false;
|
|
94360
|
+
}
|
|
94361
|
+
} else {
|
|
94362
|
+
const myTransferStatus = transferHistory.data.find(
|
|
94363
|
+
(operation) => operation.id.toString() === orderId.toString()
|
|
94364
|
+
);
|
|
94365
|
+
if (!myTransferStatus) {
|
|
94366
|
+
if (attempt < maxAttempts) {
|
|
94367
|
+
logger2.info(
|
|
94368
|
+
`Withdrawal status not found for orderId ${orderId} in completed operations, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
94369
|
+
);
|
|
94370
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
94371
|
+
continue;
|
|
94372
|
+
}
|
|
94373
|
+
logger2.warn(
|
|
94374
|
+
`Withdrawal operation not found for orderId ${orderId} after ${maxAttempts} attempts`
|
|
94375
|
+
);
|
|
94376
|
+
return false;
|
|
94377
|
+
}
|
|
94378
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
94379
|
+
logger2.info(
|
|
94380
|
+
`Withdrawal operation ${orderId} completed successfully`
|
|
94381
|
+
);
|
|
94382
|
+
return true;
|
|
94383
|
+
} else {
|
|
94384
|
+
if (attempt < maxAttempts) {
|
|
94385
|
+
logger2.info(
|
|
94386
|
+
`Withdrawal operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
94387
|
+
);
|
|
94388
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
94389
|
+
continue;
|
|
94390
|
+
}
|
|
94391
|
+
logger2.warn(
|
|
94392
|
+
`Withdrawal operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
94393
|
+
);
|
|
94394
|
+
return false;
|
|
94395
|
+
}
|
|
93839
94396
|
}
|
|
93840
|
-
|
|
93841
|
-
|
|
93842
|
-
|
|
93843
|
-
|
|
93844
|
-
|
|
94397
|
+
} catch (err2) {
|
|
94398
|
+
logger2.error(
|
|
94399
|
+
`error getting deposit or withdrawal status (attempt ${attempt}/${maxAttempts}): ${err2}`
|
|
94400
|
+
);
|
|
94401
|
+
if (attempt < maxAttempts) {
|
|
94402
|
+
logger2.info(`Retrying after ${retryDelayMs}ms...`);
|
|
94403
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
94404
|
+
continue;
|
|
93845
94405
|
}
|
|
93846
|
-
|
|
94406
|
+
logger2.error(
|
|
94407
|
+
`Max retry attempts reached for getDepositOrWithdrawalStatus`
|
|
94408
|
+
);
|
|
94409
|
+
return false;
|
|
93847
94410
|
}
|
|
93848
|
-
} catch (err2) {
|
|
93849
|
-
logger2.error(`error getting deposit or withdrawal status: ${err2}`);
|
|
93850
|
-
return false;
|
|
93851
94411
|
}
|
|
94412
|
+
return false;
|
|
93852
94413
|
}
|
|
93853
94414
|
};
|
|
93854
94415
|
|
|
@@ -93934,6 +94495,11 @@ spurious results.`);
|
|
|
93934
94495
|
AUMTypes2["DEFISPRING"] = "defispring";
|
|
93935
94496
|
return AUMTypes2;
|
|
93936
94497
|
})(AUMTypes || {});
|
|
94498
|
+
var PositionTypeAvnuExtended = /* @__PURE__ */ ((PositionTypeAvnuExtended2) => {
|
|
94499
|
+
PositionTypeAvnuExtended2["OPEN"] = "open";
|
|
94500
|
+
PositionTypeAvnuExtended2["CLOSE"] = "close";
|
|
94501
|
+
return PositionTypeAvnuExtended2;
|
|
94502
|
+
})(PositionTypeAvnuExtended || {});
|
|
93937
94503
|
var UNIVERSAL_MANAGE_IDS = /* @__PURE__ */ ((UNIVERSAL_MANAGE_IDS2) => {
|
|
93938
94504
|
UNIVERSAL_MANAGE_IDS2["FLASH_LOAN"] = "flash_loan_init";
|
|
93939
94505
|
UNIVERSAL_MANAGE_IDS2["VESU_LEG1"] = "vesu_leg1";
|
|
@@ -97111,7 +97677,8 @@ spurious results.`);
|
|
|
97111
97677
|
minHealthFactor: vaultSettings.minHealthFactor,
|
|
97112
97678
|
quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
|
|
97113
97679
|
...baseAdapterConfig,
|
|
97114
|
-
supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }]
|
|
97680
|
+
supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
|
|
97681
|
+
minimumVesuMovementAmount: 0
|
|
97115
97682
|
}));
|
|
97116
97683
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
97117
97684
|
...baseAdapterConfig
|
|
@@ -97425,7 +97992,7 @@ spurious results.`);
|
|
|
97425
97992
|
packedArguments: [
|
|
97426
97993
|
fromToken.address.toBigInt(),
|
|
97427
97994
|
//wbtc
|
|
97428
|
-
|
|
97995
|
+
toToken.address.toBigInt(),
|
|
97429
97996
|
//usdc
|
|
97430
97997
|
vaultAllocator.toBigInt()
|
|
97431
97998
|
],
|
|
@@ -97439,13 +98006,11 @@ spurious results.`);
|
|
|
97439
98006
|
}
|
|
97440
98007
|
async getDepositCall(params) {
|
|
97441
98008
|
try {
|
|
97442
|
-
console.log("params.amount", params.amount);
|
|
97443
98009
|
const fromToken = this.config.supportedPositions[0].asset;
|
|
97444
98010
|
const toToken = this.config.supportedPositions[1].asset;
|
|
97445
98011
|
const vaultAllocator = ContractAddr.from(
|
|
97446
98012
|
this.config.vaultAllocator.address
|
|
97447
98013
|
);
|
|
97448
|
-
console.log("vaultAllocator", vaultAllocator);
|
|
97449
98014
|
const quote = await this.getQuotesAvnu(
|
|
97450
98015
|
fromToken.address.toString(),
|
|
97451
98016
|
toToken.address.toString(),
|
|
@@ -97501,7 +98066,6 @@ spurious results.`);
|
|
|
97501
98066
|
const vaultAllocator = ContractAddr.from(
|
|
97502
98067
|
this.config.vaultAllocator.address
|
|
97503
98068
|
);
|
|
97504
|
-
console.log("params.amount", params.amount);
|
|
97505
98069
|
const quote = await this.getQuotesAvnu(
|
|
97506
98070
|
fromToken.address.toString(),
|
|
97507
98071
|
toToken.address.toString(),
|
|
@@ -97520,8 +98084,6 @@ spurious results.`);
|
|
|
97520
98084
|
);
|
|
97521
98085
|
const swapCallData = getCalldata[0];
|
|
97522
98086
|
const amount = uint256_exports.bnToUint256(params.amount.toWei());
|
|
97523
|
-
console.log("amount", amount);
|
|
97524
|
-
console.log("swapCallData", swapCallData);
|
|
97525
98087
|
return [
|
|
97526
98088
|
{
|
|
97527
98089
|
sanitizer: SIMPLE_SANITIZER,
|
|
@@ -97575,7 +98137,7 @@ spurious results.`);
|
|
|
97575
98137
|
}
|
|
97576
98138
|
throw new Error("Failed to fetch quote after retries");
|
|
97577
98139
|
}
|
|
97578
|
-
async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance =
|
|
98140
|
+
async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance = 5e3) {
|
|
97579
98141
|
try {
|
|
97580
98142
|
const fromToken = this.config.supportedPositions[0].asset;
|
|
97581
98143
|
const toToken = this.config.supportedPositions[1].asset;
|
|
@@ -97596,14 +98158,12 @@ spurious results.`);
|
|
|
97596
98158
|
return dataObject2;
|
|
97597
98159
|
}
|
|
97598
98160
|
const btcPrice = await this.getPriceOfToken(toToken.address.toString());
|
|
97599
|
-
console.log("btcPrice", btcPrice);
|
|
97600
98161
|
if (!btcPrice) {
|
|
97601
98162
|
logger2.error(`error getting btc price: ${btcPrice}`);
|
|
97602
98163
|
return null;
|
|
97603
98164
|
}
|
|
97604
98165
|
const estimatedUsdcAmount = Math.floor(amount * btcPrice);
|
|
97605
98166
|
const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
|
|
97606
|
-
console.log("targetBtcBig", targetBtcBig);
|
|
97607
98167
|
let low = BigInt(
|
|
97608
98168
|
Math.floor(
|
|
97609
98169
|
estimatedUsdcAmount * 10 ** fromToken.decimals * 0.9
|
|
@@ -97706,6 +98266,23 @@ spurious results.`);
|
|
|
97706
98266
|
debtPrice
|
|
97707
98267
|
};
|
|
97708
98268
|
}
|
|
98269
|
+
async getUnusedBalanceUSDCE() {
|
|
98270
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
98271
|
+
(token) => token.symbol === "USDCe"
|
|
98272
|
+
);
|
|
98273
|
+
const balance = await new ERC20(this.config).balanceOf(
|
|
98274
|
+
usdceToken.address,
|
|
98275
|
+
WALLET_ADDRESS,
|
|
98276
|
+
usdceToken.decimals
|
|
98277
|
+
);
|
|
98278
|
+
const price = await this.pricer.getPrice(usdceToken.symbol);
|
|
98279
|
+
const usdValue = Number(balance.toFixed(usdceToken.decimals)) * price.price;
|
|
98280
|
+
return {
|
|
98281
|
+
tokenInfo: usdceToken,
|
|
98282
|
+
amount: balance,
|
|
98283
|
+
usdValue
|
|
98284
|
+
};
|
|
98285
|
+
}
|
|
97709
98286
|
async getUnusedBalanceWBTC() {
|
|
97710
98287
|
const collateralToken = this.metadata.additionalInfo.borrowable_assets[0];
|
|
97711
98288
|
const balance = await new ERC20(this.config).balanceOf(
|
|
@@ -97751,22 +98328,30 @@ spurious results.`);
|
|
|
97751
98328
|
}
|
|
97752
98329
|
return extendedAdapter.adapter;
|
|
97753
98330
|
}
|
|
97754
|
-
async moveAssetsToVaultAllocator(amount) {
|
|
98331
|
+
async moveAssetsToVaultAllocator(amount, extendedAdapter) {
|
|
97755
98332
|
try {
|
|
97756
|
-
const
|
|
97757
|
-
(token) => token.symbol === "
|
|
98333
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
98334
|
+
(token) => token.symbol === "USDCe"
|
|
97758
98335
|
);
|
|
97759
98336
|
const approveCall = new ERC20(this.config).approve(
|
|
97760
|
-
|
|
98337
|
+
usdceToken.address,
|
|
97761
98338
|
this.metadata.additionalInfo.vaultAllocator,
|
|
97762
98339
|
amount
|
|
97763
98340
|
);
|
|
97764
98341
|
const transferCall = new ERC20(this.config).transfer(
|
|
97765
|
-
|
|
98342
|
+
usdceToken.address,
|
|
97766
98343
|
this.metadata.additionalInfo.vaultAllocator,
|
|
97767
98344
|
amount
|
|
97768
98345
|
);
|
|
97769
|
-
|
|
98346
|
+
const proofsInfo = extendedAdapter.getProofsForFromLegacySwap(
|
|
98347
|
+
this.getMerkleTree()
|
|
98348
|
+
);
|
|
98349
|
+
const proofGroups = proofsInfo.proofs;
|
|
98350
|
+
const call = this.getManageCall(
|
|
98351
|
+
proofGroups,
|
|
98352
|
+
await proofsInfo.callConstructor({ amount })
|
|
98353
|
+
);
|
|
98354
|
+
return [approveCall, transferCall, call];
|
|
97770
98355
|
} catch (err2) {
|
|
97771
98356
|
logger2.error(`error moving assets to vault allocator: ${err2}`);
|
|
97772
98357
|
return [];
|
|
@@ -97774,11 +98359,27 @@ spurious results.`);
|
|
|
97774
98359
|
}
|
|
97775
98360
|
async shouldInvest() {
|
|
97776
98361
|
try {
|
|
98362
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
|
|
97777
98363
|
const vesuAdapter = await this.getVesuAdapter();
|
|
97778
98364
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
97779
|
-
|
|
98365
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
|
|
98366
|
+
if (!vesuAdapter) {
|
|
97780
98367
|
logger2.error(
|
|
97781
|
-
`
|
|
98368
|
+
`Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
98369
|
+
);
|
|
98370
|
+
return {
|
|
98371
|
+
shouldInvest: false,
|
|
98372
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98373
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98374
|
+
extendedLeverage: 0,
|
|
98375
|
+
collateralPrice: 0,
|
|
98376
|
+
debtPrice: 0,
|
|
98377
|
+
vesuLeverage: 0
|
|
98378
|
+
};
|
|
98379
|
+
}
|
|
98380
|
+
if (!extendedAdapter) {
|
|
98381
|
+
logger2.error(
|
|
98382
|
+
`Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
97782
98383
|
);
|
|
97783
98384
|
return {
|
|
97784
98385
|
shouldInvest: false,
|
|
@@ -97790,10 +98391,73 @@ spurious results.`);
|
|
|
97790
98391
|
vesuLeverage: 0
|
|
97791
98392
|
};
|
|
97792
98393
|
}
|
|
98394
|
+
if (!extendedAdapter.client) {
|
|
98395
|
+
logger2.error(
|
|
98396
|
+
`Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
|
|
98397
|
+
);
|
|
98398
|
+
return {
|
|
98399
|
+
shouldInvest: false,
|
|
98400
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98401
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98402
|
+
extendedLeverage: 0,
|
|
98403
|
+
collateralPrice: 0,
|
|
98404
|
+
debtPrice: 0,
|
|
98405
|
+
vesuLeverage: 0
|
|
98406
|
+
};
|
|
98407
|
+
}
|
|
98408
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
|
|
97793
98409
|
const balance = await this.getUnusedBalance();
|
|
98410
|
+
if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
|
|
98411
|
+
logger2.error(
|
|
98412
|
+
`Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
|
|
98413
|
+
);
|
|
98414
|
+
return {
|
|
98415
|
+
shouldInvest: false,
|
|
98416
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98417
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98418
|
+
extendedLeverage: 0,
|
|
98419
|
+
collateralPrice: 0,
|
|
98420
|
+
debtPrice: 0,
|
|
98421
|
+
vesuLeverage: 0
|
|
98422
|
+
};
|
|
98423
|
+
}
|
|
98424
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
|
|
97794
98425
|
const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
|
|
97795
|
-
|
|
97796
|
-
|
|
98426
|
+
if (usdcBalanceOnExtended) {
|
|
98427
|
+
const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
|
|
98428
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
98429
|
+
logger2.error(
|
|
98430
|
+
`Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
98431
|
+
);
|
|
98432
|
+
return {
|
|
98433
|
+
shouldInvest: false,
|
|
98434
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98435
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98436
|
+
extendedLeverage: 0,
|
|
98437
|
+
collateralPrice: 0,
|
|
98438
|
+
debtPrice: 0,
|
|
98439
|
+
vesuLeverage: 0
|
|
98440
|
+
};
|
|
98441
|
+
}
|
|
98442
|
+
}
|
|
98443
|
+
const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
|
|
98444
|
+
const amountToInvestNumber = amountToInvest.toNumber();
|
|
98445
|
+
if (!Number.isFinite(amountToInvestNumber)) {
|
|
98446
|
+
logger2.error(
|
|
98447
|
+
`Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
|
|
98448
|
+
);
|
|
98449
|
+
return {
|
|
98450
|
+
shouldInvest: false,
|
|
98451
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98452
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98453
|
+
extendedLeverage: 0,
|
|
98454
|
+
collateralPrice: 0,
|
|
98455
|
+
debtPrice: 0,
|
|
98456
|
+
vesuLeverage: 0
|
|
98457
|
+
};
|
|
98458
|
+
}
|
|
98459
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
|
|
98460
|
+
if (amountToInvest.lessThan(LIMIT_BALANCE_VALUE)) {
|
|
97797
98461
|
return {
|
|
97798
98462
|
shouldInvest: false,
|
|
97799
98463
|
vesuAmount: new Web3Number(0, 0),
|
|
@@ -97822,6 +98486,34 @@ spurious results.`);
|
|
|
97822
98486
|
collateralPrice,
|
|
97823
98487
|
debtPrice
|
|
97824
98488
|
} = await this.getAssetPrices();
|
|
98489
|
+
if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
|
|
98490
|
+
logger2.error(
|
|
98491
|
+
`Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
|
|
98492
|
+
);
|
|
98493
|
+
return {
|
|
98494
|
+
shouldInvest: false,
|
|
98495
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98496
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98497
|
+
extendedLeverage: 0,
|
|
98498
|
+
collateralPrice: 0,
|
|
98499
|
+
debtPrice: 0,
|
|
98500
|
+
vesuLeverage: 0
|
|
98501
|
+
};
|
|
98502
|
+
}
|
|
98503
|
+
if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
|
|
98504
|
+
logger2.error(
|
|
98505
|
+
`Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
|
|
98506
|
+
);
|
|
98507
|
+
return {
|
|
98508
|
+
shouldInvest: false,
|
|
98509
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98510
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98511
|
+
extendedLeverage: 0,
|
|
98512
|
+
collateralPrice: 0,
|
|
98513
|
+
debtPrice: 0,
|
|
98514
|
+
vesuLeverage: 0
|
|
98515
|
+
};
|
|
98516
|
+
}
|
|
97825
98517
|
const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
|
|
97826
98518
|
amountToInvest.toNumber(),
|
|
97827
98519
|
extendedAdapter.client,
|
|
@@ -97845,6 +98537,7 @@ spurious results.`);
|
|
|
97845
98537
|
vesuLeverage: 0
|
|
97846
98538
|
};
|
|
97847
98539
|
}
|
|
98540
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`);
|
|
97848
98541
|
return {
|
|
97849
98542
|
shouldInvest: true,
|
|
97850
98543
|
vesuAmount: vesu_amount,
|
|
@@ -97871,18 +98564,48 @@ spurious results.`);
|
|
|
97871
98564
|
try {
|
|
97872
98565
|
const vesuAdapter = await this.getVesuAdapter();
|
|
97873
98566
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
97874
|
-
let calls = [];
|
|
97875
98567
|
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
|
|
97876
98568
|
logger2.error(
|
|
97877
98569
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
97878
98570
|
);
|
|
97879
|
-
return
|
|
98571
|
+
return [];
|
|
97880
98572
|
}
|
|
97881
|
-
|
|
97882
|
-
|
|
97883
|
-
|
|
98573
|
+
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
98574
|
+
if (!extendedHoldings) {
|
|
98575
|
+
logger2.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
98576
|
+
return [];
|
|
98577
|
+
}
|
|
98578
|
+
const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
|
|
98579
|
+
const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
|
|
98580
|
+
extendedHoldings.availableForWithdrawal
|
|
98581
|
+
);
|
|
98582
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
|
|
98583
|
+
let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
98584
|
+
let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
98585
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
98586
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
|
|
98587
|
+
}
|
|
98588
|
+
const extendedTargetAmount = extendedAmount.abs();
|
|
98589
|
+
let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
|
|
98590
|
+
if (extendedAmount.isNegative()) {
|
|
98591
|
+
projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
|
|
98592
|
+
}
|
|
98593
|
+
const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
|
|
98594
|
+
const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
|
|
98595
|
+
if (extendedAmountDifference.lessThan(0)) {
|
|
98596
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
|
|
98597
|
+
} else if (extendedAmountDifference.greaterThan(0)) {
|
|
98598
|
+
totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
|
|
98599
|
+
}
|
|
98600
|
+
const vesuTargetAmount = vesuAmount.abs();
|
|
98601
|
+
const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
|
|
98602
|
+
let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
|
|
98603
|
+
const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
|
|
98604
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculated movements - Extended withdrawal: ${totalExtendedWithdrawal.toNumber()}, Extended deposit: ${totalExtendedDeposit.toNumber()}, Extended diff: ${extendedAmountDifference.toNumber()}, Projected wallet: ${projectedWalletBalance.toNumber()}, Vesu diff: ${vesuAmountDifference.toNumber()}`);
|
|
98605
|
+
let calls = [];
|
|
98606
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
97884
98607
|
try {
|
|
97885
|
-
const extendedCalls = await this.moveAssets(
|
|
98608
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
97886
98609
|
{
|
|
97887
98610
|
to: Protocols.VAULT.name,
|
|
97888
98611
|
from: Protocols.EXTENDED.name,
|
|
@@ -97891,14 +98614,18 @@ spurious results.`);
|
|
|
97891
98614
|
extendedAdapter,
|
|
97892
98615
|
vesuAdapter
|
|
97893
98616
|
);
|
|
97894
|
-
|
|
98617
|
+
if (extendedStatus) {
|
|
98618
|
+
calls.push(...extendedCalls);
|
|
98619
|
+
} else {
|
|
98620
|
+
return [];
|
|
98621
|
+
}
|
|
97895
98622
|
} catch (err2) {
|
|
97896
98623
|
logger2.error(`Failed moving assets to vault: ${err2}`);
|
|
97897
98624
|
}
|
|
97898
98625
|
}
|
|
97899
|
-
if (vesuAmount.
|
|
98626
|
+
if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
97900
98627
|
try {
|
|
97901
|
-
const vesuCalls = await this.moveAssets(
|
|
98628
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
97902
98629
|
{
|
|
97903
98630
|
to: Protocols.EXTENDED.name,
|
|
97904
98631
|
from: Protocols.VESU.name,
|
|
@@ -97908,49 +98635,83 @@ spurious results.`);
|
|
|
97908
98635
|
vesuAdapter
|
|
97909
98636
|
);
|
|
97910
98637
|
calls.push(...vesuCalls);
|
|
98638
|
+
if (!vesuStatus) {
|
|
98639
|
+
return [];
|
|
98640
|
+
}
|
|
97911
98641
|
} catch (err2) {
|
|
97912
98642
|
logger2.error(`Failed moving assets to vault: ${err2}`);
|
|
97913
98643
|
}
|
|
97914
98644
|
}
|
|
97915
|
-
|
|
97916
|
-
|
|
97917
|
-
|
|
97918
|
-
|
|
97919
|
-
|
|
97920
|
-
|
|
97921
|
-
|
|
97922
|
-
|
|
97923
|
-
|
|
97924
|
-
|
|
97925
|
-
|
|
97926
|
-
|
|
97927
|
-
{
|
|
97928
|
-
|
|
97929
|
-
|
|
97930
|
-
|
|
97931
|
-
|
|
97932
|
-
|
|
97933
|
-
|
|
97934
|
-
|
|
97935
|
-
|
|
97936
|
-
|
|
97937
|
-
|
|
98645
|
+
if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
98646
|
+
if (extendedAmountDifference.greaterThan(0)) {
|
|
98647
|
+
try {
|
|
98648
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
98649
|
+
{
|
|
98650
|
+
to: Protocols.EXTENDED.name,
|
|
98651
|
+
from: Protocols.VAULT.name,
|
|
98652
|
+
amount: extendedAmountDifference
|
|
98653
|
+
},
|
|
98654
|
+
extendedAdapter,
|
|
98655
|
+
vesuAdapter
|
|
98656
|
+
);
|
|
98657
|
+
if (extendedStatus) {
|
|
98658
|
+
calls.push(...extendedCalls);
|
|
98659
|
+
} else {
|
|
98660
|
+
logger2.error(`Failed to move assets to extended - operation returned false status`);
|
|
98661
|
+
return [];
|
|
98662
|
+
}
|
|
98663
|
+
} catch (err2) {
|
|
98664
|
+
logger2.error(`Failed moving assets to extended: ${err2}`);
|
|
98665
|
+
return [];
|
|
98666
|
+
}
|
|
98667
|
+
} else if (extendedAmountDifference.lessThan(0)) {
|
|
98668
|
+
try {
|
|
98669
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
98670
|
+
{
|
|
98671
|
+
to: Protocols.VAULT.name,
|
|
98672
|
+
from: Protocols.EXTENDED.name,
|
|
98673
|
+
amount: extendedAmountDifferenceAbs
|
|
98674
|
+
},
|
|
98675
|
+
extendedAdapter,
|
|
98676
|
+
vesuAdapter
|
|
98677
|
+
);
|
|
98678
|
+
if (extendedStatus) {
|
|
98679
|
+
calls.push(...extendedCalls);
|
|
98680
|
+
} else {
|
|
98681
|
+
logger2.error(`Failed to withdraw from extended - operation returned false status`);
|
|
98682
|
+
return [];
|
|
98683
|
+
}
|
|
98684
|
+
} catch (err2) {
|
|
98685
|
+
logger2.error(`Failed moving assets from extended to vault: ${err2}`);
|
|
98686
|
+
return [];
|
|
98687
|
+
}
|
|
97938
98688
|
}
|
|
97939
98689
|
}
|
|
97940
|
-
if (
|
|
97941
|
-
|
|
97942
|
-
|
|
97943
|
-
{
|
|
97944
|
-
to: Protocols.VESU.name,
|
|
97945
|
-
from: Protocols.EXTENDED.name,
|
|
97946
|
-
amount: vesuAmount.minus(usdcAmountInWallet)
|
|
97947
|
-
},
|
|
97948
|
-
extendedAdapter,
|
|
97949
|
-
vesuAdapter
|
|
98690
|
+
if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
98691
|
+
if (vesuAmountDifference.lessThanOrEqualTo(0)) {
|
|
98692
|
+
logger2.warn(
|
|
98693
|
+
`Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
|
|
97950
98694
|
);
|
|
97951
|
-
|
|
97952
|
-
|
|
97953
|
-
|
|
98695
|
+
} else {
|
|
98696
|
+
try {
|
|
98697
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
98698
|
+
{
|
|
98699
|
+
to: Protocols.VAULT.name,
|
|
98700
|
+
from: Protocols.EXTENDED.name,
|
|
98701
|
+
amount: vesuAmountDifference
|
|
98702
|
+
},
|
|
98703
|
+
extendedAdapter,
|
|
98704
|
+
vesuAdapter
|
|
98705
|
+
);
|
|
98706
|
+
if (!vesuStatus) {
|
|
98707
|
+
logger2.error(`Failed to move assets to vesu - operation returned false status`);
|
|
98708
|
+
return [];
|
|
98709
|
+
}
|
|
98710
|
+
calls.push(...vesuCalls);
|
|
98711
|
+
} catch (err2) {
|
|
98712
|
+
logger2.error(`Failed moving assets to vault: ${err2}`);
|
|
98713
|
+
return [];
|
|
98714
|
+
}
|
|
97954
98715
|
}
|
|
97955
98716
|
}
|
|
97956
98717
|
return calls;
|
|
@@ -97961,12 +98722,47 @@ spurious results.`);
|
|
|
97961
98722
|
}
|
|
97962
98723
|
async moveAssets(params, extendedAdapter, vesuAdapter) {
|
|
97963
98724
|
try {
|
|
98725
|
+
if (params.amount.lessThanOrEqualTo(0)) {
|
|
98726
|
+
logger2.error(
|
|
98727
|
+
`Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
|
|
98728
|
+
);
|
|
98729
|
+
return {
|
|
98730
|
+
calls: [],
|
|
98731
|
+
status: false
|
|
98732
|
+
};
|
|
98733
|
+
}
|
|
98734
|
+
const amountAbs = params.amount.abs();
|
|
98735
|
+
if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
|
|
98736
|
+
if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
98737
|
+
logger2.warn(
|
|
98738
|
+
`Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
|
|
98739
|
+
);
|
|
98740
|
+
return {
|
|
98741
|
+
calls: [],
|
|
98742
|
+
status: false
|
|
98743
|
+
};
|
|
98744
|
+
}
|
|
98745
|
+
}
|
|
98746
|
+
if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
|
|
98747
|
+
if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
|
|
98748
|
+
logger2.warn(
|
|
98749
|
+
`Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
|
|
98750
|
+
);
|
|
98751
|
+
return {
|
|
98752
|
+
calls: [],
|
|
98753
|
+
status: false
|
|
98754
|
+
};
|
|
98755
|
+
}
|
|
98756
|
+
}
|
|
97964
98757
|
const avnuAdapter = await this.getAvnuAdapter();
|
|
97965
98758
|
if (!avnuAdapter) {
|
|
97966
98759
|
logger2.error(`avnu adapter not found: ${avnuAdapter}`);
|
|
97967
|
-
return
|
|
98760
|
+
return {
|
|
98761
|
+
calls: [],
|
|
98762
|
+
status: false
|
|
98763
|
+
};
|
|
97968
98764
|
}
|
|
97969
|
-
logger2.info(
|
|
98765
|
+
logger2.info(`moveAssets params, ${JSON.stringify(params)}`);
|
|
97970
98766
|
const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
|
|
97971
98767
|
const {
|
|
97972
98768
|
collateralPrice
|
|
@@ -97983,19 +98779,76 @@ spurious results.`);
|
|
|
97983
98779
|
await proofsInfo.callConstructor({ amount: params.amount })
|
|
97984
98780
|
);
|
|
97985
98781
|
calls.push(call);
|
|
97986
|
-
return
|
|
98782
|
+
return {
|
|
98783
|
+
calls: [call],
|
|
98784
|
+
status: true
|
|
98785
|
+
};
|
|
97987
98786
|
} else if (params.to === Protocols.VAULT.name && params.from === Protocols.EXTENDED.name) {
|
|
98787
|
+
const extendedLeverage = calculateExtendedLevergae();
|
|
98788
|
+
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
98789
|
+
if (!extendedHoldings) {
|
|
98790
|
+
logger2.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
98791
|
+
return {
|
|
98792
|
+
calls: [],
|
|
98793
|
+
status: false
|
|
98794
|
+
};
|
|
98795
|
+
}
|
|
98796
|
+
const extendedHoldingAmount = new Web3Number(
|
|
98797
|
+
extendedHoldings.availableForWithdrawal,
|
|
98798
|
+
USDC_TOKEN_DECIMALS
|
|
98799
|
+
);
|
|
98800
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets extendedHoldingAmount: ${extendedHoldingAmount.toNumber()}`);
|
|
98801
|
+
if (params.amount.abs().greaterThan(extendedHoldingAmount)) {
|
|
98802
|
+
const leftAmountAfterWithdrawalAmountInAccount = params.amount.abs().minus(extendedHoldingAmount);
|
|
98803
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets leftAmountAfterWithdrawalAmountInAccount: ${leftAmountAfterWithdrawalAmountInAccount.toNumber()}`);
|
|
98804
|
+
const btcAmount = leftAmountAfterWithdrawalAmountInAccount.dividedBy(collateralPrice.price);
|
|
98805
|
+
const openLongPosition = btcAmount.multipliedBy(3).greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
|
|
98806
|
+
extendedLeverage.toString(),
|
|
98807
|
+
btcAmount.toNumber(),
|
|
98808
|
+
"BUY" /* BUY */
|
|
98809
|
+
) : await extendedAdapter.createOrder(
|
|
98810
|
+
extendedLeverage.toString(),
|
|
98811
|
+
35e-6,
|
|
98812
|
+
// just in case amount falls short then we need to create a withdrawal
|
|
98813
|
+
"BUY" /* BUY */
|
|
98814
|
+
);
|
|
98815
|
+
if (!openLongPosition) {
|
|
98816
|
+
logger2.error(`error opening long position: ${openLongPosition}`);
|
|
98817
|
+
}
|
|
98818
|
+
const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
98819
|
+
if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
|
|
98820
|
+
logger2.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
|
|
98821
|
+
return { calls: [], status: false };
|
|
98822
|
+
}
|
|
98823
|
+
}
|
|
97988
98824
|
const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
|
|
97989
98825
|
if (withdrawalFromExtended) {
|
|
97990
|
-
const
|
|
98826
|
+
const extendedHoldings2 = await extendedAdapter.getExtendedDepositAmount();
|
|
98827
|
+
logger2.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
|
|
98828
|
+
await new Promise((resolve) => setTimeout(resolve, 5e3));
|
|
98829
|
+
const calls = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
|
|
97991
98830
|
if (calls.length > 0) {
|
|
97992
|
-
return
|
|
98831
|
+
return {
|
|
98832
|
+
calls,
|
|
98833
|
+
status: true
|
|
98834
|
+
};
|
|
97993
98835
|
}
|
|
97994
98836
|
} else {
|
|
97995
98837
|
logger2.error("withdrawal from extended failed");
|
|
98838
|
+
return {
|
|
98839
|
+
calls: [],
|
|
98840
|
+
status: false
|
|
98841
|
+
};
|
|
97996
98842
|
}
|
|
97997
|
-
return [];
|
|
97998
98843
|
} else if (params.to === Protocols.VAULT.name && params.from === Protocols.VESU.name) {
|
|
98844
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
|
|
98845
|
+
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
98846
|
+
logger2.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
98847
|
+
return {
|
|
98848
|
+
calls: [],
|
|
98849
|
+
status: false
|
|
98850
|
+
};
|
|
98851
|
+
}
|
|
97999
98852
|
const vesuAmountInBTC = new Web3Number(
|
|
98000
98853
|
params.amount.dividedBy(collateralPrice.price).toNumber(),
|
|
98001
98854
|
collateralToken.decimals
|
|
@@ -98015,8 +98868,19 @@ spurious results.`);
|
|
|
98015
98868
|
await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
|
|
98016
98869
|
);
|
|
98017
98870
|
calls.push(swapCall);
|
|
98018
|
-
return
|
|
98871
|
+
return {
|
|
98872
|
+
calls,
|
|
98873
|
+
status: true
|
|
98874
|
+
};
|
|
98019
98875
|
} else if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VESU.name) {
|
|
98876
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
|
|
98877
|
+
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
98878
|
+
logger2.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
98879
|
+
return {
|
|
98880
|
+
calls: [],
|
|
98881
|
+
status: false
|
|
98882
|
+
};
|
|
98883
|
+
}
|
|
98020
98884
|
const vesuAmountInBTC = new Web3Number(
|
|
98021
98885
|
params.amount.dividedBy(collateralPrice.price).toNumber(),
|
|
98022
98886
|
collateralToken.decimals
|
|
@@ -98046,13 +98910,21 @@ spurious results.`);
|
|
|
98046
98910
|
await proofsInfoDeposit.callConstructor({ amount: params.amount })
|
|
98047
98911
|
);
|
|
98048
98912
|
calls.push(callDeposit);
|
|
98049
|
-
return
|
|
98913
|
+
return {
|
|
98914
|
+
calls,
|
|
98915
|
+
status: true
|
|
98916
|
+
};
|
|
98050
98917
|
}
|
|
98051
|
-
|
|
98052
|
-
|
|
98918
|
+
return {
|
|
98919
|
+
calls: [],
|
|
98920
|
+
status: false
|
|
98921
|
+
};
|
|
98053
98922
|
} catch (err2) {
|
|
98054
98923
|
logger2.error(`error moving assets: ${err2}`);
|
|
98055
|
-
return
|
|
98924
|
+
return {
|
|
98925
|
+
calls: [],
|
|
98926
|
+
status: false
|
|
98927
|
+
};
|
|
98056
98928
|
}
|
|
98057
98929
|
}
|
|
98058
98930
|
async handleDeposit() {
|
|
@@ -98072,7 +98944,7 @@ spurious results.`);
|
|
|
98072
98944
|
};
|
|
98073
98945
|
}
|
|
98074
98946
|
const extendedLeverage = calculateExtendedLevergae();
|
|
98075
|
-
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter);
|
|
98947
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "open" /* OPEN */);
|
|
98076
98948
|
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
98077
98949
|
logger2.error("price difference between avnu and extended doesn't fit the range");
|
|
98078
98950
|
return {
|
|
@@ -98089,6 +98961,7 @@ spurious results.`);
|
|
|
98089
98961
|
};
|
|
98090
98962
|
}
|
|
98091
98963
|
const extendedPositionValue = position.length > 0 ? parseFloat(position[0].value) : 0;
|
|
98964
|
+
const BUFFER_AMOUNT_IN_AVAILABLE_FOR_TRADE = BUFFER_USDC_IN_WITHDRAWAL;
|
|
98092
98965
|
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
98093
98966
|
if (!extendedHoldings) {
|
|
98094
98967
|
logger2.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
@@ -98107,12 +98980,11 @@ spurious results.`);
|
|
|
98107
98980
|
const { collateralPrice } = await this.getAssetPrices();
|
|
98108
98981
|
const { vesuAmountInBTC, extendedAmountInBTC } = calculateVesUPositionSizeGivenExtended(
|
|
98109
98982
|
extendedPositionValue,
|
|
98110
|
-
extendedHoldingAmount,
|
|
98983
|
+
extendedHoldingAmount.minus(BUFFER_AMOUNT_IN_AVAILABLE_FOR_TRADE),
|
|
98111
98984
|
collateralTokenAmount,
|
|
98112
98985
|
collateralPrice.price
|
|
98113
98986
|
);
|
|
98114
|
-
|
|
98115
|
-
console.log("extendedAmountInBTC", extendedAmountInBTC);
|
|
98987
|
+
logger2.info(`vesuAmountInBTC ${vesuAmountInBTC}, extendedAmountInBTC ${extendedAmountInBTC}`);
|
|
98116
98988
|
let calls = [];
|
|
98117
98989
|
if (vesuAmountInBTC.greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)) {
|
|
98118
98990
|
const proofsInfo = vesuAdapter.getProofs(true, this.getMerkleTree());
|
|
@@ -98125,7 +98997,6 @@ spurious results.`);
|
|
|
98125
98997
|
);
|
|
98126
98998
|
const { amount: wbtcAmountInVaultAllocator } = await this.getUnusedBalanceWBTC();
|
|
98127
98999
|
if (wbtcAmountInVaultAllocator.lessThan(vesuAmountInBTC)) {
|
|
98128
|
-
console.log("error wbtc amount in vault allocator is less than vesu amount in btc", wbtcAmountInVaultAllocator, vesuAmountInBTC);
|
|
98129
99000
|
const swapProofsInfo = avnuAdapter.getProofs(true, this.getMerkleTree());
|
|
98130
99001
|
const swapProofGroups = swapProofsInfo.proofs;
|
|
98131
99002
|
const swapCall = this.getManageCall(
|
|
@@ -98160,68 +99031,98 @@ spurious results.`);
|
|
|
98160
99031
|
extendedAmountInBTC: new Web3Number(0, 0),
|
|
98161
99032
|
calls: []
|
|
98162
99033
|
};
|
|
98163
|
-
;
|
|
98164
99034
|
}
|
|
98165
99035
|
}
|
|
98166
|
-
async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter) {
|
|
99036
|
+
async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, positionType) {
|
|
98167
99037
|
const {
|
|
98168
99038
|
ask,
|
|
98169
99039
|
bid
|
|
98170
99040
|
} = await extendedAdapter.fetchOrderBookBTCUSDC();
|
|
98171
99041
|
const price = ask.plus(bid).dividedBy(2);
|
|
98172
|
-
const btcToken = vesuAdapter.config.supportedPositions[
|
|
99042
|
+
const btcToken = vesuAdapter.config.supportedPositions[0].asset;
|
|
98173
99043
|
const btcPriceAvnu = await avnuAdapter.getPriceOfToken(btcToken.address.toString());
|
|
98174
99044
|
if (!btcPriceAvnu) {
|
|
98175
99045
|
logger2.error(`error getting btc price avnu: ${btcPriceAvnu}`);
|
|
98176
99046
|
return false;
|
|
98177
99047
|
}
|
|
98178
|
-
const priceDifference = price.minus(btcPriceAvnu).
|
|
98179
|
-
if (priceDifference
|
|
98180
|
-
return
|
|
99048
|
+
const priceDifference = new Web3Number(price.minus(btcPriceAvnu).toFixed(2), 0);
|
|
99049
|
+
if (priceDifference.isNegative()) {
|
|
99050
|
+
return false;
|
|
99051
|
+
}
|
|
99052
|
+
if (positionType === "open" /* OPEN */) {
|
|
99053
|
+
logger2.info(`price difference between avnu and extended for open position: ${priceDifference.toNumber()}, minimumExtendedPriceDifferenceForSwapOpen: ${avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen}`);
|
|
99054
|
+
const result2 = priceDifference.greaterThanOrEqualTo(avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen);
|
|
99055
|
+
logger2.info(`result: ${result2}`);
|
|
99056
|
+
return result2;
|
|
99057
|
+
} else {
|
|
99058
|
+
logger2.info(`price difference between avnu and extended for close position: ${priceDifference.toNumber()}, maximumExtendedPriceDifferenceForSwapClosing: ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
99059
|
+
const result2 = priceDifference.lessThanOrEqualTo(avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing);
|
|
99060
|
+
logger2.info(`result: ${result2}`);
|
|
99061
|
+
return result2;
|
|
98181
99062
|
}
|
|
98182
|
-
logger2.error(`price difference between avnu and extended doesn't fit the range, priceDifference: ${priceDifference}`);
|
|
98183
|
-
return false;
|
|
98184
99063
|
}
|
|
98185
99064
|
async handleWithdraw(amount) {
|
|
98186
99065
|
try {
|
|
98187
99066
|
const usdcBalanceVaultAllocator = await this.getUnusedBalance();
|
|
98188
|
-
const usdcBalanceDifference = amount.minus(usdcBalanceVaultAllocator.usdValue);
|
|
99067
|
+
const usdcBalanceDifference = amount.plus(BUFFER_USDC_IN_WITHDRAWAL).minus(usdcBalanceVaultAllocator.usdValue);
|
|
98189
99068
|
logger2.info(`usdcBalanceDifference, ${usdcBalanceDifference.toNumber()}`);
|
|
99069
|
+
let calls = [];
|
|
99070
|
+
let status = true;
|
|
98190
99071
|
if (usdcBalanceDifference.lessThan(0)) {
|
|
98191
|
-
const
|
|
98192
|
-
amount
|
|
99072
|
+
const withdrawCall2 = await this.getBringLiquidityCall({
|
|
99073
|
+
amount: usdcBalanceVaultAllocator.amount
|
|
98193
99074
|
});
|
|
98194
|
-
logger2.info("withdraw call",
|
|
98195
|
-
|
|
99075
|
+
logger2.info("withdraw call", withdrawCall2);
|
|
99076
|
+
calls.push(withdrawCall2);
|
|
99077
|
+
return {
|
|
99078
|
+
calls,
|
|
99079
|
+
status: true
|
|
99080
|
+
};
|
|
98196
99081
|
}
|
|
98197
99082
|
const vesuAdapter = await this.getVesuAdapter();
|
|
98198
99083
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
98199
99084
|
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
|
|
99085
|
+
status = false;
|
|
98200
99086
|
logger2.error(
|
|
98201
99087
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
98202
99088
|
);
|
|
98203
|
-
return
|
|
99089
|
+
return {
|
|
99090
|
+
calls,
|
|
99091
|
+
status
|
|
99092
|
+
};
|
|
98204
99093
|
}
|
|
98205
99094
|
const { collateralTokenAmount } = await vesuAdapter.vesuAdapter.getAssetPrices();
|
|
98206
99095
|
const {
|
|
98207
99096
|
collateralPrice
|
|
98208
99097
|
} = await this.getAssetPrices();
|
|
98209
99098
|
const extendedPositon = await extendedAdapter.getAllOpenPositions();
|
|
99099
|
+
if (!extendedPositon) {
|
|
99100
|
+
status = false;
|
|
99101
|
+
logger2.error("error getting extended position", extendedPositon);
|
|
99102
|
+
return {
|
|
99103
|
+
calls,
|
|
99104
|
+
status
|
|
99105
|
+
};
|
|
99106
|
+
}
|
|
98210
99107
|
const amountDistributionForWithdrawal = await calculateAmountDistributionForWithdrawal(
|
|
98211
|
-
|
|
99108
|
+
usdcBalanceDifference,
|
|
98212
99109
|
collateralPrice.price,
|
|
98213
99110
|
collateralTokenAmount,
|
|
98214
99111
|
extendedPositon
|
|
98215
99112
|
);
|
|
98216
99113
|
if (!amountDistributionForWithdrawal) {
|
|
99114
|
+
status = false;
|
|
98217
99115
|
logger2.error(
|
|
98218
99116
|
`error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
|
|
98219
99117
|
);
|
|
98220
|
-
return
|
|
99118
|
+
return {
|
|
99119
|
+
calls,
|
|
99120
|
+
status
|
|
99121
|
+
};
|
|
98221
99122
|
}
|
|
98222
99123
|
const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
|
|
98223
|
-
if (vesu_amount.greaterThan(0)) {
|
|
98224
|
-
const
|
|
99124
|
+
if (status && vesu_amount.greaterThan(0)) {
|
|
99125
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
98225
99126
|
{
|
|
98226
99127
|
amount: vesu_amount,
|
|
98227
99128
|
from: Protocols.VESU.name,
|
|
@@ -98230,10 +99131,11 @@ spurious results.`);
|
|
|
98230
99131
|
extendedAdapter,
|
|
98231
99132
|
vesuAdapter
|
|
98232
99133
|
);
|
|
98233
|
-
|
|
99134
|
+
status = vesuStatus;
|
|
99135
|
+
calls.push(...vesuCalls);
|
|
98234
99136
|
}
|
|
98235
|
-
if (extended_amount.greaterThan(0)) {
|
|
98236
|
-
const
|
|
99137
|
+
if (status && extended_amount.greaterThan(0)) {
|
|
99138
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
98237
99139
|
{
|
|
98238
99140
|
amount: extended_amount,
|
|
98239
99141
|
from: Protocols.EXTENDED.name,
|
|
@@ -98242,12 +99144,32 @@ spurious results.`);
|
|
|
98242
99144
|
extendedAdapter,
|
|
98243
99145
|
vesuAdapter
|
|
98244
99146
|
);
|
|
98245
|
-
|
|
99147
|
+
status = extendedStatus;
|
|
99148
|
+
if (status) {
|
|
99149
|
+
calls.push(...extendedCalls);
|
|
99150
|
+
} else {
|
|
99151
|
+
logger2.error("error moving assets to vault: extendedStatus: ${extendedStatus}");
|
|
99152
|
+
return {
|
|
99153
|
+
calls: [],
|
|
99154
|
+
status
|
|
99155
|
+
};
|
|
99156
|
+
}
|
|
98246
99157
|
}
|
|
98247
|
-
|
|
99158
|
+
const withdrawCall = await this.getBringLiquidityCall({
|
|
99159
|
+
amount
|
|
99160
|
+
});
|
|
99161
|
+
logger2.info("withdraw call", withdrawCall);
|
|
99162
|
+
calls.push(withdrawCall);
|
|
99163
|
+
return {
|
|
99164
|
+
calls,
|
|
99165
|
+
status
|
|
99166
|
+
};
|
|
98248
99167
|
} catch (err2) {
|
|
98249
99168
|
logger2.error(`error handling withdrawal: ${err2}`);
|
|
98250
|
-
return
|
|
99169
|
+
return {
|
|
99170
|
+
calls: [],
|
|
99171
|
+
status: false
|
|
99172
|
+
};
|
|
98251
99173
|
}
|
|
98252
99174
|
}
|
|
98253
99175
|
async getAUM() {
|
|
@@ -98295,7 +99217,7 @@ spurious results.`);
|
|
|
98295
99217
|
};
|
|
98296
99218
|
}
|
|
98297
99219
|
};
|
|
98298
|
-
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
|
|
99220
|
+
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
|
|
98299
99221
|
vaultSettings.leafAdapters = [];
|
|
98300
99222
|
const wbtcToken = Global.getDefaultTokens().find(
|
|
98301
99223
|
(token) => token.symbol === lstSymbol
|
|
@@ -98319,7 +99241,9 @@ spurious results.`);
|
|
|
98319
99241
|
...baseAdapterConfig,
|
|
98320
99242
|
avnuContract: AVNU_MIDDLEWARE,
|
|
98321
99243
|
slippage: 0.01,
|
|
98322
|
-
baseUrl: AVNU_QUOTE_URL
|
|
99244
|
+
baseUrl: AVNU_QUOTE_URL,
|
|
99245
|
+
minimumExtendedPriceDifferenceForSwapOpen,
|
|
99246
|
+
maximumExtendedPriceDifferenceForSwapClosing
|
|
98323
99247
|
});
|
|
98324
99248
|
const extendedAdapter = new ExtendedAdapter({
|
|
98325
99249
|
...baseAdapterConfig,
|
|
@@ -98335,7 +99259,10 @@ spurious results.`);
|
|
|
98335
99259
|
extendedBaseUrl: "https://api.starknet.extended.exchange",
|
|
98336
99260
|
extendedMarketName: "BTC-USD",
|
|
98337
99261
|
extendedPrecision: 5,
|
|
98338
|
-
avnuAdapter
|
|
99262
|
+
avnuAdapter,
|
|
99263
|
+
retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3e3,
|
|
99264
|
+
minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5
|
|
99265
|
+
//5 usdcs
|
|
98339
99266
|
});
|
|
98340
99267
|
const vesuMultiplyAdapter = new VesuMultiplyAdapter({
|
|
98341
99268
|
poolId: pool1,
|
|
@@ -98348,7 +99275,9 @@ spurious results.`);
|
|
|
98348
99275
|
supportedPositions: [
|
|
98349
99276
|
{ asset: wbtcToken, isDebt: false },
|
|
98350
99277
|
{ asset: usdcToken, isDebt: true }
|
|
98351
|
-
]
|
|
99278
|
+
],
|
|
99279
|
+
minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5
|
|
99280
|
+
//5 usdc
|
|
98352
99281
|
});
|
|
98353
99282
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
98354
99283
|
...baseAdapterConfig
|
|
@@ -98381,6 +99310,7 @@ spurious results.`);
|
|
|
98381
99310
|
() => vesuMultiplyAdapter.getWithdrawLeaf()
|
|
98382
99311
|
);
|
|
98383
99312
|
vaultSettings.leafAdapters.push(() => extendedAdapter.getDepositLeaf());
|
|
99313
|
+
vaultSettings.leafAdapters.push(() => extendedAdapter.getSwapFromLegacyLeaf());
|
|
98384
99314
|
vaultSettings.leafAdapters.push(() => avnuAdapter.getDepositLeaf());
|
|
98385
99315
|
vaultSettings.leafAdapters.push(() => avnuAdapter.getWithdrawLeaf());
|
|
98386
99316
|
vaultSettings.leafAdapters.push(
|
|
@@ -98462,12 +99392,12 @@ spurious results.`);
|
|
|
98462
99392
|
borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
|
|
98463
99393
|
minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP
|
|
98464
99394
|
};
|
|
98465
|
-
var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended) => {
|
|
99395
|
+
var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) => {
|
|
98466
99396
|
return [
|
|
98467
|
-
getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended)
|
|
99397
|
+
getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing)
|
|
98468
99398
|
];
|
|
98469
99399
|
};
|
|
98470
|
-
function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
|
|
99400
|
+
function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
|
|
98471
99401
|
return {
|
|
98472
99402
|
name: `Extended Test ${underlyingSymbol}`,
|
|
98473
99403
|
description: getDescription2(lstSymbol, underlyingSymbol),
|
|
@@ -98475,7 +99405,7 @@ spurious results.`);
|
|
|
98475
99405
|
launchBlock: 0,
|
|
98476
99406
|
type: "Other",
|
|
98477
99407
|
depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol)],
|
|
98478
|
-
additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended),
|
|
99408
|
+
additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing),
|
|
98479
99409
|
risk: {
|
|
98480
99410
|
riskFactor: _riskFactor3,
|
|
98481
99411
|
netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
|