@strkfarm/sdk 1.0.22 → 1.0.24
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 +35 -16
- package/dist/index.browser.mjs +35 -16
- package/dist/index.d.ts +3 -2
- package/dist/index.js +35 -16
- package/dist/index.mjs +35 -16
- package/package.json +2 -1
- package/src/dataTypes/_bignumber.ts +11 -7
- package/src/strategies/vesu-rebalance.ts +27 -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,11 @@ 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
|
+
logger.verbose(`pool check: ${d.id == num_exports.getDecimalString(p.pool_id.address.toString())}, id: ${d.id}, pool_id: ${num_exports.getDecimalString(p.pool_id.address.toString())}`);
|
|
38706
|
+
return d.id == num_exports.getDecimalString(p.pool_id.address.toString());
|
|
38707
|
+
});
|
|
38708
|
+
logger.verbose(`pool: ${JSON.stringify(pool)}`);
|
|
38702
38709
|
const assetInfo = pool?.assets.find((d) => this.asset().address.eqString(d.address));
|
|
38703
38710
|
let vTokenContract = new Contract(vesu_rebalance_abi_default, p.v_token.address, this.config.provider);
|
|
38704
38711
|
const bal = await vTokenContract.balanceOf(this.address.address);
|
|
@@ -38746,11 +38753,13 @@ var strkfarm_risk_engine = (() => {
|
|
|
38746
38753
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
38747
38754
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
38748
38755
|
*/
|
|
38749
|
-
netAPYGivenPools(pools) {
|
|
38750
|
-
const
|
|
38756
|
+
async netAPYGivenPools(pools) {
|
|
38757
|
+
const weightedApyNumerator = pools.reduce((acc, curr) => {
|
|
38751
38758
|
const weight = curr.current_weight;
|
|
38752
|
-
return acc + curr.APY.netApy *
|
|
38759
|
+
return acc + curr.APY.netApy * Number(curr.amount.toString());
|
|
38753
38760
|
}, 0);
|
|
38761
|
+
const totalAssets = (await this.getTVL()).amount;
|
|
38762
|
+
const weightedApy = weightedApyNumerator / Number(totalAssets.toString());
|
|
38754
38763
|
return weightedApy * (1 - this.metadata.additionalInfo.feeBps / 1e4);
|
|
38755
38764
|
}
|
|
38756
38765
|
/**
|
|
@@ -38779,14 +38788,21 @@ var strkfarm_risk_engine = (() => {
|
|
|
38779
38788
|
finalPools: []
|
|
38780
38789
|
};
|
|
38781
38790
|
const sumPools = pools.reduce((acc, curr) => acc.plus(curr.amount.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
38782
|
-
|
|
38791
|
+
logger.verbose(`Sum of pools: ${sumPools.toString()}`);
|
|
38792
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
38793
|
+
assert3(sumPools.lte(totalAssets.multipliedBy(1.00001).toString()), "Sum of pools.amount must be less than or equal to totalAssets");
|
|
38783
38794
|
const sortedPools = [...pools].sort((a, b) => b.APY.netApy - a.APY.netApy);
|
|
38784
38795
|
const targetAmounts = {};
|
|
38785
38796
|
let remainingAssets = totalAssets;
|
|
38797
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
38786
38798
|
let isAnyPoolOverMaxWeight = false;
|
|
38787
38799
|
for (const pool of sortedPools) {
|
|
38788
|
-
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.
|
|
38800
|
+
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.98);
|
|
38789
38801
|
const targetAmount = remainingAssets.gte(maxAmount) ? maxAmount : remainingAssets;
|
|
38802
|
+
logger.verbose(`Target amount: ${targetAmount.toString()}`);
|
|
38803
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
38804
|
+
logger.verbose(`Max amount: ${maxAmount.toString()}`);
|
|
38805
|
+
logger.verbose(`pool.max_weight: ${pool.max_weight}`);
|
|
38790
38806
|
targetAmounts[pool.pool_id.address.toString()] = targetAmount;
|
|
38791
38807
|
remainingAssets = remainingAssets.minus(targetAmount.toString());
|
|
38792
38808
|
if (pool.current_weight > pool.max_weight) {
|
|
@@ -38804,11 +38820,15 @@ var strkfarm_risk_engine = (() => {
|
|
|
38804
38820
|
isDeposit: change.gt(0)
|
|
38805
38821
|
};
|
|
38806
38822
|
});
|
|
38823
|
+
logger.verbose(`Changes: ${JSON.stringify(changes)}`);
|
|
38807
38824
|
const sumChanges = changes.reduce((sum, c) => sum.plus(c.changeAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
38808
38825
|
const sumFinal = changes.reduce((sum, c) => sum.plus(c.finalAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
38809
38826
|
const hasChanges = changes.some((c) => !c.changeAmt.eq(0));
|
|
38810
38827
|
if (!sumChanges.eq(0)) throw new Error("Sum of changes must be zero");
|
|
38811
|
-
|
|
38828
|
+
logger.verbose(`Sum of changes: ${sumChanges.toString()}`);
|
|
38829
|
+
logger.verbose(`Sum of final: ${sumFinal.toString()}`);
|
|
38830
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
38831
|
+
if (!sumFinal.eq(totalAssets.toString())) throw new Error("Sum of final amounts must equal total assets");
|
|
38812
38832
|
if (!hasChanges) throw new Error("No changes required");
|
|
38813
38833
|
const finalPools = pools.map((p) => {
|
|
38814
38834
|
const target = targetAmounts[p.pool_id.address.toString()] || Web3Number.fromWei("0", this.decimals());
|
|
@@ -38832,13 +38852,12 @@ var strkfarm_risk_engine = (() => {
|
|
|
38832
38852
|
async getRebalanceCall(pools, isOverWeightAdjustment) {
|
|
38833
38853
|
const actions = [];
|
|
38834
38854
|
pools.sort((a, b) => b.isDeposit ? -1 : 1);
|
|
38835
|
-
console.log("pools", pools);
|
|
38836
38855
|
pools.forEach((p) => {
|
|
38837
38856
|
if (p.changeAmt.eq(0)) return null;
|
|
38838
38857
|
actions.push({
|
|
38839
38858
|
pool_id: p.pool_id.address,
|
|
38840
38859
|
feature: new CairoCustomEnum(p.isDeposit ? { DEPOSIT: {} } : { WITHDRAW: {} }),
|
|
38841
|
-
token: this.asset().address,
|
|
38860
|
+
token: this.asset().address.address,
|
|
38842
38861
|
amount: uint256_exports.bnToUint256(p.changeAmt.multipliedBy(p.isDeposit ? 1 : -1).toWei())
|
|
38843
38862
|
});
|
|
38844
38863
|
});
|
|
@@ -38849,7 +38868,7 @@ var strkfarm_risk_engine = (() => {
|
|
|
38849
38868
|
return this.contract.populate("rebalance", [actions]);
|
|
38850
38869
|
}
|
|
38851
38870
|
async getInvestmentFlows(pools) {
|
|
38852
|
-
const netYield = this.netAPYGivenPools(pools);
|
|
38871
|
+
const netYield = await this.netAPYGivenPools(pools);
|
|
38853
38872
|
const baseFlow = {
|
|
38854
38873
|
title: "Your Deposit",
|
|
38855
38874
|
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,11 @@ 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
|
+
logger.verbose(`pool check: ${d.id == num2.getDecimalString(p.pool_id.address.toString())}, id: ${d.id}, pool_id: ${num2.getDecimalString(p.pool_id.address.toString())}`);
|
|
3718
|
+
return d.id == num2.getDecimalString(p.pool_id.address.toString());
|
|
3719
|
+
});
|
|
3720
|
+
logger.verbose(`pool: ${JSON.stringify(pool)}`);
|
|
3714
3721
|
const assetInfo = pool?.assets.find((d) => this.asset().address.eqString(d.address));
|
|
3715
3722
|
let vTokenContract = new Contract4(vesu_rebalance_abi_default, p.v_token.address, this.config.provider);
|
|
3716
3723
|
const bal = await vTokenContract.balanceOf(this.address.address);
|
|
@@ -3758,11 +3765,13 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3758
3765
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
3759
3766
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
3760
3767
|
*/
|
|
3761
|
-
netAPYGivenPools(pools) {
|
|
3762
|
-
const
|
|
3768
|
+
async netAPYGivenPools(pools) {
|
|
3769
|
+
const weightedApyNumerator = pools.reduce((acc, curr) => {
|
|
3763
3770
|
const weight = curr.current_weight;
|
|
3764
|
-
return acc + curr.APY.netApy *
|
|
3771
|
+
return acc + curr.APY.netApy * Number(curr.amount.toString());
|
|
3765
3772
|
}, 0);
|
|
3773
|
+
const totalAssets = (await this.getTVL()).amount;
|
|
3774
|
+
const weightedApy = weightedApyNumerator / Number(totalAssets.toString());
|
|
3766
3775
|
return weightedApy * (1 - this.metadata.additionalInfo.feeBps / 1e4);
|
|
3767
3776
|
}
|
|
3768
3777
|
/**
|
|
@@ -3791,14 +3800,21 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3791
3800
|
finalPools: []
|
|
3792
3801
|
};
|
|
3793
3802
|
const sumPools = pools.reduce((acc, curr) => acc.plus(curr.amount.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3794
|
-
|
|
3803
|
+
logger.verbose(`Sum of pools: ${sumPools.toString()}`);
|
|
3804
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3805
|
+
assert(sumPools.lte(totalAssets.multipliedBy(1.00001).toString()), "Sum of pools.amount must be less than or equal to totalAssets");
|
|
3795
3806
|
const sortedPools = [...pools].sort((a, b) => b.APY.netApy - a.APY.netApy);
|
|
3796
3807
|
const targetAmounts = {};
|
|
3797
3808
|
let remainingAssets = totalAssets;
|
|
3809
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3798
3810
|
let isAnyPoolOverMaxWeight = false;
|
|
3799
3811
|
for (const pool of sortedPools) {
|
|
3800
|
-
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.
|
|
3812
|
+
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.98);
|
|
3801
3813
|
const targetAmount = remainingAssets.gte(maxAmount) ? maxAmount : remainingAssets;
|
|
3814
|
+
logger.verbose(`Target amount: ${targetAmount.toString()}`);
|
|
3815
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3816
|
+
logger.verbose(`Max amount: ${maxAmount.toString()}`);
|
|
3817
|
+
logger.verbose(`pool.max_weight: ${pool.max_weight}`);
|
|
3802
3818
|
targetAmounts[pool.pool_id.address.toString()] = targetAmount;
|
|
3803
3819
|
remainingAssets = remainingAssets.minus(targetAmount.toString());
|
|
3804
3820
|
if (pool.current_weight > pool.max_weight) {
|
|
@@ -3816,11 +3832,15 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3816
3832
|
isDeposit: change.gt(0)
|
|
3817
3833
|
};
|
|
3818
3834
|
});
|
|
3835
|
+
logger.verbose(`Changes: ${JSON.stringify(changes)}`);
|
|
3819
3836
|
const sumChanges = changes.reduce((sum, c) => sum.plus(c.changeAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3820
3837
|
const sumFinal = changes.reduce((sum, c) => sum.plus(c.finalAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3821
3838
|
const hasChanges = changes.some((c) => !c.changeAmt.eq(0));
|
|
3822
3839
|
if (!sumChanges.eq(0)) throw new Error("Sum of changes must be zero");
|
|
3823
|
-
|
|
3840
|
+
logger.verbose(`Sum of changes: ${sumChanges.toString()}`);
|
|
3841
|
+
logger.verbose(`Sum of final: ${sumFinal.toString()}`);
|
|
3842
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3843
|
+
if (!sumFinal.eq(totalAssets.toString())) throw new Error("Sum of final amounts must equal total assets");
|
|
3824
3844
|
if (!hasChanges) throw new Error("No changes required");
|
|
3825
3845
|
const finalPools = pools.map((p) => {
|
|
3826
3846
|
const target = targetAmounts[p.pool_id.address.toString()] || Web3Number.fromWei("0", this.decimals());
|
|
@@ -3844,13 +3864,12 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3844
3864
|
async getRebalanceCall(pools, isOverWeightAdjustment) {
|
|
3845
3865
|
const actions = [];
|
|
3846
3866
|
pools.sort((a, b) => b.isDeposit ? -1 : 1);
|
|
3847
|
-
console.log("pools", pools);
|
|
3848
3867
|
pools.forEach((p) => {
|
|
3849
3868
|
if (p.changeAmt.eq(0)) return null;
|
|
3850
3869
|
actions.push({
|
|
3851
3870
|
pool_id: p.pool_id.address,
|
|
3852
3871
|
feature: new CairoCustomEnum(p.isDeposit ? { DEPOSIT: {} } : { WITHDRAW: {} }),
|
|
3853
|
-
token: this.asset().address,
|
|
3872
|
+
token: this.asset().address.address,
|
|
3854
3873
|
amount: uint2563.bnToUint256(p.changeAmt.multipliedBy(p.isDeposit ? 1 : -1).toWei())
|
|
3855
3874
|
});
|
|
3856
3875
|
});
|
|
@@ -3861,7 +3880,7 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3861
3880
|
return this.contract.populate("rebalance", [actions]);
|
|
3862
3881
|
}
|
|
3863
3882
|
async getInvestmentFlows(pools) {
|
|
3864
|
-
const netYield = this.netAPYGivenPools(pools);
|
|
3883
|
+
const netYield = await this.netAPYGivenPools(pools);
|
|
3865
3884
|
const baseFlow = {
|
|
3866
3885
|
title: "Your Deposit",
|
|
3867
3886
|
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,11 @@ 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
|
+
logger.verbose(`pool check: ${d.id == import_starknet7.num.getDecimalString(p.pool_id.address.toString())}, id: ${d.id}, pool_id: ${import_starknet7.num.getDecimalString(p.pool_id.address.toString())}`);
|
|
3806
|
+
return d.id == import_starknet7.num.getDecimalString(p.pool_id.address.toString());
|
|
3807
|
+
});
|
|
3808
|
+
logger.verbose(`pool: ${JSON.stringify(pool)}`);
|
|
3802
3809
|
const assetInfo = pool?.assets.find((d) => this.asset().address.eqString(d.address));
|
|
3803
3810
|
let vTokenContract = new import_starknet7.Contract(vesu_rebalance_abi_default, p.v_token.address, this.config.provider);
|
|
3804
3811
|
const bal = await vTokenContract.balanceOf(this.address.address);
|
|
@@ -3846,11 +3853,13 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3846
3853
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
3847
3854
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
3848
3855
|
*/
|
|
3849
|
-
netAPYGivenPools(pools) {
|
|
3850
|
-
const
|
|
3856
|
+
async netAPYGivenPools(pools) {
|
|
3857
|
+
const weightedApyNumerator = pools.reduce((acc, curr) => {
|
|
3851
3858
|
const weight = curr.current_weight;
|
|
3852
|
-
return acc + curr.APY.netApy *
|
|
3859
|
+
return acc + curr.APY.netApy * Number(curr.amount.toString());
|
|
3853
3860
|
}, 0);
|
|
3861
|
+
const totalAssets = (await this.getTVL()).amount;
|
|
3862
|
+
const weightedApy = weightedApyNumerator / Number(totalAssets.toString());
|
|
3854
3863
|
return weightedApy * (1 - this.metadata.additionalInfo.feeBps / 1e4);
|
|
3855
3864
|
}
|
|
3856
3865
|
/**
|
|
@@ -3879,14 +3888,21 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3879
3888
|
finalPools: []
|
|
3880
3889
|
};
|
|
3881
3890
|
const sumPools = pools.reduce((acc, curr) => acc.plus(curr.amount.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3882
|
-
|
|
3891
|
+
logger.verbose(`Sum of pools: ${sumPools.toString()}`);
|
|
3892
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3893
|
+
assert(sumPools.lte(totalAssets.multipliedBy(1.00001).toString()), "Sum of pools.amount must be less than or equal to totalAssets");
|
|
3883
3894
|
const sortedPools = [...pools].sort((a, b) => b.APY.netApy - a.APY.netApy);
|
|
3884
3895
|
const targetAmounts = {};
|
|
3885
3896
|
let remainingAssets = totalAssets;
|
|
3897
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3886
3898
|
let isAnyPoolOverMaxWeight = false;
|
|
3887
3899
|
for (const pool of sortedPools) {
|
|
3888
|
-
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.
|
|
3900
|
+
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.98);
|
|
3889
3901
|
const targetAmount = remainingAssets.gte(maxAmount) ? maxAmount : remainingAssets;
|
|
3902
|
+
logger.verbose(`Target amount: ${targetAmount.toString()}`);
|
|
3903
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3904
|
+
logger.verbose(`Max amount: ${maxAmount.toString()}`);
|
|
3905
|
+
logger.verbose(`pool.max_weight: ${pool.max_weight}`);
|
|
3890
3906
|
targetAmounts[pool.pool_id.address.toString()] = targetAmount;
|
|
3891
3907
|
remainingAssets = remainingAssets.minus(targetAmount.toString());
|
|
3892
3908
|
if (pool.current_weight > pool.max_weight) {
|
|
@@ -3904,11 +3920,15 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3904
3920
|
isDeposit: change.gt(0)
|
|
3905
3921
|
};
|
|
3906
3922
|
});
|
|
3923
|
+
logger.verbose(`Changes: ${JSON.stringify(changes)}`);
|
|
3907
3924
|
const sumChanges = changes.reduce((sum, c) => sum.plus(c.changeAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3908
3925
|
const sumFinal = changes.reduce((sum, c) => sum.plus(c.finalAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3909
3926
|
const hasChanges = changes.some((c) => !c.changeAmt.eq(0));
|
|
3910
3927
|
if (!sumChanges.eq(0)) throw new Error("Sum of changes must be zero");
|
|
3911
|
-
|
|
3928
|
+
logger.verbose(`Sum of changes: ${sumChanges.toString()}`);
|
|
3929
|
+
logger.verbose(`Sum of final: ${sumFinal.toString()}`);
|
|
3930
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3931
|
+
if (!sumFinal.eq(totalAssets.toString())) throw new Error("Sum of final amounts must equal total assets");
|
|
3912
3932
|
if (!hasChanges) throw new Error("No changes required");
|
|
3913
3933
|
const finalPools = pools.map((p) => {
|
|
3914
3934
|
const target = targetAmounts[p.pool_id.address.toString()] || Web3Number.fromWei("0", this.decimals());
|
|
@@ -3932,13 +3952,12 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3932
3952
|
async getRebalanceCall(pools, isOverWeightAdjustment) {
|
|
3933
3953
|
const actions = [];
|
|
3934
3954
|
pools.sort((a, b) => b.isDeposit ? -1 : 1);
|
|
3935
|
-
console.log("pools", pools);
|
|
3936
3955
|
pools.forEach((p) => {
|
|
3937
3956
|
if (p.changeAmt.eq(0)) return null;
|
|
3938
3957
|
actions.push({
|
|
3939
3958
|
pool_id: p.pool_id.address,
|
|
3940
3959
|
feature: new import_starknet7.CairoCustomEnum(p.isDeposit ? { DEPOSIT: {} } : { WITHDRAW: {} }),
|
|
3941
|
-
token: this.asset().address,
|
|
3960
|
+
token: this.asset().address.address,
|
|
3942
3961
|
amount: import_starknet7.uint256.bnToUint256(p.changeAmt.multipliedBy(p.isDeposit ? 1 : -1).toWei())
|
|
3943
3962
|
});
|
|
3944
3963
|
});
|
|
@@ -3949,7 +3968,7 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3949
3968
|
return this.contract.populate("rebalance", [actions]);
|
|
3950
3969
|
}
|
|
3951
3970
|
async getInvestmentFlows(pools) {
|
|
3952
|
-
const netYield = this.netAPYGivenPools(pools);
|
|
3971
|
+
const netYield = await this.netAPYGivenPools(pools);
|
|
3953
3972
|
const baseFlow = {
|
|
3954
3973
|
title: "Your Deposit",
|
|
3955
3974
|
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,11 @@ 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
|
+
logger.verbose(`pool check: ${d.id == num2.getDecimalString(p.pool_id.address.toString())}, id: ${d.id}, pool_id: ${num2.getDecimalString(p.pool_id.address.toString())}`);
|
|
3738
|
+
return d.id == num2.getDecimalString(p.pool_id.address.toString());
|
|
3739
|
+
});
|
|
3740
|
+
logger.verbose(`pool: ${JSON.stringify(pool)}`);
|
|
3734
3741
|
const assetInfo = pool?.assets.find((d) => this.asset().address.eqString(d.address));
|
|
3735
3742
|
let vTokenContract = new Contract4(vesu_rebalance_abi_default, p.v_token.address, this.config.provider);
|
|
3736
3743
|
const bal = await vTokenContract.balanceOf(this.address.address);
|
|
@@ -3778,11 +3785,13 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3778
3785
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
3779
3786
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
3780
3787
|
*/
|
|
3781
|
-
netAPYGivenPools(pools) {
|
|
3782
|
-
const
|
|
3788
|
+
async netAPYGivenPools(pools) {
|
|
3789
|
+
const weightedApyNumerator = pools.reduce((acc, curr) => {
|
|
3783
3790
|
const weight = curr.current_weight;
|
|
3784
|
-
return acc + curr.APY.netApy *
|
|
3791
|
+
return acc + curr.APY.netApy * Number(curr.amount.toString());
|
|
3785
3792
|
}, 0);
|
|
3793
|
+
const totalAssets = (await this.getTVL()).amount;
|
|
3794
|
+
const weightedApy = weightedApyNumerator / Number(totalAssets.toString());
|
|
3786
3795
|
return weightedApy * (1 - this.metadata.additionalInfo.feeBps / 1e4);
|
|
3787
3796
|
}
|
|
3788
3797
|
/**
|
|
@@ -3811,14 +3820,21 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3811
3820
|
finalPools: []
|
|
3812
3821
|
};
|
|
3813
3822
|
const sumPools = pools.reduce((acc, curr) => acc.plus(curr.amount.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3814
|
-
|
|
3823
|
+
logger.verbose(`Sum of pools: ${sumPools.toString()}`);
|
|
3824
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3825
|
+
assert(sumPools.lte(totalAssets.multipliedBy(1.00001).toString()), "Sum of pools.amount must be less than or equal to totalAssets");
|
|
3815
3826
|
const sortedPools = [...pools].sort((a, b) => b.APY.netApy - a.APY.netApy);
|
|
3816
3827
|
const targetAmounts = {};
|
|
3817
3828
|
let remainingAssets = totalAssets;
|
|
3829
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3818
3830
|
let isAnyPoolOverMaxWeight = false;
|
|
3819
3831
|
for (const pool of sortedPools) {
|
|
3820
|
-
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.
|
|
3832
|
+
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.98);
|
|
3821
3833
|
const targetAmount = remainingAssets.gte(maxAmount) ? maxAmount : remainingAssets;
|
|
3834
|
+
logger.verbose(`Target amount: ${targetAmount.toString()}`);
|
|
3835
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
3836
|
+
logger.verbose(`Max amount: ${maxAmount.toString()}`);
|
|
3837
|
+
logger.verbose(`pool.max_weight: ${pool.max_weight}`);
|
|
3822
3838
|
targetAmounts[pool.pool_id.address.toString()] = targetAmount;
|
|
3823
3839
|
remainingAssets = remainingAssets.minus(targetAmount.toString());
|
|
3824
3840
|
if (pool.current_weight > pool.max_weight) {
|
|
@@ -3836,11 +3852,15 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3836
3852
|
isDeposit: change.gt(0)
|
|
3837
3853
|
};
|
|
3838
3854
|
});
|
|
3855
|
+
logger.verbose(`Changes: ${JSON.stringify(changes)}`);
|
|
3839
3856
|
const sumChanges = changes.reduce((sum, c) => sum.plus(c.changeAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3840
3857
|
const sumFinal = changes.reduce((sum, c) => sum.plus(c.finalAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
3841
3858
|
const hasChanges = changes.some((c) => !c.changeAmt.eq(0));
|
|
3842
3859
|
if (!sumChanges.eq(0)) throw new Error("Sum of changes must be zero");
|
|
3843
|
-
|
|
3860
|
+
logger.verbose(`Sum of changes: ${sumChanges.toString()}`);
|
|
3861
|
+
logger.verbose(`Sum of final: ${sumFinal.toString()}`);
|
|
3862
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
3863
|
+
if (!sumFinal.eq(totalAssets.toString())) throw new Error("Sum of final amounts must equal total assets");
|
|
3844
3864
|
if (!hasChanges) throw new Error("No changes required");
|
|
3845
3865
|
const finalPools = pools.map((p) => {
|
|
3846
3866
|
const target = targetAmounts[p.pool_id.address.toString()] || Web3Number.fromWei("0", this.decimals());
|
|
@@ -3864,13 +3884,12 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3864
3884
|
async getRebalanceCall(pools, isOverWeightAdjustment) {
|
|
3865
3885
|
const actions = [];
|
|
3866
3886
|
pools.sort((a, b) => b.isDeposit ? -1 : 1);
|
|
3867
|
-
console.log("pools", pools);
|
|
3868
3887
|
pools.forEach((p) => {
|
|
3869
3888
|
if (p.changeAmt.eq(0)) return null;
|
|
3870
3889
|
actions.push({
|
|
3871
3890
|
pool_id: p.pool_id.address,
|
|
3872
3891
|
feature: new CairoCustomEnum(p.isDeposit ? { DEPOSIT: {} } : { WITHDRAW: {} }),
|
|
3873
|
-
token: this.asset().address,
|
|
3892
|
+
token: this.asset().address.address,
|
|
3874
3893
|
amount: uint2563.bnToUint256(p.changeAmt.multipliedBy(p.isDeposit ? 1 : -1).toWei())
|
|
3875
3894
|
});
|
|
3876
3895
|
});
|
|
@@ -3881,7 +3900,7 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
3881
3900
|
return this.contract.populate("rebalance", [actions]);
|
|
3882
3901
|
}
|
|
3883
3902
|
async getInvestmentFlows(pools) {
|
|
3884
|
-
const netYield = this.netAPYGivenPools(pools);
|
|
3903
|
+
const netYield = await this.netAPYGivenPools(pools);
|
|
3885
3904
|
const baseFlow = {
|
|
3886
3905
|
title: "Your Deposit",
|
|
3887
3906
|
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.24",
|
|
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,11 @@ 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
|
+
logger.verbose(`pool check: ${d.id == num.getDecimalString(p.pool_id.address.toString())}, id: ${d.id}, pool_id: ${num.getDecimalString(p.pool_id.address.toString())}`);
|
|
269
|
+
return d.id == num.getDecimalString(p.pool_id.address.toString());
|
|
270
|
+
});
|
|
271
|
+
logger.verbose(`pool: ${JSON.stringify(pool)}`);
|
|
268
272
|
const assetInfo = pool?.assets.find((d: any) => this.asset().address.eqString(d.address));
|
|
269
273
|
let vTokenContract = new Contract(VesuRebalanceAbi, p.v_token.address, this.config.provider);
|
|
270
274
|
const bal = await vTokenContract.balanceOf(this.address.address);
|
|
@@ -314,12 +318,13 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
314
318
|
* Calculates the weighted average APY across all pools based on USD value.
|
|
315
319
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
316
320
|
*/
|
|
317
|
-
netAPYGivenPools(pools: PoolInfoFull[]): number {
|
|
318
|
-
const
|
|
321
|
+
async netAPYGivenPools(pools: PoolInfoFull[]): Promise<number> {
|
|
322
|
+
const weightedApyNumerator = pools.reduce((acc: number, curr) => {
|
|
319
323
|
const weight = curr.current_weight;
|
|
320
|
-
return acc + (curr.APY.netApy *
|
|
324
|
+
return acc + (curr.APY.netApy * Number(curr.amount.toString()));
|
|
321
325
|
}, 0);
|
|
322
|
-
|
|
326
|
+
const totalAssets = (await this.getTVL()).amount;
|
|
327
|
+
const weightedApy = weightedApyNumerator / Number(totalAssets.toString());
|
|
323
328
|
return weightedApy * (1 - (this.metadata.additionalInfo.feeBps / 10000));
|
|
324
329
|
}
|
|
325
330
|
|
|
@@ -351,18 +356,25 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
351
356
|
|
|
352
357
|
// assert sum of pools.amount <= totalAssets
|
|
353
358
|
const sumPools = pools.reduce((acc, curr) => acc.plus(curr.amount.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
354
|
-
|
|
359
|
+
logger.verbose(`Sum of pools: ${sumPools.toString()}`);
|
|
360
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
361
|
+
assert(sumPools.lte(totalAssets.multipliedBy(1.00001).toString()), 'Sum of pools.amount must be less than or equal to totalAssets');
|
|
355
362
|
|
|
356
363
|
// Sort pools by APY and calculate target amounts
|
|
357
364
|
const sortedPools = [...pools].sort((a, b) => b.APY.netApy - a.APY.netApy);
|
|
358
365
|
const targetAmounts: Record<string, Web3Number> = {};
|
|
359
366
|
let remainingAssets = totalAssets;
|
|
367
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
360
368
|
|
|
361
369
|
// First pass: Allocate to high APY pools up to their max weight
|
|
362
370
|
let isAnyPoolOverMaxWeight = false;
|
|
363
371
|
for (const pool of sortedPools) {
|
|
364
|
-
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.
|
|
372
|
+
const maxAmount = totalAssets.multipliedBy(pool.max_weight * 0.98); // some tolerance
|
|
365
373
|
const targetAmount = remainingAssets.gte(maxAmount) ? maxAmount : remainingAssets;
|
|
374
|
+
logger.verbose(`Target amount: ${targetAmount.toString()}`);
|
|
375
|
+
logger.verbose(`Remaining assets: ${remainingAssets.toString()}`);
|
|
376
|
+
logger.verbose(`Max amount: ${maxAmount.toString()}`);
|
|
377
|
+
logger.verbose(`pool.max_weight: ${pool.max_weight}`);
|
|
366
378
|
targetAmounts[pool.pool_id.address.toString()] = targetAmount;
|
|
367
379
|
remainingAssets = remainingAssets.minus(targetAmount.toString());
|
|
368
380
|
if (pool.current_weight > pool.max_weight) {
|
|
@@ -384,13 +396,17 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
384
396
|
};
|
|
385
397
|
});
|
|
386
398
|
|
|
399
|
+
logger.verbose(`Changes: ${JSON.stringify(changes)}`);
|
|
387
400
|
// Validate changes
|
|
388
401
|
const sumChanges = changes.reduce((sum, c) => sum.plus(c.changeAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
389
402
|
const sumFinal = changes.reduce((sum, c) => sum.plus(c.finalAmt.toString()), Web3Number.fromWei("0", this.decimals()));
|
|
390
403
|
const hasChanges = changes.some(c => !c.changeAmt.eq(0));
|
|
391
404
|
|
|
392
405
|
if (!sumChanges.eq(0)) throw new Error('Sum of changes must be zero');
|
|
393
|
-
|
|
406
|
+
logger.verbose(`Sum of changes: ${sumChanges.toString()}`);
|
|
407
|
+
logger.verbose(`Sum of final: ${sumFinal.toString()}`);
|
|
408
|
+
logger.verbose(`Total assets: ${totalAssets.toString()}`);
|
|
409
|
+
if (!sumFinal.eq(totalAssets.toString())) throw new Error('Sum of final amounts must equal total assets');
|
|
394
410
|
if (!hasChanges) throw new Error('No changes required');
|
|
395
411
|
|
|
396
412
|
const finalPools: PoolInfoFull[] = pools.map((p) => {
|
|
@@ -420,13 +436,12 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
420
436
|
const actions: any[] = [];
|
|
421
437
|
// sort to put withdrawals first
|
|
422
438
|
pools.sort((a, b) => b.isDeposit ? -1 : 1);
|
|
423
|
-
console.log('pools', pools);
|
|
424
439
|
pools.forEach((p) => {
|
|
425
440
|
if (p.changeAmt.eq(0)) return null;
|
|
426
441
|
actions.push({
|
|
427
442
|
pool_id: p.pool_id.address,
|
|
428
443
|
feature: new CairoCustomEnum(p.isDeposit ? {DEPOSIT: {}} : {WITHDRAW: {}}),
|
|
429
|
-
token: this.asset().address,
|
|
444
|
+
token: this.asset().address.address,
|
|
430
445
|
amount: uint256.bnToUint256(p.changeAmt.multipliedBy(p.isDeposit ? 1 : -1).toWei()),
|
|
431
446
|
});
|
|
432
447
|
});
|
|
@@ -438,7 +453,7 @@ export class VesuRebalance extends BaseStrategy<SingleTokenInfo, SingleActionAmo
|
|
|
438
453
|
}
|
|
439
454
|
|
|
440
455
|
async getInvestmentFlows(pools: PoolInfoFull[]) {
|
|
441
|
-
const netYield = this.netAPYGivenPools(pools);
|
|
456
|
+
const netYield = await this.netAPYGivenPools(pools);
|
|
442
457
|
|
|
443
458
|
const baseFlow: IInvestmentFlow = {
|
|
444
459
|
title: "Your Deposit",
|