@strkfarm/sdk 2.0.0-dev.1 → 2.0.0-dev.11
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 +1338 -391
- package/dist/index.browser.mjs +1338 -391
- package/dist/index.d.ts +53 -12
- package/dist/index.js +1339 -391
- package/dist/index.mjs +1338 -391
- package/package.json +1 -1
- package/src/dataTypes/address.ts +1 -1
- package/src/modules/ExtendedWrapperSDk/types.ts +1 -1
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +32 -5
- 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 +539 -122
|
@@ -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) {
|
|
@@ -56258,7 +56248,22 @@ ${JSON.stringify(data, null, 2)}`;
|
|
|
56258
56248
|
`HTTP ${response.status}: ${errorData.detail || response.statusText}`
|
|
56259
56249
|
);
|
|
56260
56250
|
}
|
|
56261
|
-
const
|
|
56251
|
+
const text = await response.text();
|
|
56252
|
+
const MAX_SAFE_INTEGER_STR = "9007199254740991";
|
|
56253
|
+
const largeIntegerRegex = /"data"\s*:\s*(\d{16,})/g;
|
|
56254
|
+
const modifiedText = text.replace(largeIntegerRegex, (match, largeInt) => {
|
|
56255
|
+
if (largeInt.length > MAX_SAFE_INTEGER_STR.length || largeInt.length === MAX_SAFE_INTEGER_STR.length && largeInt > MAX_SAFE_INTEGER_STR) {
|
|
56256
|
+
return `"data":"${largeInt}"`;
|
|
56257
|
+
}
|
|
56258
|
+
return match;
|
|
56259
|
+
});
|
|
56260
|
+
const data = JSON.parse(modifiedText);
|
|
56261
|
+
if (data && typeof data.data === "string" && /^\d+$/.test(data.data)) {
|
|
56262
|
+
const numValue = Number(data.data);
|
|
56263
|
+
if (Number.isSafeInteger(numValue)) {
|
|
56264
|
+
data.data = numValue;
|
|
56265
|
+
}
|
|
56266
|
+
}
|
|
56262
56267
|
return data;
|
|
56263
56268
|
} catch (error2) {
|
|
56264
56269
|
lastError = error2;
|
|
@@ -56318,6 +56323,7 @@ ${JSON.stringify(data, null, 2)}`;
|
|
|
56318
56323
|
}
|
|
56319
56324
|
/**
|
|
56320
56325
|
* Initiate a withdrawal from Extended Exchange
|
|
56326
|
+
* Returns data as number | string to preserve precision for large integers
|
|
56321
56327
|
*/
|
|
56322
56328
|
async withdraw(request) {
|
|
56323
56329
|
return this.makeRequest("/api/v1/withdraw", {
|
|
@@ -56456,6 +56462,7 @@ ${JSON.stringify(data, null, 2)}`;
|
|
|
56456
56462
|
}
|
|
56457
56463
|
/**
|
|
56458
56464
|
* Withdraw USDC (convenience method)
|
|
56465
|
+
* Returns data as number | string to preserve precision for large integers
|
|
56459
56466
|
*/
|
|
56460
56467
|
async withdrawUSDC(amount) {
|
|
56461
56468
|
return this.withdraw({ amount, asset: "USDC" });
|
|
@@ -92375,6 +92382,7 @@ spurious results.`);
|
|
|
92375
92382
|
var AVNU_API = "https://starknet.api.avnu.fi/swap/v2/quotes";
|
|
92376
92383
|
var USDC_TOKEN_DECIMALS = 6;
|
|
92377
92384
|
var USDC_TOKEN_ADDRESS = "0x053C91253BC9682c04929cA02ED00b3E423f6710D2ee7e0D5EBB06F3eCF368A8";
|
|
92385
|
+
var BUFFER_USDC_IN_WITHDRAWAL = 5;
|
|
92378
92386
|
var WBTC_TOKEN_ADDRESS = "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac";
|
|
92379
92387
|
var WBTC_TOKEN_DECIMALS = 8;
|
|
92380
92388
|
var MAINTENANCE_MARGIN = 0.01;
|
|
@@ -92390,7 +92398,8 @@ spurious results.`);
|
|
|
92390
92398
|
var MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
|
|
92391
92399
|
var MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
|
|
92392
92400
|
var EXTEND_MARKET_NAME = "BTC-USD";
|
|
92393
|
-
var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ??
|
|
92401
|
+
var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 0.05);
|
|
92402
|
+
var LIMIT_BALANCE_VALUE = 10;
|
|
92394
92403
|
var REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 18e4);
|
|
92395
92404
|
var WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18e6);
|
|
92396
92405
|
var INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 18e4);
|
|
@@ -92408,8 +92417,6 @@ spurious results.`);
|
|
|
92408
92417
|
var MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING = Number(process.env.MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING ?? 1);
|
|
92409
92418
|
var MINIMUM_EXTENDED_POSITION_SIZE = 1e-4;
|
|
92410
92419
|
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
92420
|
|
|
92414
92421
|
// src/strategies/vesu-extended-strategy/utils/helper.ts
|
|
92415
92422
|
var returnFormattedAmount = (amount, toTokenDecimals) => {
|
|
@@ -92429,8 +92436,7 @@ spurious results.`);
|
|
|
92429
92436
|
vesu_leverage: 0
|
|
92430
92437
|
};
|
|
92431
92438
|
}
|
|
92432
|
-
const
|
|
92433
|
-
const extendedExposureUSD = extendedBTCExposure.multipliedBy(collateralPrice);
|
|
92439
|
+
const extendedExposureUSD = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].value, WBTC_TOKEN_DECIMALS) : new Web3Number(0, WBTC_TOKEN_DECIMALS);
|
|
92434
92440
|
const vesuBTCExposureUSD = collateralUnits.multipliedBy(collateralPrice);
|
|
92435
92441
|
const numerator1 = vesu_leverage * amount + vesuBTCExposureUSD.toNumber();
|
|
92436
92442
|
const numerator2 = extendedExposureUSD.toNumber();
|
|
@@ -92466,8 +92472,7 @@ spurious results.`);
|
|
|
92466
92472
|
logger2.error("error getting extended positions");
|
|
92467
92473
|
return null;
|
|
92468
92474
|
}
|
|
92469
|
-
const
|
|
92470
|
-
const extendedExposureUSD = extendedBTCExposure.multipliedBy(collateralPrice);
|
|
92475
|
+
const extendedExposureUSD = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].value, USDC_TOKEN_DECIMALS) : new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
92471
92476
|
const vesuExposureUSD = collateralUnits.multipliedBy(collateralPrice);
|
|
92472
92477
|
if (vesuExposureUSD.lessThan(0)) {
|
|
92473
92478
|
return {
|
|
@@ -92485,9 +92490,14 @@ spurious results.`);
|
|
|
92485
92490
|
vesu_leverage
|
|
92486
92491
|
};
|
|
92487
92492
|
}
|
|
92493
|
+
console.log("the vesu exposure usd is", vesuExposureUSD.toNumber());
|
|
92494
|
+
console.log("the extended exposure usd is", extendedExposureUSD.toNumber());
|
|
92495
|
+
console.log("the amount in usdc is", amountInUsdc.toNumber());
|
|
92496
|
+
console.log("the extended leverage is", extended_leverage);
|
|
92497
|
+
console.log("the vesu leverage is", vesu_leverage);
|
|
92488
92498
|
const numerator1 = amountInUsdc.multipliedBy(extended_leverage);
|
|
92489
|
-
const numerator2 = vesuExposureUSD
|
|
92490
|
-
const numerator3 = extendedExposureUSD.multipliedBy(
|
|
92499
|
+
const numerator2 = vesuExposureUSD;
|
|
92500
|
+
const numerator3 = extendedExposureUSD.multipliedBy(-1);
|
|
92491
92501
|
const finalNumerator = numerator1.plus(numerator2).plus(numerator3);
|
|
92492
92502
|
const denominator = extended_leverage + vesu_leverage;
|
|
92493
92503
|
const vesuAmountInUSDC = finalNumerator.dividedBy(denominator);
|
|
@@ -92497,6 +92507,7 @@ spurious results.`);
|
|
|
92497
92507
|
"the extended amount in usdc is",
|
|
92498
92508
|
extendedAmountInUSDC.toNumber()
|
|
92499
92509
|
);
|
|
92510
|
+
await new Promise((resolve) => setTimeout(resolve, 1e4));
|
|
92500
92511
|
return {
|
|
92501
92512
|
vesu_amount: vesuAmountInUSDC,
|
|
92502
92513
|
extended_amount: extendedAmountInUSDC,
|
|
@@ -92518,10 +92529,10 @@ spurious results.`);
|
|
|
92518
92529
|
const extended_leverage_max = 1 / (MAINTENANCE_MARGIN + MAX_PRICE_DROP_PERCENTAGE);
|
|
92519
92530
|
return Math.floor(extended_leverage_max);
|
|
92520
92531
|
};
|
|
92521
|
-
var calculateDebtAmount = (collateralAmount, debtAmount, debtPrice, maxLtv =
|
|
92532
|
+
var calculateDebtAmount = (collateralAmount, debtAmount, debtPrice, maxLtv = MAX_LIQUIDATION_RATIO, addedAmount, collateralPrice, isDeposit) => {
|
|
92522
92533
|
try {
|
|
92523
|
-
const
|
|
92524
|
-
const numerator1 = collateralAmount.plus(
|
|
92534
|
+
const addedCollateral = addedAmount.multipliedBy(isDeposit ? 1 : -1);
|
|
92535
|
+
const numerator1 = collateralAmount.plus(addedCollateral).multipliedBy(collateralPrice).multipliedBy(maxLtv);
|
|
92525
92536
|
const numerator2 = debtAmount.multipliedBy(debtPrice).multipliedBy(TARGET_HF);
|
|
92526
92537
|
const denominator = TARGET_HF - maxLtv;
|
|
92527
92538
|
const x_debt_usd = numerator1.minus(numerator2).dividedBy(denominator);
|
|
@@ -92556,16 +92567,16 @@ spurious results.`);
|
|
|
92556
92567
|
const extendedHoldings = await client.getHoldings();
|
|
92557
92568
|
const extended_leverage = calculateExtendedLevergae();
|
|
92558
92569
|
const latestPosition = (await client.getPositions()).data.pop();
|
|
92559
|
-
console.log("the latest position is", latestPosition, extendedHoldings);
|
|
92560
92570
|
if (!extendedHoldings || !latestPosition) {
|
|
92561
92571
|
logger2.error(`error getting extended position: extendedHoldings=${extendedHoldings}, latestPosition=${latestPosition}`);
|
|
92562
92572
|
return null;
|
|
92563
92573
|
}
|
|
92564
|
-
const positionValueInUSD = latestPosition.value;
|
|
92574
|
+
const positionValueInUSD = new Web3Number(latestPosition.value, USDC_TOKEN_DECIMALS);
|
|
92565
92575
|
const equity = extendedHoldings.data.equity;
|
|
92566
|
-
const deposit =
|
|
92567
|
-
return new Web3Number(
|
|
92576
|
+
const deposit = positionValueInUSD.dividedBy(extended_leverage).minus(equity).toFixed(2);
|
|
92577
|
+
return new Web3Number(deposit, USDC_TOKEN_DECIMALS);
|
|
92568
92578
|
} catch (err2) {
|
|
92579
|
+
logger2.error(`error calculating amount deposit on extended when incurring losses: ${err2}`);
|
|
92569
92580
|
return null;
|
|
92570
92581
|
}
|
|
92571
92582
|
};
|
|
@@ -92643,21 +92654,36 @@ spurious results.`);
|
|
|
92643
92654
|
vaultAllocator: config3.vaultAllocator,
|
|
92644
92655
|
id: ""
|
|
92645
92656
|
});
|
|
92646
|
-
this.
|
|
92657
|
+
this.minimumVesuMovementAmount = config3.minimumVesuMovementAmount ?? 5;
|
|
92658
|
+
this.tokenMarketData = new TokenMarketData(
|
|
92659
|
+
this.config.pricer,
|
|
92660
|
+
this.config.networkConfig
|
|
92661
|
+
);
|
|
92647
92662
|
}
|
|
92648
92663
|
async getAPY(supportedPosition) {
|
|
92649
92664
|
const CACHE_KEY = `apy_${this.config.poolId.address}_${supportedPosition.asset.symbol}`;
|
|
92650
92665
|
const cacheData = this.getCache(CACHE_KEY);
|
|
92651
|
-
console.log(
|
|
92666
|
+
console.log(
|
|
92667
|
+
`${_VesuMultiplyAdapter.name}::getAPY cacheData: ${JSON.stringify(
|
|
92668
|
+
cacheData
|
|
92669
|
+
)}`,
|
|
92670
|
+
this.vesuAdapter.config.poolId.shortString(),
|
|
92671
|
+
this.vesuAdapter.config.collateral.symbol,
|
|
92672
|
+
this.vesuAdapter.config.debt.symbol
|
|
92673
|
+
);
|
|
92652
92674
|
if (cacheData) {
|
|
92653
92675
|
return cacheData;
|
|
92654
92676
|
}
|
|
92655
92677
|
try {
|
|
92656
92678
|
const allVesuPools = await VesuAdapter.getVesuPools();
|
|
92657
92679
|
const asset = supportedPosition.asset;
|
|
92658
|
-
const pool = allVesuPools.pools.find(
|
|
92680
|
+
const pool = allVesuPools.pools.find(
|
|
92681
|
+
(p) => this.vesuAdapter.config.poolId.eqString(num_exports.getHexString(p.id))
|
|
92682
|
+
);
|
|
92659
92683
|
if (!pool) {
|
|
92660
|
-
logger2.warn(
|
|
92684
|
+
logger2.warn(
|
|
92685
|
+
`VesuMultiplyAdapter: Pool not found for token ${asset.symbol}`
|
|
92686
|
+
);
|
|
92661
92687
|
return {
|
|
92662
92688
|
apy: 0,
|
|
92663
92689
|
type: "base" /* BASE */
|
|
@@ -92667,7 +92693,9 @@ spurious results.`);
|
|
|
92667
92693
|
(a) => a.symbol.toLowerCase() === asset.symbol.toLowerCase()
|
|
92668
92694
|
)?.stats;
|
|
92669
92695
|
if (!assetStats) {
|
|
92670
|
-
logger2.warn(
|
|
92696
|
+
logger2.warn(
|
|
92697
|
+
`VesuMultiplyAdapter: Asset stats not found for token ${asset.symbol}`
|
|
92698
|
+
);
|
|
92671
92699
|
return {
|
|
92672
92700
|
apy: 0,
|
|
92673
92701
|
type: "base" /* BASE */
|
|
@@ -92678,7 +92706,9 @@ spurious results.`);
|
|
|
92678
92706
|
apy = Number(assetStats.borrowApr?.value || 0) / 1e18;
|
|
92679
92707
|
} else {
|
|
92680
92708
|
const isAssetBTC = asset.symbol.toLowerCase().includes("btc");
|
|
92681
|
-
const baseAPY = Number(
|
|
92709
|
+
const baseAPY = Number(
|
|
92710
|
+
isAssetBTC ? assetStats.btcFiSupplyApr?.value + assetStats.supplyApy?.value : assetStats.supplyApy?.value || 0
|
|
92711
|
+
) / 1e18;
|
|
92682
92712
|
const rewardAPY = Number(assetStats.defiSpringSupplyApr?.value || "0") / 1e18;
|
|
92683
92713
|
const isSupported = this.tokenMarketData.isAPYSupported(asset);
|
|
92684
92714
|
apy = baseAPY + rewardAPY;
|
|
@@ -92694,7 +92724,10 @@ spurious results.`);
|
|
|
92694
92724
|
this.setCache(CACHE_KEY, result2, 3e5);
|
|
92695
92725
|
return result2;
|
|
92696
92726
|
} catch (error2) {
|
|
92697
|
-
logger2.error(
|
|
92727
|
+
logger2.error(
|
|
92728
|
+
`VesuMultiplyAdapter: Error getting APY for ${supportedPosition.asset.symbol}:`,
|
|
92729
|
+
error2
|
|
92730
|
+
);
|
|
92698
92731
|
throw error2;
|
|
92699
92732
|
}
|
|
92700
92733
|
}
|
|
@@ -92707,12 +92740,16 @@ spurious results.`);
|
|
|
92707
92740
|
try {
|
|
92708
92741
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
92709
92742
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
92710
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
92743
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
92744
|
+
this.config.networkConfig
|
|
92745
|
+
);
|
|
92711
92746
|
let position = positions.find(
|
|
92712
92747
|
(p) => p.token.address.eq(supportedPosition.asset.address)
|
|
92713
92748
|
);
|
|
92714
92749
|
if (!position) {
|
|
92715
|
-
logger2.warn(
|
|
92750
|
+
logger2.warn(
|
|
92751
|
+
`VesuMultiplyAdapter: Position not found for token ${supportedPosition.asset.symbol}`
|
|
92752
|
+
);
|
|
92716
92753
|
return {
|
|
92717
92754
|
amount: new Web3Number("0", supportedPosition.asset.decimals),
|
|
92718
92755
|
remarks: "Position not found"
|
|
@@ -92725,12 +92762,18 @@ spurious results.`);
|
|
|
92725
92762
|
this.setCache(CACHE_KEY, position, 6e4);
|
|
92726
92763
|
return position;
|
|
92727
92764
|
} catch (error2) {
|
|
92728
|
-
logger2.error(
|
|
92765
|
+
logger2.error(
|
|
92766
|
+
`VesuMultiplyAdapter: Error getting position for ${supportedPosition.asset.symbol}:`,
|
|
92767
|
+
error2
|
|
92768
|
+
);
|
|
92729
92769
|
throw error2;
|
|
92730
92770
|
}
|
|
92731
92771
|
}
|
|
92732
92772
|
async maxBorrowableAPY() {
|
|
92733
|
-
const collateralAPY = await this.getAPY({
|
|
92773
|
+
const collateralAPY = await this.getAPY({
|
|
92774
|
+
asset: this.config.collateral,
|
|
92775
|
+
isDebt: false
|
|
92776
|
+
});
|
|
92734
92777
|
const apy = collateralAPY.apy * 0.8;
|
|
92735
92778
|
return apy;
|
|
92736
92779
|
}
|
|
@@ -92740,9 +92783,15 @@ spurious results.`);
|
|
|
92740
92783
|
try {
|
|
92741
92784
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
92742
92785
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
92743
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
92744
|
-
|
|
92745
|
-
|
|
92786
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
92787
|
+
this.config.networkConfig
|
|
92788
|
+
);
|
|
92789
|
+
const collateralPosition = positions.find(
|
|
92790
|
+
(p) => p.token.address.eq(collateral.address)
|
|
92791
|
+
);
|
|
92792
|
+
const debtPosition = positions.find(
|
|
92793
|
+
(p) => p.token.address.eq(debt.address)
|
|
92794
|
+
);
|
|
92746
92795
|
if (!collateralPosition || !debtPosition) {
|
|
92747
92796
|
throw new Error("Could not find current positions");
|
|
92748
92797
|
}
|
|
@@ -92752,13 +92801,23 @@ spurious results.`);
|
|
|
92752
92801
|
debt,
|
|
92753
92802
|
maxBorrowableAPY
|
|
92754
92803
|
);
|
|
92755
|
-
logger2.verbose(
|
|
92756
|
-
|
|
92804
|
+
logger2.verbose(
|
|
92805
|
+
`VesuMultiplyAdapter: Max borrowable: ${maxBorrowable.toNumber()}`
|
|
92806
|
+
);
|
|
92807
|
+
const debtCap = await this.vesuAdapter.getDebtCap(
|
|
92808
|
+
this.config.networkConfig
|
|
92809
|
+
);
|
|
92757
92810
|
logger2.verbose(`VesuMultiplyAdapter: Debt cap: ${debtCap.toNumber()}`);
|
|
92758
92811
|
const actualMaxBorrowable = maxBorrowable.minimum(debtCap);
|
|
92759
|
-
logger2.verbose(
|
|
92760
|
-
|
|
92761
|
-
|
|
92812
|
+
logger2.verbose(
|
|
92813
|
+
`VesuMultiplyAdapter: Actual max borrowable: ${actualMaxBorrowable.toNumber()}`
|
|
92814
|
+
);
|
|
92815
|
+
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
92816
|
+
this.config.networkConfig
|
|
92817
|
+
);
|
|
92818
|
+
const collateralPrice = await this.config.pricer.getPrice(
|
|
92819
|
+
collateral.symbol
|
|
92820
|
+
);
|
|
92762
92821
|
if (collateralPrice.price === 0) {
|
|
92763
92822
|
throw new Error("Collateral price is 0");
|
|
92764
92823
|
}
|
|
@@ -92776,14 +92835,25 @@ spurious results.`);
|
|
|
92776
92835
|
);
|
|
92777
92836
|
const maxDepositAmount = amount ? amount.minimum(maxCollateralFromDebt) : maxCollateralFromDebt;
|
|
92778
92837
|
const usdValue = await this.getUSDValue(collateral, maxDepositAmount);
|
|
92779
|
-
logger2.verbose(
|
|
92780
|
-
|
|
92781
|
-
|
|
92838
|
+
logger2.verbose(
|
|
92839
|
+
`VesuMultiplyAdapter: Max deposit::USD value: ${usdValue}, amount: ${maxDepositAmount.toNumber()}`
|
|
92840
|
+
);
|
|
92841
|
+
const apys = await Promise.all([
|
|
92842
|
+
this.getAPY({ asset: collateral, isDebt: false }),
|
|
92843
|
+
this.getAPY({ asset: debt, isDebt: true })
|
|
92844
|
+
]);
|
|
92845
|
+
logger2.verbose(
|
|
92846
|
+
`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
|
|
92847
|
+
);
|
|
92782
92848
|
const borrowAmountUSD = actualMaxBorrowable.multipliedBy(debtPrice.price);
|
|
92783
|
-
logger2.verbose(
|
|
92849
|
+
logger2.verbose(
|
|
92850
|
+
`VesuMultiplyAdapter: Borrow amount: ${actualMaxBorrowable.toNumber()}, borrow amount USD: ${borrowAmountUSD.toNumber()}`
|
|
92851
|
+
);
|
|
92784
92852
|
const netCollateralUSD = usdValue + borrowAmountUSD.toNumber();
|
|
92785
92853
|
const netAPY = (apys[0].apy * netCollateralUSD + apys[1].apy * borrowAmountUSD.toNumber()) / usdValue;
|
|
92786
|
-
logger2.verbose(
|
|
92854
|
+
logger2.verbose(
|
|
92855
|
+
`VesuMultiplyAdapter: Max deposit amount: ${maxDepositAmount.toNumber()}, netAPY: ${netAPY}`
|
|
92856
|
+
);
|
|
92787
92857
|
return {
|
|
92788
92858
|
tokenInfo: collateral,
|
|
92789
92859
|
amount: maxDepositAmount,
|
|
@@ -92796,7 +92866,10 @@ spurious results.`);
|
|
|
92796
92866
|
protocol: this.protocol
|
|
92797
92867
|
};
|
|
92798
92868
|
} catch (error2) {
|
|
92799
|
-
logger2.error(
|
|
92869
|
+
logger2.error(
|
|
92870
|
+
`VesuMultiplyAdapter: Error calculating max deposit:`,
|
|
92871
|
+
error2
|
|
92872
|
+
);
|
|
92800
92873
|
throw error2;
|
|
92801
92874
|
}
|
|
92802
92875
|
}
|
|
@@ -92806,9 +92879,15 @@ spurious results.`);
|
|
|
92806
92879
|
try {
|
|
92807
92880
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
92808
92881
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
92809
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
92810
|
-
|
|
92811
|
-
|
|
92882
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
92883
|
+
this.config.networkConfig
|
|
92884
|
+
);
|
|
92885
|
+
const collateralPosition = positions.find(
|
|
92886
|
+
(p) => p.token.address.eq(collateral.address)
|
|
92887
|
+
);
|
|
92888
|
+
const debtPosition = positions.find(
|
|
92889
|
+
(p) => p.token.address.eq(this.config.debt.address)
|
|
92890
|
+
);
|
|
92812
92891
|
if (!collateralPosition || !debtPosition) {
|
|
92813
92892
|
throw new Error("Could not find current positions");
|
|
92814
92893
|
}
|
|
@@ -92818,11 +92897,20 @@ spurious results.`);
|
|
|
92818
92897
|
const result2 = maxWithdrawable.greaterThan(0) ? maxWithdrawable : new Web3Number("0", collateral.decimals);
|
|
92819
92898
|
const usdValue = await this.getUSDValue(collateral, result2);
|
|
92820
92899
|
const debtUSD = debtPosition.usdValue;
|
|
92821
|
-
logger2.verbose(
|
|
92822
|
-
|
|
92823
|
-
|
|
92900
|
+
logger2.verbose(
|
|
92901
|
+
`VesuMultiplyAdapter: Debt USD: ${debtUSD}, collateral USD: ${usdValue}`
|
|
92902
|
+
);
|
|
92903
|
+
const apys = await Promise.all([
|
|
92904
|
+
this.getAPY({ asset: collateral, isDebt: false }),
|
|
92905
|
+
this.getAPY({ asset: debt, isDebt: true })
|
|
92906
|
+
]);
|
|
92907
|
+
logger2.verbose(
|
|
92908
|
+
`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
|
|
92909
|
+
);
|
|
92824
92910
|
const netAPY = usdValue - debtUSD > 0 ? (apys[0].apy * usdValue + apys[1].apy * debtUSD) / (usdValue - debtUSD) : 0;
|
|
92825
|
-
logger2.verbose(
|
|
92911
|
+
logger2.verbose(
|
|
92912
|
+
`VesuMultiplyAdapter: Max withdraw amount: ${result2.toNumber()}, netAPY: ${netAPY}`
|
|
92913
|
+
);
|
|
92826
92914
|
return {
|
|
92827
92915
|
tokenInfo: collateral,
|
|
92828
92916
|
amount: result2,
|
|
@@ -92835,14 +92923,19 @@ spurious results.`);
|
|
|
92835
92923
|
protocol: this.protocol
|
|
92836
92924
|
};
|
|
92837
92925
|
} catch (error2) {
|
|
92838
|
-
logger2.error(
|
|
92926
|
+
logger2.error(
|
|
92927
|
+
`VesuMultiplyAdapter: Error calculating max withdraw:`,
|
|
92928
|
+
error2
|
|
92929
|
+
);
|
|
92839
92930
|
throw error2;
|
|
92840
92931
|
}
|
|
92841
92932
|
}
|
|
92842
92933
|
_getDepositLeaf() {
|
|
92843
92934
|
const collateral = this.config.collateral;
|
|
92844
92935
|
const debt = this.config.debt;
|
|
92845
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
92936
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
92937
|
+
this.config.poolId
|
|
92938
|
+
);
|
|
92846
92939
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
92847
92940
|
return [
|
|
92848
92941
|
// Approval step for collateral
|
|
@@ -92906,7 +92999,9 @@ spurious results.`);
|
|
|
92906
92999
|
];
|
|
92907
93000
|
}
|
|
92908
93001
|
_getWithdrawLeaf() {
|
|
92909
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
93002
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
93003
|
+
this.config.poolId
|
|
93004
|
+
);
|
|
92910
93005
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
92911
93006
|
const collateral = this.config.collateral;
|
|
92912
93007
|
const debt = this.config.debt;
|
|
@@ -92937,7 +93032,7 @@ spurious results.`);
|
|
|
92937
93032
|
this.config.debt.address.toBigInt(),
|
|
92938
93033
|
this.config.vaultAllocator.toBigInt()
|
|
92939
93034
|
],
|
|
92940
|
-
sanitizer: SIMPLE_SANITIZER_V2,
|
|
93035
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
|
|
92941
93036
|
// vmw = vesu multiply withdraw
|
|
92942
93037
|
id: `vmw_${this.config.poolId.shortString()}_${collateral.symbol}_${debt.symbol}`
|
|
92943
93038
|
},
|
|
@@ -92963,33 +93058,51 @@ spurious results.`);
|
|
|
92963
93058
|
const leafConfigs = this._getDepositLeaf();
|
|
92964
93059
|
const leaves = leafConfigs.map((config3) => {
|
|
92965
93060
|
const { target, method, packedArguments, sanitizer, id } = config3;
|
|
92966
|
-
const leaf = this.constructSimpleLeafData(
|
|
92967
|
-
|
|
92968
|
-
|
|
92969
|
-
|
|
92970
|
-
|
|
92971
|
-
|
|
93061
|
+
const leaf = this.constructSimpleLeafData(
|
|
93062
|
+
{
|
|
93063
|
+
id,
|
|
93064
|
+
target,
|
|
93065
|
+
method,
|
|
93066
|
+
packedArguments
|
|
93067
|
+
},
|
|
93068
|
+
sanitizer
|
|
93069
|
+
);
|
|
92972
93070
|
return leaf;
|
|
92973
93071
|
});
|
|
92974
|
-
return {
|
|
93072
|
+
return {
|
|
93073
|
+
leaves,
|
|
93074
|
+
callConstructor: this.getDepositCall.bind(
|
|
93075
|
+
this
|
|
93076
|
+
)
|
|
93077
|
+
};
|
|
92975
93078
|
}
|
|
92976
93079
|
getWithdrawAdapter() {
|
|
92977
93080
|
const leafConfigs = this._getWithdrawLeaf();
|
|
92978
93081
|
const leaves = leafConfigs.map((config3) => {
|
|
92979
93082
|
const { target, method, packedArguments, sanitizer, id } = config3;
|
|
92980
|
-
const leaf = this.constructSimpleLeafData(
|
|
92981
|
-
|
|
92982
|
-
|
|
92983
|
-
|
|
92984
|
-
|
|
92985
|
-
|
|
93083
|
+
const leaf = this.constructSimpleLeafData(
|
|
93084
|
+
{
|
|
93085
|
+
id,
|
|
93086
|
+
target,
|
|
93087
|
+
method,
|
|
93088
|
+
packedArguments
|
|
93089
|
+
},
|
|
93090
|
+
sanitizer
|
|
93091
|
+
);
|
|
92986
93092
|
return leaf;
|
|
92987
93093
|
});
|
|
92988
|
-
return {
|
|
93094
|
+
return {
|
|
93095
|
+
leaves,
|
|
93096
|
+
callConstructor: this.getWithdrawCall.bind(
|
|
93097
|
+
this
|
|
93098
|
+
)
|
|
93099
|
+
};
|
|
92989
93100
|
}
|
|
92990
93101
|
async getDepositCall(params) {
|
|
92991
93102
|
const collateral = this.config.collateral;
|
|
92992
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
93103
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
93104
|
+
this.config.poolId
|
|
93105
|
+
);
|
|
92993
93106
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
92994
93107
|
const uint256MarginAmount = uint256_exports.bnToUint256(params.amount.toWei());
|
|
92995
93108
|
return [
|
|
@@ -93061,7 +93174,9 @@ spurious results.`);
|
|
|
93061
93174
|
];
|
|
93062
93175
|
}
|
|
93063
93176
|
async getWithdrawCall(params) {
|
|
93064
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
93177
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
93178
|
+
this.config.poolId
|
|
93179
|
+
);
|
|
93065
93180
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
93066
93181
|
return [
|
|
93067
93182
|
// Switch delegation on
|
|
@@ -93086,7 +93201,7 @@ spurious results.`);
|
|
|
93086
93201
|
},
|
|
93087
93202
|
// Vesu multiply call
|
|
93088
93203
|
{
|
|
93089
|
-
sanitizer: SIMPLE_SANITIZER_V2,
|
|
93204
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
|
|
93090
93205
|
call: {
|
|
93091
93206
|
contractAddress: vesuMultiply,
|
|
93092
93207
|
selector: hash_exports.getSelectorFromName("modify_lever"),
|
|
@@ -93116,7 +93231,11 @@ spurious results.`);
|
|
|
93116
93231
|
];
|
|
93117
93232
|
}
|
|
93118
93233
|
async getMultiplyCallCalldata(params, isDeposit) {
|
|
93119
|
-
logger2.verbose(
|
|
93234
|
+
logger2.verbose(
|
|
93235
|
+
`${_VesuMultiplyAdapter.name}::getMultiplyCallCalldata params: ${JSON.stringify(
|
|
93236
|
+
params
|
|
93237
|
+
)}, isDeposit: ${isDeposit}, collateral: ${this.config.collateral.symbol}, debt: ${this.config.debt.symbol}`
|
|
93238
|
+
);
|
|
93120
93239
|
const { isV2 } = getVesuSingletonAddress(this.config.poolId);
|
|
93121
93240
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
93122
93241
|
const multiplyContract = new Contract({
|
|
@@ -93126,42 +93245,83 @@ spurious results.`);
|
|
|
93126
93245
|
});
|
|
93127
93246
|
let leverSwap = [];
|
|
93128
93247
|
let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
93129
|
-
const existingPositions = await this.vesuAdapter.getPositions(
|
|
93130
|
-
|
|
93248
|
+
const existingPositions = await this.vesuAdapter.getPositions(
|
|
93249
|
+
this.config.networkConfig
|
|
93250
|
+
);
|
|
93251
|
+
const collateralisation = await this.vesuAdapter.getCollateralization(
|
|
93252
|
+
this.config.networkConfig
|
|
93253
|
+
);
|
|
93131
93254
|
const existingCollateralInfo = existingPositions[0];
|
|
93132
93255
|
const existingDebtInfo = existingPositions[1];
|
|
93133
93256
|
const isDexPriceRequired = existingDebtInfo.token.symbol !== "USDC";
|
|
93134
|
-
logger2.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(
|
|
93135
|
-
|
|
93257
|
+
logger2.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(
|
|
93258
|
+
existingCollateralInfo
|
|
93259
|
+
)},
|
|
93260
|
+
existingDebtInfo: ${JSON.stringify(
|
|
93261
|
+
existingDebtInfo
|
|
93262
|
+
)}, collateralisation: ${JSON.stringify(collateralisation)}`);
|
|
93136
93263
|
const collateralPrice = collateralisation[0].usdValue > 0 ? collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() : (await this.config.pricer.getPrice(this.config.collateral.symbol)).price;
|
|
93137
93264
|
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
|
-
|
|
93265
|
+
logger2.debug(
|
|
93266
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`
|
|
93267
|
+
);
|
|
93268
|
+
const legLTV = await this.vesuAdapter.getLTVConfig(
|
|
93269
|
+
this.config.networkConfig
|
|
93270
|
+
);
|
|
93271
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
93272
|
+
this.config.networkConfig,
|
|
93273
|
+
this.config.pricer
|
|
93274
|
+
);
|
|
93275
|
+
const dexPrice = isDexPriceRequired ? await ekuboQuoter.getDexPrice(
|
|
93276
|
+
this.config.collateral,
|
|
93277
|
+
this.config.debt,
|
|
93278
|
+
this.config.quoteAmountToFetchPrice
|
|
93279
|
+
) : 1;
|
|
93280
|
+
logger2.verbose(
|
|
93281
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall dexPrice: ${dexPrice}, ltv: ${legLTV}`
|
|
93282
|
+
);
|
|
93143
93283
|
const addedCollateral = params.amount.multipliedBy(isDeposit ? 1 : -1);
|
|
93144
|
-
logger2.verbose(
|
|
93284
|
+
logger2.verbose(
|
|
93285
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall addedCollateral: ${addedCollateral}`
|
|
93286
|
+
);
|
|
93145
93287
|
const numeratorPart1 = existingCollateralInfo.amount.plus(addedCollateral).multipliedBy(collateralPrice).multipliedBy(legLTV);
|
|
93146
|
-
logger2.verbose(
|
|
93288
|
+
logger2.verbose(
|
|
93289
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}`
|
|
93290
|
+
);
|
|
93147
93291
|
const numeratorPart2 = existingDebtInfo.amount.multipliedBy(debtPrice).multipliedBy(this.config.targetHealthFactor);
|
|
93148
|
-
logger2.verbose(
|
|
93292
|
+
logger2.verbose(
|
|
93293
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart2: ${numeratorPart2}`
|
|
93294
|
+
);
|
|
93149
93295
|
const denominatorPart = this.config.targetHealthFactor - legLTV / dexPrice;
|
|
93150
|
-
logger2.verbose(
|
|
93296
|
+
logger2.verbose(
|
|
93297
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall denominatorPart: ${denominatorPart}`
|
|
93298
|
+
);
|
|
93151
93299
|
const x_debt_usd = numeratorPart1.minus(numeratorPart2).dividedBy(denominatorPart);
|
|
93152
|
-
logger2.verbose(
|
|
93153
|
-
|
|
93154
|
-
|
|
93300
|
+
logger2.verbose(
|
|
93301
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall x_debt_usd: ${x_debt_usd}`
|
|
93302
|
+
);
|
|
93303
|
+
logger2.debug(
|
|
93304
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}, numeratorPart2: ${numeratorPart2}, denominatorPart: ${denominatorPart}`
|
|
93305
|
+
);
|
|
93306
|
+
let debtAmount = new Web3Number(
|
|
93307
|
+
x_debt_usd.dividedBy(debtPrice).toFixed(this.config.debt.decimals),
|
|
93308
|
+
this.config.debt.decimals
|
|
93309
|
+
);
|
|
93155
93310
|
const marginAmount = addedCollateral;
|
|
93156
93311
|
const collateralToken = this.config.collateral;
|
|
93157
93312
|
const debtToken = this.config.debt;
|
|
93158
|
-
const debtAmountInCollateralUnits = new Web3Number(
|
|
93313
|
+
const debtAmountInCollateralUnits = new Web3Number(
|
|
93314
|
+
debtAmount.multipliedBy(debtPrice).dividedBy(collateralPrice).multipliedBy(10 ** collateralToken.decimals).toFixed(0),
|
|
93315
|
+
collateralToken.decimals
|
|
93316
|
+
);
|
|
93159
93317
|
const isIncrease = debtAmount.greaterThanOrEqualTo(0);
|
|
93160
93318
|
if (isIncrease && debtAmount.lessThan(0)) {
|
|
93161
93319
|
} else if (!isIncrease && debtAmount.greaterThan(0)) {
|
|
93162
93320
|
debtAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
93163
93321
|
}
|
|
93164
|
-
logger2.verbose(
|
|
93322
|
+
logger2.verbose(
|
|
93323
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall debtAmount: ${debtAmount}, marginAmount: ${marginAmount}`
|
|
93324
|
+
);
|
|
93165
93325
|
if (!debtAmount.isZero()) {
|
|
93166
93326
|
try {
|
|
93167
93327
|
const swapQuote = await ekuboQuoter.getQuote(
|
|
@@ -93171,32 +93331,49 @@ spurious results.`);
|
|
|
93171
93331
|
// negative for exact amount out
|
|
93172
93332
|
);
|
|
93173
93333
|
if (swapQuote.price_impact < 0.01) {
|
|
93174
|
-
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
93334
|
+
leverSwap = debtAmount.isNegative() ? ekuboQuoter.getVesuMultiplyQuote(
|
|
93335
|
+
swapQuote,
|
|
93336
|
+
collateralToken,
|
|
93337
|
+
debtToken
|
|
93338
|
+
) : ekuboQuoter.getVesuMultiplyQuote(
|
|
93339
|
+
swapQuote,
|
|
93340
|
+
debtToken,
|
|
93341
|
+
collateralToken
|
|
93342
|
+
);
|
|
93175
93343
|
const MAX_SLIPPAGE = 2e-3;
|
|
93176
93344
|
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);
|
|
93345
|
+
leverSwapLimitAmount = debtAmount.multipliedBy(1 + MAX_SLIPPAGE);
|
|
93181
93346
|
} else if (debtAmount.lessThan(0)) {
|
|
93182
|
-
leverSwapLimitAmount =
|
|
93183
|
-
const anotherleverSwapLimitAmount = debtAmount.abs().multipliedBy(1 - MAX_SLIPPAGE);
|
|
93184
|
-
console.log("anotherleverSwapLimitAmount", anotherleverSwapLimitAmount, leverSwapLimitAmount);
|
|
93347
|
+
leverSwapLimitAmount = debtAmount.abs().multipliedBy(1 - MAX_SLIPPAGE);
|
|
93185
93348
|
} else {
|
|
93186
|
-
leverSwapLimitAmount = Web3Number.fromWei(
|
|
93349
|
+
leverSwapLimitAmount = Web3Number.fromWei(
|
|
93350
|
+
0,
|
|
93351
|
+
this.config.debt.decimals
|
|
93352
|
+
);
|
|
93187
93353
|
}
|
|
93188
93354
|
await new Promise((resolve) => setTimeout(resolve, 1e4));
|
|
93189
|
-
console.log("leverSwapLimitAmount", leverSwapLimitAmount);
|
|
93190
93355
|
} else {
|
|
93191
|
-
throw new Error(
|
|
93356
|
+
throw new Error(
|
|
93357
|
+
`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
|
|
93358
|
+
);
|
|
93192
93359
|
}
|
|
93193
93360
|
} catch (error2) {
|
|
93194
|
-
throw new Error(
|
|
93361
|
+
throw new Error(
|
|
93362
|
+
`VesuMultiplyAdapter: Failed to get swap quote: ${error2}`
|
|
93363
|
+
);
|
|
93195
93364
|
}
|
|
93196
93365
|
}
|
|
93197
|
-
const multiplyParams = await this.getLeverParams(
|
|
93366
|
+
const multiplyParams = await this.getLeverParams(
|
|
93367
|
+
isIncrease,
|
|
93368
|
+
params,
|
|
93369
|
+
leverSwap,
|
|
93370
|
+
leverSwapLimitAmount
|
|
93371
|
+
);
|
|
93198
93372
|
const call = multiplyContract.populate("modify_lever", {
|
|
93199
|
-
modify_lever_params: this.formatMultiplyParams(
|
|
93373
|
+
modify_lever_params: this.formatMultiplyParams(
|
|
93374
|
+
isIncrease,
|
|
93375
|
+
multiplyParams
|
|
93376
|
+
)
|
|
93200
93377
|
});
|
|
93201
93378
|
return call.calldata;
|
|
93202
93379
|
}
|
|
@@ -93210,7 +93387,10 @@ spurious results.`);
|
|
|
93210
93387
|
add_margin: params.amount,
|
|
93211
93388
|
// multiplied by collateral decimals in format
|
|
93212
93389
|
margin_swap: [],
|
|
93213
|
-
margin_swap_limit_amount: Web3Number.fromWei(
|
|
93390
|
+
margin_swap_limit_amount: Web3Number.fromWei(
|
|
93391
|
+
0,
|
|
93392
|
+
this.config.collateral.decimals
|
|
93393
|
+
),
|
|
93214
93394
|
lever_swap: leverSwap,
|
|
93215
93395
|
lever_swap_limit_amount: leverSwapLimitAmount
|
|
93216
93396
|
} : {
|
|
@@ -93224,7 +93404,10 @@ spurious results.`);
|
|
|
93224
93404
|
lever_swap_limit_amount: leverSwapLimitAmount,
|
|
93225
93405
|
lever_swap_weights: [],
|
|
93226
93406
|
withdraw_swap: [],
|
|
93227
|
-
withdraw_swap_limit_amount: Web3Number.fromWei(
|
|
93407
|
+
withdraw_swap_limit_amount: Web3Number.fromWei(
|
|
93408
|
+
0,
|
|
93409
|
+
this.config.collateral.decimals
|
|
93410
|
+
),
|
|
93228
93411
|
withdraw_swap_weights: [],
|
|
93229
93412
|
close_position: false
|
|
93230
93413
|
};
|
|
@@ -93240,12 +93423,16 @@ spurious results.`);
|
|
|
93240
93423
|
});
|
|
93241
93424
|
let leverSwap = [];
|
|
93242
93425
|
let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
93243
|
-
const existingPositions = await this.vesuAdapter.getPositions(
|
|
93426
|
+
const existingPositions = await this.vesuAdapter.getPositions(
|
|
93427
|
+
this.config.networkConfig
|
|
93428
|
+
);
|
|
93244
93429
|
const existingCollateralInfo = existingPositions[0];
|
|
93245
93430
|
const existingDebtInfo = existingPositions[1];
|
|
93246
93431
|
const collateralToken = this.config.collateral;
|
|
93247
93432
|
const debtToken = this.config.debt;
|
|
93248
|
-
const collateralPrice = await this.config.pricer.getPrice(
|
|
93433
|
+
const collateralPrice = await this.config.pricer.getPrice(
|
|
93434
|
+
collateralToken.symbol
|
|
93435
|
+
);
|
|
93249
93436
|
const debtPrice = await this.config.pricer.getPrice(debtToken.symbol);
|
|
93250
93437
|
const { deltadebtAmountUnits: debtAmountToRepay } = calculateDebtReductionAmountForWithdrawal(
|
|
93251
93438
|
existingDebtInfo.amount,
|
|
@@ -93256,27 +93443,41 @@ spurious results.`);
|
|
|
93256
93443
|
debtPrice.price,
|
|
93257
93444
|
debtToken.decimals
|
|
93258
93445
|
);
|
|
93259
|
-
console.log("debtAmountToRepay", debtAmountToRepay);
|
|
93260
93446
|
if (!debtAmountToRepay) {
|
|
93261
93447
|
throw new Error("error calculating debt amount to repay");
|
|
93262
93448
|
}
|
|
93263
|
-
const ekuboQuoter = new EkuboQuoter(
|
|
93264
|
-
|
|
93265
|
-
|
|
93449
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
93450
|
+
this.config.networkConfig,
|
|
93451
|
+
this.config.pricer
|
|
93452
|
+
);
|
|
93453
|
+
const debtInDebtUnits = new Web3Number(
|
|
93454
|
+
debtAmountToRepay,
|
|
93455
|
+
debtToken.decimals
|
|
93456
|
+
).dividedBy(debtPrice.price).multipliedBy(10 ** debtToken.decimals);
|
|
93266
93457
|
const swapQuote = await ekuboQuoter.getQuote(
|
|
93267
93458
|
debtToken.address.address,
|
|
93268
93459
|
collateralToken.address.address,
|
|
93269
93460
|
debtInDebtUnits
|
|
93270
93461
|
);
|
|
93271
93462
|
const MAX_SLIPPAGE = 2e-3;
|
|
93272
|
-
if (swapQuote.price_impact <
|
|
93273
|
-
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
93463
|
+
if (swapQuote.price_impact < 25e-4) {
|
|
93464
|
+
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
93465
|
+
swapQuote,
|
|
93466
|
+
collateralToken,
|
|
93467
|
+
debtToken
|
|
93468
|
+
);
|
|
93274
93469
|
} else {
|
|
93275
|
-
logger2.error(
|
|
93470
|
+
logger2.error(
|
|
93471
|
+
`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
|
|
93472
|
+
);
|
|
93276
93473
|
}
|
|
93277
|
-
|
|
93278
|
-
|
|
93279
|
-
|
|
93474
|
+
leverSwapLimitAmount = new Web3Number(debtAmountToRepay, debtToken.decimals).abs().multipliedBy(1 + MAX_SLIPPAGE);
|
|
93475
|
+
const multiplyParams = await this.getLeverParams(
|
|
93476
|
+
false,
|
|
93477
|
+
params,
|
|
93478
|
+
leverSwap,
|
|
93479
|
+
leverSwapLimitAmount
|
|
93480
|
+
);
|
|
93280
93481
|
const call = multiplyContract.populate("modify_lever", {
|
|
93281
93482
|
modify_lever_params: this.formatMultiplyParams(false, multiplyParams)
|
|
93282
93483
|
});
|
|
@@ -93286,100 +93487,132 @@ spurious results.`);
|
|
|
93286
93487
|
if (isIncrease) {
|
|
93287
93488
|
const _params2 = params;
|
|
93288
93489
|
return {
|
|
93289
|
-
action: new CairoCustomEnum({
|
|
93290
|
-
|
|
93291
|
-
|
|
93292
|
-
|
|
93293
|
-
|
|
93294
|
-
|
|
93295
|
-
|
|
93490
|
+
action: new CairoCustomEnum({
|
|
93491
|
+
IncreaseLever: {
|
|
93492
|
+
pool_id: _params2.pool_id.toBigInt(),
|
|
93493
|
+
collateral_asset: _params2.collateral_asset.toBigInt(),
|
|
93494
|
+
debt_asset: _params2.debt_asset.toBigInt(),
|
|
93495
|
+
user: _params2.user.toBigInt(),
|
|
93496
|
+
add_margin: BigInt(_params2.add_margin.toWei()),
|
|
93497
|
+
margin_swap: _params2.margin_swap.map((swap) => ({
|
|
93498
|
+
route: swap.route.map((route) => ({
|
|
93499
|
+
pool_key: {
|
|
93500
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
93501
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
93502
|
+
fee: route.pool_key.fee,
|
|
93503
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
93504
|
+
extension: BigInt(
|
|
93505
|
+
num_exports.hexToDecimalString(route.pool_key.extension)
|
|
93506
|
+
)
|
|
93507
|
+
},
|
|
93508
|
+
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93509
|
+
route.sqrt_ratio_limit.toWei()
|
|
93510
|
+
),
|
|
93511
|
+
skip_ahead: BigInt(100)
|
|
93512
|
+
})),
|
|
93513
|
+
token_amount: {
|
|
93514
|
+
token: swap.token_amount.token.toBigInt(),
|
|
93515
|
+
amount: swap.token_amount.amount.toI129()
|
|
93516
|
+
}
|
|
93517
|
+
})),
|
|
93518
|
+
margin_swap_limit_amount: BigInt(
|
|
93519
|
+
_params2.margin_swap_limit_amount.toWei()
|
|
93520
|
+
),
|
|
93521
|
+
lever_swap: _params2.lever_swap.map((swap) => ({
|
|
93522
|
+
route: swap.route.map((route) => ({
|
|
93523
|
+
pool_key: {
|
|
93524
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
93525
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
93526
|
+
fee: route.pool_key.fee,
|
|
93527
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
93528
|
+
extension: BigInt(
|
|
93529
|
+
num_exports.hexToDecimalString(route.pool_key.extension)
|
|
93530
|
+
)
|
|
93531
|
+
},
|
|
93532
|
+
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93533
|
+
route.sqrt_ratio_limit.toWei()
|
|
93534
|
+
),
|
|
93535
|
+
skip_ahead: BigInt(0)
|
|
93536
|
+
})),
|
|
93537
|
+
token_amount: {
|
|
93538
|
+
token: swap.token_amount.token.toBigInt(),
|
|
93539
|
+
amount: swap.token_amount.amount.toI129()
|
|
93540
|
+
}
|
|
93541
|
+
})),
|
|
93542
|
+
lever_swap_limit_amount: BigInt(
|
|
93543
|
+
_params2.lever_swap_limit_amount.toWei()
|
|
93544
|
+
)
|
|
93545
|
+
}
|
|
93546
|
+
})
|
|
93547
|
+
};
|
|
93548
|
+
}
|
|
93549
|
+
const _params = params;
|
|
93550
|
+
return {
|
|
93551
|
+
action: new CairoCustomEnum({
|
|
93552
|
+
DecreaseLever: {
|
|
93553
|
+
pool_id: _params.pool_id.toBigInt(),
|
|
93554
|
+
collateral_asset: _params.collateral_asset.toBigInt(),
|
|
93555
|
+
debt_asset: _params.debt_asset.toBigInt(),
|
|
93556
|
+
user: _params.user.toBigInt(),
|
|
93557
|
+
sub_margin: BigInt(_params.sub_margin.toWei()),
|
|
93558
|
+
recipient: _params.recipient.toBigInt(),
|
|
93559
|
+
lever_swap: _params.lever_swap.map((swap) => ({
|
|
93296
93560
|
route: swap.route.map((route) => ({
|
|
93297
93561
|
pool_key: {
|
|
93298
93562
|
token0: route.pool_key.token0.toBigInt(),
|
|
93299
93563
|
token1: route.pool_key.token1.toBigInt(),
|
|
93300
93564
|
fee: route.pool_key.fee,
|
|
93301
93565
|
tick_spacing: route.pool_key.tick_spacing,
|
|
93302
|
-
extension:
|
|
93566
|
+
extension: ContractAddr.from(
|
|
93567
|
+
route.pool_key.extension
|
|
93568
|
+
).toBigInt()
|
|
93303
93569
|
},
|
|
93304
|
-
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93305
|
-
|
|
93570
|
+
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93571
|
+
route.sqrt_ratio_limit.toWei()
|
|
93572
|
+
),
|
|
93573
|
+
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
93306
93574
|
})),
|
|
93307
93575
|
token_amount: {
|
|
93308
93576
|
token: swap.token_amount.token.toBigInt(),
|
|
93309
93577
|
amount: swap.token_amount.amount.toI129()
|
|
93310
93578
|
}
|
|
93311
93579
|
})),
|
|
93312
|
-
|
|
93313
|
-
|
|
93580
|
+
lever_swap_limit_amount: BigInt(
|
|
93581
|
+
_params.lever_swap_limit_amount.toWei()
|
|
93582
|
+
),
|
|
93583
|
+
lever_swap_weights: _params.lever_swap_weights.map(
|
|
93584
|
+
(weight) => BigInt(weight.toWei())
|
|
93585
|
+
),
|
|
93586
|
+
withdraw_swap: _params.withdraw_swap.map((swap) => ({
|
|
93314
93587
|
route: swap.route.map((route) => ({
|
|
93315
93588
|
pool_key: {
|
|
93316
93589
|
token0: route.pool_key.token0.toBigInt(),
|
|
93317
93590
|
token1: route.pool_key.token1.toBigInt(),
|
|
93318
93591
|
fee: route.pool_key.fee,
|
|
93319
93592
|
tick_spacing: route.pool_key.tick_spacing,
|
|
93320
|
-
extension:
|
|
93593
|
+
extension: ContractAddr.from(
|
|
93594
|
+
route.pool_key.extension
|
|
93595
|
+
).toBigInt()
|
|
93321
93596
|
},
|
|
93322
|
-
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93323
|
-
|
|
93597
|
+
sqrt_ratio_limit: uint256_exports.bnToUint256(
|
|
93598
|
+
route.sqrt_ratio_limit.toWei()
|
|
93599
|
+
),
|
|
93600
|
+
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
93324
93601
|
})),
|
|
93325
93602
|
token_amount: {
|
|
93326
93603
|
token: swap.token_amount.token.toBigInt(),
|
|
93327
93604
|
amount: swap.token_amount.amount.toI129()
|
|
93328
93605
|
}
|
|
93329
93606
|
})),
|
|
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
|
-
} })
|
|
93607
|
+
withdraw_swap_limit_amount: BigInt(
|
|
93608
|
+
_params.withdraw_swap_limit_amount.toWei()
|
|
93609
|
+
),
|
|
93610
|
+
withdraw_swap_weights: _params.withdraw_swap_weights.map(
|
|
93611
|
+
(weight) => BigInt(weight.toWei())
|
|
93612
|
+
),
|
|
93613
|
+
close_position: _params.close_position
|
|
93614
|
+
}
|
|
93615
|
+
})
|
|
93383
93616
|
};
|
|
93384
93617
|
}
|
|
93385
93618
|
async getHealthFactor() {
|
|
@@ -93388,11 +93621,15 @@ spurious results.`);
|
|
|
93388
93621
|
}
|
|
93389
93622
|
async getNetAPY() {
|
|
93390
93623
|
const positions = await this.getPositions();
|
|
93391
|
-
logger2.verbose(
|
|
93624
|
+
logger2.verbose(
|
|
93625
|
+
`${this.name}::getNetAPY: positions: ${JSON.stringify(positions)}`
|
|
93626
|
+
);
|
|
93392
93627
|
const allZero = positions.every((p) => p.usdValue === 0);
|
|
93393
93628
|
if (allZero) {
|
|
93394
93629
|
const collateralUSD = 1e3;
|
|
93395
|
-
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
93630
|
+
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
93631
|
+
this.config.networkConfig
|
|
93632
|
+
);
|
|
93396
93633
|
const targetHF = this.config.targetHealthFactor;
|
|
93397
93634
|
const maxDebt = HealthFactorMath.getMaxDebtAmountOnLooping(
|
|
93398
93635
|
new Web3Number(collateralUSD, this.config.collateral.decimals),
|
|
@@ -93426,12 +93663,17 @@ spurious results.`);
|
|
|
93426
93663
|
timeout: this.config.extendedTimeout,
|
|
93427
93664
|
retries: this.config.extendedRetries
|
|
93428
93665
|
});
|
|
93666
|
+
this.minimumExtendedMovementAmount = this.config.minimumExtendedMovementAmount ?? 5;
|
|
93429
93667
|
this.client = client;
|
|
93668
|
+
this.retryDelayForOrderStatus = this.config.retryDelayForOrderStatus ?? 3e3;
|
|
93430
93669
|
}
|
|
93431
93670
|
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
93432
93671
|
async getAPY(supportedPosition) {
|
|
93433
93672
|
const side = supportedPosition.isDebt ? "LONG" : "SHORT";
|
|
93434
|
-
const fundingRates = await this.client.getFundingRates(
|
|
93673
|
+
const fundingRates = await this.client.getFundingRates(
|
|
93674
|
+
this.config.extendedMarketName,
|
|
93675
|
+
side
|
|
93676
|
+
);
|
|
93435
93677
|
if (fundingRates.status !== "OK") {
|
|
93436
93678
|
logger2.error("error getting funding rates", fundingRates);
|
|
93437
93679
|
return { apy: 0, type: "base" /* BASE */ };
|
|
@@ -93475,14 +93717,14 @@ spurious results.`);
|
|
|
93475
93717
|
});
|
|
93476
93718
|
}
|
|
93477
93719
|
_getDepositLeaf() {
|
|
93478
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
93720
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
93721
|
+
(token) => token.symbol === "USDCe"
|
|
93722
|
+
);
|
|
93479
93723
|
return [
|
|
93480
93724
|
{
|
|
93481
93725
|
target: this.config.supportedPositions[0].asset.address,
|
|
93482
93726
|
method: "approve",
|
|
93483
|
-
packedArguments: [
|
|
93484
|
-
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()
|
|
93485
|
-
],
|
|
93727
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
93486
93728
|
id: `extended_approve_${this.config.supportedPositions[0].asset.symbol}`,
|
|
93487
93729
|
sanitizer: AVNU_LEGACY_SANITIZER
|
|
93488
93730
|
},
|
|
@@ -93509,17 +93751,62 @@ spurious results.`);
|
|
|
93509
93751
|
}
|
|
93510
93752
|
];
|
|
93511
93753
|
}
|
|
93754
|
+
getSwapFromLegacyLeaf() {
|
|
93755
|
+
const leafConfigs = this._getSwapFromLegacyLeaf();
|
|
93756
|
+
const leaves = leafConfigs.map((config3) => {
|
|
93757
|
+
const { target, method, packedArguments, sanitizer, id } = config3;
|
|
93758
|
+
const leaf = this.constructSimpleLeafData(
|
|
93759
|
+
{
|
|
93760
|
+
id,
|
|
93761
|
+
target,
|
|
93762
|
+
method,
|
|
93763
|
+
packedArguments
|
|
93764
|
+
},
|
|
93765
|
+
sanitizer
|
|
93766
|
+
);
|
|
93767
|
+
return leaf;
|
|
93768
|
+
});
|
|
93769
|
+
return {
|
|
93770
|
+
leaves,
|
|
93771
|
+
callConstructor: this.getSwapFromLegacyCall.bind(
|
|
93772
|
+
this
|
|
93773
|
+
)
|
|
93774
|
+
};
|
|
93775
|
+
}
|
|
93776
|
+
_getSwapFromLegacyLeaf() {
|
|
93777
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
93778
|
+
(token) => token.symbol === "USDCe"
|
|
93779
|
+
);
|
|
93780
|
+
return [
|
|
93781
|
+
{
|
|
93782
|
+
target: usdceToken.address,
|
|
93783
|
+
method: "approve",
|
|
93784
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
93785
|
+
id: `extendedswaplegacyapprove_${usdceToken.symbol}`,
|
|
93786
|
+
sanitizer: AVNU_LEGACY_SANITIZER
|
|
93787
|
+
},
|
|
93788
|
+
{
|
|
93789
|
+
target: AVNU_EXCHANGE_FOR_LEGACY_USDC,
|
|
93790
|
+
method: "swap_to_new",
|
|
93791
|
+
packedArguments: [],
|
|
93792
|
+
id: `extended_swap_to_new_${usdceToken.symbol}`,
|
|
93793
|
+
sanitizer: AVNU_LEGACY_SANITIZER
|
|
93794
|
+
}
|
|
93795
|
+
];
|
|
93796
|
+
}
|
|
93512
93797
|
_getWithdrawLeaf() {
|
|
93513
93798
|
return [];
|
|
93514
93799
|
}
|
|
93515
93800
|
async getDepositCall(params) {
|
|
93516
93801
|
try {
|
|
93517
93802
|
const usdcToken = this.config.supportedPositions[0].asset;
|
|
93518
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
93519
|
-
|
|
93520
|
-
|
|
93803
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
93804
|
+
(token) => token.symbol === "USDCe"
|
|
93805
|
+
);
|
|
93806
|
+
const salt = Math.floor(Math.random() * 10 ** usdcToken.decimals);
|
|
93807
|
+
const amount = uint256_exports.bnToUint256(
|
|
93808
|
+
params.amount.multipliedBy(10).toWei()
|
|
93521
93809
|
);
|
|
93522
|
-
const amount = uint256_exports.bnToUint256(params.amount.multipliedBy(10).toWei());
|
|
93523
93810
|
const quotes = await this.config.avnuAdapter.getQuotesAvnu(
|
|
93524
93811
|
usdcToken.address.toString(),
|
|
93525
93812
|
usdceToken.address.toString(),
|
|
@@ -93532,7 +93819,9 @@ spurious results.`);
|
|
|
93532
93819
|
logger2.error("error getting quotes from avnu");
|
|
93533
93820
|
return [];
|
|
93534
93821
|
}
|
|
93535
|
-
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
93822
|
+
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
93823
|
+
quotes
|
|
93824
|
+
);
|
|
93536
93825
|
const swapCallData = getCalldata[0];
|
|
93537
93826
|
return [
|
|
93538
93827
|
{
|
|
@@ -93589,6 +93878,76 @@ spurious results.`);
|
|
|
93589
93878
|
return [];
|
|
93590
93879
|
}
|
|
93591
93880
|
}
|
|
93881
|
+
getProofsForFromLegacySwap(tree) {
|
|
93882
|
+
let proofGroups = [];
|
|
93883
|
+
const ids = this.getSwapFromLegacyLeaf().leaves.map((l) => l.readableId);
|
|
93884
|
+
for (const [i, v] of tree.entries()) {
|
|
93885
|
+
if (ids.includes(v.readableId)) {
|
|
93886
|
+
proofGroups.push(tree.getProof(i));
|
|
93887
|
+
}
|
|
93888
|
+
}
|
|
93889
|
+
if (proofGroups.length != ids.length) {
|
|
93890
|
+
throw new Error(`Not all proofs found for IDs: ${ids.join(", ")}`);
|
|
93891
|
+
}
|
|
93892
|
+
return {
|
|
93893
|
+
proofs: proofGroups,
|
|
93894
|
+
callConstructor: this.getSwapFromLegacyCall.bind(this)
|
|
93895
|
+
};
|
|
93896
|
+
}
|
|
93897
|
+
async getSwapFromLegacyCall(params) {
|
|
93898
|
+
try {
|
|
93899
|
+
const usdcToken = this.config.supportedPositions[0].asset;
|
|
93900
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
93901
|
+
(token) => token.symbol === "USDCe"
|
|
93902
|
+
);
|
|
93903
|
+
const amount = uint256_exports.bnToUint256(
|
|
93904
|
+
params.amount.multipliedBy(10).toWei()
|
|
93905
|
+
);
|
|
93906
|
+
const quotes = await this.config.avnuAdapter.getQuotesAvnu(
|
|
93907
|
+
usdceToken.address.toString(),
|
|
93908
|
+
usdcToken.address.toString(),
|
|
93909
|
+
params.amount.toNumber(),
|
|
93910
|
+
this.config.avnuAdapter.config.vaultAllocator.address.toString(),
|
|
93911
|
+
usdcToken.decimals,
|
|
93912
|
+
false
|
|
93913
|
+
);
|
|
93914
|
+
if (!quotes) {
|
|
93915
|
+
logger2.error("error getting quotes from avnu");
|
|
93916
|
+
return [];
|
|
93917
|
+
}
|
|
93918
|
+
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
93919
|
+
quotes
|
|
93920
|
+
);
|
|
93921
|
+
const swapCallData = getCalldata[0];
|
|
93922
|
+
return [
|
|
93923
|
+
{
|
|
93924
|
+
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
93925
|
+
call: {
|
|
93926
|
+
contractAddress: usdceToken.address,
|
|
93927
|
+
selector: hash_exports.getSelectorFromName("approve"),
|
|
93928
|
+
calldata: [
|
|
93929
|
+
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
|
|
93930
|
+
toBigInt3(amount.low.toString()),
|
|
93931
|
+
// amount low
|
|
93932
|
+
toBigInt3(amount.high.toString())
|
|
93933
|
+
// amount high
|
|
93934
|
+
]
|
|
93935
|
+
}
|
|
93936
|
+
},
|
|
93937
|
+
{
|
|
93938
|
+
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
93939
|
+
call: {
|
|
93940
|
+
contractAddress: AVNU_EXCHANGE_FOR_LEGACY_USDC,
|
|
93941
|
+
selector: hash_exports.getSelectorFromName("swap_to_new"),
|
|
93942
|
+
calldata: swapCallData
|
|
93943
|
+
}
|
|
93944
|
+
}
|
|
93945
|
+
];
|
|
93946
|
+
} catch (error2) {
|
|
93947
|
+
logger2.error(`Error creating Deposit Call: ${error2}`);
|
|
93948
|
+
return [];
|
|
93949
|
+
}
|
|
93950
|
+
}
|
|
93592
93951
|
//Swap wbtc to usdc
|
|
93593
93952
|
async getWithdrawCall(params) {
|
|
93594
93953
|
try {
|
|
@@ -93604,13 +93963,60 @@ spurious results.`);
|
|
|
93604
93963
|
async withdrawFromExtended(amount) {
|
|
93605
93964
|
try {
|
|
93606
93965
|
if (!this.client) {
|
|
93607
|
-
|
|
93966
|
+
logger2.error("Client not initialized");
|
|
93967
|
+
return false;
|
|
93608
93968
|
}
|
|
93609
|
-
|
|
93610
|
-
|
|
93611
|
-
|
|
93612
|
-
|
|
93969
|
+
if (amount.lessThanOrEqualTo(0)) {
|
|
93970
|
+
logger2.error(
|
|
93971
|
+
`Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
|
|
93972
|
+
);
|
|
93973
|
+
return false;
|
|
93974
|
+
}
|
|
93975
|
+
if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
|
|
93976
|
+
logger2.warn(
|
|
93977
|
+
`Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
|
|
93978
|
+
);
|
|
93979
|
+
return false;
|
|
93980
|
+
}
|
|
93981
|
+
const holdings = await this.getExtendedDepositAmount();
|
|
93982
|
+
if (!holdings) {
|
|
93983
|
+
logger2.error(
|
|
93984
|
+
"Cannot get holdings - unable to validate withdrawal amount"
|
|
93985
|
+
);
|
|
93986
|
+
return false;
|
|
93987
|
+
}
|
|
93988
|
+
const availableForWithdrawal = parseFloat(
|
|
93989
|
+
holdings.availableForWithdrawal
|
|
93990
|
+
);
|
|
93991
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
93992
|
+
logger2.error(
|
|
93993
|
+
`Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
93994
|
+
);
|
|
93995
|
+
return false;
|
|
93613
93996
|
}
|
|
93997
|
+
const withdrawalAmount = amount.toNumber();
|
|
93998
|
+
if (withdrawalAmount > availableForWithdrawal) {
|
|
93999
|
+
logger2.error(
|
|
94000
|
+
`Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
|
|
94001
|
+
);
|
|
94002
|
+
return false;
|
|
94003
|
+
}
|
|
94004
|
+
logger2.info(
|
|
94005
|
+
`Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
|
|
94006
|
+
);
|
|
94007
|
+
const withdrawalRequest = await this.client.withdrawUSDC(
|
|
94008
|
+
amount.toFixed(2)
|
|
94009
|
+
);
|
|
94010
|
+
if (withdrawalRequest.status === "OK") {
|
|
94011
|
+
const withdrawalStatus = await this.getDepositOrWithdrawalStatus(
|
|
94012
|
+
withdrawalRequest.data,
|
|
94013
|
+
"WITHDRAWAL" /* WITHDRAWAL */
|
|
94014
|
+
);
|
|
94015
|
+
return withdrawalStatus;
|
|
94016
|
+
}
|
|
94017
|
+
logger2.error(
|
|
94018
|
+
`Withdrawal request failed with status: ${withdrawalRequest.status}`
|
|
94019
|
+
);
|
|
93614
94020
|
return false;
|
|
93615
94021
|
} catch (error2) {
|
|
93616
94022
|
logger2.error(`Error creating Withdraw Call: ${error2}`);
|
|
@@ -93621,21 +94027,44 @@ spurious results.`);
|
|
|
93621
94027
|
return Promise.resolve(1);
|
|
93622
94028
|
}
|
|
93623
94029
|
async getExtendedDepositAmount() {
|
|
93624
|
-
|
|
93625
|
-
|
|
93626
|
-
|
|
93627
|
-
|
|
93628
|
-
|
|
93629
|
-
|
|
93630
|
-
|
|
93631
|
-
|
|
93632
|
-
|
|
93633
|
-
|
|
93634
|
-
|
|
93635
|
-
|
|
94030
|
+
try {
|
|
94031
|
+
if (this.client === null) {
|
|
94032
|
+
logger2.error("error initializing client - client is null");
|
|
94033
|
+
return void 0;
|
|
94034
|
+
}
|
|
94035
|
+
const result2 = await this.client.getHoldings();
|
|
94036
|
+
if (!result2) {
|
|
94037
|
+
logger2.error("error getting holdings - API returned null/undefined");
|
|
94038
|
+
return void 0;
|
|
94039
|
+
}
|
|
94040
|
+
if (result2.status && result2.status !== "OK") {
|
|
94041
|
+
logger2.error(
|
|
94042
|
+
`error getting holdings - API returned status: ${result2.status}`
|
|
94043
|
+
);
|
|
94044
|
+
return void 0;
|
|
94045
|
+
}
|
|
94046
|
+
const holdings = result2.data;
|
|
94047
|
+
if (!holdings) {
|
|
94048
|
+
logger2.warn(
|
|
94049
|
+
"holdings data is null/undefined - treating as zero balance"
|
|
94050
|
+
);
|
|
94051
|
+
return {
|
|
94052
|
+
collateral_name: "",
|
|
94053
|
+
balance: "0",
|
|
94054
|
+
equity: "0",
|
|
94055
|
+
availableForTrade: "0",
|
|
94056
|
+
availableForWithdrawal: "0",
|
|
94057
|
+
unrealisedPnl: "0",
|
|
94058
|
+
initialMargin: "0",
|
|
94059
|
+
marginRatio: "0",
|
|
94060
|
+
updatedTime: Date.now()
|
|
94061
|
+
};
|
|
94062
|
+
}
|
|
94063
|
+
return holdings;
|
|
94064
|
+
} catch (error2) {
|
|
94065
|
+
logger2.error(`error getting holdings - exception: ${error2}`);
|
|
93636
94066
|
return void 0;
|
|
93637
94067
|
}
|
|
93638
|
-
return holdings;
|
|
93639
94068
|
}
|
|
93640
94069
|
async setLeverage(leverage, marketName) {
|
|
93641
94070
|
if (this.client === null) {
|
|
@@ -93677,21 +94106,24 @@ spurious results.`);
|
|
|
93677
94106
|
return result2.data;
|
|
93678
94107
|
}
|
|
93679
94108
|
async getOrderStatus(orderId, marketName) {
|
|
93680
|
-
|
|
93681
|
-
|
|
93682
|
-
|
|
93683
|
-
|
|
93684
|
-
|
|
93685
|
-
|
|
93686
|
-
|
|
94109
|
+
try {
|
|
94110
|
+
if (this.client === null) {
|
|
94111
|
+
logger2.error("error initializing client");
|
|
94112
|
+
return null;
|
|
94113
|
+
}
|
|
94114
|
+
const orderhistory = await this.getOrderHistory(marketName);
|
|
94115
|
+
if (!orderhistory || orderhistory.length === 0) {
|
|
94116
|
+
return null;
|
|
94117
|
+
}
|
|
94118
|
+
const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
|
|
94119
|
+
if (order) {
|
|
94120
|
+
return order;
|
|
94121
|
+
}
|
|
93687
94122
|
return null;
|
|
93688
|
-
}
|
|
93689
|
-
|
|
93690
|
-
if (!order) {
|
|
93691
|
-
logger2.error(`error getting order: ${order}`);
|
|
94123
|
+
} catch (error2) {
|
|
94124
|
+
logger2.error(`error getting order status: ${error2}`);
|
|
93692
94125
|
return null;
|
|
93693
94126
|
}
|
|
93694
|
-
return order;
|
|
93695
94127
|
}
|
|
93696
94128
|
async fetchOrderBookBTCUSDC() {
|
|
93697
94129
|
try {
|
|
@@ -93742,14 +94174,40 @@ spurious results.`);
|
|
|
93742
94174
|
logger2.error("error depositing or setting leverage");
|
|
93743
94175
|
return null;
|
|
93744
94176
|
}
|
|
93745
|
-
const
|
|
93746
|
-
if (
|
|
94177
|
+
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
94178
|
+
if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
|
|
94179
|
+
logger2.error(
|
|
94180
|
+
`Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
|
|
94181
|
+
);
|
|
93747
94182
|
return null;
|
|
93748
94183
|
}
|
|
93749
|
-
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
93750
94184
|
const spread3 = ask.minus(bid);
|
|
93751
|
-
|
|
93752
|
-
|
|
94185
|
+
const midPrice = ask.plus(bid).div(2);
|
|
94186
|
+
const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
|
|
94187
|
+
const priceAdjustmentMultiplier = Math.min(
|
|
94188
|
+
0.2 * attempt,
|
|
94189
|
+
MAX_PRICE_DEVIATION_MULTIPLIER
|
|
94190
|
+
);
|
|
94191
|
+
const priceAdjustment = spread3.times(priceAdjustmentMultiplier);
|
|
94192
|
+
let price = midPrice;
|
|
94193
|
+
if (side === "SELL" /* SELL */) {
|
|
94194
|
+
price = midPrice.minus(priceAdjustment);
|
|
94195
|
+
} else {
|
|
94196
|
+
price = midPrice.plus(priceAdjustment);
|
|
94197
|
+
}
|
|
94198
|
+
const maxDeviation = midPrice.times(0.5);
|
|
94199
|
+
if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
|
|
94200
|
+
logger2.error(
|
|
94201
|
+
`Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
|
|
94202
|
+
);
|
|
94203
|
+
if (attempt >= maxAttempts) {
|
|
94204
|
+
return null;
|
|
94205
|
+
}
|
|
94206
|
+
price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
|
|
94207
|
+
}
|
|
94208
|
+
logger2.info(
|
|
94209
|
+
`createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
|
|
94210
|
+
);
|
|
93753
94211
|
const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
|
|
93754
94212
|
this.config.extendedPrecision
|
|
93755
94213
|
);
|
|
@@ -93760,14 +94218,57 @@ spurious results.`);
|
|
|
93760
94218
|
price.toFixed(0),
|
|
93761
94219
|
side
|
|
93762
94220
|
);
|
|
93763
|
-
if (!result2) {
|
|
94221
|
+
if (!result2 || !result2.position_id) {
|
|
94222
|
+
logger2.error("Failed to create order - no position_id returned");
|
|
93764
94223
|
return null;
|
|
93765
94224
|
}
|
|
93766
|
-
|
|
93767
|
-
|
|
93768
|
-
|
|
94225
|
+
const positionId = result2.position_id;
|
|
94226
|
+
logger2.info(
|
|
94227
|
+
`Order created with position_id: ${positionId}. Waiting for API to update...`
|
|
94228
|
+
);
|
|
94229
|
+
let openOrder = await this.getOrderStatus(
|
|
94230
|
+
positionId,
|
|
94231
|
+
this.config.extendedMarketName
|
|
94232
|
+
);
|
|
94233
|
+
const maxStatusRetries = 3;
|
|
94234
|
+
const statusRetryDelay = 5e3;
|
|
94235
|
+
if (!openOrder) {
|
|
94236
|
+
logger2.warn(
|
|
94237
|
+
`Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
|
|
94238
|
+
);
|
|
94239
|
+
for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
|
|
94240
|
+
await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
|
|
94241
|
+
openOrder = await this.getOrderStatus(
|
|
94242
|
+
positionId,
|
|
94243
|
+
this.config.extendedMarketName
|
|
94244
|
+
);
|
|
94245
|
+
if (openOrder) {
|
|
94246
|
+
logger2.info(
|
|
94247
|
+
`Order ${positionId} found after ${statusRetry} status retry(ies)`
|
|
94248
|
+
);
|
|
94249
|
+
break;
|
|
94250
|
+
}
|
|
94251
|
+
logger2.warn(
|
|
94252
|
+
`Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
|
|
94253
|
+
);
|
|
94254
|
+
}
|
|
94255
|
+
}
|
|
94256
|
+
if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
|
|
94257
|
+
logger2.info(
|
|
94258
|
+
`Order ${positionId} successfully filled with quantity ${openOrder.qty}`
|
|
94259
|
+
);
|
|
94260
|
+
return {
|
|
94261
|
+
position_id: positionId,
|
|
94262
|
+
btc_exposure: openOrder.qty
|
|
94263
|
+
};
|
|
94264
|
+
} else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
|
|
94265
|
+
logger2.warn(
|
|
94266
|
+
`Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
|
|
94267
|
+
);
|
|
93769
94268
|
if (attempt >= maxAttempts) {
|
|
93770
|
-
logger2.error(
|
|
94269
|
+
logger2.error(
|
|
94270
|
+
`Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
|
|
94271
|
+
);
|
|
93771
94272
|
return null;
|
|
93772
94273
|
} else {
|
|
93773
94274
|
const backoff = 2e3 * attempt;
|
|
@@ -93781,16 +94282,21 @@ spurious results.`);
|
|
|
93781
94282
|
);
|
|
93782
94283
|
}
|
|
93783
94284
|
} else {
|
|
94285
|
+
logger2.warn(
|
|
94286
|
+
`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.`
|
|
94287
|
+
);
|
|
93784
94288
|
return {
|
|
93785
|
-
position_id:
|
|
93786
|
-
btc_exposure:
|
|
94289
|
+
position_id: positionId,
|
|
94290
|
+
btc_exposure: amount_in_token
|
|
93787
94291
|
};
|
|
93788
94292
|
}
|
|
93789
94293
|
} catch (err2) {
|
|
93790
|
-
logger2.error(
|
|
94294
|
+
logger2.error(
|
|
94295
|
+
`createShortOrder failed on attempt ${attempt}: ${err2.message}`
|
|
94296
|
+
);
|
|
93791
94297
|
if (attempt < maxAttempts) {
|
|
93792
94298
|
const backoff = 1200 * attempt;
|
|
93793
|
-
|
|
94299
|
+
logger2.info(`Retrying after ${backoff}ms...`);
|
|
93794
94300
|
await new Promise((resolve) => setTimeout(resolve, backoff));
|
|
93795
94301
|
return this.createOrder(
|
|
93796
94302
|
leverage,
|
|
@@ -93821,34 +94327,106 @@ spurious results.`);
|
|
|
93821
94327
|
}
|
|
93822
94328
|
return null;
|
|
93823
94329
|
} catch (err2) {
|
|
93824
|
-
|
|
94330
|
+
logger2.error(`Error opening short extended position, ${err2}`);
|
|
93825
94331
|
return null;
|
|
93826
94332
|
}
|
|
93827
94333
|
}
|
|
93828
94334
|
async getDepositOrWithdrawalStatus(orderId, operationsType) {
|
|
93829
|
-
|
|
93830
|
-
|
|
93831
|
-
|
|
93832
|
-
|
|
93833
|
-
|
|
93834
|
-
|
|
93835
|
-
|
|
93836
|
-
|
|
93837
|
-
if (
|
|
93838
|
-
|
|
94335
|
+
const maxAttempts = 15;
|
|
94336
|
+
const retryDelayMs = 3e4;
|
|
94337
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
94338
|
+
try {
|
|
94339
|
+
let transferHistory = await this.client.getAssetOperations({
|
|
94340
|
+
operationsType: [operationsType],
|
|
94341
|
+
operationsStatus: ["COMPLETED" /* COMPLETED */]
|
|
94342
|
+
});
|
|
94343
|
+
if (operationsType === "DEPOSIT" /* DEPOSIT */) {
|
|
94344
|
+
const myTransferStatus = transferHistory.data.find(
|
|
94345
|
+
(operation) => operation.transactionHash === orderId
|
|
94346
|
+
);
|
|
94347
|
+
if (!myTransferStatus) {
|
|
94348
|
+
if (attempt < maxAttempts) {
|
|
94349
|
+
logger2.info(
|
|
94350
|
+
`Deposit operation not found for transactionHash ${orderId}, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
94351
|
+
);
|
|
94352
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
94353
|
+
continue;
|
|
94354
|
+
}
|
|
94355
|
+
logger2.warn(
|
|
94356
|
+
`Deposit operation not found for transactionHash ${orderId} after ${maxAttempts} attempts`
|
|
94357
|
+
);
|
|
94358
|
+
return false;
|
|
94359
|
+
}
|
|
94360
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
94361
|
+
logger2.info(
|
|
94362
|
+
`Deposit operation ${orderId} completed successfully`
|
|
94363
|
+
);
|
|
94364
|
+
return true;
|
|
94365
|
+
} else {
|
|
94366
|
+
if (attempt < maxAttempts) {
|
|
94367
|
+
logger2.info(
|
|
94368
|
+
`Deposit operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
94369
|
+
);
|
|
94370
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
94371
|
+
continue;
|
|
94372
|
+
}
|
|
94373
|
+
logger2.warn(
|
|
94374
|
+
`Deposit operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
94375
|
+
);
|
|
94376
|
+
return false;
|
|
94377
|
+
}
|
|
94378
|
+
} else {
|
|
94379
|
+
const myTransferStatus = transferHistory.data.find(
|
|
94380
|
+
(operation) => operation.id === orderId.toString()
|
|
94381
|
+
);
|
|
94382
|
+
if (!myTransferStatus) {
|
|
94383
|
+
if (attempt < maxAttempts) {
|
|
94384
|
+
logger2.info(
|
|
94385
|
+
`Withdrawal status not found for orderId ${orderId} in completed operations, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
94386
|
+
);
|
|
94387
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
94388
|
+
continue;
|
|
94389
|
+
}
|
|
94390
|
+
logger2.warn(
|
|
94391
|
+
`Withdrawal operation not found for orderId ${orderId} after ${maxAttempts} attempts`
|
|
94392
|
+
);
|
|
94393
|
+
return false;
|
|
94394
|
+
}
|
|
94395
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
94396
|
+
logger2.info(
|
|
94397
|
+
`Withdrawal operation ${orderId} completed successfully`
|
|
94398
|
+
);
|
|
94399
|
+
return true;
|
|
94400
|
+
} else {
|
|
94401
|
+
if (attempt < maxAttempts) {
|
|
94402
|
+
logger2.info(
|
|
94403
|
+
`Withdrawal operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
94404
|
+
);
|
|
94405
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
94406
|
+
continue;
|
|
94407
|
+
}
|
|
94408
|
+
logger2.warn(
|
|
94409
|
+
`Withdrawal operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
94410
|
+
);
|
|
94411
|
+
return false;
|
|
94412
|
+
}
|
|
93839
94413
|
}
|
|
93840
|
-
|
|
93841
|
-
|
|
93842
|
-
|
|
93843
|
-
|
|
93844
|
-
|
|
94414
|
+
} catch (err2) {
|
|
94415
|
+
logger2.error(
|
|
94416
|
+
`error getting deposit or withdrawal status (attempt ${attempt}/${maxAttempts}): ${err2}`
|
|
94417
|
+
);
|
|
94418
|
+
if (attempt < maxAttempts) {
|
|
94419
|
+
logger2.info(`Retrying after ${retryDelayMs}ms...`);
|
|
94420
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
94421
|
+
continue;
|
|
93845
94422
|
}
|
|
93846
|
-
|
|
94423
|
+
logger2.error(
|
|
94424
|
+
`Max retry attempts reached for getDepositOrWithdrawalStatus`
|
|
94425
|
+
);
|
|
94426
|
+
return false;
|
|
93847
94427
|
}
|
|
93848
|
-
} catch (err2) {
|
|
93849
|
-
logger2.error(`error getting deposit or withdrawal status: ${err2}`);
|
|
93850
|
-
return false;
|
|
93851
94428
|
}
|
|
94429
|
+
return false;
|
|
93852
94430
|
}
|
|
93853
94431
|
};
|
|
93854
94432
|
|
|
@@ -93934,6 +94512,11 @@ spurious results.`);
|
|
|
93934
94512
|
AUMTypes2["DEFISPRING"] = "defispring";
|
|
93935
94513
|
return AUMTypes2;
|
|
93936
94514
|
})(AUMTypes || {});
|
|
94515
|
+
var PositionTypeAvnuExtended = /* @__PURE__ */ ((PositionTypeAvnuExtended2) => {
|
|
94516
|
+
PositionTypeAvnuExtended2["OPEN"] = "open";
|
|
94517
|
+
PositionTypeAvnuExtended2["CLOSE"] = "close";
|
|
94518
|
+
return PositionTypeAvnuExtended2;
|
|
94519
|
+
})(PositionTypeAvnuExtended || {});
|
|
93937
94520
|
var UNIVERSAL_MANAGE_IDS = /* @__PURE__ */ ((UNIVERSAL_MANAGE_IDS2) => {
|
|
93938
94521
|
UNIVERSAL_MANAGE_IDS2["FLASH_LOAN"] = "flash_loan_init";
|
|
93939
94522
|
UNIVERSAL_MANAGE_IDS2["VESU_LEG1"] = "vesu_leg1";
|
|
@@ -97111,7 +97694,8 @@ spurious results.`);
|
|
|
97111
97694
|
minHealthFactor: vaultSettings.minHealthFactor,
|
|
97112
97695
|
quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
|
|
97113
97696
|
...baseAdapterConfig,
|
|
97114
|
-
supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }]
|
|
97697
|
+
supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
|
|
97698
|
+
minimumVesuMovementAmount: 0
|
|
97115
97699
|
}));
|
|
97116
97700
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
97117
97701
|
...baseAdapterConfig
|
|
@@ -97425,7 +98009,7 @@ spurious results.`);
|
|
|
97425
98009
|
packedArguments: [
|
|
97426
98010
|
fromToken.address.toBigInt(),
|
|
97427
98011
|
//wbtc
|
|
97428
|
-
|
|
98012
|
+
toToken.address.toBigInt(),
|
|
97429
98013
|
//usdc
|
|
97430
98014
|
vaultAllocator.toBigInt()
|
|
97431
98015
|
],
|
|
@@ -97439,13 +98023,11 @@ spurious results.`);
|
|
|
97439
98023
|
}
|
|
97440
98024
|
async getDepositCall(params) {
|
|
97441
98025
|
try {
|
|
97442
|
-
console.log("params.amount", params.amount);
|
|
97443
98026
|
const fromToken = this.config.supportedPositions[0].asset;
|
|
97444
98027
|
const toToken = this.config.supportedPositions[1].asset;
|
|
97445
98028
|
const vaultAllocator = ContractAddr.from(
|
|
97446
98029
|
this.config.vaultAllocator.address
|
|
97447
98030
|
);
|
|
97448
|
-
console.log("vaultAllocator", vaultAllocator);
|
|
97449
98031
|
const quote = await this.getQuotesAvnu(
|
|
97450
98032
|
fromToken.address.toString(),
|
|
97451
98033
|
toToken.address.toString(),
|
|
@@ -97501,7 +98083,6 @@ spurious results.`);
|
|
|
97501
98083
|
const vaultAllocator = ContractAddr.from(
|
|
97502
98084
|
this.config.vaultAllocator.address
|
|
97503
98085
|
);
|
|
97504
|
-
console.log("params.amount", params.amount);
|
|
97505
98086
|
const quote = await this.getQuotesAvnu(
|
|
97506
98087
|
fromToken.address.toString(),
|
|
97507
98088
|
toToken.address.toString(),
|
|
@@ -97520,8 +98101,6 @@ spurious results.`);
|
|
|
97520
98101
|
);
|
|
97521
98102
|
const swapCallData = getCalldata[0];
|
|
97522
98103
|
const amount = uint256_exports.bnToUint256(params.amount.toWei());
|
|
97523
|
-
console.log("amount", amount);
|
|
97524
|
-
console.log("swapCallData", swapCallData);
|
|
97525
98104
|
return [
|
|
97526
98105
|
{
|
|
97527
98106
|
sanitizer: SIMPLE_SANITIZER,
|
|
@@ -97575,7 +98154,7 @@ spurious results.`);
|
|
|
97575
98154
|
}
|
|
97576
98155
|
throw new Error("Failed to fetch quote after retries");
|
|
97577
98156
|
}
|
|
97578
|
-
async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance =
|
|
98157
|
+
async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance = 5e3) {
|
|
97579
98158
|
try {
|
|
97580
98159
|
const fromToken = this.config.supportedPositions[0].asset;
|
|
97581
98160
|
const toToken = this.config.supportedPositions[1].asset;
|
|
@@ -97596,14 +98175,12 @@ spurious results.`);
|
|
|
97596
98175
|
return dataObject2;
|
|
97597
98176
|
}
|
|
97598
98177
|
const btcPrice = await this.getPriceOfToken(toToken.address.toString());
|
|
97599
|
-
console.log("btcPrice", btcPrice);
|
|
97600
98178
|
if (!btcPrice) {
|
|
97601
98179
|
logger2.error(`error getting btc price: ${btcPrice}`);
|
|
97602
98180
|
return null;
|
|
97603
98181
|
}
|
|
97604
98182
|
const estimatedUsdcAmount = Math.floor(amount * btcPrice);
|
|
97605
98183
|
const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
|
|
97606
|
-
console.log("targetBtcBig", targetBtcBig);
|
|
97607
98184
|
let low = BigInt(
|
|
97608
98185
|
Math.floor(
|
|
97609
98186
|
estimatedUsdcAmount * 10 ** fromToken.decimals * 0.9
|
|
@@ -97706,6 +98283,23 @@ spurious results.`);
|
|
|
97706
98283
|
debtPrice
|
|
97707
98284
|
};
|
|
97708
98285
|
}
|
|
98286
|
+
async getUnusedBalanceUSDCE() {
|
|
98287
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
98288
|
+
(token) => token.symbol === "USDCe"
|
|
98289
|
+
);
|
|
98290
|
+
const balance = await new ERC20(this.config).balanceOf(
|
|
98291
|
+
usdceToken.address,
|
|
98292
|
+
WALLET_ADDRESS,
|
|
98293
|
+
usdceToken.decimals
|
|
98294
|
+
);
|
|
98295
|
+
const price = await this.pricer.getPrice(usdceToken.symbol);
|
|
98296
|
+
const usdValue = Number(balance.toFixed(usdceToken.decimals)) * price.price;
|
|
98297
|
+
return {
|
|
98298
|
+
tokenInfo: usdceToken,
|
|
98299
|
+
amount: balance,
|
|
98300
|
+
usdValue
|
|
98301
|
+
};
|
|
98302
|
+
}
|
|
97709
98303
|
async getUnusedBalanceWBTC() {
|
|
97710
98304
|
const collateralToken = this.metadata.additionalInfo.borrowable_assets[0];
|
|
97711
98305
|
const balance = await new ERC20(this.config).balanceOf(
|
|
@@ -97751,22 +98345,30 @@ spurious results.`);
|
|
|
97751
98345
|
}
|
|
97752
98346
|
return extendedAdapter.adapter;
|
|
97753
98347
|
}
|
|
97754
|
-
async moveAssetsToVaultAllocator(amount) {
|
|
98348
|
+
async moveAssetsToVaultAllocator(amount, extendedAdapter) {
|
|
97755
98349
|
try {
|
|
97756
|
-
const
|
|
97757
|
-
(token) => token.symbol === "
|
|
98350
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
98351
|
+
(token) => token.symbol === "USDCe"
|
|
97758
98352
|
);
|
|
97759
98353
|
const approveCall = new ERC20(this.config).approve(
|
|
97760
|
-
|
|
98354
|
+
usdceToken.address,
|
|
97761
98355
|
this.metadata.additionalInfo.vaultAllocator,
|
|
97762
98356
|
amount
|
|
97763
98357
|
);
|
|
97764
98358
|
const transferCall = new ERC20(this.config).transfer(
|
|
97765
|
-
|
|
98359
|
+
usdceToken.address,
|
|
97766
98360
|
this.metadata.additionalInfo.vaultAllocator,
|
|
97767
98361
|
amount
|
|
97768
98362
|
);
|
|
97769
|
-
|
|
98363
|
+
const proofsInfo = extendedAdapter.getProofsForFromLegacySwap(
|
|
98364
|
+
this.getMerkleTree()
|
|
98365
|
+
);
|
|
98366
|
+
const proofGroups = proofsInfo.proofs;
|
|
98367
|
+
const call = this.getManageCall(
|
|
98368
|
+
proofGroups,
|
|
98369
|
+
await proofsInfo.callConstructor({ amount })
|
|
98370
|
+
);
|
|
98371
|
+
return [approveCall, transferCall, call];
|
|
97770
98372
|
} catch (err2) {
|
|
97771
98373
|
logger2.error(`error moving assets to vault allocator: ${err2}`);
|
|
97772
98374
|
return [];
|
|
@@ -97774,11 +98376,27 @@ spurious results.`);
|
|
|
97774
98376
|
}
|
|
97775
98377
|
async shouldInvest() {
|
|
97776
98378
|
try {
|
|
98379
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
|
|
97777
98380
|
const vesuAdapter = await this.getVesuAdapter();
|
|
97778
98381
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
97779
|
-
|
|
98382
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
|
|
98383
|
+
if (!vesuAdapter) {
|
|
97780
98384
|
logger2.error(
|
|
97781
|
-
`
|
|
98385
|
+
`Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
98386
|
+
);
|
|
98387
|
+
return {
|
|
98388
|
+
shouldInvest: false,
|
|
98389
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98390
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98391
|
+
extendedLeverage: 0,
|
|
98392
|
+
collateralPrice: 0,
|
|
98393
|
+
debtPrice: 0,
|
|
98394
|
+
vesuLeverage: 0
|
|
98395
|
+
};
|
|
98396
|
+
}
|
|
98397
|
+
if (!extendedAdapter) {
|
|
98398
|
+
logger2.error(
|
|
98399
|
+
`Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
97782
98400
|
);
|
|
97783
98401
|
return {
|
|
97784
98402
|
shouldInvest: false,
|
|
@@ -97790,10 +98408,73 @@ spurious results.`);
|
|
|
97790
98408
|
vesuLeverage: 0
|
|
97791
98409
|
};
|
|
97792
98410
|
}
|
|
98411
|
+
if (!extendedAdapter.client) {
|
|
98412
|
+
logger2.error(
|
|
98413
|
+
`Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
|
|
98414
|
+
);
|
|
98415
|
+
return {
|
|
98416
|
+
shouldInvest: false,
|
|
98417
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98418
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98419
|
+
extendedLeverage: 0,
|
|
98420
|
+
collateralPrice: 0,
|
|
98421
|
+
debtPrice: 0,
|
|
98422
|
+
vesuLeverage: 0
|
|
98423
|
+
};
|
|
98424
|
+
}
|
|
98425
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
|
|
97793
98426
|
const balance = await this.getUnusedBalance();
|
|
98427
|
+
if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
|
|
98428
|
+
logger2.error(
|
|
98429
|
+
`Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
|
|
98430
|
+
);
|
|
98431
|
+
return {
|
|
98432
|
+
shouldInvest: false,
|
|
98433
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98434
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98435
|
+
extendedLeverage: 0,
|
|
98436
|
+
collateralPrice: 0,
|
|
98437
|
+
debtPrice: 0,
|
|
98438
|
+
vesuLeverage: 0
|
|
98439
|
+
};
|
|
98440
|
+
}
|
|
98441
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
|
|
97794
98442
|
const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
|
|
97795
|
-
|
|
97796
|
-
|
|
98443
|
+
if (usdcBalanceOnExtended) {
|
|
98444
|
+
const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
|
|
98445
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
98446
|
+
logger2.error(
|
|
98447
|
+
`Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
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
|
+
}
|
|
98460
|
+
const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
|
|
98461
|
+
const amountToInvestNumber = amountToInvest.toNumber();
|
|
98462
|
+
if (!Number.isFinite(amountToInvestNumber)) {
|
|
98463
|
+
logger2.error(
|
|
98464
|
+
`Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
|
|
98465
|
+
);
|
|
98466
|
+
return {
|
|
98467
|
+
shouldInvest: false,
|
|
98468
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98469
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98470
|
+
extendedLeverage: 0,
|
|
98471
|
+
collateralPrice: 0,
|
|
98472
|
+
debtPrice: 0,
|
|
98473
|
+
vesuLeverage: 0
|
|
98474
|
+
};
|
|
98475
|
+
}
|
|
98476
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
|
|
98477
|
+
if (amountToInvest.lessThan(LIMIT_BALANCE_VALUE)) {
|
|
97797
98478
|
return {
|
|
97798
98479
|
shouldInvest: false,
|
|
97799
98480
|
vesuAmount: new Web3Number(0, 0),
|
|
@@ -97822,6 +98503,34 @@ spurious results.`);
|
|
|
97822
98503
|
collateralPrice,
|
|
97823
98504
|
debtPrice
|
|
97824
98505
|
} = await this.getAssetPrices();
|
|
98506
|
+
if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
|
|
98507
|
+
logger2.error(
|
|
98508
|
+
`Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
|
|
98509
|
+
);
|
|
98510
|
+
return {
|
|
98511
|
+
shouldInvest: false,
|
|
98512
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98513
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98514
|
+
extendedLeverage: 0,
|
|
98515
|
+
collateralPrice: 0,
|
|
98516
|
+
debtPrice: 0,
|
|
98517
|
+
vesuLeverage: 0
|
|
98518
|
+
};
|
|
98519
|
+
}
|
|
98520
|
+
if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
|
|
98521
|
+
logger2.error(
|
|
98522
|
+
`Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
|
|
98523
|
+
);
|
|
98524
|
+
return {
|
|
98525
|
+
shouldInvest: false,
|
|
98526
|
+
vesuAmount: new Web3Number(0, 0),
|
|
98527
|
+
extendedAmount: new Web3Number(0, 0),
|
|
98528
|
+
extendedLeverage: 0,
|
|
98529
|
+
collateralPrice: 0,
|
|
98530
|
+
debtPrice: 0,
|
|
98531
|
+
vesuLeverage: 0
|
|
98532
|
+
};
|
|
98533
|
+
}
|
|
97825
98534
|
const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
|
|
97826
98535
|
amountToInvest.toNumber(),
|
|
97827
98536
|
extendedAdapter.client,
|
|
@@ -97845,6 +98554,7 @@ spurious results.`);
|
|
|
97845
98554
|
vesuLeverage: 0
|
|
97846
98555
|
};
|
|
97847
98556
|
}
|
|
98557
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`);
|
|
97848
98558
|
return {
|
|
97849
98559
|
shouldInvest: true,
|
|
97850
98560
|
vesuAmount: vesu_amount,
|
|
@@ -97871,18 +98581,48 @@ spurious results.`);
|
|
|
97871
98581
|
try {
|
|
97872
98582
|
const vesuAdapter = await this.getVesuAdapter();
|
|
97873
98583
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
97874
|
-
let calls = [];
|
|
97875
98584
|
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
|
|
97876
98585
|
logger2.error(
|
|
97877
98586
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
97878
98587
|
);
|
|
97879
|
-
return
|
|
98588
|
+
return [];
|
|
98589
|
+
}
|
|
98590
|
+
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
98591
|
+
if (!extendedHoldings) {
|
|
98592
|
+
logger2.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
98593
|
+
return [];
|
|
97880
98594
|
}
|
|
97881
|
-
|
|
97882
|
-
|
|
97883
|
-
|
|
98595
|
+
const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
|
|
98596
|
+
const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
|
|
98597
|
+
extendedHoldings.availableForWithdrawal
|
|
98598
|
+
);
|
|
98599
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
|
|
98600
|
+
let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
98601
|
+
let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
98602
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
98603
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
|
|
98604
|
+
}
|
|
98605
|
+
const extendedTargetAmount = extendedAmount.abs();
|
|
98606
|
+
let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
|
|
98607
|
+
if (extendedAmount.isNegative()) {
|
|
98608
|
+
projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
|
|
98609
|
+
}
|
|
98610
|
+
const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
|
|
98611
|
+
const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
|
|
98612
|
+
if (extendedAmountDifference.lessThan(0)) {
|
|
98613
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
|
|
98614
|
+
} else if (extendedAmountDifference.greaterThan(0)) {
|
|
98615
|
+
totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
|
|
98616
|
+
}
|
|
98617
|
+
const vesuTargetAmount = vesuAmount.abs();
|
|
98618
|
+
const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
|
|
98619
|
+
let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
|
|
98620
|
+
const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
|
|
98621
|
+
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()}`);
|
|
98622
|
+
let calls = [];
|
|
98623
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
97884
98624
|
try {
|
|
97885
|
-
const extendedCalls = await this.moveAssets(
|
|
98625
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
97886
98626
|
{
|
|
97887
98627
|
to: Protocols.VAULT.name,
|
|
97888
98628
|
from: Protocols.EXTENDED.name,
|
|
@@ -97891,14 +98631,18 @@ spurious results.`);
|
|
|
97891
98631
|
extendedAdapter,
|
|
97892
98632
|
vesuAdapter
|
|
97893
98633
|
);
|
|
97894
|
-
|
|
98634
|
+
if (extendedStatus) {
|
|
98635
|
+
calls.push(...extendedCalls);
|
|
98636
|
+
} else {
|
|
98637
|
+
return [];
|
|
98638
|
+
}
|
|
97895
98639
|
} catch (err2) {
|
|
97896
98640
|
logger2.error(`Failed moving assets to vault: ${err2}`);
|
|
97897
98641
|
}
|
|
97898
98642
|
}
|
|
97899
|
-
if (vesuAmount.
|
|
98643
|
+
if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
97900
98644
|
try {
|
|
97901
|
-
const vesuCalls = await this.moveAssets(
|
|
98645
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
97902
98646
|
{
|
|
97903
98647
|
to: Protocols.EXTENDED.name,
|
|
97904
98648
|
from: Protocols.VESU.name,
|
|
@@ -97908,49 +98652,83 @@ spurious results.`);
|
|
|
97908
98652
|
vesuAdapter
|
|
97909
98653
|
);
|
|
97910
98654
|
calls.push(...vesuCalls);
|
|
98655
|
+
if (!vesuStatus) {
|
|
98656
|
+
return [];
|
|
98657
|
+
}
|
|
97911
98658
|
} catch (err2) {
|
|
97912
98659
|
logger2.error(`Failed moving assets to vault: ${err2}`);
|
|
97913
98660
|
}
|
|
97914
98661
|
}
|
|
97915
|
-
|
|
97916
|
-
|
|
97917
|
-
|
|
97918
|
-
|
|
97919
|
-
|
|
97920
|
-
|
|
97921
|
-
|
|
97922
|
-
|
|
97923
|
-
|
|
97924
|
-
|
|
97925
|
-
|
|
97926
|
-
|
|
97927
|
-
{
|
|
97928
|
-
|
|
97929
|
-
|
|
97930
|
-
|
|
97931
|
-
|
|
97932
|
-
|
|
97933
|
-
|
|
97934
|
-
|
|
97935
|
-
|
|
97936
|
-
|
|
97937
|
-
|
|
98662
|
+
if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
98663
|
+
if (extendedAmountDifference.greaterThan(0)) {
|
|
98664
|
+
try {
|
|
98665
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
98666
|
+
{
|
|
98667
|
+
to: Protocols.EXTENDED.name,
|
|
98668
|
+
from: Protocols.VAULT.name,
|
|
98669
|
+
amount: extendedAmountDifference
|
|
98670
|
+
},
|
|
98671
|
+
extendedAdapter,
|
|
98672
|
+
vesuAdapter
|
|
98673
|
+
);
|
|
98674
|
+
if (extendedStatus) {
|
|
98675
|
+
calls.push(...extendedCalls);
|
|
98676
|
+
} else {
|
|
98677
|
+
logger2.error(`Failed to move assets to extended - operation returned false status`);
|
|
98678
|
+
return [];
|
|
98679
|
+
}
|
|
98680
|
+
} catch (err2) {
|
|
98681
|
+
logger2.error(`Failed moving assets to extended: ${err2}`);
|
|
98682
|
+
return [];
|
|
98683
|
+
}
|
|
98684
|
+
} else if (extendedAmountDifference.lessThan(0)) {
|
|
98685
|
+
try {
|
|
98686
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
98687
|
+
{
|
|
98688
|
+
to: Protocols.VAULT.name,
|
|
98689
|
+
from: Protocols.EXTENDED.name,
|
|
98690
|
+
amount: extendedAmountDifferenceAbs
|
|
98691
|
+
},
|
|
98692
|
+
extendedAdapter,
|
|
98693
|
+
vesuAdapter
|
|
98694
|
+
);
|
|
98695
|
+
if (extendedStatus) {
|
|
98696
|
+
calls.push(...extendedCalls);
|
|
98697
|
+
} else {
|
|
98698
|
+
logger2.error(`Failed to withdraw from extended - operation returned false status`);
|
|
98699
|
+
return [];
|
|
98700
|
+
}
|
|
98701
|
+
} catch (err2) {
|
|
98702
|
+
logger2.error(`Failed moving assets from extended to vault: ${err2}`);
|
|
98703
|
+
return [];
|
|
98704
|
+
}
|
|
97938
98705
|
}
|
|
97939
98706
|
}
|
|
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
|
|
98707
|
+
if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
98708
|
+
if (vesuAmountDifference.lessThanOrEqualTo(0)) {
|
|
98709
|
+
logger2.warn(
|
|
98710
|
+
`Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
|
|
97950
98711
|
);
|
|
97951
|
-
|
|
97952
|
-
|
|
97953
|
-
|
|
98712
|
+
} else {
|
|
98713
|
+
try {
|
|
98714
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
98715
|
+
{
|
|
98716
|
+
to: Protocols.VAULT.name,
|
|
98717
|
+
from: Protocols.EXTENDED.name,
|
|
98718
|
+
amount: vesuAmountDifference
|
|
98719
|
+
},
|
|
98720
|
+
extendedAdapter,
|
|
98721
|
+
vesuAdapter
|
|
98722
|
+
);
|
|
98723
|
+
if (!vesuStatus) {
|
|
98724
|
+
logger2.error(`Failed to move assets to vesu - operation returned false status`);
|
|
98725
|
+
return [];
|
|
98726
|
+
}
|
|
98727
|
+
calls.push(...vesuCalls);
|
|
98728
|
+
} catch (err2) {
|
|
98729
|
+
logger2.error(`Failed moving assets to vault: ${err2}`);
|
|
98730
|
+
return [];
|
|
98731
|
+
}
|
|
97954
98732
|
}
|
|
97955
98733
|
}
|
|
97956
98734
|
return calls;
|
|
@@ -97961,12 +98739,47 @@ spurious results.`);
|
|
|
97961
98739
|
}
|
|
97962
98740
|
async moveAssets(params, extendedAdapter, vesuAdapter) {
|
|
97963
98741
|
try {
|
|
98742
|
+
if (params.amount.lessThanOrEqualTo(0)) {
|
|
98743
|
+
logger2.error(
|
|
98744
|
+
`Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
|
|
98745
|
+
);
|
|
98746
|
+
return {
|
|
98747
|
+
calls: [],
|
|
98748
|
+
status: false
|
|
98749
|
+
};
|
|
98750
|
+
}
|
|
98751
|
+
const amountAbs = params.amount.abs();
|
|
98752
|
+
if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
|
|
98753
|
+
if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
98754
|
+
logger2.warn(
|
|
98755
|
+
`Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
|
|
98756
|
+
);
|
|
98757
|
+
return {
|
|
98758
|
+
calls: [],
|
|
98759
|
+
status: false
|
|
98760
|
+
};
|
|
98761
|
+
}
|
|
98762
|
+
}
|
|
98763
|
+
if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
|
|
98764
|
+
if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
|
|
98765
|
+
logger2.warn(
|
|
98766
|
+
`Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
|
|
98767
|
+
);
|
|
98768
|
+
return {
|
|
98769
|
+
calls: [],
|
|
98770
|
+
status: false
|
|
98771
|
+
};
|
|
98772
|
+
}
|
|
98773
|
+
}
|
|
97964
98774
|
const avnuAdapter = await this.getAvnuAdapter();
|
|
97965
98775
|
if (!avnuAdapter) {
|
|
97966
98776
|
logger2.error(`avnu adapter not found: ${avnuAdapter}`);
|
|
97967
|
-
return
|
|
98777
|
+
return {
|
|
98778
|
+
calls: [],
|
|
98779
|
+
status: false
|
|
98780
|
+
};
|
|
97968
98781
|
}
|
|
97969
|
-
logger2.info(
|
|
98782
|
+
logger2.info(`moveAssets params, ${JSON.stringify(params)}`);
|
|
97970
98783
|
const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
|
|
97971
98784
|
const {
|
|
97972
98785
|
collateralPrice
|
|
@@ -97983,21 +98796,78 @@ spurious results.`);
|
|
|
97983
98796
|
await proofsInfo.callConstructor({ amount: params.amount })
|
|
97984
98797
|
);
|
|
97985
98798
|
calls.push(call);
|
|
97986
|
-
return
|
|
98799
|
+
return {
|
|
98800
|
+
calls: [call],
|
|
98801
|
+
status: true
|
|
98802
|
+
};
|
|
97987
98803
|
} else if (params.to === Protocols.VAULT.name && params.from === Protocols.EXTENDED.name) {
|
|
98804
|
+
const extendedLeverage = calculateExtendedLevergae();
|
|
98805
|
+
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
98806
|
+
if (!extendedHoldings) {
|
|
98807
|
+
logger2.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
98808
|
+
return {
|
|
98809
|
+
calls: [],
|
|
98810
|
+
status: false
|
|
98811
|
+
};
|
|
98812
|
+
}
|
|
98813
|
+
const extendedHoldingAmount = new Web3Number(
|
|
98814
|
+
extendedHoldings.availableForWithdrawal,
|
|
98815
|
+
USDC_TOKEN_DECIMALS
|
|
98816
|
+
);
|
|
98817
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets extendedHoldingAmount: ${extendedHoldingAmount.toNumber()}`);
|
|
98818
|
+
if (params.amount.abs().greaterThan(extendedHoldingAmount)) {
|
|
98819
|
+
const leftAmountAfterWithdrawalAmountInAccount = params.amount.abs().minus(extendedHoldingAmount);
|
|
98820
|
+
logger2.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets leftAmountAfterWithdrawalAmountInAccount: ${leftAmountAfterWithdrawalAmountInAccount.toNumber()}`);
|
|
98821
|
+
const btcAmount = leftAmountAfterWithdrawalAmountInAccount.dividedBy(collateralPrice.price);
|
|
98822
|
+
const openLongPosition = btcAmount.multipliedBy(3).greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
|
|
98823
|
+
extendedLeverage.toString(),
|
|
98824
|
+
btcAmount.toNumber(),
|
|
98825
|
+
"BUY" /* BUY */
|
|
98826
|
+
) : await extendedAdapter.createOrder(
|
|
98827
|
+
extendedLeverage.toString(),
|
|
98828
|
+
35e-6,
|
|
98829
|
+
// just in case amount falls short then we need to create a withdrawal
|
|
98830
|
+
"BUY" /* BUY */
|
|
98831
|
+
);
|
|
98832
|
+
if (!openLongPosition) {
|
|
98833
|
+
logger2.error(`error opening long position: ${openLongPosition}`);
|
|
98834
|
+
}
|
|
98835
|
+
const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
98836
|
+
if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
|
|
98837
|
+
logger2.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
|
|
98838
|
+
return { calls: [], status: false };
|
|
98839
|
+
}
|
|
98840
|
+
}
|
|
97988
98841
|
const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
|
|
97989
98842
|
if (withdrawalFromExtended) {
|
|
97990
|
-
const
|
|
98843
|
+
const extendedHoldings2 = await extendedAdapter.getExtendedDepositAmount();
|
|
98844
|
+
logger2.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
|
|
98845
|
+
await new Promise((resolve) => setTimeout(resolve, 5e3));
|
|
98846
|
+
const calls = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
|
|
97991
98847
|
if (calls.length > 0) {
|
|
97992
|
-
return
|
|
98848
|
+
return {
|
|
98849
|
+
calls,
|
|
98850
|
+
status: true
|
|
98851
|
+
};
|
|
97993
98852
|
}
|
|
97994
98853
|
} else {
|
|
97995
98854
|
logger2.error("withdrawal from extended failed");
|
|
98855
|
+
return {
|
|
98856
|
+
calls: [],
|
|
98857
|
+
status: false
|
|
98858
|
+
};
|
|
97996
98859
|
}
|
|
97997
|
-
return [];
|
|
97998
98860
|
} else if (params.to === Protocols.VAULT.name && params.from === Protocols.VESU.name) {
|
|
98861
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
|
|
98862
|
+
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
98863
|
+
logger2.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
98864
|
+
return {
|
|
98865
|
+
calls: [],
|
|
98866
|
+
status: false
|
|
98867
|
+
};
|
|
98868
|
+
}
|
|
97999
98869
|
const vesuAmountInBTC = new Web3Number(
|
|
98000
|
-
params.amount.dividedBy(collateralPrice.price).
|
|
98870
|
+
params.amount.dividedBy(collateralPrice.price).toFixed(WBTC_TOKEN_DECIMALS),
|
|
98001
98871
|
collateralToken.decimals
|
|
98002
98872
|
);
|
|
98003
98873
|
const proofsInfo = vesuAdapter.getProofs(false, this.getMerkleTree());
|
|
@@ -98015,8 +98885,19 @@ spurious results.`);
|
|
|
98015
98885
|
await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
|
|
98016
98886
|
);
|
|
98017
98887
|
calls.push(swapCall);
|
|
98018
|
-
return
|
|
98888
|
+
return {
|
|
98889
|
+
calls,
|
|
98890
|
+
status: true
|
|
98891
|
+
};
|
|
98019
98892
|
} else if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VESU.name) {
|
|
98893
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
|
|
98894
|
+
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
98895
|
+
logger2.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
98896
|
+
return {
|
|
98897
|
+
calls: [],
|
|
98898
|
+
status: false
|
|
98899
|
+
};
|
|
98900
|
+
}
|
|
98020
98901
|
const vesuAmountInBTC = new Web3Number(
|
|
98021
98902
|
params.amount.dividedBy(collateralPrice.price).toNumber(),
|
|
98022
98903
|
collateralToken.decimals
|
|
@@ -98046,13 +98927,21 @@ spurious results.`);
|
|
|
98046
98927
|
await proofsInfoDeposit.callConstructor({ amount: params.amount })
|
|
98047
98928
|
);
|
|
98048
98929
|
calls.push(callDeposit);
|
|
98049
|
-
return
|
|
98930
|
+
return {
|
|
98931
|
+
calls,
|
|
98932
|
+
status: true
|
|
98933
|
+
};
|
|
98050
98934
|
}
|
|
98051
|
-
|
|
98052
|
-
|
|
98935
|
+
return {
|
|
98936
|
+
calls: [],
|
|
98937
|
+
status: false
|
|
98938
|
+
};
|
|
98053
98939
|
} catch (err2) {
|
|
98054
98940
|
logger2.error(`error moving assets: ${err2}`);
|
|
98055
|
-
return
|
|
98941
|
+
return {
|
|
98942
|
+
calls: [],
|
|
98943
|
+
status: false
|
|
98944
|
+
};
|
|
98056
98945
|
}
|
|
98057
98946
|
}
|
|
98058
98947
|
async handleDeposit() {
|
|
@@ -98072,7 +98961,7 @@ spurious results.`);
|
|
|
98072
98961
|
};
|
|
98073
98962
|
}
|
|
98074
98963
|
const extendedLeverage = calculateExtendedLevergae();
|
|
98075
|
-
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter);
|
|
98964
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "open" /* OPEN */);
|
|
98076
98965
|
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
98077
98966
|
logger2.error("price difference between avnu and extended doesn't fit the range");
|
|
98078
98967
|
return {
|
|
@@ -98089,6 +98978,7 @@ spurious results.`);
|
|
|
98089
98978
|
};
|
|
98090
98979
|
}
|
|
98091
98980
|
const extendedPositionValue = position.length > 0 ? parseFloat(position[0].value) : 0;
|
|
98981
|
+
const BUFFER_AMOUNT_IN_AVAILABLE_FOR_TRADE = BUFFER_USDC_IN_WITHDRAWAL;
|
|
98092
98982
|
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
98093
98983
|
if (!extendedHoldings) {
|
|
98094
98984
|
logger2.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
@@ -98107,12 +98997,11 @@ spurious results.`);
|
|
|
98107
98997
|
const { collateralPrice } = await this.getAssetPrices();
|
|
98108
98998
|
const { vesuAmountInBTC, extendedAmountInBTC } = calculateVesUPositionSizeGivenExtended(
|
|
98109
98999
|
extendedPositionValue,
|
|
98110
|
-
extendedHoldingAmount,
|
|
99000
|
+
extendedHoldingAmount.minus(BUFFER_AMOUNT_IN_AVAILABLE_FOR_TRADE),
|
|
98111
99001
|
collateralTokenAmount,
|
|
98112
99002
|
collateralPrice.price
|
|
98113
99003
|
);
|
|
98114
|
-
|
|
98115
|
-
console.log("extendedAmountInBTC", extendedAmountInBTC);
|
|
99004
|
+
logger2.info(`vesuAmountInBTC ${vesuAmountInBTC}, extendedAmountInBTC ${extendedAmountInBTC}`);
|
|
98116
99005
|
let calls = [];
|
|
98117
99006
|
if (vesuAmountInBTC.greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)) {
|
|
98118
99007
|
const proofsInfo = vesuAdapter.getProofs(true, this.getMerkleTree());
|
|
@@ -98125,7 +99014,6 @@ spurious results.`);
|
|
|
98125
99014
|
);
|
|
98126
99015
|
const { amount: wbtcAmountInVaultAllocator } = await this.getUnusedBalanceWBTC();
|
|
98127
99016
|
if (wbtcAmountInVaultAllocator.lessThan(vesuAmountInBTC)) {
|
|
98128
|
-
console.log("error wbtc amount in vault allocator is less than vesu amount in btc", wbtcAmountInVaultAllocator, vesuAmountInBTC);
|
|
98129
99017
|
const swapProofsInfo = avnuAdapter.getProofs(true, this.getMerkleTree());
|
|
98130
99018
|
const swapProofGroups = swapProofsInfo.proofs;
|
|
98131
99019
|
const swapCall = this.getManageCall(
|
|
@@ -98160,68 +99048,98 @@ spurious results.`);
|
|
|
98160
99048
|
extendedAmountInBTC: new Web3Number(0, 0),
|
|
98161
99049
|
calls: []
|
|
98162
99050
|
};
|
|
98163
|
-
;
|
|
98164
99051
|
}
|
|
98165
99052
|
}
|
|
98166
|
-
async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter) {
|
|
99053
|
+
async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, positionType) {
|
|
98167
99054
|
const {
|
|
98168
99055
|
ask,
|
|
98169
99056
|
bid
|
|
98170
99057
|
} = await extendedAdapter.fetchOrderBookBTCUSDC();
|
|
98171
99058
|
const price = ask.plus(bid).dividedBy(2);
|
|
98172
|
-
const btcToken = vesuAdapter.config.supportedPositions[
|
|
99059
|
+
const btcToken = vesuAdapter.config.supportedPositions[0].asset;
|
|
98173
99060
|
const btcPriceAvnu = await avnuAdapter.getPriceOfToken(btcToken.address.toString());
|
|
98174
99061
|
if (!btcPriceAvnu) {
|
|
98175
99062
|
logger2.error(`error getting btc price avnu: ${btcPriceAvnu}`);
|
|
98176
99063
|
return false;
|
|
98177
99064
|
}
|
|
98178
|
-
const priceDifference = price.minus(btcPriceAvnu).
|
|
98179
|
-
if (priceDifference
|
|
98180
|
-
return
|
|
99065
|
+
const priceDifference = new Web3Number(price.minus(btcPriceAvnu).toFixed(2), 0);
|
|
99066
|
+
if (priceDifference.isNegative()) {
|
|
99067
|
+
return false;
|
|
99068
|
+
}
|
|
99069
|
+
if (positionType === "open" /* OPEN */) {
|
|
99070
|
+
logger2.info(`price difference between avnu and extended for open position: ${priceDifference.toNumber()}, minimumExtendedPriceDifferenceForSwapOpen: ${avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen}`);
|
|
99071
|
+
const result2 = priceDifference.greaterThanOrEqualTo(avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen);
|
|
99072
|
+
logger2.info(`result: ${result2}`);
|
|
99073
|
+
return result2;
|
|
99074
|
+
} else {
|
|
99075
|
+
logger2.info(`price difference between avnu and extended for close position: ${priceDifference.toNumber()}, maximumExtendedPriceDifferenceForSwapClosing: ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
99076
|
+
const result2 = priceDifference.lessThanOrEqualTo(avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing);
|
|
99077
|
+
logger2.info(`result: ${result2}`);
|
|
99078
|
+
return result2;
|
|
98181
99079
|
}
|
|
98182
|
-
logger2.error(`price difference between avnu and extended doesn't fit the range, priceDifference: ${priceDifference}`);
|
|
98183
|
-
return false;
|
|
98184
99080
|
}
|
|
98185
99081
|
async handleWithdraw(amount) {
|
|
98186
99082
|
try {
|
|
98187
99083
|
const usdcBalanceVaultAllocator = await this.getUnusedBalance();
|
|
98188
|
-
const usdcBalanceDifference = amount.minus(usdcBalanceVaultAllocator.usdValue);
|
|
99084
|
+
const usdcBalanceDifference = amount.plus(BUFFER_USDC_IN_WITHDRAWAL).minus(usdcBalanceVaultAllocator.usdValue);
|
|
98189
99085
|
logger2.info(`usdcBalanceDifference, ${usdcBalanceDifference.toNumber()}`);
|
|
99086
|
+
let calls = [];
|
|
99087
|
+
let status = true;
|
|
98190
99088
|
if (usdcBalanceDifference.lessThan(0)) {
|
|
98191
|
-
const
|
|
98192
|
-
amount
|
|
99089
|
+
const withdrawCall2 = await this.getBringLiquidityCall({
|
|
99090
|
+
amount: usdcBalanceVaultAllocator.amount
|
|
98193
99091
|
});
|
|
98194
|
-
logger2.info("withdraw call",
|
|
98195
|
-
|
|
99092
|
+
logger2.info("withdraw call", withdrawCall2);
|
|
99093
|
+
calls.push(withdrawCall2);
|
|
99094
|
+
return {
|
|
99095
|
+
calls,
|
|
99096
|
+
status: true
|
|
99097
|
+
};
|
|
98196
99098
|
}
|
|
98197
99099
|
const vesuAdapter = await this.getVesuAdapter();
|
|
98198
99100
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
98199
99101
|
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
|
|
99102
|
+
status = false;
|
|
98200
99103
|
logger2.error(
|
|
98201
99104
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
98202
99105
|
);
|
|
98203
|
-
return
|
|
99106
|
+
return {
|
|
99107
|
+
calls,
|
|
99108
|
+
status
|
|
99109
|
+
};
|
|
98204
99110
|
}
|
|
98205
99111
|
const { collateralTokenAmount } = await vesuAdapter.vesuAdapter.getAssetPrices();
|
|
98206
99112
|
const {
|
|
98207
99113
|
collateralPrice
|
|
98208
99114
|
} = await this.getAssetPrices();
|
|
98209
99115
|
const extendedPositon = await extendedAdapter.getAllOpenPositions();
|
|
99116
|
+
if (!extendedPositon) {
|
|
99117
|
+
status = false;
|
|
99118
|
+
logger2.error("error getting extended position", extendedPositon);
|
|
99119
|
+
return {
|
|
99120
|
+
calls,
|
|
99121
|
+
status
|
|
99122
|
+
};
|
|
99123
|
+
}
|
|
98210
99124
|
const amountDistributionForWithdrawal = await calculateAmountDistributionForWithdrawal(
|
|
98211
|
-
|
|
99125
|
+
usdcBalanceDifference,
|
|
98212
99126
|
collateralPrice.price,
|
|
98213
99127
|
collateralTokenAmount,
|
|
98214
99128
|
extendedPositon
|
|
98215
99129
|
);
|
|
98216
99130
|
if (!amountDistributionForWithdrawal) {
|
|
99131
|
+
status = false;
|
|
98217
99132
|
logger2.error(
|
|
98218
99133
|
`error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
|
|
98219
99134
|
);
|
|
98220
|
-
return
|
|
99135
|
+
return {
|
|
99136
|
+
calls,
|
|
99137
|
+
status
|
|
99138
|
+
};
|
|
98221
99139
|
}
|
|
98222
99140
|
const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
|
|
98223
|
-
if (vesu_amount.greaterThan(0)) {
|
|
98224
|
-
const
|
|
99141
|
+
if (status && vesu_amount.greaterThan(0)) {
|
|
99142
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
98225
99143
|
{
|
|
98226
99144
|
amount: vesu_amount,
|
|
98227
99145
|
from: Protocols.VESU.name,
|
|
@@ -98230,10 +99148,11 @@ spurious results.`);
|
|
|
98230
99148
|
extendedAdapter,
|
|
98231
99149
|
vesuAdapter
|
|
98232
99150
|
);
|
|
98233
|
-
|
|
99151
|
+
status = vesuStatus;
|
|
99152
|
+
calls.push(...vesuCalls);
|
|
98234
99153
|
}
|
|
98235
|
-
if (extended_amount.greaterThan(0)) {
|
|
98236
|
-
const
|
|
99154
|
+
if (status && extended_amount.greaterThan(0)) {
|
|
99155
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
98237
99156
|
{
|
|
98238
99157
|
amount: extended_amount,
|
|
98239
99158
|
from: Protocols.EXTENDED.name,
|
|
@@ -98242,12 +99161,32 @@ spurious results.`);
|
|
|
98242
99161
|
extendedAdapter,
|
|
98243
99162
|
vesuAdapter
|
|
98244
99163
|
);
|
|
98245
|
-
|
|
99164
|
+
status = extendedStatus;
|
|
99165
|
+
if (status) {
|
|
99166
|
+
calls.push(...extendedCalls);
|
|
99167
|
+
} else {
|
|
99168
|
+
logger2.error("error moving assets to vault: extendedStatus: ${extendedStatus}");
|
|
99169
|
+
return {
|
|
99170
|
+
calls: [],
|
|
99171
|
+
status
|
|
99172
|
+
};
|
|
99173
|
+
}
|
|
98246
99174
|
}
|
|
98247
|
-
|
|
99175
|
+
const withdrawCall = await this.getBringLiquidityCall({
|
|
99176
|
+
amount
|
|
99177
|
+
});
|
|
99178
|
+
logger2.info("withdraw call", withdrawCall);
|
|
99179
|
+
calls.push(withdrawCall);
|
|
99180
|
+
return {
|
|
99181
|
+
calls,
|
|
99182
|
+
status
|
|
99183
|
+
};
|
|
98248
99184
|
} catch (err2) {
|
|
98249
99185
|
logger2.error(`error handling withdrawal: ${err2}`);
|
|
98250
|
-
return
|
|
99186
|
+
return {
|
|
99187
|
+
calls: [],
|
|
99188
|
+
status: false
|
|
99189
|
+
};
|
|
98251
99190
|
}
|
|
98252
99191
|
}
|
|
98253
99192
|
async getAUM() {
|
|
@@ -98295,7 +99234,7 @@ spurious results.`);
|
|
|
98295
99234
|
};
|
|
98296
99235
|
}
|
|
98297
99236
|
};
|
|
98298
|
-
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
|
|
99237
|
+
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
|
|
98299
99238
|
vaultSettings.leafAdapters = [];
|
|
98300
99239
|
const wbtcToken = Global.getDefaultTokens().find(
|
|
98301
99240
|
(token) => token.symbol === lstSymbol
|
|
@@ -98319,7 +99258,9 @@ spurious results.`);
|
|
|
98319
99258
|
...baseAdapterConfig,
|
|
98320
99259
|
avnuContract: AVNU_MIDDLEWARE,
|
|
98321
99260
|
slippage: 0.01,
|
|
98322
|
-
baseUrl: AVNU_QUOTE_URL
|
|
99261
|
+
baseUrl: AVNU_QUOTE_URL,
|
|
99262
|
+
minimumExtendedPriceDifferenceForSwapOpen,
|
|
99263
|
+
maximumExtendedPriceDifferenceForSwapClosing
|
|
98323
99264
|
});
|
|
98324
99265
|
const extendedAdapter = new ExtendedAdapter({
|
|
98325
99266
|
...baseAdapterConfig,
|
|
@@ -98335,7 +99276,10 @@ spurious results.`);
|
|
|
98335
99276
|
extendedBaseUrl: "https://api.starknet.extended.exchange",
|
|
98336
99277
|
extendedMarketName: "BTC-USD",
|
|
98337
99278
|
extendedPrecision: 5,
|
|
98338
|
-
avnuAdapter
|
|
99279
|
+
avnuAdapter,
|
|
99280
|
+
retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3e3,
|
|
99281
|
+
minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5
|
|
99282
|
+
//5 usdcs
|
|
98339
99283
|
});
|
|
98340
99284
|
const vesuMultiplyAdapter = new VesuMultiplyAdapter({
|
|
98341
99285
|
poolId: pool1,
|
|
@@ -98348,7 +99292,9 @@ spurious results.`);
|
|
|
98348
99292
|
supportedPositions: [
|
|
98349
99293
|
{ asset: wbtcToken, isDebt: false },
|
|
98350
99294
|
{ asset: usdcToken, isDebt: true }
|
|
98351
|
-
]
|
|
99295
|
+
],
|
|
99296
|
+
minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5
|
|
99297
|
+
//5 usdc
|
|
98352
99298
|
});
|
|
98353
99299
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
98354
99300
|
...baseAdapterConfig
|
|
@@ -98381,6 +99327,7 @@ spurious results.`);
|
|
|
98381
99327
|
() => vesuMultiplyAdapter.getWithdrawLeaf()
|
|
98382
99328
|
);
|
|
98383
99329
|
vaultSettings.leafAdapters.push(() => extendedAdapter.getDepositLeaf());
|
|
99330
|
+
vaultSettings.leafAdapters.push(() => extendedAdapter.getSwapFromLegacyLeaf());
|
|
98384
99331
|
vaultSettings.leafAdapters.push(() => avnuAdapter.getDepositLeaf());
|
|
98385
99332
|
vaultSettings.leafAdapters.push(() => avnuAdapter.getWithdrawLeaf());
|
|
98386
99333
|
vaultSettings.leafAdapters.push(
|
|
@@ -98443,11 +99390,11 @@ spurious results.`);
|
|
|
98443
99390
|
] });
|
|
98444
99391
|
}
|
|
98445
99392
|
var re7UsdcPrimeDevansh = {
|
|
98446
|
-
vaultAddress: ContractAddr.from("
|
|
98447
|
-
manager: ContractAddr.from("
|
|
98448
|
-
vaultAllocator: ContractAddr.from("
|
|
98449
|
-
redeemRequestNFT: ContractAddr.from("
|
|
98450
|
-
aumOracle: ContractAddr.from("
|
|
99393
|
+
vaultAddress: ContractAddr.from("0x7efaff77601813ca674c1ffe0479fc0361c0f5099f64a67d4793b80382750c2"),
|
|
99394
|
+
manager: ContractAddr.from("0x2579342f53fbf2f775b0c71d24f162aaf1d3e466edea09a6c51e77a95bd986d"),
|
|
99395
|
+
vaultAllocator: ContractAddr.from("0x46ee6073484a669631e8f88b9f357b0b073cee1bc47752fc32453dd6c1efd7b"),
|
|
99396
|
+
redeemRequestNFT: ContractAddr.from("0x1d66120b0a76068454ea36276d9f404b0a980083dcaebbf6d9f4ad154a79dbe"),
|
|
99397
|
+
aumOracle: ContractAddr.from("0x419a5e8b5a1fe5b2586e64409d5cfdb1712791aaa9361264730227563d4e140"),
|
|
98451
99398
|
leafAdapters: [],
|
|
98452
99399
|
adapters: [],
|
|
98453
99400
|
targetHealthFactor: 1.4,
|
|
@@ -98462,12 +99409,12 @@ spurious results.`);
|
|
|
98462
99409
|
borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
|
|
98463
99410
|
minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP
|
|
98464
99411
|
};
|
|
98465
|
-
var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended) => {
|
|
99412
|
+
var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) => {
|
|
98466
99413
|
return [
|
|
98467
|
-
getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended)
|
|
99414
|
+
getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing)
|
|
98468
99415
|
];
|
|
98469
99416
|
};
|
|
98470
|
-
function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
|
|
99417
|
+
function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
|
|
98471
99418
|
return {
|
|
98472
99419
|
name: `Extended Test ${underlyingSymbol}`,
|
|
98473
99420
|
description: getDescription2(lstSymbol, underlyingSymbol),
|
|
@@ -98475,7 +99422,7 @@ spurious results.`);
|
|
|
98475
99422
|
launchBlock: 0,
|
|
98476
99423
|
type: "Other",
|
|
98477
99424
|
depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol)],
|
|
98478
|
-
additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended),
|
|
99425
|
+
additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing),
|
|
98479
99426
|
risk: {
|
|
98480
99427
|
riskFactor: _riskFactor3,
|
|
98481
99428
|
netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
|