@haven-fi/solauto-sdk 1.0.661 → 1.0.662
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/services/rebalance/rebalanceTxBuilder.d.ts +0 -1
- package/dist/services/rebalance/rebalanceTxBuilder.d.ts.map +1 -1
- package/dist/services/rebalance/rebalanceTxBuilder.js +1 -6
- package/dist/services/solauto/solautoClient.js +1 -1
- package/dist/solautoPosition/solautoPositionEx.d.ts +9 -1
- package/dist/solautoPosition/solautoPositionEx.d.ts.map +1 -1
- package/dist/solautoPosition/solautoPositionEx.js +56 -29
- package/dist/utils/numberUtils.d.ts +2 -0
- package/dist/utils/numberUtils.d.ts.map +1 -1
- package/dist/utils/numberUtils.js +7 -0
- package/local/logPositions.ts +0 -2
- package/package.json +1 -1
- package/src/services/rebalance/rebalanceTxBuilder.ts +6 -19
- package/src/services/solauto/solautoClient.ts +1 -1
- package/src/solautoPosition/solautoPositionEx.ts +104 -46
- package/src/utils/numberUtils.ts +13 -1
@@ -15,7 +15,6 @@ export declare class RebalanceTxBuilder {
|
|
15
15
|
private flashLoanRequirements;
|
16
16
|
private getFlashLoanDetails;
|
17
17
|
private setRebalanceType;
|
18
|
-
private realtimeUsdToEmaUsd;
|
19
18
|
private getInitialRebalanceValues;
|
20
19
|
private setRebalanceDetails;
|
21
20
|
private refreshBeforeRebalance;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"rebalanceTxBuilder.d.ts","sourceRoot":"","sources":["../../../src/services/rebalance/rebalanceTxBuilder.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAGL,qBAAqB,EACtB,MAAM,aAAa,CAAC;
|
1
|
+
{"version":3,"file":"rebalanceTxBuilder.d.ts","sourceRoot":"","sources":["../../../src/services/rebalance/rebalanceTxBuilder.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAGL,qBAAqB,EACtB,MAAM,aAAa,CAAC;AA2BrB,qBAAa,kBAAkB;IAQ3B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,2BAA2B,CAAC;IARtC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,WAAW,CAAwB;IAC3C,OAAO,CAAC,cAAc,CAAC,CAAwB;IAC/C,OAAO,CAAC,SAAS,CAAiC;gBAGxC,MAAM,EAAE,aAAa,EACrB,2BAA2B,CAAC,EAAE,MAAM,YAAA;IAG9C,OAAO,CAAC,0BAA0B;IAQlC,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,oBAAoB;YAyCd,qBAAqB;IAwCnC,OAAO,CAAC,mBAAmB;IAwB3B,OAAO,CAAC,gBAAgB;IA+BxB,OAAO,CAAC,yBAAyB;YAqBnB,mBAAmB;YAwBnB,sBAAsB;YAyBtB,mBAAmB;IAmEpB,gBAAgB,CAC3B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;CAe9C"}
|
@@ -114,17 +114,12 @@ class RebalanceTxBuilder {
|
|
114
114
|
this.rebalanceType = generated_1.SolautoRebalanceType.Regular;
|
115
115
|
}
|
116
116
|
}
|
117
|
-
realtimeUsdToEmaUsd(realtimeAmountUsd, mint) {
|
118
|
-
return ((realtimeAmountUsd / (0, utils_1.safeGetPrice)(mint, generated_1.PriceType.Realtime)) *
|
119
|
-
(0, utils_1.safeGetPrice)(mint, generated_1.PriceType.Ema));
|
120
|
-
}
|
121
117
|
getInitialRebalanceValues() {
|
122
118
|
let rebalanceValues = this.getRebalanceValues();
|
123
119
|
if (!rebalanceValues) {
|
124
120
|
return undefined;
|
125
121
|
}
|
126
|
-
|
127
|
-
if (postRebalanceEmaUtilRateBps > this.client.pos.maxBoostToBps) {
|
122
|
+
if (!this.client.pos.rebalanceHelper.validRealtimePricesBoost(rebalanceValues.debtAdjustmentUsd)) {
|
128
123
|
this.priceType = generated_1.PriceType.Ema;
|
129
124
|
rebalanceValues = this.getRebalanceValues();
|
130
125
|
if (!rebalanceValues) {
|
@@ -30,7 +30,7 @@ class SolautoClient extends referralStateManager_1.ReferralStateManager {
|
|
30
30
|
lendingPlatform: this.lendingPlatform,
|
31
31
|
lpEnv: this.lpEnv,
|
32
32
|
}, this.contextUpdates);
|
33
|
-
if (this.pos.selfManaged
|
33
|
+
if (this.pos.selfManaged) {
|
34
34
|
await this.pos.refreshPositionState();
|
35
35
|
}
|
36
36
|
this.positionSupplyTa = (0, utils_1.getTokenAccount)(this.pos.publicKey, this.pos.supplyMint);
|
@@ -39,6 +39,7 @@ export declare abstract class SolautoPositionEx {
|
|
39
39
|
private readonly firstState;
|
40
40
|
protected _supplyPrice?: number;
|
41
41
|
protected _debtPrice?: number;
|
42
|
+
rebalanceHelper: PositionRebalanceHelper;
|
42
43
|
constructor(args: PositionExArgs);
|
43
44
|
abstract lendingPool(): Promise<PublicKey>;
|
44
45
|
get exists(): boolean;
|
@@ -80,7 +81,6 @@ export declare abstract class SolautoPositionEx {
|
|
80
81
|
abstract maxLtvAndLiqThresholdBps(): Promise<[number, number]>;
|
81
82
|
abstract priceOracles(): Promise<PublicKey[]>;
|
82
83
|
get memecoinPosition(): boolean | undefined;
|
83
|
-
private sufficientLiquidityToBoost;
|
84
84
|
eligibleForRebalance(bpsDistanceThreshold?: number): RebalanceAction | undefined;
|
85
85
|
eligibleForRefresh(): boolean;
|
86
86
|
abstract refreshPositionState(priceType?: PriceType): Promise<void>;
|
@@ -94,5 +94,13 @@ export declare abstract class SolautoPositionEx {
|
|
94
94
|
simulateRebalance(unixTime: number, supplyPrice: number, debtPrice: number, targetLiqUtilizationRateBps?: number): undefined;
|
95
95
|
refetchPositionData(): Promise<void>;
|
96
96
|
}
|
97
|
+
declare class PositionRebalanceHelper {
|
98
|
+
private pos;
|
99
|
+
constructor(pos: SolautoPositionEx);
|
100
|
+
private sufficientLiquidityToBoost;
|
101
|
+
validRealtimePricesBoost(debtAdjustmentUsd: number): boolean;
|
102
|
+
private validBoostFromHere;
|
103
|
+
eligibleForRebalance(bpsDistanceThreshold: number): RebalanceAction | undefined;
|
104
|
+
}
|
97
105
|
export {};
|
98
106
|
//# sourceMappingURL=solautoPositionEx.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"solautoPositionEx.d.ts","sourceRoot":"","sources":["../../src/solautoPosition/solautoPositionEx.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAK/C,OAAO,EACL,WAAW,EAEX,eAAe,EACf,aAAa,EACb,SAAS,EACT,eAAe,EACf,yBAAyB,EAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAOL,cAAc,
|
1
|
+
{"version":3,"file":"solautoPositionEx.d.ts","sourceRoot":"","sources":["../../src/solautoPosition/solautoPositionEx.ts"],"names":[],"mappings":"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"}
|
@@ -25,6 +25,7 @@ class SolautoPositionEx {
|
|
25
25
|
this.lpEnv = args.customArgs?.lpEnv ?? "Prod";
|
26
26
|
this._data = args.data;
|
27
27
|
this.firstState = { ...args.data.state };
|
28
|
+
this.rebalanceHelper = new PositionRebalanceHelper(this);
|
28
29
|
}
|
29
30
|
get exists() {
|
30
31
|
return this._data.position !== undefined;
|
@@ -140,36 +141,8 @@ class SolautoPositionEx {
|
|
140
141
|
get memecoinPosition() {
|
141
142
|
return (0, utils_1.tokenInfo)(this.supplyMint).isMeme || (0, utils_1.tokenInfo)(this.debtMint).isMeme;
|
142
143
|
}
|
143
|
-
sufficientLiquidityToBoost() {
|
144
|
-
const limitsUpToDate = this.debtLiquidityUsdAvailable !== 0 ||
|
145
|
-
this.supplyLiquidityUsdDepositable !== 0;
|
146
|
-
if (limitsUpToDate) {
|
147
|
-
const { debtAdjustmentUsd } = (0, rebalance_1.getDebtAdjustment)(this.state.liqThresholdBps, { supplyUsd: this.supplyUsd(), debtUsd: this.debtUsd() }, this.boostToBps, { solauto: 50, lpBorrow: 50, flashLoan: 50 } // TODO: get true data here instead of magic numbers
|
148
|
-
);
|
149
|
-
const sufficientLiquidity = this.debtLiquidityUsdAvailable * 0.95 > debtAdjustmentUsd &&
|
150
|
-
this.supplyLiquidityUsdDepositable * 0.95 > debtAdjustmentUsd;
|
151
|
-
if (!sufficientLiquidity) {
|
152
|
-
(0, utils_1.consoleLog)("Insufficient liquidity to further boost");
|
153
|
-
}
|
154
|
-
return sufficientLiquidity;
|
155
|
-
}
|
156
|
-
return true;
|
157
|
-
}
|
158
144
|
eligibleForRebalance(bpsDistanceThreshold = 0) {
|
159
|
-
|
160
|
-
return undefined;
|
161
|
-
}
|
162
|
-
const realtimeLiqUtilRateBps = this.liqUtilizationRateBps(generated_1.PriceType.Realtime);
|
163
|
-
const emaLiqUtilRateBps = this.liqUtilizationRateBps(generated_1.PriceType.Ema);
|
164
|
-
if (this.repayFromBps - realtimeLiqUtilRateBps <= bpsDistanceThreshold) {
|
165
|
-
return "repay";
|
166
|
-
}
|
167
|
-
else if (realtimeLiqUtilRateBps - this.boostFromBps <= bpsDistanceThreshold ||
|
168
|
-
emaLiqUtilRateBps - this.boostFromBps <= bpsDistanceThreshold) {
|
169
|
-
const sufficientLiquidity = this.sufficientLiquidityToBoost();
|
170
|
-
return sufficientLiquidity ? "boost" : undefined;
|
171
|
-
}
|
172
|
-
return undefined;
|
145
|
+
return this.rebalanceHelper.eligibleForRebalance(bpsDistanceThreshold);
|
173
146
|
}
|
174
147
|
eligibleForRefresh() {
|
175
148
|
if (this.selfManaged)
|
@@ -224,3 +197,57 @@ class SolautoPositionEx {
|
|
224
197
|
}
|
225
198
|
}
|
226
199
|
exports.SolautoPositionEx = SolautoPositionEx;
|
200
|
+
class PositionRebalanceHelper {
|
201
|
+
constructor(pos) {
|
202
|
+
this.pos = pos;
|
203
|
+
}
|
204
|
+
sufficientLiquidityToBoost() {
|
205
|
+
const limitsUpToDate = this.pos.debtLiquidityUsdAvailable !== 0 ||
|
206
|
+
this.pos.supplyLiquidityUsdDepositable !== 0;
|
207
|
+
if (limitsUpToDate) {
|
208
|
+
const { debtAdjustmentUsd } = (0, rebalance_1.getDebtAdjustment)(this.pos.state.liqThresholdBps, { supplyUsd: this.pos.supplyUsd(), debtUsd: this.pos.debtUsd() }, this.pos.boostToBps, { solauto: 50, lpBorrow: 50, flashLoan: 50 } // Overshoot fees
|
209
|
+
);
|
210
|
+
const sufficientLiquidity = this.pos.debtLiquidityUsdAvailable * 0.95 > debtAdjustmentUsd &&
|
211
|
+
this.pos.supplyLiquidityUsdDepositable * 0.95 > debtAdjustmentUsd;
|
212
|
+
if (!sufficientLiquidity) {
|
213
|
+
(0, utils_1.consoleLog)("Insufficient liquidity to further boost");
|
214
|
+
}
|
215
|
+
return sufficientLiquidity;
|
216
|
+
}
|
217
|
+
return true;
|
218
|
+
}
|
219
|
+
validRealtimePricesBoost(debtAdjustmentUsd) {
|
220
|
+
if (this.pos.lendingPlatform !== generated_1.LendingPlatform.Marginfi) {
|
221
|
+
// TODO: LP
|
222
|
+
return true;
|
223
|
+
}
|
224
|
+
const postRebalanceLiqUtilRate = (0, utils_1.getLiqUtilzationRateBps)((0, utils_1.realtimeUsdToEmaUsd)(this.pos.supplyUsd() + debtAdjustmentUsd, this.pos.supplyMint), (0, utils_1.realtimeUsdToEmaUsd)(this.pos.debtUsd() + debtAdjustmentUsd, this.pos.debtMint), this.pos.state.liqThresholdBps);
|
225
|
+
return postRebalanceLiqUtilRate <= this.pos.maxBoostToBps;
|
226
|
+
}
|
227
|
+
validBoostFromHere() {
|
228
|
+
const { debtAdjustmentUsd } = (0, rebalance_1.getDebtAdjustment)(this.pos.state.liqThresholdBps, {
|
229
|
+
supplyUsd: this.pos.supplyUsd(generated_1.PriceType.Realtime),
|
230
|
+
debtUsd: this.pos.debtUsd(generated_1.PriceType.Realtime),
|
231
|
+
}, this.pos.boostToBps, { solauto: 25, lpBorrow: 0, flashLoan: 0 } // Undershoot fees
|
232
|
+
);
|
233
|
+
return this.validRealtimePricesBoost(debtAdjustmentUsd);
|
234
|
+
}
|
235
|
+
eligibleForRebalance(bpsDistanceThreshold) {
|
236
|
+
if (!this.pos.settings || !this.pos.supplyUsd()) {
|
237
|
+
return undefined;
|
238
|
+
}
|
239
|
+
const realtimeLiqUtilRateBps = this.pos.liqUtilizationRateBps(generated_1.PriceType.Realtime);
|
240
|
+
const emaLiqUtilRateBps = this.pos.liqUtilizationRateBps(generated_1.PriceType.Ema);
|
241
|
+
if (this.pos.repayFromBps - realtimeLiqUtilRateBps <=
|
242
|
+
bpsDistanceThreshold) {
|
243
|
+
return "repay";
|
244
|
+
}
|
245
|
+
else if ((realtimeLiqUtilRateBps - this.pos.boostFromBps <= bpsDistanceThreshold ||
|
246
|
+
emaLiqUtilRateBps - this.pos.boostFromBps <= bpsDistanceThreshold) &&
|
247
|
+
this.validBoostFromHere()) {
|
248
|
+
const sufficientLiquidity = this.sufficientLiquidityToBoost();
|
249
|
+
return sufficientLiquidity ? "boost" : undefined;
|
250
|
+
}
|
251
|
+
return undefined;
|
252
|
+
}
|
253
|
+
}
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
1
2
|
import { PositionState } from "../generated";
|
2
3
|
import { RoundAction } from "../types";
|
3
4
|
export declare function calcNetWorthUsd(state?: PositionState): number;
|
@@ -23,4 +24,5 @@ export declare function getMaxLiqUtilizationRateBps(maxLtvBps: number, liqThresh
|
|
23
24
|
export declare function maxRepayFromBps(maxLtvBps: number, liqThresholdBps: number): number;
|
24
25
|
export declare function maxRepayToBps(maxLtvBps: number, liqThresholdBps: number): number;
|
25
26
|
export declare function maxBoostToBps(maxLtvBps: number, liqThresholdBps: number): number;
|
27
|
+
export declare function realtimeUsdToEmaUsd(realtimeAmountUsd: number, mint: PublicKey): number;
|
26
28
|
//# sourceMappingURL=numberUtils.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"numberUtils.d.ts","sourceRoot":"","sources":["../../src/utils/numberUtils.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"numberUtils.d.ts","sourceRoot":"","sources":["../../src/utils/numberUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAO5C,OAAO,EAAE,aAAa,EAAa,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGvC,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,aAAa,UAEpD;AAED,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,aAAa,UAIlD;AAED,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,aAAa,UAIhD;AAED,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,aAAa,UAKjD;AAED,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,aAAa,UAKpD;AAED,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,aAAa,UAKlD;AAED,wBAAgB,sBAAsB,CAAC,KAAK,CAAC,EAAE,aAAa,UAK3D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,CAAC,EAAE,aAAa,UAI9D;AAED,wBAAgB,0BAA0B,CAAC,KAAK,CAAC,EAAE,aAAa,UAK/D;AAED,wBAAgB,6BAA6B,CAAC,KAAK,CAAC,EAAE,aAAa,UAIlE;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,UAEjD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,UAE/C;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GACtB,MAAM,CAMR;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,WAAqB,GACjC,MAAM,CAKR;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKpE;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,KAAK,CACnB,KAAK,EAAE,MAAM,EACb,WAAW,GAAE,WAAqB,GACjC,MAAM,CAGR;AAUD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAqBrD;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAejE;AAED,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAKR;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,UASzE;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,UAKvE;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,UAKvE;AAED,wBAAgB,mBAAmB,CACjC,iBAAiB,EAAE,MAAM,EACzB,IAAI,EAAE,SAAS,UAMhB"}
|
@@ -23,7 +23,10 @@ exports.getMaxLiqUtilizationRateBps = getMaxLiqUtilizationRateBps;
|
|
23
23
|
exports.maxRepayFromBps = maxRepayFromBps;
|
24
24
|
exports.maxRepayToBps = maxRepayToBps;
|
25
25
|
exports.maxBoostToBps = maxBoostToBps;
|
26
|
+
exports.realtimeUsdToEmaUsd = realtimeUsdToEmaUsd;
|
26
27
|
const constants_1 = require("../constants");
|
28
|
+
const generated_1 = require("../generated");
|
29
|
+
const priceUtils_1 = require("./priceUtils");
|
27
30
|
function calcNetWorthUsd(state) {
|
28
31
|
return fromRoundedUsdValue(state?.netWorth.baseAmountUsdValue ?? BigInt(0));
|
29
32
|
}
|
@@ -131,3 +134,7 @@ function maxRepayToBps(maxLtvBps, liqThresholdBps) {
|
|
131
134
|
function maxBoostToBps(maxLtvBps, liqThresholdBps) {
|
132
135
|
return Math.min(maxRepayToBps(maxLtvBps, liqThresholdBps), getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps, constants_1.OFFSET_FROM_MAX_LTV));
|
133
136
|
}
|
137
|
+
function realtimeUsdToEmaUsd(realtimeAmountUsd, mint) {
|
138
|
+
return ((realtimeAmountUsd / (0, priceUtils_1.safeGetPrice)(mint, generated_1.PriceType.Realtime)) *
|
139
|
+
(0, priceUtils_1.safeGetPrice)(mint, generated_1.PriceType.Ema));
|
140
|
+
}
|
package/local/logPositions.ts
CHANGED
package/package.json
CHANGED
@@ -15,6 +15,7 @@ import {
|
|
15
15
|
getTokenAccount,
|
16
16
|
hasFirstRebalance,
|
17
17
|
hasLastRebalance,
|
18
|
+
realtimeUsdToEmaUsd,
|
18
19
|
safeGetPrice,
|
19
20
|
tokenInfo,
|
20
21
|
} from "../../utils";
|
@@ -202,31 +203,17 @@ export class RebalanceTxBuilder {
|
|
202
203
|
}
|
203
204
|
}
|
204
205
|
|
205
|
-
private realtimeUsdToEmaUsd(realtimeAmountUsd: number, mint: PublicKey) {
|
206
|
-
return (
|
207
|
-
(realtimeAmountUsd / safeGetPrice(mint, PriceType.Realtime)!) *
|
208
|
-
safeGetPrice(mint, PriceType.Ema)!
|
209
|
-
);
|
210
|
-
}
|
211
|
-
|
212
206
|
private getInitialRebalanceValues() {
|
213
207
|
let rebalanceValues = this.getRebalanceValues();
|
214
208
|
if (!rebalanceValues) {
|
215
209
|
return undefined;
|
216
210
|
}
|
217
211
|
|
218
|
-
|
219
|
-
this.
|
220
|
-
rebalanceValues.
|
221
|
-
|
222
|
-
|
223
|
-
this.realtimeUsdToEmaUsd(
|
224
|
-
rebalanceValues.endResult.debtUsd,
|
225
|
-
this.client.pos.debtMint
|
226
|
-
),
|
227
|
-
this.client.pos.state.liqThresholdBps
|
228
|
-
);
|
229
|
-
if (postRebalanceEmaUtilRateBps > this.client.pos.maxBoostToBps) {
|
212
|
+
if (
|
213
|
+
!this.client.pos.rebalanceHelper.validRealtimePricesBoost(
|
214
|
+
rebalanceValues.debtAdjustmentUsd
|
215
|
+
)
|
216
|
+
) {
|
230
217
|
this.priceType = PriceType.Ema;
|
231
218
|
rebalanceValues = this.getRebalanceValues();
|
232
219
|
if (!rebalanceValues) {
|
@@ -30,6 +30,7 @@ import {
|
|
30
30
|
maxRepayFromBps,
|
31
31
|
maxRepayToBps,
|
32
32
|
positionStateWithLatestPrices,
|
33
|
+
realtimeUsdToEmaUsd,
|
33
34
|
safeGetPrice,
|
34
35
|
solautoStrategyName,
|
35
36
|
supplyLiquidityDepositable,
|
@@ -87,6 +88,8 @@ export abstract class SolautoPositionEx {
|
|
87
88
|
protected _supplyPrice?: number;
|
88
89
|
protected _debtPrice?: number;
|
89
90
|
|
91
|
+
public rebalanceHelper!: PositionRebalanceHelper;
|
92
|
+
|
90
93
|
constructor(args: PositionExArgs) {
|
91
94
|
this.umi = args.umi;
|
92
95
|
this.contextUpdates = args.contextUpdates;
|
@@ -111,6 +114,8 @@ export abstract class SolautoPositionEx {
|
|
111
114
|
|
112
115
|
this._data = args.data;
|
113
116
|
this.firstState = { ...args.data.state };
|
117
|
+
|
118
|
+
this.rebalanceHelper = new PositionRebalanceHelper(this);
|
114
119
|
}
|
115
120
|
|
116
121
|
abstract lendingPool(): Promise<PublicKey>;
|
@@ -277,53 +282,12 @@ export abstract class SolautoPositionEx {
|
|
277
282
|
return tokenInfo(this.supplyMint).isMeme || tokenInfo(this.debtMint).isMeme;
|
278
283
|
}
|
279
284
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
if (limitsUpToDate) {
|
286
|
-
const { debtAdjustmentUsd } = getDebtAdjustment(
|
287
|
-
this.state.liqThresholdBps,
|
288
|
-
{ supplyUsd: this.supplyUsd(), debtUsd: this.debtUsd() },
|
289
|
-
this.boostToBps,
|
290
|
-
{ solauto: 50, lpBorrow: 50, flashLoan: 50 } // TODO: get true data here instead of magic numbers
|
291
|
-
);
|
292
|
-
|
293
|
-
const sufficientLiquidity =
|
294
|
-
this.debtLiquidityUsdAvailable * 0.95 > debtAdjustmentUsd &&
|
295
|
-
this.supplyLiquidityUsdDepositable * 0.95 > debtAdjustmentUsd;
|
296
|
-
|
297
|
-
if (!sufficientLiquidity) {
|
298
|
-
consoleLog("Insufficient liquidity to further boost");
|
299
|
-
}
|
300
|
-
return sufficientLiquidity;
|
301
|
-
}
|
302
|
-
|
303
|
-
return true;
|
304
|
-
}
|
305
|
-
|
306
|
-
eligibleForRebalance(bpsDistanceThreshold = 0): RebalanceAction | undefined {
|
307
|
-
if (!this.settings || !this.supplyUsd()) {
|
308
|
-
return undefined;
|
309
|
-
}
|
310
|
-
|
311
|
-
const realtimeLiqUtilRateBps = this.liqUtilizationRateBps(
|
312
|
-
PriceType.Realtime
|
285
|
+
eligibleForRebalance(
|
286
|
+
bpsDistanceThreshold: number = 0
|
287
|
+
): RebalanceAction | undefined {
|
288
|
+
return this.rebalanceHelper.eligibleForRebalance(
|
289
|
+
bpsDistanceThreshold
|
313
290
|
);
|
314
|
-
const emaLiqUtilRateBps = this.liqUtilizationRateBps(PriceType.Ema);
|
315
|
-
|
316
|
-
if (this.repayFromBps - realtimeLiqUtilRateBps <= bpsDistanceThreshold) {
|
317
|
-
return "repay";
|
318
|
-
} else if (
|
319
|
-
realtimeLiqUtilRateBps - this.boostFromBps <= bpsDistanceThreshold ||
|
320
|
-
emaLiqUtilRateBps - this.boostFromBps <= bpsDistanceThreshold
|
321
|
-
) {
|
322
|
-
const sufficientLiquidity = this.sufficientLiquidityToBoost();
|
323
|
-
return sufficientLiquidity ? "boost" : undefined;
|
324
|
-
}
|
325
|
-
|
326
|
-
return undefined;
|
327
291
|
}
|
328
292
|
|
329
293
|
eligibleForRefresh(): boolean {
|
@@ -438,3 +402,97 @@ export abstract class SolautoPositionEx {
|
|
438
402
|
);
|
439
403
|
}
|
440
404
|
}
|
405
|
+
|
406
|
+
class PositionRebalanceHelper {
|
407
|
+
constructor(private pos: SolautoPositionEx) {}
|
408
|
+
|
409
|
+
private sufficientLiquidityToBoost() {
|
410
|
+
const limitsUpToDate =
|
411
|
+
this.pos.debtLiquidityUsdAvailable !== 0 ||
|
412
|
+
this.pos.supplyLiquidityUsdDepositable !== 0;
|
413
|
+
|
414
|
+
if (limitsUpToDate) {
|
415
|
+
const { debtAdjustmentUsd } = getDebtAdjustment(
|
416
|
+
this.pos.state.liqThresholdBps,
|
417
|
+
{ supplyUsd: this.pos.supplyUsd(), debtUsd: this.pos.debtUsd() },
|
418
|
+
this.pos.boostToBps,
|
419
|
+
{ solauto: 50, lpBorrow: 50, flashLoan: 50 } // Overshoot fees
|
420
|
+
);
|
421
|
+
|
422
|
+
const sufficientLiquidity =
|
423
|
+
this.pos.debtLiquidityUsdAvailable * 0.95 > debtAdjustmentUsd &&
|
424
|
+
this.pos.supplyLiquidityUsdDepositable * 0.95 > debtAdjustmentUsd;
|
425
|
+
|
426
|
+
if (!sufficientLiquidity) {
|
427
|
+
consoleLog("Insufficient liquidity to further boost");
|
428
|
+
}
|
429
|
+
return sufficientLiquidity;
|
430
|
+
}
|
431
|
+
|
432
|
+
return true;
|
433
|
+
}
|
434
|
+
|
435
|
+
validRealtimePricesBoost(debtAdjustmentUsd: number) {
|
436
|
+
if (this.pos.lendingPlatform !== LendingPlatform.Marginfi) {
|
437
|
+
// TODO: LP
|
438
|
+
return true;
|
439
|
+
}
|
440
|
+
|
441
|
+
const postRebalanceLiqUtilRate = getLiqUtilzationRateBps(
|
442
|
+
realtimeUsdToEmaUsd(
|
443
|
+
this.pos.supplyUsd() + debtAdjustmentUsd,
|
444
|
+
this.pos.supplyMint
|
445
|
+
),
|
446
|
+
realtimeUsdToEmaUsd(
|
447
|
+
this.pos.debtUsd() + debtAdjustmentUsd,
|
448
|
+
this.pos.debtMint
|
449
|
+
),
|
450
|
+
this.pos.state.liqThresholdBps
|
451
|
+
);
|
452
|
+
|
453
|
+
return postRebalanceLiqUtilRate <= this.pos.maxBoostToBps;
|
454
|
+
}
|
455
|
+
|
456
|
+
private validBoostFromHere() {
|
457
|
+
const { debtAdjustmentUsd } = getDebtAdjustment(
|
458
|
+
this.pos.state.liqThresholdBps,
|
459
|
+
{
|
460
|
+
supplyUsd: this.pos.supplyUsd(PriceType.Realtime),
|
461
|
+
debtUsd: this.pos.debtUsd(PriceType.Realtime),
|
462
|
+
},
|
463
|
+
this.pos.boostToBps,
|
464
|
+
{ solauto: 25, lpBorrow: 0, flashLoan: 0 } // Undershoot fees
|
465
|
+
);
|
466
|
+
|
467
|
+
return this.validRealtimePricesBoost(debtAdjustmentUsd);
|
468
|
+
}
|
469
|
+
|
470
|
+
eligibleForRebalance(
|
471
|
+
bpsDistanceThreshold: number
|
472
|
+
): RebalanceAction | undefined {
|
473
|
+
if (!this.pos.settings || !this.pos.supplyUsd()) {
|
474
|
+
return undefined;
|
475
|
+
}
|
476
|
+
|
477
|
+
const realtimeLiqUtilRateBps = this.pos.liqUtilizationRateBps(
|
478
|
+
PriceType.Realtime
|
479
|
+
);
|
480
|
+
const emaLiqUtilRateBps = this.pos.liqUtilizationRateBps(PriceType.Ema);
|
481
|
+
|
482
|
+
if (
|
483
|
+
this.pos.repayFromBps - realtimeLiqUtilRateBps <=
|
484
|
+
bpsDistanceThreshold
|
485
|
+
) {
|
486
|
+
return "repay";
|
487
|
+
} else if (
|
488
|
+
(realtimeLiqUtilRateBps - this.pos.boostFromBps <= bpsDistanceThreshold ||
|
489
|
+
emaLiqUtilRateBps - this.pos.boostFromBps <= bpsDistanceThreshold) &&
|
490
|
+
this.validBoostFromHere()
|
491
|
+
) {
|
492
|
+
const sufficientLiquidity = this.sufficientLiquidityToBoost();
|
493
|
+
return sufficientLiquidity ? "boost" : undefined;
|
494
|
+
}
|
495
|
+
|
496
|
+
return undefined;
|
497
|
+
}
|
498
|
+
}
|
package/src/utils/numberUtils.ts
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
1
2
|
import {
|
2
3
|
BASIS_POINTS,
|
3
4
|
MIN_REPAY_GAP_BPS,
|
4
5
|
OFFSET_FROM_MAX_LTV,
|
5
6
|
USD_DECIMALS,
|
6
7
|
} from "../constants";
|
7
|
-
import { PositionState } from "../generated";
|
8
|
+
import { PositionState, PriceType } from "../generated";
|
8
9
|
import { RoundAction } from "../types";
|
10
|
+
import { safeGetPrice } from "./priceUtils";
|
9
11
|
|
10
12
|
export function calcNetWorthUsd(state?: PositionState) {
|
11
13
|
return fromRoundedUsdValue(state?.netWorth.baseAmountUsdValue ?? BigInt(0));
|
@@ -203,3 +205,13 @@ export function maxBoostToBps(maxLtvBps: number, liqThresholdBps: number) {
|
|
203
205
|
getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps, OFFSET_FROM_MAX_LTV)
|
204
206
|
);
|
205
207
|
}
|
208
|
+
|
209
|
+
export function realtimeUsdToEmaUsd(
|
210
|
+
realtimeAmountUsd: number,
|
211
|
+
mint: PublicKey
|
212
|
+
) {
|
213
|
+
return (
|
214
|
+
(realtimeAmountUsd / safeGetPrice(mint, PriceType.Realtime)!) *
|
215
|
+
safeGetPrice(mint, PriceType.Ema)!
|
216
|
+
);
|
217
|
+
}
|