@strkfarm/sdk 2.0.0-dev.2 → 2.0.0-dev.20
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 +2004 -1062
- package/dist/index.browser.mjs +1843 -911
- package/dist/index.d.ts +144 -37
- package/dist/index.js +1851 -915
- package/dist/index.mjs +1843 -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 +15 -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,349 @@ 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
|
+
return dataObject;
|
|
30995
|
+
} catch (err) {
|
|
30996
|
+
logger.error(`No quotes available for this swap: ${err}`);
|
|
30997
|
+
return null;
|
|
30998
|
+
}
|
|
30999
|
+
}
|
|
31000
|
+
async getPriceOfToken(tokenAddress, retries = MAX_RETRIES) {
|
|
31001
|
+
try {
|
|
31002
|
+
const url = `https://starknet.impulse.avnu.fi/v1/tokens/${tokenAddress}/prices/line`;
|
|
31003
|
+
const response = await import_axios9.default.get(url);
|
|
31004
|
+
const length = response.data.length;
|
|
31005
|
+
return response.data[length - 1].value;
|
|
31006
|
+
} catch (err) {
|
|
31007
|
+
if (retries > 0) {
|
|
31008
|
+
await new Promise((resolve) => setTimeout(resolve, MAX_DELAY));
|
|
31009
|
+
return this.getPriceOfToken(tokenAddress, retries - 1);
|
|
31010
|
+
} else {
|
|
31011
|
+
logger.error(`Failed to fetch price for ${tokenAddress} after ${MAX_RETRIES} attempts`);
|
|
31012
|
+
return null;
|
|
31013
|
+
}
|
|
31014
|
+
}
|
|
31015
|
+
}
|
|
31016
|
+
};
|
|
31017
|
+
|
|
30154
31018
|
// src/strategies/universal-strategy.tsx
|
|
30155
31019
|
var AUMTypes = /* @__PURE__ */ ((AUMTypes2) => {
|
|
30156
31020
|
AUMTypes2["FINALISED"] = "finalised";
|
|
30157
31021
|
AUMTypes2["DEFISPRING"] = "defispring";
|
|
30158
31022
|
return AUMTypes2;
|
|
30159
31023
|
})(AUMTypes || {});
|
|
31024
|
+
var PositionTypeAvnuExtended = /* @__PURE__ */ ((PositionTypeAvnuExtended2) => {
|
|
31025
|
+
PositionTypeAvnuExtended2["OPEN"] = "open";
|
|
31026
|
+
PositionTypeAvnuExtended2["CLOSE"] = "close";
|
|
31027
|
+
return PositionTypeAvnuExtended2;
|
|
31028
|
+
})(PositionTypeAvnuExtended || {});
|
|
30160
31029
|
var UNIVERSAL_MANAGE_IDS = /* @__PURE__ */ ((UNIVERSAL_MANAGE_IDS2) => {
|
|
30161
31030
|
UNIVERSAL_MANAGE_IDS2["FLASH_LOAN"] = "flash_loan_init";
|
|
30162
31031
|
UNIVERSAL_MANAGE_IDS2["VESU_LEG1"] = "vesu_leg1";
|
|
@@ -30184,7 +31053,7 @@ function getContractDetails(settings) {
|
|
|
30184
31053
|
}
|
|
30185
31054
|
|
|
30186
31055
|
// src/strategies/svk-strategy.ts
|
|
30187
|
-
var
|
|
31056
|
+
var import_starknet24 = require("starknet");
|
|
30188
31057
|
|
|
30189
31058
|
// src/data/universal-vault.abi.json
|
|
30190
31059
|
var universal_vault_abi_default = [
|
|
@@ -32511,12 +33380,12 @@ var SVKStrategy = class extends BaseStrategy {
|
|
|
32511
33380
|
this.pricer = pricer;
|
|
32512
33381
|
this.metadata = metadata;
|
|
32513
33382
|
this.address = metadata.address;
|
|
32514
|
-
this.contract = new
|
|
33383
|
+
this.contract = new import_starknet24.Contract({
|
|
32515
33384
|
abi: universal_vault_abi_default,
|
|
32516
33385
|
address: this.address.address,
|
|
32517
33386
|
providerOrAccount: this.config.provider
|
|
32518
33387
|
});
|
|
32519
|
-
this.managerContract = new
|
|
33388
|
+
this.managerContract = new import_starknet24.Contract({
|
|
32520
33389
|
abi: vault_manager_abi_default,
|
|
32521
33390
|
address: this.metadata.additionalInfo.manager.address,
|
|
32522
33391
|
providerOrAccount: this.config.provider
|
|
@@ -32629,7 +33498,7 @@ var SVKStrategy = class extends BaseStrategy {
|
|
|
32629
33498
|
getSetManagerCall(strategist, root = this.getMerkleRoot()) {
|
|
32630
33499
|
return this.managerContract.populate("set_manage_root", [
|
|
32631
33500
|
strategist.address,
|
|
32632
|
-
|
|
33501
|
+
import_starknet24.num.getHexString(root)
|
|
32633
33502
|
]);
|
|
32634
33503
|
}
|
|
32635
33504
|
/**
|
|
@@ -33337,7 +34206,8 @@ function getLooperSettings(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
|
|
|
33337
34206
|
minHealthFactor: vaultSettings.minHealthFactor,
|
|
33338
34207
|
quoteAmountToFetchPrice: vaultSettings.quoteAmountToFetchPrice,
|
|
33339
34208
|
...baseAdapterConfig,
|
|
33340
|
-
supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }]
|
|
34209
|
+
supportedPositions: [{ asset: lstToken, isDebt: false }, { asset: Global.getDefaultTokens().find((token) => token.symbol === position), isDebt: true }],
|
|
34210
|
+
minimumVesuMovementAmount: 0
|
|
33341
34211
|
}));
|
|
33342
34212
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
33343
34213
|
...baseAdapterConfig
|
|
@@ -33566,335 +34436,15 @@ var HyperLSTStrategies = [
|
|
|
33566
34436
|
getStrategySettings("mRe7YIELD", "mRe7YIELD", hypermRe7YIELD, false, false)
|
|
33567
34437
|
];
|
|
33568
34438
|
|
|
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
|
-
};
|
|
34439
|
+
// src/strategies/vesu-extended-strategy/types/transaction-metadata.ts
|
|
34440
|
+
var CycleType = /* @__PURE__ */ ((CycleType2) => {
|
|
34441
|
+
CycleType2["INVESTMENT"] = "INVESTMENT";
|
|
34442
|
+
CycleType2["REBALANCE_PRICE_DROP"] = "REBALANCE_PRICE_DROP";
|
|
34443
|
+
CycleType2["REBALANCE_PRICE_RISE"] = "REBALANCE_PRICE_RISE";
|
|
34444
|
+
CycleType2["WITHDRAWAL"] = "WITHDRAWAL";
|
|
34445
|
+
CycleType2["DELTA_NEUTRAL_ADJUSTMENT"] = "DELTA_NEUTRAL_ADJUSTMENT";
|
|
34446
|
+
return CycleType2;
|
|
34447
|
+
})(CycleType || {});
|
|
33898
34448
|
|
|
33899
34449
|
// src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx
|
|
33900
34450
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
@@ -33994,15 +34544,30 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
33994
34544
|
const usdceToken = Global.getDefaultTokens().find(
|
|
33995
34545
|
(token) => token.symbol === "USDCe"
|
|
33996
34546
|
);
|
|
34547
|
+
const walletBalance = await new ERC20(this.config).balanceOf(
|
|
34548
|
+
usdceToken.address,
|
|
34549
|
+
WALLET_ADDRESS,
|
|
34550
|
+
usdceToken.decimals
|
|
34551
|
+
);
|
|
34552
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator walletBalance: ${walletBalance}`);
|
|
34553
|
+
const amountToBeTransferred = amount.minimum(walletBalance);
|
|
34554
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator amountToBeTransferred: ${amountToBeTransferred.toNumber()}`);
|
|
34555
|
+
if (amountToBeTransferred.lessThan(0)) {
|
|
34556
|
+
logger.error(`${_VesuExtendedMultiplierStrategy.name}::moveAssetsToVaultAllocator amountToBeTransferred is less than 0: ${amountToBeTransferred.toNumber()}`);
|
|
34557
|
+
return {
|
|
34558
|
+
calls: [],
|
|
34559
|
+
status: false
|
|
34560
|
+
};
|
|
34561
|
+
}
|
|
33997
34562
|
const approveCall = new ERC20(this.config).approve(
|
|
33998
34563
|
usdceToken.address,
|
|
33999
34564
|
this.metadata.additionalInfo.vaultAllocator,
|
|
34000
|
-
|
|
34565
|
+
amountToBeTransferred
|
|
34001
34566
|
);
|
|
34002
34567
|
const transferCall = new ERC20(this.config).transfer(
|
|
34003
34568
|
usdceToken.address,
|
|
34004
34569
|
this.metadata.additionalInfo.vaultAllocator,
|
|
34005
|
-
|
|
34570
|
+
amountToBeTransferred
|
|
34006
34571
|
);
|
|
34007
34572
|
const proofsInfo = extendedAdapter.getProofsForFromLegacySwap(
|
|
34008
34573
|
this.getMerkleTree()
|
|
@@ -34010,21 +34575,29 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34010
34575
|
const proofGroups = proofsInfo.proofs;
|
|
34011
34576
|
const call = this.getManageCall(
|
|
34012
34577
|
proofGroups,
|
|
34013
|
-
await proofsInfo.callConstructor({ amount })
|
|
34578
|
+
await proofsInfo.callConstructor({ amount: amountToBeTransferred })
|
|
34014
34579
|
);
|
|
34015
|
-
return
|
|
34580
|
+
return {
|
|
34581
|
+
calls: [approveCall, transferCall, call],
|
|
34582
|
+
status: true
|
|
34583
|
+
};
|
|
34016
34584
|
} catch (err) {
|
|
34017
34585
|
logger.error(`error moving assets to vault allocator: ${err}`);
|
|
34018
|
-
return
|
|
34586
|
+
return {
|
|
34587
|
+
calls: [],
|
|
34588
|
+
status: false
|
|
34589
|
+
};
|
|
34019
34590
|
}
|
|
34020
34591
|
}
|
|
34021
34592
|
async shouldInvest() {
|
|
34022
34593
|
try {
|
|
34594
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest starting`);
|
|
34023
34595
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34024
34596
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
34025
|
-
|
|
34597
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest adapters fetched: vesuAdapter=${!!vesuAdapter}, extendedAdapter=${!!extendedAdapter}, extendedAdapter.client=${!!extendedAdapter?.client}`);
|
|
34598
|
+
if (!vesuAdapter) {
|
|
34026
34599
|
logger.error(
|
|
34027
|
-
`
|
|
34600
|
+
`Vesu adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
34028
34601
|
);
|
|
34029
34602
|
return {
|
|
34030
34603
|
shouldInvest: false,
|
|
@@ -34036,10 +34609,87 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34036
34609
|
vesuLeverage: 0
|
|
34037
34610
|
};
|
|
34038
34611
|
}
|
|
34612
|
+
if (!extendedAdapter) {
|
|
34613
|
+
logger.error(
|
|
34614
|
+
`Extended adapter not configured in metadata. This is a configuration issue, not a temporary failure.`
|
|
34615
|
+
);
|
|
34616
|
+
return {
|
|
34617
|
+
shouldInvest: false,
|
|
34618
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34619
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34620
|
+
extendedLeverage: 0,
|
|
34621
|
+
collateralPrice: 0,
|
|
34622
|
+
debtPrice: 0,
|
|
34623
|
+
vesuLeverage: 0
|
|
34624
|
+
};
|
|
34625
|
+
}
|
|
34626
|
+
if (!extendedAdapter.client) {
|
|
34627
|
+
logger.error(
|
|
34628
|
+
`Extended adapter client not initialized. This may be a temporary initialization failure - check network connectivity and API availability.`
|
|
34629
|
+
);
|
|
34630
|
+
return {
|
|
34631
|
+
shouldInvest: false,
|
|
34632
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34633
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34634
|
+
extendedLeverage: 0,
|
|
34635
|
+
collateralPrice: 0,
|
|
34636
|
+
debtPrice: 0,
|
|
34637
|
+
vesuLeverage: 0
|
|
34638
|
+
};
|
|
34639
|
+
}
|
|
34640
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest calling getUnusedBalance`);
|
|
34039
34641
|
const balance = await this.getUnusedBalance();
|
|
34642
|
+
if (!Number.isFinite(balance.usdValue) || balance.usdValue < 0) {
|
|
34643
|
+
logger.error(
|
|
34644
|
+
`Invalid balance.usdValue: ${balance.usdValue}. Expected a finite, non-negative number.`
|
|
34645
|
+
);
|
|
34646
|
+
return {
|
|
34647
|
+
shouldInvest: false,
|
|
34648
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34649
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34650
|
+
extendedLeverage: 0,
|
|
34651
|
+
collateralPrice: 0,
|
|
34652
|
+
debtPrice: 0,
|
|
34653
|
+
vesuLeverage: 0
|
|
34654
|
+
};
|
|
34655
|
+
}
|
|
34656
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest balance: ${balance.usdValue}`);
|
|
34040
34657
|
const usdcBalanceOnExtended = await extendedAdapter.getExtendedDepositAmount();
|
|
34041
|
-
|
|
34042
|
-
|
|
34658
|
+
if (usdcBalanceOnExtended) {
|
|
34659
|
+
const availableForWithdrawal = parseFloat(usdcBalanceOnExtended.availableForWithdrawal);
|
|
34660
|
+
if (!Number.isFinite(availableForWithdrawal) || availableForWithdrawal < 0) {
|
|
34661
|
+
logger.error(
|
|
34662
|
+
`Invalid usdcBalanceOnExtended.availableForWithdrawal: ${usdcBalanceOnExtended.availableForWithdrawal}. Expected a finite, non-negative number.`
|
|
34663
|
+
);
|
|
34664
|
+
return {
|
|
34665
|
+
shouldInvest: false,
|
|
34666
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34667
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34668
|
+
extendedLeverage: 0,
|
|
34669
|
+
collateralPrice: 0,
|
|
34670
|
+
debtPrice: 0,
|
|
34671
|
+
vesuLeverage: 0
|
|
34672
|
+
};
|
|
34673
|
+
}
|
|
34674
|
+
}
|
|
34675
|
+
const amountToInvest = new Web3Number(balance.usdValue, USDC_TOKEN_DECIMALS).plus(usdcBalanceOnExtended?.availableForWithdrawal ?? 0).multipliedBy(1 - LIMIT_BALANCE);
|
|
34676
|
+
const amountToInvestNumber = amountToInvest.toNumber();
|
|
34677
|
+
if (!Number.isFinite(amountToInvestNumber)) {
|
|
34678
|
+
logger.error(
|
|
34679
|
+
`Invalid amountToInvest calculation result: ${amountToInvestNumber}. Calculation may have produced NaN or Infinity.`
|
|
34680
|
+
);
|
|
34681
|
+
return {
|
|
34682
|
+
shouldInvest: false,
|
|
34683
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34684
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34685
|
+
extendedLeverage: 0,
|
|
34686
|
+
collateralPrice: 0,
|
|
34687
|
+
debtPrice: 0,
|
|
34688
|
+
vesuLeverage: 0
|
|
34689
|
+
};
|
|
34690
|
+
}
|
|
34691
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest amountToInvest: ${amountToInvestNumber}`);
|
|
34692
|
+
if (amountToInvest.lessThan(LIMIT_BALANCE_VALUE)) {
|
|
34043
34693
|
return {
|
|
34044
34694
|
shouldInvest: false,
|
|
34045
34695
|
vesuAmount: new Web3Number(0, 0),
|
|
@@ -34068,6 +34718,34 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34068
34718
|
collateralPrice,
|
|
34069
34719
|
debtPrice
|
|
34070
34720
|
} = await this.getAssetPrices();
|
|
34721
|
+
if (!Number.isFinite(collateralPrice.price) || collateralPrice.price <= 0) {
|
|
34722
|
+
logger.error(
|
|
34723
|
+
`Invalid collateralPrice: ${collateralPrice.price}. Expected a finite, positive number.`
|
|
34724
|
+
);
|
|
34725
|
+
return {
|
|
34726
|
+
shouldInvest: false,
|
|
34727
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34728
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34729
|
+
extendedLeverage: 0,
|
|
34730
|
+
collateralPrice: 0,
|
|
34731
|
+
debtPrice: 0,
|
|
34732
|
+
vesuLeverage: 0
|
|
34733
|
+
};
|
|
34734
|
+
}
|
|
34735
|
+
if (!Number.isFinite(debtPrice.price) || debtPrice.price <= 0) {
|
|
34736
|
+
logger.error(
|
|
34737
|
+
`Invalid debtPrice: ${debtPrice.price}. Expected a finite, positive number.`
|
|
34738
|
+
);
|
|
34739
|
+
return {
|
|
34740
|
+
shouldInvest: false,
|
|
34741
|
+
vesuAmount: new Web3Number(0, 0),
|
|
34742
|
+
extendedAmount: new Web3Number(0, 0),
|
|
34743
|
+
extendedLeverage: 0,
|
|
34744
|
+
collateralPrice: 0,
|
|
34745
|
+
debtPrice: 0,
|
|
34746
|
+
vesuLeverage: 0
|
|
34747
|
+
};
|
|
34748
|
+
}
|
|
34071
34749
|
const { vesu_amount, extended_amount, extended_leverage, vesu_leverage } = await calculateAmountDistribution(
|
|
34072
34750
|
amountToInvest.toNumber(),
|
|
34073
34751
|
extendedAdapter.client,
|
|
@@ -34091,6 +34769,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34091
34769
|
vesuLeverage: 0
|
|
34092
34770
|
};
|
|
34093
34771
|
}
|
|
34772
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldInvest vesu_amount: ${vesu_amount.toNumber()}, extended_amount: ${extended_amount.toNumber()}`);
|
|
34094
34773
|
return {
|
|
34095
34774
|
shouldInvest: true,
|
|
34096
34775
|
vesuAmount: vesu_amount,
|
|
@@ -34117,111 +34796,251 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34117
34796
|
try {
|
|
34118
34797
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34119
34798
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
34120
|
-
let calls = [];
|
|
34121
34799
|
if (!vesuAdapter || !extendedAdapter || !extendedAdapter.client) {
|
|
34122
34800
|
logger.error(
|
|
34123
34801
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
34124
34802
|
);
|
|
34125
|
-
return
|
|
34803
|
+
return [];
|
|
34126
34804
|
}
|
|
34127
|
-
|
|
34805
|
+
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34806
|
+
if (!extendedHoldings) {
|
|
34807
|
+
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
34808
|
+
return [];
|
|
34809
|
+
}
|
|
34810
|
+
const usdcAmountInWallet = (await this.getUnusedBalance()).amount;
|
|
34811
|
+
const usdcAmountOnExtendedAvailableForWithdrawal = parseFloat(
|
|
34812
|
+
extendedHoldings.availableForWithdrawal
|
|
34813
|
+
);
|
|
34814
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::shouldMoveAssets calculating movements - Extended current: ${usdcAmountOnExtendedAvailableForWithdrawal}, Wallet: ${usdcAmountInWallet.toNumber()}, Target Extended: ${extendedAmount.toNumber()}, Target Vesu: ${vesuAmount.toNumber()}`);
|
|
34815
|
+
let totalExtendedWithdrawal = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
34816
|
+
let totalExtendedDeposit = new Web3Number(0, USDC_TOKEN_DECIMALS);
|
|
34817
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34818
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmount.abs());
|
|
34819
|
+
}
|
|
34820
|
+
const extendedTargetAmount = extendedAmount.abs();
|
|
34821
|
+
let projectedExtendedBalance = usdcAmountOnExtendedAvailableForWithdrawal;
|
|
34822
|
+
if (extendedAmount.isNegative()) {
|
|
34823
|
+
projectedExtendedBalance = projectedExtendedBalance - extendedAmount.abs().toNumber();
|
|
34824
|
+
}
|
|
34825
|
+
const extendedAmountDifference = extendedTargetAmount.minus(projectedExtendedBalance);
|
|
34826
|
+
const extendedAmountDifferenceAbs = extendedAmountDifference.abs();
|
|
34827
|
+
if (extendedAmountDifference.lessThan(0)) {
|
|
34828
|
+
totalExtendedWithdrawal = totalExtendedWithdrawal.plus(extendedAmountDifferenceAbs);
|
|
34829
|
+
} else if (extendedAmountDifference.greaterThan(0)) {
|
|
34830
|
+
totalExtendedDeposit = totalExtendedDeposit.plus(extendedAmountDifference);
|
|
34831
|
+
}
|
|
34832
|
+
const vesuTargetAmount = vesuAmount.abs();
|
|
34833
|
+
const projectedWalletBalance = usdcAmountInWallet.plus(totalExtendedWithdrawal).minus(totalExtendedDeposit);
|
|
34834
|
+
let vesuAmountDifference = vesuTargetAmount.minus(projectedWalletBalance);
|
|
34835
|
+
const vesuAmountDifferenceAbs = vesuAmountDifference.abs();
|
|
34836
|
+
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()}`);
|
|
34837
|
+
let calls = [];
|
|
34838
|
+
let transactionResults = [];
|
|
34839
|
+
if (extendedAmount.isNegative() && extendedAmount.abs().greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34128
34840
|
try {
|
|
34129
|
-
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
34841
|
+
const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
|
|
34130
34842
|
{
|
|
34131
34843
|
to: Protocols.VAULT.name,
|
|
34132
34844
|
from: Protocols.EXTENDED.name,
|
|
34133
|
-
amount: extendedAmount.abs()
|
|
34845
|
+
amount: extendedAmount.abs(),
|
|
34846
|
+
cycleType: "INVESTMENT" /* INVESTMENT */
|
|
34134
34847
|
},
|
|
34135
34848
|
extendedAdapter,
|
|
34136
34849
|
vesuAdapter
|
|
34137
34850
|
);
|
|
34138
34851
|
if (extendedStatus) {
|
|
34139
|
-
|
|
34852
|
+
transactionResults.push({
|
|
34853
|
+
status: extendedStatus,
|
|
34854
|
+
calls: extendedCalls,
|
|
34855
|
+
transactionMetadata: {
|
|
34856
|
+
...extendedTransactionMetadata,
|
|
34857
|
+
transactionType: "DEPOSIT"
|
|
34858
|
+
}
|
|
34859
|
+
});
|
|
34140
34860
|
} else {
|
|
34141
|
-
return [];
|
|
34861
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34142
34862
|
}
|
|
34143
34863
|
} catch (err) {
|
|
34144
34864
|
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34865
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34145
34866
|
}
|
|
34146
34867
|
}
|
|
34147
|
-
if (vesuAmount.
|
|
34868
|
+
if (vesuAmount.isNegative() && vesuAmount.abs().greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34148
34869
|
try {
|
|
34149
|
-
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
34870
|
+
const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
|
|
34150
34871
|
{
|
|
34151
34872
|
to: Protocols.EXTENDED.name,
|
|
34152
34873
|
from: Protocols.VESU.name,
|
|
34153
|
-
amount: vesuAmount.abs()
|
|
34874
|
+
amount: vesuAmount.abs(),
|
|
34875
|
+
cycleType: "INVESTMENT" /* INVESTMENT */
|
|
34154
34876
|
},
|
|
34155
34877
|
extendedAdapter,
|
|
34156
34878
|
vesuAdapter
|
|
34157
34879
|
);
|
|
34158
|
-
calls.push(...vesuCalls);
|
|
34159
34880
|
if (!vesuStatus) {
|
|
34160
|
-
return [];
|
|
34161
|
-
}
|
|
34881
|
+
return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34882
|
+
}
|
|
34883
|
+
transactionResults.push({
|
|
34884
|
+
status: vesuStatus,
|
|
34885
|
+
calls: vesuCalls,
|
|
34886
|
+
transactionMetadata: {
|
|
34887
|
+
...vesuTransactionMetadata,
|
|
34888
|
+
transactionType: "DEPOSIT"
|
|
34889
|
+
}
|
|
34890
|
+
});
|
|
34162
34891
|
} catch (err) {
|
|
34163
|
-
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34892
|
+
logger.error(`Failed moving assets to extended via vault allocator: ${err}`);
|
|
34893
|
+
return [this.createTransactionResult([], false, { from: Protocols.VESU.name, to: Protocols.EXTENDED.name, amount: vesuAmount.abs() }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34164
34894
|
}
|
|
34165
34895
|
}
|
|
34166
|
-
|
|
34167
|
-
|
|
34168
|
-
|
|
34169
|
-
|
|
34170
|
-
|
|
34171
|
-
|
|
34172
|
-
|
|
34173
|
-
|
|
34174
|
-
|
|
34175
|
-
|
|
34176
|
-
|
|
34177
|
-
|
|
34178
|
-
|
|
34179
|
-
|
|
34180
|
-
|
|
34181
|
-
|
|
34182
|
-
|
|
34183
|
-
|
|
34184
|
-
|
|
34185
|
-
|
|
34186
|
-
|
|
34187
|
-
|
|
34188
|
-
|
|
34896
|
+
if (extendedAmountDifferenceAbs.greaterThan(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
34897
|
+
if (extendedAmountDifference.greaterThan(0)) {
|
|
34898
|
+
try {
|
|
34899
|
+
const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
|
|
34900
|
+
{
|
|
34901
|
+
to: Protocols.EXTENDED.name,
|
|
34902
|
+
from: Protocols.VAULT.name,
|
|
34903
|
+
amount: extendedAmountDifference,
|
|
34904
|
+
cycleType: "INVESTMENT" /* INVESTMENT */
|
|
34905
|
+
},
|
|
34906
|
+
extendedAdapter,
|
|
34907
|
+
vesuAdapter
|
|
34908
|
+
);
|
|
34909
|
+
if (extendedStatus) {
|
|
34910
|
+
transactionResults.push({
|
|
34911
|
+
status: extendedStatus,
|
|
34912
|
+
calls: extendedCalls,
|
|
34913
|
+
transactionMetadata: extendedTransactionMetadata
|
|
34914
|
+
});
|
|
34915
|
+
} else {
|
|
34916
|
+
logger.error(`Failed to move assets to extended - operation returned false status`);
|
|
34917
|
+
return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34918
|
+
}
|
|
34919
|
+
} catch (err) {
|
|
34920
|
+
logger.error(`Failed moving assets to extended: ${err}`);
|
|
34921
|
+
return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.EXTENDED.name, amount: extendedAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34922
|
+
}
|
|
34923
|
+
} else if (extendedAmountDifference.lessThan(0)) {
|
|
34924
|
+
try {
|
|
34925
|
+
const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
|
|
34926
|
+
{
|
|
34927
|
+
to: Protocols.VAULT.name,
|
|
34928
|
+
from: Protocols.EXTENDED.name,
|
|
34929
|
+
amount: extendedAmountDifferenceAbs,
|
|
34930
|
+
cycleType: "INVESTMENT" /* INVESTMENT */
|
|
34931
|
+
},
|
|
34932
|
+
extendedAdapter,
|
|
34933
|
+
vesuAdapter
|
|
34934
|
+
);
|
|
34935
|
+
if (extendedStatus) {
|
|
34936
|
+
transactionResults.push({
|
|
34937
|
+
status: extendedStatus,
|
|
34938
|
+
calls: extendedCalls,
|
|
34939
|
+
transactionMetadata: {
|
|
34940
|
+
...extendedTransactionMetadata,
|
|
34941
|
+
transactionType: "DEPOSIT"
|
|
34942
|
+
}
|
|
34943
|
+
});
|
|
34944
|
+
} else {
|
|
34945
|
+
logger.error(`Failed to withdraw from extended - operation returned false status`);
|
|
34946
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34947
|
+
}
|
|
34948
|
+
} catch (err) {
|
|
34949
|
+
logger.error(`Failed moving assets from extended to vault: ${err}`);
|
|
34950
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: extendedAmountDifferenceAbs }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34951
|
+
}
|
|
34189
34952
|
}
|
|
34190
34953
|
}
|
|
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
|
|
34954
|
+
if (vesuAmountDifferenceAbs.greaterThan(vesuAdapter.minimumVesuMovementAmount)) {
|
|
34955
|
+
if (vesuAmountDifference.lessThanOrEqualTo(0)) {
|
|
34956
|
+
logger.warn(
|
|
34957
|
+
`Vesu amount difference is negative or zero: ${vesuAmountDifference.toNumber()}. Skipping operation.`
|
|
34201
34958
|
);
|
|
34202
|
-
|
|
34203
|
-
|
|
34959
|
+
} else {
|
|
34960
|
+
try {
|
|
34961
|
+
const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
|
|
34962
|
+
{
|
|
34963
|
+
to: Protocols.VAULT.name,
|
|
34964
|
+
from: Protocols.EXTENDED.name,
|
|
34965
|
+
amount: vesuAmountDifference,
|
|
34966
|
+
cycleType: "INVESTMENT" /* INVESTMENT */
|
|
34967
|
+
},
|
|
34968
|
+
extendedAdapter,
|
|
34969
|
+
vesuAdapter
|
|
34970
|
+
);
|
|
34971
|
+
if (!vesuStatus) {
|
|
34972
|
+
logger.error(`Failed to move assets to vesu - operation returned false status`);
|
|
34973
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34974
|
+
}
|
|
34975
|
+
transactionResults.push({
|
|
34976
|
+
status: vesuStatus,
|
|
34977
|
+
calls: vesuCalls,
|
|
34978
|
+
transactionMetadata: {
|
|
34979
|
+
...vesuTransactionMetadata,
|
|
34980
|
+
transactionType: "DEPOSIT"
|
|
34981
|
+
}
|
|
34982
|
+
});
|
|
34983
|
+
} catch (err) {
|
|
34984
|
+
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34985
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: vesuAmountDifference }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34204
34986
|
}
|
|
34205
|
-
calls.push(...vesuCalls);
|
|
34206
|
-
} catch (err) {
|
|
34207
|
-
logger.error(`Failed moving assets to vault: ${err}`);
|
|
34208
34987
|
}
|
|
34209
34988
|
}
|
|
34210
|
-
return
|
|
34989
|
+
return transactionResults;
|
|
34211
34990
|
} catch (err) {
|
|
34212
34991
|
logger.error(`Failed moving assets to vesu: ${err}`);
|
|
34213
|
-
return [];
|
|
34992
|
+
return [this.createTransactionResult([], false, { from: Protocols.EXTENDED.name, to: Protocols.VAULT.name, amount: new Web3Number(0, USDC_TOKEN_DECIMALS) }, "NONE", "INVESTMENT" /* INVESTMENT */)];
|
|
34993
|
+
}
|
|
34994
|
+
}
|
|
34995
|
+
/**
|
|
34996
|
+
* Helper method to create transaction result with metadata
|
|
34997
|
+
*/
|
|
34998
|
+
createTransactionResult(calls, status, params, transactionType, cycleType) {
|
|
34999
|
+
if (status) {
|
|
35000
|
+
return {
|
|
35001
|
+
calls,
|
|
35002
|
+
status,
|
|
35003
|
+
transactionMetadata: {
|
|
35004
|
+
protocolFrom: params.from,
|
|
35005
|
+
protocolTo: params.to,
|
|
35006
|
+
transactionType,
|
|
35007
|
+
usdAmount: params.amount.abs().toFixed(),
|
|
35008
|
+
status: "PENDING",
|
|
35009
|
+
cycleType
|
|
35010
|
+
}
|
|
35011
|
+
};
|
|
34214
35012
|
}
|
|
35013
|
+
return { calls: [], status: false, transactionMetadata: { protocolFrom: "", protocolTo: "", transactionType: "DEPOSIT", usdAmount: "0", status: "FAILED", cycleType } };
|
|
34215
35014
|
}
|
|
34216
35015
|
async moveAssets(params, extendedAdapter, vesuAdapter) {
|
|
34217
35016
|
try {
|
|
35017
|
+
if (params.amount.lessThanOrEqualTo(0)) {
|
|
35018
|
+
logger.error(
|
|
35019
|
+
`Invalid amount for moveAssets: ${params.amount.toNumber()}. Amount must be positive.`
|
|
35020
|
+
);
|
|
35021
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35022
|
+
}
|
|
35023
|
+
const amountAbs = params.amount.abs();
|
|
35024
|
+
if (params.from === Protocols.EXTENDED.name || params.to === Protocols.EXTENDED.name) {
|
|
35025
|
+
if (amountAbs.lessThanOrEqualTo(extendedAdapter.minimumExtendedMovementAmount)) {
|
|
35026
|
+
logger.warn(
|
|
35027
|
+
`Amount ${amountAbs.toNumber()} is below minimum Extended movement amount ${extendedAdapter.minimumExtendedMovementAmount}. Skipping operation.`
|
|
35028
|
+
);
|
|
35029
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35030
|
+
}
|
|
35031
|
+
}
|
|
35032
|
+
if (params.from === Protocols.VESU.name || params.to === Protocols.VESU.name) {
|
|
35033
|
+
if (amountAbs.lessThanOrEqualTo(vesuAdapter.minimumVesuMovementAmount)) {
|
|
35034
|
+
logger.warn(
|
|
35035
|
+
`Amount ${amountAbs.toNumber()} is below minimum Vesu movement amount ${vesuAdapter.minimumVesuMovementAmount}. Skipping operation.`
|
|
35036
|
+
);
|
|
35037
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35038
|
+
}
|
|
35039
|
+
}
|
|
34218
35040
|
const avnuAdapter = await this.getAvnuAdapter();
|
|
34219
35041
|
if (!avnuAdapter) {
|
|
34220
35042
|
logger.error(`avnu adapter not found: ${avnuAdapter}`);
|
|
34221
|
-
return
|
|
34222
|
-
calls: [],
|
|
34223
|
-
status: false
|
|
34224
|
-
};
|
|
35043
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
34225
35044
|
}
|
|
34226
35045
|
logger.info(`moveAssets params, ${JSON.stringify(params)}`);
|
|
34227
35046
|
const collateralToken = vesuAdapter.config.supportedPositions[0].asset;
|
|
@@ -34240,61 +35059,72 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34240
35059
|
await proofsInfo.callConstructor({ amount: params.amount })
|
|
34241
35060
|
);
|
|
34242
35061
|
calls.push(call);
|
|
34243
|
-
return
|
|
34244
|
-
calls: [call],
|
|
34245
|
-
status: true
|
|
34246
|
-
};
|
|
35062
|
+
return this.createTransactionResult(calls, true, params, "DEPOSIT", params.cycleType);
|
|
34247
35063
|
} else if (params.to === Protocols.VAULT.name && params.from === Protocols.EXTENDED.name) {
|
|
34248
35064
|
const extendedLeverage = calculateExtendedLevergae();
|
|
34249
35065
|
const extendedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
34250
35066
|
if (!extendedHoldings) {
|
|
34251
35067
|
logger.error(`error getting extended holdings: ${extendedHoldings}`);
|
|
34252
|
-
return
|
|
34253
|
-
calls: [],
|
|
34254
|
-
status: false
|
|
34255
|
-
};
|
|
35068
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
34256
35069
|
}
|
|
34257
35070
|
const extendedHoldingAmount = new Web3Number(
|
|
34258
35071
|
extendedHoldings.availableForWithdrawal,
|
|
34259
35072
|
USDC_TOKEN_DECIMALS
|
|
34260
35073
|
);
|
|
34261
|
-
|
|
34262
|
-
|
|
34263
|
-
|
|
34264
|
-
|
|
34265
|
-
btcAmount.
|
|
34266
|
-
|
|
34267
|
-
|
|
34268
|
-
|
|
34269
|
-
|
|
34270
|
-
|
|
34271
|
-
|
|
34272
|
-
|
|
34273
|
-
|
|
35074
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets extendedHoldingAmount: ${extendedHoldingAmount.toNumber()}`);
|
|
35075
|
+
if (params.amount.abs().greaterThan(extendedHoldingAmount)) {
|
|
35076
|
+
const leftAmountAfterWithdrawalAmountInAccount = params.amount.abs().minus(extendedHoldingAmount);
|
|
35077
|
+
logger.info(`${_VesuExtendedMultiplierStrategy.name}::moveAssets leftAmountAfterWithdrawalAmountInAccount: ${leftAmountAfterWithdrawalAmountInAccount.toNumber()}`);
|
|
35078
|
+
const btcAmount = leftAmountAfterWithdrawalAmountInAccount.dividedBy(collateralPrice.price);
|
|
35079
|
+
const openLongPosition = btcAmount.multipliedBy(3).greaterThan(MINIMUM_EXTENDED_POSITION_SIZE) ? await extendedAdapter.createOrder(
|
|
35080
|
+
extendedLeverage.toString(),
|
|
35081
|
+
btcAmount.toNumber(),
|
|
35082
|
+
"BUY" /* BUY */
|
|
35083
|
+
) : await extendedAdapter.createOrder(
|
|
35084
|
+
extendedLeverage.toString(),
|
|
35085
|
+
34e-6,
|
|
35086
|
+
// just in case amount falls short then we need to create a withdrawal
|
|
35087
|
+
"BUY" /* BUY */
|
|
35088
|
+
);
|
|
35089
|
+
if (!openLongPosition) {
|
|
35090
|
+
logger.error(`error opening long position: ${openLongPosition}`);
|
|
35091
|
+
}
|
|
35092
|
+
const updatedHoldings = await extendedAdapter.getExtendedDepositAmount();
|
|
35093
|
+
if (!updatedHoldings || new Web3Number(updatedHoldings.availableForWithdrawal, USDC_TOKEN_DECIMALS).lessThan(params.amount.abs())) {
|
|
35094
|
+
logger.error(`Insufficient balance after opening position. Available: ${updatedHoldings?.availableForWithdrawal}, Needed: ${params.amount.abs()}`);
|
|
35095
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35096
|
+
}
|
|
34274
35097
|
}
|
|
34275
|
-
|
|
34276
|
-
|
|
34277
|
-
|
|
35098
|
+
const {
|
|
35099
|
+
status: withdrawalFromExtendedStatus,
|
|
35100
|
+
receivedTxnHash: withdrawalFromExtendedTxnHash
|
|
35101
|
+
} = await extendedAdapter.withdrawFromExtended(params.amount);
|
|
35102
|
+
logger.info(`withdrawalFromExtendedStatus: ${withdrawalFromExtendedStatus}, withdrawalFromExtendedTxnHash: ${withdrawalFromExtendedTxnHash}`);
|
|
35103
|
+
if (withdrawalFromExtendedStatus && withdrawalFromExtendedTxnHash) {
|
|
34278
35104
|
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
|
-
};
|
|
35105
|
+
logger.info(`extendedHoldings after withdrawal ${extendedHoldings2?.availableForWithdrawal}`);
|
|
35106
|
+
await new Promise((resolve) => setTimeout(resolve, 5e3));
|
|
35107
|
+
const { calls, status } = await this.moveAssetsToVaultAllocator(params.amount, extendedAdapter);
|
|
35108
|
+
if (calls.length > 0 && status) {
|
|
35109
|
+
return this.createTransactionResult(calls, true, params, "WITHDRAWAL", params.cycleType);
|
|
35110
|
+
} else {
|
|
35111
|
+
return this.createTransactionResult([], true, params, "WITHDRAWAL", params.cycleType);
|
|
34287
35112
|
}
|
|
35113
|
+
} else if (withdrawalFromExtendedStatus && !withdrawalFromExtendedTxnHash) {
|
|
35114
|
+
logger.error("withdrawal from extended successful, but funds didn't get transferred to the wallet");
|
|
35115
|
+
return this.createTransactionResult([], true, params, "WITHDRAWAL", params.cycleType);
|
|
34288
35116
|
} else {
|
|
34289
35117
|
logger.error("withdrawal from extended failed");
|
|
34290
|
-
return
|
|
34291
|
-
calls: [],
|
|
34292
|
-
status: false
|
|
34293
|
-
};
|
|
35118
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
34294
35119
|
}
|
|
34295
35120
|
} else if (params.to === Protocols.VAULT.name && params.from === Protocols.VESU.name) {
|
|
35121
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
|
|
35122
|
+
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
35123
|
+
logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
35124
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35125
|
+
}
|
|
34296
35126
|
const vesuAmountInBTC = new Web3Number(
|
|
34297
|
-
params.amount.dividedBy(collateralPrice.price).
|
|
35127
|
+
params.amount.dividedBy(collateralPrice.price).toFixed(WBTC_TOKEN_DECIMALS),
|
|
34298
35128
|
collateralToken.decimals
|
|
34299
35129
|
);
|
|
34300
35130
|
const proofsInfo = vesuAdapter.getProofs(false, this.getMerkleTree());
|
|
@@ -34312,11 +35142,13 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34312
35142
|
await swapProofsInfo.callConstructor({ amount: vesuAmountInBTC })
|
|
34313
35143
|
);
|
|
34314
35144
|
calls.push(swapCall);
|
|
34315
|
-
return
|
|
34316
|
-
calls,
|
|
34317
|
-
status: true
|
|
34318
|
-
};
|
|
35145
|
+
return this.createTransactionResult(calls, true, params, "WITHDRAWAL", params.cycleType);
|
|
34319
35146
|
} else if (params.to === Protocols.EXTENDED.name && params.from === Protocols.VESU.name) {
|
|
35147
|
+
const isPriceDifferenceBetweenAvnuAndExtended = await this.checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, "close" /* CLOSE */);
|
|
35148
|
+
if (!isPriceDifferenceBetweenAvnuAndExtended) {
|
|
35149
|
+
logger.warn(`price difference between avnu and extended doesn't fit the range for close position, ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
35150
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
35151
|
+
}
|
|
34320
35152
|
const vesuAmountInBTC = new Web3Number(
|
|
34321
35153
|
params.amount.dividedBy(collateralPrice.price).toNumber(),
|
|
34322
35154
|
collateralToken.decimals
|
|
@@ -34346,131 +35178,32 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34346
35178
|
await proofsInfoDeposit.callConstructor({ amount: params.amount })
|
|
34347
35179
|
);
|
|
34348
35180
|
calls.push(callDeposit);
|
|
34349
|
-
return
|
|
34350
|
-
calls,
|
|
34351
|
-
status: true
|
|
34352
|
-
};
|
|
35181
|
+
return this.createTransactionResult(calls, true, params, "DEPOSIT", params.cycleType);
|
|
34353
35182
|
}
|
|
34354
|
-
|
|
34355
|
-
|
|
34356
|
-
status: false
|
|
34357
|
-
};
|
|
35183
|
+
logger.error(`Unsupported assets movement: ${params.from} to ${params.to}`);
|
|
35184
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
34358
35185
|
} catch (err) {
|
|
34359
35186
|
logger.error(`error moving assets: ${err}`);
|
|
34360
|
-
return
|
|
34361
|
-
calls: [],
|
|
34362
|
-
status: false
|
|
34363
|
-
};
|
|
35187
|
+
return this.createTransactionResult([], false, params, "NONE", params.cycleType);
|
|
34364
35188
|
}
|
|
34365
35189
|
}
|
|
34366
35190
|
async handleDeposit() {
|
|
34367
35191
|
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
|
-
};
|
|
35192
|
+
return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE", "INVESTMENT" /* INVESTMENT */);
|
|
34464
35193
|
} catch (err) {
|
|
34465
35194
|
logger.error(`error handling deposit: ${err}`);
|
|
34466
|
-
return {
|
|
34467
|
-
extendedAmountInBTC: new Web3Number(0, 0),
|
|
34468
|
-
calls: []
|
|
34469
|
-
};
|
|
34470
|
-
;
|
|
35195
|
+
return this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.VAULT.name, amount: new Web3Number(0, 0) }, "NONE", "INVESTMENT" /* INVESTMENT */);
|
|
34471
35196
|
}
|
|
34472
35197
|
}
|
|
34473
|
-
|
|
35198
|
+
/**
|
|
35199
|
+
* Check if the price difference between avnu and extended is within the acceptable range to enhance the position size or close the position
|
|
35200
|
+
* @param extendedAdapter - the extended adapter
|
|
35201
|
+
* @param vesuAdapter - the vesu adapter
|
|
35202
|
+
* @param avnuAdapter - the avnu adapter
|
|
35203
|
+
* @param positionType - the position type (open or close)
|
|
35204
|
+
* @returns true if the price difference is within the acceptable range, false otherwise
|
|
35205
|
+
*/
|
|
35206
|
+
async checkPriceDifferenceBetweenAvnuAndExtended(extendedAdapter, vesuAdapter, avnuAdapter, positionType) {
|
|
34474
35207
|
const {
|
|
34475
35208
|
ask,
|
|
34476
35209
|
bid
|
|
@@ -34482,13 +35215,30 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34482
35215
|
logger.error(`error getting btc price avnu: ${btcPriceAvnu}`);
|
|
34483
35216
|
return false;
|
|
34484
35217
|
}
|
|
34485
|
-
|
|
34486
|
-
|
|
34487
|
-
|
|
35218
|
+
logger.info(`price: ${price}`);
|
|
35219
|
+
logger.info(`btcPriceAvnu: ${btcPriceAvnu}`);
|
|
35220
|
+
const priceDifference = new Web3Number(price.minus(btcPriceAvnu).toFixed(2), 0);
|
|
35221
|
+
logger.info(`priceDifference: ${priceDifference}`);
|
|
35222
|
+
if (priceDifference.isNegative()) {
|
|
35223
|
+
return false;
|
|
35224
|
+
}
|
|
35225
|
+
if (positionType === "open" /* OPEN */) {
|
|
35226
|
+
logger.info(`price difference between avnu and extended for open position: ${priceDifference.toNumber()}, minimumExtendedPriceDifferenceForSwapOpen: ${avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen}`);
|
|
35227
|
+
const result = priceDifference.greaterThanOrEqualTo(avnuAdapter.config.minimumExtendedPriceDifferenceForSwapOpen);
|
|
35228
|
+
logger.info(`result: ${result}`);
|
|
35229
|
+
return result;
|
|
35230
|
+
} else {
|
|
35231
|
+
logger.info(`price difference between avnu and extended for close position: ${priceDifference.toNumber()}, maximumExtendedPriceDifferenceForSwapClosing: ${avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing}`);
|
|
35232
|
+
const result = priceDifference.lessThanOrEqualTo(avnuAdapter.config.maximumExtendedPriceDifferenceForSwapClosing);
|
|
35233
|
+
logger.info(`result: ${result}`);
|
|
35234
|
+
return result;
|
|
34488
35235
|
}
|
|
34489
|
-
logger.error(`price difference between avnu and extended doesn't fit the range, priceDifference: ${priceDifference}`);
|
|
34490
|
-
return false;
|
|
34491
35236
|
}
|
|
35237
|
+
/**
|
|
35238
|
+
* Handle the withdrawal of assets from the vault
|
|
35239
|
+
* @param amount - the amount to withdraw in USDC
|
|
35240
|
+
* @returns the calls to be executed and the status of the calls generated along with the metadata for the calls
|
|
35241
|
+
*/
|
|
34492
35242
|
async handleWithdraw(amount) {
|
|
34493
35243
|
try {
|
|
34494
35244
|
const usdcBalanceVaultAllocator = await this.getUnusedBalance();
|
|
@@ -34500,12 +35250,8 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34500
35250
|
const withdrawCall2 = await this.getBringLiquidityCall({
|
|
34501
35251
|
amount: usdcBalanceVaultAllocator.amount
|
|
34502
35252
|
});
|
|
34503
|
-
logger.info("withdraw call", withdrawCall2);
|
|
34504
35253
|
calls.push(withdrawCall2);
|
|
34505
|
-
return {
|
|
34506
|
-
calls,
|
|
34507
|
-
status: true
|
|
34508
|
-
};
|
|
35254
|
+
return [this.createTransactionResult(calls, true, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "WITHDRAWAL", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34509
35255
|
}
|
|
34510
35256
|
const vesuAdapter = await this.getVesuAdapter();
|
|
34511
35257
|
const extendedAdapter = await this.getExtendedAdapter();
|
|
@@ -34514,11 +35260,9 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34514
35260
|
logger.error(
|
|
34515
35261
|
`vesu or extended adapter not found: vesuAdapter=${vesuAdapter}, extendedAdapter=${extendedAdapter}`
|
|
34516
35262
|
);
|
|
34517
|
-
return {
|
|
34518
|
-
calls,
|
|
34519
|
-
status
|
|
34520
|
-
};
|
|
35263
|
+
return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34521
35264
|
}
|
|
35265
|
+
let transactionResults = [];
|
|
34522
35266
|
const { collateralTokenAmount } = await vesuAdapter.vesuAdapter.getAssetPrices();
|
|
34523
35267
|
const {
|
|
34524
35268
|
collateralPrice
|
|
@@ -34527,10 +35271,7 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34527
35271
|
if (!extendedPositon) {
|
|
34528
35272
|
status = false;
|
|
34529
35273
|
logger.error("error getting extended position", extendedPositon);
|
|
34530
|
-
return {
|
|
34531
|
-
calls,
|
|
34532
|
-
status
|
|
34533
|
-
};
|
|
35274
|
+
return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34534
35275
|
}
|
|
34535
35276
|
const amountDistributionForWithdrawal = await calculateAmountDistributionForWithdrawal(
|
|
34536
35277
|
usdcBalanceDifference,
|
|
@@ -34543,61 +35284,70 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34543
35284
|
logger.error(
|
|
34544
35285
|
`error calculating amount distribution for withdrawal: ${amountDistributionForWithdrawal}`
|
|
34545
35286
|
);
|
|
34546
|
-
return {
|
|
34547
|
-
calls,
|
|
34548
|
-
status
|
|
34549
|
-
};
|
|
35287
|
+
return [this.createTransactionResult(calls, status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34550
35288
|
}
|
|
34551
35289
|
const { vesu_amount, extended_amount } = amountDistributionForWithdrawal;
|
|
34552
35290
|
if (status && vesu_amount.greaterThan(0)) {
|
|
34553
|
-
const { calls: vesuCalls, status: vesuStatus } = await this.moveAssets(
|
|
35291
|
+
const { calls: vesuCalls, status: vesuStatus, transactionMetadata: vesuTransactionMetadata } = await this.moveAssets(
|
|
34554
35292
|
{
|
|
34555
35293
|
amount: vesu_amount,
|
|
34556
35294
|
from: Protocols.VESU.name,
|
|
34557
|
-
to: Protocols.VAULT.name
|
|
35295
|
+
to: Protocols.VAULT.name,
|
|
35296
|
+
cycleType: "WITHDRAWAL" /* WITHDRAWAL */
|
|
34558
35297
|
},
|
|
34559
35298
|
extendedAdapter,
|
|
34560
35299
|
vesuAdapter
|
|
34561
35300
|
);
|
|
34562
35301
|
status = vesuStatus;
|
|
34563
|
-
|
|
35302
|
+
transactionResults.push({
|
|
35303
|
+
status: vesuStatus,
|
|
35304
|
+
calls: vesuCalls,
|
|
35305
|
+
transactionMetadata: vesuTransactionMetadata
|
|
35306
|
+
});
|
|
34564
35307
|
}
|
|
34565
35308
|
if (status && extended_amount.greaterThan(0)) {
|
|
34566
|
-
const { calls: extendedCalls, status: extendedStatus } = await this.moveAssets(
|
|
35309
|
+
const { calls: extendedCalls, status: extendedStatus, transactionMetadata: extendedTransactionMetadata } = await this.moveAssets(
|
|
34567
35310
|
{
|
|
34568
35311
|
amount: extended_amount,
|
|
34569
35312
|
from: Protocols.EXTENDED.name,
|
|
34570
|
-
to: Protocols.VAULT.name
|
|
35313
|
+
to: Protocols.VAULT.name,
|
|
35314
|
+
cycleType: "WITHDRAWAL" /* WITHDRAWAL */
|
|
34571
35315
|
},
|
|
34572
35316
|
extendedAdapter,
|
|
34573
35317
|
vesuAdapter
|
|
34574
35318
|
);
|
|
34575
35319
|
status = extendedStatus;
|
|
34576
35320
|
if (status) {
|
|
34577
|
-
|
|
35321
|
+
transactionResults.push({
|
|
35322
|
+
status: extendedStatus,
|
|
35323
|
+
calls: extendedCalls,
|
|
35324
|
+
transactionMetadata: extendedTransactionMetadata
|
|
35325
|
+
});
|
|
34578
35326
|
} else {
|
|
34579
35327
|
logger.error("error moving assets to vault: extendedStatus: ${extendedStatus}");
|
|
34580
|
-
return {
|
|
34581
|
-
calls: [],
|
|
34582
|
-
status
|
|
34583
|
-
};
|
|
35328
|
+
return [this.createTransactionResult([], status, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34584
35329
|
}
|
|
34585
35330
|
}
|
|
34586
35331
|
const withdrawCall = await this.getBringLiquidityCall({
|
|
34587
35332
|
amount
|
|
34588
35333
|
});
|
|
34589
35334
|
logger.info("withdraw call", withdrawCall);
|
|
34590
|
-
|
|
34591
|
-
|
|
34592
|
-
calls,
|
|
34593
|
-
|
|
34594
|
-
|
|
35335
|
+
transactionResults.push({
|
|
35336
|
+
status,
|
|
35337
|
+
calls: [withdrawCall],
|
|
35338
|
+
transactionMetadata: {
|
|
35339
|
+
protocolFrom: Protocols.VAULT.name,
|
|
35340
|
+
protocolTo: Protocols.NONE.name,
|
|
35341
|
+
transactionType: "WITHDRAWAL",
|
|
35342
|
+
usdAmount: amount.toFixed(),
|
|
35343
|
+
status: "PENDING",
|
|
35344
|
+
cycleType: "WITHDRAWAL" /* WITHDRAWAL */
|
|
35345
|
+
}
|
|
35346
|
+
});
|
|
35347
|
+
return transactionResults;
|
|
34595
35348
|
} catch (err) {
|
|
34596
35349
|
logger.error(`error handling withdrawal: ${err}`);
|
|
34597
|
-
return {
|
|
34598
|
-
calls: [],
|
|
34599
|
-
status: false
|
|
34600
|
-
};
|
|
35350
|
+
return [this.createTransactionResult([], false, { from: Protocols.VAULT.name, to: Protocols.NONE.name, amount }, "NONE", "WITHDRAWAL" /* WITHDRAWAL */)];
|
|
34601
35351
|
}
|
|
34602
35352
|
}
|
|
34603
35353
|
async getAUM() {
|
|
@@ -34644,8 +35394,182 @@ var VesuExtendedMultiplierStrategy = class _VesuExtendedMultiplierStrategy exten
|
|
|
34644
35394
|
splits: [realAUM, estimatedAUMDelta]
|
|
34645
35395
|
};
|
|
34646
35396
|
}
|
|
35397
|
+
async processTransactionDataFromSDK(txnData) {
|
|
35398
|
+
try {
|
|
35399
|
+
const txnsToBeExecuted = txnData.filter((txn) => {
|
|
35400
|
+
return txn.transactionMetadata.transactionType !== "NONE" && txn.transactionMetadata.protocolFrom !== "" && txn.transactionMetadata.protocolTo !== "";
|
|
35401
|
+
});
|
|
35402
|
+
const callsToBeExecutedFinal = txnsToBeExecuted.flatMap((txn) => txn.calls);
|
|
35403
|
+
const txnMetadata = txnsToBeExecuted.map((txn) => txn.transactionMetadata);
|
|
35404
|
+
return { callsToBeExecutedFinal, txnMetadata };
|
|
35405
|
+
} catch (err) {
|
|
35406
|
+
logger.error(`error processing transaction data from SDK: ${err}`);
|
|
35407
|
+
return null;
|
|
35408
|
+
}
|
|
35409
|
+
}
|
|
35410
|
+
async processTransactionMetadata(txnMetadata, extendedIntentFulfilled) {
|
|
35411
|
+
try {
|
|
35412
|
+
const txnMetadataNew = txnMetadata.map((txn) => {
|
|
35413
|
+
const isExtendedProtocol = txn.protocolFrom === Protocols.EXTENDED.name || txn.protocolTo === Protocols.EXTENDED.name;
|
|
35414
|
+
if (isExtendedProtocol) {
|
|
35415
|
+
txn.status = extendedIntentFulfilled ? "COMPLETED" : "PENDING";
|
|
35416
|
+
} else {
|
|
35417
|
+
txn.status = "COMPLETED";
|
|
35418
|
+
}
|
|
35419
|
+
return txn;
|
|
35420
|
+
});
|
|
35421
|
+
return txnMetadataNew;
|
|
35422
|
+
} catch (err) {
|
|
35423
|
+
logger.error(`error processing transaction data from SDK: ${err}`);
|
|
35424
|
+
return null;
|
|
35425
|
+
}
|
|
35426
|
+
}
|
|
35427
|
+
async getMaxBorrowableAmount() {
|
|
35428
|
+
const vesuAdapter = await this.getVesuAdapter();
|
|
35429
|
+
const extendedAdapter = await this.getExtendedAdapter();
|
|
35430
|
+
if (!vesuAdapter || !extendedAdapter) {
|
|
35431
|
+
return new Web3Number(0, 0);
|
|
35432
|
+
}
|
|
35433
|
+
const extendedFundingRate = new Web3Number((await extendedAdapter.getNetAPY()).toFixed(4), 0);
|
|
35434
|
+
const extendedPositions = await extendedAdapter.getAllOpenPositions();
|
|
35435
|
+
if (!extendedPositions || extendedPositions.length === 0) {
|
|
35436
|
+
logger.info(`no extended positions found`);
|
|
35437
|
+
return new Web3Number(0, 0);
|
|
35438
|
+
}
|
|
35439
|
+
const extendePositionSizeUSD = new Web3Number(extendedPositions[0].value || 0, 0);
|
|
35440
|
+
const vesuPositions = await vesuAdapter.getPositions();
|
|
35441
|
+
const vesuSupplyApy = vesuPositions[0].apy.apy;
|
|
35442
|
+
const vesuCollateralSizeUSD = new Web3Number(vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
|
|
35443
|
+
const vesuDebtSizeUSD = new Web3Number(vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
|
|
35444
|
+
const num1 = extendePositionSizeUSD.multipliedBy(extendedFundingRate);
|
|
35445
|
+
const num22 = vesuCollateralSizeUSD.multipliedBy(vesuSupplyApy);
|
|
35446
|
+
const num32 = vesuDebtSizeUSD.abs();
|
|
35447
|
+
const maxBorrowApy = num1.plus(num22).minus(0.1).dividedBy(num32);
|
|
35448
|
+
const vesuMaxBorrowableAmount = await vesuAdapter.vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxBorrowApy.toNumber());
|
|
35449
|
+
return new Web3Number(vesuMaxBorrowableAmount.toFixed(USDC_TOKEN_DECIMALS), USDC_TOKEN_DECIMALS);
|
|
35450
|
+
}
|
|
35451
|
+
async getVesuHealthFactors() {
|
|
35452
|
+
const vesuAdapter = await this.getVesuAdapter();
|
|
35453
|
+
const extendedAdapter = await this.getExtendedAdapter();
|
|
35454
|
+
if (!vesuAdapter || !extendedAdapter) {
|
|
35455
|
+
return [0, 0];
|
|
35456
|
+
}
|
|
35457
|
+
const vesuPositions = await vesuAdapter.getPositions();
|
|
35458
|
+
const vesuCollateralSizeUSD = new Web3Number(vesuPositions[0].usdValue.toFixed(USDC_TOKEN_DECIMALS), 0);
|
|
35459
|
+
const vesuDebtSizeUSD = new Web3Number(vesuPositions[1].usdValue.toFixed(USDC_TOKEN_DECIMALS), 0);
|
|
35460
|
+
const actualLtv = vesuDebtSizeUSD.dividedBy(vesuCollateralSizeUSD).abs();
|
|
35461
|
+
logger.info(`actualLtv: ${actualLtv.toNumber()}`);
|
|
35462
|
+
const maxLtv = new Web3Number(await vesuAdapter.vesuAdapter.getLTVConfig(this.config), 4);
|
|
35463
|
+
const healthFactor = new Web3Number(maxLtv.dividedBy(actualLtv).toFixed(4), 4);
|
|
35464
|
+
logger.info(`healthFactor: ${healthFactor.toNumber()}`);
|
|
35465
|
+
const extendedBalance = await extendedAdapter.getExtendedDepositAmount();
|
|
35466
|
+
if (!extendedBalance) {
|
|
35467
|
+
return [0, 0];
|
|
35468
|
+
}
|
|
35469
|
+
const extendedLeverage = new Web3Number((Number(extendedBalance.marginRatio) * 100).toFixed(4), 4);
|
|
35470
|
+
logger.info(`extendedLeverage: ${extendedLeverage.toNumber()}`);
|
|
35471
|
+
return [healthFactor.toNumber(), extendedLeverage.toNumber()];
|
|
35472
|
+
}
|
|
35473
|
+
async netAPY() {
|
|
35474
|
+
const allPositions = [];
|
|
35475
|
+
for (let adapter of this.metadata.additionalInfo.adapters) {
|
|
35476
|
+
if (adapter.adapter.name !== ExtendedAdapter.name) {
|
|
35477
|
+
let positions = await adapter.adapter.getPositions();
|
|
35478
|
+
if (positions.length > 0) {
|
|
35479
|
+
allPositions.push(...positions);
|
|
35480
|
+
}
|
|
35481
|
+
}
|
|
35482
|
+
}
|
|
35483
|
+
const extendedAdapter = await this.getExtendedAdapter();
|
|
35484
|
+
if (!extendedAdapter) {
|
|
35485
|
+
return {
|
|
35486
|
+
net: 0,
|
|
35487
|
+
splits: []
|
|
35488
|
+
};
|
|
35489
|
+
}
|
|
35490
|
+
let vesuPositions = allPositions.filter((item) => item.protocol === Protocols.VESU);
|
|
35491
|
+
vesuPositions.map((item) => {
|
|
35492
|
+
item.apy.apy = item.apy.apy * 0.1;
|
|
35493
|
+
});
|
|
35494
|
+
const extendedPositions = await extendedAdapter.getAllOpenPositions();
|
|
35495
|
+
const usdcToken = Global.getDefaultTokens().find((token) => token.symbol === "USDC");
|
|
35496
|
+
if (!extendedPositions || !usdcToken) {
|
|
35497
|
+
return {
|
|
35498
|
+
net: 0,
|
|
35499
|
+
splits: []
|
|
35500
|
+
};
|
|
35501
|
+
}
|
|
35502
|
+
const extendedPosition = extendedPositions[0] || 0;
|
|
35503
|
+
const extendedEquity = (await extendedAdapter.getExtendedDepositAmount())?.equity || 0;
|
|
35504
|
+
const extendedApy = await extendedAdapter.getNetAPY();
|
|
35505
|
+
const totalHoldingsUSDValue = allPositions.reduce((acc, curr) => acc + curr.usdValue, 0) + Number(extendedEquity);
|
|
35506
|
+
console.log(totalHoldingsUSDValue);
|
|
35507
|
+
const extendedPositionSizeMultipliedByApy = Number(extendedPosition.value) * extendedApy;
|
|
35508
|
+
let weightedAPYs = allPositions.reduce((acc, curr) => acc + curr.apy.apy * curr.usdValue, 0) + extendedPositionSizeMultipliedByApy;
|
|
35509
|
+
console.log(weightedAPYs);
|
|
35510
|
+
const netAPY = weightedAPYs / totalHoldingsUSDValue;
|
|
35511
|
+
console.log(netAPY);
|
|
35512
|
+
allPositions.push({
|
|
35513
|
+
tokenInfo: usdcToken,
|
|
35514
|
+
amount: new Web3Number(extendedPosition.size, 0),
|
|
35515
|
+
usdValue: Number(extendedEquity),
|
|
35516
|
+
apy: { apy: extendedApy, type: "base" /* BASE */ },
|
|
35517
|
+
remarks: "finalised" /* FINALISED */,
|
|
35518
|
+
protocol: Protocols.EXTENDED
|
|
35519
|
+
});
|
|
35520
|
+
return {
|
|
35521
|
+
net: netAPY,
|
|
35522
|
+
splits: allPositions.map((p) => ({ apy: p.apy.apy, id: p.remarks ?? "" }))
|
|
35523
|
+
};
|
|
35524
|
+
}
|
|
35525
|
+
async getWalletHoldings() {
|
|
35526
|
+
const usdceToken = Global.getDefaultTokens().find((token) => token.symbol === "USDCe");
|
|
35527
|
+
const wbtcToken = Global.getDefaultTokens().find((token) => token.symbol === "WBTC");
|
|
35528
|
+
const usdcToken = Global.getDefaultTokens().find((token) => token.symbol === "USDC");
|
|
35529
|
+
if (!usdceToken || !wbtcToken || !usdcToken) {
|
|
35530
|
+
return [];
|
|
35531
|
+
}
|
|
35532
|
+
const walletAddress = this.metadata.additionalInfo.walletAddress;
|
|
35533
|
+
const usdceWalletBalance = await new ERC20(this.config).balanceOf(
|
|
35534
|
+
usdceToken.address,
|
|
35535
|
+
walletAddress,
|
|
35536
|
+
usdceToken.decimals
|
|
35537
|
+
);
|
|
35538
|
+
const usdcWalletBalance = await new ERC20(this.config).balanceOf(
|
|
35539
|
+
usdcToken.address,
|
|
35540
|
+
walletAddress,
|
|
35541
|
+
usdcToken.decimals
|
|
35542
|
+
);
|
|
35543
|
+
const wbtcWalletBalance = await new ERC20(this.config).balanceOf(
|
|
35544
|
+
wbtcToken.address,
|
|
35545
|
+
walletAddress,
|
|
35546
|
+
wbtcToken.decimals
|
|
35547
|
+
);
|
|
35548
|
+
const price = await this.pricer.getPrice(usdceToken.symbol);
|
|
35549
|
+
const wbtcPrice = await this.pricer.getPrice(wbtcToken.symbol);
|
|
35550
|
+
const usdceUsdValue = Number(usdceWalletBalance.toFixed(usdceToken.decimals)) * price.price;
|
|
35551
|
+
const usdcUsdValue = Number(usdcWalletBalance.toFixed(usdcToken.decimals)) * price.price;
|
|
35552
|
+
const wbtcUsdValue = Number(wbtcWalletBalance.toFixed(wbtcToken.decimals)) * wbtcPrice.price;
|
|
35553
|
+
return [
|
|
35554
|
+
{
|
|
35555
|
+
tokenInfo: usdceToken,
|
|
35556
|
+
amount: usdceWalletBalance,
|
|
35557
|
+
usdValue: usdceUsdValue
|
|
35558
|
+
},
|
|
35559
|
+
{
|
|
35560
|
+
tokenInfo: usdcToken,
|
|
35561
|
+
amount: usdcWalletBalance,
|
|
35562
|
+
usdValue: usdcUsdValue
|
|
35563
|
+
},
|
|
35564
|
+
{
|
|
35565
|
+
tokenInfo: wbtcToken,
|
|
35566
|
+
amount: wbtcWalletBalance,
|
|
35567
|
+
usdValue: wbtcUsdValue
|
|
35568
|
+
}
|
|
35569
|
+
];
|
|
35570
|
+
}
|
|
34647
35571
|
};
|
|
34648
|
-
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1,
|
|
35572
|
+
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
|
|
34649
35573
|
vaultSettings.leafAdapters = [];
|
|
34650
35574
|
const wbtcToken = Global.getDefaultTokens().find(
|
|
34651
35575
|
(token) => token.symbol === lstSymbol
|
|
@@ -34669,7 +35593,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
|
|
|
34669
35593
|
...baseAdapterConfig,
|
|
34670
35594
|
avnuContract: AVNU_MIDDLEWARE,
|
|
34671
35595
|
slippage: 0.01,
|
|
34672
|
-
baseUrl: AVNU_QUOTE_URL
|
|
35596
|
+
baseUrl: AVNU_QUOTE_URL,
|
|
35597
|
+
minimumExtendedPriceDifferenceForSwapOpen,
|
|
35598
|
+
maximumExtendedPriceDifferenceForSwapClosing
|
|
34673
35599
|
});
|
|
34674
35600
|
const extendedAdapter = new ExtendedAdapter({
|
|
34675
35601
|
...baseAdapterConfig,
|
|
@@ -34678,14 +35604,17 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
|
|
|
34678
35604
|
],
|
|
34679
35605
|
vaultIdExtended,
|
|
34680
35606
|
extendedContract: EXTENDED_CONTRACT,
|
|
34681
|
-
|
|
34682
|
-
|
|
35607
|
+
extendedBackendWriteUrl,
|
|
35608
|
+
extendedBackendReadUrl,
|
|
34683
35609
|
extendedTimeout: 3e4,
|
|
34684
35610
|
extendedRetries: 3,
|
|
34685
35611
|
extendedBaseUrl: "https://api.starknet.extended.exchange",
|
|
34686
35612
|
extendedMarketName: "BTC-USD",
|
|
34687
35613
|
extendedPrecision: 5,
|
|
34688
|
-
avnuAdapter
|
|
35614
|
+
avnuAdapter,
|
|
35615
|
+
retryDelayForOrderStatus: minimumExtendedRetriesDelayForOrderStatus ?? 3e3,
|
|
35616
|
+
minimumExtendedMovementAmount: minimumExtendedMovementAmount ?? 5
|
|
35617
|
+
//5 usdcs
|
|
34689
35618
|
});
|
|
34690
35619
|
const vesuMultiplyAdapter = new VesuMultiplyAdapter({
|
|
34691
35620
|
poolId: pool1,
|
|
@@ -34698,7 +35627,9 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1, e
|
|
|
34698
35627
|
supportedPositions: [
|
|
34699
35628
|
{ asset: wbtcToken, isDebt: false },
|
|
34700
35629
|
{ asset: usdcToken, isDebt: true }
|
|
34701
|
-
]
|
|
35630
|
+
],
|
|
35631
|
+
minimumVesuMovementAmount: minimumVesuMovementAmount ?? 5
|
|
35632
|
+
//5 usdc
|
|
34702
35633
|
});
|
|
34703
35634
|
const unusedBalanceAdapter = new UnusedBalanceAdapter({
|
|
34704
35635
|
...baseAdapterConfig
|
|
@@ -34794,11 +35725,11 @@ function VaultDescription2(lstSymbol, underlyingSymbol) {
|
|
|
34794
35725
|
] });
|
|
34795
35726
|
}
|
|
34796
35727
|
var re7UsdcPrimeDevansh = {
|
|
34797
|
-
vaultAddress: ContractAddr.from("
|
|
34798
|
-
manager: ContractAddr.from("
|
|
34799
|
-
vaultAllocator: ContractAddr.from("
|
|
34800
|
-
redeemRequestNFT: ContractAddr.from("
|
|
34801
|
-
aumOracle: ContractAddr.from("
|
|
35728
|
+
vaultAddress: ContractAddr.from("0x058905be22d6a81792df79425dc9641cf3e1b77f36748631b7d7e5d713a32b55"),
|
|
35729
|
+
manager: ContractAddr.from("0x02648d703783feb2d967cf0520314cb5aa800d69a9426f3e3b317395af44de16"),
|
|
35730
|
+
vaultAllocator: ContractAddr.from("0x07d533c838eab6a4d854dd3aea96a55993fccd35821921970d00bde946b63b6f"),
|
|
35731
|
+
redeemRequestNFT: ContractAddr.from("0x01ef91f08fb99729c00f82fc6e0ece37917bcc43952596c19996259dc8adbbba"),
|
|
35732
|
+
aumOracle: ContractAddr.from("0x030b6acfec162f5d6e72b8a4d2798aedce78fb39de78a8f549f7cd277ae8bc8d"),
|
|
34802
35733
|
leafAdapters: [],
|
|
34803
35734
|
adapters: [],
|
|
34804
35735
|
targetHealthFactor: 1.4,
|
|
@@ -34811,14 +35742,15 @@ var re7UsdcPrimeDevansh = {
|
|
|
34811
35742
|
Global.getDefaultTokens().find((token) => token.symbol === "WBTC").decimals
|
|
34812
35743
|
),
|
|
34813
35744
|
borrowable_assets: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
|
|
34814
|
-
minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP
|
|
35745
|
+
minimumWBTCDifferenceForAvnuSwap: MINIMUM_WBTC_DIFFERENCE_FOR_AVNU_SWAP,
|
|
35746
|
+
walletAddress: WALLET_ADDRESS
|
|
34815
35747
|
};
|
|
34816
|
-
var VesuExtendedTestStrategies = (
|
|
35748
|
+
var VesuExtendedTestStrategies = (extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) => {
|
|
34817
35749
|
return [
|
|
34818
|
-
getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false,
|
|
35750
|
+
getStrategySettingsVesuExtended("WBTC", "USDC", re7UsdcPrimeDevansh, false, false, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing)
|
|
34819
35751
|
];
|
|
34820
35752
|
};
|
|
34821
|
-
function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST,
|
|
35753
|
+
function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses, isPreview = false, isLST, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing) {
|
|
34822
35754
|
return {
|
|
34823
35755
|
name: `Extended Test ${underlyingSymbol}`,
|
|
34824
35756
|
description: getDescription2(lstSymbol, underlyingSymbol),
|
|
@@ -34826,7 +35758,7 @@ function getStrategySettingsVesuExtended(lstSymbol, underlyingSymbol, addresses,
|
|
|
34826
35758
|
launchBlock: 0,
|
|
34827
35759
|
type: "Other",
|
|
34828
35760
|
depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol)],
|
|
34829
|
-
additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime,
|
|
35761
|
+
additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, VesuPools.Re7USDCPrime, extendedBackendReadUrl, extendedBackendWriteUrl, vaultIdExtended, minimumExtendedMovementAmount, minimumVesuMovementAmount, minimumExtendedRetriesDelayForOrderStatus, minimumExtendedPriceDifferenceForSwapOpen, maximumExtendedPriceDifferenceForSwapClosing),
|
|
34830
35762
|
risk: {
|
|
34831
35763
|
riskFactor: _riskFactor3,
|
|
34832
35764
|
netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
|
|
@@ -39070,11 +40002,13 @@ var deployer_default = Deployer;
|
|
|
39070
40002
|
AssetOperationStatus,
|
|
39071
40003
|
AssetOperationType,
|
|
39072
40004
|
AutoCompounderSTRK,
|
|
40005
|
+
AvnuAdapter,
|
|
39073
40006
|
AvnuWrapper,
|
|
39074
40007
|
BaseAdapter,
|
|
39075
40008
|
BaseStrategy,
|
|
39076
40009
|
CommonAdapter,
|
|
39077
40010
|
ContractAddr,
|
|
40011
|
+
CycleType,
|
|
39078
40012
|
Deployer,
|
|
39079
40013
|
ERC20,
|
|
39080
40014
|
EXTENDED_CONTRACT,
|
|
@@ -39103,6 +40037,7 @@ var deployer_default = Deployer;
|
|
|
39103
40037
|
PRICE_ROUTER,
|
|
39104
40038
|
PasswordJsonCryptoUtil,
|
|
39105
40039
|
PositionSide,
|
|
40040
|
+
PositionTypeAvnuExtended,
|
|
39106
40041
|
Pragma,
|
|
39107
40042
|
Pricer,
|
|
39108
40043
|
PricerBase,
|
|
@@ -39152,6 +40087,7 @@ var deployer_default = Deployer;
|
|
|
39152
40087
|
calculateExtendedLevergae,
|
|
39153
40088
|
calculateVesUPositionSizeGivenExtended,
|
|
39154
40089
|
calculateVesuLeverage,
|
|
40090
|
+
calculateWBTCAmountToMaintainLTV,
|
|
39155
40091
|
extensionMap,
|
|
39156
40092
|
getAPIUsingHeadlessBrowser,
|
|
39157
40093
|
getContractDetails,
|