@strkfarm/sdk 1.0.22 → 1.0.23
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/cli.js +9 -6
- package/dist/cli.mjs +9 -6
- package/dist/index.browser.global.js +33 -16
- package/dist/index.browser.mjs +33 -16
- package/dist/index.d.ts +3 -2
- package/dist/index.js +33 -16
- package/dist/index.mjs +33 -16
- package/package.json +2 -1
- package/src/dataTypes/_bignumber.ts +11 -7
- package/src/strategies/vesu-rebalance.ts +25 -12
package/dist/cli.js
CHANGED
|
@@ -101,26 +101,26 @@ var _Web3Number = class extends import_bignumber.default {
|
|
|
101
101
|
return this.mul(10 ** this.decimals).toFixed(0);
|
|
102
102
|
}
|
|
103
103
|
multipliedBy(value) {
|
|
104
|
-
let _value = Number(value).toFixed(
|
|
104
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
105
105
|
return this.construct(this.mul(_value).toString(), this.decimals);
|
|
106
106
|
}
|
|
107
107
|
dividedBy(value) {
|
|
108
|
-
let _value = Number(value).toFixed(
|
|
108
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
109
109
|
return this.construct(this.div(_value).toString(), this.decimals);
|
|
110
110
|
}
|
|
111
111
|
plus(value) {
|
|
112
|
-
const _value = Number(value).toFixed(
|
|
112
|
+
const _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
113
113
|
return this.construct(this.add(_value).toString(), this.decimals);
|
|
114
114
|
}
|
|
115
115
|
minus(n, base) {
|
|
116
|
-
const _value = Number(n).toFixed(
|
|
116
|
+
const _value = Number(n).toFixed(this.maxToFixedDecimals());
|
|
117
117
|
return this.construct(super.minus(_value, base).toString(), this.decimals);
|
|
118
118
|
}
|
|
119
119
|
construct(value, decimals) {
|
|
120
120
|
return new this.constructor(value, decimals);
|
|
121
121
|
}
|
|
122
|
-
toString(
|
|
123
|
-
return super.
|
|
122
|
+
toString(decimals = this.maxToFixedDecimals()) {
|
|
123
|
+
return super.toFixed(decimals);
|
|
124
124
|
}
|
|
125
125
|
toJSON() {
|
|
126
126
|
return this.toString();
|
|
@@ -128,6 +128,9 @@ var _Web3Number = class extends import_bignumber.default {
|
|
|
128
128
|
valueOf() {
|
|
129
129
|
return this.toString();
|
|
130
130
|
}
|
|
131
|
+
maxToFixedDecimals() {
|
|
132
|
+
return Math.min(this.decimals, 13);
|
|
133
|
+
}
|
|
131
134
|
};
|
|
132
135
|
import_bignumber.default.config({ DECIMAL_PLACES: 18 });
|
|
133
136
|
_Web3Number.config({ DECIMAL_PLACES: 18 });
|
package/dist/cli.mjs
CHANGED
|
@@ -78,26 +78,26 @@ var _Web3Number = class extends BigNumber {
|
|
|
78
78
|
return this.mul(10 ** this.decimals).toFixed(0);
|
|
79
79
|
}
|
|
80
80
|
multipliedBy(value) {
|
|
81
|
-
let _value = Number(value).toFixed(
|
|
81
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
82
82
|
return this.construct(this.mul(_value).toString(), this.decimals);
|
|
83
83
|
}
|
|
84
84
|
dividedBy(value) {
|
|
85
|
-
let _value = Number(value).toFixed(
|
|
85
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
86
86
|
return this.construct(this.div(_value).toString(), this.decimals);
|
|
87
87
|
}
|
|
88
88
|
plus(value) {
|
|
89
|
-
const _value = Number(value).toFixed(
|
|
89
|
+
const _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
90
90
|
return this.construct(this.add(_value).toString(), this.decimals);
|
|
91
91
|
}
|
|
92
92
|
minus(n, base) {
|
|
93
|
-
const _value = Number(n).toFixed(
|
|
93
|
+
const _value = Number(n).toFixed(this.maxToFixedDecimals());
|
|
94
94
|
return this.construct(super.minus(_value, base).toString(), this.decimals);
|
|
95
95
|
}
|
|
96
96
|
construct(value, decimals) {
|
|
97
97
|
return new this.constructor(value, decimals);
|
|
98
98
|
}
|
|
99
|
-
toString(
|
|
100
|
-
return super.
|
|
99
|
+
toString(decimals = this.maxToFixedDecimals()) {
|
|
100
|
+
return super.toFixed(decimals);
|
|
101
101
|
}
|
|
102
102
|
toJSON() {
|
|
103
103
|
return this.toString();
|
|
@@ -105,6 +105,9 @@ var _Web3Number = class extends BigNumber {
|
|
|
105
105
|
valueOf() {
|
|
106
106
|
return this.toString();
|
|
107
107
|
}
|
|
108
|
+
maxToFixedDecimals() {
|
|
109
|
+
return Math.min(this.decimals, 13);
|
|
110
|
+
}
|
|
108
111
|
};
|
|
109
112
|
BigNumber.config({ DECIMAL_PLACES: 18 });
|
|
110
113
|
_Web3Number.config({ DECIMAL_PLACES: 18 });
|
|
@@ -18507,26 +18507,26 @@ var strkfarm_risk_engine = (() => {
|
|
|
18507
18507
|
return this.mul(10 ** this.decimals).toFixed(0);
|
|
18508
18508
|
}
|
|
18509
18509
|
multipliedBy(value) {
|
|
18510
|
-
let _value = Number(value).toFixed(
|
|
18510
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
18511
18511
|
return this.construct(this.mul(_value).toString(), this.decimals);
|
|
18512
18512
|
}
|
|
18513
18513
|
dividedBy(value) {
|
|
18514
|
-
let _value = Number(value).toFixed(
|
|
18514
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
18515
18515
|
return this.construct(this.div(_value).toString(), this.decimals);
|
|
18516
18516
|
}
|
|
18517
18517
|
plus(value) {
|
|
18518
|
-
const _value = Number(value).toFixed(
|
|
18518
|
+
const _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
18519
18519
|
return this.construct(this.add(_value).toString(), this.decimals);
|
|
18520
18520
|
}
|
|
18521
18521
|
minus(n, base2) {
|
|
18522
|
-
const _value = Number(n).toFixed(
|
|
18522
|
+
const _value = Number(n).toFixed(this.maxToFixedDecimals());
|
|
18523
18523
|
return this.construct(super.minus(_value, base2).toString(), this.decimals);
|
|
18524
18524
|
}
|
|
18525
18525
|
construct(value, decimals) {
|
|
18526
18526
|
return new this.constructor(value, decimals);
|
|
18527
18527
|
}
|
|
18528
|
-
toString(
|
|
18529
|
-
return super.
|
|
18528
|
+
toString(decimals = this.maxToFixedDecimals()) {
|
|
18529
|
+
return super.toFixed(decimals);
|
|
18530
18530
|
}
|
|
18531
18531
|
toJSON() {
|
|
18532
18532
|
return this.toString();
|
|
@@ -18534,6 +18534,9 @@ var strkfarm_risk_engine = (() => {
|
|
|
18534
18534
|
valueOf() {
|
|
18535
18535
|
return this.toString();
|
|
18536
18536
|
}
|
|
18537
|
+
maxToFixedDecimals() {
|
|
18538
|
+
return Math.min(this.decimals, 13);
|
|
18539
|
+
}
|
|
18537
18540
|
};
|
|
18538
18541
|
import_bignumber.default.config({ DECIMAL_PLACES: 18 });
|
|
18539
18542
|
_Web3Number.config({ DECIMAL_PLACES: 18 });
|
|
@@ -38698,7 +38701,9 @@ var strkfarm_risk_engine = (() => {
|
|
|
38698
38701
|
const totalAssets = (await this.getTVL()).amount;
|
|
38699
38702
|
const info = allowedPools.map(async (p) => {
|
|
38700
38703
|
const vesuPosition = vesuPositions.find((d) => d.pool.id.toString() === num_exports.getDecimalString(p.pool_id.address.toString()));
|
|
38701
|
-
const pool = pools.find((d) =>
|
|
38704
|
+
const pool = pools.find((d) => {
|
|
38705
|
+
return d.id == num_exports.getDecimalString(p.pool_id.address.toString());
|
|
38706
|
+
});
|
|
38702
38707
|
const assetInfo = pool?.assets.find((d) => this.asset().address.eqString(d.address));
|
|
38703
38708
|
let vTokenContract = new Contract(vesu_rebalance_abi_default, p.v_token.address, this.config.provider);
|
|
38704
38709
|
const bal = await vTokenContract.balanceOf(this.address.address);
|
|
@@ -38746,11 +38751,13 @@ var strkfarm_risk_engine = (() => {
|
|
|
38746
38751
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
38747
38752
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
38748
38753
|
*/
|
|
38749
|
-
netAPYGivenPools(pools) {
|
|
38750
|
-
const
|
|
38754
|
+
async netAPYGivenPools(pools) {
|
|
38755
|
+
const weightedApyNumerator = pools.reduce((acc, curr) => {
|
|
38751
38756
|
const weight = curr.current_weight;
|
|
38752
|
-
return acc + curr.APY.netApy *
|
|
38757
|
+
return acc + curr.APY.netApy * Number(curr.amount.toString());
|
|
38753
38758
|
}, 0);
|
|
38759
|
+
const totalAssets = (await this.getTVL()).amount;
|
|
38760
|
+
const weightedApy = weightedApyNumerator / Number(totalAssets.toString());
|
|
38754
38761
|
return weightedApy * (1 - this.metadata.additionalInfo.feeBps / 1e4);
|
|
38755
38762
|
}
|
|
38756
38763
|
/**
|
|
@@ -38779,14 +38786,21 @@ var strkfarm_risk_engine = (() => {
|
|
|
38779
38786
|
finalPools: []
|
|
38780
38787
|
};
|
|
38781
38788
|
const sumPools = pools.reduce((acc, curr) => acc.plus(curr.amount.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
38782
|
-
|
|
38789
|
+
logger.verbose(`Sum of pools: ${sumPools.toString()}`);
|
|
38790
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
38791
|
+
assert3(sumPools.lte(totalAssets.multipliedBy(1.00001).toString()), "Sum of pools.amount must be less than or equal to totalAssets");
|
|
38783
38792
|
const sortedPools = [...pools].sort((a, b) => b.APY.netApy - a.APY.netApy);
|
|
38784
38793
|
const targetAmounts = {};
|
|
38785
38794
|
let remainingAssets = totalAssets;
|
|
38795
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
38786
38796
|
let isAnyPoolOverMaxWeight = false;
|
|
38787
38797
|
for (const pool of sortedPools) {
|
|
38788
|
-
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.
|
|
38798
|
+
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.98);
|
|
38789
38799
|
const targetAmount = remainingAssets.gte(maxAmount) ? maxAmount : remainingAssets;
|
|
38800
|
+
logger.verbose(`Target amount: ${targetAmount.toString()}`);
|
|
38801
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
38802
|
+
logger.verbose(`Max amount: ${maxAmount.toString()}`);
|
|
38803
|
+
logger.verbose(`pool.max_weight: ${pool.max_weight}`);
|
|
38790
38804
|
targetAmounts[pool.pool_id.address.toString()] = targetAmount;
|
|
38791
38805
|
remainingAssets = remainingAssets.minus(targetAmount.toString());
|
|
38792
38806
|
if (pool.current_weight > pool.max_weight) {
|
|
@@ -38804,11 +38818,15 @@ var strkfarm_risk_engine = (() => {
|
|
|
38804
38818
|
isDeposit: change.gt(0)
|
|
38805
38819
|
};
|
|
38806
38820
|
});
|
|
38821
|
+
logger.verbose(`Changes: ${JSON.stringify(changes)}`);
|
|
38807
38822
|
const sumChanges = changes.reduce((sum, c) => sum.plus(c.changeAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
38808
38823
|
const sumFinal = changes.reduce((sum, c) => sum.plus(c.finalAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
38809
38824
|
const hasChanges = changes.some((c) => !c.changeAmt.eq(0));
|
|
38810
38825
|
if (!sumChanges.eq(0)) throw new Error("Sum of changes must be zero");
|
|
38811
|
-
|
|
38826
|
+
logger.verbose(`Sum of changes: ${sumChanges.toString()}`);
|
|
38827
|
+
logger.verbose(`Sum of final: ${sumFinal.toString()}`);
|
|
38828
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
38829
|
+
if (!sumFinal.eq(totalAssets.toString())) throw new Error("Sum of final amounts must equal total assets");
|
|
38812
38830
|
if (!hasChanges) throw new Error("No changes required");
|
|
38813
38831
|
const finalPools = pools.map((p) => {
|
|
38814
38832
|
const target = targetAmounts[p.pool_id.address.toString()] || Web3Number.fromWei("0", this.decimals());
|
|
@@ -38832,13 +38850,12 @@ var strkfarm_risk_engine = (() => {
|
|
|
38832
38850
|
async getRebalanceCall(pools, isOverWeightAdjustment) {
|
|
38833
38851
|
const actions = [];
|
|
38834
38852
|
pools.sort((a, b) => b.isDeposit ? -1 : 1);
|
|
38835
|
-
console.log("pools", pools);
|
|
38836
38853
|
pools.forEach((p) => {
|
|
38837
38854
|
if (p.changeAmt.eq(0)) return null;
|
|
38838
38855
|
actions.push({
|
|
38839
38856
|
pool_id: p.pool_id.address,
|
|
38840
38857
|
feature: new CairoCustomEnum(p.isDeposit ? { DEPOSIT: {} } : { WITHDRAW: {} }),
|
|
38841
|
-
token: this.asset().address,
|
|
38858
|
+
token: this.asset().address.address,
|
|
38842
38859
|
amount: uint256_exports.bnToUint256(p.changeAmt.multipliedBy(p.isDeposit ? 1 : -1).toWei())
|
|
38843
38860
|
});
|
|
38844
38861
|
});
|
|
@@ -38849,7 +38866,7 @@ var strkfarm_risk_engine = (() => {
|
|
|
38849
38866
|
return this.contract.populate("rebalance", [actions]);
|
|
38850
38867
|
}
|
|
38851
38868
|
async getInvestmentFlows(pools) {
|
|
38852
|
-
const netYield = this.netAPYGivenPools(pools);
|
|
38869
|
+
const netYield = await this.netAPYGivenPools(pools);
|
|
38853
38870
|
const baseFlow = {
|
|
38854
38871
|
title: "Your Deposit",
|
|
38855
38872
|
subItems: [{ key: `Net yield`, value: `${(netYield * 100).toFixed(2)}%` }],
|
package/dist/index.browser.mjs
CHANGED
|
@@ -15,26 +15,26 @@ var _Web3Number = class extends BigNumber {
|
|
|
15
15
|
return this.mul(10 ** this.decimals).toFixed(0);
|
|
16
16
|
}
|
|
17
17
|
multipliedBy(value) {
|
|
18
|
-
let _value = Number(value).toFixed(
|
|
18
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
19
19
|
return this.construct(this.mul(_value).toString(), this.decimals);
|
|
20
20
|
}
|
|
21
21
|
dividedBy(value) {
|
|
22
|
-
let _value = Number(value).toFixed(
|
|
22
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
23
23
|
return this.construct(this.div(_value).toString(), this.decimals);
|
|
24
24
|
}
|
|
25
25
|
plus(value) {
|
|
26
|
-
const _value = Number(value).toFixed(
|
|
26
|
+
const _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
27
27
|
return this.construct(this.add(_value).toString(), this.decimals);
|
|
28
28
|
}
|
|
29
29
|
minus(n, base) {
|
|
30
|
-
const _value = Number(n).toFixed(
|
|
30
|
+
const _value = Number(n).toFixed(this.maxToFixedDecimals());
|
|
31
31
|
return this.construct(super.minus(_value, base).toString(), this.decimals);
|
|
32
32
|
}
|
|
33
33
|
construct(value, decimals) {
|
|
34
34
|
return new this.constructor(value, decimals);
|
|
35
35
|
}
|
|
36
|
-
toString(
|
|
37
|
-
return super.
|
|
36
|
+
toString(decimals = this.maxToFixedDecimals()) {
|
|
37
|
+
return super.toFixed(decimals);
|
|
38
38
|
}
|
|
39
39
|
toJSON() {
|
|
40
40
|
return this.toString();
|
|
@@ -42,6 +42,9 @@ var _Web3Number = class extends BigNumber {
|
|
|
42
42
|
valueOf() {
|
|
43
43
|
return this.toString();
|
|
44
44
|
}
|
|
45
|
+
maxToFixedDecimals() {
|
|
46
|
+
return Math.min(this.decimals, 13);
|
|
47
|
+
}
|
|
45
48
|
};
|
|
46
49
|
BigNumber.config({ DECIMAL_PLACES: 18 });
|
|
47
50
|
_Web3Number.config({ DECIMAL_PLACES: 18 });
|
|
@@ -3710,7 +3713,9 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3710
3713
|
const totalAssets = (await this.getTVL()).amount;
|
|
3711
3714
|
const info = allowedPools.map(async (p) => {
|
|
3712
3715
|
const vesuPosition = vesuPositions.find((d) => d.pool.id.toString() === num2.getDecimalString(p.pool_id.address.toString()));
|
|
3713
|
-
const pool = pools.find((d) =>
|
|
3716
|
+
const pool = pools.find((d) => {
|
|
3717
|
+
return d.id == num2.getDecimalString(p.pool_id.address.toString());
|
|
3718
|
+
});
|
|
3714
3719
|
const assetInfo = pool?.assets.find((d) => this.asset().address.eqString(d.address));
|
|
3715
3720
|
let vTokenContract = new Contract4(vesu_rebalance_abi_default, p.v_token.address, this.config.provider);
|
|
3716
3721
|
const bal = await vTokenContract.balanceOf(this.address.address);
|
|
@@ -3758,11 +3763,13 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3758
3763
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
3759
3764
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
3760
3765
|
*/
|
|
3761
|
-
netAPYGivenPools(pools) {
|
|
3762
|
-
const
|
|
3766
|
+
async netAPYGivenPools(pools) {
|
|
3767
|
+
const weightedApyNumerator = pools.reduce((acc, curr) => {
|
|
3763
3768
|
const weight = curr.current_weight;
|
|
3764
|
-
return acc + curr.APY.netApy *
|
|
3769
|
+
return acc + curr.APY.netApy * Number(curr.amount.toString());
|
|
3765
3770
|
}, 0);
|
|
3771
|
+
const totalAssets = (await this.getTVL()).amount;
|
|
3772
|
+
const weightedApy = weightedApyNumerator / Number(totalAssets.toString());
|
|
3766
3773
|
return weightedApy * (1 - this.metadata.additionalInfo.feeBps / 1e4);
|
|
3767
3774
|
}
|
|
3768
3775
|
/**
|
|
@@ -3791,14 +3798,21 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3791
3798
|
finalPools: []
|
|
3792
3799
|
};
|
|
3793
3800
|
const sumPools = pools.reduce((acc, curr) => acc.plus(curr.amount.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3794
|
-
|
|
3801
|
+
logger.verbose(`Sum of pools: ${sumPools.toString()}`);
|
|
3802
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3803
|
+
assert(sumPools.lte(totalAssets.multipliedBy(1.00001).toString()), "Sum of pools.amount must be less than or equal to totalAssets");
|
|
3795
3804
|
const sortedPools = [...pools].sort((a, b) => b.APY.netApy - a.APY.netApy);
|
|
3796
3805
|
const targetAmounts = {};
|
|
3797
3806
|
let remainingAssets = totalAssets;
|
|
3807
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3798
3808
|
let isAnyPoolOverMaxWeight = false;
|
|
3799
3809
|
for (const pool of sortedPools) {
|
|
3800
|
-
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.
|
|
3810
|
+
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.98);
|
|
3801
3811
|
const targetAmount = remainingAssets.gte(maxAmount) ? maxAmount : remainingAssets;
|
|
3812
|
+
logger.verbose(`Target amount: ${targetAmount.toString()}`);
|
|
3813
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3814
|
+
logger.verbose(`Max amount: ${maxAmount.toString()}`);
|
|
3815
|
+
logger.verbose(`pool.max_weight: ${pool.max_weight}`);
|
|
3802
3816
|
targetAmounts[pool.pool_id.address.toString()] = targetAmount;
|
|
3803
3817
|
remainingAssets = remainingAssets.minus(targetAmount.toString());
|
|
3804
3818
|
if (pool.current_weight > pool.max_weight) {
|
|
@@ -3816,11 +3830,15 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3816
3830
|
isDeposit: change.gt(0)
|
|
3817
3831
|
};
|
|
3818
3832
|
});
|
|
3833
|
+
logger.verbose(`Changes: ${JSON.stringify(changes)}`);
|
|
3819
3834
|
const sumChanges = changes.reduce((sum, c) => sum.plus(c.changeAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3820
3835
|
const sumFinal = changes.reduce((sum, c) => sum.plus(c.finalAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3821
3836
|
const hasChanges = changes.some((c) => !c.changeAmt.eq(0));
|
|
3822
3837
|
if (!sumChanges.eq(0)) throw new Error("Sum of changes must be zero");
|
|
3823
|
-
|
|
3838
|
+
logger.verbose(`Sum of changes: ${sumChanges.toString()}`);
|
|
3839
|
+
logger.verbose(`Sum of final: ${sumFinal.toString()}`);
|
|
3840
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3841
|
+
if (!sumFinal.eq(totalAssets.toString())) throw new Error("Sum of final amounts must equal total assets");
|
|
3824
3842
|
if (!hasChanges) throw new Error("No changes required");
|
|
3825
3843
|
const finalPools = pools.map((p) => {
|
|
3826
3844
|
const target = targetAmounts[p.pool_id.address.toString()] || Web3Number.fromWei("0", this.decimals());
|
|
@@ -3844,13 +3862,12 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3844
3862
|
async getRebalanceCall(pools, isOverWeightAdjustment) {
|
|
3845
3863
|
const actions = [];
|
|
3846
3864
|
pools.sort((a, b) => b.isDeposit ? -1 : 1);
|
|
3847
|
-
console.log("pools", pools);
|
|
3848
3865
|
pools.forEach((p) => {
|
|
3849
3866
|
if (p.changeAmt.eq(0)) return null;
|
|
3850
3867
|
actions.push({
|
|
3851
3868
|
pool_id: p.pool_id.address,
|
|
3852
3869
|
feature: new CairoCustomEnum(p.isDeposit ? { DEPOSIT: {} } : { WITHDRAW: {} }),
|
|
3853
|
-
token: this.asset().address,
|
|
3870
|
+
token: this.asset().address.address,
|
|
3854
3871
|
amount: uint2563.bnToUint256(p.changeAmt.multipliedBy(p.isDeposit ? 1 : -1).toWei())
|
|
3855
3872
|
});
|
|
3856
3873
|
});
|
|
@@ -3861,7 +3878,7 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3861
3878
|
return this.contract.populate("rebalance", [actions]);
|
|
3862
3879
|
}
|
|
3863
3880
|
async getInvestmentFlows(pools) {
|
|
3864
|
-
const netYield = this.netAPYGivenPools(pools);
|
|
3881
|
+
const netYield = await this.netAPYGivenPools(pools);
|
|
3865
3882
|
const baseFlow = {
|
|
3866
3883
|
title: "Your Deposit",
|
|
3867
3884
|
subItems: [{ key: `Net yield`, value: `${(netYield * 100).toFixed(2)}%` }],
|
package/dist/index.d.ts
CHANGED
|
@@ -14,9 +14,10 @@ declare class _Web3Number<T extends _Web3Number<T>> extends BigNumber {
|
|
|
14
14
|
plus(value: string | number | T): T;
|
|
15
15
|
minus(n: number | string | T, base?: number): T;
|
|
16
16
|
protected construct(value: string | number, decimals: number): T;
|
|
17
|
-
toString(
|
|
17
|
+
toString(decimals?: number | undefined): string;
|
|
18
18
|
toJSON(): string;
|
|
19
19
|
valueOf(): string;
|
|
20
|
+
private maxToFixedDecimals;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
declare class Web3Number extends _Web3Number<Web3Number> {
|
|
@@ -530,7 +531,7 @@ declare class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAm
|
|
|
530
531
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
531
532
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
532
533
|
*/
|
|
533
|
-
netAPYGivenPools(pools: PoolInfoFull[]): number
|
|
534
|
+
netAPYGivenPools(pools: PoolInfoFull[]): Promise<number>;
|
|
534
535
|
/**
|
|
535
536
|
* Calculates optimal position changes to maximize APY while respecting max weights.
|
|
536
537
|
* The algorithm:
|
package/dist/index.js
CHANGED
|
@@ -86,26 +86,26 @@ var _Web3Number = class extends import_bignumber.default {
|
|
|
86
86
|
return this.mul(10 ** this.decimals).toFixed(0);
|
|
87
87
|
}
|
|
88
88
|
multipliedBy(value) {
|
|
89
|
-
let _value = Number(value).toFixed(
|
|
89
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
90
90
|
return this.construct(this.mul(_value).toString(), this.decimals);
|
|
91
91
|
}
|
|
92
92
|
dividedBy(value) {
|
|
93
|
-
let _value = Number(value).toFixed(
|
|
93
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
94
94
|
return this.construct(this.div(_value).toString(), this.decimals);
|
|
95
95
|
}
|
|
96
96
|
plus(value) {
|
|
97
|
-
const _value = Number(value).toFixed(
|
|
97
|
+
const _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
98
98
|
return this.construct(this.add(_value).toString(), this.decimals);
|
|
99
99
|
}
|
|
100
100
|
minus(n, base) {
|
|
101
|
-
const _value = Number(n).toFixed(
|
|
101
|
+
const _value = Number(n).toFixed(this.maxToFixedDecimals());
|
|
102
102
|
return this.construct(super.minus(_value, base).toString(), this.decimals);
|
|
103
103
|
}
|
|
104
104
|
construct(value, decimals) {
|
|
105
105
|
return new this.constructor(value, decimals);
|
|
106
106
|
}
|
|
107
|
-
toString(
|
|
108
|
-
return super.
|
|
107
|
+
toString(decimals = this.maxToFixedDecimals()) {
|
|
108
|
+
return super.toFixed(decimals);
|
|
109
109
|
}
|
|
110
110
|
toJSON() {
|
|
111
111
|
return this.toString();
|
|
@@ -113,6 +113,9 @@ var _Web3Number = class extends import_bignumber.default {
|
|
|
113
113
|
valueOf() {
|
|
114
114
|
return this.toString();
|
|
115
115
|
}
|
|
116
|
+
maxToFixedDecimals() {
|
|
117
|
+
return Math.min(this.decimals, 13);
|
|
118
|
+
}
|
|
116
119
|
};
|
|
117
120
|
import_bignumber.default.config({ DECIMAL_PLACES: 18 });
|
|
118
121
|
_Web3Number.config({ DECIMAL_PLACES: 18 });
|
|
@@ -3798,7 +3801,9 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3798
3801
|
const totalAssets = (await this.getTVL()).amount;
|
|
3799
3802
|
const info = allowedPools.map(async (p) => {
|
|
3800
3803
|
const vesuPosition = vesuPositions.find((d) => d.pool.id.toString() === import_starknet7.num.getDecimalString(p.pool_id.address.toString()));
|
|
3801
|
-
const pool = pools.find((d) =>
|
|
3804
|
+
const pool = pools.find((d) => {
|
|
3805
|
+
return d.id == import_starknet7.num.getDecimalString(p.pool_id.address.toString());
|
|
3806
|
+
});
|
|
3802
3807
|
const assetInfo = pool?.assets.find((d) => this.asset().address.eqString(d.address));
|
|
3803
3808
|
let vTokenContract = new import_starknet7.Contract(vesu_rebalance_abi_default, p.v_token.address, this.config.provider);
|
|
3804
3809
|
const bal = await vTokenContract.balanceOf(this.address.address);
|
|
@@ -3846,11 +3851,13 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3846
3851
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
3847
3852
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
3848
3853
|
*/
|
|
3849
|
-
netAPYGivenPools(pools) {
|
|
3850
|
-
const
|
|
3854
|
+
async netAPYGivenPools(pools) {
|
|
3855
|
+
const weightedApyNumerator = pools.reduce((acc, curr) => {
|
|
3851
3856
|
const weight = curr.current_weight;
|
|
3852
|
-
return acc + curr.APY.netApy *
|
|
3857
|
+
return acc + curr.APY.netApy * Number(curr.amount.toString());
|
|
3853
3858
|
}, 0);
|
|
3859
|
+
const totalAssets = (await this.getTVL()).amount;
|
|
3860
|
+
const weightedApy = weightedApyNumerator / Number(totalAssets.toString());
|
|
3854
3861
|
return weightedApy * (1 - this.metadata.additionalInfo.feeBps / 1e4);
|
|
3855
3862
|
}
|
|
3856
3863
|
/**
|
|
@@ -3879,14 +3886,21 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3879
3886
|
finalPools: []
|
|
3880
3887
|
};
|
|
3881
3888
|
const sumPools = pools.reduce((acc, curr) => acc.plus(curr.amount.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3882
|
-
|
|
3889
|
+
logger.verbose(`Sum of pools: ${sumPools.toString()}`);
|
|
3890
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3891
|
+
assert(sumPools.lte(totalAssets.multipliedBy(1.00001).toString()), "Sum of pools.amount must be less than or equal to totalAssets");
|
|
3883
3892
|
const sortedPools = [...pools].sort((a, b) => b.APY.netApy - a.APY.netApy);
|
|
3884
3893
|
const targetAmounts = {};
|
|
3885
3894
|
let remainingAssets = totalAssets;
|
|
3895
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3886
3896
|
let isAnyPoolOverMaxWeight = false;
|
|
3887
3897
|
for (const pool of sortedPools) {
|
|
3888
|
-
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.
|
|
3898
|
+
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.98);
|
|
3889
3899
|
const targetAmount = remainingAssets.gte(maxAmount) ? maxAmount : remainingAssets;
|
|
3900
|
+
logger.verbose(`Target amount: ${targetAmount.toString()}`);
|
|
3901
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3902
|
+
logger.verbose(`Max amount: ${maxAmount.toString()}`);
|
|
3903
|
+
logger.verbose(`pool.max_weight: ${pool.max_weight}`);
|
|
3890
3904
|
targetAmounts[pool.pool_id.address.toString()] = targetAmount;
|
|
3891
3905
|
remainingAssets = remainingAssets.minus(targetAmount.toString());
|
|
3892
3906
|
if (pool.current_weight > pool.max_weight) {
|
|
@@ -3904,11 +3918,15 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3904
3918
|
isDeposit: change.gt(0)
|
|
3905
3919
|
};
|
|
3906
3920
|
});
|
|
3921
|
+
logger.verbose(`Changes: ${JSON.stringify(changes)}`);
|
|
3907
3922
|
const sumChanges = changes.reduce((sum, c) => sum.plus(c.changeAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3908
3923
|
const sumFinal = changes.reduce((sum, c) => sum.plus(c.finalAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3909
3924
|
const hasChanges = changes.some((c) => !c.changeAmt.eq(0));
|
|
3910
3925
|
if (!sumChanges.eq(0)) throw new Error("Sum of changes must be zero");
|
|
3911
|
-
|
|
3926
|
+
logger.verbose(`Sum of changes: ${sumChanges.toString()}`);
|
|
3927
|
+
logger.verbose(`Sum of final: ${sumFinal.toString()}`);
|
|
3928
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3929
|
+
if (!sumFinal.eq(totalAssets.toString())) throw new Error("Sum of final amounts must equal total assets");
|
|
3912
3930
|
if (!hasChanges) throw new Error("No changes required");
|
|
3913
3931
|
const finalPools = pools.map((p) => {
|
|
3914
3932
|
const target = targetAmounts[p.pool_id.address.toString()] || Web3Number.fromWei("0", this.decimals());
|
|
@@ -3932,13 +3950,12 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3932
3950
|
async getRebalanceCall(pools, isOverWeightAdjustment) {
|
|
3933
3951
|
const actions = [];
|
|
3934
3952
|
pools.sort((a, b) => b.isDeposit ? -1 : 1);
|
|
3935
|
-
console.log("pools", pools);
|
|
3936
3953
|
pools.forEach((p) => {
|
|
3937
3954
|
if (p.changeAmt.eq(0)) return null;
|
|
3938
3955
|
actions.push({
|
|
3939
3956
|
pool_id: p.pool_id.address,
|
|
3940
3957
|
feature: new import_starknet7.CairoCustomEnum(p.isDeposit ? { DEPOSIT: {} } : { WITHDRAW: {} }),
|
|
3941
|
-
token: this.asset().address,
|
|
3958
|
+
token: this.asset().address.address,
|
|
3942
3959
|
amount: import_starknet7.uint256.bnToUint256(p.changeAmt.multipliedBy(p.isDeposit ? 1 : -1).toWei())
|
|
3943
3960
|
});
|
|
3944
3961
|
});
|
|
@@ -3949,7 +3966,7 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3949
3966
|
return this.contract.populate("rebalance", [actions]);
|
|
3950
3967
|
}
|
|
3951
3968
|
async getInvestmentFlows(pools) {
|
|
3952
|
-
const netYield = this.netAPYGivenPools(pools);
|
|
3969
|
+
const netYield = await this.netAPYGivenPools(pools);
|
|
3953
3970
|
const baseFlow = {
|
|
3954
3971
|
title: "Your Deposit",
|
|
3955
3972
|
subItems: [{ key: `Net yield`, value: `${(netYield * 100).toFixed(2)}%` }],
|
package/dist/index.mjs
CHANGED
|
@@ -18,26 +18,26 @@ var _Web3Number = class extends BigNumber {
|
|
|
18
18
|
return this.mul(10 ** this.decimals).toFixed(0);
|
|
19
19
|
}
|
|
20
20
|
multipliedBy(value) {
|
|
21
|
-
let _value = Number(value).toFixed(
|
|
21
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
22
22
|
return this.construct(this.mul(_value).toString(), this.decimals);
|
|
23
23
|
}
|
|
24
24
|
dividedBy(value) {
|
|
25
|
-
let _value = Number(value).toFixed(
|
|
25
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
26
26
|
return this.construct(this.div(_value).toString(), this.decimals);
|
|
27
27
|
}
|
|
28
28
|
plus(value) {
|
|
29
|
-
const _value = Number(value).toFixed(
|
|
29
|
+
const _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
30
30
|
return this.construct(this.add(_value).toString(), this.decimals);
|
|
31
31
|
}
|
|
32
32
|
minus(n, base) {
|
|
33
|
-
const _value = Number(n).toFixed(
|
|
33
|
+
const _value = Number(n).toFixed(this.maxToFixedDecimals());
|
|
34
34
|
return this.construct(super.minus(_value, base).toString(), this.decimals);
|
|
35
35
|
}
|
|
36
36
|
construct(value, decimals) {
|
|
37
37
|
return new this.constructor(value, decimals);
|
|
38
38
|
}
|
|
39
|
-
toString(
|
|
40
|
-
return super.
|
|
39
|
+
toString(decimals = this.maxToFixedDecimals()) {
|
|
40
|
+
return super.toFixed(decimals);
|
|
41
41
|
}
|
|
42
42
|
toJSON() {
|
|
43
43
|
return this.toString();
|
|
@@ -45,6 +45,9 @@ var _Web3Number = class extends BigNumber {
|
|
|
45
45
|
valueOf() {
|
|
46
46
|
return this.toString();
|
|
47
47
|
}
|
|
48
|
+
maxToFixedDecimals() {
|
|
49
|
+
return Math.min(this.decimals, 13);
|
|
50
|
+
}
|
|
48
51
|
};
|
|
49
52
|
BigNumber.config({ DECIMAL_PLACES: 18 });
|
|
50
53
|
_Web3Number.config({ DECIMAL_PLACES: 18 });
|
|
@@ -3730,7 +3733,9 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3730
3733
|
const totalAssets = (await this.getTVL()).amount;
|
|
3731
3734
|
const info = allowedPools.map(async (p) => {
|
|
3732
3735
|
const vesuPosition = vesuPositions.find((d) => d.pool.id.toString() === num2.getDecimalString(p.pool_id.address.toString()));
|
|
3733
|
-
const pool = pools.find((d) =>
|
|
3736
|
+
const pool = pools.find((d) => {
|
|
3737
|
+
return d.id == num2.getDecimalString(p.pool_id.address.toString());
|
|
3738
|
+
});
|
|
3734
3739
|
const assetInfo = pool?.assets.find((d) => this.asset().address.eqString(d.address));
|
|
3735
3740
|
let vTokenContract = new Contract4(vesu_rebalance_abi_default, p.v_token.address, this.config.provider);
|
|
3736
3741
|
const bal = await vTokenContract.balanceOf(this.address.address);
|
|
@@ -3778,11 +3783,13 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3778
3783
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
3779
3784
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
3780
3785
|
*/
|
|
3781
|
-
netAPYGivenPools(pools) {
|
|
3782
|
-
const
|
|
3786
|
+
async netAPYGivenPools(pools) {
|
|
3787
|
+
const weightedApyNumerator = pools.reduce((acc, curr) => {
|
|
3783
3788
|
const weight = curr.current_weight;
|
|
3784
|
-
return acc + curr.APY.netApy *
|
|
3789
|
+
return acc + curr.APY.netApy * Number(curr.amount.toString());
|
|
3785
3790
|
}, 0);
|
|
3791
|
+
const totalAssets = (await this.getTVL()).amount;
|
|
3792
|
+
const weightedApy = weightedApyNumerator / Number(totalAssets.toString());
|
|
3786
3793
|
return weightedApy * (1 - this.metadata.additionalInfo.feeBps / 1e4);
|
|
3787
3794
|
}
|
|
3788
3795
|
/**
|
|
@@ -3811,14 +3818,21 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3811
3818
|
finalPools: []
|
|
3812
3819
|
};
|
|
3813
3820
|
const sumPools = pools.reduce((acc, curr) => acc.plus(curr.amount.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3814
|
-
|
|
3821
|
+
logger.verbose(`Sum of pools: ${sumPools.toString()}`);
|
|
3822
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3823
|
+
assert(sumPools.lte(totalAssets.multipliedBy(1.00001).toString()), "Sum of pools.amount must be less than or equal to totalAssets");
|
|
3815
3824
|
const sortedPools = [...pools].sort((a, b) => b.APY.netApy - a.APY.netApy);
|
|
3816
3825
|
const targetAmounts = {};
|
|
3817
3826
|
let remainingAssets = totalAssets;
|
|
3827
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3818
3828
|
let isAnyPoolOverMaxWeight = false;
|
|
3819
3829
|
for (const pool of sortedPools) {
|
|
3820
|
-
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.
|
|
3830
|
+
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.98);
|
|
3821
3831
|
const targetAmount = remainingAssets.gte(maxAmount) ? maxAmount : remainingAssets;
|
|
3832
|
+
logger.verbose(`Target amount: ${targetAmount.toString()}`);
|
|
3833
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3834
|
+
logger.verbose(`Max amount: ${maxAmount.toString()}`);
|
|
3835
|
+
logger.verbose(`pool.max_weight: ${pool.max_weight}`);
|
|
3822
3836
|
targetAmounts[pool.pool_id.address.toString()] = targetAmount;
|
|
3823
3837
|
remainingAssets = remainingAssets.minus(targetAmount.toString());
|
|
3824
3838
|
if (pool.current_weight > pool.max_weight) {
|
|
@@ -3836,11 +3850,15 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3836
3850
|
isDeposit: change.gt(0)
|
|
3837
3851
|
};
|
|
3838
3852
|
});
|
|
3853
|
+
logger.verbose(`Changes: ${JSON.stringify(changes)}`);
|
|
3839
3854
|
const sumChanges = changes.reduce((sum, c) => sum.plus(c.changeAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3840
3855
|
const sumFinal = changes.reduce((sum, c) => sum.plus(c.finalAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3841
3856
|
const hasChanges = changes.some((c) => !c.changeAmt.eq(0));
|
|
3842
3857
|
if (!sumChanges.eq(0)) throw new Error("Sum of changes must be zero");
|
|
3843
|
-
|
|
3858
|
+
logger.verbose(`Sum of changes: ${sumChanges.toString()}`);
|
|
3859
|
+
logger.verbose(`Sum of final: ${sumFinal.toString()}`);
|
|
3860
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3861
|
+
if (!sumFinal.eq(totalAssets.toString())) throw new Error("Sum of final amounts must equal total assets");
|
|
3844
3862
|
if (!hasChanges) throw new Error("No changes required");
|
|
3845
3863
|
const finalPools = pools.map((p) => {
|
|
3846
3864
|
const target = targetAmounts[p.pool_id.address.toString()] || Web3Number.fromWei("0", this.decimals());
|
|
@@ -3864,13 +3882,12 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3864
3882
|
async getRebalanceCall(pools, isOverWeightAdjustment) {
|
|
3865
3883
|
const actions = [];
|
|
3866
3884
|
pools.sort((a, b) => b.isDeposit ? -1 : 1);
|
|
3867
|
-
console.log("pools", pools);
|
|
3868
3885
|
pools.forEach((p) => {
|
|
3869
3886
|
if (p.changeAmt.eq(0)) return null;
|
|
3870
3887
|
actions.push({
|
|
3871
3888
|
pool_id: p.pool_id.address,
|
|
3872
3889
|
feature: new CairoCustomEnum(p.isDeposit ? { DEPOSIT: {} } : { WITHDRAW: {} }),
|
|
3873
|
-
token: this.asset().address,
|
|
3890
|
+
token: this.asset().address.address,
|
|
3874
3891
|
amount: uint2563.bnToUint256(p.changeAmt.multipliedBy(p.isDeposit ? 1 : -1).toWei())
|
|
3875
3892
|
});
|
|
3876
3893
|
});
|
|
@@ -3881,7 +3898,7 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3881
3898
|
return this.contract.populate("rebalance", [actions]);
|
|
3882
3899
|
}
|
|
3883
3900
|
async getInvestmentFlows(pools) {
|
|
3884
|
-
const netYield = this.netAPYGivenPools(pools);
|
|
3901
|
+
const netYield = await this.netAPYGivenPools(pools);
|
|
3885
3902
|
const baseFlow = {
|
|
3886
3903
|
title: "Your Deposit",
|
|
3887
3904
|
subItems: [{ key: `Net yield`, value: `${(netYield * 100).toFixed(2)}%` }],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strkfarm/sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"description": "STRKFarm TS SDK (Meant for our internal use, but feel free to use it)",
|
|
5
5
|
"typings": "dist/index.d.ts",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"browser-assert": "^1.2.1",
|
|
57
57
|
"chalk": "^4.1.2",
|
|
58
58
|
"commander": "^12.1.0",
|
|
59
|
+
"ethers": "^6.13.5",
|
|
59
60
|
"form-data": "^4.0.2",
|
|
60
61
|
"inquirer": "^10.1.2",
|
|
61
62
|
"node-telegram-bot-api": "^0.66.0",
|
|
@@ -13,22 +13,22 @@ export class _Web3Number<T extends _Web3Number<T>> extends BigNumber {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
multipliedBy(value: string | number | T): T {
|
|
16
|
-
let _value = Number(value).toFixed(
|
|
16
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
17
17
|
return this.construct(this.mul(_value).toString(), this.decimals);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
dividedBy(value: string | number | T): T {
|
|
21
|
-
let _value = Number(value).toFixed(
|
|
21
|
+
let _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
22
22
|
return this.construct(this.div(_value).toString(), this.decimals);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
plus(value: string | number | T): T {
|
|
26
|
-
const _value = Number(value).toFixed(
|
|
26
|
+
const _value = Number(value).toFixed(this.maxToFixedDecimals());
|
|
27
27
|
return this.construct(this.add(_value).toString(), this.decimals);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
minus(n: number | string | T, base?: number): T {
|
|
31
|
-
const _value = Number(n).toFixed(
|
|
31
|
+
const _value = Number(n).toFixed(this.maxToFixedDecimals());
|
|
32
32
|
return this.construct(super.minus(_value, base).toString(), this.decimals);
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -36,10 +36,10 @@ export class _Web3Number<T extends _Web3Number<T>> extends BigNumber {
|
|
|
36
36
|
return new (this.constructor as { new (value: string | number, decimals: number): T })(value, decimals);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
toString(
|
|
40
|
-
return super.
|
|
39
|
+
toString(decimals: number | undefined = this.maxToFixedDecimals()): string {
|
|
40
|
+
return super.toFixed(decimals);
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
toJSON() {
|
|
44
44
|
return this.toString();
|
|
45
45
|
}
|
|
@@ -47,6 +47,10 @@ export class _Web3Number<T extends _Web3Number<T>> extends BigNumber {
|
|
|
47
47
|
valueOf() {
|
|
48
48
|
return this.toString();
|
|
49
49
|
}
|
|
50
|
+
|
|
51
|
+
private maxToFixedDecimals() {
|
|
52
|
+
return Math.min(this.decimals, 13);
|
|
53
|
+
}
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
BigNumber.config({ DECIMAL_PLACES: 18 })
|
|
@@ -3,7 +3,7 @@ import { FlowChartColors, getNoRiskTags, IConfig, IInvestmentFlow, IProtocol, IS
|
|
|
3
3
|
import { Pricer } from "@/modules";
|
|
4
4
|
import { CairoCustomEnum, Contract, num, uint256 } from "starknet";
|
|
5
5
|
import VesuRebalanceAbi from '@/data/vesu-rebalance.abi.json';
|
|
6
|
-
import { Global } from "@/global";
|
|
6
|
+
import { Global, logger } from "@/global";
|
|
7
7
|
import { assert } from "@/utils";
|
|
8
8
|
import axios from "axios";
|
|
9
9
|
import { PricerBase } from "@/modules/pricerBase";
|
|
@@ -264,7 +264,9 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
264
264
|
|
|
265
265
|
const info = allowedPools.map(async (p) => {
|
|
266
266
|
const vesuPosition = vesuPositions.find((d: any) => d.pool.id.toString() === num.getDecimalString(p.pool_id.address.toString()));
|
|
267
|
-
const pool = pools.find((d: any) =>
|
|
267
|
+
const pool = pools.find((d: any) => {
|
|
268
|
+
return d.id == num.getDecimalString(p.pool_id.address.toString());
|
|
269
|
+
});
|
|
268
270
|
const assetInfo = pool?.assets.find((d: any) => this.asset().address.eqString(d.address));
|
|
269
271
|
let vTokenContract = new Contract(VesuRebalanceAbi, p.v_token.address, this.config.provider);
|
|
270
272
|
const bal = await vTokenContract.balanceOf(this.address.address);
|
|
@@ -314,12 +316,13 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
314
316
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
315
317
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
316
318
|
*/
|
|
317
|
-
netAPYGivenPools(pools: PoolInfoFull[]): number {
|
|
318
|
-
const
|
|
319
|
+
async netAPYGivenPools(pools: PoolInfoFull[]): Promise<number> {
|
|
320
|
+
const weightedApyNumerator = pools.reduce((acc: number, curr) => {
|
|
319
321
|
const weight = curr.current_weight;
|
|
320
|
-
return acc + (curr.APY.netApy *
|
|
322
|
+
return acc + (curr.APY.netApy * Number(curr.amount.toString()));
|
|
321
323
|
}, 0);
|
|
322
|
-
|
|
324
|
+
const totalAssets = (await this.getTVL()).amount;
|
|
325
|
+
const weightedApy = weightedApyNumerator / Number(totalAssets.toString());
|
|
323
326
|
return weightedApy * (1 - (this.metadata.additionalInfo.feeBps / 10000));
|
|
324
327
|
}
|
|
325
328
|
|
|
@@ -351,18 +354,25 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
351
354
|
|
|
352
355
|
// assert sum of pools.amount <= totalAssets
|
|
353
356
|
const sumPools = pools.reduce((acc, curr) => acc.plus(curr.amount.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
354
|
-
|
|
357
|
+
logger.verbose(`Sum of pools: ${sumPools.toString()}`);
|
|
358
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
359
|
+
assert(sumPools.lte(totalAssets.multipliedBy(1.00001).toString()), 'Sum of pools.amount must be less than or equal to totalAssets');
|
|
355
360
|
|
|
356
361
|
// Sort pools by APY and calculate target amounts
|
|
357
362
|
const sortedPools = [...pools].sort((a, b) => b.APY.netApy - a.APY.netApy);
|
|
358
363
|
const targetAmounts: Record<string, Web3Number> = {};
|
|
359
364
|
let remainingAssets = totalAssets;
|
|
365
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
360
366
|
|
|
361
367
|
// First pass: Allocate to high APY pools up to their max weight
|
|
362
368
|
let isAnyPoolOverMaxWeight = false;
|
|
363
369
|
for (const pool of sortedPools) {
|
|
364
|
-
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.
|
|
370
|
+
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.98); // some tolerance
|
|
365
371
|
const targetAmount = remainingAssets.gte(maxAmount) ? maxAmount : remainingAssets;
|
|
372
|
+
logger.verbose(`Target amount: ${targetAmount.toString()}`);
|
|
373
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
374
|
+
logger.verbose(`Max amount: ${maxAmount.toString()}`);
|
|
375
|
+
logger.verbose(`pool.max_weight: ${pool.max_weight}`);
|
|
366
376
|
targetAmounts[pool.pool_id.address.toString()] = targetAmount;
|
|
367
377
|
remainingAssets = remainingAssets.minus(targetAmount.toString());
|
|
368
378
|
if (pool.current_weight > pool.max_weight) {
|
|
@@ -384,13 +394,17 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
384
394
|
};
|
|
385
395
|
});
|
|
386
396
|
|
|
397
|
+
logger.verbose(`Changes: ${JSON.stringify(changes)}`);
|
|
387
398
|
// Validate changes
|
|
388
399
|
const sumChanges = changes.reduce((sum, c) => sum.plus(c.changeAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
389
400
|
const sumFinal = changes.reduce((sum, c) => sum.plus(c.finalAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
390
401
|
const hasChanges = changes.some(c => !c.changeAmt.eq(0));
|
|
391
402
|
|
|
392
403
|
if (!sumChanges.eq(0)) throw new Error('Sum of changes must be zero');
|
|
393
|
-
|
|
404
|
+
logger.verbose(`Sum of changes: ${sumChanges.toString()}`);
|
|
405
|
+
logger.verbose(`Sum of final: ${sumFinal.toString()}`);
|
|
406
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
407
|
+
if (!sumFinal.eq(totalAssets.toString())) throw new Error('Sum of final amounts must equal total assets');
|
|
394
408
|
if (!hasChanges) throw new Error('No changes required');
|
|
395
409
|
|
|
396
410
|
const finalPools: PoolInfoFull[] = pools.map((p) => {
|
|
@@ -420,13 +434,12 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
420
434
|
const actions: any[] = [];
|
|
421
435
|
// sort to put withdrawals first
|
|
422
436
|
pools.sort((a, b) => b.isDeposit ? -1 : 1);
|
|
423
|
-
console.log('pools', pools);
|
|
424
437
|
pools.forEach((p) => {
|
|
425
438
|
if (p.changeAmt.eq(0)) return null;
|
|
426
439
|
actions.push({
|
|
427
440
|
pool_id: p.pool_id.address,
|
|
428
441
|
feature: new CairoCustomEnum(p.isDeposit ? {DEPOSIT: {}} : {WITHDRAW: {}}),
|
|
429
|
-
token: this.asset().address,
|
|
442
|
+
token: this.asset().address.address,
|
|
430
443
|
amount: uint256.bnToUint256(p.changeAmt.multipliedBy(p.isDeposit ? 1 : -1).toWei()),
|
|
431
444
|
});
|
|
432
445
|
});
|
|
@@ -438,7 +451,7 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
438
451
|
}
|
|
439
452
|
|
|
440
453
|
async getInvestmentFlows(pools: PoolInfoFull[]) {
|
|
441
|
-
const netYield = this.netAPYGivenPools(pools);
|
|
454
|
+
const netYield = await this.netAPYGivenPools(pools);
|
|
442
455
|
|
|
443
456
|
const baseFlow: IInvestmentFlow = {
|
|
444
457
|
title: "Your Deposit",
|