@strkfarm/sdk 1.0.56 → 1.0.57
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 +260 -83
- package/dist/index.browser.mjs +255 -66
- package/dist/index.d.ts +55 -9
- package/dist/index.js +255 -69
- package/dist/index.mjs +255 -69
- package/package.json +1 -1
- package/src/notifs/telegram.ts +0 -2
- package/src/strategies/base-strategy.ts +3 -23
- package/src/strategies/sensei.ts +13 -6
- package/src/strategies/universal-adapters/baseAdapter.ts +2 -1
- package/src/strategies/universal-adapters/vesu-adapter.ts +80 -10
- package/src/strategies/universal-strategy.ts +183 -31
- package/src/utils/cacheClass.ts +29 -0
- package/src/utils/oz-merkle.ts +0 -9
package/dist/index.browser.mjs
CHANGED
|
@@ -1937,7 +1937,6 @@ import { toHex } from "@ericnordelo/strk-merkle-tree/dist/bytes";
|
|
|
1937
1937
|
import { processMultiProof, processProof } from "@ericnordelo/strk-merkle-tree/dist/core";
|
|
1938
1938
|
import { standardLeafHash } from "@ericnordelo/strk-merkle-tree/dist/hashes";
|
|
1939
1939
|
import { MerkleTreeImpl } from "@ericnordelo/strk-merkle-tree/dist/merkletree";
|
|
1940
|
-
import { validateArgument } from "@ericnordelo/strk-merkle-tree/src/utils/errors";
|
|
1941
1940
|
import { num as num2 } from "starknet";
|
|
1942
1941
|
|
|
1943
1942
|
// ../node_modules/@noble/hashes/esm/_assert.js
|
|
@@ -3994,13 +3993,6 @@ var StandardMerkleTree = class _StandardMerkleTree extends MerkleTreeImpl {
|
|
|
3994
3993
|
});
|
|
3995
3994
|
return new _StandardMerkleTree(tree, indexedValues, leafEncoding);
|
|
3996
3995
|
}
|
|
3997
|
-
static load(data) {
|
|
3998
|
-
validateArgument(data.format === "standard-v1", `Unknown format '${data.format}'`);
|
|
3999
|
-
validateArgument(data.leafEncoding !== void 0, "Expected leaf encoding");
|
|
4000
|
-
const tree = new _StandardMerkleTree(data.tree, data.values, data.leafEncoding);
|
|
4001
|
-
tree.validate();
|
|
4002
|
-
return tree;
|
|
4003
|
-
}
|
|
4004
3996
|
static verify(root, leafEncoding, leaf, proof) {
|
|
4005
3997
|
return toHex(root) === processProof(standardLeafHash(leafEncoding, leaf), proof);
|
|
4006
3998
|
}
|
|
@@ -5758,23 +5750,10 @@ var vesu_rebalance_abi_default = [
|
|
|
5758
5750
|
}
|
|
5759
5751
|
];
|
|
5760
5752
|
|
|
5761
|
-
// src/
|
|
5762
|
-
var
|
|
5763
|
-
constructor(
|
|
5753
|
+
// src/utils/cacheClass.ts
|
|
5754
|
+
var CacheClass = class {
|
|
5755
|
+
constructor() {
|
|
5764
5756
|
this.cache = /* @__PURE__ */ new Map();
|
|
5765
|
-
this.config = config;
|
|
5766
|
-
}
|
|
5767
|
-
async getUserTVL(user) {
|
|
5768
|
-
throw new Error("Not implemented");
|
|
5769
|
-
}
|
|
5770
|
-
async getTVL() {
|
|
5771
|
-
throw new Error("Not implemented");
|
|
5772
|
-
}
|
|
5773
|
-
async depositCall(amountInfo, receiver) {
|
|
5774
|
-
throw new Error("Not implemented");
|
|
5775
|
-
}
|
|
5776
|
-
async withdrawCall(amountInfo, receiver, owner) {
|
|
5777
|
-
throw new Error("Not implemented");
|
|
5778
5757
|
}
|
|
5779
5758
|
setCache(key, data, ttl = 6e4) {
|
|
5780
5759
|
const timestamp = Date.now();
|
|
@@ -5795,6 +5774,27 @@ var BaseStrategy = class {
|
|
|
5795
5774
|
}
|
|
5796
5775
|
};
|
|
5797
5776
|
|
|
5777
|
+
// src/strategies/base-strategy.ts
|
|
5778
|
+
var BaseStrategy = class extends CacheClass {
|
|
5779
|
+
constructor(config) {
|
|
5780
|
+
super();
|
|
5781
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
5782
|
+
this.config = config;
|
|
5783
|
+
}
|
|
5784
|
+
async getUserTVL(user) {
|
|
5785
|
+
throw new Error("Not implemented");
|
|
5786
|
+
}
|
|
5787
|
+
async getTVL() {
|
|
5788
|
+
throw new Error("Not implemented");
|
|
5789
|
+
}
|
|
5790
|
+
async depositCall(amountInfo, receiver) {
|
|
5791
|
+
throw new Error("Not implemented");
|
|
5792
|
+
}
|
|
5793
|
+
async withdrawCall(amountInfo, receiver, owner) {
|
|
5794
|
+
throw new Error("Not implemented");
|
|
5795
|
+
}
|
|
5796
|
+
};
|
|
5797
|
+
|
|
5798
5798
|
// src/node/headless.browser.ts
|
|
5799
5799
|
import axios5 from "axios";
|
|
5800
5800
|
async function getAPIUsingHeadlessBrowser(url) {
|
|
@@ -20268,9 +20268,8 @@ var SenseiVault = class extends BaseStrategy {
|
|
|
20268
20268
|
}
|
|
20269
20269
|
async getPositionInfo() {
|
|
20270
20270
|
const CACHE_KEY = "positionInfo";
|
|
20271
|
-
|
|
20272
|
-
|
|
20273
|
-
}
|
|
20271
|
+
const existingCacheData = this.getCache(CACHE_KEY);
|
|
20272
|
+
if (existingCacheData) return existingCacheData;
|
|
20274
20273
|
const resp = await fetch(
|
|
20275
20274
|
`${getTrovesEndpoint()}/vesu/positions?walletAddress=${this.address.address}`
|
|
20276
20275
|
);
|
|
@@ -20314,9 +20313,8 @@ var SenseiVault = class extends BaseStrategy {
|
|
|
20314
20313
|
}
|
|
20315
20314
|
async getSecondaryTokenPriceRelativeToMain(retry = 0) {
|
|
20316
20315
|
const CACHE_KEY = "xSTRKPrice";
|
|
20317
|
-
|
|
20318
|
-
|
|
20319
|
-
}
|
|
20316
|
+
const existingCacheData = this.getCache(CACHE_KEY);
|
|
20317
|
+
if (existingCacheData) return existingCacheData;
|
|
20320
20318
|
const params = {
|
|
20321
20319
|
sellTokenAddress: this.metadata.additionalInfo.secondaryToken.address.address,
|
|
20322
20320
|
buyTokenAddress: this.metadata.additionalInfo.mainToken.address.address,
|
|
@@ -20470,7 +20468,7 @@ function toBigInt(value) {
|
|
|
20470
20468
|
}
|
|
20471
20469
|
|
|
20472
20470
|
// src/strategies/universal-adapters/baseAdapter.ts
|
|
20473
|
-
var BaseAdapter = class {
|
|
20471
|
+
var BaseAdapter = class extends CacheClass {
|
|
20474
20472
|
constructSimpleLeafData(params) {
|
|
20475
20473
|
const { id, target, method, packedArguments } = params;
|
|
20476
20474
|
return {
|
|
@@ -22845,7 +22843,6 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
22845
22843
|
constructor(config) {
|
|
22846
22844
|
super();
|
|
22847
22845
|
this.VESU_SINGLETON = ContractAddr.from("0x000d8d6dfec4d33bfb6895de9f3852143a17c6f92fd2a21da3d6924d34870160");
|
|
22848
|
-
this.cache = {};
|
|
22849
22846
|
this.getModifyPosition = () => {
|
|
22850
22847
|
const positionData = [0n];
|
|
22851
22848
|
const packedArguments = [
|
|
@@ -22874,17 +22871,19 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
22874
22871
|
denomination: this.formatAmountDenominationEnum(params.collateralAmount.denomination),
|
|
22875
22872
|
value: {
|
|
22876
22873
|
abs: uint2567.bnToUint256(params.collateralAmount.value.abs.toWei()),
|
|
22877
|
-
is_negative: params.collateralAmount.value.is_negative
|
|
22874
|
+
is_negative: params.collateralAmount.value.abs.isZero() ? false : params.collateralAmount.value.is_negative
|
|
22878
22875
|
}
|
|
22879
22876
|
};
|
|
22877
|
+
logger.verbose(`VesuAdapter::ConstructingModify::Collateral::${JSON.stringify(_collateral)}`);
|
|
22880
22878
|
const _debt = {
|
|
22881
22879
|
amount_type: this.formatAmountTypeEnum(params.debtAmount.amount_type),
|
|
22882
22880
|
denomination: this.formatAmountDenominationEnum(params.debtAmount.denomination),
|
|
22883
22881
|
value: {
|
|
22884
22882
|
abs: uint2567.bnToUint256(params.debtAmount.value.abs.toWei()),
|
|
22885
|
-
is_negative: params.debtAmount.value.is_negative
|
|
22883
|
+
is_negative: params.debtAmount.value.abs.isZero() ? false : params.debtAmount.value.is_negative
|
|
22886
22884
|
}
|
|
22887
22885
|
};
|
|
22886
|
+
logger.verbose(`VesuAdapter::ConstructingModify::Debt::${JSON.stringify(_debt)}`);
|
|
22888
22887
|
const singletonContract = new Contract8(vesu_singleton_abi_default, this.VESU_SINGLETON.toString(), new RpcProvider4({ nodeUrl: "" }));
|
|
22889
22888
|
const call = singletonContract.populate("modify_position", {
|
|
22890
22889
|
params: {
|
|
@@ -22953,20 +22952,22 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
22953
22952
|
}
|
|
22954
22953
|
async getLTVConfig(config) {
|
|
22955
22954
|
const CACHE_KEY = "ltv_config";
|
|
22956
|
-
|
|
22957
|
-
|
|
22955
|
+
const cacheData = this.getCache(CACHE_KEY);
|
|
22956
|
+
if (cacheData) {
|
|
22957
|
+
return cacheData;
|
|
22958
22958
|
}
|
|
22959
22959
|
const output2 = await this.getVesuSingletonContract(config).call("ltv_config", [this.config.poolId.address, this.config.collateral.address.address, this.config.debt.address.address]);
|
|
22960
|
-
this.
|
|
22961
|
-
return this.
|
|
22960
|
+
this.setCache(CACHE_KEY, Number(output2.max_ltv) / 1e18, 3e5);
|
|
22961
|
+
return this.getCache(CACHE_KEY);
|
|
22962
22962
|
}
|
|
22963
22963
|
async getPositions(config) {
|
|
22964
22964
|
if (!this.pricer) {
|
|
22965
22965
|
throw new Error("Pricer is not initialized");
|
|
22966
22966
|
}
|
|
22967
22967
|
const CACHE_KEY = "positions";
|
|
22968
|
-
|
|
22969
|
-
|
|
22968
|
+
const cacheData = this.getCache(CACHE_KEY);
|
|
22969
|
+
if (cacheData) {
|
|
22970
|
+
return cacheData;
|
|
22970
22971
|
}
|
|
22971
22972
|
const output2 = await this.getVesuSingletonContract(config).call("position_unsafe", [
|
|
22972
22973
|
this.config.poolId.address,
|
|
@@ -22989,9 +22990,65 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
22989
22990
|
usdValue: debtAmount.multipliedBy(token2Price.price).toNumber(),
|
|
22990
22991
|
remarks: "Debt"
|
|
22991
22992
|
}];
|
|
22992
|
-
this.
|
|
22993
|
+
this.setCache(CACHE_KEY, value, 6e4);
|
|
22994
|
+
return value;
|
|
22995
|
+
}
|
|
22996
|
+
async getCollateralization(config) {
|
|
22997
|
+
if (!this.pricer) {
|
|
22998
|
+
throw new Error("Pricer is not initialized");
|
|
22999
|
+
}
|
|
23000
|
+
const CACHE_KEY = "collateralization";
|
|
23001
|
+
const cacheData = this.getCache(CACHE_KEY);
|
|
23002
|
+
if (cacheData) {
|
|
23003
|
+
return cacheData;
|
|
23004
|
+
}
|
|
23005
|
+
const output2 = await this.getVesuSingletonContract(config).call("check_collateralization_unsafe", [
|
|
23006
|
+
this.config.poolId.address,
|
|
23007
|
+
this.config.collateral.address.address,
|
|
23008
|
+
this.config.debt.address.address,
|
|
23009
|
+
this.config.vaultAllocator.address
|
|
23010
|
+
]);
|
|
23011
|
+
const collateralAmount = Web3Number.fromWei(output2["1"].toString(), 18);
|
|
23012
|
+
const debtAmount = Web3Number.fromWei(output2["2"].toString(), 18);
|
|
23013
|
+
const value = [{
|
|
23014
|
+
token: this.config.collateral,
|
|
23015
|
+
usdValue: collateralAmount.toNumber(),
|
|
23016
|
+
remarks: "Collateral"
|
|
23017
|
+
}, {
|
|
23018
|
+
token: this.config.debt,
|
|
23019
|
+
usdValue: debtAmount.toNumber(),
|
|
23020
|
+
remarks: "Debt"
|
|
23021
|
+
}];
|
|
23022
|
+
this.setCache(CACHE_KEY, value, 6e4);
|
|
22993
23023
|
return value;
|
|
22994
23024
|
}
|
|
23025
|
+
async getAssetPrices() {
|
|
23026
|
+
const collateralizationProm = this.getCollateralization(this.networkConfig);
|
|
23027
|
+
const positionsProm = this.getPositions(this.networkConfig);
|
|
23028
|
+
const ltvProm = this.getLTVConfig(this.networkConfig);
|
|
23029
|
+
const output2 = await Promise.all([collateralizationProm, positionsProm, ltvProm]);
|
|
23030
|
+
const [collateralization, positions, ltv] = output2;
|
|
23031
|
+
const collateralTokenAmount = positions[0].amount;
|
|
23032
|
+
const collateralUSDAmount = collateralization[0].usdValue;
|
|
23033
|
+
const collateralPrice = collateralUSDAmount / collateralTokenAmount.toNumber();
|
|
23034
|
+
const debtTokenAmount = positions[1].amount;
|
|
23035
|
+
const debtUSDAmount = collateralization[1].usdValue;
|
|
23036
|
+
const debtPrice = debtUSDAmount / debtTokenAmount.toNumber();
|
|
23037
|
+
return {
|
|
23038
|
+
collateralTokenAmount,
|
|
23039
|
+
collateralUSDAmount,
|
|
23040
|
+
collateralPrice,
|
|
23041
|
+
debtTokenAmount,
|
|
23042
|
+
debtUSDAmount,
|
|
23043
|
+
debtPrice,
|
|
23044
|
+
ltv
|
|
23045
|
+
};
|
|
23046
|
+
}
|
|
23047
|
+
async getHealthFactor() {
|
|
23048
|
+
const ltv = await this.getLTVConfig(this.networkConfig);
|
|
23049
|
+
const collateralisation = await this.getCollateralization(this.networkConfig);
|
|
23050
|
+
return collateralisation[0].usdValue * ltv / collateralisation[1].usdValue;
|
|
23051
|
+
}
|
|
22995
23052
|
static async getVesuPools(retry = 0) {
|
|
22996
23053
|
const CACHE_KEY = "VESU_POOLS";
|
|
22997
23054
|
const cacheValue = Global.getGlobalCache(CACHE_KEY);
|
|
@@ -25363,19 +25420,32 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25363
25420
|
const debtAsset1 = pool1.assets.find((a) => a.symbol === vesuAdapter1.config.debt.symbol)?.stats;
|
|
25364
25421
|
const collateralAsset2 = pool2.assets.find((a) => a.symbol === vesuAdapter2.config.collateral.symbol)?.stats;
|
|
25365
25422
|
const debtAsset2 = pool2.assets.find((a) => a.symbol === vesuAdapter2.config.debt.symbol)?.stats;
|
|
25366
|
-
const collateral1APY = Number(collateralAsset1.supplyApy.value) / 1e18
|
|
25423
|
+
const collateral1APY = Number(collateralAsset1.supplyApy.value) / 1e18;
|
|
25367
25424
|
const debt1APY = Number(debtAsset1.borrowApr.value) / 1e18;
|
|
25368
|
-
const collateral2APY = Number(collateralAsset2.supplyApy.value) / 1e18
|
|
25425
|
+
const collateral2APY = Number(collateralAsset2.supplyApy.value) / 1e18;
|
|
25369
25426
|
const debt2APY = Number(debtAsset2.borrowApr.value) / 1e18;
|
|
25370
|
-
const apys = [collateral1APY, debt1APY, collateral2APY, debt2APY];
|
|
25371
25427
|
const positions = await this.getVaultPositions();
|
|
25372
|
-
|
|
25373
|
-
const
|
|
25374
|
-
|
|
25375
|
-
|
|
25376
|
-
const
|
|
25377
|
-
const
|
|
25378
|
-
|
|
25428
|
+
const weights = positions.map((p, index) => p.usdValue * (index % 2 == 0 ? 1 : -1));
|
|
25429
|
+
const baseAPYs = [collateral1APY, debt1APY, collateral2APY, debt2APY];
|
|
25430
|
+
assert(positions.length == baseAPYs.length, "Positions and APYs length mismatch");
|
|
25431
|
+
const rewardAPYs = [Number(collateralAsset1.defiSpringSupplyApr.value) / 1e18, 0, Number(collateralAsset2.defiSpringSupplyApr.value) / 1e18, 0];
|
|
25432
|
+
const baseAPY = this.computeAPY(baseAPYs, weights);
|
|
25433
|
+
const rewardAPY = this.computeAPY(rewardAPYs, weights);
|
|
25434
|
+
const apys = [...baseAPYs, ...rewardAPYs];
|
|
25435
|
+
const netAPY = baseAPY + rewardAPY;
|
|
25436
|
+
return { net: netAPY, splits: [{
|
|
25437
|
+
apy: baseAPY,
|
|
25438
|
+
id: "base"
|
|
25439
|
+
}, {
|
|
25440
|
+
apy: rewardAPY,
|
|
25441
|
+
id: "defispring"
|
|
25442
|
+
}] };
|
|
25443
|
+
}
|
|
25444
|
+
computeAPY(apys, weights) {
|
|
25445
|
+
assert(apys.length === weights.length, "APYs and weights length mismatch");
|
|
25446
|
+
const weightedSum = apys.reduce((acc, apy, i) => acc + apy * weights[i], 0);
|
|
25447
|
+
const totalWeight = weights.reduce((acc, weight) => acc + weight, 0);
|
|
25448
|
+
return weightedSum / totalWeight;
|
|
25379
25449
|
}
|
|
25380
25450
|
/**
|
|
25381
25451
|
* Calculates the total TVL of the strategy.
|
|
@@ -25398,22 +25468,48 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25398
25468
|
};
|
|
25399
25469
|
}
|
|
25400
25470
|
async getAUM() {
|
|
25471
|
+
const currentAUM = await this.contract.call("aum", []);
|
|
25472
|
+
const lastReportTime = await this.contract.call("last_report_timestamp", []);
|
|
25473
|
+
const token1Price = await this.pricer.getPrice(this.metadata.depositTokens[0].symbol);
|
|
25401
25474
|
const [vesuAdapter1, vesuAdapter2] = this.getVesuAdapters();
|
|
25402
25475
|
const leg1AUM = await vesuAdapter1.getPositions(this.config);
|
|
25403
25476
|
const leg2AUM = await vesuAdapter2.getPositions(this.config);
|
|
25404
|
-
const token1Price = await this.pricer.getPrice(vesuAdapter1.config.collateral.symbol);
|
|
25405
25477
|
const aumToken = leg1AUM[0].amount.plus(leg2AUM[0].usdValue / token1Price.price).minus(leg1AUM[1].usdValue / token1Price.price).minus(leg2AUM[1].amount);
|
|
25406
|
-
|
|
25478
|
+
logger.verbose(`${this.getTag()} Actual AUM: ${aumToken}`);
|
|
25479
|
+
const netAPY = await this.netAPY();
|
|
25480
|
+
const defispringAPY = netAPY.splits.find((s) => s.id === "defispring")?.apy || 0;
|
|
25481
|
+
if (!defispringAPY) throw new Error("DefiSpring APY not found");
|
|
25482
|
+
const timeDiff = Math.round(Date.now() / 1e3) - Number(lastReportTime);
|
|
25483
|
+
const growthRate = timeDiff * defispringAPY / (365 * 24 * 60 * 60);
|
|
25484
|
+
const prevAum = Web3Number.fromWei(currentAUM.toString(), this.asset().decimals);
|
|
25485
|
+
const rewardAssets = prevAum.multipliedBy(growthRate);
|
|
25486
|
+
logger.verbose(`${this.getTag()} DefiSpring AUM time difference: ${timeDiff}`);
|
|
25487
|
+
logger.verbose(`${this.getTag()} Current AUM: ${currentAUM}`);
|
|
25488
|
+
logger.verbose(`${this.getTag()} Net APY: ${JSON.stringify(netAPY)}`);
|
|
25489
|
+
logger.verbose(`${this.getTag()} rewards AUM: ${rewardAssets}`);
|
|
25490
|
+
const newAUM = aumToken.plus(rewardAssets);
|
|
25491
|
+
logger.verbose(`${this.getTag()} New AUM: ${newAUM}`);
|
|
25492
|
+
const net = {
|
|
25407
25493
|
tokenInfo: this.asset(),
|
|
25408
|
-
amount:
|
|
25409
|
-
usdValue:
|
|
25494
|
+
amount: newAUM,
|
|
25495
|
+
usdValue: newAUM.multipliedBy(token1Price.price).toNumber()
|
|
25410
25496
|
};
|
|
25497
|
+
const splits = [{
|
|
25498
|
+
id: "finalised",
|
|
25499
|
+
aum: aumToken
|
|
25500
|
+
}, {
|
|
25501
|
+
id: "defispring",
|
|
25502
|
+
aum: rewardAssets
|
|
25503
|
+
}];
|
|
25504
|
+
return { net, splits, prevAum };
|
|
25411
25505
|
}
|
|
25412
25506
|
getVesuAdapters() {
|
|
25413
25507
|
const vesuAdapter1 = this.getAdapter("vesu_leg1_adapter" /* VESU_LEG1 */);
|
|
25414
25508
|
const vesuAdapter2 = this.getAdapter("vesu_leg2_adapter" /* VESU_LEG2 */);
|
|
25415
25509
|
vesuAdapter1.pricer = this.pricer;
|
|
25416
25510
|
vesuAdapter2.pricer = this.pricer;
|
|
25511
|
+
vesuAdapter1.networkConfig = this.config;
|
|
25512
|
+
vesuAdapter2.networkConfig = this.config;
|
|
25417
25513
|
return [vesuAdapter1, vesuAdapter2];
|
|
25418
25514
|
}
|
|
25419
25515
|
async getVaultPositions() {
|
|
@@ -25455,12 +25551,14 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25455
25551
|
}));
|
|
25456
25552
|
const output2 = [{
|
|
25457
25553
|
proofs: manage5Info.proofs,
|
|
25458
|
-
manageCall: manageCall5
|
|
25554
|
+
manageCall: manageCall5,
|
|
25555
|
+
step: STEP2_ID
|
|
25459
25556
|
}];
|
|
25460
25557
|
if (approveAmount.gt(0)) {
|
|
25461
25558
|
output2.unshift({
|
|
25462
25559
|
proofs: manage4Info.proofs,
|
|
25463
|
-
manageCall: manageCall4
|
|
25560
|
+
manageCall: manageCall4,
|
|
25561
|
+
step: STEP1_ID
|
|
25464
25562
|
});
|
|
25465
25563
|
}
|
|
25466
25564
|
return output2;
|
|
@@ -25468,9 +25566,96 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25468
25566
|
getTag() {
|
|
25469
25567
|
return `${_UniversalStrategy.name}:${this.metadata.name}`;
|
|
25470
25568
|
}
|
|
25569
|
+
async getVesuHealthFactors() {
|
|
25570
|
+
return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor()));
|
|
25571
|
+
}
|
|
25572
|
+
async computeRebalanceConditionAndReturnCalls() {
|
|
25573
|
+
const vesuAdapters = this.getVesuAdapters();
|
|
25574
|
+
const healthFactors = await this.getVesuHealthFactors();
|
|
25575
|
+
const leg1HealthFactor = healthFactors[0];
|
|
25576
|
+
const leg2HealthFactor = healthFactors[1];
|
|
25577
|
+
logger.verbose(`${this.getTag()}: HealthFactorLeg1: ${leg1HealthFactor}`);
|
|
25578
|
+
logger.verbose(`${this.getTag()}: HealthFactorLeg2: ${leg2HealthFactor}`);
|
|
25579
|
+
const minHf = this.metadata.additionalInfo.minHealthFactor;
|
|
25580
|
+
const isRebalanceNeeded1 = leg1HealthFactor < minHf;
|
|
25581
|
+
const isRebalanceNeeded2 = leg2HealthFactor < minHf;
|
|
25582
|
+
if (!isRebalanceNeeded1 && !isRebalanceNeeded2) {
|
|
25583
|
+
return [];
|
|
25584
|
+
}
|
|
25585
|
+
if (isRebalanceNeeded1) {
|
|
25586
|
+
const amount = await this.getLegRebalanceAmount(vesuAdapters[0], leg1HealthFactor, false);
|
|
25587
|
+
const leg2HF = await this.getNewHealthFactor(vesuAdapters[1], amount, true);
|
|
25588
|
+
assert(leg2HF > minHf, `Rebalance Leg1 failed: Leg2 HF after rebalance would be too low: ${leg2HF}`);
|
|
25589
|
+
return [await this.getRebalanceCall({
|
|
25590
|
+
isLeg1toLeg2: false,
|
|
25591
|
+
amount
|
|
25592
|
+
})];
|
|
25593
|
+
} else {
|
|
25594
|
+
const amount = await this.getLegRebalanceAmount(vesuAdapters[1], leg2HealthFactor, true);
|
|
25595
|
+
const leg1HF = await this.getNewHealthFactor(vesuAdapters[0], amount, false);
|
|
25596
|
+
assert(leg1HF > minHf, `Rebalance Leg2 failed: Leg1 HF after rebalance would be too low: ${leg1HF}`);
|
|
25597
|
+
return [await this.getRebalanceCall({
|
|
25598
|
+
isLeg1toLeg2: true,
|
|
25599
|
+
amount
|
|
25600
|
+
})];
|
|
25601
|
+
}
|
|
25602
|
+
}
|
|
25603
|
+
async getNewHealthFactor(vesuAdapter, newAmount, isWithdraw) {
|
|
25604
|
+
const {
|
|
25605
|
+
collateralTokenAmount,
|
|
25606
|
+
collateralUSDAmount,
|
|
25607
|
+
collateralPrice,
|
|
25608
|
+
debtTokenAmount,
|
|
25609
|
+
debtUSDAmount,
|
|
25610
|
+
debtPrice,
|
|
25611
|
+
ltv
|
|
25612
|
+
} = await vesuAdapter.getAssetPrices();
|
|
25613
|
+
if (isWithdraw) {
|
|
25614
|
+
const newHF = (collateralTokenAmount.toNumber() - newAmount.toNumber()) * collateralPrice * ltv / debtUSDAmount;
|
|
25615
|
+
logger.verbose(`getNewHealthFactor:: HF: ${newHF}, amoutn: ${newAmount.toNumber()}, isDeposit`);
|
|
25616
|
+
return newHF;
|
|
25617
|
+
} else {
|
|
25618
|
+
const newHF = collateralUSDAmount * ltv / ((debtTokenAmount.toNumber() + newAmount.toNumber()) * debtPrice);
|
|
25619
|
+
logger.verbose(`getNewHealthFactor:: HF: ${newHF}, amoutn: ${newAmount.toNumber()}, isRepay`);
|
|
25620
|
+
return newHF;
|
|
25621
|
+
}
|
|
25622
|
+
}
|
|
25623
|
+
/**
|
|
25624
|
+
*
|
|
25625
|
+
* @param vesuAdapter
|
|
25626
|
+
* @param currentHf
|
|
25627
|
+
* @param isDeposit if true, attempt by adding collateral, else by repaying
|
|
25628
|
+
* @returns
|
|
25629
|
+
*/
|
|
25630
|
+
async getLegRebalanceAmount(vesuAdapter, currentHf, isDeposit) {
|
|
25631
|
+
const {
|
|
25632
|
+
collateralTokenAmount,
|
|
25633
|
+
collateralUSDAmount,
|
|
25634
|
+
collateralPrice,
|
|
25635
|
+
debtTokenAmount,
|
|
25636
|
+
debtUSDAmount,
|
|
25637
|
+
debtPrice,
|
|
25638
|
+
ltv
|
|
25639
|
+
} = await vesuAdapter.getAssetPrices();
|
|
25640
|
+
if (debtTokenAmount.isZero()) {
|
|
25641
|
+
return Web3Number.fromWei(0, 0);
|
|
25642
|
+
}
|
|
25643
|
+
assert(collateralPrice > 0 && debtPrice > 0, "getRebalanceAmount: Invalid price");
|
|
25644
|
+
const targetHF = this.metadata.additionalInfo.targetHealthFactor;
|
|
25645
|
+
if (currentHf > targetHF - 0.01)
|
|
25646
|
+
throw new Error("getLegRebalanceAmount: Current health factor is healthy");
|
|
25647
|
+
if (isDeposit) {
|
|
25648
|
+
const newAmount = targetHF * debtUSDAmount / (collateralPrice * ltv) - collateralTokenAmount.toNumber();
|
|
25649
|
+
logger.verbose(`${this.getTag()}:: getLegRebalanceAmount: addCollateral, currentHf: ${currentHf}, targetHF: ${targetHF}, collAmount: ${collateralTokenAmount.toString()}, collUSD: ${collateralUSDAmount}, collPrice: ${collateralPrice}, debtAmount: ${debtTokenAmount.toString()}, debtUSD: ${debtUSDAmount}, debtPrice: ${debtPrice}, ltv: ${ltv}, newAmount: ${newAmount}`);
|
|
25650
|
+
return new Web3Number(newAmount.toFixed(8), collateralTokenAmount.decimals);
|
|
25651
|
+
} else {
|
|
25652
|
+
const newAmount = debtTokenAmount.toNumber() - collateralUSDAmount * ltv / (targetHF * debtPrice);
|
|
25653
|
+
logger.verbose(`${this.getTag()}:: getLegRebalanceAmount: repayDebt, currentHf: ${currentHf}, targetHF: ${targetHF}, collAmount: ${collateralTokenAmount.toString()}, collUSD: ${collateralUSDAmount}, collPrice: ${collateralPrice}, debtAmount: ${debtTokenAmount.toString()}, debtUSD: ${debtUSDAmount}, debtPrice: ${debtPrice}, ltv: ${ltv}, newAmount: ${newAmount}`);
|
|
25654
|
+
return new Web3Number(newAmount.toFixed(8), debtTokenAmount.decimals);
|
|
25655
|
+
}
|
|
25656
|
+
}
|
|
25471
25657
|
async getVesuMultiplyCall(params) {
|
|
25472
|
-
const vesuAdapter1 = this.
|
|
25473
|
-
const vesuAdapter2 = this.getAdapter("vesu_leg2_adapter" /* VESU_LEG2 */);
|
|
25658
|
+
const [vesuAdapter1, vesuAdapter2] = this.getVesuAdapters();
|
|
25474
25659
|
const leg1LTV = await vesuAdapter1.getLTVConfig(this.config);
|
|
25475
25660
|
const leg2LTV = await vesuAdapter2.getLTVConfig(this.config);
|
|
25476
25661
|
logger.verbose(`${this.getTag()}: LTVLeg1: ${leg1LTV}`);
|
|
@@ -25479,7 +25664,7 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25479
25664
|
const token2Price = await this.pricer.getPrice(vesuAdapter2.config.collateral.symbol);
|
|
25480
25665
|
logger.verbose(`${this.getTag()}: Price${vesuAdapter1.config.collateral.symbol}: ${token1Price.price}`);
|
|
25481
25666
|
logger.verbose(`${this.getTag()}: Price${vesuAdapter2.config.collateral.symbol}: ${token2Price.price}`);
|
|
25482
|
-
const TARGET_HF =
|
|
25667
|
+
const TARGET_HF = this.metadata.additionalInfo.targetHealthFactor;
|
|
25483
25668
|
const k1 = token1Price.price * leg1LTV / token2Price.price / TARGET_HF;
|
|
25484
25669
|
const k2 = token1Price.price * TARGET_HF / token2Price.price / leg2LTV;
|
|
25485
25670
|
const borrow2Amount = new Web3Number(
|
|
@@ -25537,14 +25722,14 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25537
25722
|
});
|
|
25538
25723
|
if (params.isLeg1toLeg2) {
|
|
25539
25724
|
const manageCall = this.getManageCall([
|
|
25540
|
-
|
|
25541
|
-
|
|
25725
|
+
...callSet1.map((i) => i.step),
|
|
25726
|
+
...callSet2.map((i) => i.step)
|
|
25542
25727
|
], [...callSet1.map((i) => i.manageCall), ...callSet2.map((i) => i.manageCall)]);
|
|
25543
25728
|
return manageCall;
|
|
25544
25729
|
} else {
|
|
25545
25730
|
const manageCall = this.getManageCall([
|
|
25546
|
-
|
|
25547
|
-
|
|
25731
|
+
...callSet2.map((i) => i.step),
|
|
25732
|
+
...callSet1.map((i) => i.step)
|
|
25548
25733
|
], [...callSet2.map((i) => i.manageCall), ...callSet1.map((i) => i.manageCall)]);
|
|
25549
25734
|
return manageCall;
|
|
25550
25735
|
}
|
|
@@ -25612,14 +25797,18 @@ var usdcVaultSettings = {
|
|
|
25612
25797
|
vaultAllocator: ContractAddr.from("0x228cca1005d3f2b55cbaba27cb291dacf1b9a92d1d6b1638195fbd3d0c1e3ba"),
|
|
25613
25798
|
redeemRequestNFT: ContractAddr.from("0x906d03590010868cbf7590ad47043959d7af8e782089a605d9b22567b64fda"),
|
|
25614
25799
|
leafAdapters: [],
|
|
25615
|
-
adapters: []
|
|
25800
|
+
adapters: [],
|
|
25801
|
+
targetHealthFactor: 1.3,
|
|
25802
|
+
minHealthFactor: 1.25
|
|
25616
25803
|
};
|
|
25617
25804
|
var wbtcVaultSettings = {
|
|
25618
25805
|
manager: ContractAddr.from("0xef8a664ffcfe46a6af550766d27c28937bf1b77fb4ab54d8553e92bca5ba34"),
|
|
25619
25806
|
vaultAllocator: ContractAddr.from("0x1e01c25f0d9494570226ad28a7fa856c0640505e809c366a9fab4903320e735"),
|
|
25620
25807
|
redeemRequestNFT: ContractAddr.from("0x4fec59a12f8424281c1e65a80b5de51b4e754625c60cddfcd00d46941ec37b2"),
|
|
25621
25808
|
leafAdapters: [],
|
|
25622
|
-
adapters: []
|
|
25809
|
+
adapters: [],
|
|
25810
|
+
targetHealthFactor: 1.3,
|
|
25811
|
+
minHealthFactor: 1.25
|
|
25623
25812
|
};
|
|
25624
25813
|
var UniversalStrategies = [
|
|
25625
25814
|
{
|
package/dist/index.d.ts
CHANGED
|
@@ -380,6 +380,18 @@ declare class AutoCompounderSTRK {
|
|
|
380
380
|
}>;
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
+
interface CacheData$1 {
|
|
384
|
+
timestamp: number;
|
|
385
|
+
ttl: number;
|
|
386
|
+
data: any;
|
|
387
|
+
}
|
|
388
|
+
declare class CacheClass {
|
|
389
|
+
readonly cache: Map<string, CacheData$1>;
|
|
390
|
+
setCache(key: string, data: any, ttl?: number): void;
|
|
391
|
+
getCache<T>(key: string): T | null;
|
|
392
|
+
isCacheValid(key: string): boolean;
|
|
393
|
+
}
|
|
394
|
+
|
|
383
395
|
interface SingleActionAmount {
|
|
384
396
|
tokenInfo: TokenInfo;
|
|
385
397
|
amount: Web3Number;
|
|
@@ -401,7 +413,7 @@ interface CacheData {
|
|
|
401
413
|
ttl: number;
|
|
402
414
|
data: any;
|
|
403
415
|
}
|
|
404
|
-
declare class BaseStrategy<TVLInfo, ActionInfo> {
|
|
416
|
+
declare class BaseStrategy<TVLInfo, ActionInfo> extends CacheClass {
|
|
405
417
|
readonly config: IConfig;
|
|
406
418
|
readonly cache: Map<string, CacheData>;
|
|
407
419
|
constructor(config: IConfig);
|
|
@@ -409,9 +421,6 @@ declare class BaseStrategy<TVLInfo, ActionInfo> {
|
|
|
409
421
|
getTVL(): Promise<TVLInfo>;
|
|
410
422
|
depositCall(amountInfo: ActionInfo, receiver: ContractAddr): Promise<Call[]>;
|
|
411
423
|
withdrawCall(amountInfo: ActionInfo, receiver: ContractAddr, owner: ContractAddr): Promise<Call[]>;
|
|
412
|
-
setCache(key: string, data: any, ttl?: number): void;
|
|
413
|
-
getCache(key: string): any | null;
|
|
414
|
-
isCacheValid(key: string): boolean;
|
|
415
424
|
}
|
|
416
425
|
|
|
417
426
|
interface PoolProps {
|
|
@@ -866,7 +875,6 @@ declare class StandardMerkleTree extends MerkleTreeImpl<LeafData> {
|
|
|
866
875
|
protected readonly leafEncoding: ValueType[];
|
|
867
876
|
protected constructor(tree: HexString[], values: StandardMerkleTreeData<LeafData>['values'], leafEncoding: ValueType[]);
|
|
868
877
|
static of(values: LeafData[], leafEncoding?: ValueType[], options?: MerkleTreeOptions): StandardMerkleTree;
|
|
869
|
-
static load(data: StandardMerkleTreeData<LeafData>): StandardMerkleTree;
|
|
870
878
|
static verify<T extends any[]>(root: BytesLike, leafEncoding: ValueType[], leaf: T, proof: BytesLike[]): boolean;
|
|
871
879
|
static verifyMultiProof<T extends any[]>(root: BytesLike, leafEncoding: ValueType[], multiproof: MultiProof<BytesLike, T>): boolean;
|
|
872
880
|
dump(): StandardMerkleTreeData<LeafData>;
|
|
@@ -895,7 +903,7 @@ type AdapterLeafType<T> = {
|
|
|
895
903
|
callConstructor: GenerateCallFn<T>;
|
|
896
904
|
};
|
|
897
905
|
type LeafAdapterFn<T> = () => AdapterLeafType<T>;
|
|
898
|
-
declare class BaseAdapter {
|
|
906
|
+
declare class BaseAdapter extends CacheClass {
|
|
899
907
|
protected constructSimpleLeafData(params: {
|
|
900
908
|
id: string;
|
|
901
909
|
target: ContractAddr;
|
|
@@ -972,7 +980,6 @@ declare class VesuAdapter extends BaseAdapter {
|
|
|
972
980
|
config: VesuAdapterConfig;
|
|
973
981
|
networkConfig: IConfig | undefined;
|
|
974
982
|
pricer: PricerBase | undefined;
|
|
975
|
-
cache: Record<string, any>;
|
|
976
983
|
constructor(config: VesuAdapterConfig);
|
|
977
984
|
getModifyPosition: () => AdapterLeafType<VesuModifyPositionCallParams>;
|
|
978
985
|
static getDefaultModifyPositionCallParams(params: {
|
|
@@ -1004,6 +1011,17 @@ declare class VesuAdapter extends BaseAdapter {
|
|
|
1004
1011
|
getVesuSingletonContract(config: IConfig): Contract;
|
|
1005
1012
|
getLTVConfig(config: IConfig): Promise<number>;
|
|
1006
1013
|
getPositions(config: IConfig): Promise<VaultPosition[]>;
|
|
1014
|
+
getCollateralization(config: IConfig): Promise<Omit<VaultPosition, 'amount'>[]>;
|
|
1015
|
+
getAssetPrices(): Promise<{
|
|
1016
|
+
collateralTokenAmount: Web3Number;
|
|
1017
|
+
collateralUSDAmount: number;
|
|
1018
|
+
collateralPrice: number;
|
|
1019
|
+
debtTokenAmount: Web3Number;
|
|
1020
|
+
debtUSDAmount: number;
|
|
1021
|
+
debtPrice: number;
|
|
1022
|
+
ltv: number;
|
|
1023
|
+
}>;
|
|
1024
|
+
getHealthFactor(): Promise<number>;
|
|
1007
1025
|
static getVesuPools(retry?: number): Promise<VesuPoolsInfo>;
|
|
1008
1026
|
}
|
|
1009
1027
|
|
|
@@ -1016,6 +1034,8 @@ interface UniversalStrategySettings {
|
|
|
1016
1034
|
id: string;
|
|
1017
1035
|
adapter: BaseAdapter;
|
|
1018
1036
|
}[];
|
|
1037
|
+
targetHealthFactor: number;
|
|
1038
|
+
minHealthFactor: number;
|
|
1019
1039
|
}
|
|
1020
1040
|
declare class UniversalStrategy<S extends UniversalStrategySettings> extends BaseStrategy<SingleTokenInfo, SingleActionAmount> {
|
|
1021
1041
|
/** Contract address of the strategy */
|
|
@@ -1052,7 +1072,14 @@ declare class UniversalStrategy<S extends UniversalStrategySettings> extends Bas
|
|
|
1052
1072
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
1053
1073
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
1054
1074
|
*/
|
|
1055
|
-
netAPY(): Promise<
|
|
1075
|
+
netAPY(): Promise<{
|
|
1076
|
+
net: number;
|
|
1077
|
+
splits: {
|
|
1078
|
+
apy: number;
|
|
1079
|
+
id: string;
|
|
1080
|
+
}[];
|
|
1081
|
+
}>;
|
|
1082
|
+
private computeAPY;
|
|
1056
1083
|
/**
|
|
1057
1084
|
* Calculates the total TVL of the strategy.
|
|
1058
1085
|
* @returns Object containing the total amount in token units and USD value
|
|
@@ -1062,7 +1089,14 @@ declare class UniversalStrategy<S extends UniversalStrategySettings> extends Bas
|
|
|
1062
1089
|
amount: Web3Number;
|
|
1063
1090
|
usdValue: number;
|
|
1064
1091
|
}>;
|
|
1065
|
-
getAUM(): Promise<
|
|
1092
|
+
getAUM(): Promise<{
|
|
1093
|
+
net: SingleTokenInfo;
|
|
1094
|
+
prevAum: Web3Number;
|
|
1095
|
+
splits: {
|
|
1096
|
+
id: string;
|
|
1097
|
+
aum: Web3Number;
|
|
1098
|
+
}[];
|
|
1099
|
+
}>;
|
|
1066
1100
|
getVesuAdapters(): VesuAdapter[];
|
|
1067
1101
|
getVaultPositions(): Promise<VaultPosition[]>;
|
|
1068
1102
|
getSetManagerCall(strategist: ContractAddr, root?: string): Call;
|
|
@@ -1075,8 +1109,20 @@ declare class UniversalStrategy<S extends UniversalStrategySettings> extends Bas
|
|
|
1075
1109
|
}): {
|
|
1076
1110
|
proofs: string[];
|
|
1077
1111
|
manageCall: ManageCall;
|
|
1112
|
+
step: UNIVERSAL_MANAGE_IDS;
|
|
1078
1113
|
}[];
|
|
1079
1114
|
getTag(): string;
|
|
1115
|
+
getVesuHealthFactors(): Promise<number[]>;
|
|
1116
|
+
computeRebalanceConditionAndReturnCalls(): Promise<Call[]>;
|
|
1117
|
+
private getNewHealthFactor;
|
|
1118
|
+
/**
|
|
1119
|
+
*
|
|
1120
|
+
* @param vesuAdapter
|
|
1121
|
+
* @param currentHf
|
|
1122
|
+
* @param isDeposit if true, attempt by adding collateral, else by repaying
|
|
1123
|
+
* @returns
|
|
1124
|
+
*/
|
|
1125
|
+
private getLegRebalanceAmount;
|
|
1080
1126
|
getVesuMultiplyCall(params: {
|
|
1081
1127
|
isDeposit: boolean;
|
|
1082
1128
|
leg1DepositAmount: Web3Number;
|