@strkfarm/sdk 2.0.0-dev.2 → 2.0.0-dev.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.global.js +2006 -1062
- package/dist/index.browser.mjs +1845 -911
- package/dist/index.d.ts +144 -37
- package/dist/index.js +1853 -915
- package/dist/index.mjs +1845 -911
- package/package.json +1 -1
- package/src/modules/ExtendedWrapperSDk/types.ts +1 -1
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +39 -8
- package/src/modules/ekubo-quoter.ts +0 -12
- package/src/strategies/index.ts +2 -1
- package/src/strategies/universal-adapters/avnu-adapter.ts +17 -9
- package/src/strategies/universal-adapters/extended-adapter.ts +500 -146
- package/src/strategies/universal-adapters/index.ts +2 -1
- package/src/strategies/universal-adapters/vesu-adapter.ts +6 -6
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +778 -396
- 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 +25 -16
- package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +36 -0
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +3 -6
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +50 -16
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +746 -305
package/dist/index.js
CHANGED
|
@@ -43,11 +43,13 @@ __export(index_exports, {
|
|
|
43
43
|
AssetOperationStatus: () => AssetOperationStatus,
|
|
44
44
|
AssetOperationType: () => AssetOperationType,
|
|
45
45
|
AutoCompounderSTRK: () => AutoCompounderSTRK,
|
|
46
|
+
AvnuAdapter: () => AvnuAdapter,
|
|
46
47
|
AvnuWrapper: () => AvnuWrapper,
|
|
47
48
|
BaseAdapter: () => BaseAdapter,
|
|
48
49
|
BaseStrategy: () => BaseStrategy,
|
|
49
50
|
CommonAdapter: () => CommonAdapter,
|
|
50
51
|
ContractAddr: () => ContractAddr,
|
|
52
|
+
CycleType: () => CycleType,
|
|
51
53
|
Deployer: () => deployer_default,
|
|
52
54
|
ERC20: () => ERC20,
|
|
53
55
|
EXTENDED_CONTRACT: () => EXTENDED_CONTRACT,
|
|
@@ -76,6 +78,7 @@ __export(index_exports, {
|
|
|
76
78
|
PRICE_ROUTER: () => PRICE_ROUTER,
|
|
77
79
|
PasswordJsonCryptoUtil: () => PasswordJsonCryptoUtil,
|
|
78
80
|
PositionSide: () => PositionSide,
|
|
81
|
+
PositionTypeAvnuExtended: () => PositionTypeAvnuExtended,
|
|
79
82
|
Pragma: () => Pragma,
|
|
80
83
|
Pricer: () => Pricer,
|
|
81
84
|
PricerBase: () => PricerBase,
|
|
@@ -125,6 +128,7 @@ __export(index_exports, {
|
|
|
125
128
|
calculateExtendedLevergae: () => calculateExtendedLevergae,
|
|
126
129
|
calculateVesUPositionSizeGivenExtended: () => calculateVesUPositionSizeGivenExtended,
|
|
127
130
|
calculateVesuLeverage: () => calculateVesuLeverage,
|
|
131
|
+
calculateWBTCAmountToMaintainLTV: () => calculateWBTCAmountToMaintainLTV,
|
|
128
132
|
extensionMap: () => extensionMap,
|
|
129
133
|
getAPIUsingHeadlessBrowser: () => getAPIUsingHeadlessBrowser,
|
|
130
134
|
getContractDetails: () => getContractDetails,
|
|
@@ -4474,20 +4478,13 @@ var EkuboQuoter = class _EkuboQuoter {
|
|
|
4474
4478
|
async getDexPrice(baseToken, quoteToken, amount) {
|
|
4475
4479
|
const lstTokenInfo = baseToken;
|
|
4476
4480
|
const lstUnderlyingTokenInfo = quoteToken;
|
|
4477
|
-
console.log("lstTokenInfo", lstTokenInfo);
|
|
4478
|
-
console.log("lstUnderlyingTokenInfo", lstUnderlyingTokenInfo);
|
|
4479
|
-
console.log("amount", amount);
|
|
4480
4481
|
const quote = await this.getQuote(
|
|
4481
4482
|
lstTokenInfo.address.address,
|
|
4482
4483
|
lstUnderlyingTokenInfo.address.address,
|
|
4483
4484
|
amount
|
|
4484
4485
|
);
|
|
4485
|
-
console.log("quote", quote);
|
|
4486
4486
|
const outputAmount = Web3Number.fromWei(quote.total_calculated, lstUnderlyingTokenInfo.decimals);
|
|
4487
|
-
console.log("outputAmount", outputAmount);
|
|
4488
|
-
console.log("amount", amount);
|
|
4489
4487
|
const price = outputAmount.toNumber() / amount.toNumber();
|
|
4490
|
-
console.log("price", price);
|
|
4491
4488
|
logger.verbose(`${_EkuboQuoter.name}:: LST Dex Price: ${price}`);
|
|
4492
4489
|
return price;
|
|
4493
4490
|
}
|
|
@@ -4506,16 +4503,12 @@ var EkuboQuoter = class _EkuboQuoter {
|
|
|
4506
4503
|
// debt collateral
|
|
4507
4504
|
async getSwapLimitAmount(fromToken, toToken, amount, max_slippage = 2e-3) {
|
|
4508
4505
|
const isExactAmountIn = amount.greaterThanOrEqualTo(0);
|
|
4509
|
-
console.log("isExactAmountIn", isExactAmountIn);
|
|
4510
4506
|
logger.verbose(`${_EkuboQuoter.name}::getSwapLimitAmount isExactAmountIn: ${isExactAmountIn}, fromToken: ${fromToken.symbol}, toToken: ${toToken.symbol}, amount: ${amount}`);
|
|
4511
4507
|
const isYieldToken = this.tokenMarketData.isAPYSupported(toToken);
|
|
4512
4508
|
console.log("isYieldToken", isYieldToken);
|
|
4513
4509
|
const baseToken = isExactAmountIn ? toToken : fromToken;
|
|
4514
4510
|
const quoteToken = isExactAmountIn ? fromToken : toToken;
|
|
4515
|
-
console.log("baseToken", baseToken);
|
|
4516
|
-
console.log("quoteToken", quoteToken);
|
|
4517
4511
|
const dexPrice = await this.getDexPrice(baseToken, quoteToken, amount);
|
|
4518
|
-
console.log("dexPrice", dexPrice);
|
|
4519
4512
|
const trueExchangeRate = isYieldToken ? await this.tokenMarketData.getTruePrice(baseToken) : dexPrice;
|
|
4520
4513
|
console.log("trueExchangeRate", trueExchangeRate);
|
|
4521
4514
|
if (isExactAmountIn) {
|
|
@@ -4546,7 +4539,6 @@ var EkuboQuoter = class _EkuboQuoter {
|
|
|
4546
4539
|
return quote.splits.map((split) => {
|
|
4547
4540
|
const isNegativeAmount = BigInt(split.amount_specified) <= 0n;
|
|
4548
4541
|
const token = isNegativeAmount ? toTokenInfo : fromTokenInfo;
|
|
4549
|
-
console.log("token for withdrawal", token, isNegativeAmount);
|
|
4550
4542
|
return {
|
|
4551
4543
|
route: split.route.map((_route) => ({
|
|
4552
4544
|
pool_key: {
|
|
@@ -27219,11 +27211,6 @@ var VesuAdapter = class _VesuAdapter extends CacheClass {
|
|
|
27219
27211
|
if (!this.pricer) {
|
|
27220
27212
|
throw new Error("Pricer is not initialized");
|
|
27221
27213
|
}
|
|
27222
|
-
const CACHE_KEY = `positions_${blockNumber}_${this.config.poolId.shortString()}_${this.config.collateral.symbol}_${this.config.debt.symbol}`;
|
|
27223
|
-
const cacheData = this.getCache(CACHE_KEY);
|
|
27224
|
-
if (cacheData) {
|
|
27225
|
-
return cacheData;
|
|
27226
|
-
}
|
|
27227
27214
|
const { contract, isV2 } = this.getVesuSingletonContract(config, this.config.poolId);
|
|
27228
27215
|
const output = await contract.call(isV2 ? "position" : "position_unsafe", [
|
|
27229
27216
|
...isV2 ? [] : [this.config.poolId.address],
|
|
@@ -27249,7 +27236,6 @@ var VesuAdapter = class _VesuAdapter extends CacheClass {
|
|
|
27249
27236
|
usdValue: debtAmount.multipliedBy(token2Price.price).toNumber(),
|
|
27250
27237
|
remarks: "Debt"
|
|
27251
27238
|
}];
|
|
27252
|
-
this.setCache(CACHE_KEY, value, 6e4);
|
|
27253
27239
|
return value.map((v) => ({ ...v, protocol: Protocols.VESU }));
|
|
27254
27240
|
}
|
|
27255
27241
|
async getCollateralization(config, blockNumber = "latest") {
|
|
@@ -28172,15 +28158,14 @@ var MAX_PRICE_DROP_PERCENTAGE = Number(process.env.MAX_PRICE_DROP_PERCENTAGE ??
|
|
|
28172
28158
|
var MAX_LTV_BTC_USDC = 0.8428;
|
|
28173
28159
|
var MAX_LIQUIDATION_RATIO = 0.86;
|
|
28174
28160
|
var VAULT_ID_EXTENDED = process.env.VAULT_ID_EXTENDED ?? 220774;
|
|
28175
|
-
var WALLET_ADDRESS = process.env.WALLET_ADDRESS ?? "
|
|
28176
|
-
var TESTNET_WALLET_ADDRESS = process.env.TESTNET_WALLET_ADDRESS ?? "0x07b84bb6E87588BdAde0bfe6173A615b3C220F9C3803456aE183C50EA1d15Ba1";
|
|
28177
|
-
var TEST_WALLET_2 = process.env.TEST_WALLET_2 ?? "0x004C1bdC61DAc7947F3C93d0163d660012E2aB0521567f7155fcf502848791A7";
|
|
28161
|
+
var WALLET_ADDRESS = process.env.WALLET_ADDRESS ?? "0x007E24592287427aaE9d291770B17d582E8A45f3aE54228F998793Ec769B7D13";
|
|
28178
28162
|
var STRK_API_TEST_RPC = process.env.STRK_API_TEST_RPC ?? "https://sepolia.starknet.a5a.ch";
|
|
28179
28163
|
var STRK_API_RPC = process.env.STRK_API_RPC ?? "https://mainnet.starknet.a5a.ch";
|
|
28180
28164
|
var MAX_RETRIES = Number(process.env.MAX_RETRIES ?? 3);
|
|
28181
28165
|
var MAX_DELAY = Number(process.env.MAX_DELAY ?? 100);
|
|
28182
28166
|
var EXTEND_MARKET_NAME = "BTC-USD";
|
|
28183
|
-
var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ??
|
|
28167
|
+
var LIMIT_BALANCE = Number(process.env.LIMIT_BALANCE ?? 0.05);
|
|
28168
|
+
var LIMIT_BALANCE_VALUE = 10;
|
|
28184
28169
|
var REBALANCER_INTERVAL = Number(process.env.REBALANCER_INTERVAL ?? 18e4);
|
|
28185
28170
|
var WITHDRAWAL_INTERVAL = Number(process.env.WITHDRAWAL_INTERVAL ?? 18e6);
|
|
28186
28171
|
var INVESTING_INTERVAL = Number(process.env.INVESTING_INTERVAL ?? 18e4);
|
|
@@ -28198,8 +28183,6 @@ var PRICE_MAX_SLIPPAGE_EKUBO = Number(process.env.PRICE_MAX_SLIPPAGE_EKUBO ?? 5e
|
|
|
28198
28183
|
var MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING = Number(process.env.MINIMUM_DEBT_AMOUNT_VESU_FOR_REBALANCING ?? 1);
|
|
28199
28184
|
var MINIMUM_EXTENDED_POSITION_SIZE = 1e-4;
|
|
28200
28185
|
var MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP = 1e-5;
|
|
28201
|
-
var MAX_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = 700;
|
|
28202
|
-
var MIN_PRICE_DIFFERENCE_BETWEEN_AVNU_AND_EXTENDED = -100;
|
|
28203
28186
|
|
|
28204
28187
|
// src/strategies/vesu-extended-strategy/utils/helper.ts
|
|
28205
28188
|
var returnFormattedAmount = (amount, toTokenDecimals) => {
|
|
@@ -28219,8 +28202,7 @@ var calculateAmountDistribution = async (amount, client, marketName, collateralP
|
|
|
28219
28202
|
vesu_leverage: 0
|
|
28220
28203
|
};
|
|
28221
28204
|
}
|
|
28222
|
-
const
|
|
28223
|
-
const extendedExposureUSD = extendedBTCExposure.multipliedBy(collateralPrice);
|
|
28205
|
+
const extendedExposureUSD = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].value, WBTC_TOKEN_DECIMALS) : new Web3Number(0, WBTC_TOKEN_DECIMALS);
|
|
28224
28206
|
const vesuBTCExposureUSD = collateralUnits.multipliedBy(collateralPrice);
|
|
28225
28207
|
const numerator1 = vesu_leverage * amount + vesuBTCExposureUSD.toNumber();
|
|
28226
28208
|
const numerator2 = extendedExposureUSD.toNumber();
|
|
@@ -28257,7 +28239,6 @@ var calculateAmountDistributionForWithdrawal = async (amountInUsdc, collateralPr
|
|
|
28257
28239
|
return null;
|
|
28258
28240
|
}
|
|
28259
28241
|
const extendedExposureUSD = extendedPosition.length > 0 ? new Web3Number(extendedPosition[0].value, USDC_TOKEN_DECIMALS) : new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
28260
|
-
console.log("THe collateral is", collateralPrice, collateralUnits);
|
|
28261
28242
|
const vesuExposureUSD = collateralUnits.multipliedBy(collateralPrice);
|
|
28262
28243
|
if (vesuExposureUSD.lessThan(0)) {
|
|
28263
28244
|
return {
|
|
@@ -28314,10 +28295,10 @@ var calculateExtendedLevergae = () => {
|
|
|
28314
28295
|
const extended_leverage_max = 1 / (MAINTENANCE_MARGIN + MAX_PRICE_DROP_PERCENTAGE);
|
|
28315
28296
|
return Math.floor(extended_leverage_max);
|
|
28316
28297
|
};
|
|
28317
|
-
var calculateDebtAmount = (collateralAmount, debtAmount, debtPrice, maxLtv =
|
|
28298
|
+
var calculateDebtAmount = (collateralAmount, debtAmount, debtPrice, maxLtv = MAX_LIQUIDATION_RATIO, addedAmount, collateralPrice, isDeposit) => {
|
|
28318
28299
|
try {
|
|
28319
|
-
const
|
|
28320
|
-
const numerator1 = collateralAmount.plus(
|
|
28300
|
+
const addedCollateral = addedAmount.multipliedBy(isDeposit ? 1 : -1);
|
|
28301
|
+
const numerator1 = collateralAmount.plus(addedCollateral).multipliedBy(collateralPrice).multipliedBy(maxLtv);
|
|
28321
28302
|
const numerator2 = debtAmount.multipliedBy(debtPrice).multipliedBy(TARGET_HF);
|
|
28322
28303
|
const denominator = TARGET_HF - maxLtv;
|
|
28323
28304
|
const x_debt_usd = numerator1.minus(numerator2).dividedBy(denominator);
|
|
@@ -28352,19 +28333,34 @@ var calculateAmountDepositOnExtendedWhenIncurringLosses = async (client) => {
|
|
|
28352
28333
|
const extendedHoldings = await client.getHoldings();
|
|
28353
28334
|
const extended_leverage = calculateExtendedLevergae();
|
|
28354
28335
|
const latestPosition = (await client.getPositions()).data.pop();
|
|
28355
|
-
console.log("the latest position is", latestPosition, extendedHoldings);
|
|
28356
28336
|
if (!extendedHoldings || !latestPosition) {
|
|
28357
28337
|
logger.error(`error getting extended position: extendedHoldings=${extendedHoldings}, latestPosition=${latestPosition}`);
|
|
28358
28338
|
return null;
|
|
28359
28339
|
}
|
|
28360
|
-
const positionValueInUSD = latestPosition.value;
|
|
28340
|
+
const positionValueInUSD = new Web3Number(latestPosition.value, USDC_TOKEN_DECIMALS);
|
|
28361
28341
|
const equity = extendedHoldings.data.equity;
|
|
28362
|
-
const deposit =
|
|
28363
|
-
return new Web3Number(
|
|
28342
|
+
const deposit = positionValueInUSD.dividedBy(extended_leverage).minus(equity).toFixed(2);
|
|
28343
|
+
return new Web3Number(deposit, USDC_TOKEN_DECIMALS);
|
|
28364
28344
|
} catch (err) {
|
|
28345
|
+
logger.error(`error calculating amount deposit on extended when incurring losses: ${err}`);
|
|
28365
28346
|
return null;
|
|
28366
28347
|
}
|
|
28367
28348
|
};
|
|
28349
|
+
var calculateWBTCAmountToMaintainLTV = (collateralAmount, debtAmount, debtPrice, maxLtv = MAX_LIQUIDATION_RATIO, collateralPrice, targetHF = TARGET_HF) => {
|
|
28350
|
+
try {
|
|
28351
|
+
const numerator1 = collateralAmount.multipliedBy(collateralPrice).multipliedBy(maxLtv);
|
|
28352
|
+
const numerator2 = debtAmount.multipliedBy(debtPrice).multipliedBy(targetHF);
|
|
28353
|
+
const denominator = maxLtv;
|
|
28354
|
+
const collateralAmountToMaintainLTV = numerator2.minus(numerator1).dividedBy(denominator);
|
|
28355
|
+
let deltaCollateralAmountUnits = new Web3Number(
|
|
28356
|
+
collateralAmountToMaintainLTV.dividedBy(collateralPrice).toFixed(WBTC_TOKEN_DECIMALS),
|
|
28357
|
+
WBTC_TOKEN_DECIMALS
|
|
28358
|
+
);
|
|
28359
|
+
return { deltaCollateralAmountUnits };
|
|
28360
|
+
} catch (err) {
|
|
28361
|
+
return { deltaCollateralAmountUnits: null };
|
|
28362
|
+
}
|
|
28363
|
+
};
|
|
28368
28364
|
var calculateExposureDelta = (exposure_extended, exposure_vesu) => {
|
|
28369
28365
|
const exposure_delta = new Web3Number(exposure_extended - exposure_vesu, 2);
|
|
28370
28366
|
return exposure_delta.absoluteValue().toNumber();
|
|
@@ -28439,21 +28435,36 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28439
28435
|
vaultAllocator: config.vaultAllocator,
|
|
28440
28436
|
id: ""
|
|
28441
28437
|
});
|
|
28442
|
-
this.
|
|
28438
|
+
this.minimumVesuMovementAmount = config.minimumVesuMovementAmount ?? 5;
|
|
28439
|
+
this.tokenMarketData = new TokenMarketData(
|
|
28440
|
+
this.config.pricer,
|
|
28441
|
+
this.config.networkConfig
|
|
28442
|
+
);
|
|
28443
28443
|
}
|
|
28444
28444
|
async getAPY(supportedPosition) {
|
|
28445
28445
|
const CACHE_KEY = `apy_${this.config.poolId.address}_${supportedPosition.asset.symbol}`;
|
|
28446
28446
|
const cacheData = this.getCache(CACHE_KEY);
|
|
28447
|
-
console.log(
|
|
28447
|
+
console.log(
|
|
28448
|
+
`${_VesuMultiplyAdapter.name}::getAPY cacheData: ${JSON.stringify(
|
|
28449
|
+
cacheData
|
|
28450
|
+
)}`,
|
|
28451
|
+
this.vesuAdapter.config.poolId.shortString(),
|
|
28452
|
+
this.vesuAdapter.config.collateral.symbol,
|
|
28453
|
+
this.vesuAdapter.config.debt.symbol
|
|
28454
|
+
);
|
|
28448
28455
|
if (cacheData) {
|
|
28449
28456
|
return cacheData;
|
|
28450
28457
|
}
|
|
28451
28458
|
try {
|
|
28452
28459
|
const allVesuPools = await VesuAdapter.getVesuPools();
|
|
28453
28460
|
const asset = supportedPosition.asset;
|
|
28454
|
-
const pool = allVesuPools.pools.find(
|
|
28461
|
+
const pool = allVesuPools.pools.find(
|
|
28462
|
+
(p) => this.vesuAdapter.config.poolId.eqString(import_starknet21.num.getHexString(p.id))
|
|
28463
|
+
);
|
|
28455
28464
|
if (!pool) {
|
|
28456
|
-
logger.warn(
|
|
28465
|
+
logger.warn(
|
|
28466
|
+
`VesuMultiplyAdapter: Pool not found for token ${asset.symbol}`
|
|
28467
|
+
);
|
|
28457
28468
|
return {
|
|
28458
28469
|
apy: 0,
|
|
28459
28470
|
type: "base" /* BASE */
|
|
@@ -28463,7 +28474,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28463
28474
|
(a) => a.symbol.toLowerCase() === asset.symbol.toLowerCase()
|
|
28464
28475
|
)?.stats;
|
|
28465
28476
|
if (!assetStats) {
|
|
28466
|
-
logger.warn(
|
|
28477
|
+
logger.warn(
|
|
28478
|
+
`VesuMultiplyAdapter: Asset stats not found for token ${asset.symbol}`
|
|
28479
|
+
);
|
|
28467
28480
|
return {
|
|
28468
28481
|
apy: 0,
|
|
28469
28482
|
type: "base" /* BASE */
|
|
@@ -28474,7 +28487,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28474
28487
|
apy = Number(assetStats.borrowApr?.value || 0) / 1e18;
|
|
28475
28488
|
} else {
|
|
28476
28489
|
const isAssetBTC = asset.symbol.toLowerCase().includes("btc");
|
|
28477
|
-
const baseAPY = Number(
|
|
28490
|
+
const baseAPY = Number(
|
|
28491
|
+
isAssetBTC ? assetStats.btcFiSupplyApr?.value + assetStats.supplyApy?.value : assetStats.supplyApy?.value || 0
|
|
28492
|
+
) / 1e18;
|
|
28478
28493
|
const rewardAPY = Number(assetStats.defiSpringSupplyApr?.value || "0") / 1e18;
|
|
28479
28494
|
const isSupported = this.tokenMarketData.isAPYSupported(asset);
|
|
28480
28495
|
apy = baseAPY + rewardAPY;
|
|
@@ -28490,7 +28505,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28490
28505
|
this.setCache(CACHE_KEY, result, 3e5);
|
|
28491
28506
|
return result;
|
|
28492
28507
|
} catch (error) {
|
|
28493
|
-
logger.error(
|
|
28508
|
+
logger.error(
|
|
28509
|
+
`VesuMultiplyAdapter: Error getting APY for ${supportedPosition.asset.symbol}:`,
|
|
28510
|
+
error
|
|
28511
|
+
);
|
|
28494
28512
|
throw error;
|
|
28495
28513
|
}
|
|
28496
28514
|
}
|
|
@@ -28503,12 +28521,16 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28503
28521
|
try {
|
|
28504
28522
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
28505
28523
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
28506
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
28524
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
28525
|
+
this.config.networkConfig
|
|
28526
|
+
);
|
|
28507
28527
|
let position = positions.find(
|
|
28508
28528
|
(p) => p.token.address.eq(supportedPosition.asset.address)
|
|
28509
28529
|
);
|
|
28510
28530
|
if (!position) {
|
|
28511
|
-
logger.warn(
|
|
28531
|
+
logger.warn(
|
|
28532
|
+
`VesuMultiplyAdapter: Position not found for token ${supportedPosition.asset.symbol}`
|
|
28533
|
+
);
|
|
28512
28534
|
return {
|
|
28513
28535
|
amount: new Web3Number("0", supportedPosition.asset.decimals),
|
|
28514
28536
|
remarks: "Position not found"
|
|
@@ -28521,12 +28543,18 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28521
28543
|
this.setCache(CACHE_KEY, position, 6e4);
|
|
28522
28544
|
return position;
|
|
28523
28545
|
} catch (error) {
|
|
28524
|
-
logger.error(
|
|
28546
|
+
logger.error(
|
|
28547
|
+
`VesuMultiplyAdapter: Error getting position for ${supportedPosition.asset.symbol}:`,
|
|
28548
|
+
error
|
|
28549
|
+
);
|
|
28525
28550
|
throw error;
|
|
28526
28551
|
}
|
|
28527
28552
|
}
|
|
28528
28553
|
async maxBorrowableAPY() {
|
|
28529
|
-
const collateralAPY = await this.getAPY({
|
|
28554
|
+
const collateralAPY = await this.getAPY({
|
|
28555
|
+
asset: this.config.collateral,
|
|
28556
|
+
isDebt: false
|
|
28557
|
+
});
|
|
28530
28558
|
const apy = collateralAPY.apy * 0.8;
|
|
28531
28559
|
return apy;
|
|
28532
28560
|
}
|
|
@@ -28536,9 +28564,15 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28536
28564
|
try {
|
|
28537
28565
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
28538
28566
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
28539
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
28540
|
-
|
|
28541
|
-
|
|
28567
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
28568
|
+
this.config.networkConfig
|
|
28569
|
+
);
|
|
28570
|
+
const collateralPosition = positions.find(
|
|
28571
|
+
(p) => p.token.address.eq(collateral.address)
|
|
28572
|
+
);
|
|
28573
|
+
const debtPosition = positions.find(
|
|
28574
|
+
(p) => p.token.address.eq(debt.address)
|
|
28575
|
+
);
|
|
28542
28576
|
if (!collateralPosition || !debtPosition) {
|
|
28543
28577
|
throw new Error("Could not find current positions");
|
|
28544
28578
|
}
|
|
@@ -28548,13 +28582,23 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28548
28582
|
debt,
|
|
28549
28583
|
maxBorrowableAPY
|
|
28550
28584
|
);
|
|
28551
|
-
logger.verbose(
|
|
28552
|
-
|
|
28585
|
+
logger.verbose(
|
|
28586
|
+
`VesuMultiplyAdapter: Max borrowable: ${maxBorrowable.toNumber()}`
|
|
28587
|
+
);
|
|
28588
|
+
const debtCap = await this.vesuAdapter.getDebtCap(
|
|
28589
|
+
this.config.networkConfig
|
|
28590
|
+
);
|
|
28553
28591
|
logger.verbose(`VesuMultiplyAdapter: Debt cap: ${debtCap.toNumber()}`);
|
|
28554
28592
|
const actualMaxBorrowable = maxBorrowable.minimum(debtCap);
|
|
28555
|
-
logger.verbose(
|
|
28556
|
-
|
|
28557
|
-
|
|
28593
|
+
logger.verbose(
|
|
28594
|
+
`VesuMultiplyAdapter: Actual max borrowable: ${actualMaxBorrowable.toNumber()}`
|
|
28595
|
+
);
|
|
28596
|
+
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
28597
|
+
this.config.networkConfig
|
|
28598
|
+
);
|
|
28599
|
+
const collateralPrice = await this.config.pricer.getPrice(
|
|
28600
|
+
collateral.symbol
|
|
28601
|
+
);
|
|
28558
28602
|
if (collateralPrice.price === 0) {
|
|
28559
28603
|
throw new Error("Collateral price is 0");
|
|
28560
28604
|
}
|
|
@@ -28572,14 +28616,25 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28572
28616
|
);
|
|
28573
28617
|
const maxDepositAmount = amount ? amount.minimum(maxCollateralFromDebt) : maxCollateralFromDebt;
|
|
28574
28618
|
const usdValue = await this.getUSDValue(collateral, maxDepositAmount);
|
|
28575
|
-
logger.verbose(
|
|
28576
|
-
|
|
28577
|
-
|
|
28619
|
+
logger.verbose(
|
|
28620
|
+
`VesuMultiplyAdapter: Max deposit::USD value: ${usdValue}, amount: ${maxDepositAmount.toNumber()}`
|
|
28621
|
+
);
|
|
28622
|
+
const apys = await Promise.all([
|
|
28623
|
+
this.getAPY({ asset: collateral, isDebt: false }),
|
|
28624
|
+
this.getAPY({ asset: debt, isDebt: true })
|
|
28625
|
+
]);
|
|
28626
|
+
logger.verbose(
|
|
28627
|
+
`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
|
|
28628
|
+
);
|
|
28578
28629
|
const borrowAmountUSD = actualMaxBorrowable.multipliedBy(debtPrice.price);
|
|
28579
|
-
logger.verbose(
|
|
28630
|
+
logger.verbose(
|
|
28631
|
+
`VesuMultiplyAdapter: Borrow amount: ${actualMaxBorrowable.toNumber()}, borrow amount USD: ${borrowAmountUSD.toNumber()}`
|
|
28632
|
+
);
|
|
28580
28633
|
const netCollateralUSD = usdValue + borrowAmountUSD.toNumber();
|
|
28581
28634
|
const netAPY = (apys[0].apy * netCollateralUSD + apys[1].apy * borrowAmountUSD.toNumber()) / usdValue;
|
|
28582
|
-
logger.verbose(
|
|
28635
|
+
logger.verbose(
|
|
28636
|
+
`VesuMultiplyAdapter: Max deposit amount: ${maxDepositAmount.toNumber()}, netAPY: ${netAPY}`
|
|
28637
|
+
);
|
|
28583
28638
|
return {
|
|
28584
28639
|
tokenInfo: collateral,
|
|
28585
28640
|
amount: maxDepositAmount,
|
|
@@ -28592,7 +28647,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28592
28647
|
protocol: this.protocol
|
|
28593
28648
|
};
|
|
28594
28649
|
} catch (error) {
|
|
28595
|
-
logger.error(
|
|
28650
|
+
logger.error(
|
|
28651
|
+
`VesuMultiplyAdapter: Error calculating max deposit:`,
|
|
28652
|
+
error
|
|
28653
|
+
);
|
|
28596
28654
|
throw error;
|
|
28597
28655
|
}
|
|
28598
28656
|
}
|
|
@@ -28602,9 +28660,15 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28602
28660
|
try {
|
|
28603
28661
|
this.vesuAdapter.networkConfig = this.config.networkConfig;
|
|
28604
28662
|
this.vesuAdapter.pricer = this.config.pricer;
|
|
28605
|
-
const positions = await this.vesuAdapter.getPositions(
|
|
28606
|
-
|
|
28607
|
-
|
|
28663
|
+
const positions = await this.vesuAdapter.getPositions(
|
|
28664
|
+
this.config.networkConfig
|
|
28665
|
+
);
|
|
28666
|
+
const collateralPosition = positions.find(
|
|
28667
|
+
(p) => p.token.address.eq(collateral.address)
|
|
28668
|
+
);
|
|
28669
|
+
const debtPosition = positions.find(
|
|
28670
|
+
(p) => p.token.address.eq(this.config.debt.address)
|
|
28671
|
+
);
|
|
28608
28672
|
if (!collateralPosition || !debtPosition) {
|
|
28609
28673
|
throw new Error("Could not find current positions");
|
|
28610
28674
|
}
|
|
@@ -28614,11 +28678,20 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28614
28678
|
const result = maxWithdrawable.greaterThan(0) ? maxWithdrawable : new Web3Number("0", collateral.decimals);
|
|
28615
28679
|
const usdValue = await this.getUSDValue(collateral, result);
|
|
28616
28680
|
const debtUSD = debtPosition.usdValue;
|
|
28617
|
-
logger.verbose(
|
|
28618
|
-
|
|
28619
|
-
|
|
28681
|
+
logger.verbose(
|
|
28682
|
+
`VesuMultiplyAdapter: Debt USD: ${debtUSD}, collateral USD: ${usdValue}`
|
|
28683
|
+
);
|
|
28684
|
+
const apys = await Promise.all([
|
|
28685
|
+
this.getAPY({ asset: collateral, isDebt: false }),
|
|
28686
|
+
this.getAPY({ asset: debt, isDebt: true })
|
|
28687
|
+
]);
|
|
28688
|
+
logger.verbose(
|
|
28689
|
+
`VesuMultiplyAdapter: Apys: ${apys[0].apy}, ${apys[1].apy}`
|
|
28690
|
+
);
|
|
28620
28691
|
const netAPY = usdValue - debtUSD > 0 ? (apys[0].apy * usdValue + apys[1].apy * debtUSD) / (usdValue - debtUSD) : 0;
|
|
28621
|
-
logger.verbose(
|
|
28692
|
+
logger.verbose(
|
|
28693
|
+
`VesuMultiplyAdapter: Max withdraw amount: ${result.toNumber()}, netAPY: ${netAPY}`
|
|
28694
|
+
);
|
|
28622
28695
|
return {
|
|
28623
28696
|
tokenInfo: collateral,
|
|
28624
28697
|
amount: result,
|
|
@@ -28631,14 +28704,19 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28631
28704
|
protocol: this.protocol
|
|
28632
28705
|
};
|
|
28633
28706
|
} catch (error) {
|
|
28634
|
-
logger.error(
|
|
28707
|
+
logger.error(
|
|
28708
|
+
`VesuMultiplyAdapter: Error calculating max withdraw:`,
|
|
28709
|
+
error
|
|
28710
|
+
);
|
|
28635
28711
|
throw error;
|
|
28636
28712
|
}
|
|
28637
28713
|
}
|
|
28638
28714
|
_getDepositLeaf() {
|
|
28639
28715
|
const collateral = this.config.collateral;
|
|
28640
28716
|
const debt = this.config.debt;
|
|
28641
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28717
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28718
|
+
this.config.poolId
|
|
28719
|
+
);
|
|
28642
28720
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
28643
28721
|
return [
|
|
28644
28722
|
// Approval step for collateral
|
|
@@ -28702,7 +28780,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28702
28780
|
];
|
|
28703
28781
|
}
|
|
28704
28782
|
_getWithdrawLeaf() {
|
|
28705
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28783
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28784
|
+
this.config.poolId
|
|
28785
|
+
);
|
|
28706
28786
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
28707
28787
|
const collateral = this.config.collateral;
|
|
28708
28788
|
const debt = this.config.debt;
|
|
@@ -28759,33 +28839,51 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28759
28839
|
const leafConfigs = this._getDepositLeaf();
|
|
28760
28840
|
const leaves = leafConfigs.map((config) => {
|
|
28761
28841
|
const { target, method, packedArguments, sanitizer, id } = config;
|
|
28762
|
-
const leaf = this.constructSimpleLeafData(
|
|
28763
|
-
|
|
28764
|
-
|
|
28765
|
-
|
|
28766
|
-
|
|
28767
|
-
|
|
28842
|
+
const leaf = this.constructSimpleLeafData(
|
|
28843
|
+
{
|
|
28844
|
+
id,
|
|
28845
|
+
target,
|
|
28846
|
+
method,
|
|
28847
|
+
packedArguments
|
|
28848
|
+
},
|
|
28849
|
+
sanitizer
|
|
28850
|
+
);
|
|
28768
28851
|
return leaf;
|
|
28769
28852
|
});
|
|
28770
|
-
return {
|
|
28853
|
+
return {
|
|
28854
|
+
leaves,
|
|
28855
|
+
callConstructor: this.getDepositCall.bind(
|
|
28856
|
+
this
|
|
28857
|
+
)
|
|
28858
|
+
};
|
|
28771
28859
|
}
|
|
28772
28860
|
getWithdrawAdapter() {
|
|
28773
28861
|
const leafConfigs = this._getWithdrawLeaf();
|
|
28774
28862
|
const leaves = leafConfigs.map((config) => {
|
|
28775
28863
|
const { target, method, packedArguments, sanitizer, id } = config;
|
|
28776
|
-
const leaf = this.constructSimpleLeafData(
|
|
28777
|
-
|
|
28778
|
-
|
|
28779
|
-
|
|
28780
|
-
|
|
28781
|
-
|
|
28864
|
+
const leaf = this.constructSimpleLeafData(
|
|
28865
|
+
{
|
|
28866
|
+
id,
|
|
28867
|
+
target,
|
|
28868
|
+
method,
|
|
28869
|
+
packedArguments
|
|
28870
|
+
},
|
|
28871
|
+
sanitizer
|
|
28872
|
+
);
|
|
28782
28873
|
return leaf;
|
|
28783
28874
|
});
|
|
28784
|
-
return {
|
|
28875
|
+
return {
|
|
28876
|
+
leaves,
|
|
28877
|
+
callConstructor: this.getWithdrawCall.bind(
|
|
28878
|
+
this
|
|
28879
|
+
)
|
|
28880
|
+
};
|
|
28785
28881
|
}
|
|
28786
28882
|
async getDepositCall(params) {
|
|
28787
28883
|
const collateral = this.config.collateral;
|
|
28788
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28884
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28885
|
+
this.config.poolId
|
|
28886
|
+
);
|
|
28789
28887
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
28790
28888
|
const uint256MarginAmount = import_starknet21.uint256.bnToUint256(params.amount.toWei());
|
|
28791
28889
|
return [
|
|
@@ -28857,7 +28955,9 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28857
28955
|
];
|
|
28858
28956
|
}
|
|
28859
28957
|
async getWithdrawCall(params) {
|
|
28860
|
-
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28958
|
+
const { addr: vesuSingleton, isV2 } = getVesuSingletonAddress(
|
|
28959
|
+
this.config.poolId
|
|
28960
|
+
);
|
|
28861
28961
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
28862
28962
|
return [
|
|
28863
28963
|
// Switch delegation on
|
|
@@ -28912,7 +29012,11 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28912
29012
|
];
|
|
28913
29013
|
}
|
|
28914
29014
|
async getMultiplyCallCalldata(params, isDeposit) {
|
|
28915
|
-
logger.verbose(
|
|
29015
|
+
logger.verbose(
|
|
29016
|
+
`${_VesuMultiplyAdapter.name}::getMultiplyCallCalldata params: ${JSON.stringify(
|
|
29017
|
+
params
|
|
29018
|
+
)}, isDeposit: ${isDeposit}, collateral: ${this.config.collateral.symbol}, debt: ${this.config.debt.symbol}`
|
|
29019
|
+
);
|
|
28916
29020
|
const { isV2 } = getVesuSingletonAddress(this.config.poolId);
|
|
28917
29021
|
const vesuMultiply = isV2 ? this.vesuAdapter.VESU_MULTIPLY : this.vesuAdapter.VESU_MULTIPLY_V1;
|
|
28918
29022
|
const multiplyContract = new import_starknet21.Contract({
|
|
@@ -28922,42 +29026,83 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28922
29026
|
});
|
|
28923
29027
|
let leverSwap = [];
|
|
28924
29028
|
let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
28925
|
-
const existingPositions = await this.vesuAdapter.getPositions(
|
|
28926
|
-
|
|
29029
|
+
const existingPositions = await this.vesuAdapter.getPositions(
|
|
29030
|
+
this.config.networkConfig
|
|
29031
|
+
);
|
|
29032
|
+
const collateralisation = await this.vesuAdapter.getCollateralization(
|
|
29033
|
+
this.config.networkConfig
|
|
29034
|
+
);
|
|
28927
29035
|
const existingCollateralInfo = existingPositions[0];
|
|
28928
29036
|
const existingDebtInfo = existingPositions[1];
|
|
28929
29037
|
const isDexPriceRequired = existingDebtInfo.token.symbol !== "USDC";
|
|
28930
|
-
logger.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(
|
|
28931
|
-
|
|
29038
|
+
logger.debug(`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall existingCollateralInfo: ${JSON.stringify(
|
|
29039
|
+
existingCollateralInfo
|
|
29040
|
+
)},
|
|
29041
|
+
existingDebtInfo: ${JSON.stringify(
|
|
29042
|
+
existingDebtInfo
|
|
29043
|
+
)}, collateralisation: ${JSON.stringify(collateralisation)}`);
|
|
28932
29044
|
const collateralPrice = collateralisation[0].usdValue > 0 ? collateralisation[0].usdValue / existingCollateralInfo.amount.toNumber() : (await this.config.pricer.getPrice(this.config.collateral.symbol)).price;
|
|
28933
29045
|
const debtPrice = collateralisation[1].usdValue > 0 ? collateralisation[1].usdValue / existingDebtInfo.amount.toNumber() : (await this.config.pricer.getPrice(this.config.debt.symbol)).price;
|
|
28934
|
-
logger.debug(
|
|
28935
|
-
|
|
28936
|
-
|
|
28937
|
-
const
|
|
28938
|
-
|
|
29046
|
+
logger.debug(
|
|
29047
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall collateralPrice: ${collateralPrice}, debtPrice: ${debtPrice}`
|
|
29048
|
+
);
|
|
29049
|
+
const legLTV = await this.vesuAdapter.getLTVConfig(
|
|
29050
|
+
this.config.networkConfig
|
|
29051
|
+
);
|
|
29052
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
29053
|
+
this.config.networkConfig,
|
|
29054
|
+
this.config.pricer
|
|
29055
|
+
);
|
|
29056
|
+
const dexPrice = isDexPriceRequired ? await ekuboQuoter.getDexPrice(
|
|
29057
|
+
this.config.collateral,
|
|
29058
|
+
this.config.debt,
|
|
29059
|
+
this.config.quoteAmountToFetchPrice
|
|
29060
|
+
) : 1;
|
|
29061
|
+
logger.verbose(
|
|
29062
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall dexPrice: ${dexPrice}, ltv: ${legLTV}`
|
|
29063
|
+
);
|
|
28939
29064
|
const addedCollateral = params.amount.multipliedBy(isDeposit ? 1 : -1);
|
|
28940
|
-
logger.verbose(
|
|
29065
|
+
logger.verbose(
|
|
29066
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall addedCollateral: ${addedCollateral}`
|
|
29067
|
+
);
|
|
28941
29068
|
const numeratorPart1 = existingCollateralInfo.amount.plus(addedCollateral).multipliedBy(collateralPrice).multipliedBy(legLTV);
|
|
28942
|
-
logger.verbose(
|
|
29069
|
+
logger.verbose(
|
|
29070
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}`
|
|
29071
|
+
);
|
|
28943
29072
|
const numeratorPart2 = existingDebtInfo.amount.multipliedBy(debtPrice).multipliedBy(this.config.targetHealthFactor);
|
|
28944
|
-
logger.verbose(
|
|
29073
|
+
logger.verbose(
|
|
29074
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart2: ${numeratorPart2}`
|
|
29075
|
+
);
|
|
28945
29076
|
const denominatorPart = this.config.targetHealthFactor - legLTV / dexPrice;
|
|
28946
|
-
logger.verbose(
|
|
29077
|
+
logger.verbose(
|
|
29078
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall denominatorPart: ${denominatorPart}`
|
|
29079
|
+
);
|
|
28947
29080
|
const x_debt_usd = numeratorPart1.minus(numeratorPart2).dividedBy(denominatorPart);
|
|
28948
|
-
logger.verbose(
|
|
28949
|
-
|
|
28950
|
-
|
|
29081
|
+
logger.verbose(
|
|
29082
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall x_debt_usd: ${x_debt_usd}`
|
|
29083
|
+
);
|
|
29084
|
+
logger.debug(
|
|
29085
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall numeratorPart1: ${numeratorPart1}, numeratorPart2: ${numeratorPart2}, denominatorPart: ${denominatorPart}`
|
|
29086
|
+
);
|
|
29087
|
+
let debtAmount = new Web3Number(
|
|
29088
|
+
x_debt_usd.dividedBy(debtPrice).toFixed(this.config.debt.decimals),
|
|
29089
|
+
this.config.debt.decimals
|
|
29090
|
+
);
|
|
28951
29091
|
const marginAmount = addedCollateral;
|
|
28952
29092
|
const collateralToken = this.config.collateral;
|
|
28953
29093
|
const debtToken = this.config.debt;
|
|
28954
|
-
const debtAmountInCollateralUnits = new Web3Number(
|
|
29094
|
+
const debtAmountInCollateralUnits = new Web3Number(
|
|
29095
|
+
debtAmount.multipliedBy(debtPrice).dividedBy(collateralPrice).multipliedBy(10 ** collateralToken.decimals).toFixed(0),
|
|
29096
|
+
collateralToken.decimals
|
|
29097
|
+
);
|
|
28955
29098
|
const isIncrease = debtAmount.greaterThanOrEqualTo(0);
|
|
28956
29099
|
if (isIncrease && debtAmount.lessThan(0)) {
|
|
28957
29100
|
} else if (!isIncrease && debtAmount.greaterThan(0)) {
|
|
28958
29101
|
debtAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
28959
29102
|
}
|
|
28960
|
-
logger.verbose(
|
|
29103
|
+
logger.verbose(
|
|
29104
|
+
`${_VesuMultiplyAdapter.name}::getVesuMultiplyCall debtAmount: ${debtAmount}, marginAmount: ${marginAmount}`
|
|
29105
|
+
);
|
|
28961
29106
|
if (!debtAmount.isZero()) {
|
|
28962
29107
|
try {
|
|
28963
29108
|
const swapQuote = await ekuboQuoter.getQuote(
|
|
@@ -28967,26 +29112,49 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
28967
29112
|
// negative for exact amount out
|
|
28968
29113
|
);
|
|
28969
29114
|
if (swapQuote.price_impact < 0.01) {
|
|
28970
|
-
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
29115
|
+
leverSwap = debtAmount.isNegative() ? ekuboQuoter.getVesuMultiplyQuote(
|
|
29116
|
+
swapQuote,
|
|
29117
|
+
collateralToken,
|
|
29118
|
+
debtToken
|
|
29119
|
+
) : ekuboQuoter.getVesuMultiplyQuote(
|
|
29120
|
+
swapQuote,
|
|
29121
|
+
debtToken,
|
|
29122
|
+
collateralToken
|
|
29123
|
+
);
|
|
28971
29124
|
const MAX_SLIPPAGE = 2e-3;
|
|
28972
29125
|
if (debtAmount.greaterThan(0)) {
|
|
28973
29126
|
leverSwapLimitAmount = debtAmount.multipliedBy(1 + MAX_SLIPPAGE);
|
|
28974
29127
|
} else if (debtAmount.lessThan(0)) {
|
|
28975
29128
|
leverSwapLimitAmount = debtAmount.abs().multipliedBy(1 - MAX_SLIPPAGE);
|
|
28976
29129
|
} else {
|
|
28977
|
-
leverSwapLimitAmount = Web3Number.fromWei(
|
|
29130
|
+
leverSwapLimitAmount = Web3Number.fromWei(
|
|
29131
|
+
0,
|
|
29132
|
+
this.config.debt.decimals
|
|
29133
|
+
);
|
|
28978
29134
|
}
|
|
28979
29135
|
await new Promise((resolve) => setTimeout(resolve, 1e4));
|
|
28980
29136
|
} else {
|
|
28981
|
-
throw new Error(
|
|
29137
|
+
throw new Error(
|
|
29138
|
+
`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
|
|
29139
|
+
);
|
|
28982
29140
|
}
|
|
28983
29141
|
} catch (error) {
|
|
28984
|
-
throw new Error(
|
|
29142
|
+
throw new Error(
|
|
29143
|
+
`VesuMultiplyAdapter: Failed to get swap quote: ${error}`
|
|
29144
|
+
);
|
|
28985
29145
|
}
|
|
28986
29146
|
}
|
|
28987
|
-
const multiplyParams = await this.getLeverParams(
|
|
29147
|
+
const multiplyParams = await this.getLeverParams(
|
|
29148
|
+
isIncrease,
|
|
29149
|
+
params,
|
|
29150
|
+
leverSwap,
|
|
29151
|
+
leverSwapLimitAmount
|
|
29152
|
+
);
|
|
28988
29153
|
const call = multiplyContract.populate("modify_lever", {
|
|
28989
|
-
modify_lever_params: this.formatMultiplyParams(
|
|
29154
|
+
modify_lever_params: this.formatMultiplyParams(
|
|
29155
|
+
isIncrease,
|
|
29156
|
+
multiplyParams
|
|
29157
|
+
)
|
|
28990
29158
|
});
|
|
28991
29159
|
return call.calldata;
|
|
28992
29160
|
}
|
|
@@ -29000,7 +29168,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
29000
29168
|
add_margin: params.amount,
|
|
29001
29169
|
// multiplied by collateral decimals in format
|
|
29002
29170
|
margin_swap: [],
|
|
29003
|
-
margin_swap_limit_amount: Web3Number.fromWei(
|
|
29171
|
+
margin_swap_limit_amount: Web3Number.fromWei(
|
|
29172
|
+
0,
|
|
29173
|
+
this.config.collateral.decimals
|
|
29174
|
+
),
|
|
29004
29175
|
lever_swap: leverSwap,
|
|
29005
29176
|
lever_swap_limit_amount: leverSwapLimitAmount
|
|
29006
29177
|
} : {
|
|
@@ -29014,7 +29185,10 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
29014
29185
|
lever_swap_limit_amount: leverSwapLimitAmount,
|
|
29015
29186
|
lever_swap_weights: [],
|
|
29016
29187
|
withdraw_swap: [],
|
|
29017
|
-
withdraw_swap_limit_amount: Web3Number.fromWei(
|
|
29188
|
+
withdraw_swap_limit_amount: Web3Number.fromWei(
|
|
29189
|
+
0,
|
|
29190
|
+
this.config.collateral.decimals
|
|
29191
|
+
),
|
|
29018
29192
|
withdraw_swap_weights: [],
|
|
29019
29193
|
close_position: false
|
|
29020
29194
|
};
|
|
@@ -29030,12 +29204,16 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
29030
29204
|
});
|
|
29031
29205
|
let leverSwap = [];
|
|
29032
29206
|
let leverSwapLimitAmount = Web3Number.fromWei(0, this.config.debt.decimals);
|
|
29033
|
-
const existingPositions = await this.vesuAdapter.getPositions(
|
|
29207
|
+
const existingPositions = await this.vesuAdapter.getPositions(
|
|
29208
|
+
this.config.networkConfig
|
|
29209
|
+
);
|
|
29034
29210
|
const existingCollateralInfo = existingPositions[0];
|
|
29035
29211
|
const existingDebtInfo = existingPositions[1];
|
|
29036
29212
|
const collateralToken = this.config.collateral;
|
|
29037
29213
|
const debtToken = this.config.debt;
|
|
29038
|
-
const collateralPrice = await this.config.pricer.getPrice(
|
|
29214
|
+
const collateralPrice = await this.config.pricer.getPrice(
|
|
29215
|
+
collateralToken.symbol
|
|
29216
|
+
);
|
|
29039
29217
|
const debtPrice = await this.config.pricer.getPrice(debtToken.symbol);
|
|
29040
29218
|
const { deltadebtAmountUnits: debtAmountToRepay } = calculateDebtReductionAmountForWithdrawal(
|
|
29041
29219
|
existingDebtInfo.amount,
|
|
@@ -29049,8 +29227,14 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
29049
29227
|
if (!debtAmountToRepay) {
|
|
29050
29228
|
throw new Error("error calculating debt amount to repay");
|
|
29051
29229
|
}
|
|
29052
|
-
const ekuboQuoter = new EkuboQuoter(
|
|
29053
|
-
|
|
29230
|
+
const ekuboQuoter = new EkuboQuoter(
|
|
29231
|
+
this.config.networkConfig,
|
|
29232
|
+
this.config.pricer
|
|
29233
|
+
);
|
|
29234
|
+
const debtInDebtUnits = new Web3Number(
|
|
29235
|
+
debtAmountToRepay,
|
|
29236
|
+
debtToken.decimals
|
|
29237
|
+
).dividedBy(debtPrice.price).multipliedBy(10 ** debtToken.decimals);
|
|
29054
29238
|
const swapQuote = await ekuboQuoter.getQuote(
|
|
29055
29239
|
debtToken.address.address,
|
|
29056
29240
|
collateralToken.address.address,
|
|
@@ -29058,12 +29242,23 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
29058
29242
|
);
|
|
29059
29243
|
const MAX_SLIPPAGE = 2e-3;
|
|
29060
29244
|
if (swapQuote.price_impact < 25e-4) {
|
|
29061
|
-
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
29245
|
+
leverSwap = ekuboQuoter.getVesuMultiplyQuote(
|
|
29246
|
+
swapQuote,
|
|
29247
|
+
collateralToken,
|
|
29248
|
+
debtToken
|
|
29249
|
+
);
|
|
29062
29250
|
} else {
|
|
29063
|
-
logger.error(
|
|
29251
|
+
logger.error(
|
|
29252
|
+
`VesuMultiplyAdapter: Price impact too high (${swapQuote.price_impact}), skipping swap`
|
|
29253
|
+
);
|
|
29064
29254
|
}
|
|
29065
29255
|
leverSwapLimitAmount = new Web3Number(debtAmountToRepay, debtToken.decimals).abs().multipliedBy(1 + MAX_SLIPPAGE);
|
|
29066
|
-
const multiplyParams = await this.getLeverParams(
|
|
29256
|
+
const multiplyParams = await this.getLeverParams(
|
|
29257
|
+
false,
|
|
29258
|
+
params,
|
|
29259
|
+
leverSwap,
|
|
29260
|
+
leverSwapLimitAmount
|
|
29261
|
+
);
|
|
29067
29262
|
const call = multiplyContract.populate("modify_lever", {
|
|
29068
29263
|
modify_lever_params: this.formatMultiplyParams(false, multiplyParams)
|
|
29069
29264
|
});
|
|
@@ -29073,100 +29268,132 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
29073
29268
|
if (isIncrease) {
|
|
29074
29269
|
const _params2 = params;
|
|
29075
29270
|
return {
|
|
29076
|
-
action: new import_starknet21.CairoCustomEnum({
|
|
29077
|
-
|
|
29078
|
-
|
|
29079
|
-
|
|
29080
|
-
|
|
29081
|
-
|
|
29082
|
-
|
|
29271
|
+
action: new import_starknet21.CairoCustomEnum({
|
|
29272
|
+
IncreaseLever: {
|
|
29273
|
+
pool_id: _params2.pool_id.toBigInt(),
|
|
29274
|
+
collateral_asset: _params2.collateral_asset.toBigInt(),
|
|
29275
|
+
debt_asset: _params2.debt_asset.toBigInt(),
|
|
29276
|
+
user: _params2.user.toBigInt(),
|
|
29277
|
+
add_margin: BigInt(_params2.add_margin.toWei()),
|
|
29278
|
+
margin_swap: _params2.margin_swap.map((swap) => ({
|
|
29279
|
+
route: swap.route.map((route) => ({
|
|
29280
|
+
pool_key: {
|
|
29281
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
29282
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
29283
|
+
fee: route.pool_key.fee,
|
|
29284
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
29285
|
+
extension: BigInt(
|
|
29286
|
+
import_starknet21.num.hexToDecimalString(route.pool_key.extension)
|
|
29287
|
+
)
|
|
29288
|
+
},
|
|
29289
|
+
sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(
|
|
29290
|
+
route.sqrt_ratio_limit.toWei()
|
|
29291
|
+
),
|
|
29292
|
+
skip_ahead: BigInt(100)
|
|
29293
|
+
})),
|
|
29294
|
+
token_amount: {
|
|
29295
|
+
token: swap.token_amount.token.toBigInt(),
|
|
29296
|
+
amount: swap.token_amount.amount.toI129()
|
|
29297
|
+
}
|
|
29298
|
+
})),
|
|
29299
|
+
margin_swap_limit_amount: BigInt(
|
|
29300
|
+
_params2.margin_swap_limit_amount.toWei()
|
|
29301
|
+
),
|
|
29302
|
+
lever_swap: _params2.lever_swap.map((swap) => ({
|
|
29303
|
+
route: swap.route.map((route) => ({
|
|
29304
|
+
pool_key: {
|
|
29305
|
+
token0: route.pool_key.token0.toBigInt(),
|
|
29306
|
+
token1: route.pool_key.token1.toBigInt(),
|
|
29307
|
+
fee: route.pool_key.fee,
|
|
29308
|
+
tick_spacing: route.pool_key.tick_spacing,
|
|
29309
|
+
extension: BigInt(
|
|
29310
|
+
import_starknet21.num.hexToDecimalString(route.pool_key.extension)
|
|
29311
|
+
)
|
|
29312
|
+
},
|
|
29313
|
+
sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(
|
|
29314
|
+
route.sqrt_ratio_limit.toWei()
|
|
29315
|
+
),
|
|
29316
|
+
skip_ahead: BigInt(0)
|
|
29317
|
+
})),
|
|
29318
|
+
token_amount: {
|
|
29319
|
+
token: swap.token_amount.token.toBigInt(),
|
|
29320
|
+
amount: swap.token_amount.amount.toI129()
|
|
29321
|
+
}
|
|
29322
|
+
})),
|
|
29323
|
+
lever_swap_limit_amount: BigInt(
|
|
29324
|
+
_params2.lever_swap_limit_amount.toWei()
|
|
29325
|
+
)
|
|
29326
|
+
}
|
|
29327
|
+
})
|
|
29328
|
+
};
|
|
29329
|
+
}
|
|
29330
|
+
const _params = params;
|
|
29331
|
+
return {
|
|
29332
|
+
action: new import_starknet21.CairoCustomEnum({
|
|
29333
|
+
DecreaseLever: {
|
|
29334
|
+
pool_id: _params.pool_id.toBigInt(),
|
|
29335
|
+
collateral_asset: _params.collateral_asset.toBigInt(),
|
|
29336
|
+
debt_asset: _params.debt_asset.toBigInt(),
|
|
29337
|
+
user: _params.user.toBigInt(),
|
|
29338
|
+
sub_margin: BigInt(_params.sub_margin.toWei()),
|
|
29339
|
+
recipient: _params.recipient.toBigInt(),
|
|
29340
|
+
lever_swap: _params.lever_swap.map((swap) => ({
|
|
29083
29341
|
route: swap.route.map((route) => ({
|
|
29084
29342
|
pool_key: {
|
|
29085
29343
|
token0: route.pool_key.token0.toBigInt(),
|
|
29086
29344
|
token1: route.pool_key.token1.toBigInt(),
|
|
29087
29345
|
fee: route.pool_key.fee,
|
|
29088
29346
|
tick_spacing: route.pool_key.tick_spacing,
|
|
29089
|
-
extension:
|
|
29347
|
+
extension: ContractAddr.from(
|
|
29348
|
+
route.pool_key.extension
|
|
29349
|
+
).toBigInt()
|
|
29090
29350
|
},
|
|
29091
|
-
sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(
|
|
29092
|
-
|
|
29351
|
+
sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(
|
|
29352
|
+
route.sqrt_ratio_limit.toWei()
|
|
29353
|
+
),
|
|
29354
|
+
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
29093
29355
|
})),
|
|
29094
29356
|
token_amount: {
|
|
29095
29357
|
token: swap.token_amount.token.toBigInt(),
|
|
29096
29358
|
amount: swap.token_amount.amount.toI129()
|
|
29097
29359
|
}
|
|
29098
29360
|
})),
|
|
29099
|
-
|
|
29100
|
-
|
|
29361
|
+
lever_swap_limit_amount: BigInt(
|
|
29362
|
+
_params.lever_swap_limit_amount.toWei()
|
|
29363
|
+
),
|
|
29364
|
+
lever_swap_weights: _params.lever_swap_weights.map(
|
|
29365
|
+
(weight) => BigInt(weight.toWei())
|
|
29366
|
+
),
|
|
29367
|
+
withdraw_swap: _params.withdraw_swap.map((swap) => ({
|
|
29101
29368
|
route: swap.route.map((route) => ({
|
|
29102
29369
|
pool_key: {
|
|
29103
29370
|
token0: route.pool_key.token0.toBigInt(),
|
|
29104
29371
|
token1: route.pool_key.token1.toBigInt(),
|
|
29105
29372
|
fee: route.pool_key.fee,
|
|
29106
29373
|
tick_spacing: route.pool_key.tick_spacing,
|
|
29107
|
-
extension:
|
|
29374
|
+
extension: ContractAddr.from(
|
|
29375
|
+
route.pool_key.extension
|
|
29376
|
+
).toBigInt()
|
|
29108
29377
|
},
|
|
29109
|
-
sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(
|
|
29110
|
-
|
|
29378
|
+
sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(
|
|
29379
|
+
route.sqrt_ratio_limit.toWei()
|
|
29380
|
+
),
|
|
29381
|
+
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
29111
29382
|
})),
|
|
29112
29383
|
token_amount: {
|
|
29113
29384
|
token: swap.token_amount.token.toBigInt(),
|
|
29114
29385
|
amount: swap.token_amount.amount.toI129()
|
|
29115
29386
|
}
|
|
29116
29387
|
})),
|
|
29117
|
-
|
|
29118
|
-
|
|
29119
|
-
|
|
29120
|
-
|
|
29121
|
-
|
|
29122
|
-
|
|
29123
|
-
|
|
29124
|
-
|
|
29125
|
-
|
|
29126
|
-
debt_asset: _params.debt_asset.toBigInt(),
|
|
29127
|
-
user: _params.user.toBigInt(),
|
|
29128
|
-
sub_margin: BigInt(_params.sub_margin.toWei()),
|
|
29129
|
-
recipient: _params.recipient.toBigInt(),
|
|
29130
|
-
lever_swap: _params.lever_swap.map((swap) => ({
|
|
29131
|
-
route: swap.route.map((route) => ({
|
|
29132
|
-
pool_key: {
|
|
29133
|
-
token0: route.pool_key.token0.toBigInt(),
|
|
29134
|
-
token1: route.pool_key.token1.toBigInt(),
|
|
29135
|
-
fee: route.pool_key.fee,
|
|
29136
|
-
tick_spacing: route.pool_key.tick_spacing,
|
|
29137
|
-
extension: ContractAddr.from(route.pool_key.extension).toBigInt()
|
|
29138
|
-
},
|
|
29139
|
-
sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
|
|
29140
|
-
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
29141
|
-
})),
|
|
29142
|
-
token_amount: {
|
|
29143
|
-
token: swap.token_amount.token.toBigInt(),
|
|
29144
|
-
amount: swap.token_amount.amount.toI129()
|
|
29145
|
-
}
|
|
29146
|
-
})),
|
|
29147
|
-
lever_swap_limit_amount: BigInt(_params.lever_swap_limit_amount.toWei()),
|
|
29148
|
-
lever_swap_weights: _params.lever_swap_weights.map((weight) => BigInt(weight.toWei())),
|
|
29149
|
-
withdraw_swap: _params.withdraw_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: ContractAddr.from(route.pool_key.extension).toBigInt()
|
|
29157
|
-
},
|
|
29158
|
-
sqrt_ratio_limit: import_starknet21.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
|
|
29159
|
-
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
29160
|
-
})),
|
|
29161
|
-
token_amount: {
|
|
29162
|
-
token: swap.token_amount.token.toBigInt(),
|
|
29163
|
-
amount: swap.token_amount.amount.toI129()
|
|
29164
|
-
}
|
|
29165
|
-
})),
|
|
29166
|
-
withdraw_swap_limit_amount: BigInt(_params.withdraw_swap_limit_amount.toWei()),
|
|
29167
|
-
withdraw_swap_weights: _params.withdraw_swap_weights.map((weight) => BigInt(weight.toWei())),
|
|
29168
|
-
close_position: _params.close_position
|
|
29169
|
-
} })
|
|
29388
|
+
withdraw_swap_limit_amount: BigInt(
|
|
29389
|
+
_params.withdraw_swap_limit_amount.toWei()
|
|
29390
|
+
),
|
|
29391
|
+
withdraw_swap_weights: _params.withdraw_swap_weights.map(
|
|
29392
|
+
(weight) => BigInt(weight.toWei())
|
|
29393
|
+
),
|
|
29394
|
+
close_position: _params.close_position
|
|
29395
|
+
}
|
|
29396
|
+
})
|
|
29170
29397
|
};
|
|
29171
29398
|
}
|
|
29172
29399
|
async getHealthFactor() {
|
|
@@ -29175,11 +29402,15 @@ var VesuMultiplyAdapter = class _VesuMultiplyAdapter extends BaseAdapter {
|
|
|
29175
29402
|
}
|
|
29176
29403
|
async getNetAPY() {
|
|
29177
29404
|
const positions = await this.getPositions();
|
|
29178
|
-
logger.verbose(
|
|
29405
|
+
logger.verbose(
|
|
29406
|
+
`${this.name}::getNetAPY: positions: ${JSON.stringify(positions)}`
|
|
29407
|
+
);
|
|
29179
29408
|
const allZero = positions.every((p) => p.usdValue === 0);
|
|
29180
29409
|
if (allZero) {
|
|
29181
29410
|
const collateralUSD = 1e3;
|
|
29182
|
-
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
29411
|
+
const maxLTV = await this.vesuAdapter.getLTVConfig(
|
|
29412
|
+
this.config.networkConfig
|
|
29413
|
+
);
|
|
29183
29414
|
const targetHF = this.config.targetHealthFactor;
|
|
29184
29415
|
const maxDebt = HealthFactorMath.getMaxDebtAmountOnLooping(
|
|
29185
29416
|
new Web3Number(collateralUSD, this.config.collateral.decimals),
|
|
@@ -29322,7 +29553,22 @@ var ExtendedWrapper = class {
|
|
|
29322
29553
|
`HTTP ${response.status}: ${errorData.detail || response.statusText}`
|
|
29323
29554
|
);
|
|
29324
29555
|
}
|
|
29325
|
-
const
|
|
29556
|
+
const text = await response.text();
|
|
29557
|
+
const MAX_SAFE_INTEGER_STR = "9007199254740991";
|
|
29558
|
+
const largeIntegerRegex = /"data"\s*:\s*(\d{16,})/g;
|
|
29559
|
+
const modifiedText = text.replace(largeIntegerRegex, (match, largeInt) => {
|
|
29560
|
+
if (largeInt.length > MAX_SAFE_INTEGER_STR.length || largeInt.length === MAX_SAFE_INTEGER_STR.length && largeInt > MAX_SAFE_INTEGER_STR) {
|
|
29561
|
+
return `"data":"${largeInt}"`;
|
|
29562
|
+
}
|
|
29563
|
+
return match;
|
|
29564
|
+
});
|
|
29565
|
+
const data = JSON.parse(modifiedText);
|
|
29566
|
+
if (data && typeof data.data === "string" && /^\d+$/.test(data.data)) {
|
|
29567
|
+
const numValue = Number(data.data);
|
|
29568
|
+
if (Number.isSafeInteger(numValue)) {
|
|
29569
|
+
data.data = numValue;
|
|
29570
|
+
}
|
|
29571
|
+
}
|
|
29326
29572
|
return data;
|
|
29327
29573
|
} catch (error) {
|
|
29328
29574
|
lastError = error;
|
|
@@ -29382,6 +29628,7 @@ var ExtendedWrapper = class {
|
|
|
29382
29628
|
}
|
|
29383
29629
|
/**
|
|
29384
29630
|
* Initiate a withdrawal from Extended Exchange
|
|
29631
|
+
* Returns data as number | string to preserve precision for large integers
|
|
29385
29632
|
*/
|
|
29386
29633
|
async withdraw(request) {
|
|
29387
29634
|
return this.makeRequest("/api/v1/withdraw", {
|
|
@@ -29520,6 +29767,7 @@ var ExtendedWrapper = class {
|
|
|
29520
29767
|
}
|
|
29521
29768
|
/**
|
|
29522
29769
|
* Withdraw USDC (convenience method)
|
|
29770
|
+
* Returns data as number | string to preserve precision for large integers
|
|
29523
29771
|
*/
|
|
29524
29772
|
async withdrawUSDC(amount) {
|
|
29525
29773
|
return this.withdraw({ amount, asset: "USDC" });
|
|
@@ -29529,11 +29777,13 @@ var ExtendedWrapper = class {
|
|
|
29529
29777
|
* @param marketName - The name of the market to get funding rates for
|
|
29530
29778
|
* @returns The funding rates for the specified market
|
|
29531
29779
|
*/
|
|
29532
|
-
async getFundingRates(marketName, side) {
|
|
29780
|
+
async getFundingRates(marketName, side, startTime, endTime) {
|
|
29781
|
+
const endTimeParam = endTime !== void 0 ? `&end_time=${endTime}` : "";
|
|
29782
|
+
const startTimeParam = startTime !== void 0 ? `&start_time=${startTime}` : "";
|
|
29533
29783
|
return this.makeRequest(
|
|
29534
29784
|
`/api/v1/markets/funding-rates?market_name=${encodeURIComponent(
|
|
29535
29785
|
marketName
|
|
29536
|
-
)}&side=${encodeURIComponent(side)}`
|
|
29786
|
+
)}&side=${encodeURIComponent(side)}${startTimeParam}${endTimeParam}`
|
|
29537
29787
|
);
|
|
29538
29788
|
}
|
|
29539
29789
|
};
|
|
@@ -29546,18 +29796,20 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29546
29796
|
super(config, _ExtendedAdapter.name, Protocols.EXTENDED);
|
|
29547
29797
|
this.config = config;
|
|
29548
29798
|
const client = new wrapper_default({
|
|
29549
|
-
baseUrl: this.config.
|
|
29550
|
-
apiKey:
|
|
29799
|
+
baseUrl: this.config.extendedBackendWriteUrl,
|
|
29800
|
+
apiKey: "",
|
|
29551
29801
|
timeout: this.config.extendedTimeout,
|
|
29552
29802
|
retries: this.config.extendedRetries
|
|
29553
29803
|
});
|
|
29804
|
+
this.minimumExtendedMovementAmount = this.config.minimumExtendedMovementAmount ?? 5;
|
|
29554
29805
|
this.client = client;
|
|
29806
|
+
this.retryDelayForOrderStatus = this.config.retryDelayForOrderStatus ?? 3e3;
|
|
29555
29807
|
}
|
|
29556
29808
|
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
29557
29809
|
async getAPY(supportedPosition) {
|
|
29558
29810
|
const side = supportedPosition.isDebt ? "LONG" : "SHORT";
|
|
29559
|
-
const fundingRates = await this.
|
|
29560
|
-
if (fundingRates.
|
|
29811
|
+
const fundingRates = await this.getFundingRates(side);
|
|
29812
|
+
if (!fundingRates.success) {
|
|
29561
29813
|
logger.error("error getting funding rates", fundingRates);
|
|
29562
29814
|
return { apy: 0, type: "base" /* BASE */ };
|
|
29563
29815
|
}
|
|
@@ -29565,10 +29817,26 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29565
29817
|
const apy = Number(fundingRate.f) * 365 * 24;
|
|
29566
29818
|
return { apy, type: "base" /* BASE */ };
|
|
29567
29819
|
}
|
|
29568
|
-
async
|
|
29569
|
-
|
|
29570
|
-
|
|
29820
|
+
async getFundingRates(side, startTime, endTime) {
|
|
29821
|
+
try {
|
|
29822
|
+
const response = await import_axios8.default.get(`${this.config.extendedBackendReadUrl}/fundingRates/${this.config.extendedMarketName}/${side}`, {
|
|
29823
|
+
params: {
|
|
29824
|
+
startTime: startTime ? startTime.toString() : void 0,
|
|
29825
|
+
endTime: endTime ? endTime.toString() : void 0
|
|
29826
|
+
}
|
|
29827
|
+
});
|
|
29828
|
+
if (!response.data.success) {
|
|
29829
|
+
logger.error("error getting funding rates", response.data);
|
|
29830
|
+
return { success: false, data: [] };
|
|
29831
|
+
}
|
|
29832
|
+
logger.info("success getting funding rates", response.data.data);
|
|
29833
|
+
return { success: true, data: response.data.data };
|
|
29834
|
+
} catch (err) {
|
|
29835
|
+
logger.error("error getting funding rates", err);
|
|
29836
|
+
return { success: false, data: [] };
|
|
29571
29837
|
}
|
|
29838
|
+
}
|
|
29839
|
+
async getPosition(supportedPosition) {
|
|
29572
29840
|
const holdings = await this.getExtendedDepositAmount();
|
|
29573
29841
|
if (!holdings) {
|
|
29574
29842
|
throw new Error("No position found");
|
|
@@ -29576,7 +29844,7 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29576
29844
|
const amount = holdings.equity;
|
|
29577
29845
|
return Promise.resolve({
|
|
29578
29846
|
amount: new Web3Number(amount, 0),
|
|
29579
|
-
remarks:
|
|
29847
|
+
remarks: `Extended Equity`
|
|
29580
29848
|
});
|
|
29581
29849
|
}
|
|
29582
29850
|
async maxDeposit(amount) {
|
|
@@ -29600,14 +29868,14 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29600
29868
|
});
|
|
29601
29869
|
}
|
|
29602
29870
|
_getDepositLeaf() {
|
|
29603
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
29871
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
29872
|
+
(token) => token.symbol === "USDCe"
|
|
29873
|
+
);
|
|
29604
29874
|
return [
|
|
29605
29875
|
{
|
|
29606
29876
|
target: this.config.supportedPositions[0].asset.address,
|
|
29607
29877
|
method: "approve",
|
|
29608
|
-
packedArguments: [
|
|
29609
|
-
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()
|
|
29610
|
-
],
|
|
29878
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
29611
29879
|
id: `extended_approve_${this.config.supportedPositions[0].asset.symbol}`,
|
|
29612
29880
|
sanitizer: AVNU_LEGACY_SANITIZER
|
|
29613
29881
|
},
|
|
@@ -29638,25 +29906,33 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29638
29906
|
const leafConfigs = this._getSwapFromLegacyLeaf();
|
|
29639
29907
|
const leaves = leafConfigs.map((config) => {
|
|
29640
29908
|
const { target, method, packedArguments, sanitizer, id } = config;
|
|
29641
|
-
const leaf = this.constructSimpleLeafData(
|
|
29642
|
-
|
|
29643
|
-
|
|
29644
|
-
|
|
29645
|
-
|
|
29646
|
-
|
|
29909
|
+
const leaf = this.constructSimpleLeafData(
|
|
29910
|
+
{
|
|
29911
|
+
id,
|
|
29912
|
+
target,
|
|
29913
|
+
method,
|
|
29914
|
+
packedArguments
|
|
29915
|
+
},
|
|
29916
|
+
sanitizer
|
|
29917
|
+
);
|
|
29647
29918
|
return leaf;
|
|
29648
29919
|
});
|
|
29649
|
-
return {
|
|
29920
|
+
return {
|
|
29921
|
+
leaves,
|
|
29922
|
+
callConstructor: this.getSwapFromLegacyCall.bind(
|
|
29923
|
+
this
|
|
29924
|
+
)
|
|
29925
|
+
};
|
|
29650
29926
|
}
|
|
29651
29927
|
_getSwapFromLegacyLeaf() {
|
|
29652
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
29928
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
29929
|
+
(token) => token.symbol === "USDCe"
|
|
29930
|
+
);
|
|
29653
29931
|
return [
|
|
29654
29932
|
{
|
|
29655
29933
|
target: usdceToken.address,
|
|
29656
29934
|
method: "approve",
|
|
29657
|
-
packedArguments: [
|
|
29658
|
-
AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()
|
|
29659
|
-
],
|
|
29935
|
+
packedArguments: [AVNU_EXCHANGE_FOR_LEGACY_USDC.toBigInt()],
|
|
29660
29936
|
id: `extendedswaplegacyapprove_${usdceToken.symbol}`,
|
|
29661
29937
|
sanitizer: AVNU_LEGACY_SANITIZER
|
|
29662
29938
|
},
|
|
@@ -29675,11 +29951,13 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29675
29951
|
async getDepositCall(params) {
|
|
29676
29952
|
try {
|
|
29677
29953
|
const usdcToken = this.config.supportedPositions[0].asset;
|
|
29678
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
29679
|
-
|
|
29680
|
-
|
|
29954
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
29955
|
+
(token) => token.symbol === "USDCe"
|
|
29956
|
+
);
|
|
29957
|
+
const salt = Math.floor(Math.random() * 10 ** usdcToken.decimals);
|
|
29958
|
+
const amount = import_starknet22.uint256.bnToUint256(
|
|
29959
|
+
params.amount.multipliedBy(10).toWei()
|
|
29681
29960
|
);
|
|
29682
|
-
const amount = import_starknet22.uint256.bnToUint256(params.amount.multipliedBy(10).toWei());
|
|
29683
29961
|
const quotes = await this.config.avnuAdapter.getQuotesAvnu(
|
|
29684
29962
|
usdcToken.address.toString(),
|
|
29685
29963
|
usdceToken.address.toString(),
|
|
@@ -29692,7 +29970,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29692
29970
|
logger.error("error getting quotes from avnu");
|
|
29693
29971
|
return [];
|
|
29694
29972
|
}
|
|
29695
|
-
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
29973
|
+
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
29974
|
+
quotes
|
|
29975
|
+
);
|
|
29696
29976
|
const swapCallData = getCalldata[0];
|
|
29697
29977
|
return [
|
|
29698
29978
|
{
|
|
@@ -29768,8 +30048,12 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29768
30048
|
async getSwapFromLegacyCall(params) {
|
|
29769
30049
|
try {
|
|
29770
30050
|
const usdcToken = this.config.supportedPositions[0].asset;
|
|
29771
|
-
const usdceToken = Global.getDefaultTokens().find(
|
|
29772
|
-
|
|
30051
|
+
const usdceToken = Global.getDefaultTokens().find(
|
|
30052
|
+
(token) => token.symbol === "USDCe"
|
|
30053
|
+
);
|
|
30054
|
+
const amount = import_starknet22.uint256.bnToUint256(
|
|
30055
|
+
params.amount.multipliedBy(10).toWei()
|
|
30056
|
+
);
|
|
29773
30057
|
const quotes = await this.config.avnuAdapter.getQuotesAvnu(
|
|
29774
30058
|
usdceToken.address.toString(),
|
|
29775
30059
|
usdcToken.address.toString(),
|
|
@@ -29782,7 +30066,9 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29782
30066
|
logger.error("error getting quotes from avnu");
|
|
29783
30067
|
return [];
|
|
29784
30068
|
}
|
|
29785
|
-
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
30069
|
+
const getCalldata = await this.config.avnuAdapter.getSwapCallData(
|
|
30070
|
+
quotes
|
|
30071
|
+
);
|
|
29786
30072
|
const swapCallData = getCalldata[0];
|
|
29787
30073
|
return [
|
|
29788
30074
|
{
|
|
@@ -29828,38 +30114,131 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29828
30114
|
async withdrawFromExtended(amount) {
|
|
29829
30115
|
try {
|
|
29830
30116
|
if (!this.client) {
|
|
29831
|
-
|
|
30117
|
+
logger.error("Client not initialized");
|
|
30118
|
+
return {
|
|
30119
|
+
status: false,
|
|
30120
|
+
receivedTxnHash: false
|
|
30121
|
+
};
|
|
30122
|
+
}
|
|
30123
|
+
if (amount.lessThanOrEqualTo(0)) {
|
|
30124
|
+
logger.error(
|
|
30125
|
+
`Invalid withdrawal amount: ${amount.toNumber()}. Amount must be positive.`
|
|
30126
|
+
);
|
|
30127
|
+
return {
|
|
30128
|
+
status: false,
|
|
30129
|
+
receivedTxnHash: false
|
|
30130
|
+
};
|
|
30131
|
+
}
|
|
30132
|
+
if (amount.lessThanOrEqualTo(this.minimumExtendedMovementAmount)) {
|
|
30133
|
+
logger.warn(
|
|
30134
|
+
`Withdrawal amount ${amount.toNumber()} is below minimum Extended movement amount ${this.minimumExtendedMovementAmount}. Skipping withdrawal.`
|
|
30135
|
+
);
|
|
30136
|
+
return {
|
|
30137
|
+
status: false,
|
|
30138
|
+
receivedTxnHash: false
|
|
30139
|
+
};
|
|
30140
|
+
}
|
|
30141
|
+
const holdings = await this.getExtendedDepositAmount();
|
|
30142
|
+
if (!holdings) {
|
|
30143
|
+
logger.error(
|
|
30144
|
+
"Cannot get holdings - unable to validate withdrawal amount"
|
|
30145
|
+
);
|
|
30146
|
+
return {
|
|
30147
|
+
status: false,
|
|
30148
|
+
receivedTxnHash: false
|
|
30149
|
+
};
|
|
30150
|
+
}
|
|
30151
|
+
const availableForWithdrawal = parseFloat(
|
|
30152
|
+
holdings.availableForWithdrawal
|
|
30153
|
+
);
|
|
30154
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
30155
|
+
logger.error(
|
|
30156
|
+
`Invalid availableForWithdrawal: ${holdings.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
30157
|
+
);
|
|
30158
|
+
return {
|
|
30159
|
+
status: false,
|
|
30160
|
+
receivedTxnHash: false
|
|
30161
|
+
};
|
|
30162
|
+
}
|
|
30163
|
+
const withdrawalAmount = amount.toNumber();
|
|
30164
|
+
if (withdrawalAmount > availableForWithdrawal) {
|
|
30165
|
+
logger.error(
|
|
30166
|
+
`Withdrawal amount ${withdrawalAmount} exceeds available balance ${availableForWithdrawal}`
|
|
30167
|
+
);
|
|
30168
|
+
return {
|
|
30169
|
+
status: false,
|
|
30170
|
+
receivedTxnHash: false
|
|
30171
|
+
};
|
|
29832
30172
|
}
|
|
29833
|
-
|
|
30173
|
+
logger.info(
|
|
30174
|
+
`Withdrawing ${withdrawalAmount} from Extended. Available balance: ${availableForWithdrawal}`
|
|
30175
|
+
);
|
|
30176
|
+
const withdrawalRequest = await this.client.withdrawUSDC(
|
|
30177
|
+
amount.toFixed(2)
|
|
30178
|
+
);
|
|
29834
30179
|
if (withdrawalRequest.status === "OK") {
|
|
29835
|
-
const withdrawalStatus = await this.getDepositOrWithdrawalStatus(
|
|
29836
|
-
|
|
30180
|
+
const withdrawalStatus = await this.getDepositOrWithdrawalStatus(
|
|
30181
|
+
withdrawalRequest.data,
|
|
30182
|
+
"WITHDRAWAL" /* WITHDRAWAL */
|
|
30183
|
+
);
|
|
30184
|
+
return {
|
|
30185
|
+
status: true,
|
|
30186
|
+
receivedTxnHash: withdrawalStatus
|
|
30187
|
+
};
|
|
29837
30188
|
}
|
|
29838
|
-
|
|
30189
|
+
logger.error(
|
|
30190
|
+
`Withdrawal request failed with status: ${withdrawalRequest.status}`
|
|
30191
|
+
);
|
|
30192
|
+
return {
|
|
30193
|
+
status: false,
|
|
30194
|
+
receivedTxnHash: false
|
|
30195
|
+
};
|
|
29839
30196
|
} catch (error) {
|
|
29840
30197
|
logger.error(`Error creating Withdraw Call: ${error}`);
|
|
29841
|
-
return
|
|
30198
|
+
return {
|
|
30199
|
+
status: false,
|
|
30200
|
+
receivedTxnHash: false
|
|
30201
|
+
};
|
|
29842
30202
|
}
|
|
29843
30203
|
}
|
|
29844
30204
|
async getHealthFactor() {
|
|
29845
30205
|
return Promise.resolve(1);
|
|
29846
30206
|
}
|
|
29847
30207
|
async getExtendedDepositAmount() {
|
|
29848
|
-
|
|
29849
|
-
|
|
29850
|
-
|
|
29851
|
-
|
|
29852
|
-
|
|
29853
|
-
|
|
29854
|
-
|
|
29855
|
-
|
|
29856
|
-
|
|
29857
|
-
|
|
29858
|
-
|
|
29859
|
-
|
|
30208
|
+
try {
|
|
30209
|
+
const result = await import_axios8.default.get(`${this.config.extendedBackendReadUrl}/holdings`);
|
|
30210
|
+
if (!result.data) {
|
|
30211
|
+
logger.error("error getting holdings - API returned null/undefined");
|
|
30212
|
+
return void 0;
|
|
30213
|
+
}
|
|
30214
|
+
if (!result.data.success) {
|
|
30215
|
+
logger.error(
|
|
30216
|
+
`error getting holdings - API returned status: ${result.status}`
|
|
30217
|
+
);
|
|
30218
|
+
return void 0;
|
|
30219
|
+
}
|
|
30220
|
+
const holdings = result.data.data;
|
|
30221
|
+
if (!holdings) {
|
|
30222
|
+
logger.warn(
|
|
30223
|
+
"holdings data is null/undefined - treating as zero balance"
|
|
30224
|
+
);
|
|
30225
|
+
return {
|
|
30226
|
+
collateral_name: "",
|
|
30227
|
+
balance: "0",
|
|
30228
|
+
equity: "0",
|
|
30229
|
+
availableForTrade: "0",
|
|
30230
|
+
availableForWithdrawal: "0",
|
|
30231
|
+
unrealisedPnl: "0",
|
|
30232
|
+
initialMargin: "0",
|
|
30233
|
+
marginRatio: "0",
|
|
30234
|
+
updatedTime: Date.now()
|
|
30235
|
+
};
|
|
30236
|
+
}
|
|
30237
|
+
return holdings;
|
|
30238
|
+
} catch (error) {
|
|
30239
|
+
logger.error(`error getting holdings - exception: ${error}`);
|
|
29860
30240
|
return void 0;
|
|
29861
30241
|
}
|
|
29862
|
-
return holdings;
|
|
29863
30242
|
}
|
|
29864
30243
|
async setLeverage(leverage, marketName) {
|
|
29865
30244
|
if (this.client === null) {
|
|
@@ -29876,46 +30255,52 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29876
30255
|
return false;
|
|
29877
30256
|
}
|
|
29878
30257
|
async getAllOpenPositions() {
|
|
29879
|
-
|
|
29880
|
-
|
|
29881
|
-
|
|
29882
|
-
|
|
29883
|
-
|
|
29884
|
-
|
|
29885
|
-
|
|
29886
|
-
|
|
29887
|
-
if (response.data.length === 0) {
|
|
29888
|
-
return [];
|
|
29889
|
-
} else {
|
|
29890
|
-
return response.data;
|
|
30258
|
+
try {
|
|
30259
|
+
const response = await import_axios8.default.get(`${this.config.extendedBackendReadUrl}/positions`);
|
|
30260
|
+
if (response.data.success) {
|
|
30261
|
+
if (response.data.data.length === 0) {
|
|
30262
|
+
return [];
|
|
30263
|
+
} else {
|
|
30264
|
+
return response.data.data;
|
|
30265
|
+
}
|
|
29891
30266
|
}
|
|
30267
|
+
return null;
|
|
30268
|
+
} catch (err) {
|
|
30269
|
+
logger.error("error getting all open positions", err);
|
|
30270
|
+
return null;
|
|
29892
30271
|
}
|
|
29893
|
-
return null;
|
|
29894
30272
|
}
|
|
29895
30273
|
async getOrderHistory(marketName) {
|
|
29896
|
-
|
|
29897
|
-
|
|
30274
|
+
try {
|
|
30275
|
+
const result = await import_axios8.default.get(`${this.config.extendedBackendReadUrl}/marketOrders/${marketName}`);
|
|
30276
|
+
if (!result.data.success) {
|
|
30277
|
+
return null;
|
|
30278
|
+
}
|
|
30279
|
+
return result.data.data;
|
|
30280
|
+
} catch (err) {
|
|
30281
|
+
logger.error("error getting order history", err);
|
|
29898
30282
|
return null;
|
|
29899
30283
|
}
|
|
29900
|
-
const result = await this.client.getOrderHistory(marketName);
|
|
29901
|
-
return result.data;
|
|
29902
30284
|
}
|
|
29903
30285
|
async getOrderStatus(orderId, marketName) {
|
|
29904
|
-
|
|
29905
|
-
|
|
29906
|
-
|
|
29907
|
-
|
|
29908
|
-
|
|
29909
|
-
|
|
29910
|
-
|
|
30286
|
+
try {
|
|
30287
|
+
if (this.client === null) {
|
|
30288
|
+
logger.error("error initializing client");
|
|
30289
|
+
return null;
|
|
30290
|
+
}
|
|
30291
|
+
const orderhistory = await this.getOrderHistory(marketName);
|
|
30292
|
+
if (!orderhistory || orderhistory.length === 0) {
|
|
30293
|
+
return null;
|
|
30294
|
+
}
|
|
30295
|
+
const order = orderhistory.slice(0, 20).find((order2) => order2.id.toString() === orderId);
|
|
30296
|
+
if (order) {
|
|
30297
|
+
return order;
|
|
30298
|
+
}
|
|
29911
30299
|
return null;
|
|
29912
|
-
}
|
|
29913
|
-
|
|
29914
|
-
if (!order) {
|
|
29915
|
-
logger.error(`error getting order: ${order}`);
|
|
30300
|
+
} catch (error) {
|
|
30301
|
+
logger.error(`error getting order status: ${error}`);
|
|
29916
30302
|
return null;
|
|
29917
30303
|
}
|
|
29918
|
-
return order;
|
|
29919
30304
|
}
|
|
29920
30305
|
async fetchOrderBookBTCUSDC() {
|
|
29921
30306
|
try {
|
|
@@ -29966,14 +30351,40 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29966
30351
|
logger.error("error depositing or setting leverage");
|
|
29967
30352
|
return null;
|
|
29968
30353
|
}
|
|
29969
|
-
const
|
|
29970
|
-
if (
|
|
30354
|
+
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
30355
|
+
if (!ask || !bid || ask.lessThanOrEqualTo(0) || bid.lessThanOrEqualTo(0)) {
|
|
30356
|
+
logger.error(
|
|
30357
|
+
`Invalid orderbook prices: ask=${ask?.toNumber()}, bid=${bid?.toNumber()}`
|
|
30358
|
+
);
|
|
29971
30359
|
return null;
|
|
29972
30360
|
}
|
|
29973
|
-
const { ask, bid } = await this.fetchOrderBookBTCUSDC();
|
|
29974
30361
|
const spread = ask.minus(bid);
|
|
29975
|
-
|
|
29976
|
-
|
|
30362
|
+
const midPrice = ask.plus(bid).div(2);
|
|
30363
|
+
const MAX_PRICE_DEVIATION_MULTIPLIER = 0.5;
|
|
30364
|
+
const priceAdjustmentMultiplier = Math.min(
|
|
30365
|
+
0.2 * attempt,
|
|
30366
|
+
MAX_PRICE_DEVIATION_MULTIPLIER
|
|
30367
|
+
);
|
|
30368
|
+
const priceAdjustment = spread.times(priceAdjustmentMultiplier);
|
|
30369
|
+
let price = midPrice;
|
|
30370
|
+
if (side === "SELL" /* SELL */) {
|
|
30371
|
+
price = midPrice.minus(priceAdjustment);
|
|
30372
|
+
} else {
|
|
30373
|
+
price = midPrice.plus(priceAdjustment);
|
|
30374
|
+
}
|
|
30375
|
+
const maxDeviation = midPrice.times(0.5);
|
|
30376
|
+
if (price.minus(midPrice).abs().greaterThan(maxDeviation)) {
|
|
30377
|
+
logger.error(
|
|
30378
|
+
`Price deviation too large on attempt ${attempt}: price=${price.toNumber()}, midPrice=${midPrice.toNumber()}, deviation=${price.minus(midPrice).abs().toNumber()}`
|
|
30379
|
+
);
|
|
30380
|
+
if (attempt >= maxAttempts) {
|
|
30381
|
+
return null;
|
|
30382
|
+
}
|
|
30383
|
+
price = side === "SELL" /* SELL */ ? midPrice.minus(maxDeviation) : midPrice.plus(maxDeviation);
|
|
30384
|
+
}
|
|
30385
|
+
logger.info(
|
|
30386
|
+
`createOrder attempt ${attempt}/${maxAttempts}: side=${side}, midPrice=${midPrice.toNumber()}, adjustedPrice=${price.toNumber()}, adjustment=${priceAdjustmentMultiplier * 100}%`
|
|
30387
|
+
);
|
|
29977
30388
|
const amount_in_token = (btcAmount * parseInt(leverage)).toFixed(
|
|
29978
30389
|
this.config.extendedPrecision
|
|
29979
30390
|
);
|
|
@@ -29984,14 +30395,57 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
29984
30395
|
price.toFixed(0),
|
|
29985
30396
|
side
|
|
29986
30397
|
);
|
|
29987
|
-
if (!result) {
|
|
30398
|
+
if (!result || !result.position_id) {
|
|
30399
|
+
logger.error("Failed to create order - no position_id returned");
|
|
29988
30400
|
return null;
|
|
29989
30401
|
}
|
|
29990
|
-
|
|
29991
|
-
|
|
29992
|
-
|
|
30402
|
+
const positionId = result.position_id;
|
|
30403
|
+
logger.info(
|
|
30404
|
+
`Order created with position_id: ${positionId}. Waiting for API to update...`
|
|
30405
|
+
);
|
|
30406
|
+
let openOrder = await this.getOrderStatus(
|
|
30407
|
+
positionId,
|
|
30408
|
+
this.config.extendedMarketName
|
|
30409
|
+
);
|
|
30410
|
+
const maxStatusRetries = 3;
|
|
30411
|
+
const statusRetryDelay = 5e3;
|
|
30412
|
+
if (!openOrder) {
|
|
30413
|
+
logger.warn(
|
|
30414
|
+
`Order ${positionId} not found in API yet. Retrying status fetch (max ${maxStatusRetries} times)...`
|
|
30415
|
+
);
|
|
30416
|
+
for (let statusRetry = 1; statusRetry <= maxStatusRetries; statusRetry++) {
|
|
30417
|
+
await new Promise((resolve) => setTimeout(resolve, statusRetryDelay));
|
|
30418
|
+
openOrder = await this.getOrderStatus(
|
|
30419
|
+
positionId,
|
|
30420
|
+
this.config.extendedMarketName
|
|
30421
|
+
);
|
|
30422
|
+
if (openOrder) {
|
|
30423
|
+
logger.info(
|
|
30424
|
+
`Order ${positionId} found after ${statusRetry} status retry(ies)`
|
|
30425
|
+
);
|
|
30426
|
+
break;
|
|
30427
|
+
}
|
|
30428
|
+
logger.warn(
|
|
30429
|
+
`Order ${positionId} still not found after ${statusRetry}/${maxStatusRetries} status retries`
|
|
30430
|
+
);
|
|
30431
|
+
}
|
|
30432
|
+
}
|
|
30433
|
+
if (openOrder && openOrder.status === "FILLED" /* FILLED */) {
|
|
30434
|
+
logger.info(
|
|
30435
|
+
`Order ${positionId} successfully filled with quantity ${openOrder.qty}`
|
|
30436
|
+
);
|
|
30437
|
+
return {
|
|
30438
|
+
position_id: positionId,
|
|
30439
|
+
btc_exposure: openOrder.qty
|
|
30440
|
+
};
|
|
30441
|
+
} else if (openOrder && openOrder.status !== "FILLED" /* FILLED */) {
|
|
30442
|
+
logger.warn(
|
|
30443
|
+
`Order ${positionId} found but status is ${openOrder.status}, not FILLED. Retrying order creation...`
|
|
30444
|
+
);
|
|
29993
30445
|
if (attempt >= maxAttempts) {
|
|
29994
|
-
logger.error(
|
|
30446
|
+
logger.error(
|
|
30447
|
+
`Max retries reached \u2014 order ${positionId} status is ${openOrder.status}, not FILLED`
|
|
30448
|
+
);
|
|
29995
30449
|
return null;
|
|
29996
30450
|
} else {
|
|
29997
30451
|
const backoff = 2e3 * attempt;
|
|
@@ -30005,13 +30459,18 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30005
30459
|
);
|
|
30006
30460
|
}
|
|
30007
30461
|
} else {
|
|
30462
|
+
logger.warn(
|
|
30463
|
+
`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.`
|
|
30464
|
+
);
|
|
30008
30465
|
return {
|
|
30009
|
-
position_id:
|
|
30010
|
-
btc_exposure:
|
|
30466
|
+
position_id: positionId,
|
|
30467
|
+
btc_exposure: amount_in_token
|
|
30011
30468
|
};
|
|
30012
30469
|
}
|
|
30013
30470
|
} catch (err) {
|
|
30014
|
-
logger.error(
|
|
30471
|
+
logger.error(
|
|
30472
|
+
`createShortOrder failed on attempt ${attempt}: ${err.message}`
|
|
30473
|
+
);
|
|
30015
30474
|
if (attempt < maxAttempts) {
|
|
30016
30475
|
const backoff = 1200 * attempt;
|
|
30017
30476
|
logger.info(`Retrying after ${backoff}ms...`);
|
|
@@ -30050,28 +30509,101 @@ var ExtendedAdapter = class _ExtendedAdapter extends BaseAdapter {
|
|
|
30050
30509
|
}
|
|
30051
30510
|
}
|
|
30052
30511
|
async getDepositOrWithdrawalStatus(orderId, operationsType) {
|
|
30053
|
-
|
|
30054
|
-
|
|
30055
|
-
|
|
30056
|
-
|
|
30057
|
-
|
|
30058
|
-
|
|
30059
|
-
|
|
30060
|
-
|
|
30061
|
-
|
|
30512
|
+
const maxAttempts = 15;
|
|
30513
|
+
const retryDelayMs = 3e4;
|
|
30514
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
30515
|
+
try {
|
|
30516
|
+
let transferHistory = await this.client.getAssetOperations({
|
|
30517
|
+
operationsType: [operationsType],
|
|
30518
|
+
operationsStatus: ["COMPLETED" /* COMPLETED */]
|
|
30519
|
+
});
|
|
30520
|
+
if (operationsType === "DEPOSIT" /* DEPOSIT */) {
|
|
30521
|
+
const myTransferStatus = transferHistory.data.find(
|
|
30522
|
+
(operation) => operation.transactionHash?.toLowerCase() === orderId.toString().toLowerCase()
|
|
30523
|
+
);
|
|
30524
|
+
if (!myTransferStatus) {
|
|
30525
|
+
if (attempt < maxAttempts) {
|
|
30526
|
+
logger.info(
|
|
30527
|
+
`Deposit operation not found for transactionHash ${orderId}, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30528
|
+
);
|
|
30529
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30530
|
+
continue;
|
|
30531
|
+
}
|
|
30532
|
+
logger.warn(
|
|
30533
|
+
`Deposit operation not found for transactionHash ${orderId} after ${maxAttempts} attempts`
|
|
30534
|
+
);
|
|
30535
|
+
return false;
|
|
30536
|
+
}
|
|
30537
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
30538
|
+
logger.info(
|
|
30539
|
+
`Deposit operation ${orderId} completed successfully`
|
|
30540
|
+
);
|
|
30541
|
+
return true;
|
|
30542
|
+
} else {
|
|
30543
|
+
if (attempt < maxAttempts) {
|
|
30544
|
+
logger.info(
|
|
30545
|
+
`Deposit operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30546
|
+
);
|
|
30547
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30548
|
+
continue;
|
|
30549
|
+
}
|
|
30550
|
+
logger.warn(
|
|
30551
|
+
`Deposit operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
30552
|
+
);
|
|
30553
|
+
return false;
|
|
30554
|
+
}
|
|
30555
|
+
} else {
|
|
30556
|
+
const myTransferStatus = transferHistory.data.find(
|
|
30557
|
+
(operation) => operation.id === orderId.toString()
|
|
30558
|
+
);
|
|
30559
|
+
if (!myTransferStatus) {
|
|
30560
|
+
if (attempt < maxAttempts) {
|
|
30561
|
+
logger.info(
|
|
30562
|
+
`Withdrawal status not found for orderId ${orderId} in completed operations, retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30563
|
+
);
|
|
30564
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30565
|
+
continue;
|
|
30566
|
+
}
|
|
30567
|
+
logger.warn(
|
|
30568
|
+
`Withdrawal operation not found for orderId ${orderId} after ${maxAttempts} attempts`
|
|
30569
|
+
);
|
|
30570
|
+
return false;
|
|
30571
|
+
}
|
|
30572
|
+
if (myTransferStatus.status === "COMPLETED" /* COMPLETED */) {
|
|
30573
|
+
logger.info(
|
|
30574
|
+
`Withdrawal operation ${orderId} completed successfully`
|
|
30575
|
+
);
|
|
30576
|
+
return true;
|
|
30577
|
+
} else {
|
|
30578
|
+
if (attempt < maxAttempts) {
|
|
30579
|
+
logger.info(
|
|
30580
|
+
`Withdrawal operation ${orderId} found but status is ${myTransferStatus.status}, not COMPLETED. Retrying (attempt ${attempt}/${maxAttempts})...`
|
|
30581
|
+
);
|
|
30582
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30583
|
+
continue;
|
|
30584
|
+
}
|
|
30585
|
+
logger.warn(
|
|
30586
|
+
`Withdrawal operation ${orderId} status is ${myTransferStatus.status} after ${maxAttempts} attempts, expected COMPLETED`
|
|
30587
|
+
);
|
|
30588
|
+
return false;
|
|
30589
|
+
}
|
|
30062
30590
|
}
|
|
30063
|
-
|
|
30064
|
-
|
|
30065
|
-
|
|
30066
|
-
|
|
30067
|
-
|
|
30591
|
+
} catch (err) {
|
|
30592
|
+
logger.error(
|
|
30593
|
+
`error getting deposit or withdrawal status (attempt ${attempt}/${maxAttempts}): ${err}`
|
|
30594
|
+
);
|
|
30595
|
+
if (attempt < maxAttempts) {
|
|
30596
|
+
logger.info(`Retrying after ${retryDelayMs}ms...`);
|
|
30597
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
30598
|
+
continue;
|
|
30068
30599
|
}
|
|
30069
|
-
|
|
30600
|
+
logger.error(
|
|
30601
|
+
`Max retry attempts reached for getDepositOrWithdrawalStatus`
|
|
30602
|
+
);
|
|
30603
|
+
return false;
|
|
30070
30604
|
}
|
|
30071
|
-
} catch (err) {
|
|
30072
|
-
logger.error(`error getting deposit or withdrawal status: ${err}`);
|
|
30073
|
-
return false;
|
|
30074
30605
|
}
|
|
30606
|
+
return false;
|
|
30075
30607
|
}
|
|
30076
30608
|
};
|
|
30077
30609
|
|
|
@@ -30151,12 +30683,351 @@ var UnusedBalanceAdapter = class _UnusedBalanceAdapter extends BaseAdapter {
|
|
|
30151
30683
|
}
|
|
30152
30684
|
};
|
|
30153
30685
|
|
|
30686
|
+
// src/strategies/universal-adapters/avnu-adapter.ts
|
|
30687
|
+
var import_starknet23 = require("starknet");
|
|
30688
|
+
var import_axios9 = __toESM(require("axios"));
|
|
30689
|
+
var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
|
|
30690
|
+
constructor(config) {
|
|
30691
|
+
super(config, _AvnuAdapter.name, Protocols.AVNU);
|
|
30692
|
+
this.config = config;
|
|
30693
|
+
this.avnuWrapper = new AvnuWrapper();
|
|
30694
|
+
}
|
|
30695
|
+
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
30696
|
+
async getAPY(supportedPosition) {
|
|
30697
|
+
return Promise.resolve({ apy: 0, type: "base" /* BASE */ });
|
|
30698
|
+
}
|
|
30699
|
+
async getPosition(supportedPosition) {
|
|
30700
|
+
return Promise.resolve({ amount: new Web3Number(0, 0), remarks: "Avnu Positions" });
|
|
30701
|
+
}
|
|
30702
|
+
async maxDeposit(amount) {
|
|
30703
|
+
return Promise.resolve({
|
|
30704
|
+
tokenInfo: this.config.baseToken,
|
|
30705
|
+
amount: new Web3Number(0, 0),
|
|
30706
|
+
usdValue: 0,
|
|
30707
|
+
apy: { apy: 0, type: "base" /* BASE */ },
|
|
30708
|
+
protocol: Protocols.AVNU,
|
|
30709
|
+
remarks: ""
|
|
30710
|
+
});
|
|
30711
|
+
}
|
|
30712
|
+
async maxWithdraw() {
|
|
30713
|
+
return Promise.resolve({
|
|
30714
|
+
tokenInfo: this.config.baseToken,
|
|
30715
|
+
amount: new Web3Number(0, 0),
|
|
30716
|
+
usdValue: 0,
|
|
30717
|
+
apy: { apy: 0, type: "base" /* BASE */ },
|
|
30718
|
+
protocol: Protocols.AVNU,
|
|
30719
|
+
remarks: ""
|
|
30720
|
+
});
|
|
30721
|
+
}
|
|
30722
|
+
_getDepositLeaf() {
|
|
30723
|
+
const vaultAllocator = ContractAddr.from(
|
|
30724
|
+
this.config.vaultAllocator.address
|
|
30725
|
+
);
|
|
30726
|
+
return [
|
|
30727
|
+
{
|
|
30728
|
+
target: this.config.supportedPositions[0].asset.address,
|
|
30729
|
+
method: "approve",
|
|
30730
|
+
packedArguments: [
|
|
30731
|
+
AVNU_EXCHANGE.toBigInt()
|
|
30732
|
+
],
|
|
30733
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
30734
|
+
id: `approve_${this.config.supportedPositions[0].asset.symbol}`
|
|
30735
|
+
},
|
|
30736
|
+
{
|
|
30737
|
+
target: AVNU_EXCHANGE,
|
|
30738
|
+
method: "multi_route_swap",
|
|
30739
|
+
packedArguments: [
|
|
30740
|
+
this.config.supportedPositions[0].asset.address.toBigInt(),
|
|
30741
|
+
//usdc
|
|
30742
|
+
this.config.supportedPositions[1].asset.address.toBigInt(),
|
|
30743
|
+
//wbtc
|
|
30744
|
+
vaultAllocator.toBigInt()
|
|
30745
|
+
],
|
|
30746
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
30747
|
+
id: `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`
|
|
30748
|
+
}
|
|
30749
|
+
];
|
|
30750
|
+
}
|
|
30751
|
+
_getWithdrawLeaf() {
|
|
30752
|
+
const vaultAllocator = ContractAddr.from(
|
|
30753
|
+
this.config.vaultAllocator.address
|
|
30754
|
+
);
|
|
30755
|
+
const toToken = this.config.supportedPositions[0].asset;
|
|
30756
|
+
const fromToken = this.config.supportedPositions[1].asset;
|
|
30757
|
+
return [
|
|
30758
|
+
{
|
|
30759
|
+
target: fromToken.address,
|
|
30760
|
+
method: "approve",
|
|
30761
|
+
packedArguments: [
|
|
30762
|
+
AVNU_EXCHANGE.toBigInt()
|
|
30763
|
+
],
|
|
30764
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
30765
|
+
id: `approve_${fromToken.symbol}`
|
|
30766
|
+
},
|
|
30767
|
+
{
|
|
30768
|
+
target: AVNU_EXCHANGE,
|
|
30769
|
+
method: "multi_route_swap",
|
|
30770
|
+
packedArguments: [
|
|
30771
|
+
fromToken.address.toBigInt(),
|
|
30772
|
+
//wbtc
|
|
30773
|
+
toToken.address.toBigInt(),
|
|
30774
|
+
//usdc
|
|
30775
|
+
vaultAllocator.toBigInt()
|
|
30776
|
+
],
|
|
30777
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
30778
|
+
id: `asbtu_${fromToken.symbol}_${fromToken.symbol}`
|
|
30779
|
+
}
|
|
30780
|
+
];
|
|
30781
|
+
}
|
|
30782
|
+
_getLegacySwapLeaf() {
|
|
30783
|
+
return [];
|
|
30784
|
+
}
|
|
30785
|
+
async getDepositCall(params) {
|
|
30786
|
+
try {
|
|
30787
|
+
const fromToken = this.config.supportedPositions[0].asset;
|
|
30788
|
+
const toToken = this.config.supportedPositions[1].asset;
|
|
30789
|
+
const vaultAllocator = ContractAddr.from(
|
|
30790
|
+
this.config.vaultAllocator.address
|
|
30791
|
+
);
|
|
30792
|
+
const quote = await this.getQuotesAvnu(
|
|
30793
|
+
fromToken.address.toString(),
|
|
30794
|
+
toToken.address.toString(),
|
|
30795
|
+
params.amount.toNumber(),
|
|
30796
|
+
vaultAllocator.address.toString(),
|
|
30797
|
+
toToken.decimals,
|
|
30798
|
+
true
|
|
30799
|
+
);
|
|
30800
|
+
if (!quote) {
|
|
30801
|
+
logger.error("error getting quote from avnu");
|
|
30802
|
+
return [];
|
|
30803
|
+
}
|
|
30804
|
+
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
30805
|
+
quote,
|
|
30806
|
+
vaultAllocator.address
|
|
30807
|
+
);
|
|
30808
|
+
const swapCallData = getCalldata[0];
|
|
30809
|
+
const amount = import_starknet23.uint256.bnToUint256(quote.sellAmountInUsd * 10 ** 7);
|
|
30810
|
+
return [
|
|
30811
|
+
{
|
|
30812
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
30813
|
+
call: {
|
|
30814
|
+
contractAddress: fromToken.address,
|
|
30815
|
+
selector: import_starknet23.hash.getSelectorFromName("approve"),
|
|
30816
|
+
calldata: [
|
|
30817
|
+
AVNU_EXCHANGE.toBigInt(),
|
|
30818
|
+
toBigInt(amount.low.toString()),
|
|
30819
|
+
// amount low
|
|
30820
|
+
toBigInt(amount.high.toString())
|
|
30821
|
+
// amount high
|
|
30822
|
+
]
|
|
30823
|
+
}
|
|
30824
|
+
},
|
|
30825
|
+
{
|
|
30826
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
30827
|
+
call: {
|
|
30828
|
+
contractAddress: AVNU_EXCHANGE,
|
|
30829
|
+
selector: import_starknet23.hash.getSelectorFromName("multi_route_swap"),
|
|
30830
|
+
calldata: swapCallData
|
|
30831
|
+
}
|
|
30832
|
+
}
|
|
30833
|
+
];
|
|
30834
|
+
} catch (error) {
|
|
30835
|
+
logger.error(`Error getting Avnu quote: ${error}`);
|
|
30836
|
+
return [];
|
|
30837
|
+
}
|
|
30838
|
+
}
|
|
30839
|
+
//Swap wbtc to usdc
|
|
30840
|
+
async getWithdrawCall(params) {
|
|
30841
|
+
try {
|
|
30842
|
+
const toToken = this.config.supportedPositions[0].asset;
|
|
30843
|
+
const fromToken = this.config.supportedPositions[1].asset;
|
|
30844
|
+
const vaultAllocator = ContractAddr.from(
|
|
30845
|
+
this.config.vaultAllocator.address
|
|
30846
|
+
);
|
|
30847
|
+
const quote = await this.getQuotesAvnu(
|
|
30848
|
+
fromToken.address.toString(),
|
|
30849
|
+
toToken.address.toString(),
|
|
30850
|
+
params.amount.toNumber(),
|
|
30851
|
+
vaultAllocator.address.toString(),
|
|
30852
|
+
fromToken.decimals,
|
|
30853
|
+
false
|
|
30854
|
+
);
|
|
30855
|
+
if (!quote) {
|
|
30856
|
+
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
30857
|
+
return [];
|
|
30858
|
+
}
|
|
30859
|
+
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
30860
|
+
quote,
|
|
30861
|
+
vaultAllocator.address
|
|
30862
|
+
);
|
|
30863
|
+
const swapCallData = getCalldata[0];
|
|
30864
|
+
const amount = import_starknet23.uint256.bnToUint256(params.amount.toWei());
|
|
30865
|
+
return [
|
|
30866
|
+
{
|
|
30867
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
30868
|
+
call: {
|
|
30869
|
+
contractAddress: fromToken.address,
|
|
30870
|
+
selector: import_starknet23.hash.getSelectorFromName("approve"),
|
|
30871
|
+
calldata: [
|
|
30872
|
+
AVNU_EXCHANGE.toBigInt(),
|
|
30873
|
+
toBigInt(amount.low.toString()),
|
|
30874
|
+
// amount low
|
|
30875
|
+
toBigInt(amount.high.toString())
|
|
30876
|
+
// amount high
|
|
30877
|
+
]
|
|
30878
|
+
}
|
|
30879
|
+
},
|
|
30880
|
+
{
|
|
30881
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
30882
|
+
call: {
|
|
30883
|
+
contractAddress: AVNU_EXCHANGE,
|
|
30884
|
+
selector: import_starknet23.hash.getSelectorFromName("multi_route_swap"),
|
|
30885
|
+
calldata: swapCallData
|
|
30886
|
+
}
|
|
30887
|
+
}
|
|
30888
|
+
];
|
|
30889
|
+
} catch (error) {
|
|
30890
|
+
logger.error(`Error getting Avnu quote: ${error}`);
|
|
30891
|
+
return [];
|
|
30892
|
+
}
|
|
30893
|
+
}
|
|
30894
|
+
async getSwapCallData(quote) {
|
|
30895
|
+
return await this.avnuWrapper.getSwapCallData(quote, this.config.vaultAllocator.address);
|
|
30896
|
+
}
|
|
30897
|
+
async getHealthFactor() {
|
|
30898
|
+
return Promise.resolve(1);
|
|
30899
|
+
}
|
|
30900
|
+
async fetchQuoteWithRetry(params, retries = 5) {
|
|
30901
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
30902
|
+
try {
|
|
30903
|
+
const response = await import_axios9.default.get(this.config.baseUrl, { params });
|
|
30904
|
+
if (response.data && response.data.length > 0) {
|
|
30905
|
+
return response;
|
|
30906
|
+
}
|
|
30907
|
+
throw new Error("Empty response data");
|
|
30908
|
+
} catch (err) {
|
|
30909
|
+
logger.error(`Error fetching quote with retry: ${err}`);
|
|
30910
|
+
if (attempt === retries - 1) {
|
|
30911
|
+
throw err;
|
|
30912
|
+
}
|
|
30913
|
+
await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
|
|
30914
|
+
}
|
|
30915
|
+
}
|
|
30916
|
+
throw new Error("Failed to fetch quote after retries");
|
|
30917
|
+
}
|
|
30918
|
+
async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance = 5e3) {
|
|
30919
|
+
try {
|
|
30920
|
+
const fromToken = this.config.supportedPositions[0].asset;
|
|
30921
|
+
const toToken = this.config.supportedPositions[1].asset;
|
|
30922
|
+
if (!usdcToBtc) {
|
|
30923
|
+
const sellAmount2 = returnFormattedAmount(amount, toTokenDecimals);
|
|
30924
|
+
const params2 = {
|
|
30925
|
+
sellTokenAddress: from_token_address,
|
|
30926
|
+
buyTokenAddress: to_token_address,
|
|
30927
|
+
takerAddress,
|
|
30928
|
+
sellAmount: sellAmount2
|
|
30929
|
+
};
|
|
30930
|
+
const finalQuote2 = await this.fetchQuoteWithRetry(params2);
|
|
30931
|
+
if (!finalQuote2.data.length) {
|
|
30932
|
+
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
30933
|
+
return null;
|
|
30934
|
+
}
|
|
30935
|
+
const dataObject2 = finalQuote2.data[0];
|
|
30936
|
+
return dataObject2;
|
|
30937
|
+
}
|
|
30938
|
+
const btcPrice = await this.getPriceOfToken(toToken.address.toString());
|
|
30939
|
+
if (!btcPrice) {
|
|
30940
|
+
logger.error(`error getting btc price: ${btcPrice}`);
|
|
30941
|
+
return null;
|
|
30942
|
+
}
|
|
30943
|
+
const estimatedUsdcAmount = Math.floor(amount * btcPrice);
|
|
30944
|
+
logger.info(`${_AvnuAdapter.name}::getQuotesAvnu estimatedUsdcAmount: ${estimatedUsdcAmount}`);
|
|
30945
|
+
const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
|
|
30946
|
+
logger.info(`${_AvnuAdapter.name}::getQuotesAvnu targetBtcBig: ${targetBtcBig}`);
|
|
30947
|
+
let low = BigInt(
|
|
30948
|
+
Math.floor(
|
|
30949
|
+
estimatedUsdcAmount * 10 ** fromToken.decimals * 0.9
|
|
30950
|
+
)
|
|
30951
|
+
);
|
|
30952
|
+
let high = BigInt(
|
|
30953
|
+
Math.floor(
|
|
30954
|
+
estimatedUsdcAmount * 10 ** fromToken.decimals * 1.1
|
|
30955
|
+
)
|
|
30956
|
+
);
|
|
30957
|
+
let mid = 0n;
|
|
30958
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
30959
|
+
mid = (low + high) / 2n;
|
|
30960
|
+
const sellAmount2 = returnFormattedAmount(Number(mid), 0);
|
|
30961
|
+
const quote = await this.fetchQuoteWithRetry({
|
|
30962
|
+
sellTokenAddress: from_token_address,
|
|
30963
|
+
buyTokenAddress: to_token_address,
|
|
30964
|
+
takerAddress,
|
|
30965
|
+
sellAmount: sellAmount2
|
|
30966
|
+
});
|
|
30967
|
+
const gotBtc = BigInt(quote.data[0].buyAmount);
|
|
30968
|
+
if (gotBtc === targetBtcBig) return quote.data[0];
|
|
30969
|
+
if (gotBtc > targetBtcBig) {
|
|
30970
|
+
high = mid;
|
|
30971
|
+
} else {
|
|
30972
|
+
low = mid;
|
|
30973
|
+
}
|
|
30974
|
+
if (gotBtc >= targetBtcBig && gotBtc <= targetBtcBig + BigInt(tolerance)) {
|
|
30975
|
+
return quote.data[0];
|
|
30976
|
+
}
|
|
30977
|
+
}
|
|
30978
|
+
let sellAmount = returnFormattedAmount(
|
|
30979
|
+
Number(mid),
|
|
30980
|
+
0
|
|
30981
|
+
);
|
|
30982
|
+
const params = {
|
|
30983
|
+
sellTokenAddress: from_token_address,
|
|
30984
|
+
buyTokenAddress: to_token_address,
|
|
30985
|
+
takerAddress,
|
|
30986
|
+
sellAmount
|
|
30987
|
+
};
|
|
30988
|
+
const finalQuote = await this.fetchQuoteWithRetry(params);
|
|
30989
|
+
if (!finalQuote.data.length) {
|
|
30990
|
+
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
30991
|
+
return null;
|
|
30992
|
+
}
|
|
30993
|
+
const dataObject = finalQuote.data[0];
|
|
30994
|
+
const wbtcAmountOut = parseInt(dataObject.buyAmount.toString(), 16);
|
|
30995
|
+
logger.info(`${_AvnuAdapter.name}::getQuotesAvnu finalAmountOfWbtcOut : ${wbtcAmountOut} ${dataObject.buyAmount} ${dataObject.sellAmount.toString()} ${dataObject.sellAmount.toString()}`);
|
|
30996
|
+
return dataObject;
|
|
30997
|
+
} catch (err) {
|
|
30998
|
+
logger.error(`No quotes available for this swap: ${err}`);
|
|
30999
|
+
return null;
|
|
31000
|
+
}
|
|
31001
|
+
}
|
|
31002
|
+
async getPriceOfToken(tokenAddress, retries = MAX_RETRIES) {
|
|
31003
|
+
try {
|
|
31004
|
+
const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
|
|
31005
|
+
const response = await import_axios9.default.get(url);
|
|
31006
|
+
const length = response.data.length;
|
|
31007
|
+
return response.data[length - 1].value;
|
|
31008
|
+
} catch (err) {
|
|
31009
|
+
if (retries > 0) {
|
|
31010
|
+
await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
|
|
31011
|
+
return this.getPriceOfToken(tokenAddress, retries - 1);
|
|
31012
|
+
} else {
|
|
31013
|
+
logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
|
|
31014
|
+
return null;
|
|
31015
|
+
}
|
|
31016
|
+
}
|
|
31017
|
+
}
|
|
31018
|
+
};
|
|
31019
|
+
|
|
30154
31020
|
// src/strategies/universal-strategy.tsx
|
|
30155
31021
|
var AUMTypes = /* @__PURE__ */ ((AUMTypes2) => {
|
|
30156
31022
|
AUMTypes2["FINALISED"] = "finalised";
|
|
30157
31023
|
AUMTypes2["DEFISPRING"] = "defispring";
|
|
30158
31024
|
return AUMTypes2;
|
|
30159
31025
|
})(AUMTypes || {});
|
|
31026
|
+
var PositionTypeAvnuExtended = /* @__PURE__ */ ((PositionTypeAvnuExtended2) => {
|
|
31027
|
+
PositionTypeAvnuExtended2["OPEN"] = "open";
|
|
31028
|
+
PositionTypeAvnuExtended2["CLOSE"] = "close";
|
|
31029
|
+
return PositionTypeAvnuExtended2;
|
|
31030
|
+
})(PositionTypeAvnuExtended || {});
|
|
30160
31031
|
var UNIVERSAL_MANAGE_IDS = /* @__PURE__ */ ((UNIVERSAL_MANAGE_IDS2) => {
|
|
30161
31032
|
UNIVERSAL_MANAGE_IDS2["FLASH_LOAN"] = "flash_loan_init";
|
|
30162
31033
|
UNIVERSAL_MANAGE_IDS2["VESU_LEG1"] = "vesu_leg1";
|
|
@@ -30184,7 +31055,7 @@ function getContractDetails(settings) {
|
|
|
30184
31055
|
}
|
|
30185
31056
|
|
|
30186
31057
|
// src/strategies/svk-strategy.ts
|
|
30187
|
-
var
|
|
31058
|
+
var import_starknet24 = require("starknet");
|
|
30188
31059
|
|
|
30189
31060
|
// src/data/universal-vault.abi.json
|
|
30190
31061
|
var universal_vault_abi_default = [
|
|
@@ -32511,12 +33382,12 @@ var SVKStrategy = class extends BaseStrategy {
|
|
|
32511
33382
|
this.pricer = pricer;
|
|
32512
33383
|
this.metadata = metadata;
|
|
32513
33384
|
this.address = metadata.address;
|
|
32514
|
-
this.contract = new
|
|
33385
|
+
this.contract = new import_starknet24.Contract({
|
|
32515
33386
|
abi: universal_vault_abi_default,
|
|
32516
33387
|
address: this.address.address,
|
|
32517
33388
|
providerOrAccount: this.config.provider
|
|
32518
33389
|
});
|
|
32519
|
-
this.managerContract = new
|
|
33390
|
+
this.managerContract = new import_starknet24.Contract({
|
|
32520
33391
|
abi: vault_manager_abi_default,
|
|
32521
33392
|
address: this.metadata.additionalInfo.manager.address,
|
|
32522
33393
|
providerOrAccount: this.config.provider
|
|
@@ -32629,7 +33500,7 @@ var SVKStrategy = class extends BaseStrategy {
|
|
|
32629
33500
|
getSetManagerCall(strategist, root = this.getMerkleRoot()) {
|
|
32630
33501
|
return this.managerContract.populate("set_manage_root", [
|
|
32631
33502
|
strategist.address,
|
|
32632
|
-
|
|
33503
|
+
import_starknet24.num.getHexString(root)
|
|
32633
33504
|
]);
|
|
32634
33505
|
}
|
|
32635
33506
|
/**
|
|
@@ -33337,7 +34208,8 @@ function getLooperSettings(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
|
|
|
33337
34208
|
minHealthFactor: vaultSettings.minHealthFactor,
|
|
33338
34209
|
quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
|
|
33339
34210
|
...baseAdapterConfig,
|
|
33340
|
-
supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }]
|
|
34211
|
+
supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
|
|
34212
|
+
minimumVesuMovementAmount: 0
|
|
33341
34213
|
}));
|
|
33342
34214
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
33343
34215
|
...baseAdapterConfig
|
|
@@ -33566,335 +34438,15 @@ var HyperLSTStrategies = [
|
|
|
33566
34438
|
getStrategySettings("mRe7YIELD", "mRe7YIELD", hypermRe7YIELD, false, false)
|
|
33567
34439
|
];
|
|
33568
34440
|
|
|
33569
|
-
// src/strategies/
|
|
33570
|
-
var
|
|
33571
|
-
|
|
33572
|
-
|
|
33573
|
-
|
|
33574
|
-
|
|
33575
|
-
|
|
33576
|
-
|
|
33577
|
-
|
|
33578
|
-
//abstract means the method has no implementation in this class; instead, child classes must implement it.
|
|
33579
|
-
async getAPY(supportedPosition) {
|
|
33580
|
-
return Promise.resolve({ apy: 0, type: "base" /* BASE */ });
|
|
33581
|
-
}
|
|
33582
|
-
async getPosition(supportedPosition) {
|
|
33583
|
-
return Promise.resolve({ amount: new Web3Number(0, 0), remarks: "" });
|
|
33584
|
-
}
|
|
33585
|
-
async maxDeposit(amount) {
|
|
33586
|
-
return Promise.resolve({
|
|
33587
|
-
tokenInfo: this.config.baseToken,
|
|
33588
|
-
amount: new Web3Number(0, 0),
|
|
33589
|
-
usdValue: 0,
|
|
33590
|
-
apy: { apy: 0, type: "base" /* BASE */ },
|
|
33591
|
-
protocol: Protocols.AVNU,
|
|
33592
|
-
remarks: ""
|
|
33593
|
-
});
|
|
33594
|
-
}
|
|
33595
|
-
async maxWithdraw() {
|
|
33596
|
-
return Promise.resolve({
|
|
33597
|
-
tokenInfo: this.config.baseToken,
|
|
33598
|
-
amount: new Web3Number(0, 0),
|
|
33599
|
-
usdValue: 0,
|
|
33600
|
-
apy: { apy: 0, type: "base" /* BASE */ },
|
|
33601
|
-
protocol: Protocols.AVNU,
|
|
33602
|
-
remarks: ""
|
|
33603
|
-
});
|
|
33604
|
-
}
|
|
33605
|
-
_getDepositLeaf() {
|
|
33606
|
-
const vaultAllocator = ContractAddr.from(
|
|
33607
|
-
this.config.vaultAllocator.address
|
|
33608
|
-
);
|
|
33609
|
-
return [
|
|
33610
|
-
{
|
|
33611
|
-
target: this.config.supportedPositions[0].asset.address,
|
|
33612
|
-
method: "approve",
|
|
33613
|
-
packedArguments: [
|
|
33614
|
-
AVNU_EXCHANGE.toBigInt()
|
|
33615
|
-
],
|
|
33616
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
33617
|
-
id: `approve_${this.config.supportedPositions[0].asset.symbol}`
|
|
33618
|
-
},
|
|
33619
|
-
{
|
|
33620
|
-
target: AVNU_EXCHANGE,
|
|
33621
|
-
method: "multi_route_swap",
|
|
33622
|
-
packedArguments: [
|
|
33623
|
-
this.config.supportedPositions[0].asset.address.toBigInt(),
|
|
33624
|
-
//usdc
|
|
33625
|
-
this.config.supportedPositions[1].asset.address.toBigInt(),
|
|
33626
|
-
//wbtc
|
|
33627
|
-
vaultAllocator.toBigInt()
|
|
33628
|
-
],
|
|
33629
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
33630
|
-
id: `asutb_${this.config.supportedPositions[0].asset.symbol}_${this.config.supportedPositions[1].asset.symbol}`
|
|
33631
|
-
}
|
|
33632
|
-
];
|
|
33633
|
-
}
|
|
33634
|
-
_getWithdrawLeaf() {
|
|
33635
|
-
const vaultAllocator = ContractAddr.from(
|
|
33636
|
-
this.config.vaultAllocator.address
|
|
33637
|
-
);
|
|
33638
|
-
const toToken = this.config.supportedPositions[0].asset;
|
|
33639
|
-
const fromToken = this.config.supportedPositions[1].asset;
|
|
33640
|
-
return [
|
|
33641
|
-
{
|
|
33642
|
-
target: fromToken.address,
|
|
33643
|
-
method: "approve",
|
|
33644
|
-
packedArguments: [
|
|
33645
|
-
AVNU_EXCHANGE.toBigInt()
|
|
33646
|
-
],
|
|
33647
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
33648
|
-
id: `approve_${fromToken.symbol}`
|
|
33649
|
-
},
|
|
33650
|
-
{
|
|
33651
|
-
target: AVNU_EXCHANGE,
|
|
33652
|
-
method: "multi_route_swap",
|
|
33653
|
-
packedArguments: [
|
|
33654
|
-
fromToken.address.toBigInt(),
|
|
33655
|
-
//wbtc
|
|
33656
|
-
toToken.address.toBigInt(),
|
|
33657
|
-
//usdc
|
|
33658
|
-
vaultAllocator.toBigInt()
|
|
33659
|
-
],
|
|
33660
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
33661
|
-
id: `asbtu_${fromToken.symbol}_${fromToken.symbol}`
|
|
33662
|
-
}
|
|
33663
|
-
];
|
|
33664
|
-
}
|
|
33665
|
-
_getLegacySwapLeaf() {
|
|
33666
|
-
return [];
|
|
33667
|
-
}
|
|
33668
|
-
async getDepositCall(params) {
|
|
33669
|
-
try {
|
|
33670
|
-
const fromToken = this.config.supportedPositions[0].asset;
|
|
33671
|
-
const toToken = this.config.supportedPositions[1].asset;
|
|
33672
|
-
const vaultAllocator = ContractAddr.from(
|
|
33673
|
-
this.config.vaultAllocator.address
|
|
33674
|
-
);
|
|
33675
|
-
const quote = await this.getQuotesAvnu(
|
|
33676
|
-
fromToken.address.toString(),
|
|
33677
|
-
toToken.address.toString(),
|
|
33678
|
-
params.amount.toNumber(),
|
|
33679
|
-
vaultAllocator.address.toString(),
|
|
33680
|
-
toToken.decimals,
|
|
33681
|
-
true
|
|
33682
|
-
);
|
|
33683
|
-
if (!quote) {
|
|
33684
|
-
logger.error("error getting quote from avnu");
|
|
33685
|
-
return [];
|
|
33686
|
-
}
|
|
33687
|
-
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
33688
|
-
quote,
|
|
33689
|
-
vaultAllocator.address
|
|
33690
|
-
);
|
|
33691
|
-
const swapCallData = getCalldata[0];
|
|
33692
|
-
const amount = import_starknet24.uint256.bnToUint256(quote.sellAmountInUsd * 10 ** 7);
|
|
33693
|
-
return [
|
|
33694
|
-
{
|
|
33695
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
33696
|
-
call: {
|
|
33697
|
-
contractAddress: fromToken.address,
|
|
33698
|
-
selector: import_starknet24.hash.getSelectorFromName("approve"),
|
|
33699
|
-
calldata: [
|
|
33700
|
-
AVNU_EXCHANGE.toBigInt(),
|
|
33701
|
-
toBigInt(amount.low.toString()),
|
|
33702
|
-
// amount low
|
|
33703
|
-
toBigInt(amount.high.toString())
|
|
33704
|
-
// amount high
|
|
33705
|
-
]
|
|
33706
|
-
}
|
|
33707
|
-
},
|
|
33708
|
-
{
|
|
33709
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
33710
|
-
call: {
|
|
33711
|
-
contractAddress: AVNU_EXCHANGE,
|
|
33712
|
-
selector: import_starknet24.hash.getSelectorFromName("multi_route_swap"),
|
|
33713
|
-
calldata: swapCallData
|
|
33714
|
-
}
|
|
33715
|
-
}
|
|
33716
|
-
];
|
|
33717
|
-
} catch (error) {
|
|
33718
|
-
logger.error(`Error getting Avnu quote: ${error}`);
|
|
33719
|
-
return [];
|
|
33720
|
-
}
|
|
33721
|
-
}
|
|
33722
|
-
//Swap wbtc to usdc
|
|
33723
|
-
async getWithdrawCall(params) {
|
|
33724
|
-
try {
|
|
33725
|
-
const toToken = this.config.supportedPositions[0].asset;
|
|
33726
|
-
const fromToken = this.config.supportedPositions[1].asset;
|
|
33727
|
-
const vaultAllocator = ContractAddr.from(
|
|
33728
|
-
this.config.vaultAllocator.address
|
|
33729
|
-
);
|
|
33730
|
-
const quote = await this.getQuotesAvnu(
|
|
33731
|
-
fromToken.address.toString(),
|
|
33732
|
-
toToken.address.toString(),
|
|
33733
|
-
params.amount.toNumber(),
|
|
33734
|
-
vaultAllocator.address.toString(),
|
|
33735
|
-
fromToken.decimals,
|
|
33736
|
-
false
|
|
33737
|
-
);
|
|
33738
|
-
if (!quote) {
|
|
33739
|
-
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
33740
|
-
return [];
|
|
33741
|
-
}
|
|
33742
|
-
const getCalldata = await this.avnuWrapper.getSwapCallData(
|
|
33743
|
-
quote,
|
|
33744
|
-
vaultAllocator.address
|
|
33745
|
-
);
|
|
33746
|
-
const swapCallData = getCalldata[0];
|
|
33747
|
-
const amount = import_starknet24.uint256.bnToUint256(params.amount.toWei());
|
|
33748
|
-
return [
|
|
33749
|
-
{
|
|
33750
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
33751
|
-
call: {
|
|
33752
|
-
contractAddress: fromToken.address,
|
|
33753
|
-
selector: import_starknet24.hash.getSelectorFromName("approve"),
|
|
33754
|
-
calldata: [
|
|
33755
|
-
AVNU_EXCHANGE.toBigInt(),
|
|
33756
|
-
toBigInt(amount.low.toString()),
|
|
33757
|
-
// amount low
|
|
33758
|
-
toBigInt(amount.high.toString())
|
|
33759
|
-
// amount high
|
|
33760
|
-
]
|
|
33761
|
-
}
|
|
33762
|
-
},
|
|
33763
|
-
{
|
|
33764
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
33765
|
-
call: {
|
|
33766
|
-
contractAddress: AVNU_EXCHANGE,
|
|
33767
|
-
selector: import_starknet24.hash.getSelectorFromName("multi_route_swap"),
|
|
33768
|
-
calldata: swapCallData
|
|
33769
|
-
}
|
|
33770
|
-
}
|
|
33771
|
-
];
|
|
33772
|
-
} catch (error) {
|
|
33773
|
-
logger.error(`Error getting Avnu quote: ${error}`);
|
|
33774
|
-
return [];
|
|
33775
|
-
}
|
|
33776
|
-
}
|
|
33777
|
-
async getSwapCallData(quote) {
|
|
33778
|
-
return await this.avnuWrapper.getSwapCallData(quote, this.config.vaultAllocator.address);
|
|
33779
|
-
}
|
|
33780
|
-
async getHealthFactor() {
|
|
33781
|
-
return Promise.resolve(1);
|
|
33782
|
-
}
|
|
33783
|
-
async fetchQuoteWithRetry(params, retries = 5) {
|
|
33784
|
-
for (let attempt = 0; attempt < retries; attempt++) {
|
|
33785
|
-
try {
|
|
33786
|
-
const response = await import_axios9.default.get(this.config.baseUrl, { params });
|
|
33787
|
-
if (response.data && response.data.length > 0) {
|
|
33788
|
-
return response;
|
|
33789
|
-
}
|
|
33790
|
-
throw new Error("Empty response data");
|
|
33791
|
-
} catch (err) {
|
|
33792
|
-
logger.error(`Error fetching quote with retry: ${err}`);
|
|
33793
|
-
if (attempt === retries - 1) {
|
|
33794
|
-
throw err;
|
|
33795
|
-
}
|
|
33796
|
-
await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
|
|
33797
|
-
}
|
|
33798
|
-
}
|
|
33799
|
-
throw new Error("Failed to fetch quote after retries");
|
|
33800
|
-
}
|
|
33801
|
-
async getQuotesAvnu(from_token_address, to_token_address, amount, takerAddress, toTokenDecimals, usdcToBtc, maxIterations = 5, tolerance = 1e4) {
|
|
33802
|
-
try {
|
|
33803
|
-
const fromToken = this.config.supportedPositions[0].asset;
|
|
33804
|
-
const toToken = this.config.supportedPositions[1].asset;
|
|
33805
|
-
if (!usdcToBtc) {
|
|
33806
|
-
const sellAmount2 = returnFormattedAmount(amount, toTokenDecimals);
|
|
33807
|
-
const params2 = {
|
|
33808
|
-
sellTokenAddress: from_token_address,
|
|
33809
|
-
buyTokenAddress: to_token_address,
|
|
33810
|
-
takerAddress,
|
|
33811
|
-
sellAmount: sellAmount2
|
|
33812
|
-
};
|
|
33813
|
-
const finalQuote2 = await this.fetchQuoteWithRetry(params2);
|
|
33814
|
-
if (!finalQuote2.data.length) {
|
|
33815
|
-
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
33816
|
-
return null;
|
|
33817
|
-
}
|
|
33818
|
-
const dataObject2 = finalQuote2.data[0];
|
|
33819
|
-
return dataObject2;
|
|
33820
|
-
}
|
|
33821
|
-
const btcPrice = await this.getPriceOfToken(toToken.address.toString());
|
|
33822
|
-
if (!btcPrice) {
|
|
33823
|
-
logger.error(`error getting btc price: ${btcPrice}`);
|
|
33824
|
-
return null;
|
|
33825
|
-
}
|
|
33826
|
-
const estimatedUsdcAmount = Math.floor(amount * btcPrice);
|
|
33827
|
-
const targetBtcBig = BigInt(returnFormattedAmount(amount, toTokenDecimals));
|
|
33828
|
-
let low = BigInt(
|
|
33829
|
-
Math.floor(
|
|
33830
|
-
estimatedUsdcAmount * 10 ** fromToken.decimals * 0.9
|
|
33831
|
-
)
|
|
33832
|
-
);
|
|
33833
|
-
let high = BigInt(
|
|
33834
|
-
Math.floor(
|
|
33835
|
-
estimatedUsdcAmount * 10 ** fromToken.decimals * 1.1
|
|
33836
|
-
)
|
|
33837
|
-
);
|
|
33838
|
-
let mid = 0n;
|
|
33839
|
-
for (let i = 0; i < maxIterations; i++) {
|
|
33840
|
-
mid = (low + high) / 2n;
|
|
33841
|
-
const sellAmount2 = returnFormattedAmount(Number(mid), 0);
|
|
33842
|
-
const quote = await this.fetchQuoteWithRetry({
|
|
33843
|
-
sellTokenAddress: from_token_address,
|
|
33844
|
-
buyTokenAddress: to_token_address,
|
|
33845
|
-
takerAddress,
|
|
33846
|
-
sellAmount: sellAmount2
|
|
33847
|
-
});
|
|
33848
|
-
const gotBtc = BigInt(quote.data[0].buyAmount);
|
|
33849
|
-
if (gotBtc === targetBtcBig) return quote.data[0];
|
|
33850
|
-
if (gotBtc > targetBtcBig) {
|
|
33851
|
-
high = mid;
|
|
33852
|
-
} else {
|
|
33853
|
-
low = mid;
|
|
33854
|
-
}
|
|
33855
|
-
if (gotBtc >= targetBtcBig && gotBtc <= targetBtcBig + BigInt(tolerance)) {
|
|
33856
|
-
return quote.data[0];
|
|
33857
|
-
}
|
|
33858
|
-
}
|
|
33859
|
-
let sellAmount = returnFormattedAmount(
|
|
33860
|
-
Number(mid),
|
|
33861
|
-
0
|
|
33862
|
-
);
|
|
33863
|
-
const params = {
|
|
33864
|
-
sellTokenAddress: from_token_address,
|
|
33865
|
-
buyTokenAddress: to_token_address,
|
|
33866
|
-
takerAddress,
|
|
33867
|
-
sellAmount
|
|
33868
|
-
};
|
|
33869
|
-
const finalQuote = await this.fetchQuoteWithRetry(params);
|
|
33870
|
-
if (!finalQuote.data.length) {
|
|
33871
|
-
logger.error("No quotes available for this swap, error in quotes avnu");
|
|
33872
|
-
return null;
|
|
33873
|
-
}
|
|
33874
|
-
const dataObject = finalQuote.data[0];
|
|
33875
|
-
return dataObject;
|
|
33876
|
-
} catch (err) {
|
|
33877
|
-
logger.error(`No quotes available for this swap: ${err}`);
|
|
33878
|
-
return null;
|
|
33879
|
-
}
|
|
33880
|
-
}
|
|
33881
|
-
async getPriceOfToken(tokenAddress, retries = MAX_RETRIES) {
|
|
33882
|
-
try {
|
|
33883
|
-
const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
|
|
33884
|
-
const response = await import_axios9.default.get(url);
|
|
33885
|
-
const length = response.data.length;
|
|
33886
|
-
return response.data[length - 1].value;
|
|
33887
|
-
} catch (err) {
|
|
33888
|
-
if (retries > 0) {
|
|
33889
|
-
await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
|
|
33890
|
-
return this.getPriceOfToken(tokenAddress, retries - 1);
|
|
33891
|
-
} else {
|
|
33892
|
-
logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
|
|
33893
|
-
return null;
|
|
33894
|
-
}
|
|
33895
|
-
}
|
|
33896
|
-
}
|
|
33897
|
-
};
|
|
34441
|
+
// src/strategies/vesu-extended-strategy/types/transaction-metadata.ts
|
|
34442
|
+
var CycleType = /* @__PURE__ */ ((CycleType2) => {
|
|
34443
|
+
CycleType2["INVESTMENT"] = "INVESTMENT";
|
|
34444
|
+
CycleType2["REBALANCE_PRICE_DROP"] = "REBALANCE_PRICE_DROP";
|
|
34445
|
+
CycleType2["REBALANCE_PRICE_RISE"] = "REBALANCE_PRICE_RISE";
|
|
34446
|
+
CycleType2["WITHDRAWAL"] = "WITHDRAWAL";
|
|
34447
|
+
CycleType2["DELTA_NEUTRAL_ADJUSTMENT"] = "DELTA_NEUTRAL_ADJUSTMENT";
|
|
34448
|
+
return CycleType2;
|
|
34449
|
+
})(CycleType || {});
|
|
33898
34450
|
|
|
33899
34451
|
// src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx
|
|
33900
34452
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
@@ -33994,15 +34546,30 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33994
34546
|
const usdceToken = Global.getDefaultTokens().find(
|
|
33995
34547
|
(token) => token.symbol === "USDCe"
|
|
33996
34548
|
);
|
|
34549
|
+
const walletBalance = await new ERC20(this.config).balanceOf(
|
|
34550
|
+
usdceToken.address,
|
|
34551
|
+
WALLET_ADDRESS,
|
|
34552
|
+
usdceToken.decimals
|
|
34553
|
+
);
|
|
34554
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator walletBalance: ${walletBalance}`);
|
|
34555
|
+
const amountToBeTransferred = amount.minimum(walletBalance);
|
|
34556
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator amountToBeTransferred: ${amountToBeTransferred.toNumber()}`);
|
|
34557
|
+
if (amountToBeTransferred.lessThan(0)) {
|
|
34558
|
+
logger.error(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator amountToBeTransferred is less than 0: ${amountToBeTransferred.toNumber()}`);
|
|
34559
|
+
return {
|
|
34560
|
+
calls: [],
|
|
34561
|
+
status: false
|
|
34562
|
+
};
|
|
34563
|
+
}
|
|
33997
34564
|
const approveCall = new ERC20(this.config).approve(
|
|
33998
34565
|
usdceToken.address,
|
|
33999
34566
|
this.metadata.additionalInfo.vaultAllocator,
|
|
34000
|
-
|
|
34567
|
+
amountToBeTransferred
|
|
34001
34568
|
);
|
|
34002
34569
|
const transferCall = new ERC20(this.config).transfer(
|
|
34003
34570
|
usdceToken.address,
|
|
34004
34571
|
this.metadata.additionalInfo.vaultAllocator,
|
|
34005
|
-
|
|
34572
|
+
amountToBeTransferred
|
|
34006
34573
|
);
|
|
34007
34574
|
const proofsInfo = extendedAdapter.getProofsForFromLegacySwap(
|
|
34008
34575
|
this.getMerkleTree()
|
|
@@ -34010,21 +34577,29 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34010
34577
|
const proofGroups = proofsInfo.proofs;
|
|
34011
34578
|
const call = this.getManageCall(
|
|
34012
34579
|
proofGroups,
|
|
34013
|
-
await proofsInfo.callConstructor({ amount })
|
|
34580
|
+
await proofsInfo.callConstructor({ amount: amountToBeTransferred })
|
|
34014
34581
|
);
|
|
34015
|
-
return
|
|
34582
|
+
return {
|
|
34583
|
+
calls: [approveCall, transferCall, call],
|
|
34584
|
+
status: true
|
|
34585
|
+
};
|
|
34016
34586
|
} catch (err) {
|
|
34017
34587
|
logger.error(`error moving assets to vault allocator: ${err}`);
|
|
34018
|
-
return
|
|
34588
|
+
return {
|
|
34589
|
+
calls: [],
|
|
34590
|
+
status: false
|
|
34591
|
+
};
|
|
34019
34592
|
}
|
|
34020
34593
|
}
|
|
34021
34594
|
async shouldInvest() {
|
|
34022
34595
|
try {
|
|
34596
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
|
|
34023
34597
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34024
34598
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
34025
|
-
|
|
34599
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
|
|
34600
|
+
if (!vesuAdapter) {
|
|
34026
34601
|
logger.error(
|
|
34027
|
-
`
|
|
34602
|
+
`Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
34028
34603
|
);
|
|
34029
34604
|
return {
|
|
34030
34605
|
shouldInvest: false,
|
|
@@ -34036,10 +34611,87 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34036
34611
|
vesuLeverage: 0
|
|
34037
34612
|
};
|
|
34038
34613
|
}
|
|
34614
|
+
if (!extendedAdapter) {
|
|
34615
|
+
logger.error(
|
|
34616
|
+
`Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
34617
|
+
);
|
|
34618
|
+
return {
|
|
34619
|
+
shouldInvest: false,
|
|
34620
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34621
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34622
|
+
extendedLeverage: 0,
|
|
34623
|
+
collateralPrice: 0,
|
|
34624
|
+
debtPrice: 0,
|
|
34625
|
+
vesuLeverage: 0
|
|
34626
|
+
};
|
|
34627
|
+
}
|
|
34628
|
+
if (!extendedAdapter.client) {
|
|
34629
|
+
logger.error(
|
|
34630
|
+
`Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
|
|
34631
|
+
);
|
|
34632
|
+
return {
|
|
34633
|
+
shouldInvest: false,
|
|
34634
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34635
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34636
|
+
extendedLeverage: 0,
|
|
34637
|
+
collateralPrice: 0,
|
|
34638
|
+
debtPrice: 0,
|
|
34639
|
+
vesuLeverage: 0
|
|
34640
|
+
};
|
|
34641
|
+
}
|
|
34642
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
|
|
34039
34643
|
const balance = await this.getUnusedBalance();
|
|
34644
|
+
if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
|
|
34645
|
+
logger.error(
|
|
34646
|
+
`Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
|
|
34647
|
+
);
|
|
34648
|
+
return {
|
|
34649
|
+
shouldInvest: false,
|
|
34650
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34651
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34652
|
+
extendedLeverage: 0,
|
|
34653
|
+
collateralPrice: 0,
|
|
34654
|
+
debtPrice: 0,
|
|
34655
|
+
vesuLeverage: 0
|
|
34656
|
+
};
|
|
34657
|
+
}
|
|
34658
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
|
|
34040
34659
|
const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
|
|
34041
|
-
|
|
34042
|
-
|
|
34660
|
+
if (usdcBalanceOnExtended) {
|
|
34661
|
+
const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
|
|
34662
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
34663
|
+
logger.error(
|
|
34664
|
+
`Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
34665
|
+
);
|
|
34666
|
+
return {
|
|
34667
|
+
shouldInvest: false,
|
|
34668
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34669
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34670
|
+
extendedLeverage: 0,
|
|
34671
|
+
collateralPrice: 0,
|
|
34672
|
+
debtPrice: 0,
|
|
34673
|
+
vesuLeverage: 0
|
|
34674
|
+
};
|
|
34675
|
+
}
|
|
34676
|
+
}
|
|
34677
|
+
const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
|
|
34678
|
+
const amountToInvestNumber = amountToInvest.toNumber();
|
|
34679
|
+
if (!Number.isFinite(amountToInvestNumber)) {
|
|
34680
|
+
logger.error(
|
|
34681
|
+
`Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
|
|
34682
|
+
);
|
|
34683
|
+
return {
|
|
34684
|
+
shouldInvest: false,
|
|
34685
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34686
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34687
|
+
extendedLeverage: 0,
|
|
34688
|
+
collateralPrice: 0,
|
|
34689
|
+
debtPrice: 0,
|
|
34690
|
+
vesuLeverage: 0
|
|
34691
|
+
};
|
|
34692
|
+
}
|
|
34693
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
|
|
34694
|
+
if (amountToInvest.lessThan(LIMIT_BALANCE_VALUE)) {
|
|
34043
34695
|
return {
|
|
34044
34696
|
shouldInvest: false,
|
|
34045
34697
|
vesuAmount: new Web3Number(0, 0),
|
|
@@ -34068,6 +34720,34 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34068
34720
|
collateralPrice,
|
|
34069
34721
|
debtPrice
|
|
34070
34722
|
} = await this.getAssetPrices();
|
|
34723
|
+
if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
|
|
34724
|
+
logger.error(
|
|
34725
|
+
`Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
|
|
34726
|
+
);
|
|
34727
|
+
return {
|
|
34728
|
+
shouldInvest: false,
|
|
34729
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34730
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34731
|
+
extendedLeverage: 0,
|
|
34732
|
+
collateralPrice: 0,
|
|
34733
|
+
debtPrice: 0,
|
|
34734
|
+
vesuLeverage: 0
|
|
34735
|
+
};
|
|
34736
|
+
}
|
|
34737
|
+
if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
|
|
34738
|
+
logger.error(
|
|
34739
|
+
`Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
|
|
34740
|
+
);
|
|
34741
|
+
return {
|
|
34742
|
+
shouldInvest: false,
|
|
34743
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34744
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34745
|
+
extendedLeverage: 0,
|
|
34746
|
+
collateralPrice: 0,
|
|
34747
|
+
debtPrice: 0,
|
|
34748
|
+
vesuLeverage: 0
|
|
34749
|
+
};
|
|
34750
|
+
}
|
|
34071
34751
|
const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
|
|
34072
34752
|
amountToInvest.toNumber(),
|
|
34073
34753
|
extendedAdapter.client,
|
|
@@ -34091,6 +34771,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34091
34771
|
vesuLeverage: 0
|
|
34092
34772
|
};
|
|
34093
34773
|
}
|
|
34774
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`);
|
|
34094
34775
|
return {
|
|
34095
34776
|
shouldInvest: true,
|
|
34096
34777
|
vesuAmount: vesu_amount,
|
|
@@ -34117,111 +34798,251 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34117
34798
|
try {
|
|
34118
34799
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34119
34800
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
34120
|
-
let calls = [];
|
|
34121
34801
|
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
|
|
34122
34802
|
logger.error(
|
|
34123
34803
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
34124
34804
|
);
|
|
34125
|
-
return
|
|
34805
|
+
return [];
|
|
34126
34806
|
}
|
|
34127
|
-
|
|
34807
|
+
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34808
|
+
if (!extendedHoldings) {
|
|
34809
|
+
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
34810
|
+
return [];
|
|
34811
|
+
}
|
|
34812
|
+
const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
|
|
34813
|
+
const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
|
|
34814
|
+
extendedHoldings.availableForWithdrawal
|
|
34815
|
+
);
|
|
34816
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
|
|
34817
|
+
let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
34818
|
+
let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
34819
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34820
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
|
|
34821
|
+
}
|
|
34822
|
+
const extendedTargetAmount = extendedAmount.abs();
|
|
34823
|
+
let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
|
|
34824
|
+
if (extendedAmount.isNegative()) {
|
|
34825
|
+
projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
|
|
34826
|
+
}
|
|
34827
|
+
const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
|
|
34828
|
+
const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
|
|
34829
|
+
if (extendedAmountDifference.lessThan(0)) {
|
|
34830
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
|
|
34831
|
+
} else if (extendedAmountDifference.greaterThan(0)) {
|
|
34832
|
+
totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
|
|
34833
|
+
}
|
|
34834
|
+
const vesuTargetAmount = vesuAmount.abs();
|
|
34835
|
+
const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
|
|
34836
|
+
let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
|
|
34837
|
+
const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
|
|
34838
|
+
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()}`);
|
|
34839
|
+
let calls = [];
|
|
34840
|
+
let transactionResults = [];
|
|
34841
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34128
34842
|
try {
|
|
34129
|
-
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
34843
|
+
const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
|
|
34130
34844
|
{
|
|
34131
34845
|
to: Protocols.VAULT.name,
|
|
34132
34846
|
from: Protocols.EXTENDED.name,
|
|
34133
|
-
amount: extendedAmount.abs()
|
|
34847
|
+
amount: extendedAmount.abs(),
|
|
34848
|
+
cycleType: "INVESTMENT" /* INVESTMENT */
|
|
34134
34849
|
},
|
|
34135
34850
|
extendedAdapter,
|
|
34136
34851
|
vesuAdapter
|
|
34137
34852
|
);
|
|
34138
34853
|
if (extendedStatus) {
|
|
34139
|
-
|
|
34854
|
+
transactionResults.push({
|
|
34855
|
+
status: extendedStatus,
|
|
34856
|
+
calls: extendedCalls,
|
|
34857
|
+
transactionMetadata: {
|
|
34858
|
+
...extendedTransactionMetadata,
|
|
34859
|
+
transactionType: "DEPOSIT"
|
|
34860
|
+
}
|
|
34861
|
+
});
|
|
34140
34862
|
} else {
|
|
34141
|
-
return [];
|
|
34863
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34142
34864
|
}
|
|
34143
34865
|
} catch (err) {
|
|
34144
34866
|
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34867
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34145
34868
|
}
|
|
34146
34869
|
}
|
|
34147
|
-
if (vesuAmount.
|
|
34870
|
+
if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34148
34871
|
try {
|
|
34149
|
-
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
34872
|
+
const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
|
|
34150
34873
|
{
|
|
34151
34874
|
to: Protocols.EXTENDED.name,
|
|
34152
34875
|
from: Protocols.VESU.name,
|
|
34153
|
-
amount: vesuAmount.abs()
|
|
34876
|
+
amount: vesuAmount.abs(),
|
|
34877
|
+
cycleType: "INVESTMENT" /* INVESTMENT */
|
|
34154
34878
|
},
|
|
34155
34879
|
extendedAdapter,
|
|
34156
34880
|
vesuAdapter
|
|
34157
34881
|
);
|
|
34158
|
-
calls.push(...vesuCalls);
|
|
34159
34882
|
if (!vesuStatus) {
|
|
34160
|
-
return [];
|
|
34161
|
-
}
|
|
34883
|
+
return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34884
|
+
}
|
|
34885
|
+
transactionResults.push({
|
|
34886
|
+
status: vesuStatus,
|
|
34887
|
+
calls: vesuCalls,
|
|
34888
|
+
transactionMetadata: {
|
|
34889
|
+
...vesuTransactionMetadata,
|
|
34890
|
+
transactionType: "DEPOSIT"
|
|
34891
|
+
}
|
|
34892
|
+
});
|
|
34162
34893
|
} catch (err) {
|
|
34163
|
-
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34894
|
+
logger.error(`Failed moving assets to extended via vault allocator: ${err}`);
|
|
34895
|
+
return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34164
34896
|
}
|
|
34165
34897
|
}
|
|
34166
|
-
|
|
34167
|
-
|
|
34168
|
-
|
|
34169
|
-
|
|
34170
|
-
|
|
34171
|
-
|
|
34172
|
-
|
|
34173
|
-
|
|
34174
|
-
|
|
34175
|
-
|
|
34176
|
-
|
|
34177
|
-
|
|
34178
|
-
|
|
34179
|
-
|
|
34180
|
-
|
|
34181
|
-
|
|
34182
|
-
|
|
34183
|
-
|
|
34184
|
-
|
|
34185
|
-
|
|
34186
|
-
|
|
34187
|
-
|
|
34188
|
-
|
|
34898
|
+
if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34899
|
+
if (extendedAmountDifference.greaterThan(0)) {
|
|
34900
|
+
try {
|
|
34901
|
+
const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
|
|
34902
|
+
{
|
|
34903
|
+
to: Protocols.EXTENDED.name,
|
|
34904
|
+
from: Protocols.VAULT.name,
|
|
34905
|
+
amount: extendedAmountDifference,
|
|
34906
|
+
cycleType: "INVESTMENT" /* INVESTMENT */
|
|
34907
|
+
},
|
|
34908
|
+
extendedAdapter,
|
|
34909
|
+
vesuAdapter
|
|
34910
|
+
);
|
|
34911
|
+
if (extendedStatus) {
|
|
34912
|
+
transactionResults.push({
|
|
34913
|
+
status: extendedStatus,
|
|
34914
|
+
calls: extendedCalls,
|
|
34915
|
+
transactionMetadata: extendedTransactionMetadata
|
|
34916
|
+
});
|
|
34917
|
+
} else {
|
|
34918
|
+
logger.error(`Failed to move assets to extended - operation returned false status`);
|
|
34919
|
+
return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34920
|
+
}
|
|
34921
|
+
} catch (err) {
|
|
34922
|
+
logger.error(`Failed moving assets to extended: ${err}`);
|
|
34923
|
+
return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34924
|
+
}
|
|
34925
|
+
} else if (extendedAmountDifference.lessThan(0)) {
|
|
34926
|
+
try {
|
|
34927
|
+
const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
|
|
34928
|
+
{
|
|
34929
|
+
to: Protocols.VAULT.name,
|
|
34930
|
+
from: Protocols.EXTENDED.name,
|
|
34931
|
+
amount: extendedAmountDifferenceAbs,
|
|
34932
|
+
cycleType: "INVESTMENT" /* INVESTMENT */
|
|
34933
|
+
},
|
|
34934
|
+
extendedAdapter,
|
|
34935
|
+
vesuAdapter
|
|
34936
|
+
);
|
|
34937
|
+
if (extendedStatus) {
|
|
34938
|
+
transactionResults.push({
|
|
34939
|
+
status: extendedStatus,
|
|
34940
|
+
calls: extendedCalls,
|
|
34941
|
+
transactionMetadata: {
|
|
34942
|
+
...extendedTransactionMetadata,
|
|
34943
|
+
transactionType: "DEPOSIT"
|
|
34944
|
+
}
|
|
34945
|
+
});
|
|
34946
|
+
} else {
|
|
34947
|
+
logger.error(`Failed to withdraw from extended - operation returned false status`);
|
|
34948
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34949
|
+
}
|
|
34950
|
+
} catch (err) {
|
|
34951
|
+
logger.error(`Failed moving assets from extended to vault: ${err}`);
|
|
34952
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34953
|
+
}
|
|
34189
34954
|
}
|
|
34190
34955
|
}
|
|
34191
|
-
if (
|
|
34192
|
-
|
|
34193
|
-
|
|
34194
|
-
{
|
|
34195
|
-
to: Protocols.VAULT.name,
|
|
34196
|
-
from: Protocols.EXTENDED.name,
|
|
34197
|
-
amount: vesuAmount.minus(usdcAmountInWallet)
|
|
34198
|
-
},
|
|
34199
|
-
extendedAdapter,
|
|
34200
|
-
vesuAdapter
|
|
34956
|
+
if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34957
|
+
if (vesuAmountDifference.lessThanOrEqualTo(0)) {
|
|
34958
|
+
logger.warn(
|
|
34959
|
+
`Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
|
|
34201
34960
|
);
|
|
34202
|
-
|
|
34203
|
-
|
|
34961
|
+
} else {
|
|
34962
|
+
try {
|
|
34963
|
+
const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
|
|
34964
|
+
{
|
|
34965
|
+
to: Protocols.VAULT.name,
|
|
34966
|
+
from: Protocols.EXTENDED.name,
|
|
34967
|
+
amount: vesuAmountDifference,
|
|
34968
|
+
cycleType: "INVESTMENT" /* INVESTMENT */
|
|
34969
|
+
},
|
|
34970
|
+
extendedAdapter,
|
|
34971
|
+
vesuAdapter
|
|
34972
|
+
);
|
|
34973
|
+
if (!vesuStatus) {
|
|
34974
|
+
logger.error(`Failed to move assets to vesu - operation returned false status`);
|
|
34975
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34976
|
+
}
|
|
34977
|
+
transactionResults.push({
|
|
34978
|
+
status: vesuStatus,
|
|
34979
|
+
calls: vesuCalls,
|
|
34980
|
+
transactionMetadata: {
|
|
34981
|
+
...vesuTransactionMetadata,
|
|
34982
|
+
transactionType: "DEPOSIT"
|
|
34983
|
+
}
|
|
34984
|
+
});
|
|
34985
|
+
} catch (err) {
|
|
34986
|
+
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34987
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34204
34988
|
}
|
|
34205
|
-
calls.push(...vesuCalls);
|
|
34206
|
-
} catch (err) {
|
|
34207
|
-
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34208
34989
|
}
|
|
34209
34990
|
}
|
|
34210
|
-
return
|
|
34991
|
+
return transactionResults;
|
|
34211
34992
|
} catch (err) {
|
|
34212
34993
|
logger.error(`Failed moving assets to vesu: ${err}`);
|
|
34213
|
-
return [];
|
|
34994
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: new Web3Number(0, USDC_TOKEN_DECIMALS) }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34995
|
+
}
|
|
34996
|
+
}
|
|
34997
|
+
/**
|
|
34998
|
+
* Helper method to create transaction result with metadata
|
|
34999
|
+
*/
|
|
35000
|
+
createTransactionResult(calls, status, params, transactionType, cycleType) {
|
|
35001
|
+
if (status) {
|
|
35002
|
+
return {
|
|
35003
|
+
calls,
|
|
35004
|
+
status,
|
|
35005
|
+
transactionMetadata: {
|
|
35006
|
+
protocolFrom: params.from,
|
|
35007
|
+
protocolTo: params.to,
|
|
35008
|
+
transactionType,
|
|
35009
|
+
usdAmount: params.amount.abs().toFixed(),
|
|
35010
|
+
status: "PENDING",
|
|
35011
|
+
cycleType
|
|
35012
|
+
}
|
|
35013
|
+
};
|
|
34214
35014
|
}
|
|
35015
|
+
return { calls: [], status: false, transactionMetadata: { protocolFrom: "", protocolTo: "", transactionType: "DEPOSIT", usdAmount: "0", status: "FAILED", cycleType } };
|
|
34215
35016
|
}
|
|
34216
35017
|
async moveAssets(params, extendedAdapter, vesuAdapter) {
|
|
34217
35018
|
try {
|
|
35019
|
+
if (params.amount.lessThanOrEqualTo(0)) {
|
|
35020
|
+
logger.error(
|
|
35021
|
+
`Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
|
|
35022
|
+
);
|
|
35023
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35024
|
+
}
|
|
35025
|
+
const amountAbs = params.amount.abs();
|
|
35026
|
+
if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
|
|
35027
|
+
if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
35028
|
+
logger.warn(
|
|
35029
|
+
`Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
|
|
35030
|
+
);
|
|
35031
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35032
|
+
}
|
|
35033
|
+
}
|
|
35034
|
+
if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
|
|
35035
|
+
if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
|
|
35036
|
+
logger.warn(
|
|
35037
|
+
`Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
|
|
35038
|
+
);
|
|
35039
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35040
|
+
}
|
|
35041
|
+
}
|
|
34218
35042
|
const avnuAdapter = await this.getAvnuAdapter();
|
|
34219
35043
|
if (!avnuAdapter) {
|
|
34220
35044
|
logger.error(`avnu adapter not found: ${avnuAdapter}`);
|
|
34221
|
-
return
|
|
34222
|
-
calls: [],
|
|
34223
|
-
status: false
|
|
34224
|
-
};
|
|
35045
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
34225
35046
|
}
|
|
34226
35047
|
logger.info(`moveAssets params, ${JSON.stringify(params)}`);
|
|
34227
35048
|
const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
|
|
@@ -34240,61 +35061,72 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34240
35061
|
await proofsInfo.callConstructor({ amount: params.amount })
|
|
34241
35062
|
);
|
|
34242
35063
|
calls.push(call);
|
|
34243
|
-
return
|
|
34244
|
-
calls: [call],
|
|
34245
|
-
status: true
|
|
34246
|
-
};
|
|
35064
|
+
return this.createTransactionResult(calls, true, params, "DEPOSIT", params.cycleType);
|
|
34247
35065
|
} else if (params.to === Protocols.VAULT.name && params.from === Protocols.EXTENDED.name) {
|
|
34248
35066
|
const extendedLeverage = calculateExtendedLevergae();
|
|
34249
35067
|
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34250
35068
|
if (!extendedHoldings) {
|
|
34251
35069
|
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
34252
|
-
return
|
|
34253
|
-
calls: [],
|
|
34254
|
-
status: false
|
|
34255
|
-
};
|
|
35070
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
34256
35071
|
}
|
|
34257
35072
|
const extendedHoldingAmount = new Web3Number(
|
|
34258
35073
|
extendedHoldings.availableForWithdrawal,
|
|
34259
35074
|
USDC_TOKEN_DECIMALS
|
|
34260
35075
|
);
|
|
34261
|
-
|
|
34262
|
-
|
|
34263
|
-
|
|
34264
|
-
|
|
34265
|
-
btcAmount.
|
|
34266
|
-
|
|
34267
|
-
|
|
34268
|
-
|
|
34269
|
-
|
|
34270
|
-
|
|
34271
|
-
|
|
34272
|
-
|
|
34273
|
-
|
|
35076
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets extendedHoldingAmount: ${extendedHoldingAmount.toNumber()}`);
|
|
35077
|
+
if (params.amount.abs().greaterThan(extendedHoldingAmount)) {
|
|
35078
|
+
const leftAmountAfterWithdrawalAmountInAccount = params.amount.abs().minus(extendedHoldingAmount);
|
|
35079
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets leftAmountAfterWithdrawalAmountInAccount: ${leftAmountAfterWithdrawalAmountInAccount.toNumber()}`);
|
|
35080
|
+
const btcAmount = leftAmountAfterWithdrawalAmountInAccount.dividedBy(collateralPrice.price);
|
|
35081
|
+
const openLongPosition = btcAmount.multipliedBy(3).greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
|
|
35082
|
+
extendedLeverage.toString(),
|
|
35083
|
+
btcAmount.toNumber(),
|
|
35084
|
+
"BUY" /* BUY */
|
|
35085
|
+
) : await extendedAdapter.createOrder(
|
|
35086
|
+
extendedLeverage.toString(),
|
|
35087
|
+
34e-6,
|
|
35088
|
+
// just in case amount falls short then we need to create a withdrawal
|
|
35089
|
+
"BUY" /* BUY */
|
|
35090
|
+
);
|
|
35091
|
+
if (!openLongPosition) {
|
|
35092
|
+
logger.error(`error opening long position: ${openLongPosition}`);
|
|
35093
|
+
}
|
|
35094
|
+
const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
35095
|
+
if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
|
|
35096
|
+
logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
|
|
35097
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35098
|
+
}
|
|
34274
35099
|
}
|
|
34275
|
-
|
|
34276
|
-
|
|
34277
|
-
|
|
35100
|
+
const {
|
|
35101
|
+
status: withdrawalFromExtendedStatus,
|
|
35102
|
+
receivedTxnHash: withdrawalFromExtendedTxnHash
|
|
35103
|
+
} = await extendedAdapter.withdrawFromExtended(params.amount);
|
|
35104
|
+
logger.info(`withdrawalFromExtendedStatus: ${withdrawalFromExtendedStatus}, withdrawalFromExtendedTxnHash: ${withdrawalFromExtendedTxnHash}`);
|
|
35105
|
+
if (withdrawalFromExtendedStatus && withdrawalFromExtendedTxnHash) {
|
|
34278
35106
|
const extendedHoldings2 = await extendedAdapter.getExtendedDepositAmount();
|
|
34279
|
-
logger.info(`extendedHoldings after withdrawal ${extendedHoldings2}`);
|
|
34280
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
34281
|
-
const calls = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
|
|
34282
|
-
if (calls.length > 0) {
|
|
34283
|
-
return
|
|
34284
|
-
|
|
34285
|
-
|
|
34286
|
-
};
|
|
35107
|
+
logger.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
|
|
35108
|
+
await new Promise((resolve) => setTimeout(resolve, 5e3));
|
|
35109
|
+
const { calls, status } = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
|
|
35110
|
+
if (calls.length > 0 && status) {
|
|
35111
|
+
return this.createTransactionResult(calls, true, params, "WITHDRAWAL", params.cycleType);
|
|
35112
|
+
} else {
|
|
35113
|
+
return this.createTransactionResult([], true, params, "WITHDRAWAL", params.cycleType);
|
|
34287
35114
|
}
|
|
35115
|
+
} else if (withdrawalFromExtendedStatus && !withdrawalFromExtendedTxnHash) {
|
|
35116
|
+
logger.error("withdrawal from extended successful, but funds didn't get transferred to the wallet");
|
|
35117
|
+
return this.createTransactionResult([], true, params, "WITHDRAWAL", params.cycleType);
|
|
34288
35118
|
} else {
|
|
34289
35119
|
logger.error("withdrawal from extended failed");
|
|
34290
|
-
return
|
|
34291
|
-
calls: [],
|
|
34292
|
-
status: false
|
|
34293
|
-
};
|
|
35120
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
34294
35121
|
}
|
|
34295
35122
|
} else if (params.to === Protocols.VAULT.name && params.from === Protocols.VESU.name) {
|
|
35123
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
|
|
35124
|
+
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
35125
|
+
logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
35126
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35127
|
+
}
|
|
34296
35128
|
const vesuAmountInBTC = new Web3Number(
|
|
34297
|
-
params.amount.dividedBy(collateralPrice.price).
|
|
35129
|
+
params.amount.dividedBy(collateralPrice.price).toFixed(WBTC_TOKEN_DECIMALS),
|
|
34298
35130
|
collateralToken.decimals
|
|
34299
35131
|
);
|
|
34300
35132
|
const proofsInfo = vesuAdapter.getProofs(false, this.getMerkleTree());
|
|
@@ -34312,11 +35144,13 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34312
35144
|
await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
|
|
34313
35145
|
);
|
|
34314
35146
|
calls.push(swapCall);
|
|
34315
|
-
return
|
|
34316
|
-
calls,
|
|
34317
|
-
status: true
|
|
34318
|
-
};
|
|
35147
|
+
return this.createTransactionResult(calls, true, params, "WITHDRAWAL", params.cycleType);
|
|
34319
35148
|
} else if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VESU.name) {
|
|
35149
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
|
|
35150
|
+
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
35151
|
+
logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
35152
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35153
|
+
}
|
|
34320
35154
|
const vesuAmountInBTC = new Web3Number(
|
|
34321
35155
|
params.amount.dividedBy(collateralPrice.price).toNumber(),
|
|
34322
35156
|
collateralToken.decimals
|
|
@@ -34346,131 +35180,32 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34346
35180
|
await proofsInfoDeposit.callConstructor({ amount: params.amount })
|
|
34347
35181
|
);
|
|
34348
35182
|
calls.push(callDeposit);
|
|
34349
|
-
return
|
|
34350
|
-
calls,
|
|
34351
|
-
status: true
|
|
34352
|
-
};
|
|
35183
|
+
return this.createTransactionResult(calls, true, params, "DEPOSIT", params.cycleType);
|
|
34353
35184
|
}
|
|
34354
|
-
|
|
34355
|
-
|
|
34356
|
-
status: false
|
|
34357
|
-
};
|
|
35185
|
+
logger.error(`Unsupported assets movement: ${params.from} to ${params.to}`);
|
|
35186
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
34358
35187
|
} catch (err) {
|
|
34359
35188
|
logger.error(`error moving assets: ${err}`);
|
|
34360
|
-
return
|
|
34361
|
-
calls: [],
|
|
34362
|
-
status: false
|
|
34363
|
-
};
|
|
35189
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
34364
35190
|
}
|
|
34365
35191
|
}
|
|
34366
35192
|
async handleDeposit() {
|
|
34367
35193
|
try {
|
|
34368
|
-
|
|
34369
|
-
const extendedAdapter = await this.getExtendedAdapter();
|
|
34370
|
-
const avnuAdapter = await this.getAvnuAdapter();
|
|
34371
|
-
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client || !avnuAdapter) {
|
|
34372
|
-
logger.error(
|
|
34373
|
-
"vesu or extended adapter not found",
|
|
34374
|
-
vesuAdapter,
|
|
34375
|
-
extendedAdapter
|
|
34376
|
-
);
|
|
34377
|
-
return {
|
|
34378
|
-
extendedAmountInBTC: new Web3Number(0, 0),
|
|
34379
|
-
calls: []
|
|
34380
|
-
};
|
|
34381
|
-
}
|
|
34382
|
-
const extendedLeverage = calculateExtendedLevergae();
|
|
34383
|
-
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter);
|
|
34384
|
-
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
34385
|
-
logger.error("price difference between avnu and extended doesn't fit the range");
|
|
34386
|
-
return {
|
|
34387
|
-
extendedAmountInBTC: new Web3Number(0, 0),
|
|
34388
|
-
calls: []
|
|
34389
|
-
};
|
|
34390
|
-
}
|
|
34391
|
-
const position = await extendedAdapter.getAllOpenPositions();
|
|
34392
|
-
if (!position) {
|
|
34393
|
-
logger.error("error getting extended position", position);
|
|
34394
|
-
return {
|
|
34395
|
-
extendedAmountInBTC: new Web3Number(0, 0),
|
|
34396
|
-
calls: []
|
|
34397
|
-
};
|
|
34398
|
-
}
|
|
34399
|
-
const extendedPositionValue = position.length > 0 ? parseFloat(position[0].value) : 0;
|
|
34400
|
-
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34401
|
-
if (!extendedHoldings) {
|
|
34402
|
-
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
34403
|
-
return {
|
|
34404
|
-
extendedAmountInBTC: new Web3Number(0, 0),
|
|
34405
|
-
calls: []
|
|
34406
|
-
};
|
|
34407
|
-
}
|
|
34408
|
-
const extendedHoldingAmount = new Web3Number(
|
|
34409
|
-
extendedHoldings.availableForWithdrawal,
|
|
34410
|
-
USDC_TOKEN_DECIMALS
|
|
34411
|
-
);
|
|
34412
|
-
const {
|
|
34413
|
-
collateralTokenAmount
|
|
34414
|
-
} = await vesuAdapter.vesuAdapter.getAssetPrices();
|
|
34415
|
-
const { collateralPrice } = await this.getAssetPrices();
|
|
34416
|
-
const { vesuAmountInBTC, extendedAmountInBTC } = calculateVesUPositionSizeGivenExtended(
|
|
34417
|
-
extendedPositionValue,
|
|
34418
|
-
extendedHoldingAmount,
|
|
34419
|
-
collateralTokenAmount,
|
|
34420
|
-
collateralPrice.price
|
|
34421
|
-
);
|
|
34422
|
-
logger.info(`vesuAmountInBTC ${vesuAmountInBTC}, extendedAmountInBTC ${extendedAmountInBTC}`);
|
|
34423
|
-
let calls = [];
|
|
34424
|
-
if (vesuAmountInBTC.greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)) {
|
|
34425
|
-
const proofsInfo = vesuAdapter.getProofs(true, this.getMerkleTree());
|
|
34426
|
-
const proofGroups = proofsInfo.proofs;
|
|
34427
|
-
const call = this.getManageCall(
|
|
34428
|
-
proofGroups,
|
|
34429
|
-
await proofsInfo.callConstructor({
|
|
34430
|
-
amount: vesuAmountInBTC
|
|
34431
|
-
})
|
|
34432
|
-
);
|
|
34433
|
-
const { amount: wbtcAmountInVaultAllocator } = await this.getUnusedBalanceWBTC();
|
|
34434
|
-
if (wbtcAmountInVaultAllocator.lessThan(vesuAmountInBTC)) {
|
|
34435
|
-
logger.info(`WBTC amount in vault allocator is less than vesu amount required in WBTC thus swapping, wbtcAmountInVaultAllocator: ${wbtcAmountInVaultAllocator}, vesuAmountInBTC: ${vesuAmountInBTC}`);
|
|
34436
|
-
const swapProofsInfo = avnuAdapter.getProofs(true, this.getMerkleTree());
|
|
34437
|
-
const swapProofGroups = swapProofsInfo.proofs;
|
|
34438
|
-
const swapCall = this.getManageCall(
|
|
34439
|
-
swapProofGroups,
|
|
34440
|
-
await swapProofsInfo.callConstructor({
|
|
34441
|
-
amount: vesuAmountInBTC
|
|
34442
|
-
})
|
|
34443
|
-
);
|
|
34444
|
-
calls.push(swapCall);
|
|
34445
|
-
}
|
|
34446
|
-
calls.push(call);
|
|
34447
|
-
}
|
|
34448
|
-
const shortPosition = extendedAmountInBTC.multipliedBy(3).abs().greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
|
|
34449
|
-
extendedLeverage.toString(),
|
|
34450
|
-
extendedAmountInBTC.toNumber(),
|
|
34451
|
-
"SELL" /* SELL */
|
|
34452
|
-
) : null;
|
|
34453
|
-
if (!shortPosition && extendedAmountInBTC.multipliedBy(3).abs().greaterThan(MINIMUM_EXTENDED_POSITION_SIZE)) {
|
|
34454
|
-
logger.error(`error creating short position thus no position to be opened on vesu: ${shortPosition}`);
|
|
34455
|
-
return {
|
|
34456
|
-
extendedAmountInBTC: new Web3Number(0, 0),
|
|
34457
|
-
calls: []
|
|
34458
|
-
};
|
|
34459
|
-
}
|
|
34460
|
-
return {
|
|
34461
|
-
extendedAmountInBTC,
|
|
34462
|
-
calls
|
|
34463
|
-
};
|
|
35194
|
+
return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE", "INVESTMENT" /* INVESTMENT */);
|
|
34464
35195
|
} catch (err) {
|
|
34465
35196
|
logger.error(`error handling deposit: ${err}`);
|
|
34466
|
-
return {
|
|
34467
|
-
extendedAmountInBTC: new Web3Number(0, 0),
|
|
34468
|
-
calls: []
|
|
34469
|
-
};
|
|
34470
|
-
;
|
|
35197
|
+
return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE", "INVESTMENT" /* INVESTMENT */);
|
|
34471
35198
|
}
|
|
34472
35199
|
}
|
|
34473
|
-
|
|
35200
|
+
/**
|
|
35201
|
+
* Check if the price difference between avnu and extended is within the acceptable range to enhance the position size or close the position
|
|
35202
|
+
* @param extendedAdapter - the extended adapter
|
|
35203
|
+
* @param vesuAdapter - the vesu adapter
|
|
35204
|
+
* @param avnuAdapter - the avnu adapter
|
|
35205
|
+
* @param positionType - the position type (open or close)
|
|
35206
|
+
* @returns true if the price difference is within the acceptable range, false otherwise
|
|
35207
|
+
*/
|
|
35208
|
+
async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, positionType) {
|
|
34474
35209
|
const {
|
|
34475
35210
|
ask,
|
|
34476
35211
|
bid
|
|
@@ -34482,13 +35217,30 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34482
35217
|
logger.error(`error getting btc price avnu: ${btcPriceAvnu}`);
|
|
34483
35218
|
return false;
|
|
34484
35219
|
}
|
|
34485
|
-
|
|
34486
|
-
|
|
34487
|
-
|
|
35220
|
+
logger.info(`price: ${price}`);
|
|
35221
|
+
logger.info(`btcPriceAvnu: ${btcPriceAvnu}`);
|
|
35222
|
+
const priceDifference = new Web3Number(price.minus(btcPriceAvnu).toFixed(2), 0);
|
|
35223
|
+
logger.info(`priceDifference: ${priceDifference}`);
|
|
35224
|
+
if (priceDifference.isNegative()) {
|
|
35225
|
+
return false;
|
|
35226
|
+
}
|
|
35227
|
+
if (positionType === "open" /* OPEN */) {
|
|
35228
|
+
logger.info(`price difference between avnu and extended for open position: ${priceDifference.toNumber()}, minimumExtendedPriceDifferenceForSwapOpen: ${avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen}`);
|
|
35229
|
+
const result = priceDifference.greaterThanOrEqualTo(avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen);
|
|
35230
|
+
logger.info(`result: ${result}`);
|
|
35231
|
+
return result;
|
|
35232
|
+
} else {
|
|
35233
|
+
logger.info(`price difference between avnu and extended for close position: ${priceDifference.toNumber()}, maximumExtendedPriceDifferenceForSwapClosing: ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
35234
|
+
const result = priceDifference.lessThanOrEqualTo(avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing);
|
|
35235
|
+
logger.info(`result: ${result}`);
|
|
35236
|
+
return result;
|
|
34488
35237
|
}
|
|
34489
|
-
logger.error(`price difference between avnu and extended doesn't fit the range, priceDifference: ${priceDifference}`);
|
|
34490
|
-
return false;
|
|
34491
35238
|
}
|
|
35239
|
+
/**
|
|
35240
|
+
* Handle the withdrawal of assets from the vault
|
|
35241
|
+
* @param amount - the amount to withdraw in USDC
|
|
35242
|
+
* @returns the calls to be executed and the status of the calls generated along with the metadata for the calls
|
|
35243
|
+
*/
|
|
34492
35244
|
async handleWithdraw(amount) {
|
|
34493
35245
|
try {
|
|
34494
35246
|
const usdcBalanceVaultAllocator = await this.getUnusedBalance();
|
|
@@ -34500,12 +35252,8 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34500
35252
|
const withdrawCall2 = await this.getBringLiquidityCall({
|
|
34501
35253
|
amount: usdcBalanceVaultAllocator.amount
|
|
34502
35254
|
});
|
|
34503
|
-
logger.info("withdraw call", withdrawCall2);
|
|
34504
35255
|
calls.push(withdrawCall2);
|
|
34505
|
-
return {
|
|
34506
|
-
calls,
|
|
34507
|
-
status: true
|
|
34508
|
-
};
|
|
35256
|
+
return [this.createTransactionResult(calls, true, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "WITHDRAWAL", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34509
35257
|
}
|
|
34510
35258
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34511
35259
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
@@ -34514,11 +35262,9 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34514
35262
|
logger.error(
|
|
34515
35263
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
34516
35264
|
);
|
|
34517
|
-
return {
|
|
34518
|
-
calls,
|
|
34519
|
-
status
|
|
34520
|
-
};
|
|
35265
|
+
return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34521
35266
|
}
|
|
35267
|
+
let transactionResults = [];
|
|
34522
35268
|
const { collateralTokenAmount } = await vesuAdapter.vesuAdapter.getAssetPrices();
|
|
34523
35269
|
const {
|
|
34524
35270
|
collateralPrice
|
|
@@ -34527,10 +35273,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34527
35273
|
if (!extendedPositon) {
|
|
34528
35274
|
status = false;
|
|
34529
35275
|
logger.error("error getting extended position", extendedPositon);
|
|
34530
|
-
return {
|
|
34531
|
-
calls,
|
|
34532
|
-
status
|
|
34533
|
-
};
|
|
35276
|
+
return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34534
35277
|
}
|
|
34535
35278
|
const amountDistributionForWithdrawal = await calculateAmountDistributionForWithdrawal(
|
|
34536
35279
|
usdcBalanceDifference,
|
|
@@ -34543,61 +35286,70 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34543
35286
|
logger.error(
|
|
34544
35287
|
`error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
|
|
34545
35288
|
);
|
|
34546
|
-
return {
|
|
34547
|
-
calls,
|
|
34548
|
-
status
|
|
34549
|
-
};
|
|
35289
|
+
return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34550
35290
|
}
|
|
34551
35291
|
const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
|
|
34552
35292
|
if (status && vesu_amount.greaterThan(0)) {
|
|
34553
|
-
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
35293
|
+
const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
|
|
34554
35294
|
{
|
|
34555
35295
|
amount: vesu_amount,
|
|
34556
35296
|
from: Protocols.VESU.name,
|
|
34557
|
-
to: Protocols.VAULT.name
|
|
35297
|
+
to: Protocols.VAULT.name,
|
|
35298
|
+
cycleType: "WITHDRAWAL" /* WITHDRAWAL */
|
|
34558
35299
|
},
|
|
34559
35300
|
extendedAdapter,
|
|
34560
35301
|
vesuAdapter
|
|
34561
35302
|
);
|
|
34562
35303
|
status = vesuStatus;
|
|
34563
|
-
|
|
35304
|
+
transactionResults.push({
|
|
35305
|
+
status: vesuStatus,
|
|
35306
|
+
calls: vesuCalls,
|
|
35307
|
+
transactionMetadata: vesuTransactionMetadata
|
|
35308
|
+
});
|
|
34564
35309
|
}
|
|
34565
35310
|
if (status && extended_amount.greaterThan(0)) {
|
|
34566
|
-
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
35311
|
+
const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
|
|
34567
35312
|
{
|
|
34568
35313
|
amount: extended_amount,
|
|
34569
35314
|
from: Protocols.EXTENDED.name,
|
|
34570
|
-
to: Protocols.VAULT.name
|
|
35315
|
+
to: Protocols.VAULT.name,
|
|
35316
|
+
cycleType: "WITHDRAWAL" /* WITHDRAWAL */
|
|
34571
35317
|
},
|
|
34572
35318
|
extendedAdapter,
|
|
34573
35319
|
vesuAdapter
|
|
34574
35320
|
);
|
|
34575
35321
|
status = extendedStatus;
|
|
34576
35322
|
if (status) {
|
|
34577
|
-
|
|
35323
|
+
transactionResults.push({
|
|
35324
|
+
status: extendedStatus,
|
|
35325
|
+
calls: extendedCalls,
|
|
35326
|
+
transactionMetadata: extendedTransactionMetadata
|
|
35327
|
+
});
|
|
34578
35328
|
} else {
|
|
34579
35329
|
logger.error("error moving assets to vault: extendedStatus: ${extendedStatus}");
|
|
34580
|
-
return {
|
|
34581
|
-
calls: [],
|
|
34582
|
-
status
|
|
34583
|
-
};
|
|
35330
|
+
return [this.createTransactionResult([], status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34584
35331
|
}
|
|
34585
35332
|
}
|
|
34586
35333
|
const withdrawCall = await this.getBringLiquidityCall({
|
|
34587
35334
|
amount
|
|
34588
35335
|
});
|
|
34589
35336
|
logger.info("withdraw call", withdrawCall);
|
|
34590
|
-
|
|
34591
|
-
|
|
34592
|
-
calls,
|
|
34593
|
-
|
|
34594
|
-
|
|
35337
|
+
transactionResults.push({
|
|
35338
|
+
status,
|
|
35339
|
+
calls: [withdrawCall],
|
|
35340
|
+
transactionMetadata: {
|
|
35341
|
+
protocolFrom: Protocols.VAULT.name,
|
|
35342
|
+
protocolTo: Protocols.NONE.name,
|
|
35343
|
+
transactionType: "WITHDRAWAL",
|
|
35344
|
+
usdAmount: amount.toFixed(),
|
|
35345
|
+
status: "PENDING",
|
|
35346
|
+
cycleType: "WITHDRAWAL" /* WITHDRAWAL */
|
|
35347
|
+
}
|
|
35348
|
+
});
|
|
35349
|
+
return transactionResults;
|
|
34595
35350
|
} catch (err) {
|
|
34596
35351
|
logger.error(`error handling withdrawal: ${err}`);
|
|
34597
|
-
return {
|
|
34598
|
-
calls: [],
|
|
34599
|
-
status: false
|
|
34600
|
-
};
|
|
35352
|
+
return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34601
35353
|
}
|
|
34602
35354
|
}
|
|
34603
35355
|
async getAUM() {
|
|
@@ -34644,8 +35396,182 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34644
35396
|
splits: [realAUM, estimatedAUMDelta]
|
|
34645
35397
|
};
|
|
34646
35398
|
}
|
|
35399
|
+
async processTransactionDataFromSDK(txnData) {
|
|
35400
|
+
try {
|
|
35401
|
+
const txnsToBeExecuted = txnData.filter((txn) => {
|
|
35402
|
+
return txn.transactionMetadata.transactionType !== "NONE" && txn.transactionMetadata.protocolFrom !== "" && txn.transactionMetadata.protocolTo !== "";
|
|
35403
|
+
});
|
|
35404
|
+
const callsToBeExecutedFinal = txnsToBeExecuted.flatMap((txn) => txn.calls);
|
|
35405
|
+
const txnMetadata = txnsToBeExecuted.map((txn) => txn.transactionMetadata);
|
|
35406
|
+
return { callsToBeExecutedFinal, txnMetadata };
|
|
35407
|
+
} catch (err) {
|
|
35408
|
+
logger.error(`error processing transaction data from SDK: ${err}`);
|
|
35409
|
+
return null;
|
|
35410
|
+
}
|
|
35411
|
+
}
|
|
35412
|
+
async processTransactionMetadata(txnMetadata, extendedIntentFulfilled) {
|
|
35413
|
+
try {
|
|
35414
|
+
const txnMetadataNew = txnMetadata.map((txn) => {
|
|
35415
|
+
const isExtendedProtocol = txn.protocolFrom === Protocols.EXTENDED.name || txn.protocolTo === Protocols.EXTENDED.name;
|
|
35416
|
+
if (isExtendedProtocol) {
|
|
35417
|
+
txn.status = extendedIntentFulfilled ? "COMPLETED" : "PENDING";
|
|
35418
|
+
} else {
|
|
35419
|
+
txn.status = "COMPLETED";
|
|
35420
|
+
}
|
|
35421
|
+
return txn;
|
|
35422
|
+
});
|
|
35423
|
+
return txnMetadataNew;
|
|
35424
|
+
} catch (err) {
|
|
35425
|
+
logger.error(`error processing transaction data from SDK: ${err}`);
|
|
35426
|
+
return null;
|
|
35427
|
+
}
|
|
35428
|
+
}
|
|
35429
|
+
async getMaxBorrowableAmount() {
|
|
35430
|
+
const vesuAdapter = await this.getVesuAdapter();
|
|
35431
|
+
const extendedAdapter = await this.getExtendedAdapter();
|
|
35432
|
+
if (!vesuAdapter || !extendedAdapter) {
|
|
35433
|
+
return new Web3Number(0, 0);
|
|
35434
|
+
}
|
|
35435
|
+
const extendedFundingRate = new Web3Number((await extendedAdapter.getNetAPY()).toFixed(4), 0);
|
|
35436
|
+
const extendedPositions = await extendedAdapter.getAllOpenPositions();
|
|
35437
|
+
if (!extendedPositions || extendedPositions.length === 0) {
|
|
35438
|
+
logger.info(`no extended positions found`);
|
|
35439
|
+
return new Web3Number(0, 0);
|
|
35440
|
+
}
|
|
35441
|
+
const extendePositionSizeUSD = new Web3Number(extendedPositions[0].value || 0, 0);
|
|
35442
|
+
const vesuPositions = await vesuAdapter.getPositions();
|
|
35443
|
+
const vesuSupplyApy = vesuPositions[0].apy.apy;
|
|
35444
|
+
const vesuCollateralSizeUSD = new Web3Number(vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
|
|
35445
|
+
const vesuDebtSizeUSD = new Web3Number(vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
|
|
35446
|
+
const num1 = extendePositionSizeUSD.multipliedBy(extendedFundingRate);
|
|
35447
|
+
const num22 = vesuCollateralSizeUSD.multipliedBy(vesuSupplyApy);
|
|
35448
|
+
const num32 = vesuDebtSizeUSD.abs();
|
|
35449
|
+
const maxBorrowApy = num1.plus(num22).minus(0.1).dividedBy(num32);
|
|
35450
|
+
const vesuMaxBorrowableAmount = await vesuAdapter.vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxBorrowApy.toNumber());
|
|
35451
|
+
return new Web3Number(vesuMaxBorrowableAmount.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
|
|
35452
|
+
}
|
|
35453
|
+
async getVesuHealthFactors() {
|
|
35454
|
+
const vesuAdapter = await this.getVesuAdapter();
|
|
35455
|
+
const extendedAdapter = await this.getExtendedAdapter();
|
|
35456
|
+
if (!vesuAdapter || !extendedAdapter) {
|
|
35457
|
+
return [0, 0];
|
|
35458
|
+
}
|
|
35459
|
+
const vesuPositions = await vesuAdapter.getPositions();
|
|
35460
|
+
const vesuCollateralSizeUSD = new Web3Number(vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS), 0);
|
|
35461
|
+
const vesuDebtSizeUSD = new Web3Number(vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS), 0);
|
|
35462
|
+
const actualLtv = vesuDebtSizeUSD.dividedBy(vesuCollateralSizeUSD).abs();
|
|
35463
|
+
logger.info(`actualLtv: ${actualLtv.toNumber()}`);
|
|
35464
|
+
const maxLtv = new Web3Number(await vesuAdapter.vesuAdapter.getLTVConfig(this.config), 4);
|
|
35465
|
+
const healthFactor = new Web3Number(maxLtv.dividedBy(actualLtv).toFixed(4), 4);
|
|
35466
|
+
logger.info(`healthFactor: ${healthFactor.toNumber()}`);
|
|
35467
|
+
const extendedBalance = await extendedAdapter.getExtendedDepositAmount();
|
|
35468
|
+
if (!extendedBalance) {
|
|
35469
|
+
return [0, 0];
|
|
35470
|
+
}
|
|
35471
|
+
const extendedLeverage = new Web3Number((Number(extendedBalance.marginRatio) * 100).toFixed(4), 4);
|
|
35472
|
+
logger.info(`extendedLeverage: ${extendedLeverage.toNumber()}`);
|
|
35473
|
+
return [healthFactor.toNumber(), extendedLeverage.toNumber()];
|
|
35474
|
+
}
|
|
35475
|
+
async netAPY() {
|
|
35476
|
+
const allPositions = [];
|
|
35477
|
+
for (let adapter of this.metadata.additionalInfo.adapters) {
|
|
35478
|
+
if (adapter.adapter.name !== ExtendedAdapter.name) {
|
|
35479
|
+
let positions = await adapter.adapter.getPositions();
|
|
35480
|
+
if (positions.length > 0) {
|
|
35481
|
+
allPositions.push(...positions);
|
|
35482
|
+
}
|
|
35483
|
+
}
|
|
35484
|
+
}
|
|
35485
|
+
const extendedAdapter = await this.getExtendedAdapter();
|
|
35486
|
+
if (!extendedAdapter) {
|
|
35487
|
+
return {
|
|
35488
|
+
net: 0,
|
|
35489
|
+
splits: []
|
|
35490
|
+
};
|
|
35491
|
+
}
|
|
35492
|
+
let vesuPositions = allPositions.filter((item) => item.protocol === Protocols.VESU);
|
|
35493
|
+
vesuPositions.map((item) => {
|
|
35494
|
+
item.apy.apy = item.apy.apy * 0.1;
|
|
35495
|
+
});
|
|
35496
|
+
const extendedPositions = await extendedAdapter.getAllOpenPositions();
|
|
35497
|
+
const usdcToken = Global.getDefaultTokens().find((token) => token.symbol === "USDC");
|
|
35498
|
+
if (!extendedPositions || !usdcToken) {
|
|
35499
|
+
return {
|
|
35500
|
+
net: 0,
|
|
35501
|
+
splits: []
|
|
35502
|
+
};
|
|
35503
|
+
}
|
|
35504
|
+
const extendedPosition = extendedPositions[0] || 0;
|
|
35505
|
+
const extendedEquity = (await extendedAdapter.getExtendedDepositAmount())?.equity || 0;
|
|
35506
|
+
const extendedApy = await extendedAdapter.getNetAPY();
|
|
35507
|
+
const totalHoldingsUSDValue = allPositions.reduce((acc, curr) => acc + curr.usdValue, 0) + Number(extendedEquity);
|
|
35508
|
+
console.log(totalHoldingsUSDValue);
|
|
35509
|
+
const extendedPositionSizeMultipliedByApy = Number(extendedPosition.value) * extendedApy;
|
|
35510
|
+
let weightedAPYs = allPositions.reduce((acc, curr) => acc + curr.apy.apy * curr.usdValue, 0) + extendedPositionSizeMultipliedByApy;
|
|
35511
|
+
console.log(weightedAPYs);
|
|
35512
|
+
const netAPY = weightedAPYs / totalHoldingsUSDValue;
|
|
35513
|
+
console.log(netAPY);
|
|
35514
|
+
allPositions.push({
|
|
35515
|
+
tokenInfo: usdcToken,
|
|
35516
|
+
amount: new Web3Number(extendedPosition.size, 0),
|
|
35517
|
+
usdValue: Number(extendedEquity),
|
|
35518
|
+
apy: { apy: extendedApy, type: "base" /* BASE */ },
|
|
35519
|
+
remarks: "finalised" /* FINALISED */,
|
|
35520
|
+
protocol: Protocols.EXTENDED
|
|
35521
|
+
});
|
|
35522
|
+
return {
|
|
35523
|
+
net: netAPY,
|
|
35524
|
+
splits: allPositions.map((p) => ({ apy: p.apy.apy, id: p.remarks ?? "" }))
|
|
35525
|
+
};
|
|
35526
|
+
}
|
|
35527
|
+
async getWalletHoldings() {
|
|
35528
|
+
const usdceToken = Global.getDefaultTokens().find((token) => token.symbol === "USDCe");
|
|
35529
|
+
const wbtcToken = Global.getDefaultTokens().find((token) => token.symbol === "WBTC");
|
|
35530
|
+
const usdcToken = Global.getDefaultTokens().find((token) => token.symbol === "USDC");
|
|
35531
|
+
if (!usdceToken || !wbtcToken || !usdcToken) {
|
|
35532
|
+
return [];
|
|
35533
|
+
}
|
|
35534
|
+
const walletAddress = this.metadata.additionalInfo.walletAddress;
|
|
35535
|
+
const usdceWalletBalance = await new ERC20(this.config).balanceOf(
|
|
35536
|
+
usdceToken.address,
|
|
35537
|
+
walletAddress,
|
|
35538
|
+
usdceToken.decimals
|
|
35539
|
+
);
|
|
35540
|
+
const usdcWalletBalance = await new ERC20(this.config).balanceOf(
|
|
35541
|
+
usdcToken.address,
|
|
35542
|
+
walletAddress,
|
|
35543
|
+
usdcToken.decimals
|
|
35544
|
+
);
|
|
35545
|
+
const wbtcWalletBalance = await new ERC20(this.config).balanceOf(
|
|
35546
|
+
wbtcToken.address,
|
|
35547
|
+
walletAddress,
|
|
35548
|
+
wbtcToken.decimals
|
|
35549
|
+
);
|
|
35550
|
+
const price = await this.pricer.getPrice(usdceToken.symbol);
|
|
35551
|
+
const wbtcPrice = await this.pricer.getPrice(wbtcToken.symbol);
|
|
35552
|
+
const usdceUsdValue = Number(usdceWalletBalance.toFixed(usdceToken.decimals)) * price.price;
|
|
35553
|
+
const usdcUsdValue = Number(usdcWalletBalance.toFixed(usdcToken.decimals)) * price.price;
|
|
35554
|
+
const wbtcUsdValue = Number(wbtcWalletBalance.toFixed(wbtcToken.decimals)) * wbtcPrice.price;
|
|
35555
|
+
return [
|
|
35556
|
+
{
|
|
35557
|
+
tokenInfo: usdceToken,
|
|
35558
|
+
amount: usdceWalletBalance,
|
|
35559
|
+
usdValue: usdceUsdValue
|
|
35560
|
+
},
|
|
35561
|
+
{
|
|
35562
|
+
tokenInfo: usdcToken,
|
|
35563
|
+
amount: usdcWalletBalance,
|
|
35564
|
+
usdValue: usdcUsdValue
|
|
35565
|
+
},
|
|
35566
|
+
{
|
|
35567
|
+
tokenInfo: wbtcToken,
|
|
35568
|
+
amount: wbtcWalletBalance,
|
|
35569
|
+
usdValue: wbtcUsdValue
|
|
35570
|
+
}
|
|
35571
|
+
];
|
|
35572
|
+
}
|
|
34647
35573
|
};
|
|
34648
|
-
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1,
|
|
35574
|
+
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
|
|
34649
35575
|
vaultSettings.leafAdapters = [];
|
|
34650
35576
|
const wbtcToken = Global.getDefaultTokens().find(
|
|
34651
35577
|
(token) => token.symbol === lstSymbol
|
|
@@ -34669,7 +35595,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
|
|
|
34669
35595
|
...baseAdapterConfig,
|
|
34670
35596
|
avnuContract: AVNU_MIDDLEWARE,
|
|
34671
35597
|
slippage: 0.01,
|
|
34672
|
-
baseUrl: AVNU_QUOTE_URL
|
|
35598
|
+
baseUrl: AVNU_QUOTE_URL,
|
|
35599
|
+
minimumExtendedPriceDifferenceForSwapOpen,
|
|
35600
|
+
maximumExtendedPriceDifferenceForSwapClosing
|
|
34673
35601
|
});
|
|
34674
35602
|
const extendedAdapter = new ExtendedAdapter({
|
|
34675
35603
|
...baseAdapterConfig,
|
|
@@ -34678,14 +35606,17 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
|
|
|
34678
35606
|
],
|
|
34679
35607
|
vaultIdExtended,
|
|
34680
35608
|
extendedContract: EXTENDED_CONTRACT,
|
|
34681
|
-
|
|
34682
|
-
|
|
35609
|
+
extendedBackendWriteUrl,
|
|
35610
|
+
extendedBackendReadUrl,
|
|
34683
35611
|
extendedTimeout: 3e4,
|
|
34684
35612
|
extendedRetries: 3,
|
|
34685
35613
|
extendedBaseUrl: "https://api.starknet.extended.exchange",
|
|
34686
35614
|
extendedMarketName: "BTC-USD",
|
|
34687
35615
|
extendedPrecision: 5,
|
|
34688
|
-
avnuAdapter
|
|
35616
|
+
avnuAdapter,
|
|
35617
|
+
retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3e3,
|
|
35618
|
+
minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5
|
|
35619
|
+
//5 usdcs
|
|
34689
35620
|
});
|
|
34690
35621
|
const vesuMultiplyAdapter = new VesuMultiplyAdapter({
|
|
34691
35622
|
poolId: pool1,
|
|
@@ -34698,7 +35629,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
|
|
|
34698
35629
|
supportedPositions: [
|
|
34699
35630
|
{ asset: wbtcToken, isDebt: false },
|
|
34700
35631
|
{ asset: usdcToken, isDebt: true }
|
|
34701
|
-
]
|
|
35632
|
+
],
|
|
35633
|
+
minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5
|
|
35634
|
+
//5 usdc
|
|
34702
35635
|
});
|
|
34703
35636
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
34704
35637
|
...baseAdapterConfig
|
|
@@ -34794,11 +35727,11 @@ function VaultDescription2(lstSymbol, underlyingSymbol) {
|
|
|
34794
35727
|
] });
|
|
34795
35728
|
}
|
|
34796
35729
|
var re7UsdcPrimeDevansh = {
|
|
34797
|
-
vaultAddress: ContractAddr.from("
|
|
34798
|
-
manager: ContractAddr.from("
|
|
34799
|
-
vaultAllocator: ContractAddr.from("
|
|
34800
|
-
redeemRequestNFT: ContractAddr.from("
|
|
34801
|
-
aumOracle: ContractAddr.from("
|
|
35730
|
+
vaultAddress: ContractAddr.from("0x058905be22d6a81792df79425dc9641cf3e1b77f36748631b7d7e5d713a32b55"),
|
|
35731
|
+
manager: ContractAddr.from("0x02648d703783feb2d967cf0520314cb5aa800d69a9426f3e3b317395af44de16"),
|
|
35732
|
+
vaultAllocator: ContractAddr.from("0x07d533c838eab6a4d854dd3aea96a55993fccd35821921970d00bde946b63b6f"),
|
|
35733
|
+
redeemRequestNFT: ContractAddr.from("0x01ef91f08fb99729c00f82fc6e0ece37917bcc43952596c19996259dc8adbbba"),
|
|
35734
|
+
aumOracle: ContractAddr.from("0x030b6acfec162f5d6e72b8a4d2798aedce78fb39de78a8f549f7cd277ae8bc8d"),
|
|
34802
35735
|
leafAdapters: [],
|
|
34803
35736
|
adapters: [],
|
|
34804
35737
|
targetHealthFactor: 1.4,
|
|
@@ -34811,14 +35744,15 @@ var re7UsdcPrimeDevansh = {
|
|
|
34811
35744
|
Global.getDefaultTokens().find((token) => token.symbol === "WBTC").decimals
|
|
34812
35745
|
),
|
|
34813
35746
|
borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
|
|
34814
|
-
minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP
|
|
35747
|
+
minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP,
|
|
35748
|
+
walletAddress: WALLET_ADDRESS
|
|
34815
35749
|
};
|
|
34816
|
-
var VesuExtendedTestStrategies = (
|
|
35750
|
+
var VesuExtendedTestStrategies = (extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) => {
|
|
34817
35751
|
return [
|
|
34818
|
-
getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false,
|
|
35752
|
+
getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing)
|
|
34819
35753
|
];
|
|
34820
35754
|
};
|
|
34821
|
-
function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST,
|
|
35755
|
+
function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
|
|
34822
35756
|
return {
|
|
34823
35757
|
name: `Extended Test ${underlyingSymbol}`,
|
|
34824
35758
|
description: getDescription2(lstSymbol, underlyingSymbol),
|
|
@@ -34826,7 +35760,7 @@ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses,
|
|
|
34826
35760
|
launchBlock: 0,
|
|
34827
35761
|
type: "Other",
|
|
34828
35762
|
depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol)],
|
|
34829
|
-
additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime,
|
|
35763
|
+
additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing),
|
|
34830
35764
|
risk: {
|
|
34831
35765
|
riskFactor: _riskFactor3,
|
|
34832
35766
|
netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
|
|
@@ -39070,11 +40004,13 @@ var deployer_default = Deployer;
|
|
|
39070
40004
|
AssetOperationStatus,
|
|
39071
40005
|
AssetOperationType,
|
|
39072
40006
|
AutoCompounderSTRK,
|
|
40007
|
+
AvnuAdapter,
|
|
39073
40008
|
AvnuWrapper,
|
|
39074
40009
|
BaseAdapter,
|
|
39075
40010
|
BaseStrategy,
|
|
39076
40011
|
CommonAdapter,
|
|
39077
40012
|
ContractAddr,
|
|
40013
|
+
CycleType,
|
|
39078
40014
|
Deployer,
|
|
39079
40015
|
ERC20,
|
|
39080
40016
|
EXTENDED_CONTRACT,
|
|
@@ -39103,6 +40039,7 @@ var deployer_default = Deployer;
|
|
|
39103
40039
|
PRICE_ROUTER,
|
|
39104
40040
|
PasswordJsonCryptoUtil,
|
|
39105
40041
|
PositionSide,
|
|
40042
|
+
PositionTypeAvnuExtended,
|
|
39106
40043
|
Pragma,
|
|
39107
40044
|
Pricer,
|
|
39108
40045
|
PricerBase,
|
|
@@ -39152,6 +40089,7 @@ var deployer_default = Deployer;
|
|
|
39152
40089
|
calculateExtendedLevergae,
|
|
39153
40090
|
calculateVesUPositionSizeGivenExtended,
|
|
39154
40091
|
calculateVesuLeverage,
|
|
40092
|
+
calculateWBTCAmountToMaintainLTV,
|
|
39155
40093
|
extensionMap,
|
|
39156
40094
|
getAPIUsingHeadlessBrowser,
|
|
39157
40095
|
getContractDetails,
|