@strkfarm/sdk 2.0.0-dev.1 → 2.0.0-dev.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.global.js +1314 -384
- package/dist/index.browser.mjs +1314 -384
- package/dist/index.d.ts +48 -9
- package/dist/index.js +1315 -384
- package/dist/index.mjs +1314 -384
- package/package.json +1 -1
- package/src/dataTypes/address.ts +1 -1
- package/src/modules/ekubo-quoter.ts +1 -12
- package/src/strategies/universal-adapters/avnu-adapter.ts +11 -14
- package/src/strategies/universal-adapters/extended-adapter.ts +514 -86
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +790 -408
- package/src/strategies/universal-lst-muliplier-strategy.tsx +2 -1
- package/src/strategies/universal-strategy.tsx +5 -0
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +8 -2
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +3 -1
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +21 -25
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +533 -115
package/dist/index.mjs
CHANGED
|
@@ -4328,20 +4328,13 @@ var EkuboQuoter = class _EkuboQuoter {
|
|
|
4328
4328
|
async getDexPrice(baseToken, quoteToken, amount) {
|
|
4329
4329
|
const lstTokenInfo = baseToken;
|
|
4330
4330
|
const lstUnderlyingTokenInfo = quoteToken;
|
|
4331
|
-
console.log("lstTokenInfo", lstTokenInfo);
|
|
4332
|
-
console.log("lstUnderlyingTokenInfo", lstUnderlyingTokenInfo);
|
|
4333
|
-
console.log("amount", amount);
|
|
4334
4331
|
const quote = await this.getQuote(
|
|
4335
4332
|
lstTokenInfo.address.address,
|
|
4336
4333
|
lstUnderlyingTokenInfo.address.address,
|
|
4337
4334
|
amount
|
|
4338
4335
|
);
|
|
4339
|
-
console.log("quote", quote);
|
|
4340
4336
|
const outputAmount = Web3Number.fromWei(quote.total_calculated, lstUnderlyingTokenInfo.decimals);
|
|
4341
|
-
console.log("outputAmount", outputAmount);
|
|
4342
|
-
console.log("amount", amount);
|
|
4343
4337
|
const price = outputAmount.toNumber() / amount.toNumber();
|
|
4344
|
-
console.log("price", price);
|
|
4345
4338
|
logger.verbose(`${_EkuboQuoter.name}:: LST Dex Price: ${price}`);
|
|
4346
4339
|
return price;
|
|
4347
4340
|
}
|
|
@@ -4360,16 +4353,12 @@ var EkuboQuoter = class _EkuboQuoter {
|
|
|
4360
4353
|
// debt collateral
|
|
4361
4354
|
async getSwapLimitAmount(fromToken, toToken, amount, max_slippage = 2e-3) {
|
|
4362
4355
|
const isExactAmountIn = amount.greaterThanOrEqualTo(0);
|
|
4363
|
-
console.log("isExactAmountIn", isExactAmountIn);
|
|
4364
4356
|
logger.verbose(`${_EkuboQuoter.name}::getSwapLimitAmount isExactAmountIn: ${isExactAmountIn}, fromToken: ${fromToken.symbol}, toToken: ${toToken.symbol}, amount: ${amount}`);
|
|
4365
4357
|
const isYieldToken = this.tokenMarketData.isAPYSupported(toToken);
|
|
4366
4358
|
console.log("isYieldToken", isYieldToken);
|
|
4367
4359
|
const baseToken = isExactAmountIn ? toToken : fromToken;
|
|
4368
4360
|
const quoteToken = isExactAmountIn ? fromToken : toToken;
|
|
4369
|
-
console.log("baseToken", baseToken);
|
|
4370
|
-
console.log("quoteToken", quoteToken);
|
|
4371
4361
|
const dexPrice = await this.getDexPrice(baseToken, quoteToken, amount);
|
|
4372
|
-
console.log("dexPrice", dexPrice);
|
|
4373
4362
|
const trueExchangeRate = isYieldToken ? await this.tokenMarketData.getTruePrice(baseToken) : dexPrice;
|
|
4374
4363
|
console.log("trueExchangeRate", trueExchangeRate);
|
|
4375
4364
|
if (isExactAmountIn) {
|
|
@@ -28021,6 +28010,7 @@ var vesu_multiple_abi_default = [
|
|
|
28021
28010
|
var AVNU_API = "https://starknet.api.avnu.fi/swap/v2/quotes";
|
|
28022
28011
|
var USDC_TOKEN_DECIMALS = 6;
|
|
28023
28012
|
var USDC_TOKEN_ADDRESS = "0x053C91253BC9682c04929cA02ED00b3E423f6710D2ee7e0D5EBB06F3eCF368A8";
|
|
28013
|
+
var BUFFER_USDC_IN_WITHDRAWAL = 5;
|
|
28024
28014
|
var WBTC_TOKEN_ADDRESS = "0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac";
|
|
28025
28015
|
var WBTC_TOKEN_DECIMALS = 8;
|
|
28026
28016
|
var MAINTENANCE_MARGIN = 0.01;
|
|
@@ -28036,7 +28026,8 @@ var STRK_API_RPC = process.env.STRK_API_RPC ?? "https://mainnet.starknet.a5a.ch"
|
|
|
28036
28026
|
var MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
|
|
28037
28027
|
var MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
|
|
28038
28028
|
var EXTEND_MARKET_NAME = "BTC-USD";
|
|
28039
|
-
var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ??
|
|
28029
|
+
var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 0.05);
|
|
28030
|
+
var LIMIT_BALANCE_VALUE = 10;
|
|
28040
28031
|
var REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 18e4);
|
|
28041
28032
|
var WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18e6);
|
|
28042
28033
|
var INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 18e4);
|
|
@@ -28054,8 +28045,6 @@ var PRICE_MAX_SLIPPAGE_EKUBO = Number(process.env.PRICE_MAX_SLIPPAGE_EKUBO ?? 5e
|
|
|
28054
28045
|
var MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING = Number(process.env.MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING ?? 1);
|
|
28055
28046
|
var MINIMUM_EXTENDED_POSITION_SIZE = 1e-4;
|
|
28056
28047
|
var MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP = 1e-5;
|
|
28057
|
-
var MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = 700;
|
|
28058
|
-
var MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = -100;
|
|
28059
28048
|
|
|
28060
28049
|
// src/strategies/vesu-extended-strategy/utils/helper.ts
|
|
28061
28050
|
var returnFormattedAmount = (amount, toTokenDecimals) => {
|
|
@@ -28075,8 +28064,7 @@ var calculateAmountDistribution = async (amount, client, marketName, collateralP
|
|
|
28075
28064
|
vesu_leverage: 0
|
|
28076
28065
|
};
|
|
28077
28066
|
}
|
|
28078
|
-
const
|
|
28079
|
-
const extendedExposureUSD = extendedBTCExposure.multipliedBy(collateralPrice);
|
|
28067
|
+
const extendedExposureUSD = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].value, WBTC_TOKEN_DECIMALS) : new Web3Number(0, WBTC_TOKEN_DECIMALS);
|
|
28080
28068
|
const vesuBTCExposureUSD = collateralUnits.multipliedBy(collateralPrice);
|
|
28081
28069
|
const numerator1 = vesu_leverage * amount + vesuBTCExposureUSD.toNumber();
|
|
28082
28070
|
const numerator2 = extendedExposureUSD.toNumber();
|
|
@@ -28112,8 +28100,7 @@ var calculateAmountDistributionForWithdrawal = async (amountInUsdc, collateralPr
|
|
|
28112
28100
|
logger.error("error getting extended positions");
|
|
28113
28101
|
return null;
|
|
28114
28102
|
}
|
|
28115
|
-
const
|
|
28116
|
-
const extendedExposureUSD = extendedBTCExposure.multipliedBy(collateralPrice);
|
|
28103
|
+
const extendedExposureUSD = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].value, USDC_TOKEN_DECIMALS) : new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
28117
28104
|
const vesuExposureUSD = collateralUnits.multipliedBy(collateralPrice);
|
|
28118
28105
|
if (vesuExposureUSD.lessThan(0)) {
|
|
28119
28106
|
return {
|
|
@@ -28131,9 +28118,14 @@ var calculateAmountDistributionForWithdrawal = async (amountInUsdc, collateralPr
|
|
|
28131
28118
|
vesu_leverage
|
|
28132
28119
|
};
|
|
28133
28120
|
}
|
|
28121
|
+
console.log("the vesu exposure usd is", vesuExposureUSD.toNumber());
|
|
28122
|
+
console.log("the extended exposure usd is", extendedExposureUSD.toNumber());
|
|
28123
|
+
console.log("the amount in usdc is", amountInUsdc.toNumber());
|
|
28124
|
+
console.log("the extended leverage is", extended_leverage);
|
|
28125
|
+
console.log("the vesu leverage is", vesu_leverage);
|
|
28134
28126
|
const numerator1 = amountInUsdc.multipliedBy(extended_leverage);
|
|
28135
|
-
const numerator2 = vesuExposureUSD
|
|
28136
|
-
const numerator3 = extendedExposureUSD.multipliedBy(
|
|
28127
|
+
const numerator2 = vesuExposureUSD;
|
|
28128
|
+
const numerator3 = extendedExposureUSD.multipliedBy(-1);
|
|
28137
28129
|
const finalNumerator = numerator1.plus(numerator2).plus(numerator3);
|
|
28138
28130
|
const denominator = extended_leverage + vesu_leverage;
|
|
28139
28131
|
const vesuAmountInUSDC = finalNumerator.dividedBy(denominator);
|
|
@@ -28143,6 +28135,7 @@ var calculateAmountDistributionForWithdrawal = async (amountInUsdc, collateralPr
|
|
|
28143
28135
|
"the extended amount in usdc is",
|
|
28144
28136
|
extendedAmountInUSDC.toNumber()
|
|
28145
28137
|
);
|
|
28138
|
+
await new Promise((resolve) => setTimeout(resolve, 1e4));
|
|
28146
28139
|
return {
|
|
28147
28140
|
vesu_amount: vesuAmountInUSDC,
|
|
28148
28141
|
extended_amount: extendedAmountInUSDC,
|
|
@@ -28164,10 +28157,10 @@ var calculateExtendedLevergae = () => {
|
|
|
28164
28157
|
const extended_leverage_max = 1 / (MAINTENANCE_MARGIN + MAX_PRICE_DROP_PERCENTAGE);
|
|
28165
28158
|
return Math.floor(extended_leverage_max);
|
|
28166
28159
|
};
|
|
28167
|
-
var calculateDebtAmount = (collateralAmount, debtAmount, debtPrice, maxLtv =
|
|
28160
|
+
var calculateDebtAmount = (collateralAmount, debtAmount, debtPrice, maxLtv = MAX_LIQUIDATION_RATIO, addedAmount, collateralPrice, isDeposit) => {
|
|
28168
28161
|
try {
|
|
28169
|
-
const
|
|
28170
|
-
const numerator1 = collateralAmount.plus(
|
|
28162
|
+
const addedCollateral = addedAmount.multipliedBy(isDeposit ? 1 : -1);
|
|
28163
|
+
const numerator1 = collateralAmount.plus(addedCollateral).multipliedBy(collateralPrice).multipliedBy(maxLtv);
|
|
28171
28164
|
const numerator2 = debtAmount.multipliedBy(debtPrice).multipliedBy(TARGET_HF);
|
|
28172
28165
|
const denominator = TARGET_HF - maxLtv;
|
|
28173
28166
|
const x_debt_usd = numerator1.minus(numerator2).dividedBy(denominator);
|
|
@@ -28202,16 +28195,16 @@ var calculateAmountDepositOnExtendedWhenIncurringLosses = async (client) => {
|
|
|
28202
28195
|
const extendedHoldings = await client.getHoldings();
|
|
28203
28196
|
const extended_leverage = calculateExtendedLevergae();
|
|
28204
28197
|
const latestPosition = (await client.getPositions()).data.pop();
|
|
28205
|
-
console.log("the latest position is", latestPosition, extendedHoldings);
|
|
28206
28198
|
if (!extendedHoldings || !latestPosition) {
|
|
28207
28199
|
logger.error(`error getting extended position: extendedHoldings=${extendedHoldings}, latestPosition=${latestPosition}`);
|
|
28208
28200
|
return null;
|
|
28209
28201
|
}
|
|
28210
|
-
const positionValueInUSD = latestPosition.value;
|
|
28202
|
+
const positionValueInUSD = new Web3Number(latestPosition.value, USDC_TOKEN_DECIMALS);
|
|
28211
28203
|
const equity = extendedHoldings.data.equity;
|
|
28212
|
-
const deposit =
|
|
28213
|
-
return new Web3Number(
|
|
28204
|
+
const deposit = positionValueInUSD.dividedBy(extended_leverage).minus(equity).toFixed(2);
|
|
28205
|
+
return new Web3Number(deposit, USDC_TOKEN_DECIMALS);
|
|
28214
28206
|
} catch (err) {
|
|
28207
|
+
logger.error(`error calculating amount deposit on extended when incurring losses: ${err}`);
|
|
28215
28208
|
return null;
|
|
28216
28209
|
}
|
|
28217
28210
|
};
|
|
@@ -28289,21 +28282,36 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28289
28282
|
vaultAllocator: config.vaultAllocator,
|
|
28290
28283
|
id: ""
|
|
28291
28284
|
});
|
|
28292
|
-
this.
|
|
28285
|
+
this.minimumVesuMovementAmount = config.minimumVesuMovementAmount ?? 5;
|
|
28286
|
+
this.tokenMarketData = new TokenMarketData(
|
|
28287
|
+
this.config.pricer,
|
|
28288
|
+
this.config.networkConfig
|
|
28289
|
+
);
|
|
28293
28290
|
}
|
|
28294
28291
|
async getAPY(supportedPosition) {
|
|
28295
28292
|
const CACHE_KEY = `apy_${this.config.poolId.address}_${supportedPosition.asset.symbol}`;
|
|
28296
28293
|
const cacheData = this.getCache(CACHE_KEY);
|
|
28297
|
-
console.log(
|
|
28294
|
+
console.log(
|
|
28295
|
+
`${_VesuMultiplyAdapter.name}::getAPY cacheData: ${JSON.stringify(
|
|
28296
|
+
cacheData
|
|
28297
|
+
)}`,
|
|
28298
|
+
this.vesuAdapter.config.poolId.shortString(),
|
|
28299
|
+
this.vesuAdapter.config.collateral.symbol,
|
|
28300
|
+
this.vesuAdapter.config.debt.symbol
|
|
28301
|
+
);
|
|
28298
28302
|
if (cacheData) {
|
|
28299
28303
|
return cacheData;
|
|
28300
28304
|
}
|
|
28301
28305
|
try {
|
|
28302
28306
|
const allVesuPools = await VesuAdapter.getVesuPools();
|
|
28303
28307
|
const asset = supportedPosition.asset;
|
|
28304
|
-
const pool = allVesuPools.pools.find(
|
|
28308
|
+
const pool = allVesuPools.pools.find(
|
|
28309
|
+
(p) => this.vesuAdapter.config.poolId.eqString(num9.getHexString(p.id))
|
|
28310
|
+
);
|
|
28305
28311
|
if (!pool) {
|
|
28306
|
-
logger.warn(
|
|
28312
|
+
logger.warn(
|
|
28313
|
+
`VesuMultiplyAdapter: Pool not found for token ${asset.symbol}`
|
|
28314
|
+
);
|
|
28307
28315
|
return {
|
|
28308
28316
|
apy: 0,
|
|
28309
28317
|
type: "base" /* BASE */
|
|
@@ -28313,7 +28321,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28313
28321
|
(a) => a.symbol.toLowerCase() === asset.symbol.toLowerCase()
|
|
28314
28322
|
)?.stats;
|
|
28315
28323
|
if (!assetStats) {
|
|
28316
|
-
logger.warn(
|
|
28324
|
+
logger.warn(
|
|
28325
|
+
`VesuMultiplyAdapter: Asset stats not found for token ${asset.symbol}`
|
|
28326
|
+
);
|
|
28317
28327
|
return {
|
|
28318
28328
|
apy: 0,
|
|
28319
28329
|
type: "base" /* BASE */
|
|
@@ -28324,7 +28334,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28324
28334
|
apy = Number(assetStats.borrowApr?.value || 0) / 1e18;
|
|
28325
28335
|
} else {
|
|
28326
28336
|
const isAssetBTC = asset.symbol.toLowerCase().includes("btc");
|
|
28327
|
-
const baseAPY = Number(
|
|
28337
|
+
const baseAPY = Number(
|
|
28338
|
+
isAssetBTC ? assetStats.btcFiSupplyApr?.value + assetStats.supplyApy?.value : assetStats.supplyApy?.value || 0
|
|
28339
|
+
) / 1e18;
|
|
28328
28340
|
const rewardAPY = Number(assetStats.defiSpringSupplyApr?.value || "0") / 1e18;
|
|
28329
28341
|
const isSupported = this.tokenMarketData.isAPYSupported(asset);
|
|
28330
28342
|
apy = baseAPY + rewardAPY;
|
|
@@ -28340,7 +28352,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28340
28352
|
this.setCache(CACHE_KEY, result, 3e5);
|
|
28341
28353
|
return result;
|
|
28342
28354
|
} catch (error) {
|
|
28343
|
-
logger.error(
|
|
28355
|
+
logger.error(
|
|
28356
|
+
`VesuMultiplyAdapter: Error getting APY for ${supportedPosition.asset.symbol}:`,
|
|
28357
|
+
error
|
|
28358
|
+
);
|
|
28344
28359
|
throw error;
|
|
28345
28360
|
}
|
|
28346
28361
|
}
|
|
@@ -28353,12 +28368,16 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28353
28368
|
try {
|
|
28354
28369
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
28355
28370
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
28356
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
28371
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
28372
|
+
this.config.networkConfig
|
|
28373
|
+
);
|
|
28357
28374
|
let position = positions.find(
|
|
28358
28375
|
(p) => p.token.address.eq(supportedPosition.asset.address)
|
|
28359
28376
|
);
|
|
28360
28377
|
if (!position) {
|
|
28361
|
-
logger.warn(
|
|
28378
|
+
logger.warn(
|
|
28379
|
+
`VesuMultiplyAdapter: Position not found for token ${supportedPosition.asset.symbol}`
|
|
28380
|
+
);
|
|
28362
28381
|
return {
|
|
28363
28382
|
amount: new Web3Number("0", supportedPosition.asset.decimals),
|
|
28364
28383
|
remarks: "Position not found"
|
|
@@ -28371,12 +28390,18 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28371
28390
|
this.setCache(CACHE_KEY, position, 6e4);
|
|
28372
28391
|
return position;
|
|
28373
28392
|
} catch (error) {
|
|
28374
|
-
logger.error(
|
|
28393
|
+
logger.error(
|
|
28394
|
+
`VesuMultiplyAdapter: Error getting position for ${supportedPosition.asset.symbol}:`,
|
|
28395
|
+
error
|
|
28396
|
+
);
|
|
28375
28397
|
throw error;
|
|
28376
28398
|
}
|
|
28377
28399
|
}
|
|
28378
28400
|
async maxBorrowableAPY() {
|
|
28379
|
-
const collateralAPY = await this.getAPY({
|
|
28401
|
+
const collateralAPY = await this.getAPY({
|
|
28402
|
+
asset: this.config.collateral,
|
|
28403
|
+
isDebt: false
|
|
28404
|
+
});
|
|
28380
28405
|
const apy = collateralAPY.apy * 0.8;
|
|
28381
28406
|
return apy;
|
|
28382
28407
|
}
|
|
@@ -28386,9 +28411,15 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28386
28411
|
try {
|
|
28387
28412
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
28388
28413
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
28389
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
28390
|
-
|
|
28391
|
-
|
|
28414
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
28415
|
+
this.config.networkConfig
|
|
28416
|
+
);
|
|
28417
|
+
const collateralPosition = positions.find(
|
|
28418
|
+
(p) => p.token.address.eq(collateral.address)
|
|
28419
|
+
);
|
|
28420
|
+
const debtPosition = positions.find(
|
|
28421
|
+
(p) => p.token.address.eq(debt.address)
|
|
28422
|
+
);
|
|
28392
28423
|
if (!collateralPosition || !debtPosition) {
|
|
28393
28424
|
throw new Error("Could not find current positions");
|
|
28394
28425
|
}
|
|
@@ -28398,13 +28429,23 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28398
28429
|
debt,
|
|
28399
28430
|
maxBorrowableAPY
|
|
28400
28431
|
);
|
|
28401
|
-
logger.verbose(
|
|
28402
|
-
|
|
28432
|
+
logger.verbose(
|
|
28433
|
+
`VesuMultiplyAdapter: Max borrowable: ${maxBorrowable.toNumber()}`
|
|
28434
|
+
);
|
|
28435
|
+
const debtCap = await this.vesuAdapter.getDebtCap(
|
|
28436
|
+
this.config.networkConfig
|
|
28437
|
+
);
|
|
28403
28438
|
logger.verbose(`VesuMultiplyAdapter: Debt cap: ${debtCap.toNumber()}`);
|
|
28404
28439
|
const actualMaxBorrowable = maxBorrowable.minimum(debtCap);
|
|
28405
|
-
logger.verbose(
|
|
28406
|
-
|
|
28407
|
-
|
|
28440
|
+
logger.verbose(
|
|
28441
|
+
`VesuMultiplyAdapter: Actual max borrowable: ${actualMaxBorrowable.toNumber()}`
|
|
28442
|
+
);
|
|
28443
|
+
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
28444
|
+
this.config.networkConfig
|
|
28445
|
+
);
|
|
28446
|
+
const collateralPrice = await this.config.pricer.getPrice(
|
|
28447
|
+
collateral.symbol
|
|
28448
|
+
);
|
|
28408
28449
|
if (collateralPrice.price === 0) {
|
|
28409
28450
|
throw new Error("Collateral price is 0");
|
|
28410
28451
|
}
|
|
@@ -28422,14 +28463,25 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28422
28463
|
);
|
|
28423
28464
|
const maxDepositAmount = amount ? amount.minimum(maxCollateralFromDebt) : maxCollateralFromDebt;
|
|
28424
28465
|
const usdValue = await this.getUSDValue(collateral, maxDepositAmount);
|
|
28425
|
-
logger.verbose(
|
|
28426
|
-
|
|
28427
|
-
|
|
28466
|
+
logger.verbose(
|
|
28467
|
+
`VesuMultiplyAdapter: Max deposit::USD value: ${usdValue}, amount: ${maxDepositAmount.toNumber()}`
|
|
28468
|
+
);
|
|
28469
|
+
const apys = await Promise.all([
|
|
28470
|
+
this.getAPY({ asset: collateral, isDebt: false }),
|
|
28471
|
+
this.getAPY({ asset: debt, isDebt: true })
|
|
28472
|
+
]);
|
|
28473
|
+
logger.verbose(
|
|
28474
|
+
`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
|
|
28475
|
+
);
|
|
28428
28476
|
const borrowAmountUSD = actualMaxBorrowable.multipliedBy(debtPrice.price);
|
|
28429
|
-
logger.verbose(
|
|
28477
|
+
logger.verbose(
|
|
28478
|
+
`VesuMultiplyAdapter: Borrow amount: ${actualMaxBorrowable.toNumber()}, borrow amount USD: ${borrowAmountUSD.toNumber()}`
|
|
28479
|
+
);
|
|
28430
28480
|
const netCollateralUSD = usdValue + borrowAmountUSD.toNumber();
|
|
28431
28481
|
const netAPY = (apys[0].apy * netCollateralUSD + apys[1].apy * borrowAmountUSD.toNumber()) / usdValue;
|
|
28432
|
-
logger.verbose(
|
|
28482
|
+
logger.verbose(
|
|
28483
|
+
`VesuMultiplyAdapter: Max deposit amount: ${maxDepositAmount.toNumber()}, netAPY: ${netAPY}`
|
|
28484
|
+
);
|
|
28433
28485
|
return {
|
|
28434
28486
|
tokenInfo: collateral,
|
|
28435
28487
|
amount: maxDepositAmount,
|
|
@@ -28442,7 +28494,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28442
28494
|
protocol: this.protocol
|
|
28443
28495
|
};
|
|
28444
28496
|
} catch (error) {
|
|
28445
|
-
logger.error(
|
|
28497
|
+
logger.error(
|
|
28498
|
+
`VesuMultiplyAdapter: Error calculating max deposit:`,
|
|
28499
|
+
error
|
|
28500
|
+
);
|
|
28446
28501
|
throw error;
|
|
28447
28502
|
}
|
|
28448
28503
|
}
|
|
@@ -28452,9 +28507,15 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28452
28507
|
try {
|
|
28453
28508
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
28454
28509
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
28455
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
28456
|
-
|
|
28457
|
-
|
|
28510
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
28511
|
+
this.config.networkConfig
|
|
28512
|
+
);
|
|
28513
|
+
const collateralPosition = positions.find(
|
|
28514
|
+
(p) => p.token.address.eq(collateral.address)
|
|
28515
|
+
);
|
|
28516
|
+
const debtPosition = positions.find(
|
|
28517
|
+
(p) => p.token.address.eq(this.config.debt.address)
|
|
28518
|
+
);
|
|
28458
28519
|
if (!collateralPosition || !debtPosition) {
|
|
28459
28520
|
throw new Error("Could not find current positions");
|
|
28460
28521
|
}
|
|
@@ -28464,11 +28525,20 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28464
28525
|
const result = maxWithdrawable.greaterThan(0) ? maxWithdrawable : new Web3Number("0", collateral.decimals);
|
|
28465
28526
|
const usdValue = await this.getUSDValue(collateral, result);
|
|
28466
28527
|
const debtUSD = debtPosition.usdValue;
|
|
28467
|
-
logger.verbose(
|
|
28468
|
-
|
|
28469
|
-
|
|
28528
|
+
logger.verbose(
|
|
28529
|
+
`VesuMultiplyAdapter: Debt USD: ${debtUSD}, collateral USD: ${usdValue}`
|
|
28530
|
+
);
|
|
28531
|
+
const apys = await Promise.all([
|
|
28532
|
+
this.getAPY({ asset: collateral, isDebt: false }),
|
|
28533
|
+
this.getAPY({ asset: debt, isDebt: true })
|
|
28534
|
+
]);
|
|
28535
|
+
logger.verbose(
|
|
28536
|
+
`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
|
|
28537
|
+
);
|
|
28470
28538
|
const netAPY = usdValue - debtUSD > 0 ? (apys[0].apy * usdValue + apys[1].apy * debtUSD) / (usdValue - debtUSD) : 0;
|
|
28471
|
-
logger.verbose(
|
|
28539
|
+
logger.verbose(
|
|
28540
|
+
`VesuMultiplyAdapter: Max withdraw amount: ${result.toNumber()}, netAPY: ${netAPY}`
|
|
28541
|
+
);
|
|
28472
28542
|
return {
|
|
28473
28543
|
tokenInfo: collateral,
|
|
28474
28544
|
amount: result,
|
|
@@ -28481,14 +28551,19 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28481
28551
|
protocol: this.protocol
|
|
28482
28552
|
};
|
|
28483
28553
|
} catch (error) {
|
|
28484
|
-
logger.error(
|
|
28554
|
+
logger.error(
|
|
28555
|
+
`VesuMultiplyAdapter: Error calculating max withdraw:`,
|
|
28556
|
+
error
|
|
28557
|
+
);
|
|
28485
28558
|
throw error;
|
|
28486
28559
|
}
|
|
28487
28560
|
}
|
|
28488
28561
|
_getDepositLeaf() {
|
|
28489
28562
|
const collateral = this.config.collateral;
|
|
28490
28563
|
const debt = this.config.debt;
|
|
28491
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28564
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28565
|
+
this.config.poolId
|
|
28566
|
+
);
|
|
28492
28567
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
28493
28568
|
return [
|
|
28494
28569
|
// Approval step for collateral
|
|
@@ -28552,7 +28627,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28552
28627
|
];
|
|
28553
28628
|
}
|
|
28554
28629
|
_getWithdrawLeaf() {
|
|
28555
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28630
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28631
|
+
this.config.poolId
|
|
28632
|
+
);
|
|
28556
28633
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
28557
28634
|
const collateral = this.config.collateral;
|
|
28558
28635
|
const debt = this.config.debt;
|
|
@@ -28583,7 +28660,7 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28583
28660
|
this.config.debt.address.toBigInt(),
|
|
28584
28661
|
this.config.vaultAllocator.toBigInt()
|
|
28585
28662
|
],
|
|
28586
|
-
sanitizer: SIMPLE_SANITIZER_V2,
|
|
28663
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
|
|
28587
28664
|
// vmw = vesu multiply withdraw
|
|
28588
28665
|
id: `vmw_${this.config.poolId.shortString()}_${collateral.symbol}_${debt.symbol}`
|
|
28589
28666
|
},
|
|
@@ -28609,33 +28686,51 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28609
28686
|
const leafConfigs = this._getDepositLeaf();
|
|
28610
28687
|
const leaves = leafConfigs.map((config) => {
|
|
28611
28688
|
const { target, method, packedArguments, sanitizer, id } = config;
|
|
28612
|
-
const leaf = this.constructSimpleLeafData(
|
|
28613
|
-
|
|
28614
|
-
|
|
28615
|
-
|
|
28616
|
-
|
|
28617
|
-
|
|
28689
|
+
const leaf = this.constructSimpleLeafData(
|
|
28690
|
+
{
|
|
28691
|
+
id,
|
|
28692
|
+
target,
|
|
28693
|
+
method,
|
|
28694
|
+
packedArguments
|
|
28695
|
+
},
|
|
28696
|
+
sanitizer
|
|
28697
|
+
);
|
|
28618
28698
|
return leaf;
|
|
28619
28699
|
});
|
|
28620
|
-
return {
|
|
28700
|
+
return {
|
|
28701
|
+
leaves,
|
|
28702
|
+
callConstructor: this.getDepositCall.bind(
|
|
28703
|
+
this
|
|
28704
|
+
)
|
|
28705
|
+
};
|
|
28621
28706
|
}
|
|
28622
28707
|
getWithdrawAdapter() {
|
|
28623
28708
|
const leafConfigs = this._getWithdrawLeaf();
|
|
28624
28709
|
const leaves = leafConfigs.map((config) => {
|
|
28625
28710
|
const { target, method, packedArguments, sanitizer, id } = config;
|
|
28626
|
-
const leaf = this.constructSimpleLeafData(
|
|
28627
|
-
|
|
28628
|
-
|
|
28629
|
-
|
|
28630
|
-
|
|
28631
|
-
|
|
28711
|
+
const leaf = this.constructSimpleLeafData(
|
|
28712
|
+
{
|
|
28713
|
+
id,
|
|
28714
|
+
target,
|
|
28715
|
+
method,
|
|
28716
|
+
packedArguments
|
|
28717
|
+
},
|
|
28718
|
+
sanitizer
|
|
28719
|
+
);
|
|
28632
28720
|
return leaf;
|
|
28633
28721
|
});
|
|
28634
|
-
return {
|
|
28722
|
+
return {
|
|
28723
|
+
leaves,
|
|
28724
|
+
callConstructor: this.getWithdrawCall.bind(
|
|
28725
|
+
this
|
|
28726
|
+
)
|
|
28727
|
+
};
|
|
28635
28728
|
}
|
|
28636
28729
|
async getDepositCall(params) {
|
|
28637
28730
|
const collateral = this.config.collateral;
|
|
28638
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28731
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28732
|
+
this.config.poolId
|
|
28733
|
+
);
|
|
28639
28734
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
28640
28735
|
const uint256MarginAmount = uint25612.bnToUint256(params.amount.toWei());
|
|
28641
28736
|
return [
|
|
@@ -28707,7 +28802,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28707
28802
|
];
|
|
28708
28803
|
}
|
|
28709
28804
|
async getWithdrawCall(params) {
|
|
28710
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28805
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28806
|
+
this.config.poolId
|
|
28807
|
+
);
|
|
28711
28808
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
28712
28809
|
return [
|
|
28713
28810
|
// Switch delegation on
|
|
@@ -28732,7 +28829,7 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28732
28829
|
},
|
|
28733
28830
|
// Vesu multiply call
|
|
28734
28831
|
{
|
|
28735
|
-
sanitizer: SIMPLE_SANITIZER_V2,
|
|
28832
|
+
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER,
|
|
28736
28833
|
call: {
|
|
28737
28834
|
contractAddress: vesuMultiply,
|
|
28738
28835
|
selector: hash5.getSelectorFromName("modify_lever"),
|
|
@@ -28762,7 +28859,11 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28762
28859
|
];
|
|
28763
28860
|
}
|
|
28764
28861
|
async getMultiplyCallCalldata(params, isDeposit) {
|
|
28765
|
-
logger.verbose(
|
|
28862
|
+
logger.verbose(
|
|
28863
|
+
`${_VesuMultiplyAdapter.name}::getMultiplyCallCalldata params: ${JSON.stringify(
|
|
28864
|
+
params
|
|
28865
|
+
)}, isDeposit: ${isDeposit}, collateral: ${this.config.collateral.symbol}, debt: ${this.config.debt.symbol}`
|
|
28866
|
+
);
|
|
28766
28867
|
const { isV2 } = getVesuSingletonAddress(this.config.poolId);
|
|
28767
28868
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
28768
28869
|
const multiplyContract = new Contract12({
|
|
@@ -28772,42 +28873,83 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28772
28873
|
});
|
|
28773
28874
|
let leverSwap = [];
|
|
28774
28875
|
let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
28775
|
-
const existingPositions = await this.vesuAdapter.getPositions(
|
|
28776
|
-
|
|
28876
|
+
const existingPositions = await this.vesuAdapter.getPositions(
|
|
28877
|
+
this.config.networkConfig
|
|
28878
|
+
);
|
|
28879
|
+
const collateralisation = await this.vesuAdapter.getCollateralization(
|
|
28880
|
+
this.config.networkConfig
|
|
28881
|
+
);
|
|
28777
28882
|
const existingCollateralInfo = existingPositions[0];
|
|
28778
28883
|
const existingDebtInfo = existingPositions[1];
|
|
28779
28884
|
const isDexPriceRequired = existingDebtInfo.token.symbol !== "USDC";
|
|
28780
|
-
logger.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(
|
|
28781
|
-
|
|
28885
|
+
logger.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(
|
|
28886
|
+
existingCollateralInfo
|
|
28887
|
+
)},
|
|
28888
|
+
existingDebtInfo: ${JSON.stringify(
|
|
28889
|
+
existingDebtInfo
|
|
28890
|
+
)}, collateralisation: ${JSON.stringify(collateralisation)}`);
|
|
28782
28891
|
const collateralPrice = collateralisation[0].usdValue > 0 ? collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() : (await this.config.pricer.getPrice(this.config.collateral.symbol)).price;
|
|
28783
28892
|
const debtPrice = collateralisation[1].usdValue > 0 ? collateralisation[1].usdValue / existingDebtInfo.amount.toNumber() : (await this.config.pricer.getPrice(this.config.debt.symbol)).price;
|
|
28784
|
-
logger.debug(
|
|
28785
|
-
|
|
28786
|
-
|
|
28787
|
-
const
|
|
28788
|
-
|
|
28893
|
+
logger.debug(
|
|
28894
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`
|
|
28895
|
+
);
|
|
28896
|
+
const legLTV = await this.vesuAdapter.getLTVConfig(
|
|
28897
|
+
this.config.networkConfig
|
|
28898
|
+
);
|
|
28899
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
28900
|
+
this.config.networkConfig,
|
|
28901
|
+
this.config.pricer
|
|
28902
|
+
);
|
|
28903
|
+
const dexPrice = isDexPriceRequired ? await ekuboQuoter.getDexPrice(
|
|
28904
|
+
this.config.collateral,
|
|
28905
|
+
this.config.debt,
|
|
28906
|
+
this.config.quoteAmountToFetchPrice
|
|
28907
|
+
) : 1;
|
|
28908
|
+
logger.verbose(
|
|
28909
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall dexPrice: ${dexPrice}, ltv: ${legLTV}`
|
|
28910
|
+
);
|
|
28789
28911
|
const addedCollateral = params.amount.multipliedBy(isDeposit ? 1 : -1);
|
|
28790
|
-
logger.verbose(
|
|
28912
|
+
logger.verbose(
|
|
28913
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall addedCollateral: ${addedCollateral}`
|
|
28914
|
+
);
|
|
28791
28915
|
const numeratorPart1 = existingCollateralInfo.amount.plus(addedCollateral).multipliedBy(collateralPrice).multipliedBy(legLTV);
|
|
28792
|
-
logger.verbose(
|
|
28916
|
+
logger.verbose(
|
|
28917
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}`
|
|
28918
|
+
);
|
|
28793
28919
|
const numeratorPart2 = existingDebtInfo.amount.multipliedBy(debtPrice).multipliedBy(this.config.targetHealthFactor);
|
|
28794
|
-
logger.verbose(
|
|
28920
|
+
logger.verbose(
|
|
28921
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart2: ${numeratorPart2}`
|
|
28922
|
+
);
|
|
28795
28923
|
const denominatorPart = this.config.targetHealthFactor - legLTV / dexPrice;
|
|
28796
|
-
logger.verbose(
|
|
28924
|
+
logger.verbose(
|
|
28925
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall denominatorPart: ${denominatorPart}`
|
|
28926
|
+
);
|
|
28797
28927
|
const x_debt_usd = numeratorPart1.minus(numeratorPart2).dividedBy(denominatorPart);
|
|
28798
|
-
logger.verbose(
|
|
28799
|
-
|
|
28800
|
-
|
|
28928
|
+
logger.verbose(
|
|
28929
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall x_debt_usd: ${x_debt_usd}`
|
|
28930
|
+
);
|
|
28931
|
+
logger.debug(
|
|
28932
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}, numeratorPart2: ${numeratorPart2}, denominatorPart: ${denominatorPart}`
|
|
28933
|
+
);
|
|
28934
|
+
let debtAmount = new Web3Number(
|
|
28935
|
+
x_debt_usd.dividedBy(debtPrice).toFixed(this.config.debt.decimals),
|
|
28936
|
+
this.config.debt.decimals
|
|
28937
|
+
);
|
|
28801
28938
|
const marginAmount = addedCollateral;
|
|
28802
28939
|
const collateralToken = this.config.collateral;
|
|
28803
28940
|
const debtToken = this.config.debt;
|
|
28804
|
-
const debtAmountInCollateralUnits = new Web3Number(
|
|
28941
|
+
const debtAmountInCollateralUnits = new Web3Number(
|
|
28942
|
+
debtAmount.multipliedBy(debtPrice).dividedBy(collateralPrice).multipliedBy(10 ** collateralToken.decimals).toFixed(0),
|
|
28943
|
+
collateralToken.decimals
|
|
28944
|
+
);
|
|
28805
28945
|
const isIncrease = debtAmount.greaterThanOrEqualTo(0);
|
|
28806
28946
|
if (isIncrease && debtAmount.lessThan(0)) {
|
|
28807
28947
|
} else if (!isIncrease && debtAmount.greaterThan(0)) {
|
|
28808
28948
|
debtAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
28809
28949
|
}
|
|
28810
|
-
logger.verbose(
|
|
28950
|
+
logger.verbose(
|
|
28951
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall debtAmount: ${debtAmount}, marginAmount: ${marginAmount}`
|
|
28952
|
+
);
|
|
28811
28953
|
if (!debtAmount.isZero()) {
|
|
28812
28954
|
try {
|
|
28813
28955
|
const swapQuote = await ekuboQuoter.getQuote(
|
|
@@ -28817,32 +28959,49 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28817
28959
|
// negative for exact amount out
|
|
28818
28960
|
);
|
|
28819
28961
|
if (swapQuote.price_impact < 0.01) {
|
|
28820
|
-
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
28962
|
+
leverSwap = debtAmount.isNegative() ? ekuboQuoter.getVesuMultiplyQuote(
|
|
28963
|
+
swapQuote,
|
|
28964
|
+
collateralToken,
|
|
28965
|
+
debtToken
|
|
28966
|
+
) : ekuboQuoter.getVesuMultiplyQuote(
|
|
28967
|
+
swapQuote,
|
|
28968
|
+
debtToken,
|
|
28969
|
+
collateralToken
|
|
28970
|
+
);
|
|
28821
28971
|
const MAX_SLIPPAGE = 2e-3;
|
|
28822
28972
|
if (debtAmount.greaterThan(0)) {
|
|
28823
|
-
|
|
28824
|
-
leverSwapLimitAmount = await ekuboQuoter.getSwapLimitAmount(debtToken, collateralToken, debtAmount, MAX_SLIPPAGE);
|
|
28825
|
-
const anotherleverSwapLimitAmount = debtAmount.multipliedBy(1 + MAX_SLIPPAGE);
|
|
28826
|
-
console.log("anotherleverSwapLimitAmount", anotherleverSwapLimitAmount, leverSwapLimitAmount);
|
|
28973
|
+
leverSwapLimitAmount = debtAmount.multipliedBy(1 + MAX_SLIPPAGE);
|
|
28827
28974
|
} else if (debtAmount.lessThan(0)) {
|
|
28828
|
-
leverSwapLimitAmount =
|
|
28829
|
-
const anotherleverSwapLimitAmount = debtAmount.abs().multipliedBy(1 - MAX_SLIPPAGE);
|
|
28830
|
-
console.log("anotherleverSwapLimitAmount", anotherleverSwapLimitAmount, leverSwapLimitAmount);
|
|
28975
|
+
leverSwapLimitAmount = debtAmount.abs().multipliedBy(1 - MAX_SLIPPAGE);
|
|
28831
28976
|
} else {
|
|
28832
|
-
leverSwapLimitAmount = Web3Number.fromWei(
|
|
28977
|
+
leverSwapLimitAmount = Web3Number.fromWei(
|
|
28978
|
+
0,
|
|
28979
|
+
this.config.debt.decimals
|
|
28980
|
+
);
|
|
28833
28981
|
}
|
|
28834
28982
|
await new Promise((resolve) => setTimeout(resolve, 1e4));
|
|
28835
|
-
console.log("leverSwapLimitAmount", leverSwapLimitAmount);
|
|
28836
28983
|
} else {
|
|
28837
|
-
throw new Error(
|
|
28984
|
+
throw new Error(
|
|
28985
|
+
`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
|
|
28986
|
+
);
|
|
28838
28987
|
}
|
|
28839
28988
|
} catch (error) {
|
|
28840
|
-
throw new Error(
|
|
28989
|
+
throw new Error(
|
|
28990
|
+
`VesuMultiplyAdapter: Failed to get swap quote: ${error}`
|
|
28991
|
+
);
|
|
28841
28992
|
}
|
|
28842
28993
|
}
|
|
28843
|
-
const multiplyParams = await this.getLeverParams(
|
|
28994
|
+
const multiplyParams = await this.getLeverParams(
|
|
28995
|
+
isIncrease,
|
|
28996
|
+
params,
|
|
28997
|
+
leverSwap,
|
|
28998
|
+
leverSwapLimitAmount
|
|
28999
|
+
);
|
|
28844
29000
|
const call = multiplyContract.populate("modify_lever", {
|
|
28845
|
-
modify_lever_params: this.formatMultiplyParams(
|
|
29001
|
+
modify_lever_params: this.formatMultiplyParams(
|
|
29002
|
+
isIncrease,
|
|
29003
|
+
multiplyParams
|
|
29004
|
+
)
|
|
28846
29005
|
});
|
|
28847
29006
|
return call.calldata;
|
|
28848
29007
|
}
|
|
@@ -28856,7 +29015,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28856
29015
|
add_margin: params.amount,
|
|
28857
29016
|
// multiplied by collateral decimals in format
|
|
28858
29017
|
margin_swap: [],
|
|
28859
|
-
margin_swap_limit_amount: Web3Number.fromWei(
|
|
29018
|
+
margin_swap_limit_amount: Web3Number.fromWei(
|
|
29019
|
+
0,
|
|
29020
|
+
this.config.collateral.decimals
|
|
29021
|
+
),
|
|
28860
29022
|
lever_swap: leverSwap,
|
|
28861
29023
|
lever_swap_limit_amount: leverSwapLimitAmount
|
|
28862
29024
|
} : {
|
|
@@ -28870,7 +29032,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28870
29032
|
lever_swap_limit_amount: leverSwapLimitAmount,
|
|
28871
29033
|
lever_swap_weights: [],
|
|
28872
29034
|
withdraw_swap: [],
|
|
28873
|
-
withdraw_swap_limit_amount: Web3Number.fromWei(
|
|
29035
|
+
withdraw_swap_limit_amount: Web3Number.fromWei(
|
|
29036
|
+
0,
|
|
29037
|
+
this.config.collateral.decimals
|
|
29038
|
+
),
|
|
28874
29039
|
withdraw_swap_weights: [],
|
|
28875
29040
|
close_position: false
|
|
28876
29041
|
};
|
|
@@ -28886,12 +29051,16 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28886
29051
|
});
|
|
28887
29052
|
let leverSwap = [];
|
|
28888
29053
|
let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
28889
|
-
const existingPositions = await this.vesuAdapter.getPositions(
|
|
29054
|
+
const existingPositions = await this.vesuAdapter.getPositions(
|
|
29055
|
+
this.config.networkConfig
|
|
29056
|
+
);
|
|
28890
29057
|
const existingCollateralInfo = existingPositions[0];
|
|
28891
29058
|
const existingDebtInfo = existingPositions[1];
|
|
28892
29059
|
const collateralToken = this.config.collateral;
|
|
28893
29060
|
const debtToken = this.config.debt;
|
|
28894
|
-
const collateralPrice = await this.config.pricer.getPrice(
|
|
29061
|
+
const collateralPrice = await this.config.pricer.getPrice(
|
|
29062
|
+
collateralToken.symbol
|
|
29063
|
+
);
|
|
28895
29064
|
const debtPrice = await this.config.pricer.getPrice(debtToken.symbol);
|
|
28896
29065
|
const { deltadebtAmountUnits: debtAmountToRepay } = calculateDebtReductionAmountForWithdrawal(
|
|
28897
29066
|
existingDebtInfo.amount,
|
|
@@ -28902,27 +29071,41 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28902
29071
|
debtPrice.price,
|
|
28903
29072
|
debtToken.decimals
|
|
28904
29073
|
);
|
|
28905
|
-
console.log("debtAmountToRepay", debtAmountToRepay);
|
|
28906
29074
|
if (!debtAmountToRepay) {
|
|
28907
29075
|
throw new Error("error calculating debt amount to repay");
|
|
28908
29076
|
}
|
|
28909
|
-
const ekuboQuoter = new EkuboQuoter(
|
|
28910
|
-
|
|
28911
|
-
|
|
29077
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
29078
|
+
this.config.networkConfig,
|
|
29079
|
+
this.config.pricer
|
|
29080
|
+
);
|
|
29081
|
+
const debtInDebtUnits = new Web3Number(
|
|
29082
|
+
debtAmountToRepay,
|
|
29083
|
+
debtToken.decimals
|
|
29084
|
+
).dividedBy(debtPrice.price).multipliedBy(10 ** debtToken.decimals);
|
|
28912
29085
|
const swapQuote = await ekuboQuoter.getQuote(
|
|
28913
29086
|
debtToken.address.address,
|
|
28914
29087
|
collateralToken.address.address,
|
|
28915
29088
|
debtInDebtUnits
|
|
28916
29089
|
);
|
|
28917
29090
|
const MAX_SLIPPAGE = 2e-3;
|
|
28918
|
-
if (swapQuote.price_impact <
|
|
28919
|
-
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
29091
|
+
if (swapQuote.price_impact < 25e-4) {
|
|
29092
|
+
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
29093
|
+
swapQuote,
|
|
29094
|
+
collateralToken,
|
|
29095
|
+
debtToken
|
|
29096
|
+
);
|
|
28920
29097
|
} else {
|
|
28921
|
-
logger.error(
|
|
29098
|
+
logger.error(
|
|
29099
|
+
`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
|
|
29100
|
+
);
|
|
28922
29101
|
}
|
|
28923
|
-
|
|
28924
|
-
|
|
28925
|
-
|
|
29102
|
+
leverSwapLimitAmount = new Web3Number(debtAmountToRepay, debtToken.decimals).abs().multipliedBy(1 + MAX_SLIPPAGE);
|
|
29103
|
+
const multiplyParams = await this.getLeverParams(
|
|
29104
|
+
false,
|
|
29105
|
+
params,
|
|
29106
|
+
leverSwap,
|
|
29107
|
+
leverSwapLimitAmount
|
|
29108
|
+
);
|
|
28926
29109
|
const call = multiplyContract.populate("modify_lever", {
|
|
28927
29110
|
modify_lever_params: this.formatMultiplyParams(false, multiplyParams)
|
|
28928
29111
|
});
|
|
@@ -28932,100 +29115,132 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28932
29115
|
if (isIncrease) {
|
|
28933
29116
|
const _params2 = params;
|
|
28934
29117
|
return {
|
|
28935
|
-
action: new CairoCustomEnum3({
|
|
28936
|
-
|
|
28937
|
-
|
|
28938
|
-
|
|
28939
|
-
|
|
28940
|
-
|
|
28941
|
-
|
|
29118
|
+
action: new CairoCustomEnum3({
|
|
29119
|
+
IncreaseLever: {
|
|
29120
|
+
pool_id: _params2.pool_id.toBigInt(),
|
|
29121
|
+
collateral_asset: _params2.collateral_asset.toBigInt(),
|
|
29122
|
+
debt_asset: _params2.debt_asset.toBigInt(),
|
|
29123
|
+
user: _params2.user.toBigInt(),
|
|
29124
|
+
add_margin: BigInt(_params2.add_margin.toWei()),
|
|
29125
|
+
margin_swap: _params2.margin_swap.map((swap) => ({
|
|
29126
|
+
route: swap.route.map((route) => ({
|
|
29127
|
+
pool_key: {
|
|
29128
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
29129
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
29130
|
+
fee: route.pool_key.fee,
|
|
29131
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
29132
|
+
extension: BigInt(
|
|
29133
|
+
num9.hexToDecimalString(route.pool_key.extension)
|
|
29134
|
+
)
|
|
29135
|
+
},
|
|
29136
|
+
sqrt_ratio_limit: uint25612.bnToUint256(
|
|
29137
|
+
route.sqrt_ratio_limit.toWei()
|
|
29138
|
+
),
|
|
29139
|
+
skip_ahead: BigInt(100)
|
|
29140
|
+
})),
|
|
29141
|
+
token_amount: {
|
|
29142
|
+
token: swap.token_amount.token.toBigInt(),
|
|
29143
|
+
amount: swap.token_amount.amount.toI129()
|
|
29144
|
+
}
|
|
29145
|
+
})),
|
|
29146
|
+
margin_swap_limit_amount: BigInt(
|
|
29147
|
+
_params2.margin_swap_limit_amount.toWei()
|
|
29148
|
+
),
|
|
29149
|
+
lever_swap: _params2.lever_swap.map((swap) => ({
|
|
29150
|
+
route: swap.route.map((route) => ({
|
|
29151
|
+
pool_key: {
|
|
29152
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
29153
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
29154
|
+
fee: route.pool_key.fee,
|
|
29155
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
29156
|
+
extension: BigInt(
|
|
29157
|
+
num9.hexToDecimalString(route.pool_key.extension)
|
|
29158
|
+
)
|
|
29159
|
+
},
|
|
29160
|
+
sqrt_ratio_limit: uint25612.bnToUint256(
|
|
29161
|
+
route.sqrt_ratio_limit.toWei()
|
|
29162
|
+
),
|
|
29163
|
+
skip_ahead: BigInt(0)
|
|
29164
|
+
})),
|
|
29165
|
+
token_amount: {
|
|
29166
|
+
token: swap.token_amount.token.toBigInt(),
|
|
29167
|
+
amount: swap.token_amount.amount.toI129()
|
|
29168
|
+
}
|
|
29169
|
+
})),
|
|
29170
|
+
lever_swap_limit_amount: BigInt(
|
|
29171
|
+
_params2.lever_swap_limit_amount.toWei()
|
|
29172
|
+
)
|
|
29173
|
+
}
|
|
29174
|
+
})
|
|
29175
|
+
};
|
|
29176
|
+
}
|
|
29177
|
+
const _params = params;
|
|
29178
|
+
return {
|
|
29179
|
+
action: new CairoCustomEnum3({
|
|
29180
|
+
DecreaseLever: {
|
|
29181
|
+
pool_id: _params.pool_id.toBigInt(),
|
|
29182
|
+
collateral_asset: _params.collateral_asset.toBigInt(),
|
|
29183
|
+
debt_asset: _params.debt_asset.toBigInt(),
|
|
29184
|
+
user: _params.user.toBigInt(),
|
|
29185
|
+
sub_margin: BigInt(_params.sub_margin.toWei()),
|
|
29186
|
+
recipient: _params.recipient.toBigInt(),
|
|
29187
|
+
lever_swap: _params.lever_swap.map((swap) => ({
|
|
28942
29188
|
route: swap.route.map((route) => ({
|
|
28943
29189
|
pool_key: {
|
|
28944
29190
|
token0: route.pool_key.token0.toBigInt(),
|
|
28945
29191
|
token1: route.pool_key.token1.toBigInt(),
|
|
28946
29192
|
fee: route.pool_key.fee,
|
|
28947
29193
|
tick_spacing: route.pool_key.tick_spacing,
|
|
28948
|
-
extension:
|
|
29194
|
+
extension: ContractAddr.from(
|
|
29195
|
+
route.pool_key.extension
|
|
29196
|
+
).toBigInt()
|
|
28949
29197
|
},
|
|
28950
|
-
sqrt_ratio_limit: uint25612.bnToUint256(
|
|
28951
|
-
|
|
29198
|
+
sqrt_ratio_limit: uint25612.bnToUint256(
|
|
29199
|
+
route.sqrt_ratio_limit.toWei()
|
|
29200
|
+
),
|
|
29201
|
+
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
28952
29202
|
})),
|
|
28953
29203
|
token_amount: {
|
|
28954
29204
|
token: swap.token_amount.token.toBigInt(),
|
|
28955
29205
|
amount: swap.token_amount.amount.toI129()
|
|
28956
29206
|
}
|
|
28957
29207
|
})),
|
|
28958
|
-
|
|
28959
|
-
|
|
29208
|
+
lever_swap_limit_amount: BigInt(
|
|
29209
|
+
_params.lever_swap_limit_amount.toWei()
|
|
29210
|
+
),
|
|
29211
|
+
lever_swap_weights: _params.lever_swap_weights.map(
|
|
29212
|
+
(weight) => BigInt(weight.toWei())
|
|
29213
|
+
),
|
|
29214
|
+
withdraw_swap: _params.withdraw_swap.map((swap) => ({
|
|
28960
29215
|
route: swap.route.map((route) => ({
|
|
28961
29216
|
pool_key: {
|
|
28962
29217
|
token0: route.pool_key.token0.toBigInt(),
|
|
28963
29218
|
token1: route.pool_key.token1.toBigInt(),
|
|
28964
29219
|
fee: route.pool_key.fee,
|
|
28965
29220
|
tick_spacing: route.pool_key.tick_spacing,
|
|
28966
|
-
extension:
|
|
29221
|
+
extension: ContractAddr.from(
|
|
29222
|
+
route.pool_key.extension
|
|
29223
|
+
).toBigInt()
|
|
28967
29224
|
},
|
|
28968
|
-
sqrt_ratio_limit: uint25612.bnToUint256(
|
|
28969
|
-
|
|
29225
|
+
sqrt_ratio_limit: uint25612.bnToUint256(
|
|
29226
|
+
route.sqrt_ratio_limit.toWei()
|
|
29227
|
+
),
|
|
29228
|
+
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
28970
29229
|
})),
|
|
28971
29230
|
token_amount: {
|
|
28972
29231
|
token: swap.token_amount.token.toBigInt(),
|
|
28973
29232
|
amount: swap.token_amount.amount.toI129()
|
|
28974
29233
|
}
|
|
28975
29234
|
})),
|
|
28976
|
-
|
|
28977
|
-
|
|
28978
|
-
|
|
28979
|
-
|
|
28980
|
-
|
|
28981
|
-
|
|
28982
|
-
|
|
28983
|
-
|
|
28984
|
-
|
|
28985
|
-
debt_asset: _params.debt_asset.toBigInt(),
|
|
28986
|
-
user: _params.user.toBigInt(),
|
|
28987
|
-
sub_margin: BigInt(_params.sub_margin.toWei()),
|
|
28988
|
-
recipient: _params.recipient.toBigInt(),
|
|
28989
|
-
lever_swap: _params.lever_swap.map((swap) => ({
|
|
28990
|
-
route: swap.route.map((route) => ({
|
|
28991
|
-
pool_key: {
|
|
28992
|
-
token0: route.pool_key.token0.toBigInt(),
|
|
28993
|
-
token1: route.pool_key.token1.toBigInt(),
|
|
28994
|
-
fee: route.pool_key.fee,
|
|
28995
|
-
tick_spacing: route.pool_key.tick_spacing,
|
|
28996
|
-
extension: ContractAddr.from(route.pool_key.extension).toBigInt()
|
|
28997
|
-
},
|
|
28998
|
-
sqrt_ratio_limit: uint25612.bnToUint256(route.sqrt_ratio_limit.toWei()),
|
|
28999
|
-
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
29000
|
-
})),
|
|
29001
|
-
token_amount: {
|
|
29002
|
-
token: swap.token_amount.token.toBigInt(),
|
|
29003
|
-
amount: swap.token_amount.amount.toI129()
|
|
29004
|
-
}
|
|
29005
|
-
})),
|
|
29006
|
-
lever_swap_limit_amount: BigInt(_params.lever_swap_limit_amount.toWei()),
|
|
29007
|
-
lever_swap_weights: _params.lever_swap_weights.map((weight) => BigInt(weight.toWei())),
|
|
29008
|
-
withdraw_swap: _params.withdraw_swap.map((swap) => ({
|
|
29009
|
-
route: swap.route.map((route) => ({
|
|
29010
|
-
pool_key: {
|
|
29011
|
-
token0: route.pool_key.token0.toBigInt(),
|
|
29012
|
-
token1: route.pool_key.token1.toBigInt(),
|
|
29013
|
-
fee: route.pool_key.fee,
|
|
29014
|
-
tick_spacing: route.pool_key.tick_spacing,
|
|
29015
|
-
extension: ContractAddr.from(route.pool_key.extension).toBigInt()
|
|
29016
|
-
},
|
|
29017
|
-
sqrt_ratio_limit: uint25612.bnToUint256(route.sqrt_ratio_limit.toWei()),
|
|
29018
|
-
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
29019
|
-
})),
|
|
29020
|
-
token_amount: {
|
|
29021
|
-
token: swap.token_amount.token.toBigInt(),
|
|
29022
|
-
amount: swap.token_amount.amount.toI129()
|
|
29023
|
-
}
|
|
29024
|
-
})),
|
|
29025
|
-
withdraw_swap_limit_amount: BigInt(_params.withdraw_swap_limit_amount.toWei()),
|
|
29026
|
-
withdraw_swap_weights: _params.withdraw_swap_weights.map((weight) => BigInt(weight.toWei())),
|
|
29027
|
-
close_position: _params.close_position
|
|
29028
|
-
} })
|
|
29235
|
+
withdraw_swap_limit_amount: BigInt(
|
|
29236
|
+
_params.withdraw_swap_limit_amount.toWei()
|
|
29237
|
+
),
|
|
29238
|
+
withdraw_swap_weights: _params.withdraw_swap_weights.map(
|
|
29239
|
+
(weight) => BigInt(weight.toWei())
|
|
29240
|
+
),
|
|
29241
|
+
close_position: _params.close_position
|
|
29242
|
+
}
|
|
29243
|
+
})
|
|
29029
29244
|
};
|
|
29030
29245
|
}
|
|
29031
29246
|
async getHealthFactor() {
|
|
@@ -29034,11 +29249,15 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
29034
29249
|
}
|
|
29035
29250
|
async getNetAPY() {
|
|
29036
29251
|
const positions = await this.getPositions();
|
|
29037
|
-
logger.verbose(
|
|
29252
|
+
logger.verbose(
|
|
29253
|
+
`${this.name}::getNetAPY: positions: ${JSON.stringify(positions)}`
|
|
29254
|
+
);
|
|
29038
29255
|
const allZero = positions.every((p) => p.usdValue === 0);
|
|
29039
29256
|
if (allZero) {
|
|
29040
29257
|
const collateralUSD = 1e3;
|
|
29041
|
-
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
29258
|
+
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
29259
|
+
this.config.networkConfig
|
|
29260
|
+
);
|
|
29042
29261
|
const targetHF = this.config.targetHealthFactor;
|
|
29043
29262
|
const maxDebt = HealthFactorMath.getMaxDebtAmountOnLooping(
|
|
29044
29263
|
new Web3Number(collateralUSD, this.config.collateral.decimals),
|
|
@@ -29410,12 +29629,17 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29410
29629
|
timeout: this.config.extendedTimeout,
|
|
29411
29630
|
retries: this.config.extendedRetries
|
|
29412
29631
|
});
|
|
29632
|
+
this.minimumExtendedMovementAmount = this.config.minimumExtendedMovementAmount ?? 5;
|
|
29413
29633
|
this.client = client;
|
|
29634
|
+
this.retryDelayForOrderStatus = this.config.retryDelayForOrderStatus ?? 3e3;
|
|
29414
29635
|
}
|
|
29415
29636
|
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
29416
29637
|
async getAPY(supportedPosition) {
|
|
29417
29638
|
const side = supportedPosition.isDebt ? "LONG" : "SHORT";
|
|
29418
|
-
const fundingRates = await this.client.getFundingRates(
|
|
29639
|
+
const fundingRates = await this.client.getFundingRates(
|
|
29640
|
+
this.config.extendedMarketName,
|
|
29641
|
+
side
|
|
29642
|
+
);
|
|
29419
29643
|
if (fundingRates.status !== "OK") {
|
|
29420
29644
|
logger.error("error getting funding rates", fundingRates);
|
|
29421
29645
|
return { apy: 0, type: "base" /* BASE */ };
|
|
@@ -29459,14 +29683,14 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29459
29683
|
});
|
|
29460
29684
|
}
|
|
29461
29685
|
_getDepositLeaf() {
|
|
29462
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
29686
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
29687
|
+
(token) => token.symbol === "USDCe"
|
|
29688
|
+
);
|
|
29463
29689
|
return [
|
|
29464
29690
|
{
|
|
29465
29691
|
target: this.config.supportedPositions[0].asset.address,
|
|
29466
29692
|
method: "approve",
|
|
29467
|
-
packedArguments: [
|
|
29468
|
-
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()
|
|
29469
|
-
],
|
|
29693
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
29470
29694
|
id: `extended_approve_${this.config.supportedPositions[0].asset.symbol}`,
|
|
29471
29695
|
sanitizer: AVNU_LEGACY_SANITIZER
|
|
29472
29696
|
},
|
|
@@ -29493,17 +29717,62 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29493
29717
|
}
|
|
29494
29718
|
];
|
|
29495
29719
|
}
|
|
29720
|
+
getSwapFromLegacyLeaf() {
|
|
29721
|
+
const leafConfigs = this._getSwapFromLegacyLeaf();
|
|
29722
|
+
const leaves = leafConfigs.map((config) => {
|
|
29723
|
+
const { target, method, packedArguments, sanitizer, id } = config;
|
|
29724
|
+
const leaf = this.constructSimpleLeafData(
|
|
29725
|
+
{
|
|
29726
|
+
id,
|
|
29727
|
+
target,
|
|
29728
|
+
method,
|
|
29729
|
+
packedArguments
|
|
29730
|
+
},
|
|
29731
|
+
sanitizer
|
|
29732
|
+
);
|
|
29733
|
+
return leaf;
|
|
29734
|
+
});
|
|
29735
|
+
return {
|
|
29736
|
+
leaves,
|
|
29737
|
+
callConstructor: this.getSwapFromLegacyCall.bind(
|
|
29738
|
+
this
|
|
29739
|
+
)
|
|
29740
|
+
};
|
|
29741
|
+
}
|
|
29742
|
+
_getSwapFromLegacyLeaf() {
|
|
29743
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
29744
|
+
(token) => token.symbol === "USDCe"
|
|
29745
|
+
);
|
|
29746
|
+
return [
|
|
29747
|
+
{
|
|
29748
|
+
target: usdceToken.address,
|
|
29749
|
+
method: "approve",
|
|
29750
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
29751
|
+
id: `extendedswaplegacyapprove_${usdceToken.symbol}`,
|
|
29752
|
+
sanitizer: AVNU_LEGACY_SANITIZER
|
|
29753
|
+
},
|
|
29754
|
+
{
|
|
29755
|
+
target: AVNU_EXCHANGE_FOR_LEGACY_USDC,
|
|
29756
|
+
method: "swap_to_new",
|
|
29757
|
+
packedArguments: [],
|
|
29758
|
+
id: `extended_swap_to_new_${usdceToken.symbol}`,
|
|
29759
|
+
sanitizer: AVNU_LEGACY_SANITIZER
|
|
29760
|
+
}
|
|
29761
|
+
];
|
|
29762
|
+
}
|
|
29496
29763
|
_getWithdrawLeaf() {
|
|
29497
29764
|
return [];
|
|
29498
29765
|
}
|
|
29499
29766
|
async getDepositCall(params) {
|
|
29500
29767
|
try {
|
|
29501
29768
|
const usdcToken = this.config.supportedPositions[0].asset;
|
|
29502
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
29503
|
-
|
|
29504
|
-
|
|
29769
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
29770
|
+
(token) => token.symbol === "USDCe"
|
|
29771
|
+
);
|
|
29772
|
+
const salt = Math.floor(Math.random() * 10 ** usdcToken.decimals);
|
|
29773
|
+
const amount = uint25613.bnToUint256(
|
|
29774
|
+
params.amount.multipliedBy(10).toWei()
|
|
29505
29775
|
);
|
|
29506
|
-
const amount = uint25613.bnToUint256(params.amount.multipliedBy(10).toWei());
|
|
29507
29776
|
const quotes = await this.config.avnuAdapter.getQuotesAvnu(
|
|
29508
29777
|
usdcToken.address.toString(),
|
|
29509
29778
|
usdceToken.address.toString(),
|
|
@@ -29516,7 +29785,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29516
29785
|
logger.error("error getting quotes from avnu");
|
|
29517
29786
|
return [];
|
|
29518
29787
|
}
|
|
29519
|
-
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
29788
|
+
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
29789
|
+
quotes
|
|
29790
|
+
);
|
|
29520
29791
|
const swapCallData = getCalldata[0];
|
|
29521
29792
|
return [
|
|
29522
29793
|
{
|
|
@@ -29573,6 +29844,76 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29573
29844
|
return [];
|
|
29574
29845
|
}
|
|
29575
29846
|
}
|
|
29847
|
+
getProofsForFromLegacySwap(tree) {
|
|
29848
|
+
let proofGroups = [];
|
|
29849
|
+
const ids = this.getSwapFromLegacyLeaf().leaves.map((l) => l.readableId);
|
|
29850
|
+
for (const [i, v] of tree.entries()) {
|
|
29851
|
+
if (ids.includes(v.readableId)) {
|
|
29852
|
+
proofGroups.push(tree.getProof(i));
|
|
29853
|
+
}
|
|
29854
|
+
}
|
|
29855
|
+
if (proofGroups.length != ids.length) {
|
|
29856
|
+
throw new Error(`Not all proofs found for IDs: ${ids.join(", ")}`);
|
|
29857
|
+
}
|
|
29858
|
+
return {
|
|
29859
|
+
proofs: proofGroups,
|
|
29860
|
+
callConstructor: this.getSwapFromLegacyCall.bind(this)
|
|
29861
|
+
};
|
|
29862
|
+
}
|
|
29863
|
+
async getSwapFromLegacyCall(params) {
|
|
29864
|
+
try {
|
|
29865
|
+
const usdcToken = this.config.supportedPositions[0].asset;
|
|
29866
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
29867
|
+
(token) => token.symbol === "USDCe"
|
|
29868
|
+
);
|
|
29869
|
+
const amount = uint25613.bnToUint256(
|
|
29870
|
+
params.amount.multipliedBy(10).toWei()
|
|
29871
|
+
);
|
|
29872
|
+
const quotes = await this.config.avnuAdapter.getQuotesAvnu(
|
|
29873
|
+
usdceToken.address.toString(),
|
|
29874
|
+
usdcToken.address.toString(),
|
|
29875
|
+
params.amount.toNumber(),
|
|
29876
|
+
this.config.avnuAdapter.config.vaultAllocator.address.toString(),
|
|
29877
|
+
usdcToken.decimals,
|
|
29878
|
+
false
|
|
29879
|
+
);
|
|
29880
|
+
if (!quotes) {
|
|
29881
|
+
logger.error("error getting quotes from avnu");
|
|
29882
|
+
return [];
|
|
29883
|
+
}
|
|
29884
|
+
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
29885
|
+
quotes
|
|
29886
|
+
);
|
|
29887
|
+
const swapCallData = getCalldata[0];
|
|
29888
|
+
return [
|
|
29889
|
+
{
|
|
29890
|
+
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
29891
|
+
call: {
|
|
29892
|
+
contractAddress: usdceToken.address,
|
|
29893
|
+
selector: hash6.getSelectorFromName("approve"),
|
|
29894
|
+
calldata: [
|
|
29895
|
+
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt(),
|
|
29896
|
+
toBigInt(amount.low.toString()),
|
|
29897
|
+
// amount low
|
|
29898
|
+
toBigInt(amount.high.toString())
|
|
29899
|
+
// amount high
|
|
29900
|
+
]
|
|
29901
|
+
}
|
|
29902
|
+
},
|
|
29903
|
+
{
|
|
29904
|
+
sanitizer: AVNU_LEGACY_SANITIZER,
|
|
29905
|
+
call: {
|
|
29906
|
+
contractAddress: AVNU_EXCHANGE_FOR_LEGACY_USDC,
|
|
29907
|
+
selector: hash6.getSelectorFromName("swap_to_new"),
|
|
29908
|
+
calldata: swapCallData
|
|
29909
|
+
}
|
|
29910
|
+
}
|
|
29911
|
+
];
|
|
29912
|
+
} catch (error) {
|
|
29913
|
+
logger.error(`Error creating Deposit Call: ${error}`);
|
|
29914
|
+
return [];
|
|
29915
|
+
}
|
|
29916
|
+
}
|
|
29576
29917
|
//Swap wbtc to usdc
|
|
29577
29918
|
async getWithdrawCall(params) {
|
|
29578
29919
|
try {
|
|
@@ -29588,13 +29929,60 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29588
29929
|
async withdrawFromExtended(amount) {
|
|
29589
29930
|
try {
|
|
29590
29931
|
if (!this.client) {
|
|
29591
|
-
|
|
29932
|
+
logger.error("Client not initialized");
|
|
29933
|
+
return false;
|
|
29592
29934
|
}
|
|
29593
|
-
|
|
29594
|
-
|
|
29595
|
-
|
|
29596
|
-
|
|
29935
|
+
if (amount.lessThanOrEqualTo(0)) {
|
|
29936
|
+
logger.error(
|
|
29937
|
+
`Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
|
|
29938
|
+
);
|
|
29939
|
+
return false;
|
|
29940
|
+
}
|
|
29941
|
+
if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
|
|
29942
|
+
logger.warn(
|
|
29943
|
+
`Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
|
|
29944
|
+
);
|
|
29945
|
+
return false;
|
|
29946
|
+
}
|
|
29947
|
+
const holdings = await this.getExtendedDepositAmount();
|
|
29948
|
+
if (!holdings) {
|
|
29949
|
+
logger.error(
|
|
29950
|
+
"Cannot get holdings - unable to validate withdrawal amount"
|
|
29951
|
+
);
|
|
29952
|
+
return false;
|
|
29953
|
+
}
|
|
29954
|
+
const availableForWithdrawal = parseFloat(
|
|
29955
|
+
holdings.availableForWithdrawal
|
|
29956
|
+
);
|
|
29957
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
29958
|
+
logger.error(
|
|
29959
|
+
`Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
29960
|
+
);
|
|
29961
|
+
return false;
|
|
29962
|
+
}
|
|
29963
|
+
const withdrawalAmount = amount.toNumber();
|
|
29964
|
+
if (withdrawalAmount > availableForWithdrawal) {
|
|
29965
|
+
logger.error(
|
|
29966
|
+
`Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
|
|
29967
|
+
);
|
|
29968
|
+
return false;
|
|
29969
|
+
}
|
|
29970
|
+
logger.info(
|
|
29971
|
+
`Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
|
|
29972
|
+
);
|
|
29973
|
+
const withdrawalRequest = await this.client.withdrawUSDC(
|
|
29974
|
+
amount.toFixed(2)
|
|
29975
|
+
);
|
|
29976
|
+
if (withdrawalRequest.status === "OK") {
|
|
29977
|
+
const withdrawalStatus = await this.getDepositOrWithdrawalStatus(
|
|
29978
|
+
withdrawalRequest.data,
|
|
29979
|
+
"WITHDRAWAL" /* WITHDRAWAL */
|
|
29980
|
+
);
|
|
29981
|
+
return withdrawalStatus;
|
|
29597
29982
|
}
|
|
29983
|
+
logger.error(
|
|
29984
|
+
`Withdrawal request failed with status: ${withdrawalRequest.status}`
|
|
29985
|
+
);
|
|
29598
29986
|
return false;
|
|
29599
29987
|
} catch (error) {
|
|
29600
29988
|
logger.error(`Error creating Withdraw Call: ${error}`);
|
|
@@ -29605,21 +29993,44 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29605
29993
|
return Promise.resolve(1);
|
|
29606
29994
|
}
|
|
29607
29995
|
async getExtendedDepositAmount() {
|
|
29608
|
-
|
|
29609
|
-
|
|
29610
|
-
|
|
29611
|
-
|
|
29612
|
-
|
|
29613
|
-
|
|
29614
|
-
|
|
29615
|
-
|
|
29616
|
-
|
|
29617
|
-
|
|
29618
|
-
|
|
29619
|
-
|
|
29996
|
+
try {
|
|
29997
|
+
if (this.client === null) {
|
|
29998
|
+
logger.error("error initializing client - client is null");
|
|
29999
|
+
return void 0;
|
|
30000
|
+
}
|
|
30001
|
+
const result = await this.client.getHoldings();
|
|
30002
|
+
if (!result) {
|
|
30003
|
+
logger.error("error getting holdings - API returned null/undefined");
|
|
30004
|
+
return void 0;
|
|
30005
|
+
}
|
|
30006
|
+
if (result.status && result.status !== "OK") {
|
|
30007
|
+
logger.error(
|
|
30008
|
+
`error getting holdings - API returned status: ${result.status}`
|
|
30009
|
+
);
|
|
30010
|
+
return void 0;
|
|
30011
|
+
}
|
|
30012
|
+
const holdings = result.data;
|
|
30013
|
+
if (!holdings) {
|
|
30014
|
+
logger.warn(
|
|
30015
|
+
"holdings data is null/undefined - treating as zero balance"
|
|
30016
|
+
);
|
|
30017
|
+
return {
|
|
30018
|
+
collateral_name: "",
|
|
30019
|
+
balance: "0",
|
|
30020
|
+
equity: "0",
|
|
30021
|
+
availableForTrade: "0",
|
|
30022
|
+
availableForWithdrawal: "0",
|
|
30023
|
+
unrealisedPnl: "0",
|
|
30024
|
+
initialMargin: "0",
|
|
30025
|
+
marginRatio: "0",
|
|
30026
|
+
updatedTime: Date.now()
|
|
30027
|
+
};
|
|
30028
|
+
}
|
|
30029
|
+
return holdings;
|
|
30030
|
+
} catch (error) {
|
|
30031
|
+
logger.error(`error getting holdings - exception: ${error}`);
|
|
29620
30032
|
return void 0;
|
|
29621
30033
|
}
|
|
29622
|
-
return holdings;
|
|
29623
30034
|
}
|
|
29624
30035
|
async setLeverage(leverage, marketName) {
|
|
29625
30036
|
if (this.client === null) {
|
|
@@ -29661,21 +30072,24 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29661
30072
|
return result.data;
|
|
29662
30073
|
}
|
|
29663
30074
|
async getOrderStatus(orderId, marketName) {
|
|
29664
|
-
|
|
29665
|
-
|
|
29666
|
-
|
|
29667
|
-
|
|
29668
|
-
|
|
29669
|
-
|
|
29670
|
-
|
|
30075
|
+
try {
|
|
30076
|
+
if (this.client === null) {
|
|
30077
|
+
logger.error("error initializing client");
|
|
30078
|
+
return null;
|
|
30079
|
+
}
|
|
30080
|
+
const orderhistory = await this.getOrderHistory(marketName);
|
|
30081
|
+
if (!orderhistory || orderhistory.length === 0) {
|
|
30082
|
+
return null;
|
|
30083
|
+
}
|
|
30084
|
+
const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
|
|
30085
|
+
if (order) {
|
|
30086
|
+
return order;
|
|
30087
|
+
}
|
|
29671
30088
|
return null;
|
|
29672
|
-
}
|
|
29673
|
-
|
|
29674
|
-
if (!order) {
|
|
29675
|
-
logger.error(`error getting order: ${order}`);
|
|
30089
|
+
} catch (error) {
|
|
30090
|
+
logger.error(`error getting order status: ${error}`);
|
|
29676
30091
|
return null;
|
|
29677
30092
|
}
|
|
29678
|
-
return order;
|
|
29679
30093
|
}
|
|
29680
30094
|
async fetchOrderBookBTCUSDC() {
|
|
29681
30095
|
try {
|
|
@@ -29726,14 +30140,40 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29726
30140
|
logger.error("error depositing or setting leverage");
|
|
29727
30141
|
return null;
|
|
29728
30142
|
}
|
|
29729
|
-
const
|
|
29730
|
-
if (
|
|
30143
|
+
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
30144
|
+
if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
|
|
30145
|
+
logger.error(
|
|
30146
|
+
`Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
|
|
30147
|
+
);
|
|
29731
30148
|
return null;
|
|
29732
30149
|
}
|
|
29733
|
-
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
29734
30150
|
const spread = ask.minus(bid);
|
|
29735
|
-
|
|
29736
|
-
|
|
30151
|
+
const midPrice = ask.plus(bid).div(2);
|
|
30152
|
+
const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
|
|
30153
|
+
const priceAdjustmentMultiplier = Math.min(
|
|
30154
|
+
0.2 * attempt,
|
|
30155
|
+
MAX_PRICE_DEVIATION_MULTIPLIER
|
|
30156
|
+
);
|
|
30157
|
+
const priceAdjustment = spread.times(priceAdjustmentMultiplier);
|
|
30158
|
+
let price = midPrice;
|
|
30159
|
+
if (side === "SELL" /* SELL */) {
|
|
30160
|
+
price = midPrice.minus(priceAdjustment);
|
|
30161
|
+
} else {
|
|
30162
|
+
price = midPrice.plus(priceAdjustment);
|
|
30163
|
+
}
|
|
30164
|
+
const maxDeviation = midPrice.times(0.5);
|
|
30165
|
+
if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
|
|
30166
|
+
logger.error(
|
|
30167
|
+
`Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
|
|
30168
|
+
);
|
|
30169
|
+
if (attempt >= maxAttempts) {
|
|
30170
|
+
return null;
|
|
30171
|
+
}
|
|
30172
|
+
price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
|
|
30173
|
+
}
|
|
30174
|
+
logger.info(
|
|
30175
|
+
`createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
|
|
30176
|
+
);
|
|
29737
30177
|
const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
|
|
29738
30178
|
this.config.extendedPrecision
|
|
29739
30179
|
);
|
|
@@ -29744,14 +30184,57 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29744
30184
|
price.toFixed(0),
|
|
29745
30185
|
side
|
|
29746
30186
|
);
|
|
29747
|
-
if (!result) {
|
|
30187
|
+
if (!result || !result.position_id) {
|
|
30188
|
+
logger.error("Failed to create order - no position_id returned");
|
|
29748
30189
|
return null;
|
|
29749
30190
|
}
|
|
29750
|
-
|
|
29751
|
-
|
|
29752
|
-
|
|
30191
|
+
const positionId = result.position_id;
|
|
30192
|
+
logger.info(
|
|
30193
|
+
`Order created with position_id: ${positionId}. Waiting for API to update...`
|
|
30194
|
+
);
|
|
30195
|
+
let openOrder = await this.getOrderStatus(
|
|
30196
|
+
positionId,
|
|
30197
|
+
this.config.extendedMarketName
|
|
30198
|
+
);
|
|
30199
|
+
const maxStatusRetries = 3;
|
|
30200
|
+
const statusRetryDelay = 5e3;
|
|
30201
|
+
if (!openOrder) {
|
|
30202
|
+
logger.warn(
|
|
30203
|
+
`Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
|
|
30204
|
+
);
|
|
30205
|
+
for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
|
|
30206
|
+
await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
|
|
30207
|
+
openOrder = await this.getOrderStatus(
|
|
30208
|
+
positionId,
|
|
30209
|
+
this.config.extendedMarketName
|
|
30210
|
+
);
|
|
30211
|
+
if (openOrder) {
|
|
30212
|
+
logger.info(
|
|
30213
|
+
`Order ${positionId} found after ${statusRetry} status retry(ies)`
|
|
30214
|
+
);
|
|
30215
|
+
break;
|
|
30216
|
+
}
|
|
30217
|
+
logger.warn(
|
|
30218
|
+
`Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
|
|
30219
|
+
);
|
|
30220
|
+
}
|
|
30221
|
+
}
|
|
30222
|
+
if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
|
|
30223
|
+
logger.info(
|
|
30224
|
+
`Order ${positionId} successfully filled with quantity ${openOrder.qty}`
|
|
30225
|
+
);
|
|
30226
|
+
return {
|
|
30227
|
+
position_id: positionId,
|
|
30228
|
+
btc_exposure: openOrder.qty
|
|
30229
|
+
};
|
|
30230
|
+
} else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
|
|
30231
|
+
logger.warn(
|
|
30232
|
+
`Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
|
|
30233
|
+
);
|
|
29753
30234
|
if (attempt >= maxAttempts) {
|
|
29754
|
-
logger.error(
|
|
30235
|
+
logger.error(
|
|
30236
|
+
`Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
|
|
30237
|
+
);
|
|
29755
30238
|
return null;
|
|
29756
30239
|
} else {
|
|
29757
30240
|
const backoff = 2e3 * attempt;
|
|
@@ -29765,16 +30248,21 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29765
30248
|
);
|
|
29766
30249
|
}
|
|
29767
30250
|
} else {
|
|
30251
|
+
logger.warn(
|
|
30252
|
+
`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.`
|
|
30253
|
+
);
|
|
29768
30254
|
return {
|
|
29769
|
-
position_id:
|
|
29770
|
-
btc_exposure:
|
|
30255
|
+
position_id: positionId,
|
|
30256
|
+
btc_exposure: amount_in_token
|
|
29771
30257
|
};
|
|
29772
30258
|
}
|
|
29773
30259
|
} catch (err) {
|
|
29774
|
-
logger.error(
|
|
30260
|
+
logger.error(
|
|
30261
|
+
`createShortOrder failed on attempt ${attempt}: ${err.message}`
|
|
30262
|
+
);
|
|
29775
30263
|
if (attempt < maxAttempts) {
|
|
29776
30264
|
const backoff = 1200 * attempt;
|
|
29777
|
-
|
|
30265
|
+
logger.info(`Retrying after ${backoff}ms...`);
|
|
29778
30266
|
await new Promise((resolve) => setTimeout(resolve, backoff));
|
|
29779
30267
|
return this.createOrder(
|
|
29780
30268
|
leverage,
|
|
@@ -29805,34 +30293,106 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29805
30293
|
}
|
|
29806
30294
|
return null;
|
|
29807
30295
|
} catch (err) {
|
|
29808
|
-
|
|
30296
|
+
logger.error(`Error opening short extended position, ${err}`);
|
|
29809
30297
|
return null;
|
|
29810
30298
|
}
|
|
29811
30299
|
}
|
|
29812
30300
|
async getDepositOrWithdrawalStatus(orderId, operationsType) {
|
|
29813
|
-
|
|
29814
|
-
|
|
29815
|
-
|
|
29816
|
-
|
|
29817
|
-
|
|
29818
|
-
|
|
29819
|
-
|
|
29820
|
-
|
|
29821
|
-
if (
|
|
29822
|
-
|
|
30301
|
+
const maxAttempts = 15;
|
|
30302
|
+
const retryDelayMs = 3e4;
|
|
30303
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
30304
|
+
try {
|
|
30305
|
+
let transferHistory = await this.client.getAssetOperations({
|
|
30306
|
+
operationsType: [operationsType],
|
|
30307
|
+
operationsStatus: ["COMPLETED" /* COMPLETED */]
|
|
30308
|
+
});
|
|
30309
|
+
if (operationsType === "DEPOSIT" /* DEPOSIT */) {
|
|
30310
|
+
const myTransferStatus = transferHistory.data.find(
|
|
30311
|
+
(operation) => operation.transactionHash === orderId
|
|
30312
|
+
);
|
|
30313
|
+
if (!myTransferStatus) {
|
|
30314
|
+
if (attempt < maxAttempts) {
|
|
30315
|
+
logger.info(
|
|
30316
|
+
`Deposit operation not found for transactionHash ${orderId}, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30317
|
+
);
|
|
30318
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30319
|
+
continue;
|
|
30320
|
+
}
|
|
30321
|
+
logger.warn(
|
|
30322
|
+
`Deposit operation not found for transactionHash ${orderId} after ${maxAttempts} attempts`
|
|
30323
|
+
);
|
|
30324
|
+
return false;
|
|
30325
|
+
}
|
|
30326
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
30327
|
+
logger.info(
|
|
30328
|
+
`Deposit operation ${orderId} completed successfully`
|
|
30329
|
+
);
|
|
30330
|
+
return true;
|
|
30331
|
+
} else {
|
|
30332
|
+
if (attempt < maxAttempts) {
|
|
30333
|
+
logger.info(
|
|
30334
|
+
`Deposit operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30335
|
+
);
|
|
30336
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30337
|
+
continue;
|
|
30338
|
+
}
|
|
30339
|
+
logger.warn(
|
|
30340
|
+
`Deposit operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
30341
|
+
);
|
|
30342
|
+
return false;
|
|
30343
|
+
}
|
|
30344
|
+
} else {
|
|
30345
|
+
const myTransferStatus = transferHistory.data.find(
|
|
30346
|
+
(operation) => operation.id.toString() === orderId.toString()
|
|
30347
|
+
);
|
|
30348
|
+
if (!myTransferStatus) {
|
|
30349
|
+
if (attempt < maxAttempts) {
|
|
30350
|
+
logger.info(
|
|
30351
|
+
`Withdrawal status not found for orderId ${orderId} in completed operations, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30352
|
+
);
|
|
30353
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30354
|
+
continue;
|
|
30355
|
+
}
|
|
30356
|
+
logger.warn(
|
|
30357
|
+
`Withdrawal operation not found for orderId ${orderId} after ${maxAttempts} attempts`
|
|
30358
|
+
);
|
|
30359
|
+
return false;
|
|
30360
|
+
}
|
|
30361
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
30362
|
+
logger.info(
|
|
30363
|
+
`Withdrawal operation ${orderId} completed successfully`
|
|
30364
|
+
);
|
|
30365
|
+
return true;
|
|
30366
|
+
} else {
|
|
30367
|
+
if (attempt < maxAttempts) {
|
|
30368
|
+
logger.info(
|
|
30369
|
+
`Withdrawal operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30370
|
+
);
|
|
30371
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30372
|
+
continue;
|
|
30373
|
+
}
|
|
30374
|
+
logger.warn(
|
|
30375
|
+
`Withdrawal operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
30376
|
+
);
|
|
30377
|
+
return false;
|
|
30378
|
+
}
|
|
29823
30379
|
}
|
|
29824
|
-
|
|
29825
|
-
|
|
29826
|
-
|
|
29827
|
-
|
|
29828
|
-
|
|
30380
|
+
} catch (err) {
|
|
30381
|
+
logger.error(
|
|
30382
|
+
`error getting deposit or withdrawal status (attempt ${attempt}/${maxAttempts}): ${err}`
|
|
30383
|
+
);
|
|
30384
|
+
if (attempt < maxAttempts) {
|
|
30385
|
+
logger.info(`Retrying after ${retryDelayMs}ms...`);
|
|
30386
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30387
|
+
continue;
|
|
29829
30388
|
}
|
|
29830
|
-
|
|
30389
|
+
logger.error(
|
|
30390
|
+
`Max retry attempts reached for getDepositOrWithdrawalStatus`
|
|
30391
|
+
);
|
|
30392
|
+
return false;
|
|
29831
30393
|
}
|
|
29832
|
-
} catch (err) {
|
|
29833
|
-
logger.error(`error getting deposit or withdrawal status: ${err}`);
|
|
29834
|
-
return false;
|
|
29835
30394
|
}
|
|
30395
|
+
return false;
|
|
29836
30396
|
}
|
|
29837
30397
|
};
|
|
29838
30398
|
|
|
@@ -29918,6 +30478,11 @@ var AUMTypes = /* @__PURE__ */ ((AUMTypes2) => {
|
|
|
29918
30478
|
AUMTypes2["DEFISPRING"] = "defispring";
|
|
29919
30479
|
return AUMTypes2;
|
|
29920
30480
|
})(AUMTypes || {});
|
|
30481
|
+
var PositionTypeAvnuExtended = /* @__PURE__ */ ((PositionTypeAvnuExtended2) => {
|
|
30482
|
+
PositionTypeAvnuExtended2["OPEN"] = "open";
|
|
30483
|
+
PositionTypeAvnuExtended2["CLOSE"] = "close";
|
|
30484
|
+
return PositionTypeAvnuExtended2;
|
|
30485
|
+
})(PositionTypeAvnuExtended || {});
|
|
29921
30486
|
var UNIVERSAL_MANAGE_IDS = /* @__PURE__ */ ((UNIVERSAL_MANAGE_IDS2) => {
|
|
29922
30487
|
UNIVERSAL_MANAGE_IDS2["FLASH_LOAN"] = "flash_loan_init";
|
|
29923
30488
|
UNIVERSAL_MANAGE_IDS2["VESU_LEG1"] = "vesu_leg1";
|
|
@@ -33098,7 +33663,8 @@ function getLooperSettings(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
|
|
|
33098
33663
|
minHealthFactor: vaultSettings.minHealthFactor,
|
|
33099
33664
|
quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
|
|
33100
33665
|
...baseAdapterConfig,
|
|
33101
|
-
supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }]
|
|
33666
|
+
supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
|
|
33667
|
+
minimumVesuMovementAmount: 0
|
|
33102
33668
|
}));
|
|
33103
33669
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
33104
33670
|
...baseAdapterConfig
|
|
@@ -33414,7 +33980,7 @@ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
|
|
|
33414
33980
|
packedArguments: [
|
|
33415
33981
|
fromToken.address.toBigInt(),
|
|
33416
33982
|
//wbtc
|
|
33417
|
-
|
|
33983
|
+
toToken.address.toBigInt(),
|
|
33418
33984
|
//usdc
|
|
33419
33985
|
vaultAllocator.toBigInt()
|
|
33420
33986
|
],
|
|
@@ -33428,13 +33994,11 @@ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
|
|
|
33428
33994
|
}
|
|
33429
33995
|
async getDepositCall(params) {
|
|
33430
33996
|
try {
|
|
33431
|
-
console.log("params.amount", params.amount);
|
|
33432
33997
|
const fromToken = this.config.supportedPositions[0].asset;
|
|
33433
33998
|
const toToken = this.config.supportedPositions[1].asset;
|
|
33434
33999
|
const vaultAllocator = ContractAddr.from(
|
|
33435
34000
|
this.config.vaultAllocator.address
|
|
33436
34001
|
);
|
|
33437
|
-
console.log("vaultAllocator", vaultAllocator);
|
|
33438
34002
|
const quote = await this.getQuotesAvnu(
|
|
33439
34003
|
fromToken.address.toString(),
|
|
33440
34004
|
toToken.address.toString(),
|
|
@@ -33490,7 +34054,6 @@ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
|
|
|
33490
34054
|
const vaultAllocator = ContractAddr.from(
|
|
33491
34055
|
this.config.vaultAllocator.address
|
|
33492
34056
|
);
|
|
33493
|
-
console.log("params.amount", params.amount);
|
|
33494
34057
|
const quote = await this.getQuotesAvnu(
|
|
33495
34058
|
fromToken.address.toString(),
|
|
33496
34059
|
toToken.address.toString(),
|
|
@@ -33509,8 +34072,6 @@ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
|
|
|
33509
34072
|
);
|
|
33510
34073
|
const swapCallData = getCalldata[0];
|
|
33511
34074
|
const amount = uint25614.bnToUint256(params.amount.toWei());
|
|
33512
|
-
console.log("amount", amount);
|
|
33513
|
-
console.log("swapCallData", swapCallData);
|
|
33514
34075
|
return [
|
|
33515
34076
|
{
|
|
33516
34077
|
sanitizer: SIMPLE_SANITIZER,
|
|
@@ -33564,7 +34125,7 @@ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
|
|
|
33564
34125
|
}
|
|
33565
34126
|
throw new Error("Failed to fetch quote after retries");
|
|
33566
34127
|
}
|
|
33567
|
-
async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance =
|
|
34128
|
+
async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance = 5e3) {
|
|
33568
34129
|
try {
|
|
33569
34130
|
const fromToken = this.config.supportedPositions[0].asset;
|
|
33570
34131
|
const toToken = this.config.supportedPositions[1].asset;
|
|
@@ -33585,14 +34146,12 @@ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
|
|
|
33585
34146
|
return dataObject2;
|
|
33586
34147
|
}
|
|
33587
34148
|
const btcPrice = await this.getPriceOfToken(toToken.address.toString());
|
|
33588
|
-
console.log("btcPrice", btcPrice);
|
|
33589
34149
|
if (!btcPrice) {
|
|
33590
34150
|
logger.error(`error getting btc price: ${btcPrice}`);
|
|
33591
34151
|
return null;
|
|
33592
34152
|
}
|
|
33593
34153
|
const estimatedUsdcAmount = Math.floor(amount * btcPrice);
|
|
33594
34154
|
const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
|
|
33595
|
-
console.log("targetBtcBig", targetBtcBig);
|
|
33596
34155
|
let low = BigInt(
|
|
33597
34156
|
Math.floor(
|
|
33598
34157
|
estimatedUsdcAmount * 10 ** fromToken.decimals * 0.9
|
|
@@ -33695,6 +34254,23 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33695
34254
|
debtPrice
|
|
33696
34255
|
};
|
|
33697
34256
|
}
|
|
34257
|
+
async getUnusedBalanceUSDCE() {
|
|
34258
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
34259
|
+
(token) => token.symbol === "USDCe"
|
|
34260
|
+
);
|
|
34261
|
+
const balance = await new ERC20(this.config).balanceOf(
|
|
34262
|
+
usdceToken.address,
|
|
34263
|
+
WALLET_ADDRESS,
|
|
34264
|
+
usdceToken.decimals
|
|
34265
|
+
);
|
|
34266
|
+
const price = await this.pricer.getPrice(usdceToken.symbol);
|
|
34267
|
+
const usdValue = Number(balance.toFixed(usdceToken.decimals)) * price.price;
|
|
34268
|
+
return {
|
|
34269
|
+
tokenInfo: usdceToken,
|
|
34270
|
+
amount: balance,
|
|
34271
|
+
usdValue
|
|
34272
|
+
};
|
|
34273
|
+
}
|
|
33698
34274
|
async getUnusedBalanceWBTC() {
|
|
33699
34275
|
const collateralToken = this.metadata.additionalInfo.borrowable_assets[0];
|
|
33700
34276
|
const balance = await new ERC20(this.config).balanceOf(
|
|
@@ -33740,22 +34316,30 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33740
34316
|
}
|
|
33741
34317
|
return extendedAdapter.adapter;
|
|
33742
34318
|
}
|
|
33743
|
-
async moveAssetsToVaultAllocator(amount) {
|
|
34319
|
+
async moveAssetsToVaultAllocator(amount, extendedAdapter) {
|
|
33744
34320
|
try {
|
|
33745
|
-
const
|
|
33746
|
-
(token) => token.symbol === "
|
|
34321
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
34322
|
+
(token) => token.symbol === "USDCe"
|
|
33747
34323
|
);
|
|
33748
34324
|
const approveCall = new ERC20(this.config).approve(
|
|
33749
|
-
|
|
34325
|
+
usdceToken.address,
|
|
33750
34326
|
this.metadata.additionalInfo.vaultAllocator,
|
|
33751
34327
|
amount
|
|
33752
34328
|
);
|
|
33753
34329
|
const transferCall = new ERC20(this.config).transfer(
|
|
33754
|
-
|
|
34330
|
+
usdceToken.address,
|
|
33755
34331
|
this.metadata.additionalInfo.vaultAllocator,
|
|
33756
34332
|
amount
|
|
33757
34333
|
);
|
|
33758
|
-
|
|
34334
|
+
const proofsInfo = extendedAdapter.getProofsForFromLegacySwap(
|
|
34335
|
+
this.getMerkleTree()
|
|
34336
|
+
);
|
|
34337
|
+
const proofGroups = proofsInfo.proofs;
|
|
34338
|
+
const call = this.getManageCall(
|
|
34339
|
+
proofGroups,
|
|
34340
|
+
await proofsInfo.callConstructor({ amount })
|
|
34341
|
+
);
|
|
34342
|
+
return [approveCall, transferCall, call];
|
|
33759
34343
|
} catch (err) {
|
|
33760
34344
|
logger.error(`error moving assets to vault allocator: ${err}`);
|
|
33761
34345
|
return [];
|
|
@@ -33763,11 +34347,13 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33763
34347
|
}
|
|
33764
34348
|
async shouldInvest() {
|
|
33765
34349
|
try {
|
|
34350
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
|
|
33766
34351
|
const vesuAdapter = await this.getVesuAdapter();
|
|
33767
34352
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
33768
|
-
|
|
34353
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
|
|
34354
|
+
if (!vesuAdapter) {
|
|
33769
34355
|
logger.error(
|
|
33770
|
-
`
|
|
34356
|
+
`Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
33771
34357
|
);
|
|
33772
34358
|
return {
|
|
33773
34359
|
shouldInvest: false,
|
|
@@ -33779,10 +34365,87 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33779
34365
|
vesuLeverage: 0
|
|
33780
34366
|
};
|
|
33781
34367
|
}
|
|
34368
|
+
if (!extendedAdapter) {
|
|
34369
|
+
logger.error(
|
|
34370
|
+
`Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
34371
|
+
);
|
|
34372
|
+
return {
|
|
34373
|
+
shouldInvest: false,
|
|
34374
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34375
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34376
|
+
extendedLeverage: 0,
|
|
34377
|
+
collateralPrice: 0,
|
|
34378
|
+
debtPrice: 0,
|
|
34379
|
+
vesuLeverage: 0
|
|
34380
|
+
};
|
|
34381
|
+
}
|
|
34382
|
+
if (!extendedAdapter.client) {
|
|
34383
|
+
logger.error(
|
|
34384
|
+
`Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
|
|
34385
|
+
);
|
|
34386
|
+
return {
|
|
34387
|
+
shouldInvest: false,
|
|
34388
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34389
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34390
|
+
extendedLeverage: 0,
|
|
34391
|
+
collateralPrice: 0,
|
|
34392
|
+
debtPrice: 0,
|
|
34393
|
+
vesuLeverage: 0
|
|
34394
|
+
};
|
|
34395
|
+
}
|
|
34396
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
|
|
33782
34397
|
const balance = await this.getUnusedBalance();
|
|
34398
|
+
if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
|
|
34399
|
+
logger.error(
|
|
34400
|
+
`Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
|
|
34401
|
+
);
|
|
34402
|
+
return {
|
|
34403
|
+
shouldInvest: false,
|
|
34404
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34405
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34406
|
+
extendedLeverage: 0,
|
|
34407
|
+
collateralPrice: 0,
|
|
34408
|
+
debtPrice: 0,
|
|
34409
|
+
vesuLeverage: 0
|
|
34410
|
+
};
|
|
34411
|
+
}
|
|
34412
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
|
|
33783
34413
|
const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
|
|
33784
|
-
|
|
33785
|
-
|
|
34414
|
+
if (usdcBalanceOnExtended) {
|
|
34415
|
+
const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
|
|
34416
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
34417
|
+
logger.error(
|
|
34418
|
+
`Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
34419
|
+
);
|
|
34420
|
+
return {
|
|
34421
|
+
shouldInvest: false,
|
|
34422
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34423
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34424
|
+
extendedLeverage: 0,
|
|
34425
|
+
collateralPrice: 0,
|
|
34426
|
+
debtPrice: 0,
|
|
34427
|
+
vesuLeverage: 0
|
|
34428
|
+
};
|
|
34429
|
+
}
|
|
34430
|
+
}
|
|
34431
|
+
const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
|
|
34432
|
+
const amountToInvestNumber = amountToInvest.toNumber();
|
|
34433
|
+
if (!Number.isFinite(amountToInvestNumber)) {
|
|
34434
|
+
logger.error(
|
|
34435
|
+
`Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
|
|
34436
|
+
);
|
|
34437
|
+
return {
|
|
34438
|
+
shouldInvest: false,
|
|
34439
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34440
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34441
|
+
extendedLeverage: 0,
|
|
34442
|
+
collateralPrice: 0,
|
|
34443
|
+
debtPrice: 0,
|
|
34444
|
+
vesuLeverage: 0
|
|
34445
|
+
};
|
|
34446
|
+
}
|
|
34447
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
|
|
34448
|
+
if (amountToInvest.lessThan(LIMIT_BALANCE_VALUE)) {
|
|
33786
34449
|
return {
|
|
33787
34450
|
shouldInvest: false,
|
|
33788
34451
|
vesuAmount: new Web3Number(0, 0),
|
|
@@ -33811,6 +34474,34 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33811
34474
|
collateralPrice,
|
|
33812
34475
|
debtPrice
|
|
33813
34476
|
} = await this.getAssetPrices();
|
|
34477
|
+
if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
|
|
34478
|
+
logger.error(
|
|
34479
|
+
`Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
|
|
34480
|
+
);
|
|
34481
|
+
return {
|
|
34482
|
+
shouldInvest: false,
|
|
34483
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34484
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34485
|
+
extendedLeverage: 0,
|
|
34486
|
+
collateralPrice: 0,
|
|
34487
|
+
debtPrice: 0,
|
|
34488
|
+
vesuLeverage: 0
|
|
34489
|
+
};
|
|
34490
|
+
}
|
|
34491
|
+
if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
|
|
34492
|
+
logger.error(
|
|
34493
|
+
`Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
|
|
34494
|
+
);
|
|
34495
|
+
return {
|
|
34496
|
+
shouldInvest: false,
|
|
34497
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34498
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34499
|
+
extendedLeverage: 0,
|
|
34500
|
+
collateralPrice: 0,
|
|
34501
|
+
debtPrice: 0,
|
|
34502
|
+
vesuLeverage: 0
|
|
34503
|
+
};
|
|
34504
|
+
}
|
|
33814
34505
|
const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
|
|
33815
34506
|
amountToInvest.toNumber(),
|
|
33816
34507
|
extendedAdapter.client,
|
|
@@ -33834,6 +34525,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33834
34525
|
vesuLeverage: 0
|
|
33835
34526
|
};
|
|
33836
34527
|
}
|
|
34528
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`);
|
|
33837
34529
|
return {
|
|
33838
34530
|
shouldInvest: true,
|
|
33839
34531
|
vesuAmount: vesu_amount,
|
|
@@ -33860,18 +34552,48 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33860
34552
|
try {
|
|
33861
34553
|
const vesuAdapter = await this.getVesuAdapter();
|
|
33862
34554
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
33863
|
-
let calls = [];
|
|
33864
34555
|
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
|
|
33865
34556
|
logger.error(
|
|
33866
34557
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
33867
34558
|
);
|
|
33868
|
-
return
|
|
34559
|
+
return [];
|
|
33869
34560
|
}
|
|
33870
|
-
|
|
33871
|
-
|
|
33872
|
-
|
|
34561
|
+
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34562
|
+
if (!extendedHoldings) {
|
|
34563
|
+
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
34564
|
+
return [];
|
|
34565
|
+
}
|
|
34566
|
+
const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
|
|
34567
|
+
const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
|
|
34568
|
+
extendedHoldings.availableForWithdrawal
|
|
34569
|
+
);
|
|
34570
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
|
|
34571
|
+
let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
34572
|
+
let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
34573
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34574
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
|
|
34575
|
+
}
|
|
34576
|
+
const extendedTargetAmount = extendedAmount.abs();
|
|
34577
|
+
let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
|
|
34578
|
+
if (extendedAmount.isNegative()) {
|
|
34579
|
+
projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
|
|
34580
|
+
}
|
|
34581
|
+
const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
|
|
34582
|
+
const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
|
|
34583
|
+
if (extendedAmountDifference.lessThan(0)) {
|
|
34584
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
|
|
34585
|
+
} else if (extendedAmountDifference.greaterThan(0)) {
|
|
34586
|
+
totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
|
|
34587
|
+
}
|
|
34588
|
+
const vesuTargetAmount = vesuAmount.abs();
|
|
34589
|
+
const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
|
|
34590
|
+
let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
|
|
34591
|
+
const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
|
|
34592
|
+
logger.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()}`);
|
|
34593
|
+
let calls = [];
|
|
34594
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
33873
34595
|
try {
|
|
33874
|
-
const extendedCalls = await this.moveAssets(
|
|
34596
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
33875
34597
|
{
|
|
33876
34598
|
to: Protocols.VAULT.name,
|
|
33877
34599
|
from: Protocols.EXTENDED.name,
|
|
@@ -33880,14 +34602,18 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33880
34602
|
extendedAdapter,
|
|
33881
34603
|
vesuAdapter
|
|
33882
34604
|
);
|
|
33883
|
-
|
|
34605
|
+
if (extendedStatus) {
|
|
34606
|
+
calls.push(...extendedCalls);
|
|
34607
|
+
} else {
|
|
34608
|
+
return [];
|
|
34609
|
+
}
|
|
33884
34610
|
} catch (err) {
|
|
33885
34611
|
logger.error(`Failed moving assets to vault: ${err}`);
|
|
33886
34612
|
}
|
|
33887
34613
|
}
|
|
33888
|
-
if (vesuAmount.
|
|
34614
|
+
if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
33889
34615
|
try {
|
|
33890
|
-
const vesuCalls = await this.moveAssets(
|
|
34616
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
33891
34617
|
{
|
|
33892
34618
|
to: Protocols.EXTENDED.name,
|
|
33893
34619
|
from: Protocols.VESU.name,
|
|
@@ -33897,49 +34623,83 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33897
34623
|
vesuAdapter
|
|
33898
34624
|
);
|
|
33899
34625
|
calls.push(...vesuCalls);
|
|
34626
|
+
if (!vesuStatus) {
|
|
34627
|
+
return [];
|
|
34628
|
+
}
|
|
33900
34629
|
} catch (err) {
|
|
33901
34630
|
logger.error(`Failed moving assets to vault: ${err}`);
|
|
33902
34631
|
}
|
|
33903
34632
|
}
|
|
33904
|
-
|
|
33905
|
-
|
|
33906
|
-
|
|
33907
|
-
|
|
33908
|
-
|
|
33909
|
-
|
|
33910
|
-
|
|
33911
|
-
|
|
33912
|
-
|
|
33913
|
-
|
|
33914
|
-
|
|
33915
|
-
|
|
33916
|
-
{
|
|
33917
|
-
|
|
33918
|
-
|
|
33919
|
-
|
|
33920
|
-
|
|
33921
|
-
|
|
33922
|
-
|
|
33923
|
-
|
|
33924
|
-
|
|
33925
|
-
|
|
33926
|
-
|
|
34633
|
+
if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34634
|
+
if (extendedAmountDifference.greaterThan(0)) {
|
|
34635
|
+
try {
|
|
34636
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
34637
|
+
{
|
|
34638
|
+
to: Protocols.EXTENDED.name,
|
|
34639
|
+
from: Protocols.VAULT.name,
|
|
34640
|
+
amount: extendedAmountDifference
|
|
34641
|
+
},
|
|
34642
|
+
extendedAdapter,
|
|
34643
|
+
vesuAdapter
|
|
34644
|
+
);
|
|
34645
|
+
if (extendedStatus) {
|
|
34646
|
+
calls.push(...extendedCalls);
|
|
34647
|
+
} else {
|
|
34648
|
+
logger.error(`Failed to move assets to extended - operation returned false status`);
|
|
34649
|
+
return [];
|
|
34650
|
+
}
|
|
34651
|
+
} catch (err) {
|
|
34652
|
+
logger.error(`Failed moving assets to extended: ${err}`);
|
|
34653
|
+
return [];
|
|
34654
|
+
}
|
|
34655
|
+
} else if (extendedAmountDifference.lessThan(0)) {
|
|
34656
|
+
try {
|
|
34657
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
34658
|
+
{
|
|
34659
|
+
to: Protocols.VAULT.name,
|
|
34660
|
+
from: Protocols.EXTENDED.name,
|
|
34661
|
+
amount: extendedAmountDifferenceAbs
|
|
34662
|
+
},
|
|
34663
|
+
extendedAdapter,
|
|
34664
|
+
vesuAdapter
|
|
34665
|
+
);
|
|
34666
|
+
if (extendedStatus) {
|
|
34667
|
+
calls.push(...extendedCalls);
|
|
34668
|
+
} else {
|
|
34669
|
+
logger.error(`Failed to withdraw from extended - operation returned false status`);
|
|
34670
|
+
return [];
|
|
34671
|
+
}
|
|
34672
|
+
} catch (err) {
|
|
34673
|
+
logger.error(`Failed moving assets from extended to vault: ${err}`);
|
|
34674
|
+
return [];
|
|
34675
|
+
}
|
|
33927
34676
|
}
|
|
33928
34677
|
}
|
|
33929
|
-
if (
|
|
33930
|
-
|
|
33931
|
-
|
|
33932
|
-
{
|
|
33933
|
-
to: Protocols.VESU.name,
|
|
33934
|
-
from: Protocols.EXTENDED.name,
|
|
33935
|
-
amount: vesuAmount.minus(usdcAmountInWallet)
|
|
33936
|
-
},
|
|
33937
|
-
extendedAdapter,
|
|
33938
|
-
vesuAdapter
|
|
34678
|
+
if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34679
|
+
if (vesuAmountDifference.lessThanOrEqualTo(0)) {
|
|
34680
|
+
logger.warn(
|
|
34681
|
+
`Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
|
|
33939
34682
|
);
|
|
33940
|
-
|
|
33941
|
-
|
|
33942
|
-
|
|
34683
|
+
} else {
|
|
34684
|
+
try {
|
|
34685
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
34686
|
+
{
|
|
34687
|
+
to: Protocols.VAULT.name,
|
|
34688
|
+
from: Protocols.EXTENDED.name,
|
|
34689
|
+
amount: vesuAmountDifference
|
|
34690
|
+
},
|
|
34691
|
+
extendedAdapter,
|
|
34692
|
+
vesuAdapter
|
|
34693
|
+
);
|
|
34694
|
+
if (!vesuStatus) {
|
|
34695
|
+
logger.error(`Failed to move assets to vesu - operation returned false status`);
|
|
34696
|
+
return [];
|
|
34697
|
+
}
|
|
34698
|
+
calls.push(...vesuCalls);
|
|
34699
|
+
} catch (err) {
|
|
34700
|
+
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34701
|
+
return [];
|
|
34702
|
+
}
|
|
33943
34703
|
}
|
|
33944
34704
|
}
|
|
33945
34705
|
return calls;
|
|
@@ -33950,12 +34710,47 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33950
34710
|
}
|
|
33951
34711
|
async moveAssets(params, extendedAdapter, vesuAdapter) {
|
|
33952
34712
|
try {
|
|
34713
|
+
if (params.amount.lessThanOrEqualTo(0)) {
|
|
34714
|
+
logger.error(
|
|
34715
|
+
`Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
|
|
34716
|
+
);
|
|
34717
|
+
return {
|
|
34718
|
+
calls: [],
|
|
34719
|
+
status: false
|
|
34720
|
+
};
|
|
34721
|
+
}
|
|
34722
|
+
const amountAbs = params.amount.abs();
|
|
34723
|
+
if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
|
|
34724
|
+
if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34725
|
+
logger.warn(
|
|
34726
|
+
`Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
|
|
34727
|
+
);
|
|
34728
|
+
return {
|
|
34729
|
+
calls: [],
|
|
34730
|
+
status: false
|
|
34731
|
+
};
|
|
34732
|
+
}
|
|
34733
|
+
}
|
|
34734
|
+
if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
|
|
34735
|
+
if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34736
|
+
logger.warn(
|
|
34737
|
+
`Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
|
|
34738
|
+
);
|
|
34739
|
+
return {
|
|
34740
|
+
calls: [],
|
|
34741
|
+
status: false
|
|
34742
|
+
};
|
|
34743
|
+
}
|
|
34744
|
+
}
|
|
33953
34745
|
const avnuAdapter = await this.getAvnuAdapter();
|
|
33954
34746
|
if (!avnuAdapter) {
|
|
33955
34747
|
logger.error(`avnu adapter not found: ${avnuAdapter}`);
|
|
33956
|
-
return
|
|
34748
|
+
return {
|
|
34749
|
+
calls: [],
|
|
34750
|
+
status: false
|
|
34751
|
+
};
|
|
33957
34752
|
}
|
|
33958
|
-
logger.info(
|
|
34753
|
+
logger.info(`moveAssets params, ${JSON.stringify(params)}`);
|
|
33959
34754
|
const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
|
|
33960
34755
|
const {
|
|
33961
34756
|
collateralPrice
|
|
@@ -33972,19 +34767,76 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33972
34767
|
await proofsInfo.callConstructor({ amount: params.amount })
|
|
33973
34768
|
);
|
|
33974
34769
|
calls.push(call);
|
|
33975
|
-
return
|
|
34770
|
+
return {
|
|
34771
|
+
calls: [call],
|
|
34772
|
+
status: true
|
|
34773
|
+
};
|
|
33976
34774
|
} else if (params.to === Protocols.VAULT.name && params.from === Protocols.EXTENDED.name) {
|
|
34775
|
+
const extendedLeverage = calculateExtendedLevergae();
|
|
34776
|
+
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34777
|
+
if (!extendedHoldings) {
|
|
34778
|
+
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
34779
|
+
return {
|
|
34780
|
+
calls: [],
|
|
34781
|
+
status: false
|
|
34782
|
+
};
|
|
34783
|
+
}
|
|
34784
|
+
const extendedHoldingAmount = new Web3Number(
|
|
34785
|
+
extendedHoldings.availableForWithdrawal,
|
|
34786
|
+
USDC_TOKEN_DECIMALS
|
|
34787
|
+
);
|
|
34788
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets extendedHoldingAmount: ${extendedHoldingAmount.toNumber()}`);
|
|
34789
|
+
if (params.amount.abs().greaterThan(extendedHoldingAmount)) {
|
|
34790
|
+
const leftAmountAfterWithdrawalAmountInAccount = params.amount.abs().minus(extendedHoldingAmount);
|
|
34791
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets leftAmountAfterWithdrawalAmountInAccount: ${leftAmountAfterWithdrawalAmountInAccount.toNumber()}`);
|
|
34792
|
+
const btcAmount = leftAmountAfterWithdrawalAmountInAccount.dividedBy(collateralPrice.price);
|
|
34793
|
+
const openLongPosition = btcAmount.multipliedBy(3).greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
|
|
34794
|
+
extendedLeverage.toString(),
|
|
34795
|
+
btcAmount.toNumber(),
|
|
34796
|
+
"BUY" /* BUY */
|
|
34797
|
+
) : await extendedAdapter.createOrder(
|
|
34798
|
+
extendedLeverage.toString(),
|
|
34799
|
+
35e-6,
|
|
34800
|
+
// just in case amount falls short then we need to create a withdrawal
|
|
34801
|
+
"BUY" /* BUY */
|
|
34802
|
+
);
|
|
34803
|
+
if (!openLongPosition) {
|
|
34804
|
+
logger.error(`error opening long position: ${openLongPosition}`);
|
|
34805
|
+
}
|
|
34806
|
+
const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34807
|
+
if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
|
|
34808
|
+
logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
|
|
34809
|
+
return { calls: [], status: false };
|
|
34810
|
+
}
|
|
34811
|
+
}
|
|
33977
34812
|
const withdrawalFromExtended = await extendedAdapter.withdrawFromExtended(params.amount);
|
|
33978
34813
|
if (withdrawalFromExtended) {
|
|
33979
|
-
const
|
|
34814
|
+
const extendedHoldings2 = await extendedAdapter.getExtendedDepositAmount();
|
|
34815
|
+
logger.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
|
|
34816
|
+
await new Promise((resolve) => setTimeout(resolve, 5e3));
|
|
34817
|
+
const calls = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
|
|
33980
34818
|
if (calls.length > 0) {
|
|
33981
|
-
return
|
|
34819
|
+
return {
|
|
34820
|
+
calls,
|
|
34821
|
+
status: true
|
|
34822
|
+
};
|
|
33982
34823
|
}
|
|
33983
34824
|
} else {
|
|
33984
34825
|
logger.error("withdrawal from extended failed");
|
|
34826
|
+
return {
|
|
34827
|
+
calls: [],
|
|
34828
|
+
status: false
|
|
34829
|
+
};
|
|
33985
34830
|
}
|
|
33986
|
-
return [];
|
|
33987
34831
|
} else if (params.to === Protocols.VAULT.name && params.from === Protocols.VESU.name) {
|
|
34832
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
|
|
34833
|
+
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
34834
|
+
logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
34835
|
+
return {
|
|
34836
|
+
calls: [],
|
|
34837
|
+
status: false
|
|
34838
|
+
};
|
|
34839
|
+
}
|
|
33988
34840
|
const vesuAmountInBTC = new Web3Number(
|
|
33989
34841
|
params.amount.dividedBy(collateralPrice.price).toNumber(),
|
|
33990
34842
|
collateralToken.decimals
|
|
@@ -34004,8 +34856,19 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34004
34856
|
await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
|
|
34005
34857
|
);
|
|
34006
34858
|
calls.push(swapCall);
|
|
34007
|
-
return
|
|
34859
|
+
return {
|
|
34860
|
+
calls,
|
|
34861
|
+
status: true
|
|
34862
|
+
};
|
|
34008
34863
|
} else if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VESU.name) {
|
|
34864
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
|
|
34865
|
+
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
34866
|
+
logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
34867
|
+
return {
|
|
34868
|
+
calls: [],
|
|
34869
|
+
status: false
|
|
34870
|
+
};
|
|
34871
|
+
}
|
|
34009
34872
|
const vesuAmountInBTC = new Web3Number(
|
|
34010
34873
|
params.amount.dividedBy(collateralPrice.price).toNumber(),
|
|
34011
34874
|
collateralToken.decimals
|
|
@@ -34035,13 +34898,21 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34035
34898
|
await proofsInfoDeposit.callConstructor({ amount: params.amount })
|
|
34036
34899
|
);
|
|
34037
34900
|
calls.push(callDeposit);
|
|
34038
|
-
return
|
|
34901
|
+
return {
|
|
34902
|
+
calls,
|
|
34903
|
+
status: true
|
|
34904
|
+
};
|
|
34039
34905
|
}
|
|
34040
|
-
|
|
34041
|
-
|
|
34906
|
+
return {
|
|
34907
|
+
calls: [],
|
|
34908
|
+
status: false
|
|
34909
|
+
};
|
|
34042
34910
|
} catch (err) {
|
|
34043
34911
|
logger.error(`error moving assets: ${err}`);
|
|
34044
|
-
return
|
|
34912
|
+
return {
|
|
34913
|
+
calls: [],
|
|
34914
|
+
status: false
|
|
34915
|
+
};
|
|
34045
34916
|
}
|
|
34046
34917
|
}
|
|
34047
34918
|
async handleDeposit() {
|
|
@@ -34061,7 +34932,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34061
34932
|
};
|
|
34062
34933
|
}
|
|
34063
34934
|
const extendedLeverage = calculateExtendedLevergae();
|
|
34064
|
-
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter);
|
|
34935
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "open" /* OPEN */);
|
|
34065
34936
|
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
34066
34937
|
logger.error("price difference between avnu and extended doesn't fit the range");
|
|
34067
34938
|
return {
|
|
@@ -34078,6 +34949,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34078
34949
|
};
|
|
34079
34950
|
}
|
|
34080
34951
|
const extendedPositionValue = position.length > 0 ? parseFloat(position[0].value) : 0;
|
|
34952
|
+
const BUFFER_AMOUNT_IN_AVAILABLE_FOR_TRADE = BUFFER_USDC_IN_WITHDRAWAL;
|
|
34081
34953
|
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34082
34954
|
if (!extendedHoldings) {
|
|
34083
34955
|
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
@@ -34096,12 +34968,11 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34096
34968
|
const { collateralPrice } = await this.getAssetPrices();
|
|
34097
34969
|
const { vesuAmountInBTC, extendedAmountInBTC } = calculateVesUPositionSizeGivenExtended(
|
|
34098
34970
|
extendedPositionValue,
|
|
34099
|
-
extendedHoldingAmount,
|
|
34971
|
+
extendedHoldingAmount.minus(BUFFER_AMOUNT_IN_AVAILABLE_FOR_TRADE),
|
|
34100
34972
|
collateralTokenAmount,
|
|
34101
34973
|
collateralPrice.price
|
|
34102
34974
|
);
|
|
34103
|
-
|
|
34104
|
-
console.log("extendedAmountInBTC", extendedAmountInBTC);
|
|
34975
|
+
logger.info(`vesuAmountInBTC ${vesuAmountInBTC}, extendedAmountInBTC ${extendedAmountInBTC}`);
|
|
34105
34976
|
let calls = [];
|
|
34106
34977
|
if (vesuAmountInBTC.greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)) {
|
|
34107
34978
|
const proofsInfo = vesuAdapter.getProofs(true, this.getMerkleTree());
|
|
@@ -34114,7 +34985,6 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34114
34985
|
);
|
|
34115
34986
|
const { amount: wbtcAmountInVaultAllocator } = await this.getUnusedBalanceWBTC();
|
|
34116
34987
|
if (wbtcAmountInVaultAllocator.lessThan(vesuAmountInBTC)) {
|
|
34117
|
-
console.log("error wbtc amount in vault allocator is less than vesu amount in btc", wbtcAmountInVaultAllocator, vesuAmountInBTC);
|
|
34118
34988
|
const swapProofsInfo = avnuAdapter.getProofs(true, this.getMerkleTree());
|
|
34119
34989
|
const swapProofGroups = swapProofsInfo.proofs;
|
|
34120
34990
|
const swapCall = this.getManageCall(
|
|
@@ -34149,68 +35019,98 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34149
35019
|
extendedAmountInBTC: new Web3Number(0, 0),
|
|
34150
35020
|
calls: []
|
|
34151
35021
|
};
|
|
34152
|
-
;
|
|
34153
35022
|
}
|
|
34154
35023
|
}
|
|
34155
|
-
async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter) {
|
|
35024
|
+
async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, positionType) {
|
|
34156
35025
|
const {
|
|
34157
35026
|
ask,
|
|
34158
35027
|
bid
|
|
34159
35028
|
} = await extendedAdapter.fetchOrderBookBTCUSDC();
|
|
34160
35029
|
const price = ask.plus(bid).dividedBy(2);
|
|
34161
|
-
const btcToken = vesuAdapter.config.supportedPositions[
|
|
35030
|
+
const btcToken = vesuAdapter.config.supportedPositions[0].asset;
|
|
34162
35031
|
const btcPriceAvnu = await avnuAdapter.getPriceOfToken(btcToken.address.toString());
|
|
34163
35032
|
if (!btcPriceAvnu) {
|
|
34164
35033
|
logger.error(`error getting btc price avnu: ${btcPriceAvnu}`);
|
|
34165
35034
|
return false;
|
|
34166
35035
|
}
|
|
34167
|
-
const priceDifference = price.minus(btcPriceAvnu).
|
|
34168
|
-
if (priceDifference
|
|
34169
|
-
return
|
|
35036
|
+
const priceDifference = new Web3Number(price.minus(btcPriceAvnu).toFixed(2), 0);
|
|
35037
|
+
if (priceDifference.isNegative()) {
|
|
35038
|
+
return false;
|
|
35039
|
+
}
|
|
35040
|
+
if (positionType === "open" /* OPEN */) {
|
|
35041
|
+
logger.info(`price difference between avnu and extended for open position: ${priceDifference.toNumber()}, minimumExtendedPriceDifferenceForSwapOpen: ${avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen}`);
|
|
35042
|
+
const result = priceDifference.greaterThanOrEqualTo(avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen);
|
|
35043
|
+
logger.info(`result: ${result}`);
|
|
35044
|
+
return result;
|
|
35045
|
+
} else {
|
|
35046
|
+
logger.info(`price difference between avnu and extended for close position: ${priceDifference.toNumber()}, maximumExtendedPriceDifferenceForSwapClosing: ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
35047
|
+
const result = priceDifference.lessThanOrEqualTo(avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing);
|
|
35048
|
+
logger.info(`result: ${result}`);
|
|
35049
|
+
return result;
|
|
34170
35050
|
}
|
|
34171
|
-
logger.error(`price difference between avnu and extended doesn't fit the range, priceDifference: ${priceDifference}`);
|
|
34172
|
-
return false;
|
|
34173
35051
|
}
|
|
34174
35052
|
async handleWithdraw(amount) {
|
|
34175
35053
|
try {
|
|
34176
35054
|
const usdcBalanceVaultAllocator = await this.getUnusedBalance();
|
|
34177
|
-
const usdcBalanceDifference = amount.minus(usdcBalanceVaultAllocator.usdValue);
|
|
35055
|
+
const usdcBalanceDifference = amount.plus(BUFFER_USDC_IN_WITHDRAWAL).minus(usdcBalanceVaultAllocator.usdValue);
|
|
34178
35056
|
logger.info(`usdcBalanceDifference, ${usdcBalanceDifference.toNumber()}`);
|
|
35057
|
+
let calls = [];
|
|
35058
|
+
let status = true;
|
|
34179
35059
|
if (usdcBalanceDifference.lessThan(0)) {
|
|
34180
|
-
const
|
|
34181
|
-
amount
|
|
35060
|
+
const withdrawCall2 = await this.getBringLiquidityCall({
|
|
35061
|
+
amount: usdcBalanceVaultAllocator.amount
|
|
34182
35062
|
});
|
|
34183
|
-
logger.info("withdraw call",
|
|
34184
|
-
|
|
35063
|
+
logger.info("withdraw call", withdrawCall2);
|
|
35064
|
+
calls.push(withdrawCall2);
|
|
35065
|
+
return {
|
|
35066
|
+
calls,
|
|
35067
|
+
status: true
|
|
35068
|
+
};
|
|
34185
35069
|
}
|
|
34186
35070
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34187
35071
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
34188
35072
|
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
|
|
35073
|
+
status = false;
|
|
34189
35074
|
logger.error(
|
|
34190
35075
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
34191
35076
|
);
|
|
34192
|
-
return
|
|
35077
|
+
return {
|
|
35078
|
+
calls,
|
|
35079
|
+
status
|
|
35080
|
+
};
|
|
34193
35081
|
}
|
|
34194
35082
|
const { collateralTokenAmount } = await vesuAdapter.vesuAdapter.getAssetPrices();
|
|
34195
35083
|
const {
|
|
34196
35084
|
collateralPrice
|
|
34197
35085
|
} = await this.getAssetPrices();
|
|
34198
35086
|
const extendedPositon = await extendedAdapter.getAllOpenPositions();
|
|
35087
|
+
if (!extendedPositon) {
|
|
35088
|
+
status = false;
|
|
35089
|
+
logger.error("error getting extended position", extendedPositon);
|
|
35090
|
+
return {
|
|
35091
|
+
calls,
|
|
35092
|
+
status
|
|
35093
|
+
};
|
|
35094
|
+
}
|
|
34199
35095
|
const amountDistributionForWithdrawal = await calculateAmountDistributionForWithdrawal(
|
|
34200
|
-
|
|
35096
|
+
usdcBalanceDifference,
|
|
34201
35097
|
collateralPrice.price,
|
|
34202
35098
|
collateralTokenAmount,
|
|
34203
35099
|
extendedPositon
|
|
34204
35100
|
);
|
|
34205
35101
|
if (!amountDistributionForWithdrawal) {
|
|
35102
|
+
status = false;
|
|
34206
35103
|
logger.error(
|
|
34207
35104
|
`error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
|
|
34208
35105
|
);
|
|
34209
|
-
return
|
|
35106
|
+
return {
|
|
35107
|
+
calls,
|
|
35108
|
+
status
|
|
35109
|
+
};
|
|
34210
35110
|
}
|
|
34211
35111
|
const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
|
|
34212
|
-
if (vesu_amount.greaterThan(0)) {
|
|
34213
|
-
const
|
|
35112
|
+
if (status && vesu_amount.greaterThan(0)) {
|
|
35113
|
+
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
34214
35114
|
{
|
|
34215
35115
|
amount: vesu_amount,
|
|
34216
35116
|
from: Protocols.VESU.name,
|
|
@@ -34219,10 +35119,11 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34219
35119
|
extendedAdapter,
|
|
34220
35120
|
vesuAdapter
|
|
34221
35121
|
);
|
|
34222
|
-
|
|
35122
|
+
status = vesuStatus;
|
|
35123
|
+
calls.push(...vesuCalls);
|
|
34223
35124
|
}
|
|
34224
|
-
if (extended_amount.greaterThan(0)) {
|
|
34225
|
-
const
|
|
35125
|
+
if (status && extended_amount.greaterThan(0)) {
|
|
35126
|
+
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
34226
35127
|
{
|
|
34227
35128
|
amount: extended_amount,
|
|
34228
35129
|
from: Protocols.EXTENDED.name,
|
|
@@ -34231,12 +35132,32 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34231
35132
|
extendedAdapter,
|
|
34232
35133
|
vesuAdapter
|
|
34233
35134
|
);
|
|
34234
|
-
|
|
35135
|
+
status = extendedStatus;
|
|
35136
|
+
if (status) {
|
|
35137
|
+
calls.push(...extendedCalls);
|
|
35138
|
+
} else {
|
|
35139
|
+
logger.error("error moving assets to vault: extendedStatus: ${extendedStatus}");
|
|
35140
|
+
return {
|
|
35141
|
+
calls: [],
|
|
35142
|
+
status
|
|
35143
|
+
};
|
|
35144
|
+
}
|
|
34235
35145
|
}
|
|
34236
|
-
|
|
35146
|
+
const withdrawCall = await this.getBringLiquidityCall({
|
|
35147
|
+
amount
|
|
35148
|
+
});
|
|
35149
|
+
logger.info("withdraw call", withdrawCall);
|
|
35150
|
+
calls.push(withdrawCall);
|
|
35151
|
+
return {
|
|
35152
|
+
calls,
|
|
35153
|
+
status
|
|
35154
|
+
};
|
|
34237
35155
|
} catch (err) {
|
|
34238
35156
|
logger.error(`error handling withdrawal: ${err}`);
|
|
34239
|
-
return
|
|
35157
|
+
return {
|
|
35158
|
+
calls: [],
|
|
35159
|
+
status: false
|
|
35160
|
+
};
|
|
34240
35161
|
}
|
|
34241
35162
|
}
|
|
34242
35163
|
async getAUM() {
|
|
@@ -34284,7 +35205,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34284
35205
|
};
|
|
34285
35206
|
}
|
|
34286
35207
|
};
|
|
34287
|
-
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
|
|
35208
|
+
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
|
|
34288
35209
|
vaultSettings.leafAdapters = [];
|
|
34289
35210
|
const wbtcToken = Global.getDefaultTokens().find(
|
|
34290
35211
|
(token) => token.symbol === lstSymbol
|
|
@@ -34308,7 +35229,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
|
|
|
34308
35229
|
...baseAdapterConfig,
|
|
34309
35230
|
avnuContract: AVNU_MIDDLEWARE,
|
|
34310
35231
|
slippage: 0.01,
|
|
34311
|
-
baseUrl: AVNU_QUOTE_URL
|
|
35232
|
+
baseUrl: AVNU_QUOTE_URL,
|
|
35233
|
+
minimumExtendedPriceDifferenceForSwapOpen,
|
|
35234
|
+
maximumExtendedPriceDifferenceForSwapClosing
|
|
34312
35235
|
});
|
|
34313
35236
|
const extendedAdapter = new ExtendedAdapter({
|
|
34314
35237
|
...baseAdapterConfig,
|
|
@@ -34324,7 +35247,10 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
|
|
|
34324
35247
|
extendedBaseUrl: "https://api.starknet.extended.exchange",
|
|
34325
35248
|
extendedMarketName: "BTC-USD",
|
|
34326
35249
|
extendedPrecision: 5,
|
|
34327
|
-
avnuAdapter
|
|
35250
|
+
avnuAdapter,
|
|
35251
|
+
retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3e3,
|
|
35252
|
+
minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5
|
|
35253
|
+
//5 usdcs
|
|
34328
35254
|
});
|
|
34329
35255
|
const vesuMultiplyAdapter = new VesuMultiplyAdapter({
|
|
34330
35256
|
poolId: pool1,
|
|
@@ -34337,7 +35263,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
|
|
|
34337
35263
|
supportedPositions: [
|
|
34338
35264
|
{ asset: wbtcToken, isDebt: false },
|
|
34339
35265
|
{ asset: usdcToken, isDebt: true }
|
|
34340
|
-
]
|
|
35266
|
+
],
|
|
35267
|
+
minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5
|
|
35268
|
+
//5 usdc
|
|
34341
35269
|
});
|
|
34342
35270
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
34343
35271
|
...baseAdapterConfig
|
|
@@ -34370,6 +35298,7 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
|
|
|
34370
35298
|
() => vesuMultiplyAdapter.getWithdrawLeaf()
|
|
34371
35299
|
);
|
|
34372
35300
|
vaultSettings.leafAdapters.push(() => extendedAdapter.getDepositLeaf());
|
|
35301
|
+
vaultSettings.leafAdapters.push(() => extendedAdapter.getSwapFromLegacyLeaf());
|
|
34373
35302
|
vaultSettings.leafAdapters.push(() => avnuAdapter.getDepositLeaf());
|
|
34374
35303
|
vaultSettings.leafAdapters.push(() => avnuAdapter.getWithdrawLeaf());
|
|
34375
35304
|
vaultSettings.leafAdapters.push(
|
|
@@ -34451,12 +35380,12 @@ var re7UsdcPrimeDevansh = {
|
|
|
34451
35380
|
borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
|
|
34452
35381
|
minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP
|
|
34453
35382
|
};
|
|
34454
|
-
var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended) => {
|
|
35383
|
+
var VesuExtendedTestStrategies = (extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) => {
|
|
34455
35384
|
return [
|
|
34456
|
-
getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended)
|
|
35385
|
+
getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing)
|
|
34457
35386
|
];
|
|
34458
35387
|
};
|
|
34459
|
-
function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended) {
|
|
35388
|
+
function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
|
|
34460
35389
|
return {
|
|
34461
35390
|
name: `Extended Test ${underlyingSymbol}`,
|
|
34462
35391
|
description: getDescription2(lstSymbol, underlyingSymbol),
|
|
@@ -34464,7 +35393,7 @@ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses,
|
|
|
34464
35393
|
launchBlock: 0,
|
|
34465
35394
|
type: "Other",
|
|
34466
35395
|
depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol)],
|
|
34467
|
-
additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended),
|
|
35396
|
+
additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendUrl, extendedApiKey, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing),
|
|
34468
35397
|
risk: {
|
|
34469
35398
|
riskFactor: _riskFactor3,
|
|
34470
35399
|
netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
|
|
@@ -38740,6 +39669,7 @@ export {
|
|
|
38740
39669
|
PRICE_ROUTER,
|
|
38741
39670
|
PasswordJsonCryptoUtil,
|
|
38742
39671
|
PositionSide,
|
|
39672
|
+
PositionTypeAvnuExtended,
|
|
38743
39673
|
Pragma,
|
|
38744
39674
|
Pricer,
|
|
38745
39675
|
PricerBase,
|