@haven-fi/solauto-sdk 1.0.68 → 1.0.70
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/transactions/transactionUtils.d.ts.map +1 -1
- package/dist/transactions/transactionUtils.js +2 -2
- package/dist/utils/numberUtils.d.ts +8 -1
- package/dist/utils/numberUtils.d.ts.map +1 -1
- package/dist/utils/numberUtils.js +46 -9
- package/dist/utils/solauto/generalUtils.d.ts +2 -7
- package/dist/utils/solauto/generalUtils.d.ts.map +1 -1
- package/dist/utils/solauto/generalUtils.js +4 -17
- package/dist/utils/solauto/rebalanceUtils.d.ts.map +1 -1
- package/dist/utils/solauto/rebalanceUtils.js +5 -5
- package/package.json +1 -1
- package/src/transactions/transactionUtils.ts +3 -4
- package/src/utils/numberUtils.ts +71 -16
- package/src/utils/solauto/generalUtils.ts +4 -27
- package/src/utils/solauto/rebalanceUtils.ts +11 -6
- package/tests/transactions/solautoMarginfi.ts +25 -22
- package/tests/unit/rebalanceCalculations.ts +28 -24
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transactionUtils.d.ts","sourceRoot":"","sources":["../../src/transactions/transactionUtils.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"transactionUtils.d.ts","sourceRoot":"","sources":["../../src/transactions/transactionUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kBAAkB,EAClB,GAAG,EAGJ,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAGL,OAAO,IAAI,eAAe,EAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,aAAa,EASd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAuMzD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,EAAE,EAAE,kBAAkB,EACtB,sBAAsB,EAAE,MAAM,EAAE,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CA8G7B;AAkLD,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,EACrB,EAAE,EAAE,kBAAkB,GACrB,OAAO,CAAC,CAAC,kBAAkB,EAAE,kBAAkB,CAAC,CAAC,CA4BnD;AAED,wBAAsB,gCAAgC,CACpD,MAAM,EAAE,aAAa,EACrB,2BAA2B,CAAC,EAAE,MAAM,EACpC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CACN;IACE,EAAE,EAAE,kBAAkB,CAAC;IACvB,oBAAoB,EAAE,MAAM,EAAE,CAAC;CAChC,GACD,SAAS,CACZ,CA2HA;AAED,wBAAsB,gCAAgC,CACpD,GAAG,EAAE,GAAG,EACR,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,eAAe,GAC5B,OAAO,CAAC,CAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC,CAAC,CA8BzC"}
|
|
@@ -329,7 +329,7 @@ async function buildSolautoRebalanceTransaction(client, targetLiqUtilizationRate
|
|
|
329
329
|
client.log("Not eligible for a rebalance");
|
|
330
330
|
return undefined;
|
|
331
331
|
}
|
|
332
|
-
const values = (0, rebalanceUtils_1.getRebalanceValues)(client.solautoPositionState, client.solautoPositionSettings(), client.solautoPositionActiveDca(), client.solautoPositionData
|
|
332
|
+
const values = (0, rebalanceUtils_1.getRebalanceValues)(client.solautoPositionState, client.solautoPositionSettings(), client.solautoPositionActiveDca(), client.solautoPositionData.feeType, (0, generalUtils_1.currentUnixSeconds)(), constants_1.PRICES[client.supplyMint.toString()].price, constants_1.PRICES[client.debtMint.toString()].price, targetLiqUtilizationRateBps);
|
|
333
333
|
client.log("Rebalance values: ", values);
|
|
334
334
|
const swapDetails = (0, rebalanceUtils_1.getJupSwapRebalanceDetails)(client, values, targetLiqUtilizationRateBps, attemptNum);
|
|
335
335
|
const { jupQuote, lookupTableAddresses, setupInstructions, tokenLedgerIx, swapIx, } = await (0, jupiterUtils_1.getJupSwapTransaction)(client.signer, swapDetails, attemptNum);
|
|
@@ -366,7 +366,7 @@ async function buildSolautoRebalanceTransaction(client, targetLiqUtilizationRate
|
|
|
366
366
|
]);
|
|
367
367
|
}
|
|
368
368
|
if (client.solautoPositionState.liqUtilizationRateBps >
|
|
369
|
-
(0, numberUtils_1.getMaxLiqUtilizationRateBps)(client.solautoPositionState.maxLtvBps, client.solautoPositionState.liqThresholdBps)) {
|
|
369
|
+
(0, numberUtils_1.getMaxLiqUtilizationRateBps)(client.solautoPositionState.maxLtvBps, client.solautoPositionState.liqThresholdBps, 0.01)) {
|
|
370
370
|
tx = tx.prepend(client.refresh());
|
|
371
371
|
}
|
|
372
372
|
return {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FeeType } from "../generated";
|
|
1
2
|
export declare function getLiqUtilzationRateBps(supplyUsd: number, debtUsd: number, liqThresholdBps: number): number;
|
|
2
3
|
export declare function toBaseUnit(value: number, decimals: number): bigint;
|
|
3
4
|
export declare function fromBaseUnit(value: bigint, decimals: number): number;
|
|
@@ -6,7 +7,13 @@ export declare function toBps(value: number): number;
|
|
|
6
7
|
export declare function bytesToI80F48(bytes: number[]): number;
|
|
7
8
|
export declare function uint8ArrayToBigInt(uint8Array: Uint8Array): bigint;
|
|
8
9
|
export declare function getDebtAdjustmentUsd(liqThresholdBps: number, supplyUsd: number, debtUsd: number, targetLiqUtilizationRateBps: number, adjustmentFeeBps?: number): number;
|
|
9
|
-
export declare function
|
|
10
|
+
export declare function getSolautoFeesBps(isReferred: boolean, feeType: FeeType, positionNetWorthUsd: number): {
|
|
11
|
+
solauto: number;
|
|
12
|
+
referrer: number;
|
|
13
|
+
total: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function getMaxLiqUtilizationRateBps(maxLtvBps: number, liqThresholdBps: number, offsetFromMaxLtv: number): number;
|
|
16
|
+
export declare function maxBoostToBps(maxLtvBps: number, liqThresholdBps: number): number;
|
|
10
17
|
export declare function maxRepayFromBps(maxLtvBps: number, liqThresholdBps: number): number;
|
|
11
18
|
export declare function maxRepayToBps(maxLtvBps: number, liqThresholdBps: number): number;
|
|
12
19
|
//# 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":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GACtB,MAAM,CAMR;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAqBrD;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAejE;AAED,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,2BAA2B,EAAE,MAAM,EACnC,gBAAgB,CAAC,EAAE,MAAM,UAW1B;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,OAAO,EAChB,mBAAmB,EAAE,MAAM,GAC1B;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CA8BA;AAED,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAER;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,UAEvE;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,UAKzE;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,UAKvE"}
|
|
@@ -8,10 +8,13 @@ exports.toBps = toBps;
|
|
|
8
8
|
exports.bytesToI80F48 = bytesToI80F48;
|
|
9
9
|
exports.uint8ArrayToBigInt = uint8ArrayToBigInt;
|
|
10
10
|
exports.getDebtAdjustmentUsd = getDebtAdjustmentUsd;
|
|
11
|
+
exports.getSolautoFeesBps = getSolautoFeesBps;
|
|
11
12
|
exports.getMaxLiqUtilizationRateBps = getMaxLiqUtilizationRateBps;
|
|
13
|
+
exports.maxBoostToBps = maxBoostToBps;
|
|
12
14
|
exports.maxRepayFromBps = maxRepayFromBps;
|
|
13
15
|
exports.maxRepayToBps = maxRepayToBps;
|
|
14
16
|
const constants_1 = require("../constants");
|
|
17
|
+
const generated_1 = require("../generated");
|
|
15
18
|
function getLiqUtilzationRateBps(supplyUsd, debtUsd, liqThresholdBps) {
|
|
16
19
|
if (supplyUsd === 0) {
|
|
17
20
|
return 0;
|
|
@@ -32,7 +35,7 @@ function toBps(value) {
|
|
|
32
35
|
}
|
|
33
36
|
function bytesToI80F48(bytes) {
|
|
34
37
|
if (bytes.length !== 16) {
|
|
35
|
-
throw new Error(
|
|
38
|
+
throw new Error("Byte array must be exactly 16 bytes.");
|
|
36
39
|
}
|
|
37
40
|
const reversedBytes = bytes.slice().reverse();
|
|
38
41
|
let integerPart = BigInt(0);
|
|
@@ -44,31 +47,65 @@ function bytesToI80F48(bytes) {
|
|
|
44
47
|
fractionalPart = (fractionalPart << 8n) | BigInt(reversedBytes[i]);
|
|
45
48
|
}
|
|
46
49
|
const fullValue = integerPart * BigInt(2 ** 48) + fractionalPart;
|
|
47
|
-
return Number(fullValue) /
|
|
50
|
+
return Number(fullValue) / 2 ** 48;
|
|
48
51
|
}
|
|
49
52
|
function uint8ArrayToBigInt(uint8Array) {
|
|
50
53
|
if (uint8Array.length !== 8) {
|
|
51
|
-
throw new Error(
|
|
54
|
+
throw new Error("Uint8Array must be exactly 8 bytes long to convert to u64.");
|
|
52
55
|
}
|
|
53
56
|
const buffer = uint8Array.buffer;
|
|
54
57
|
const dataView = new DataView(buffer);
|
|
55
58
|
const low = dataView.getUint32(0, true);
|
|
56
59
|
const high = dataView.getUint32(4, true);
|
|
57
|
-
return BigInt(high) << 32n | BigInt(low);
|
|
60
|
+
return (BigInt(high) << 32n) | BigInt(low);
|
|
58
61
|
}
|
|
59
62
|
function getDebtAdjustmentUsd(liqThresholdBps, supplyUsd, debtUsd, targetLiqUtilizationRateBps, adjustmentFeeBps) {
|
|
60
63
|
const adjustmentFee = adjustmentFeeBps && adjustmentFeeBps > 0 ? fromBps(adjustmentFeeBps) : 0;
|
|
61
64
|
const liqThreshold = fromBps(liqThresholdBps);
|
|
62
65
|
const targetLiqUtilizationRate = fromBps(targetLiqUtilizationRateBps);
|
|
63
|
-
const debtAdjustmentUsd = (targetLiqUtilizationRate * supplyUsd * liqThreshold - debtUsd) /
|
|
66
|
+
const debtAdjustmentUsd = (targetLiqUtilizationRate * supplyUsd * liqThreshold - debtUsd) /
|
|
67
|
+
(1 - targetLiqUtilizationRate * (1 - adjustmentFee) * liqThreshold);
|
|
64
68
|
return debtAdjustmentUsd;
|
|
65
69
|
}
|
|
66
|
-
function
|
|
67
|
-
|
|
70
|
+
function getSolautoFeesBps(isReferred, feeType, positionNetWorthUsd) {
|
|
71
|
+
const minSize = 10000; // Minimum position size
|
|
72
|
+
const maxSize = 1000000; // Maximum position size
|
|
73
|
+
const maxFeeBps = 500; // Fee in basis points for minSize (5%)
|
|
74
|
+
const minFeeBps = 100; // Fee in basis points for maxSize (1%)
|
|
75
|
+
let feeBps = 0;
|
|
76
|
+
if (feeType === generated_1.FeeType.Small) {
|
|
77
|
+
feeBps = 100;
|
|
78
|
+
}
|
|
79
|
+
else if (positionNetWorthUsd <= minSize) {
|
|
80
|
+
feeBps = maxFeeBps;
|
|
81
|
+
}
|
|
82
|
+
else if (positionNetWorthUsd >= maxSize) {
|
|
83
|
+
feeBps = minFeeBps;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const t = (Math.log(positionNetWorthUsd) - Math.log(minSize)) /
|
|
87
|
+
(Math.log(maxSize) - Math.log(minSize));
|
|
88
|
+
feeBps = Math.round(minFeeBps + (maxFeeBps - minFeeBps) * (1 - t));
|
|
89
|
+
}
|
|
90
|
+
let referrer = 0;
|
|
91
|
+
if (isReferred) {
|
|
92
|
+
referrer = Math.floor(feeBps / 4);
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
solauto: feeBps - referrer,
|
|
96
|
+
referrer,
|
|
97
|
+
total: feeBps,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps, offsetFromMaxLtv) {
|
|
101
|
+
return toBps((fromBps(maxLtvBps) - offsetFromMaxLtv) / fromBps(liqThresholdBps)) - 1; // -1 to account for any rounding issues
|
|
102
|
+
}
|
|
103
|
+
function maxBoostToBps(maxLtvBps, liqThresholdBps) {
|
|
104
|
+
return getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps, 0.015);
|
|
68
105
|
}
|
|
69
106
|
function maxRepayFromBps(maxLtvBps, liqThresholdBps) {
|
|
70
|
-
return Math.min(9000, getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps - 1000));
|
|
107
|
+
return Math.min(9000, getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps - 1000, 0.005));
|
|
71
108
|
}
|
|
72
109
|
function maxRepayToBps(maxLtvBps, liqThresholdBps) {
|
|
73
|
-
return Math.min(maxRepayFromBps(maxLtvBps, liqThresholdBps) - constants_1.MAX_REPAY_GAP_BPS, getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps));
|
|
110
|
+
return Math.min(maxRepayFromBps(maxLtvBps, liqThresholdBps) - constants_1.MAX_REPAY_GAP_BPS, getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps, 0.005));
|
|
74
111
|
}
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { PublicKey } from "@solana/web3.js";
|
|
2
2
|
import { Umi } from "@metaplex-foundation/umi";
|
|
3
|
-
import { AutomationSettings, DCASettings, DCASettingsInpArgs,
|
|
3
|
+
import { AutomationSettings, DCASettings, DCASettingsInpArgs, PositionState, SolautoSettingsParameters, SolautoSettingsParametersInpArgs } from "../../generated";
|
|
4
4
|
import { RebalanceAction, SolautoPositionDetails } from "../../types/solauto";
|
|
5
5
|
export declare function nextAutomationPeriodTimestamp(automation: AutomationSettings): number;
|
|
6
6
|
export declare function eligibleForNextAutomationPeriod(automation: AutomationSettings, currentUnixTime: number): boolean;
|
|
7
7
|
export declare function getUpdatedValueFromAutomation(currValue: number, targetValue: number, automation: AutomationSettings, currentUnixTimestamp: number): number;
|
|
8
8
|
export declare function getAdjustedSettingsFromAutomation(settings: SolautoSettingsParameters, currentUnixTime: number): SolautoSettingsParameters;
|
|
9
|
-
export declare function
|
|
10
|
-
solauto: number;
|
|
11
|
-
referrer: number;
|
|
12
|
-
total: number;
|
|
13
|
-
};
|
|
14
|
-
export declare function eligibleForRebalance(positionState: PositionState, positionSettings: SolautoSettingsParameters, positionDca: DCASettings | undefined, currentUnixSecs: number): RebalanceAction | undefined;
|
|
9
|
+
export declare function eligibleForRebalance(positionState: PositionState, positionSettings: SolautoSettingsParameters, positionDca: DCASettings | undefined, currentUnixTime: number): RebalanceAction | undefined;
|
|
15
10
|
export declare function eligibleForRefresh(positionState: PositionState, positionSettings: SolautoSettingsParameters, currentUnixTime: number): boolean;
|
|
16
11
|
export declare function getSolautoManagedPositions(umi: Umi, authority?: PublicKey): Promise<SolautoPositionDetails[]>;
|
|
17
12
|
export declare function getAllReferralStates(umi: Umi): Promise<PublicKey[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generalUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/solauto/generalUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAA+B,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,kBAAkB,
|
|
1
|
+
{"version":3,"file":"generalUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/solauto/generalUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,6 @@ exports.nextAutomationPeriodTimestamp = nextAutomationPeriodTimestamp;
|
|
|
5
5
|
exports.eligibleForNextAutomationPeriod = eligibleForNextAutomationPeriod;
|
|
6
6
|
exports.getUpdatedValueFromAutomation = getUpdatedValueFromAutomation;
|
|
7
7
|
exports.getAdjustedSettingsFromAutomation = getAdjustedSettingsFromAutomation;
|
|
8
|
-
exports.getSolautoFeesBps = getSolautoFeesBps;
|
|
9
8
|
exports.eligibleForRebalance = eligibleForRebalance;
|
|
10
9
|
exports.eligibleForRefresh = eligibleForRefresh;
|
|
11
10
|
exports.getSolautoManagedPositions = getSolautoManagedPositions;
|
|
@@ -55,30 +54,18 @@ function getAdjustedSettingsFromAutomation(settings, currentUnixTime) {
|
|
|
55
54
|
boostToBps,
|
|
56
55
|
};
|
|
57
56
|
}
|
|
58
|
-
function
|
|
59
|
-
const fees = feeType === generated_1.FeeType.Small ? 100 : 500;
|
|
60
|
-
let referrer = 0;
|
|
61
|
-
if (isReferred) {
|
|
62
|
-
referrer = fees / 4;
|
|
63
|
-
}
|
|
64
|
-
return {
|
|
65
|
-
solauto: fees - referrer,
|
|
66
|
-
referrer,
|
|
67
|
-
total: fees,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
function eligibleForRebalance(positionState, positionSettings, positionDca, currentUnixSecs) {
|
|
57
|
+
function eligibleForRebalance(positionState, positionSettings, positionDca, currentUnixTime) {
|
|
71
58
|
if (positionDca &&
|
|
72
59
|
positionDca.automation.targetPeriods > 0 &&
|
|
73
|
-
eligibleForNextAutomationPeriod(positionDca.automation,
|
|
60
|
+
eligibleForNextAutomationPeriod(positionDca.automation, currentUnixTime)) {
|
|
74
61
|
return "dca";
|
|
75
62
|
}
|
|
76
63
|
if (positionState.supply.amountUsed.baseUnit === BigInt(0)) {
|
|
77
64
|
return undefined;
|
|
78
65
|
}
|
|
79
|
-
const boostToBps = eligibleForRefresh(positionState, positionSettings,
|
|
66
|
+
const boostToBps = eligibleForRefresh(positionState, positionSettings, currentUnixTime) &&
|
|
80
67
|
positionSettings.automation.targetPeriods > 0
|
|
81
|
-
? getUpdatedValueFromAutomation(positionSettings.boostToBps, positionSettings.targetBoostToBps, positionSettings.automation,
|
|
68
|
+
? getUpdatedValueFromAutomation(positionSettings.boostToBps, positionSettings.targetBoostToBps, positionSettings.automation, currentUnixTime)
|
|
82
69
|
: positionSettings.boostToBps;
|
|
83
70
|
const repayFrom = positionSettings.repayToBps + positionSettings.repayGap;
|
|
84
71
|
const boostFrom = boostToBps - positionSettings.boostGap;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rebalanceUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/solauto/rebalanceUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,OAAO,EACP,aAAa,EAEb,yBAAyB,EAC1B,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"rebalanceUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/solauto/rebalanceUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,OAAO,EACP,aAAa,EAEb,yBAAyB,EAC1B,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAkJjD,MAAM,WAAW,eAAe;IAC9B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,yBAAyB,GAAG,SAAS,EAC/C,GAAG,EAAE,WAAW,GAAG,SAAS,EAC5B,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,MAAM,EACvB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,2BAA2B,CAAC,EAAE,MAAM,EACpC,WAAW,CAAC,EAAE,MAAM,GACnB,eAAe,CA0EjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,aAAa,GACtB,gBAAgB,GAAG,SAAS,CAmE9B;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,eAAe,EACvB,2BAA2B,CAAC,EAAE,MAAM,EACpC,UAAU,CAAC,EAAE,MAAM,GAClB,cAAc,CAkChB"}
|
|
@@ -19,8 +19,8 @@ function getAdditionalAmountToDcaIn(dca) {
|
|
|
19
19
|
}
|
|
20
20
|
function getStandardTargetLiqUtilizationRateBps(state, settings) {
|
|
21
21
|
const adjustedSettings = (0, generalUtils_1.getAdjustedSettingsFromAutomation)(settings, (0, generalUtils_2.currentUnixSeconds)());
|
|
22
|
-
const repayFrom =
|
|
23
|
-
const boostFrom = adjustedSettings.boostToBps -
|
|
22
|
+
const repayFrom = settings.repayToBps + settings.repayGap;
|
|
23
|
+
const boostFrom = adjustedSettings.boostToBps - settings.boostGap;
|
|
24
24
|
if (state.liqUtilizationRateBps < boostFrom) {
|
|
25
25
|
return adjustedSettings.boostToBps;
|
|
26
26
|
}
|
|
@@ -63,7 +63,7 @@ function getTargetRateAndDcaAmount(state, settings, dca, currentUnixTime, target
|
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
if (settings === undefined) {
|
|
66
|
-
throw new Error("If rebalancing a self-managed position, settings
|
|
66
|
+
throw new Error("If rebalancing a self-managed position, settings and DCA should be provided");
|
|
67
67
|
}
|
|
68
68
|
if (isDcaRebalance(state, settings, dca, currentUnixTime)) {
|
|
69
69
|
const amountToDcaIn = getAdditionalAmountToDcaIn(dca);
|
|
@@ -91,7 +91,7 @@ function getRebalanceValues(state, settings, dca, feeType, currentUnixTime, supp
|
|
|
91
91
|
const increasingLeverage = amountUsdToDcaIn > 0 || state.liqUtilizationRateBps < targetRateBps;
|
|
92
92
|
let adjustmentFeeBps = 0;
|
|
93
93
|
if (increasingLeverage) {
|
|
94
|
-
adjustmentFeeBps = (0,
|
|
94
|
+
adjustmentFeeBps = (0, numberUtils_1.getSolautoFeesBps)(false, feeType, (0, numberUtils_1.fromBaseUnit)(state.netWorth.baseAmountUsdValue, generalAccounts_1.USD_DECIMALS)).total;
|
|
95
95
|
}
|
|
96
96
|
const supplyUsd = (0, numberUtils_1.fromBaseUnit)(state.supply.amountUsed.baseAmountUsdValue, generalAccounts_1.USD_DECIMALS) +
|
|
97
97
|
amountUsdToDcaIn;
|
|
@@ -133,7 +133,7 @@ function getFlashLoanDetails(client, values, jupQuote) {
|
|
|
133
133
|
const tempLiqUtilizationRateBps = (0, numberUtils_1.getLiqUtilzationRateBps)(supplyUsd, debtUsd, client.solautoPositionState.liqThresholdBps);
|
|
134
134
|
const requiresFlashLoan = supplyUsd <= 0 ||
|
|
135
135
|
tempLiqUtilizationRateBps >
|
|
136
|
-
(0, numberUtils_1.getMaxLiqUtilizationRateBps)(client.solautoPositionState.maxLtvBps, client.solautoPositionState.liqThresholdBps);
|
|
136
|
+
(0, numberUtils_1.getMaxLiqUtilizationRateBps)(client.solautoPositionState.maxLtvBps, client.solautoPositionState.liqThresholdBps, 0.01);
|
|
137
137
|
let flashLoanToken = undefined;
|
|
138
138
|
let flashLoanTokenPrice = 0;
|
|
139
139
|
if (values.increasingLeverage) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Instruction,
|
|
3
|
-
Signer,
|
|
4
3
|
TransactionBuilder,
|
|
5
4
|
Umi,
|
|
6
5
|
publicKey,
|
|
@@ -14,7 +13,6 @@ import {
|
|
|
14
13
|
Account as SplTokenAccount,
|
|
15
14
|
} from "@solana/spl-token";
|
|
16
15
|
import {
|
|
17
|
-
FeeType,
|
|
18
16
|
LendingPlatform,
|
|
19
17
|
ReferralState,
|
|
20
18
|
SOLAUTO_PROGRAM_ID,
|
|
@@ -582,7 +580,7 @@ export async function buildSolautoRebalanceTransaction(
|
|
|
582
580
|
client.solautoPositionState!,
|
|
583
581
|
client.solautoPositionSettings(),
|
|
584
582
|
client.solautoPositionActiveDca(),
|
|
585
|
-
client.solautoPositionData
|
|
583
|
+
client.solautoPositionData!.feeType,
|
|
586
584
|
currentUnixSeconds(),
|
|
587
585
|
PRICES[client.supplyMint.toString()].price,
|
|
588
586
|
PRICES[client.debtMint.toString()].price,
|
|
@@ -672,7 +670,8 @@ export async function buildSolautoRebalanceTransaction(
|
|
|
672
670
|
client.solautoPositionState!.liqUtilizationRateBps >
|
|
673
671
|
getMaxLiqUtilizationRateBps(
|
|
674
672
|
client.solautoPositionState!.maxLtvBps,
|
|
675
|
-
client.solautoPositionState!.liqThresholdBps
|
|
673
|
+
client.solautoPositionState!.liqThresholdBps,
|
|
674
|
+
0.01
|
|
676
675
|
)
|
|
677
676
|
) {
|
|
678
677
|
tx = tx.prepend(client.refresh());
|
package/src/utils/numberUtils.ts
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { MAX_REPAY_GAP_BPS } from "../constants";
|
|
2
|
+
import { FeeType } from "../generated";
|
|
2
3
|
|
|
3
|
-
export function getLiqUtilzationRateBps(
|
|
4
|
+
export function getLiqUtilzationRateBps(
|
|
5
|
+
supplyUsd: number,
|
|
6
|
+
debtUsd: number,
|
|
7
|
+
liqThresholdBps: number
|
|
8
|
+
): number {
|
|
4
9
|
if (supplyUsd === 0) {
|
|
5
10
|
return 0;
|
|
6
11
|
}
|
|
7
|
-
|
|
12
|
+
|
|
8
13
|
return toBps(debtUsd / (supplyUsd * fromBps(liqThresholdBps)));
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
export function toBaseUnit(value: number, decimals: number): bigint {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
return BigInt(Math.round(value * Math.pow(10, decimals)));
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
export function fromBaseUnit(value: bigint, decimals: number): number {
|
|
16
21
|
return Number(value) / Math.pow(10, decimals);
|
|
17
22
|
}
|
|
@@ -26,7 +31,7 @@ export function toBps(value: number): number {
|
|
|
26
31
|
|
|
27
32
|
export function bytesToI80F48(bytes: number[]): number {
|
|
28
33
|
if (bytes.length !== 16) {
|
|
29
|
-
throw new Error(
|
|
34
|
+
throw new Error("Byte array must be exactly 16 bytes.");
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
const reversedBytes = bytes.slice().reverse();
|
|
@@ -44,12 +49,14 @@ export function bytesToI80F48(bytes: number[]): number {
|
|
|
44
49
|
|
|
45
50
|
const fullValue = integerPart * BigInt(2 ** 48) + fractionalPart;
|
|
46
51
|
|
|
47
|
-
return Number(fullValue) /
|
|
52
|
+
return Number(fullValue) / 2 ** 48;
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
export function uint8ArrayToBigInt(uint8Array: Uint8Array): bigint {
|
|
51
56
|
if (uint8Array.length !== 8) {
|
|
52
|
-
throw new Error(
|
|
57
|
+
throw new Error(
|
|
58
|
+
"Uint8Array must be exactly 8 bytes long to convert to u64."
|
|
59
|
+
);
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
const buffer = uint8Array.buffer;
|
|
@@ -59,7 +66,7 @@ export function uint8ArrayToBigInt(uint8Array: Uint8Array): bigint {
|
|
|
59
66
|
const low = dataView.getUint32(0, true);
|
|
60
67
|
const high = dataView.getUint32(4, true);
|
|
61
68
|
|
|
62
|
-
return BigInt(high) << 32n | BigInt(low);
|
|
69
|
+
return (BigInt(high) << 32n) | BigInt(low);
|
|
63
70
|
}
|
|
64
71
|
|
|
65
72
|
export function getDebtAdjustmentUsd(
|
|
@@ -69,31 +76,79 @@ export function getDebtAdjustmentUsd(
|
|
|
69
76
|
targetLiqUtilizationRateBps: number,
|
|
70
77
|
adjustmentFeeBps?: number
|
|
71
78
|
) {
|
|
72
|
-
const adjustmentFee =
|
|
79
|
+
const adjustmentFee =
|
|
80
|
+
adjustmentFeeBps && adjustmentFeeBps > 0 ? fromBps(adjustmentFeeBps) : 0;
|
|
73
81
|
const liqThreshold = fromBps(liqThresholdBps);
|
|
74
82
|
const targetLiqUtilizationRate = fromBps(targetLiqUtilizationRateBps);
|
|
75
83
|
|
|
76
|
-
const debtAdjustmentUsd =
|
|
84
|
+
const debtAdjustmentUsd =
|
|
85
|
+
(targetLiqUtilizationRate * supplyUsd * liqThreshold - debtUsd) /
|
|
86
|
+
(1 - targetLiqUtilizationRate * (1 - adjustmentFee) * liqThreshold);
|
|
77
87
|
return debtAdjustmentUsd;
|
|
78
88
|
}
|
|
79
89
|
|
|
90
|
+
export function getSolautoFeesBps(
|
|
91
|
+
isReferred: boolean,
|
|
92
|
+
feeType: FeeType,
|
|
93
|
+
positionNetWorthUsd: number
|
|
94
|
+
): {
|
|
95
|
+
solauto: number;
|
|
96
|
+
referrer: number;
|
|
97
|
+
total: number;
|
|
98
|
+
} {
|
|
99
|
+
const minSize = 10000; // Minimum position size
|
|
100
|
+
const maxSize = 1000000; // Maximum position size
|
|
101
|
+
const maxFeeBps = 500; // Fee in basis points for minSize (5%)
|
|
102
|
+
const minFeeBps = 100; // Fee in basis points for maxSize (1%)
|
|
103
|
+
|
|
104
|
+
let feeBps: number = 0;
|
|
105
|
+
if (feeType === FeeType.Small) {
|
|
106
|
+
feeBps = 100;
|
|
107
|
+
} else if (positionNetWorthUsd <= minSize) {
|
|
108
|
+
feeBps = maxFeeBps;
|
|
109
|
+
} else if (positionNetWorthUsd >= maxSize) {
|
|
110
|
+
feeBps = minFeeBps;
|
|
111
|
+
} else {
|
|
112
|
+
const t =
|
|
113
|
+
(Math.log(positionNetWorthUsd) - Math.log(minSize)) /
|
|
114
|
+
(Math.log(maxSize) - Math.log(minSize));
|
|
115
|
+
feeBps = Math.round(minFeeBps + (maxFeeBps - minFeeBps) * (1 - t));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
let referrer = 0;
|
|
119
|
+
if (isReferred) {
|
|
120
|
+
referrer = Math.floor(feeBps / 4);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
solauto: feeBps - referrer,
|
|
125
|
+
referrer,
|
|
126
|
+
total: feeBps,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
80
130
|
export function getMaxLiqUtilizationRateBps(
|
|
81
131
|
maxLtvBps: number,
|
|
82
|
-
liqThresholdBps: number
|
|
132
|
+
liqThresholdBps: number,
|
|
133
|
+
offsetFromMaxLtv: number
|
|
83
134
|
): number {
|
|
84
|
-
return toBps((fromBps(maxLtvBps) -
|
|
135
|
+
return toBps((fromBps(maxLtvBps) - offsetFromMaxLtv) / fromBps(liqThresholdBps)) - 1; // -1 to account for any rounding issues
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function maxBoostToBps(maxLtvBps: number, liqThresholdBps: number) {
|
|
139
|
+
return getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps, 0.015);
|
|
85
140
|
}
|
|
86
141
|
|
|
87
142
|
export function maxRepayFromBps(maxLtvBps: number, liqThresholdBps: number) {
|
|
88
143
|
return Math.min(
|
|
89
144
|
9000,
|
|
90
|
-
getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps - 1000)
|
|
145
|
+
getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps - 1000, 0.005)
|
|
91
146
|
);
|
|
92
147
|
}
|
|
93
148
|
|
|
94
149
|
export function maxRepayToBps(maxLtvBps: number, liqThresholdBps: number) {
|
|
95
150
|
return Math.min(
|
|
96
151
|
maxRepayFromBps(maxLtvBps, liqThresholdBps) - MAX_REPAY_GAP_BPS,
|
|
97
|
-
getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps)
|
|
152
|
+
getMaxLiqUtilizationRateBps(maxLtvBps, liqThresholdBps, 0.005)
|
|
98
153
|
);
|
|
99
|
-
}
|
|
154
|
+
}
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
AutomationSettings,
|
|
5
5
|
DCASettings,
|
|
6
6
|
DCASettingsInpArgs,
|
|
7
|
-
FeeType,
|
|
8
7
|
LendingPlatform,
|
|
9
8
|
PositionState,
|
|
10
9
|
SOLAUTO_PROGRAM_ID,
|
|
@@ -29,7 +28,6 @@ import {
|
|
|
29
28
|
} from "../../constants";
|
|
30
29
|
import {
|
|
31
30
|
getAllMarginfiAccountsByAuthority,
|
|
32
|
-
getMarginfiAccountPositionState,
|
|
33
31
|
} from "../marginfiUtils";
|
|
34
32
|
import { RebalanceAction, SolautoPositionDetails } from "../../types/solauto";
|
|
35
33
|
|
|
@@ -102,37 +100,16 @@ export function getAdjustedSettingsFromAutomation(
|
|
|
102
100
|
};
|
|
103
101
|
}
|
|
104
102
|
|
|
105
|
-
export function getSolautoFeesBps(
|
|
106
|
-
isReferred: boolean,
|
|
107
|
-
feeType: FeeType
|
|
108
|
-
): {
|
|
109
|
-
solauto: number;
|
|
110
|
-
referrer: number;
|
|
111
|
-
total: number;
|
|
112
|
-
} {
|
|
113
|
-
const fees = feeType === FeeType.Small ? 100 : 500;
|
|
114
|
-
let referrer = 0;
|
|
115
|
-
if (isReferred) {
|
|
116
|
-
referrer = fees / 4;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
solauto: fees - referrer,
|
|
121
|
-
referrer,
|
|
122
|
-
total: fees,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
103
|
export function eligibleForRebalance(
|
|
127
104
|
positionState: PositionState,
|
|
128
105
|
positionSettings: SolautoSettingsParameters,
|
|
129
106
|
positionDca: DCASettings | undefined,
|
|
130
|
-
|
|
107
|
+
currentUnixTime: number
|
|
131
108
|
): RebalanceAction | undefined {
|
|
132
109
|
if (
|
|
133
110
|
positionDca &&
|
|
134
111
|
positionDca.automation.targetPeriods > 0 &&
|
|
135
|
-
eligibleForNextAutomationPeriod(positionDca.automation,
|
|
112
|
+
eligibleForNextAutomationPeriod(positionDca.automation, currentUnixTime)
|
|
136
113
|
) {
|
|
137
114
|
return "dca";
|
|
138
115
|
}
|
|
@@ -142,13 +119,13 @@ export function eligibleForRebalance(
|
|
|
142
119
|
}
|
|
143
120
|
|
|
144
121
|
const boostToBps =
|
|
145
|
-
eligibleForRefresh(positionState, positionSettings,
|
|
122
|
+
eligibleForRefresh(positionState, positionSettings, currentUnixTime) &&
|
|
146
123
|
positionSettings.automation.targetPeriods > 0
|
|
147
124
|
? getUpdatedValueFromAutomation(
|
|
148
125
|
positionSettings.boostToBps,
|
|
149
126
|
positionSettings.targetBoostToBps,
|
|
150
127
|
positionSettings.automation,
|
|
151
|
-
|
|
128
|
+
currentUnixTime
|
|
152
129
|
)
|
|
153
130
|
: positionSettings.boostToBps;
|
|
154
131
|
const repayFrom = positionSettings.repayToBps + positionSettings.repayGap;
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
eligibleForNextAutomationPeriod,
|
|
12
12
|
getAdjustedSettingsFromAutomation,
|
|
13
|
-
getSolautoFeesBps,
|
|
14
13
|
getUpdatedValueFromAutomation,
|
|
15
14
|
} from "./generalUtils";
|
|
16
15
|
import { toWeb3JsPublicKey } from "@metaplex-foundation/umi-web3js-adapters";
|
|
@@ -23,6 +22,7 @@ import {
|
|
|
23
22
|
getDebtAdjustmentUsd,
|
|
24
23
|
getLiqUtilzationRateBps,
|
|
25
24
|
getMaxLiqUtilizationRateBps,
|
|
25
|
+
getSolautoFeesBps,
|
|
26
26
|
toBaseUnit,
|
|
27
27
|
} from "../numberUtils";
|
|
28
28
|
import { USD_DECIMALS } from "../../constants/generalAccounts";
|
|
@@ -57,8 +57,8 @@ function getStandardTargetLiqUtilizationRateBps(
|
|
|
57
57
|
currentUnixSeconds()
|
|
58
58
|
);
|
|
59
59
|
|
|
60
|
-
const repayFrom =
|
|
61
|
-
const boostFrom = adjustedSettings.boostToBps -
|
|
60
|
+
const repayFrom = settings.repayToBps + settings.repayGap;
|
|
61
|
+
const boostFrom = adjustedSettings.boostToBps - settings.boostGap;
|
|
62
62
|
|
|
63
63
|
if (state.liqUtilizationRateBps < boostFrom) {
|
|
64
64
|
return adjustedSettings.boostToBps;
|
|
@@ -136,7 +136,7 @@ function getTargetRateAndDcaAmount(
|
|
|
136
136
|
|
|
137
137
|
if (settings === undefined) {
|
|
138
138
|
throw new Error(
|
|
139
|
-
"If rebalancing a self-managed position, settings
|
|
139
|
+
"If rebalancing a self-managed position, settings and DCA should be provided"
|
|
140
140
|
);
|
|
141
141
|
}
|
|
142
142
|
|
|
@@ -204,7 +204,11 @@ export function getRebalanceValues(
|
|
|
204
204
|
amountUsdToDcaIn > 0 || state.liqUtilizationRateBps < targetRateBps;
|
|
205
205
|
let adjustmentFeeBps = 0;
|
|
206
206
|
if (increasingLeverage) {
|
|
207
|
-
adjustmentFeeBps = getSolautoFeesBps(
|
|
207
|
+
adjustmentFeeBps = getSolautoFeesBps(
|
|
208
|
+
false,
|
|
209
|
+
feeType,
|
|
210
|
+
fromBaseUnit(state.netWorth.baseAmountUsdValue, USD_DECIMALS)
|
|
211
|
+
).total;
|
|
208
212
|
}
|
|
209
213
|
|
|
210
214
|
const supplyUsd =
|
|
@@ -290,7 +294,8 @@ export function getFlashLoanDetails(
|
|
|
290
294
|
tempLiqUtilizationRateBps >
|
|
291
295
|
getMaxLiqUtilizationRateBps(
|
|
292
296
|
client.solautoPositionState!.maxLtvBps,
|
|
293
|
-
client.solautoPositionState!.liqThresholdBps
|
|
297
|
+
client.solautoPositionState!.liqThresholdBps,
|
|
298
|
+
0.01
|
|
294
299
|
);
|
|
295
300
|
|
|
296
301
|
let flashLoanToken: PositionTokenUsage | undefined = undefined;
|
|
@@ -5,12 +5,11 @@ import {
|
|
|
5
5
|
SolautoMarginfiClient,
|
|
6
6
|
} from "../../src/clients/solautoMarginfiClient";
|
|
7
7
|
import {
|
|
8
|
-
LendingPlatform,
|
|
9
8
|
solautoAction,
|
|
10
9
|
SolautoSettingsParametersInpArgs,
|
|
11
10
|
} from "../../src/generated";
|
|
12
11
|
import { buildSolautoRebalanceTransaction } from "../../src/transactions/transactionUtils";
|
|
13
|
-
import {
|
|
12
|
+
import { maxBoostToBps, maxRepayFromBps, maxRepayToBps, toBaseUnit } from "../../src/utils/numberUtils";
|
|
14
13
|
import { NATIVE_MINT } from "@solana/spl-token";
|
|
15
14
|
import { getTokenPrices } from "../../src/utils/generalUtils";
|
|
16
15
|
import {
|
|
@@ -21,12 +20,12 @@ import { PublicKey } from "@solana/web3.js";
|
|
|
21
20
|
import { USDC_MINT } from "../../src/constants";
|
|
22
21
|
|
|
23
22
|
describe("Solauto Marginfi tests", async () => {
|
|
24
|
-
|
|
25
|
-
const signer = setupTest("solauto-manager");
|
|
23
|
+
const signer = setupTest();
|
|
24
|
+
// const signer = setupTest("solauto-manager");
|
|
26
25
|
|
|
27
26
|
const payForTransactions = false;
|
|
28
27
|
const useJitoBundle = false;
|
|
29
|
-
const positionId =
|
|
28
|
+
const positionId = 2;
|
|
30
29
|
|
|
31
30
|
it("open - deposit - borrow - rebalance to 0 - withdraw - close", async () => {
|
|
32
31
|
const client = new SolautoMarginfiClient(process.env.HELIUS_API_KEY!, true);
|
|
@@ -67,22 +66,26 @@ describe("Solauto Marginfi tests", async () => {
|
|
|
67
66
|
// }, "open position")
|
|
68
67
|
// );
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
69
|
+
// const initialSupplyUsd = 150;
|
|
70
|
+
// transactionItems.push(
|
|
71
|
+
// new TransactionItem(async () => {
|
|
72
|
+
// const [supplyPrice] = await getTokenPrices([supply]);
|
|
73
|
+
// return {
|
|
74
|
+
// tx: client.protocolInteraction(
|
|
75
|
+
// solautoAction("Deposit", [
|
|
76
|
+
// toBaseUnit(initialSupplyUsd / supplyPrice, supplyDecimals),
|
|
77
|
+
// ])
|
|
78
|
+
// ),
|
|
79
|
+
// };
|
|
80
|
+
// }, "deposit")
|
|
81
|
+
// );
|
|
83
82
|
// }
|
|
84
83
|
|
|
85
|
-
// const
|
|
84
|
+
// const maxLtvBps = client.solautoPositionState!.maxLtvBps;
|
|
85
|
+
// const liqThresholdBps = client.solautoPositionState!.liqThresholdBps;
|
|
86
|
+
// const maxRepayFrom = maxRepayFromBps(maxLtvBps, liqThresholdBps);
|
|
87
|
+
// const maxRepayTo = maxRepayToBps(maxLtvBps, liqThresholdBps);
|
|
88
|
+
// const maxBoostTo = maxBoostToBps(maxLtvBps, liqThresholdBps);
|
|
86
89
|
// transactionItems.push(
|
|
87
90
|
// new TransactionItem(
|
|
88
91
|
// async () => ({
|
|
@@ -90,10 +93,10 @@ describe("Solauto Marginfi tests", async () => {
|
|
|
90
93
|
// positionId: client.positionId,
|
|
91
94
|
// settingParams: some({
|
|
92
95
|
// ...settingParams,
|
|
96
|
+
// boostToBps: maxBoostTo,
|
|
93
97
|
// boostGap: 50,
|
|
94
|
-
//
|
|
95
|
-
// repayGap:
|
|
96
|
-
// repayToBps: maxLiqRate
|
|
98
|
+
// repayToBps: maxRepayTo,
|
|
99
|
+
// repayGap: maxRepayFrom - maxRepayTo
|
|
97
100
|
// }),
|
|
98
101
|
// dca: null,
|
|
99
102
|
// }),
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
fromBaseUnit,
|
|
19
19
|
fromBps,
|
|
20
20
|
getLiqUtilzationRateBps,
|
|
21
|
+
getSolautoFeesBps,
|
|
21
22
|
toBaseUnit,
|
|
22
23
|
} from "../../src/utils/numberUtils";
|
|
23
24
|
import { USD_DECIMALS } from "../../src/constants/generalAccounts";
|
|
@@ -25,7 +26,6 @@ import {
|
|
|
25
26
|
createFakePositionState,
|
|
26
27
|
eligibleForNextAutomationPeriod,
|
|
27
28
|
getAdjustedSettingsFromAutomation,
|
|
28
|
-
getSolautoFeesBps,
|
|
29
29
|
getUpdatedValueFromAutomation,
|
|
30
30
|
positionStateWithLatestPrices,
|
|
31
31
|
} from "../../src/utils/solauto/generalUtils";
|
|
@@ -49,7 +49,7 @@ function assertAccurateRebalance(
|
|
|
49
49
|
client.solautoPositionState!,
|
|
50
50
|
client.solautoPositionSettings(),
|
|
51
51
|
client.solautoPositionActiveDca(),
|
|
52
|
-
client.solautoPositionData
|
|
52
|
+
client.solautoPositionData!.feeType,
|
|
53
53
|
currentUnixSeconds(),
|
|
54
54
|
PRICES[client.supplyMint.toString()].price,
|
|
55
55
|
PRICES[client.debtMint.toString()].price,
|
|
@@ -60,7 +60,11 @@ function assertAccurateRebalance(
|
|
|
60
60
|
if (increasingLeverage) {
|
|
61
61
|
adjustmentFeeBps = getSolautoFeesBps(
|
|
62
62
|
client.referredByState !== undefined,
|
|
63
|
-
client.solautoPositionData!.feeType
|
|
63
|
+
client.solautoPositionData!.feeType,
|
|
64
|
+
fromBaseUnit(
|
|
65
|
+
client.solautoPositionState?.netWorth.baseAmountUsdValue ?? BigInt(0),
|
|
66
|
+
USD_DECIMALS
|
|
67
|
+
)
|
|
64
68
|
).total;
|
|
65
69
|
}
|
|
66
70
|
|
|
@@ -285,28 +289,28 @@ describe("Rebalance tests", async () => {
|
|
|
285
289
|
]);
|
|
286
290
|
});
|
|
287
291
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
292
|
+
it("Standard rebalance with target rate", async () => {
|
|
293
|
+
const client = await getFakePosition(supplyPrice, debtPrice, 3450, {
|
|
294
|
+
boostToBps: 500,
|
|
295
|
+
boostGap: 100,
|
|
296
|
+
repayToBps: 7000,
|
|
297
|
+
repayGap: 250,
|
|
298
|
+
automation: {
|
|
299
|
+
targetPeriods: 0,
|
|
300
|
+
periodsPassed: 0,
|
|
301
|
+
unixStartDate: BigInt(0),
|
|
302
|
+
intervalSeconds: BigInt(0),
|
|
303
|
+
padding1: [],
|
|
304
|
+
padding: new Uint8Array([]),
|
|
305
|
+
},
|
|
306
|
+
targetBoostToBps: 0,
|
|
307
|
+
padding1: [],
|
|
308
|
+
padding: new Uint8Array([]),
|
|
309
|
+
});
|
|
306
310
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
311
|
+
assertAccurateRebalance(client, 5000, 5000);
|
|
312
|
+
assertAccurateRebalance(client, 1000, 1000);
|
|
313
|
+
});
|
|
310
314
|
|
|
311
315
|
it("Standard boost or repay", async () => {
|
|
312
316
|
const settings: SolautoSettingsParameters = {
|