@strkfarm/sdk 1.0.56 → 1.0.58
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 +265 -84
- package/dist/index.browser.mjs +260 -67
- package/dist/index.d.ts +56 -9
- package/dist/index.js +261 -71
- package/dist/index.mjs +261 -71
- package/package.json +1 -1
- package/src/node/deployer.ts +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 +190 -31
- package/src/utils/cacheClass.ts +29 -0
- package/src/utils/oz-merkle.ts +0 -9
package/dist/index.mjs
CHANGED
|
@@ -1986,7 +1986,6 @@ import { toHex } from "@ericnordelo/strk-merkle-tree/dist/bytes";
|
|
|
1986
1986
|
import { processMultiProof, processProof } from "@ericnordelo/strk-merkle-tree/dist/core";
|
|
1987
1987
|
import { standardLeafHash } from "@ericnordelo/strk-merkle-tree/dist/hashes";
|
|
1988
1988
|
import { MerkleTreeImpl } from "@ericnordelo/strk-merkle-tree/dist/merkletree";
|
|
1989
|
-
import { validateArgument } from "@ericnordelo/strk-merkle-tree/src/utils/errors";
|
|
1990
1989
|
import { num as num2 } from "starknet";
|
|
1991
1990
|
|
|
1992
1991
|
// ../node_modules/@noble/hashes/esm/_assert.js
|
|
@@ -4044,13 +4043,6 @@ var StandardMerkleTree = class _StandardMerkleTree extends MerkleTreeImpl {
|
|
|
4044
4043
|
});
|
|
4045
4044
|
return new _StandardMerkleTree(tree, indexedValues, leafEncoding);
|
|
4046
4045
|
}
|
|
4047
|
-
static load(data) {
|
|
4048
|
-
validateArgument(data.format === "standard-v1", `Unknown format '${data.format}'`);
|
|
4049
|
-
validateArgument(data.leafEncoding !== void 0, "Expected leaf encoding");
|
|
4050
|
-
const tree = new _StandardMerkleTree(data.tree, data.values, data.leafEncoding);
|
|
4051
|
-
tree.validate();
|
|
4052
|
-
return tree;
|
|
4053
|
-
}
|
|
4054
4046
|
static verify(root, leafEncoding, leaf, proof) {
|
|
4055
4047
|
return toHex(root) === processProof(standardLeafHash(leafEncoding, leaf), proof);
|
|
4056
4048
|
}
|
|
@@ -5808,23 +5800,10 @@ var vesu_rebalance_abi_default = [
|
|
|
5808
5800
|
}
|
|
5809
5801
|
];
|
|
5810
5802
|
|
|
5811
|
-
// src/
|
|
5812
|
-
var
|
|
5813
|
-
constructor(
|
|
5803
|
+
// src/utils/cacheClass.ts
|
|
5804
|
+
var CacheClass = class {
|
|
5805
|
+
constructor() {
|
|
5814
5806
|
this.cache = /* @__PURE__ */ new Map();
|
|
5815
|
-
this.config = config;
|
|
5816
|
-
}
|
|
5817
|
-
async getUserTVL(user) {
|
|
5818
|
-
throw new Error("Not implemented");
|
|
5819
|
-
}
|
|
5820
|
-
async getTVL() {
|
|
5821
|
-
throw new Error("Not implemented");
|
|
5822
|
-
}
|
|
5823
|
-
async depositCall(amountInfo, receiver) {
|
|
5824
|
-
throw new Error("Not implemented");
|
|
5825
|
-
}
|
|
5826
|
-
async withdrawCall(amountInfo, receiver, owner) {
|
|
5827
|
-
throw new Error("Not implemented");
|
|
5828
5807
|
}
|
|
5829
5808
|
setCache(key, data, ttl = 6e4) {
|
|
5830
5809
|
const timestamp = Date.now();
|
|
@@ -5845,6 +5824,27 @@ var BaseStrategy = class {
|
|
|
5845
5824
|
}
|
|
5846
5825
|
};
|
|
5847
5826
|
|
|
5827
|
+
// src/strategies/base-strategy.ts
|
|
5828
|
+
var BaseStrategy = class extends CacheClass {
|
|
5829
|
+
constructor(config) {
|
|
5830
|
+
super();
|
|
5831
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
5832
|
+
this.config = config;
|
|
5833
|
+
}
|
|
5834
|
+
async getUserTVL(user) {
|
|
5835
|
+
throw new Error("Not implemented");
|
|
5836
|
+
}
|
|
5837
|
+
async getTVL() {
|
|
5838
|
+
throw new Error("Not implemented");
|
|
5839
|
+
}
|
|
5840
|
+
async depositCall(amountInfo, receiver) {
|
|
5841
|
+
throw new Error("Not implemented");
|
|
5842
|
+
}
|
|
5843
|
+
async withdrawCall(amountInfo, receiver, owner) {
|
|
5844
|
+
throw new Error("Not implemented");
|
|
5845
|
+
}
|
|
5846
|
+
};
|
|
5847
|
+
|
|
5848
5848
|
// src/node/headless.browser.ts
|
|
5849
5849
|
import axios5 from "axios";
|
|
5850
5850
|
async function getAPIUsingHeadlessBrowser(url) {
|
|
@@ -20318,9 +20318,8 @@ var SenseiVault = class extends BaseStrategy {
|
|
|
20318
20318
|
}
|
|
20319
20319
|
async getPositionInfo() {
|
|
20320
20320
|
const CACHE_KEY = "positionInfo";
|
|
20321
|
-
|
|
20322
|
-
|
|
20323
|
-
}
|
|
20321
|
+
const existingCacheData = this.getCache(CACHE_KEY);
|
|
20322
|
+
if (existingCacheData) return existingCacheData;
|
|
20324
20323
|
const resp = await fetch(
|
|
20325
20324
|
`${getTrovesEndpoint()}/vesu/positions?walletAddress=${this.address.address}`
|
|
20326
20325
|
);
|
|
@@ -20364,9 +20363,8 @@ var SenseiVault = class extends BaseStrategy {
|
|
|
20364
20363
|
}
|
|
20365
20364
|
async getSecondaryTokenPriceRelativeToMain(retry = 0) {
|
|
20366
20365
|
const CACHE_KEY = "xSTRKPrice";
|
|
20367
|
-
|
|
20368
|
-
|
|
20369
|
-
}
|
|
20366
|
+
const existingCacheData = this.getCache(CACHE_KEY);
|
|
20367
|
+
if (existingCacheData) return existingCacheData;
|
|
20370
20368
|
const params = {
|
|
20371
20369
|
sellTokenAddress: this.metadata.additionalInfo.secondaryToken.address.address,
|
|
20372
20370
|
buyTokenAddress: this.metadata.additionalInfo.mainToken.address.address,
|
|
@@ -20520,7 +20518,7 @@ function toBigInt(value) {
|
|
|
20520
20518
|
}
|
|
20521
20519
|
|
|
20522
20520
|
// src/strategies/universal-adapters/baseAdapter.ts
|
|
20523
|
-
var BaseAdapter = class {
|
|
20521
|
+
var BaseAdapter = class extends CacheClass {
|
|
20524
20522
|
constructSimpleLeafData(params) {
|
|
20525
20523
|
const { id, target, method, packedArguments } = params;
|
|
20526
20524
|
return {
|
|
@@ -22895,7 +22893,6 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
22895
22893
|
constructor(config) {
|
|
22896
22894
|
super();
|
|
22897
22895
|
this.VESU_SINGLETON = ContractAddr.from("0x000d8d6dfec4d33bfb6895de9f3852143a17c6f92fd2a21da3d6924d34870160");
|
|
22898
|
-
this.cache = {};
|
|
22899
22896
|
this.getModifyPosition = () => {
|
|
22900
22897
|
const positionData = [0n];
|
|
22901
22898
|
const packedArguments = [
|
|
@@ -22924,17 +22921,19 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
22924
22921
|
denomination: this.formatAmountDenominationEnum(params.collateralAmount.denomination),
|
|
22925
22922
|
value: {
|
|
22926
22923
|
abs: uint2567.bnToUint256(params.collateralAmount.value.abs.toWei()),
|
|
22927
|
-
is_negative: params.collateralAmount.value.is_negative
|
|
22924
|
+
is_negative: params.collateralAmount.value.abs.isZero() ? false : params.collateralAmount.value.is_negative
|
|
22928
22925
|
}
|
|
22929
22926
|
};
|
|
22927
|
+
logger.verbose(`VesuAdapter::ConstructingModify::Collateral::${JSON.stringify(_collateral)}`);
|
|
22930
22928
|
const _debt = {
|
|
22931
22929
|
amount_type: this.formatAmountTypeEnum(params.debtAmount.amount_type),
|
|
22932
22930
|
denomination: this.formatAmountDenominationEnum(params.debtAmount.denomination),
|
|
22933
22931
|
value: {
|
|
22934
22932
|
abs: uint2567.bnToUint256(params.debtAmount.value.abs.toWei()),
|
|
22935
|
-
is_negative: params.debtAmount.value.is_negative
|
|
22933
|
+
is_negative: params.debtAmount.value.abs.isZero() ? false : params.debtAmount.value.is_negative
|
|
22936
22934
|
}
|
|
22937
22935
|
};
|
|
22936
|
+
logger.verbose(`VesuAdapter::ConstructingModify::Debt::${JSON.stringify(_debt)}`);
|
|
22938
22937
|
const singletonContract = new Contract8(vesu_singleton_abi_default, this.VESU_SINGLETON.toString(), new RpcProvider4({ nodeUrl: "" }));
|
|
22939
22938
|
const call = singletonContract.populate("modify_position", {
|
|
22940
22939
|
params: {
|
|
@@ -23003,20 +23002,22 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
23003
23002
|
}
|
|
23004
23003
|
async getLTVConfig(config) {
|
|
23005
23004
|
const CACHE_KEY = "ltv_config";
|
|
23006
|
-
|
|
23007
|
-
|
|
23005
|
+
const cacheData = this.getCache(CACHE_KEY);
|
|
23006
|
+
if (cacheData) {
|
|
23007
|
+
return cacheData;
|
|
23008
23008
|
}
|
|
23009
23009
|
const output2 = await this.getVesuSingletonContract(config).call("ltv_config", [this.config.poolId.address, this.config.collateral.address.address, this.config.debt.address.address]);
|
|
23010
|
-
this.
|
|
23011
|
-
return this.
|
|
23010
|
+
this.setCache(CACHE_KEY, Number(output2.max_ltv) / 1e18, 3e5);
|
|
23011
|
+
return this.getCache(CACHE_KEY);
|
|
23012
23012
|
}
|
|
23013
23013
|
async getPositions(config) {
|
|
23014
23014
|
if (!this.pricer) {
|
|
23015
23015
|
throw new Error("Pricer is not initialized");
|
|
23016
23016
|
}
|
|
23017
23017
|
const CACHE_KEY = "positions";
|
|
23018
|
-
|
|
23019
|
-
|
|
23018
|
+
const cacheData = this.getCache(CACHE_KEY);
|
|
23019
|
+
if (cacheData) {
|
|
23020
|
+
return cacheData;
|
|
23020
23021
|
}
|
|
23021
23022
|
const output2 = await this.getVesuSingletonContract(config).call("position_unsafe", [
|
|
23022
23023
|
this.config.poolId.address,
|
|
@@ -23039,9 +23040,65 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
23039
23040
|
usdValue: debtAmount.multipliedBy(token2Price.price).toNumber(),
|
|
23040
23041
|
remarks: "Debt"
|
|
23041
23042
|
}];
|
|
23042
|
-
this.
|
|
23043
|
+
this.setCache(CACHE_KEY, value, 6e4);
|
|
23044
|
+
return value;
|
|
23045
|
+
}
|
|
23046
|
+
async getCollateralization(config) {
|
|
23047
|
+
if (!this.pricer) {
|
|
23048
|
+
throw new Error("Pricer is not initialized");
|
|
23049
|
+
}
|
|
23050
|
+
const CACHE_KEY = "collateralization";
|
|
23051
|
+
const cacheData = this.getCache(CACHE_KEY);
|
|
23052
|
+
if (cacheData) {
|
|
23053
|
+
return cacheData;
|
|
23054
|
+
}
|
|
23055
|
+
const output2 = await this.getVesuSingletonContract(config).call("check_collateralization_unsafe", [
|
|
23056
|
+
this.config.poolId.address,
|
|
23057
|
+
this.config.collateral.address.address,
|
|
23058
|
+
this.config.debt.address.address,
|
|
23059
|
+
this.config.vaultAllocator.address
|
|
23060
|
+
]);
|
|
23061
|
+
const collateralAmount = Web3Number.fromWei(output2["1"].toString(), 18);
|
|
23062
|
+
const debtAmount = Web3Number.fromWei(output2["2"].toString(), 18);
|
|
23063
|
+
const value = [{
|
|
23064
|
+
token: this.config.collateral,
|
|
23065
|
+
usdValue: collateralAmount.toNumber(),
|
|
23066
|
+
remarks: "Collateral"
|
|
23067
|
+
}, {
|
|
23068
|
+
token: this.config.debt,
|
|
23069
|
+
usdValue: debtAmount.toNumber(),
|
|
23070
|
+
remarks: "Debt"
|
|
23071
|
+
}];
|
|
23072
|
+
this.setCache(CACHE_KEY, value, 6e4);
|
|
23043
23073
|
return value;
|
|
23044
23074
|
}
|
|
23075
|
+
async getAssetPrices() {
|
|
23076
|
+
const collateralizationProm = this.getCollateralization(this.networkConfig);
|
|
23077
|
+
const positionsProm = this.getPositions(this.networkConfig);
|
|
23078
|
+
const ltvProm = this.getLTVConfig(this.networkConfig);
|
|
23079
|
+
const output2 = await Promise.all([collateralizationProm, positionsProm, ltvProm]);
|
|
23080
|
+
const [collateralization, positions, ltv] = output2;
|
|
23081
|
+
const collateralTokenAmount = positions[0].amount;
|
|
23082
|
+
const collateralUSDAmount = collateralization[0].usdValue;
|
|
23083
|
+
const collateralPrice = collateralUSDAmount / collateralTokenAmount.toNumber();
|
|
23084
|
+
const debtTokenAmount = positions[1].amount;
|
|
23085
|
+
const debtUSDAmount = collateralization[1].usdValue;
|
|
23086
|
+
const debtPrice = debtUSDAmount / debtTokenAmount.toNumber();
|
|
23087
|
+
return {
|
|
23088
|
+
collateralTokenAmount,
|
|
23089
|
+
collateralUSDAmount,
|
|
23090
|
+
collateralPrice,
|
|
23091
|
+
debtTokenAmount,
|
|
23092
|
+
debtUSDAmount,
|
|
23093
|
+
debtPrice,
|
|
23094
|
+
ltv
|
|
23095
|
+
};
|
|
23096
|
+
}
|
|
23097
|
+
async getHealthFactor() {
|
|
23098
|
+
const ltv = await this.getLTVConfig(this.networkConfig);
|
|
23099
|
+
const collateralisation = await this.getCollateralization(this.networkConfig);
|
|
23100
|
+
return collateralisation[0].usdValue * ltv / collateralisation[1].usdValue;
|
|
23101
|
+
}
|
|
23045
23102
|
static async getVesuPools(retry = 0) {
|
|
23046
23103
|
const CACHE_KEY = "VESU_POOLS";
|
|
23047
23104
|
const cacheValue = Global.getGlobalCache(CACHE_KEY);
|
|
@@ -25413,19 +25470,32 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25413
25470
|
const debtAsset1 = pool1.assets.find((a) => a.symbol === vesuAdapter1.config.debt.symbol)?.stats;
|
|
25414
25471
|
const collateralAsset2 = pool2.assets.find((a) => a.symbol === vesuAdapter2.config.collateral.symbol)?.stats;
|
|
25415
25472
|
const debtAsset2 = pool2.assets.find((a) => a.symbol === vesuAdapter2.config.debt.symbol)?.stats;
|
|
25416
|
-
const collateral1APY = Number(collateralAsset1.supplyApy.value) / 1e18
|
|
25473
|
+
const collateral1APY = Number(collateralAsset1.supplyApy.value) / 1e18;
|
|
25417
25474
|
const debt1APY = Number(debtAsset1.borrowApr.value) / 1e18;
|
|
25418
|
-
const collateral2APY = Number(collateralAsset2.supplyApy.value) / 1e18
|
|
25475
|
+
const collateral2APY = Number(collateralAsset2.supplyApy.value) / 1e18;
|
|
25419
25476
|
const debt2APY = Number(debtAsset2.borrowApr.value) / 1e18;
|
|
25420
|
-
const apys = [collateral1APY, debt1APY, collateral2APY, debt2APY];
|
|
25421
25477
|
const positions = await this.getVaultPositions();
|
|
25422
|
-
|
|
25423
|
-
const
|
|
25424
|
-
|
|
25425
|
-
|
|
25426
|
-
const
|
|
25427
|
-
const
|
|
25428
|
-
|
|
25478
|
+
const weights = positions.map((p, index) => p.usdValue * (index % 2 == 0 ? 1 : -1));
|
|
25479
|
+
const baseAPYs = [collateral1APY, debt1APY, collateral2APY, debt2APY];
|
|
25480
|
+
assert(positions.length == baseAPYs.length, "Positions and APYs length mismatch");
|
|
25481
|
+
const rewardAPYs = [Number(collateralAsset1.defiSpringSupplyApr.value) / 1e18, 0, Number(collateralAsset2.defiSpringSupplyApr.value) / 1e18, 0];
|
|
25482
|
+
const baseAPY = this.computeAPY(baseAPYs, weights);
|
|
25483
|
+
const rewardAPY = this.computeAPY(rewardAPYs, weights);
|
|
25484
|
+
const apys = [...baseAPYs, ...rewardAPYs];
|
|
25485
|
+
const netAPY = baseAPY + rewardAPY;
|
|
25486
|
+
return { net: netAPY, splits: [{
|
|
25487
|
+
apy: baseAPY,
|
|
25488
|
+
id: "base"
|
|
25489
|
+
}, {
|
|
25490
|
+
apy: rewardAPY,
|
|
25491
|
+
id: "defispring"
|
|
25492
|
+
}] };
|
|
25493
|
+
}
|
|
25494
|
+
computeAPY(apys, weights) {
|
|
25495
|
+
assert(apys.length === weights.length, "APYs and weights length mismatch");
|
|
25496
|
+
const weightedSum = apys.reduce((acc, apy, i) => acc + apy * weights[i], 0);
|
|
25497
|
+
const totalWeight = weights.reduce((acc, weight) => acc + weight, 0);
|
|
25498
|
+
return weightedSum / totalWeight;
|
|
25429
25499
|
}
|
|
25430
25500
|
/**
|
|
25431
25501
|
* Calculates the total TVL of the strategy.
|
|
@@ -25448,22 +25518,50 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25448
25518
|
};
|
|
25449
25519
|
}
|
|
25450
25520
|
async getAUM() {
|
|
25521
|
+
const currentAUM = await this.contract.call("aum", []);
|
|
25522
|
+
const lastReportTime = await this.contract.call("last_report_timestamp", []);
|
|
25523
|
+
const token1Price = await this.pricer.getPrice(this.metadata.depositTokens[0].symbol);
|
|
25451
25524
|
const [vesuAdapter1, vesuAdapter2] = this.getVesuAdapters();
|
|
25452
25525
|
const leg1AUM = await vesuAdapter1.getPositions(this.config);
|
|
25453
25526
|
const leg2AUM = await vesuAdapter2.getPositions(this.config);
|
|
25454
|
-
const
|
|
25455
|
-
|
|
25456
|
-
|
|
25527
|
+
const balance = await new ERC20(this.config).balanceOf(this.asset().address, this.metadata.additionalInfo.vaultAllocator, this.asset().decimals);
|
|
25528
|
+
logger.verbose(`${this.getTag()} unused balance: ${balance}`);
|
|
25529
|
+
const aumToken = leg1AUM[0].amount.plus(leg2AUM[0].usdValue / token1Price.price).minus(leg1AUM[1].usdValue / token1Price.price).minus(leg2AUM[1].amount).plus(balance);
|
|
25530
|
+
logger.verbose(`${this.getTag()} Actual AUM: ${aumToken}`);
|
|
25531
|
+
const netAPY = await this.netAPY();
|
|
25532
|
+
const defispringAPY = netAPY.splits.find((s) => s.id === "defispring")?.apy || 0;
|
|
25533
|
+
if (!defispringAPY) throw new Error("DefiSpring APY not found");
|
|
25534
|
+
const timeDiff = Math.round(Date.now() / 1e3) - Number(lastReportTime);
|
|
25535
|
+
const growthRate = timeDiff * defispringAPY / (365 * 24 * 60 * 60);
|
|
25536
|
+
const prevAum = Web3Number.fromWei(currentAUM.toString(), this.asset().decimals);
|
|
25537
|
+
const rewardAssets = prevAum.multipliedBy(growthRate);
|
|
25538
|
+
logger.verbose(`${this.getTag()} DefiSpring AUM time difference: ${timeDiff}`);
|
|
25539
|
+
logger.verbose(`${this.getTag()} Current AUM: ${currentAUM}`);
|
|
25540
|
+
logger.verbose(`${this.getTag()} Net APY: ${JSON.stringify(netAPY)}`);
|
|
25541
|
+
logger.verbose(`${this.getTag()} rewards AUM: ${rewardAssets}`);
|
|
25542
|
+
const newAUM = aumToken.plus(rewardAssets);
|
|
25543
|
+
logger.verbose(`${this.getTag()} New AUM: ${newAUM}`);
|
|
25544
|
+
const net = {
|
|
25457
25545
|
tokenInfo: this.asset(),
|
|
25458
|
-
amount:
|
|
25459
|
-
usdValue:
|
|
25546
|
+
amount: newAUM,
|
|
25547
|
+
usdValue: newAUM.multipliedBy(token1Price.price).toNumber()
|
|
25460
25548
|
};
|
|
25549
|
+
const splits = [{
|
|
25550
|
+
id: "finalised",
|
|
25551
|
+
aum: aumToken
|
|
25552
|
+
}, {
|
|
25553
|
+
id: "defispring",
|
|
25554
|
+
aum: rewardAssets
|
|
25555
|
+
}];
|
|
25556
|
+
return { net, splits, prevAum };
|
|
25461
25557
|
}
|
|
25462
25558
|
getVesuAdapters() {
|
|
25463
25559
|
const vesuAdapter1 = this.getAdapter("vesu_leg1_adapter" /* VESU_LEG1 */);
|
|
25464
25560
|
const vesuAdapter2 = this.getAdapter("vesu_leg2_adapter" /* VESU_LEG2 */);
|
|
25465
25561
|
vesuAdapter1.pricer = this.pricer;
|
|
25466
25562
|
vesuAdapter2.pricer = this.pricer;
|
|
25563
|
+
vesuAdapter1.networkConfig = this.config;
|
|
25564
|
+
vesuAdapter2.networkConfig = this.config;
|
|
25467
25565
|
return [vesuAdapter1, vesuAdapter2];
|
|
25468
25566
|
}
|
|
25469
25567
|
async getVaultPositions() {
|
|
@@ -25505,12 +25603,14 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25505
25603
|
}));
|
|
25506
25604
|
const output2 = [{
|
|
25507
25605
|
proofs: manage5Info.proofs,
|
|
25508
|
-
manageCall: manageCall5
|
|
25606
|
+
manageCall: manageCall5,
|
|
25607
|
+
step: STEP2_ID
|
|
25509
25608
|
}];
|
|
25510
25609
|
if (approveAmount.gt(0)) {
|
|
25511
25610
|
output2.unshift({
|
|
25512
25611
|
proofs: manage4Info.proofs,
|
|
25513
|
-
manageCall: manageCall4
|
|
25612
|
+
manageCall: manageCall4,
|
|
25613
|
+
step: STEP1_ID
|
|
25514
25614
|
});
|
|
25515
25615
|
}
|
|
25516
25616
|
return output2;
|
|
@@ -25518,9 +25618,96 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25518
25618
|
getTag() {
|
|
25519
25619
|
return `${_UniversalStrategy.name}:${this.metadata.name}`;
|
|
25520
25620
|
}
|
|
25621
|
+
async getVesuHealthFactors() {
|
|
25622
|
+
return await Promise.all(this.getVesuAdapters().map((v) => v.getHealthFactor()));
|
|
25623
|
+
}
|
|
25624
|
+
async computeRebalanceConditionAndReturnCalls() {
|
|
25625
|
+
const vesuAdapters = this.getVesuAdapters();
|
|
25626
|
+
const healthFactors = await this.getVesuHealthFactors();
|
|
25627
|
+
const leg1HealthFactor = healthFactors[0];
|
|
25628
|
+
const leg2HealthFactor = healthFactors[1];
|
|
25629
|
+
logger.verbose(`${this.getTag()}: HealthFactorLeg1: ${leg1HealthFactor}`);
|
|
25630
|
+
logger.verbose(`${this.getTag()}: HealthFactorLeg2: ${leg2HealthFactor}`);
|
|
25631
|
+
const minHf = this.metadata.additionalInfo.minHealthFactor;
|
|
25632
|
+
const isRebalanceNeeded1 = leg1HealthFactor < minHf;
|
|
25633
|
+
const isRebalanceNeeded2 = leg2HealthFactor < minHf;
|
|
25634
|
+
if (!isRebalanceNeeded1 && !isRebalanceNeeded2) {
|
|
25635
|
+
return [];
|
|
25636
|
+
}
|
|
25637
|
+
if (isRebalanceNeeded1) {
|
|
25638
|
+
const amount = await this.getLegRebalanceAmount(vesuAdapters[0], leg1HealthFactor, false);
|
|
25639
|
+
const leg2HF = await this.getNewHealthFactor(vesuAdapters[1], amount, true);
|
|
25640
|
+
assert(leg2HF > minHf, `Rebalance Leg1 failed: Leg2 HF after rebalance would be too low: ${leg2HF}`);
|
|
25641
|
+
return [await this.getRebalanceCall({
|
|
25642
|
+
isLeg1toLeg2: false,
|
|
25643
|
+
amount
|
|
25644
|
+
})];
|
|
25645
|
+
} else {
|
|
25646
|
+
const amount = await this.getLegRebalanceAmount(vesuAdapters[1], leg2HealthFactor, true);
|
|
25647
|
+
const leg1HF = await this.getNewHealthFactor(vesuAdapters[0], amount, false);
|
|
25648
|
+
assert(leg1HF > minHf, `Rebalance Leg2 failed: Leg1 HF after rebalance would be too low: ${leg1HF}`);
|
|
25649
|
+
return [await this.getRebalanceCall({
|
|
25650
|
+
isLeg1toLeg2: true,
|
|
25651
|
+
amount
|
|
25652
|
+
})];
|
|
25653
|
+
}
|
|
25654
|
+
}
|
|
25655
|
+
async getNewHealthFactor(vesuAdapter, newAmount, isWithdraw) {
|
|
25656
|
+
const {
|
|
25657
|
+
collateralTokenAmount,
|
|
25658
|
+
collateralUSDAmount,
|
|
25659
|
+
collateralPrice,
|
|
25660
|
+
debtTokenAmount,
|
|
25661
|
+
debtUSDAmount,
|
|
25662
|
+
debtPrice,
|
|
25663
|
+
ltv
|
|
25664
|
+
} = await vesuAdapter.getAssetPrices();
|
|
25665
|
+
if (isWithdraw) {
|
|
25666
|
+
const newHF = (collateralTokenAmount.toNumber() - newAmount.toNumber()) * collateralPrice * ltv / debtUSDAmount;
|
|
25667
|
+
logger.verbose(`getNewHealthFactor:: HF: ${newHF}, amoutn: ${newAmount.toNumber()}, isDeposit`);
|
|
25668
|
+
return newHF;
|
|
25669
|
+
} else {
|
|
25670
|
+
const newHF = collateralUSDAmount * ltv / ((debtTokenAmount.toNumber() + newAmount.toNumber()) * debtPrice);
|
|
25671
|
+
logger.verbose(`getNewHealthFactor:: HF: ${newHF}, amoutn: ${newAmount.toNumber()}, isRepay`);
|
|
25672
|
+
return newHF;
|
|
25673
|
+
}
|
|
25674
|
+
}
|
|
25675
|
+
/**
|
|
25676
|
+
*
|
|
25677
|
+
* @param vesuAdapter
|
|
25678
|
+
* @param currentHf
|
|
25679
|
+
* @param isDeposit if true, attempt by adding collateral, else by repaying
|
|
25680
|
+
* @returns
|
|
25681
|
+
*/
|
|
25682
|
+
async getLegRebalanceAmount(vesuAdapter, currentHf, isDeposit) {
|
|
25683
|
+
const {
|
|
25684
|
+
collateralTokenAmount,
|
|
25685
|
+
collateralUSDAmount,
|
|
25686
|
+
collateralPrice,
|
|
25687
|
+
debtTokenAmount,
|
|
25688
|
+
debtUSDAmount,
|
|
25689
|
+
debtPrice,
|
|
25690
|
+
ltv
|
|
25691
|
+
} = await vesuAdapter.getAssetPrices();
|
|
25692
|
+
if (debtTokenAmount.isZero()) {
|
|
25693
|
+
return Web3Number.fromWei(0, 0);
|
|
25694
|
+
}
|
|
25695
|
+
assert(collateralPrice > 0 && debtPrice > 0, "getRebalanceAmount: Invalid price");
|
|
25696
|
+
const targetHF = this.metadata.additionalInfo.targetHealthFactor;
|
|
25697
|
+
if (currentHf > targetHF - 0.01)
|
|
25698
|
+
throw new Error("getLegRebalanceAmount: Current health factor is healthy");
|
|
25699
|
+
if (isDeposit) {
|
|
25700
|
+
const newAmount = targetHF * debtUSDAmount / (collateralPrice * ltv) - collateralTokenAmount.toNumber();
|
|
25701
|
+
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}`);
|
|
25702
|
+
return new Web3Number(newAmount.toFixed(8), collateralTokenAmount.decimals);
|
|
25703
|
+
} else {
|
|
25704
|
+
const newAmount = debtTokenAmount.toNumber() - collateralUSDAmount * ltv / (targetHF * debtPrice);
|
|
25705
|
+
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}`);
|
|
25706
|
+
return new Web3Number(newAmount.toFixed(8), debtTokenAmount.decimals);
|
|
25707
|
+
}
|
|
25708
|
+
}
|
|
25521
25709
|
async getVesuMultiplyCall(params) {
|
|
25522
|
-
const vesuAdapter1 = this.
|
|
25523
|
-
const vesuAdapter2 = this.getAdapter("vesu_leg2_adapter" /* VESU_LEG2 */);
|
|
25710
|
+
const [vesuAdapter1, vesuAdapter2] = this.getVesuAdapters();
|
|
25524
25711
|
const leg1LTV = await vesuAdapter1.getLTVConfig(this.config);
|
|
25525
25712
|
const leg2LTV = await vesuAdapter2.getLTVConfig(this.config);
|
|
25526
25713
|
logger.verbose(`${this.getTag()}: LTVLeg1: ${leg1LTV}`);
|
|
@@ -25529,7 +25716,7 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25529
25716
|
const token2Price = await this.pricer.getPrice(vesuAdapter2.config.collateral.symbol);
|
|
25530
25717
|
logger.verbose(`${this.getTag()}: Price${vesuAdapter1.config.collateral.symbol}: ${token1Price.price}`);
|
|
25531
25718
|
logger.verbose(`${this.getTag()}: Price${vesuAdapter2.config.collateral.symbol}: ${token2Price.price}`);
|
|
25532
|
-
const TARGET_HF =
|
|
25719
|
+
const TARGET_HF = this.metadata.additionalInfo.targetHealthFactor;
|
|
25533
25720
|
const k1 = token1Price.price * leg1LTV / token2Price.price / TARGET_HF;
|
|
25534
25721
|
const k2 = token1Price.price * TARGET_HF / token2Price.price / leg2LTV;
|
|
25535
25722
|
const borrow2Amount = new Web3Number(
|
|
@@ -25587,14 +25774,14 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
25587
25774
|
});
|
|
25588
25775
|
if (params.isLeg1toLeg2) {
|
|
25589
25776
|
const manageCall = this.getManageCall([
|
|
25590
|
-
|
|
25591
|
-
|
|
25777
|
+
...callSet1.map((i) => i.step),
|
|
25778
|
+
...callSet2.map((i) => i.step)
|
|
25592
25779
|
], [...callSet1.map((i) => i.manageCall), ...callSet2.map((i) => i.manageCall)]);
|
|
25593
25780
|
return manageCall;
|
|
25594
25781
|
} else {
|
|
25595
25782
|
const manageCall = this.getManageCall([
|
|
25596
|
-
|
|
25597
|
-
|
|
25783
|
+
...callSet2.map((i) => i.step),
|
|
25784
|
+
...callSet1.map((i) => i.step)
|
|
25598
25785
|
], [...callSet2.map((i) => i.manageCall), ...callSet1.map((i) => i.manageCall)]);
|
|
25599
25786
|
return manageCall;
|
|
25600
25787
|
}
|
|
@@ -25661,15 +25848,21 @@ var usdcVaultSettings = {
|
|
|
25661
25848
|
manager: ContractAddr.from("0xf41a2b1f498a7f9629db0b8519259e66e964260a23d20003f3e42bb1997a07"),
|
|
25662
25849
|
vaultAllocator: ContractAddr.from("0x228cca1005d3f2b55cbaba27cb291dacf1b9a92d1d6b1638195fbd3d0c1e3ba"),
|
|
25663
25850
|
redeemRequestNFT: ContractAddr.from("0x906d03590010868cbf7590ad47043959d7af8e782089a605d9b22567b64fda"),
|
|
25851
|
+
aumOracle: ContractAddr.from("0x6faf45ed185dec13ef723c9ead4266cab98d06f2cb237e331b1fa5c2aa79afe"),
|
|
25664
25852
|
leafAdapters: [],
|
|
25665
|
-
adapters: []
|
|
25853
|
+
adapters: [],
|
|
25854
|
+
targetHealthFactor: 1.3,
|
|
25855
|
+
minHealthFactor: 1.25
|
|
25666
25856
|
};
|
|
25667
25857
|
var wbtcVaultSettings = {
|
|
25668
25858
|
manager: ContractAddr.from("0xef8a664ffcfe46a6af550766d27c28937bf1b77fb4ab54d8553e92bca5ba34"),
|
|
25669
25859
|
vaultAllocator: ContractAddr.from("0x1e01c25f0d9494570226ad28a7fa856c0640505e809c366a9fab4903320e735"),
|
|
25670
25860
|
redeemRequestNFT: ContractAddr.from("0x4fec59a12f8424281c1e65a80b5de51b4e754625c60cddfcd00d46941ec37b2"),
|
|
25861
|
+
aumOracle: ContractAddr.from("0x2edf4edbed3f839e7f07dcd913e92299898ff4cf0ba532f8c572c66c5b331b2"),
|
|
25671
25862
|
leafAdapters: [],
|
|
25672
|
-
adapters: []
|
|
25863
|
+
adapters: [],
|
|
25864
|
+
targetHealthFactor: 1.3,
|
|
25865
|
+
minHealthFactor: 1.25
|
|
25673
25866
|
};
|
|
25674
25867
|
var UniversalStrategies = [
|
|
25675
25868
|
{
|
|
@@ -25719,13 +25912,10 @@ var TelegramNotif = class {
|
|
|
25719
25912
|
this.subscribers = [
|
|
25720
25913
|
// '6820228303',
|
|
25721
25914
|
"1505578076",
|
|
25722
|
-
// '5434736198', // maaza
|
|
25723
25915
|
"1356705582",
|
|
25724
25916
|
// langs
|
|
25725
25917
|
"1388729514",
|
|
25726
25918
|
// hwashere
|
|
25727
|
-
"6020162572",
|
|
25728
|
-
//minato
|
|
25729
25919
|
"985902592"
|
|
25730
25920
|
];
|
|
25731
25921
|
this.bot = new TelegramBot(token, { polling: shouldPoll });
|
|
@@ -26002,7 +26192,7 @@ function getAccount(accountKey, config, password = process.env.ACCOUNT_SECURE_PA
|
|
|
26002
26192
|
...storeConfig,
|
|
26003
26193
|
PASSWORD: password
|
|
26004
26194
|
});
|
|
26005
|
-
return store.getAccount(accountKey);
|
|
26195
|
+
return store.getAccount(accountKey, "0x3");
|
|
26006
26196
|
}
|
|
26007
26197
|
async function myDeclare(contract_name, package_name = "strkfarm", config, acc) {
|
|
26008
26198
|
const provider2 = config.provider;
|
package/package.json
CHANGED
package/src/node/deployer.ts
CHANGED
|
@@ -36,7 +36,7 @@ function getAccount(
|
|
|
36
36
|
PASSWORD: password
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
return store.getAccount(accountKey);
|
|
39
|
+
return store.getAccount(accountKey, '0x3');
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
async function myDeclare(contract_name: string, package_name: string = 'strkfarm', config: IConfig, acc: Account) {
|
package/src/notifs/telegram.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ContractAddr, Web3Number } from "@/dataTypes";
|
|
2
2
|
import { IConfig, TokenInfo } from "@/interfaces";
|
|
3
|
+
import { CacheClass } from "@/utils/cacheClass";
|
|
3
4
|
import { Call } from "starknet";
|
|
4
5
|
|
|
5
6
|
export interface SingleActionAmount {
|
|
@@ -26,11 +27,12 @@ interface CacheData {
|
|
|
26
27
|
ttl: number;
|
|
27
28
|
data: any;
|
|
28
29
|
}
|
|
29
|
-
export class BaseStrategy<TVLInfo, ActionInfo> {
|
|
30
|
+
export class BaseStrategy<TVLInfo, ActionInfo> extends CacheClass {
|
|
30
31
|
readonly config: IConfig;
|
|
31
32
|
readonly cache: Map<string, CacheData> = new Map();
|
|
32
33
|
|
|
33
34
|
constructor(config: IConfig) {
|
|
35
|
+
super();
|
|
34
36
|
this.config = config;
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -49,26 +51,4 @@ export class BaseStrategy<TVLInfo, ActionInfo> {
|
|
|
49
51
|
async withdrawCall(amountInfo: ActionInfo, receiver: ContractAddr, owner: ContractAddr): Promise<Call[]> {
|
|
50
52
|
throw new Error("Not implemented");
|
|
51
53
|
}
|
|
52
|
-
|
|
53
|
-
setCache(key: string, data: any, ttl: number = 60000): void {
|
|
54
|
-
const timestamp = Date.now();
|
|
55
|
-
this.cache.set(key, { timestamp, ttl, data });
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
getCache(key: string): any | null {
|
|
59
|
-
const cachedData = this.cache.get(key);
|
|
60
|
-
if (!cachedData || !this.isCacheValid(key)) {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
return cachedData.data;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
isCacheValid(key: string): boolean {
|
|
67
|
-
const cachedData = this.cache.get(key);
|
|
68
|
-
if (!cachedData) return false;
|
|
69
|
-
|
|
70
|
-
const { timestamp, ttl } = cachedData;
|
|
71
|
-
return Date.now() - timestamp <= ttl;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
54
|
}
|
package/src/strategies/sensei.ts
CHANGED
|
@@ -126,9 +126,16 @@ export class SenseiVault extends BaseStrategy<
|
|
|
126
126
|
collateralInSTRK: number;
|
|
127
127
|
}> {
|
|
128
128
|
const CACHE_KEY = 'positionInfo';
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
const existingCacheData = this.getCache<{
|
|
130
|
+
collateralXSTRK: Web3Number;
|
|
131
|
+
collateralUSDValue: Web3Number;
|
|
132
|
+
debtSTRK: Web3Number;
|
|
133
|
+
debtUSDValue: Web3Number;
|
|
134
|
+
xSTRKPrice: number;
|
|
135
|
+
collateralInSTRK: number;
|
|
136
|
+
}>(CACHE_KEY);
|
|
137
|
+
if (existingCacheData) return existingCacheData;
|
|
138
|
+
|
|
132
139
|
const resp = await fetch(
|
|
133
140
|
`${getTrovesEndpoint()}/vesu/positions?walletAddress=${this.address.address}`,
|
|
134
141
|
);
|
|
@@ -179,9 +186,9 @@ export class SenseiVault extends BaseStrategy<
|
|
|
179
186
|
|
|
180
187
|
async getSecondaryTokenPriceRelativeToMain(retry = 0): Promise<number> {
|
|
181
188
|
const CACHE_KEY = 'xSTRKPrice';
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
189
|
+
const existingCacheData = this.getCache<number>(CACHE_KEY);
|
|
190
|
+
if (existingCacheData) return existingCacheData;
|
|
191
|
+
|
|
185
192
|
const params: QuoteRequest = {
|
|
186
193
|
sellTokenAddress: this.metadata.additionalInfo.secondaryToken.address.address,
|
|
187
194
|
buyTokenAddress: this.metadata.additionalInfo.mainToken.address.address,
|
|
@@ -2,6 +2,7 @@ import { Call, hash, num, shortString } from "starknet";
|
|
|
2
2
|
import { SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
|
|
3
3
|
import { ContractAddr } from "@/dataTypes";
|
|
4
4
|
import { LeafData } from "@/utils";
|
|
5
|
+
import { CacheClass } from "@/utils/cacheClass";
|
|
5
6
|
|
|
6
7
|
export interface ManageCall {
|
|
7
8
|
sanitizer: ContractAddr,
|
|
@@ -16,7 +17,7 @@ export type GenerateCallFn<T> = (params: T) => ManageCall;
|
|
|
16
17
|
export type AdapterLeafType<T> = {leaf: LeafData, callConstructor: GenerateCallFn<T>}
|
|
17
18
|
export type LeafAdapterFn<T> = () => AdapterLeafType<T>;
|
|
18
19
|
|
|
19
|
-
export class BaseAdapter {
|
|
20
|
+
export class BaseAdapter extends CacheClass {
|
|
20
21
|
|
|
21
22
|
protected constructSimpleLeafData(params: {
|
|
22
23
|
id: string,
|