@haven-fi/solauto-sdk 1.0.59 → 1.0.60

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.
@@ -1 +1 @@
1
- {"version":3,"file":"transactionUtils.d.ts","sourceRoot":"","sources":["../../src/transactions/transactionUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,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;AAsMzD,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;AAGD,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,CAiHA;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"}
1
+ {"version":3,"file":"transactionUtils.d.ts","sourceRoot":"","sources":["../../src/transactions/transactionUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,kBAAkB,EAClB,GAAG,EAGJ,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAGL,OAAO,IAAI,eAAe,EAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAGL,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,CA0HA;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"}
@@ -17,6 +17,7 @@ const numberUtils_1 = require("../utils/numberUtils");
17
17
  const generalUtils_2 = require("../utils/solauto/generalUtils");
18
18
  const accountUtils_1 = require("../utils/accountUtils");
19
19
  const marginfi_sdk_1 = require("../marginfi-sdk");
20
+ const constants_1 = require("../constants");
20
21
  function getWSolUsage(client, solautoActions, initiatingDcaIn, cancellingDcaIn) {
21
22
  const supplyIsWsol = client.supplyMint.equals(spl_token_1.NATIVE_MINT);
22
23
  const debtIsWsol = client.debtMint.equals(spl_token_1.NATIVE_MINT);
@@ -328,7 +329,7 @@ async function buildSolautoRebalanceTransaction(client, targetLiqUtilizationRate
328
329
  client.log("Not eligible for a rebalance");
329
330
  return undefined;
330
331
  }
331
- const values = (0, rebalanceUtils_1.getRebalanceValues)(client, targetLiqUtilizationRateBps);
332
+ const values = (0, rebalanceUtils_1.getRebalanceValues)(client.solautoPositionState, client.solautoPositionSettings(), client.solautoPositionActiveDca(), client.solautoPositionData?.feeType ?? generated_1.FeeType.Small, (0, generalUtils_1.currentUnixSeconds)(), constants_1.PRICES[client.supplyMint.toString()].price, constants_1.PRICES[client.debtMint.toString()].price, targetLiqUtilizationRateBps);
332
333
  client.log("Rebalance values: ", values);
333
334
  const swapDetails = (0, rebalanceUtils_1.getJupSwapRebalanceDetails)(client, values, targetLiqUtilizationRateBps, attemptNum);
334
335
  const { jupQuote, lookupTableAddresses, setupInstructions, tokenLedgerIx, swapIx, } = await (0, jupiterUtils_1.getJupSwapTransaction)(client.signer, swapDetails, attemptNum);
@@ -3,21 +3,36 @@ import { Umi } from "@metaplex-foundation/umi";
3
3
  import { AutomationSettings, DCASettings, DCASettingsInpArgs, FeeType, LendingPlatform, PositionState, SolautoSettingsParameters, SolautoSettingsParametersInpArgs } from "../../generated";
4
4
  import { RebalanceAction, SolautoPositionDetails } from "../../types/solauto";
5
5
  export declare function nextAutomationPeriodTimestamp(automation: AutomationSettings): number;
6
- export declare function eligibleForNextAutomationPeriod(automation: AutomationSettings, currentUnixSecs?: number): boolean;
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
- export declare function getAdjustedSettingsFromAutomation(settings: SolautoSettingsParameters, currentUnixSecs?: number): SolautoSettingsParameters;
8
+ export declare function getAdjustedSettingsFromAutomation(settings: SolautoSettingsParameters, currentUnixTime: number): SolautoSettingsParameters;
9
9
  export declare function getSolautoFeesBps(isReferred: boolean, feeType: FeeType): {
10
10
  solauto: number;
11
11
  referrer: number;
12
12
  total: number;
13
13
  };
14
14
  export declare function eligibleForRebalance(positionState: PositionState, positionSettings: SolautoSettingsParameters, positionDca: DCASettings, currentUnixSecs: number): RebalanceAction | undefined;
15
- export declare function eligibleForRefresh(positionState: PositionState, positionSettings: SolautoSettingsParameters, currentUnixSecs?: number): boolean;
15
+ export declare function eligibleForRefresh(positionState: PositionState, positionSettings: SolautoSettingsParameters, currentUnixTime: number): boolean;
16
16
  export declare function getSolautoManagedPositions(umi: Umi, authority?: PublicKey): Promise<SolautoPositionDetails[]>;
17
17
  export declare function getAllReferralStates(umi: Umi): Promise<PublicKey[]>;
18
18
  export declare function getReferralsByUser(umi: Umi, user: PublicKey): Promise<PublicKey[]>;
19
19
  export declare function getAllPositionsByAuthority(umi: Umi, user: PublicKey): Promise<SolautoPositionDetails[]>;
20
- export declare function positionStateWithPrices(umi: Umi, state: PositionState, protocolAccount: PublicKey, lendingPlatform: LendingPlatform, supplyPrice?: number, debtPrice?: number): Promise<PositionState | undefined>;
20
+ interface GetLatestStateProps {
21
+ state: PositionState;
22
+ umi?: Umi;
23
+ protocolAccount?: PublicKey;
24
+ lendingPlatform?: LendingPlatform;
25
+ supplyPrice?: number;
26
+ debtPrice?: number;
27
+ }
28
+ export declare function positionStateWithPrices({ state, supplyPrice, debtPrice, umi, protocolAccount, lendingPlatform, }: GetLatestStateProps): Promise<PositionState | undefined>;
29
+ interface AssetProps {
30
+ amountUsedBaseUnit: bigint;
31
+ decimals: number;
32
+ price: number;
33
+ mint: PublicKey;
34
+ }
35
+ export declare function createFakePositionState(supply: AssetProps, debt: AssetProps, maxLtvBps: number, liqThresholdBps: number): PositionState;
21
36
  type PositionAdjustment = {
22
37
  type: "supply";
23
38
  value: bigint;
@@ -1 +1 @@
1
- {"version":3,"file":"generalUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/solauto/generalUtils.ts"],"names":[],"mappings":"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"}
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,EAClB,OAAO,EACP,eAAe,EACf,aAAa,EAEb,yBAAyB,EACzB,gCAAgC,EAIjC,MAAM,iBAAiB,CAAC;AAczB,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAgB9E,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,kBAAkB,GAC7B,MAAM,CAKR;AAED,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,kBAAkB,EAC9B,eAAe,EAAE,MAAM,GACtB,OAAO,CAET;AAED,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,kBAAkB,EAC9B,oBAAoB,EAAE,MAAM,UAY7B;AAED,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,yBAAyB,EACnC,eAAe,EAAE,MAAM,GACtB,yBAAyB,CAgB3B;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,OAAO,GACf;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAYA;AAED,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,yBAAyB,EAC3C,WAAW,EAAE,WAAW,EACxB,eAAe,EAAE,MAAM,GACtB,eAAe,GAAG,SAAS,CAgC7B;AAED,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,yBAAyB,EAC3C,eAAe,EAAE,MAAM,GACtB,OAAO,CAYT;AAED,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,GAAG,EACR,SAAS,CAAC,EAAE,SAAS,GACpB,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAmDnC;AAED,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAezE;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,SAAS,EAAE,CAAC,CA2BtB;AAED,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAuCnC;AAED,UAAU,mBAAmB;IAC3B,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,uBAAuB,CAAC,EAC5C,KAAK,EACL,WAAW,EACX,SAAS,EACT,GAAG,EACH,eAAe,EACf,eAAe,GAChB,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAgE1D;AAED,UAAU,UAAU;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,GACtB,aAAa,CA8Df;AAED,KAAK,kBAAkB,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,gCAAgC,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAE/C,qBAAa,mBAAmB;IACvB,gBAAgB,EAAE,MAAM,CAAa;IACrC,cAAc,EAAE,MAAM,CAAa;IACnC,uBAAuB,EAAE,MAAM,CAAa;IAC5C,QAAQ,EAAE,yBAAyB,GAAG,SAAS,CAAa;IAC5D,SAAS,EAAE,WAAW,GAAG,SAAS,CAAa;IAEtD,GAAG,CAAC,MAAM,EAAE,kBAAkB;IAyD9B,KAAK;IAQL,UAAU,IAAI,OAAO;CAQtB"}
@@ -13,6 +13,7 @@ exports.getAllReferralStates = getAllReferralStates;
13
13
  exports.getReferralsByUser = getReferralsByUser;
14
14
  exports.getAllPositionsByAuthority = getAllPositionsByAuthority;
15
15
  exports.positionStateWithPrices = positionStateWithPrices;
16
+ exports.createFakePositionState = createFakePositionState;
16
17
  const web3_js_1 = require("@solana/web3.js");
17
18
  const umi_1 = require("@metaplex-foundation/umi");
18
19
  const generated_1 = require("../../generated");
@@ -33,8 +34,8 @@ function nextAutomationPeriodTimestamp(automation) {
33
34
  : Number(automation.unixStartDate) +
34
35
  automation.periodsPassed * Number(automation.intervalSeconds);
35
36
  }
36
- function eligibleForNextAutomationPeriod(automation, currentUnixSecs) {
37
- return (currentUnixSecs ?? (0, generalUtils_1.currentUnixSeconds)()) >= nextAutomationPeriodTimestamp(automation);
37
+ function eligibleForNextAutomationPeriod(automation, currentUnixTime) {
38
+ return currentUnixTime >= nextAutomationPeriodTimestamp(automation);
38
39
  }
39
40
  function getUpdatedValueFromAutomation(currValue, targetValue, automation, currentUnixTimestamp) {
40
41
  const currRateDiff = currValue - targetValue;
@@ -44,10 +45,10 @@ function getUpdatedValueFromAutomation(currValue, targetValue, automation, curre
44
45
  const newValue = currValue - currRateDiff * progressPct;
45
46
  return newValue;
46
47
  }
47
- function getAdjustedSettingsFromAutomation(settings, currentUnixSecs) {
48
+ function getAdjustedSettingsFromAutomation(settings, currentUnixTime) {
48
49
  const boostToBps = settings.automation.targetPeriods > 0 &&
49
- eligibleForNextAutomationPeriod(settings.automation, currentUnixSecs)
50
- ? getUpdatedValueFromAutomation(settings.boostToBps, settings.targetBoostToBps, settings.automation, currentUnixSecs ?? (0, generalUtils_1.currentUnixSeconds)())
50
+ eligibleForNextAutomationPeriod(settings.automation, currentUnixTime)
51
+ ? getUpdatedValueFromAutomation(settings.boostToBps, settings.targetBoostToBps, settings.automation, currentUnixTime)
51
52
  : settings.boostToBps;
52
53
  return {
53
54
  ...settings,
@@ -88,9 +89,9 @@ function eligibleForRebalance(positionState, positionSettings, positionDca, curr
88
89
  }
89
90
  return undefined;
90
91
  }
91
- function eligibleForRefresh(positionState, positionSettings, currentUnixSecs) {
92
+ function eligibleForRefresh(positionState, positionSettings, currentUnixTime) {
92
93
  if (positionSettings.automation.targetPeriods > 0) {
93
- return eligibleForNextAutomationPeriod(positionSettings.automation, currentUnixSecs);
94
+ return eligibleForNextAutomationPeriod(positionSettings.automation, currentUnixTime);
94
95
  }
95
96
  else {
96
97
  return ((0, generalUtils_1.currentUnixSeconds)() - Number(positionState.lastUpdated) >
@@ -211,8 +212,13 @@ async function getAllPositionsByAuthority(umi, user) {
211
212
  // TODO support other platforms
212
213
  return allPositions;
213
214
  }
214
- async function positionStateWithPrices(umi, state, protocolAccount, lendingPlatform, supplyPrice, debtPrice) {
215
+ async function positionStateWithPrices({ state, supplyPrice, debtPrice, umi, protocolAccount, lendingPlatform, }) {
215
216
  if ((0, generalUtils_1.currentUnixSeconds)() - Number(state.lastUpdated) > 60 * 60 * 24 * 7) {
217
+ if (umi === undefined ||
218
+ protocolAccount === undefined ||
219
+ lendingPlatform === undefined) {
220
+ throw new Error("Missing required parameters");
221
+ }
216
222
  if (lendingPlatform === generated_1.LendingPlatform.Marginfi) {
217
223
  return await (0, marginfiUtils_1.getMarginfiAccountPositionState)(umi, protocolAccount, (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(state.supply.mint), (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(state.debt.mint));
218
224
  }
@@ -234,7 +240,7 @@ async function positionStateWithPrices(umi, state, protocolAccount, lendingPlatf
234
240
  ...state,
235
241
  liqUtilizationRateBps: (0, numberUtils_1.getLiqUtilzationRateBps)(supplyUsd, debtUsd, state.liqThresholdBps),
236
242
  netWorth: {
237
- ...state.netWorth,
243
+ baseUnit: (0, numberUtils_1.toBaseUnit)((supplyUsd - debtUsd) / supplyPrice, state.supply.decimals),
238
244
  baseAmountUsdValue: (0, numberUtils_1.toBaseUnit)(supplyUsd - debtUsd, constants_1.USD_DECIMALS),
239
245
  },
240
246
  supply: {
@@ -253,6 +259,59 @@ async function positionStateWithPrices(umi, state, protocolAccount, lendingPlatf
253
259
  },
254
260
  };
255
261
  }
262
+ function createFakePositionState(supply, debt, maxLtvBps, liqThresholdBps) {
263
+ const supplyUsd = (0, numberUtils_1.fromBaseUnit)(supply.amountUsedBaseUnit, supply.decimals) * supply.price;
264
+ const debtUsd = (0, numberUtils_1.fromBaseUnit)(debt.amountUsedBaseUnit, debt.decimals) * debt.price;
265
+ return {
266
+ liqUtilizationRateBps: (0, numberUtils_1.getLiqUtilzationRateBps)(supplyUsd, debtUsd, liqThresholdBps),
267
+ supply: {
268
+ amountUsed: {
269
+ baseUnit: supply.amountUsedBaseUnit,
270
+ baseAmountUsdValue: (0, numberUtils_1.toBaseUnit)(supplyUsd, constants_1.USD_DECIMALS),
271
+ },
272
+ amountCanBeUsed: {
273
+ baseUnit: (0, numberUtils_1.toBaseUnit)(1000000, supply.decimals),
274
+ baseAmountUsdValue: BigInt(Math.round(1000000 * supply.price)),
275
+ },
276
+ baseAmountMarketPriceUsd: (0, numberUtils_1.toBaseUnit)(supply.price, constants_1.USD_DECIMALS),
277
+ borrowFeeBps: 0,
278
+ decimals: supply.decimals,
279
+ flashLoanFeeBps: 0,
280
+ mint: (0, umi_1.publicKey)(supply.mint),
281
+ padding1: [],
282
+ padding2: [],
283
+ padding: new Uint8Array([]),
284
+ },
285
+ debt: {
286
+ amountUsed: {
287
+ baseUnit: debt.amountUsedBaseUnit,
288
+ baseAmountUsdValue: (0, numberUtils_1.toBaseUnit)(debtUsd, constants_1.USD_DECIMALS),
289
+ },
290
+ amountCanBeUsed: {
291
+ baseUnit: (0, numberUtils_1.toBaseUnit)(1000000, debt.decimals),
292
+ baseAmountUsdValue: BigInt(Math.round(1000000 * debt.price)),
293
+ },
294
+ baseAmountMarketPriceUsd: (0, numberUtils_1.toBaseUnit)(debt.price, constants_1.USD_DECIMALS),
295
+ borrowFeeBps: 0,
296
+ decimals: debt.decimals,
297
+ flashLoanFeeBps: 0,
298
+ mint: (0, umi_1.publicKey)(debt.mint),
299
+ padding1: [],
300
+ padding2: [],
301
+ padding: new Uint8Array([]),
302
+ },
303
+ netWorth: {
304
+ baseUnit: (0, numberUtils_1.toBaseUnit)((supplyUsd - debtUsd) / supply.price, supply.decimals),
305
+ baseAmountUsdValue: (0, numberUtils_1.toBaseUnit)(supplyUsd - debtUsd, constants_1.USD_DECIMALS),
306
+ },
307
+ maxLtvBps,
308
+ liqThresholdBps,
309
+ lastUpdated: BigInt((0, generalUtils_1.currentUnixSeconds)()),
310
+ padding1: [],
311
+ padding2: [],
312
+ padding: [],
313
+ };
314
+ }
256
315
  class LivePositionUpdates {
257
316
  constructor() {
258
317
  this.supplyAdjustment = BigInt(0);
@@ -1,13 +1,15 @@
1
1
  import { PublicKey } from "@solana/web3.js";
2
2
  import { SolautoClient } from "../../clients/solautoClient";
3
+ import { DCASettings, FeeType, PositionState, SolautoSettingsParameters } from "../../generated";
3
4
  import { QuoteResponse } from "@jup-ag/api";
4
5
  import { JupSwapDetails } from "../jupiterUtils";
5
6
  export interface RebalanceValues {
6
7
  increasingLeverage: boolean;
7
8
  debtAdjustmentUsd: number;
9
+ amountToDcaIn: number;
8
10
  amountUsdToDcaIn: number;
9
11
  }
10
- export declare function getRebalanceValues(client: SolautoClient, targetLiqUtilizationRateBps?: number, limitGapBps?: number): RebalanceValues;
12
+ export declare function getRebalanceValues(state: PositionState, settings: SolautoSettingsParameters | undefined, dca: DCASettings | undefined, feeType: FeeType, currentUnixTime: number, supplyPrice: number, debtPrice: number, targetLiqUtilizationRateBps?: number, limitGapBps?: number): RebalanceValues;
11
13
  export interface FlashLoanDetails {
12
14
  baseUnitAmount: bigint;
13
15
  mint: PublicKey;
@@ -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;AAS5D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA4IjD,MAAM,WAAW,eAAe;IAC9B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,aAAa,EACrB,2BAA2B,CAAC,EAAE,MAAM,EACpC,WAAW,CAAC,EAAE,MAAM,GACnB,eAAe,CA8EjB;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,CAkE9B;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,eAAe,EACvB,2BAA2B,CAAC,EAAE,MAAM,EACpC,UAAU,CAAC,EAAE,MAAM,GAClB,cAAc,CAkChB"}
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;AAQzB,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,CAsEjB;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,CAkE9B;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,eAAe,EACvB,2BAA2B,CAAC,EAAE,MAAM,EACpC,UAAU,CAAC,EAAE,MAAM,GAClB,cAAc,CAkChB"}
@@ -3,81 +3,72 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getRebalanceValues = getRebalanceValues;
4
4
  exports.getFlashLoanDetails = getFlashLoanDetails;
5
5
  exports.getJupSwapRebalanceDetails = getJupSwapRebalanceDetails;
6
- const generated_1 = require("../../generated");
7
6
  const generalUtils_1 = require("./generalUtils");
8
7
  const umi_web3js_adapters_1 = require("@metaplex-foundation/umi-web3js-adapters");
9
8
  const generalUtils_2 = require("../generalUtils");
10
9
  const numberUtils_1 = require("../numberUtils");
11
10
  const generalAccounts_1 = require("../../constants/generalAccounts");
12
11
  const solautoConstants_1 = require("../../constants/solautoConstants");
13
- function getAdditionalAmountToDcaIn(client) {
14
- const dca = client.solautoPositionActiveDca();
12
+ function getAdditionalAmountToDcaIn(dca) {
15
13
  if (dca.debtToAddBaseUnit === BigInt(0)) {
16
14
  return 0;
17
15
  }
18
- const debtBalance = Number(client.solautoPositionData?.position.dca.debtToAddBaseUnit ?? 0) +
19
- Number(client.livePositionUpdates.debtTaBalanceAdjustment ?? 0);
16
+ const debtBalance = Number(dca.debtToAddBaseUnit);
20
17
  const updatedDebtBalance = (0, generalUtils_1.getUpdatedValueFromAutomation)(debtBalance, 0, dca.automation, (0, generalUtils_2.currentUnixSeconds)());
21
18
  return debtBalance - updatedDebtBalance;
22
19
  }
23
- function getStandardTargetLiqUtilizationRateBps(client) {
24
- if (!client.selfManaged) {
25
- const adjustedSettings = (0, generalUtils_1.getAdjustedSettingsFromAutomation)(client.solautoPositionSettings(), (0, generalUtils_2.currentUnixSeconds)());
26
- const repayFrom = adjustedSettings.repayToBps - adjustedSettings.repayGap;
27
- const boostFrom = adjustedSettings.boostToBps + adjustedSettings.boostGap;
28
- if (client.solautoPositionState.liqUtilizationRateBps < boostFrom) {
29
- return adjustedSettings.boostToBps;
30
- }
31
- else if (client.solautoPositionState.liqUtilizationRateBps > repayFrom ||
32
- repayFrom - client.solautoPositionState.liqUtilizationRateBps <
33
- repayFrom * 0.015) {
34
- return adjustedSettings.repayToBps;
35
- }
36
- else {
37
- throw new Error("Invalid rebalance condition");
38
- }
20
+ function getStandardTargetLiqUtilizationRateBps(state, settings) {
21
+ const adjustedSettings = (0, generalUtils_1.getAdjustedSettingsFromAutomation)(settings, (0, generalUtils_2.currentUnixSeconds)());
22
+ const repayFrom = adjustedSettings.repayToBps - adjustedSettings.repayGap;
23
+ const boostFrom = adjustedSettings.boostToBps + adjustedSettings.boostGap;
24
+ if (state.liqUtilizationRateBps < boostFrom) {
25
+ return adjustedSettings.boostToBps;
26
+ }
27
+ else if (state.liqUtilizationRateBps > repayFrom ||
28
+ repayFrom - state.liqUtilizationRateBps < repayFrom * 0.015) {
29
+ return adjustedSettings.repayToBps;
39
30
  }
40
31
  else {
41
- throw new Error("This is a self-managed position, a targetLiqUtilizationRateBps must be provided initiate a rebalance");
32
+ throw new Error("Invalid rebalance condition");
42
33
  }
43
34
  }
44
- function targetLiqUtilizationRateBpsFromDCA(client) {
45
- const adjustedSettings = (0, generalUtils_1.getAdjustedSettingsFromAutomation)(client.solautoPositionSettings(), (0, generalUtils_2.currentUnixSeconds)());
35
+ function targetLiqUtilizationRateBpsFromDCA(state, settings, dca) {
36
+ const adjustedSettings = (0, generalUtils_1.getAdjustedSettingsFromAutomation)(settings, (0, generalUtils_2.currentUnixSeconds)());
46
37
  let targetRateBps = 0;
47
- if (client.solautoPositionActiveDca().debtToAddBaseUnit > BigInt(0)) {
48
- targetRateBps = Math.max(client.solautoPositionState.liqUtilizationRateBps, adjustedSettings.boostToBps);
38
+ if (dca.debtToAddBaseUnit > BigInt(0)) {
39
+ targetRateBps = Math.max(state.liqUtilizationRateBps, adjustedSettings.boostToBps);
49
40
  }
50
41
  else {
51
42
  targetRateBps = adjustedSettings.boostToBps;
52
43
  }
53
44
  return targetRateBps;
54
45
  }
55
- function isDcaRebalance(client) {
56
- if (client.solautoPositionActiveDca() === undefined || client.selfManaged) {
46
+ function isDcaRebalance(state, settings, dca, currentUnixTime) {
47
+ if (dca === undefined || dca.automation.targetPeriods === 0) {
57
48
  return false;
58
49
  }
59
- const adjustedSettings = (0, generalUtils_1.getAdjustedSettingsFromAutomation)(client.solautoPositionSettings(), (0, generalUtils_2.currentUnixSeconds)());
60
- if (client.solautoPositionState.liqUtilizationRateBps >
50
+ const adjustedSettings = (0, generalUtils_1.getAdjustedSettingsFromAutomation)(settings, (0, generalUtils_2.currentUnixSeconds)());
51
+ if (state.liqUtilizationRateBps >
61
52
  adjustedSettings.repayToBps + adjustedSettings.repayGap) {
62
53
  return false;
63
54
  }
64
- if (client.solautoPositionActiveDca().automation.targetPeriods === 0) {
65
- return false;
66
- }
67
- if (!(0, generalUtils_1.eligibleForNextAutomationPeriod)(client.solautoPositionActiveDca().automation)) {
55
+ if (!(0, generalUtils_1.eligibleForNextAutomationPeriod)(dca.automation, currentUnixTime)) {
68
56
  return false;
69
57
  }
70
58
  return true;
71
59
  }
72
- function getTargetRateAndDcaAmount(client, targetLiqUtilizationRateBps) {
60
+ function getTargetRateAndDcaAmount(state, settings, dca, currentUnixTime, targetLiqUtilizationRateBps) {
73
61
  if (targetLiqUtilizationRateBps !== undefined) {
74
62
  return {
75
63
  targetRateBps: targetLiqUtilizationRateBps,
76
64
  };
77
65
  }
78
- if (isDcaRebalance(client)) {
79
- const amountToDcaIn = getAdditionalAmountToDcaIn(client);
80
- const targetLiqUtilizationRateBps = targetLiqUtilizationRateBpsFromDCA(client);
66
+ if (settings === undefined) {
67
+ throw new Error("If rebalancing a self-managed position, settings, and DCA should be provided");
68
+ }
69
+ if (isDcaRebalance(state, settings, dca, currentUnixTime)) {
70
+ const amountToDcaIn = getAdditionalAmountToDcaIn(dca);
71
+ const targetLiqUtilizationRateBps = targetLiqUtilizationRateBpsFromDCA(state, settings, dca);
81
72
  return {
82
73
  targetRateBps: targetLiqUtilizationRateBps,
83
74
  amountToDcaIn,
@@ -85,33 +76,30 @@ function getTargetRateAndDcaAmount(client, targetLiqUtilizationRateBps) {
85
76
  }
86
77
  else {
87
78
  return {
88
- targetRateBps: getStandardTargetLiqUtilizationRateBps(client),
79
+ targetRateBps: getStandardTargetLiqUtilizationRateBps(state, settings),
89
80
  };
90
81
  }
91
82
  }
92
- function getRebalanceValues(client, targetLiqUtilizationRateBps, limitGapBps) {
93
- if (client.solautoPositionState === undefined ||
94
- client.solautoPositionState.lastUpdated <
83
+ function getRebalanceValues(state, settings, dca, feeType, currentUnixTime, supplyPrice, debtPrice, targetLiqUtilizationRateBps, limitGapBps) {
84
+ if (state === undefined ||
85
+ state.lastUpdated <
95
86
  BigInt(Math.round((0, generalUtils_2.currentUnixSeconds)() - solautoConstants_1.MIN_POSITION_STATE_FRESHNESS_SECS))) {
96
87
  throw new Error("Requires a fresh position state to get rebalance details");
97
88
  }
98
- const { targetRateBps, amountToDcaIn } = getTargetRateAndDcaAmount(client, targetLiqUtilizationRateBps);
99
- const amountUsdToDcaIn = (0, numberUtils_1.fromBaseUnit)(BigInt(Math.round(amountToDcaIn ?? 0)), client.solautoPositionState.debt.decimals) * solautoConstants_1.PRICES[client.debtMint.toString()].price;
100
- const increasingLeverage = amountUsdToDcaIn > 0 ||
101
- client.solautoPositionState.liqUtilizationRateBps < targetRateBps;
89
+ const { targetRateBps, amountToDcaIn } = getTargetRateAndDcaAmount(state, settings, dca, currentUnixTime, targetLiqUtilizationRateBps);
90
+ const amountUsdToDcaIn = (0, numberUtils_1.fromBaseUnit)(BigInt(Math.round(amountToDcaIn ?? 0)), state.debt.decimals) *
91
+ debtPrice;
92
+ const increasingLeverage = amountUsdToDcaIn > 0 || state.liqUtilizationRateBps < targetRateBps;
102
93
  let adjustmentFeeBps = 0;
103
94
  if (increasingLeverage) {
104
- adjustmentFeeBps = (0, generalUtils_1.getSolautoFeesBps)(client.referredByState !== undefined, client.solautoPositionData?.feeType ?? generated_1.FeeType.Small).total;
105
- }
106
- const supplyUsd = (0, numberUtils_1.fromBaseUnit)(client.solautoPositionState.supply.amountUsed.baseAmountUsdValue, generalAccounts_1.USD_DECIMALS) + amountUsdToDcaIn;
107
- const debtUsd = (0, numberUtils_1.fromBaseUnit)(client.solautoPositionState.debt.amountUsed.baseAmountUsdValue, generalAccounts_1.USD_DECIMALS);
108
- let debtAdjustmentUsd = (0, numberUtils_1.getDebtAdjustmentUsd)(client.solautoPositionState.liqThresholdBps, supplyUsd, debtUsd, targetRateBps, adjustmentFeeBps);
109
- const input = increasingLeverage
110
- ? client.solautoPositionState.debt
111
- : client.solautoPositionState.supply;
112
- const inputMarketPrice = increasingLeverage
113
- ? solautoConstants_1.PRICES[client.debtMint.toString()].price
114
- : solautoConstants_1.PRICES[client.supplyMint.toString()].price;
95
+ adjustmentFeeBps = (0, generalUtils_1.getSolautoFeesBps)(false, feeType).total;
96
+ }
97
+ const supplyUsd = (0, numberUtils_1.fromBaseUnit)(state.supply.amountUsed.baseAmountUsdValue, generalAccounts_1.USD_DECIMALS) +
98
+ amountUsdToDcaIn;
99
+ const debtUsd = (0, numberUtils_1.fromBaseUnit)(state.debt.amountUsed.baseAmountUsdValue, generalAccounts_1.USD_DECIMALS);
100
+ let debtAdjustmentUsd = (0, numberUtils_1.getDebtAdjustmentUsd)(state.liqThresholdBps, supplyUsd, debtUsd, targetRateBps, adjustmentFeeBps);
101
+ const input = increasingLeverage ? state.debt : state.supply;
102
+ const inputMarketPrice = increasingLeverage ? debtPrice : supplyPrice;
115
103
  const limitGap = limitGapBps
116
104
  ? (0, numberUtils_1.fromBps)(limitGapBps)
117
105
  : (0, numberUtils_1.fromBps)(solautoConstants_1.DEFAULT_LIMIT_GAP_BPS);
@@ -126,6 +114,7 @@ function getRebalanceValues(client, targetLiqUtilizationRateBps, limitGapBps) {
126
114
  return {
127
115
  increasingLeverage,
128
116
  debtAdjustmentUsd,
117
+ amountToDcaIn: amountToDcaIn ?? 0,
129
118
  amountUsdToDcaIn,
130
119
  };
131
120
  }
@@ -186,7 +175,7 @@ function getJupSwapRebalanceDetails(client, values, targetLiqUtilizationRateBps,
186
175
  inputMint: (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(input.mint),
187
176
  outputMint: (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(output.mint),
188
177
  destinationWallet: client.solautoPosition,
189
- slippageBpsIncFactor: 0.25 + ((attemptNum ?? 0) * 0.2),
178
+ slippageBpsIncFactor: 0.25 + (attemptNum ?? 0) * 0.2,
190
179
  amount: rebalancingToZero
191
180
  ? client.solautoPositionState.debt.amountUsed.baseUnit +
192
181
  BigInt(Math.round(Number(client.solautoPositionState.debt.amountUsed.baseUnit) *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haven-fi/solauto-sdk",
3
- "version": "1.0.59",
3
+ "version": "1.0.60",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "description": "Typescript SDK for the Solauto program on the Solana blockchain",
@@ -14,6 +14,7 @@ import {
14
14
  Account as SplTokenAccount,
15
15
  } from "@solana/spl-token";
16
16
  import {
17
+ FeeType,
17
18
  LendingPlatform,
18
19
  ReferralState,
19
20
  SOLAUTO_PROGRAM_ID,
@@ -56,6 +57,7 @@ import {
56
57
  getLendingAccountWithdrawInstructionDataSerializer,
57
58
  MARGINFI_PROGRAM_ID,
58
59
  } from "../marginfi-sdk";
60
+ import { PRICES } from "../constants";
59
61
 
60
62
  interface wSolTokenUsage {
61
63
  wSolTokenAccount: PublicKey;
@@ -548,7 +550,6 @@ export async function getTransactionChores(
548
550
  return [choresBefore, choresAfter];
549
551
  }
550
552
 
551
-
552
553
  export async function buildSolautoRebalanceTransaction(
553
554
  client: SolautoClient,
554
555
  targetLiqUtilizationRateBps?: number,
@@ -570,14 +571,23 @@ export async function buildSolautoRebalanceTransaction(
570
571
  client.solautoPositionData?.position.settingParams!,
571
572
  client.livePositionUpdates.activeDca ??
572
573
  client.solautoPositionData?.position.dca!,
573
- currentUnixSeconds()
574
+ currentUnixSeconds()
574
575
  ))
575
576
  ) {
576
577
  client.log("Not eligible for a rebalance");
577
578
  return undefined;
578
579
  }
579
580
 
580
- const values = getRebalanceValues(client, targetLiqUtilizationRateBps);
581
+ const values = getRebalanceValues(
582
+ client.solautoPositionState!,
583
+ client.solautoPositionSettings(),
584
+ client.solautoPositionActiveDca(),
585
+ client.solautoPositionData?.feeType ?? FeeType.Small,
586
+ currentUnixSeconds(),
587
+ PRICES[client.supplyMint.toString()].price,
588
+ PRICES[client.debtMint.toString()].price,
589
+ targetLiqUtilizationRateBps
590
+ );
581
591
  client.log("Rebalance values: ", values);
582
592
 
583
593
  const swapDetails = getJupSwapRebalanceDetails(
@@ -1,5 +1,5 @@
1
1
  import { PublicKey } from "@solana/web3.js";
2
- import { isOption, isSome, Umi } from "@metaplex-foundation/umi";
2
+ import { isOption, isSome, publicKey, Umi } from "@metaplex-foundation/umi";
3
3
  import {
4
4
  AutomationSettings,
5
5
  DCASettings,
@@ -54,9 +54,9 @@ export function nextAutomationPeriodTimestamp(
54
54
 
55
55
  export function eligibleForNextAutomationPeriod(
56
56
  automation: AutomationSettings,
57
- currentUnixSecs?: number
57
+ currentUnixTime: number
58
58
  ): boolean {
59
- return (currentUnixSecs ?? currentUnixSeconds()) >= nextAutomationPeriodTimestamp(automation);
59
+ return currentUnixTime >= nextAutomationPeriodTimestamp(automation);
60
60
  }
61
61
 
62
62
  export function getUpdatedValueFromAutomation(
@@ -79,16 +79,16 @@ export function getUpdatedValueFromAutomation(
79
79
 
80
80
  export function getAdjustedSettingsFromAutomation(
81
81
  settings: SolautoSettingsParameters,
82
- currentUnixSecs?: number
82
+ currentUnixTime: number
83
83
  ): SolautoSettingsParameters {
84
84
  const boostToBps =
85
85
  settings.automation.targetPeriods > 0 &&
86
- eligibleForNextAutomationPeriod(settings.automation, currentUnixSecs)
86
+ eligibleForNextAutomationPeriod(settings.automation, currentUnixTime)
87
87
  ? getUpdatedValueFromAutomation(
88
88
  settings.boostToBps,
89
89
  settings.targetBoostToBps,
90
90
  settings.automation,
91
- currentUnixSecs ?? currentUnixSeconds()
91
+ currentUnixTime
92
92
  )
93
93
  : settings.boostToBps;
94
94
 
@@ -161,10 +161,13 @@ export function eligibleForRebalance(
161
161
  export function eligibleForRefresh(
162
162
  positionState: PositionState,
163
163
  positionSettings: SolautoSettingsParameters,
164
- currentUnixSecs?: number
164
+ currentUnixTime: number
165
165
  ): boolean {
166
166
  if (positionSettings.automation.targetPeriods > 0) {
167
- return eligibleForNextAutomationPeriod(positionSettings.automation, currentUnixSecs);
167
+ return eligibleForNextAutomationPeriod(
168
+ positionSettings.automation,
169
+ currentUnixTime
170
+ );
168
171
  } else {
169
172
  return (
170
173
  currentUnixSeconds() - Number(positionState.lastUpdated) >
@@ -322,15 +325,32 @@ export async function getAllPositionsByAuthority(
322
325
  return allPositions;
323
326
  }
324
327
 
325
- export async function positionStateWithPrices(
326
- umi: Umi,
327
- state: PositionState,
328
- protocolAccount: PublicKey,
329
- lendingPlatform: LendingPlatform,
330
- supplyPrice?: number,
331
- debtPrice?: number
332
- ): Promise<PositionState | undefined> {
328
+ interface GetLatestStateProps {
329
+ state: PositionState;
330
+ umi?: Umi;
331
+ protocolAccount?: PublicKey;
332
+ lendingPlatform?: LendingPlatform;
333
+ supplyPrice?: number;
334
+ debtPrice?: number;
335
+ }
336
+
337
+ export async function positionStateWithPrices({
338
+ state,
339
+ supplyPrice,
340
+ debtPrice,
341
+ umi,
342
+ protocolAccount,
343
+ lendingPlatform,
344
+ }: GetLatestStateProps): Promise<PositionState | undefined> {
333
345
  if (currentUnixSeconds() - Number(state.lastUpdated) > 60 * 60 * 24 * 7) {
346
+ if (
347
+ umi === undefined ||
348
+ protocolAccount === undefined ||
349
+ lendingPlatform === undefined
350
+ ) {
351
+ throw new Error("Missing required parameters");
352
+ }
353
+
334
354
  if (lendingPlatform === LendingPlatform.Marginfi) {
335
355
  return await getMarginfiAccountPositionState(
336
356
  umi,
@@ -364,7 +384,10 @@ export async function positionStateWithPrices(
364
384
  state.liqThresholdBps
365
385
  ),
366
386
  netWorth: {
367
- ...state.netWorth,
387
+ baseUnit: toBaseUnit(
388
+ (supplyUsd - debtUsd) / supplyPrice,
389
+ state.supply.decimals
390
+ ),
368
391
  baseAmountUsdValue: toBaseUnit(supplyUsd - debtUsd, USD_DECIMALS),
369
392
  },
370
393
  supply: {
@@ -384,6 +407,82 @@ export async function positionStateWithPrices(
384
407
  };
385
408
  }
386
409
 
410
+ interface AssetProps {
411
+ amountUsedBaseUnit: bigint;
412
+ decimals: number;
413
+ price: number;
414
+ mint: PublicKey;
415
+ }
416
+
417
+ export function createFakePositionState(
418
+ supply: AssetProps,
419
+ debt: AssetProps,
420
+ maxLtvBps: number,
421
+ liqThresholdBps: number
422
+ ): PositionState {
423
+ const supplyUsd =
424
+ fromBaseUnit(supply.amountUsedBaseUnit, supply.decimals) * supply.price;
425
+ const debtUsd =
426
+ fromBaseUnit(debt.amountUsedBaseUnit, debt.decimals) * debt.price;
427
+
428
+ return {
429
+ liqUtilizationRateBps: getLiqUtilzationRateBps(
430
+ supplyUsd,
431
+ debtUsd,
432
+ liqThresholdBps
433
+ ),
434
+ supply: {
435
+ amountUsed: {
436
+ baseUnit: supply.amountUsedBaseUnit,
437
+ baseAmountUsdValue: toBaseUnit(supplyUsd, USD_DECIMALS),
438
+ },
439
+ amountCanBeUsed: {
440
+ baseUnit: toBaseUnit(1000000, supply.decimals),
441
+ baseAmountUsdValue: BigInt(Math.round(1000000 * supply.price)),
442
+ },
443
+ baseAmountMarketPriceUsd: toBaseUnit(supply.price, USD_DECIMALS),
444
+ borrowFeeBps: 0,
445
+ decimals: supply.decimals,
446
+ flashLoanFeeBps: 0,
447
+ mint: publicKey(supply.mint),
448
+ padding1: [],
449
+ padding2: [],
450
+ padding: new Uint8Array([]),
451
+ },
452
+ debt: {
453
+ amountUsed: {
454
+ baseUnit: debt.amountUsedBaseUnit,
455
+ baseAmountUsdValue: toBaseUnit(debtUsd, USD_DECIMALS),
456
+ },
457
+ amountCanBeUsed: {
458
+ baseUnit: toBaseUnit(1000000, debt.decimals),
459
+ baseAmountUsdValue: BigInt(Math.round(1000000 * debt.price)),
460
+ },
461
+ baseAmountMarketPriceUsd: toBaseUnit(debt.price, USD_DECIMALS),
462
+ borrowFeeBps: 0,
463
+ decimals: debt.decimals,
464
+ flashLoanFeeBps: 0,
465
+ mint: publicKey(debt.mint),
466
+ padding1: [],
467
+ padding2: [],
468
+ padding: new Uint8Array([]),
469
+ },
470
+ netWorth: {
471
+ baseUnit: toBaseUnit(
472
+ (supplyUsd - debtUsd) / supply.price,
473
+ supply.decimals
474
+ ),
475
+ baseAmountUsdValue: toBaseUnit(supplyUsd - debtUsd, USD_DECIMALS),
476
+ },
477
+ maxLtvBps,
478
+ liqThresholdBps,
479
+ lastUpdated: BigInt(currentUnixSeconds()),
480
+ padding1: [],
481
+ padding2: [],
482
+ padding: [],
483
+ };
484
+ }
485
+
387
486
  type PositionAdjustment =
388
487
  | { type: "supply"; value: bigint }
389
488
  | { type: "debt"; value: bigint }
@@ -1,6 +1,12 @@
1
1
  import { PublicKey } from "@solana/web3.js";
2
2
  import { SolautoClient } from "../../clients/solautoClient";
3
- import { FeeType, PositionTokenUsage } from "../../generated";
3
+ import {
4
+ DCASettings,
5
+ FeeType,
6
+ PositionState,
7
+ PositionTokenUsage,
8
+ SolautoSettingsParameters,
9
+ } from "../../generated";
4
10
  import {
5
11
  eligibleForNextAutomationPeriod,
6
12
  getAdjustedSettingsFromAutomation,
@@ -26,15 +32,12 @@ import {
26
32
  PRICES,
27
33
  } from "../../constants/solautoConstants";
28
34
 
29
- function getAdditionalAmountToDcaIn(client: SolautoClient): number {
30
- const dca = client.solautoPositionActiveDca()!;
35
+ function getAdditionalAmountToDcaIn(dca: DCASettings): number {
31
36
  if (dca.debtToAddBaseUnit === BigInt(0)) {
32
37
  return 0;
33
38
  }
34
39
 
35
- const debtBalance =
36
- Number(client.solautoPositionData?.position.dca.debtToAddBaseUnit ?? 0) +
37
- Number(client.livePositionUpdates.debtTaBalanceAdjustment ?? 0);
40
+ const debtBalance = Number(dca.debtToAddBaseUnit);
38
41
  const updatedDebtBalance = getUpdatedValueFromAutomation(
39
42
  debtBalance,
40
43
  0,
@@ -45,44 +48,44 @@ function getAdditionalAmountToDcaIn(client: SolautoClient): number {
45
48
  return debtBalance - updatedDebtBalance;
46
49
  }
47
50
 
48
- function getStandardTargetLiqUtilizationRateBps(client: SolautoClient): number {
49
- if (!client.selfManaged) {
50
- const adjustedSettings = getAdjustedSettingsFromAutomation(
51
- client.solautoPositionSettings()!,
52
- currentUnixSeconds()
53
- );
51
+ function getStandardTargetLiqUtilizationRateBps(
52
+ state: PositionState,
53
+ settings: SolautoSettingsParameters
54
+ ): number {
55
+ const adjustedSettings = getAdjustedSettingsFromAutomation(
56
+ settings,
57
+ currentUnixSeconds()
58
+ );
59
+
60
+ const repayFrom = adjustedSettings.repayToBps - adjustedSettings.repayGap;
61
+ const boostFrom = adjustedSettings.boostToBps + adjustedSettings.boostGap;
54
62
 
55
- const repayFrom = adjustedSettings.repayToBps - adjustedSettings.repayGap;
56
- const boostFrom = adjustedSettings.boostToBps + adjustedSettings.boostGap;
57
-
58
- if (client.solautoPositionState!.liqUtilizationRateBps < boostFrom) {
59
- return adjustedSettings.boostToBps;
60
- } else if (
61
- client.solautoPositionState!.liqUtilizationRateBps > repayFrom ||
62
- repayFrom - client.solautoPositionState!.liqUtilizationRateBps <
63
- repayFrom * 0.015
64
- ) {
65
- return adjustedSettings.repayToBps;
66
- } else {
67
- throw new Error("Invalid rebalance condition");
68
- }
63
+ if (state.liqUtilizationRateBps < boostFrom) {
64
+ return adjustedSettings.boostToBps;
65
+ } else if (
66
+ state.liqUtilizationRateBps > repayFrom ||
67
+ repayFrom - state.liqUtilizationRateBps < repayFrom * 0.015
68
+ ) {
69
+ return adjustedSettings.repayToBps;
69
70
  } else {
70
- throw new Error(
71
- "This is a self-managed position, a targetLiqUtilizationRateBps must be provided initiate a rebalance"
72
- );
71
+ throw new Error("Invalid rebalance condition");
73
72
  }
74
73
  }
75
74
 
76
- function targetLiqUtilizationRateBpsFromDCA(client: SolautoClient) {
75
+ function targetLiqUtilizationRateBpsFromDCA(
76
+ state: PositionState,
77
+ settings: SolautoSettingsParameters,
78
+ dca: DCASettings
79
+ ) {
77
80
  const adjustedSettings = getAdjustedSettingsFromAutomation(
78
- client.solautoPositionSettings()!,
81
+ settings,
79
82
  currentUnixSeconds()
80
83
  );
81
84
 
82
85
  let targetRateBps = 0;
83
- if (client.solautoPositionActiveDca()!.debtToAddBaseUnit > BigInt(0)) {
86
+ if (dca.debtToAddBaseUnit > BigInt(0)) {
84
87
  targetRateBps = Math.max(
85
- client.solautoPositionState!.liqUtilizationRateBps,
88
+ state.liqUtilizationRateBps,
86
89
  adjustedSettings.boostToBps
87
90
  );
88
91
  } else {
@@ -91,32 +94,29 @@ function targetLiqUtilizationRateBpsFromDCA(client: SolautoClient) {
91
94
  return targetRateBps;
92
95
  }
93
96
 
94
- function isDcaRebalance(client: SolautoClient): boolean {
95
- if (client.solautoPositionActiveDca() === undefined || client.selfManaged) {
97
+ function isDcaRebalance(
98
+ state: PositionState,
99
+ settings: SolautoSettingsParameters,
100
+ dca: DCASettings | undefined,
101
+ currentUnixTime: number
102
+ ): boolean {
103
+ if (dca === undefined || dca.automation.targetPeriods === 0) {
96
104
  return false;
97
105
  }
98
106
 
99
107
  const adjustedSettings = getAdjustedSettingsFromAutomation(
100
- client.solautoPositionSettings()!,
108
+ settings,
101
109
  currentUnixSeconds()
102
110
  );
103
111
 
104
112
  if (
105
- client.solautoPositionState!.liqUtilizationRateBps >
113
+ state.liqUtilizationRateBps >
106
114
  adjustedSettings.repayToBps + adjustedSettings.repayGap
107
115
  ) {
108
116
  return false;
109
117
  }
110
118
 
111
- if (client.solautoPositionActiveDca()!.automation.targetPeriods === 0) {
112
- return false;
113
- }
114
-
115
- if (
116
- !eligibleForNextAutomationPeriod(
117
- client.solautoPositionActiveDca()!.automation
118
- )
119
- ) {
119
+ if (!eligibleForNextAutomationPeriod(dca.automation, currentUnixTime)) {
120
120
  return false;
121
121
  }
122
122
 
@@ -124,7 +124,10 @@ function isDcaRebalance(client: SolautoClient): boolean {
124
124
  }
125
125
 
126
126
  function getTargetRateAndDcaAmount(
127
- client: SolautoClient,
127
+ state: PositionState,
128
+ settings: SolautoSettingsParameters | undefined,
129
+ dca: DCASettings | undefined,
130
+ currentUnixTime: number,
128
131
  targetLiqUtilizationRateBps?: number
129
132
  ): { targetRateBps: number; amountToDcaIn?: number } {
130
133
  if (targetLiqUtilizationRateBps !== undefined) {
@@ -133,10 +136,19 @@ function getTargetRateAndDcaAmount(
133
136
  };
134
137
  }
135
138
 
136
- if (isDcaRebalance(client)) {
137
- const amountToDcaIn = getAdditionalAmountToDcaIn(client);
138
- const targetLiqUtilizationRateBps =
139
- targetLiqUtilizationRateBpsFromDCA(client);
139
+ if (settings === undefined) {
140
+ throw new Error(
141
+ "If rebalancing a self-managed position, settings, and DCA should be provided"
142
+ );
143
+ }
144
+
145
+ if (isDcaRebalance(state, settings, dca, currentUnixTime)) {
146
+ const amountToDcaIn = getAdditionalAmountToDcaIn(dca!);
147
+ const targetLiqUtilizationRateBps = targetLiqUtilizationRateBpsFromDCA(
148
+ state,
149
+ settings,
150
+ dca!
151
+ );
140
152
 
141
153
  return {
142
154
  targetRateBps: targetLiqUtilizationRateBps,
@@ -144,7 +156,7 @@ function getTargetRateAndDcaAmount(
144
156
  };
145
157
  } else {
146
158
  return {
147
- targetRateBps: getStandardTargetLiqUtilizationRateBps(client),
159
+ targetRateBps: getStandardTargetLiqUtilizationRateBps(state, settings),
148
160
  };
149
161
  }
150
162
  }
@@ -152,17 +164,24 @@ function getTargetRateAndDcaAmount(
152
164
  export interface RebalanceValues {
153
165
  increasingLeverage: boolean;
154
166
  debtAdjustmentUsd: number;
167
+ amountToDcaIn: number;
155
168
  amountUsdToDcaIn: number;
156
169
  }
157
170
 
158
171
  export function getRebalanceValues(
159
- client: SolautoClient,
172
+ state: PositionState,
173
+ settings: SolautoSettingsParameters | undefined,
174
+ dca: DCASettings | undefined,
175
+ feeType: FeeType,
176
+ currentUnixTime: number,
177
+ supplyPrice: number,
178
+ debtPrice: number,
160
179
  targetLiqUtilizationRateBps?: number,
161
180
  limitGapBps?: number
162
181
  ): RebalanceValues {
163
182
  if (
164
- client.solautoPositionState === undefined ||
165
- client.solautoPositionState.lastUpdated <
183
+ state === undefined ||
184
+ state.lastUpdated <
166
185
  BigInt(
167
186
  Math.round(currentUnixSeconds() - MIN_POSITION_STATE_FRESHNESS_SECS)
168
187
  )
@@ -171,50 +190,41 @@ export function getRebalanceValues(
171
190
  }
172
191
 
173
192
  const { targetRateBps, amountToDcaIn } = getTargetRateAndDcaAmount(
174
- client,
193
+ state,
194
+ settings,
195
+ dca,
196
+ currentUnixTime,
175
197
  targetLiqUtilizationRateBps
176
198
  );
177
199
 
178
200
  const amountUsdToDcaIn =
179
- fromBaseUnit(
180
- BigInt(Math.round(amountToDcaIn ?? 0)),
181
- client.solautoPositionState!.debt.decimals
182
- ) * PRICES[client.debtMint.toString()].price;
201
+ fromBaseUnit(BigInt(Math.round(amountToDcaIn ?? 0)), state.debt.decimals) *
202
+ debtPrice;
183
203
 
184
204
  const increasingLeverage =
185
- amountUsdToDcaIn > 0 ||
186
- client.solautoPositionState!.liqUtilizationRateBps < targetRateBps;
205
+ amountUsdToDcaIn > 0 || state.liqUtilizationRateBps < targetRateBps;
187
206
  let adjustmentFeeBps = 0;
188
207
  if (increasingLeverage) {
189
- adjustmentFeeBps = getSolautoFeesBps(
190
- client.referredByState !== undefined,
191
- client.solautoPositionData?.feeType ?? FeeType.Small
192
- ).total;
208
+ adjustmentFeeBps = getSolautoFeesBps(false, feeType).total;
193
209
  }
194
210
 
195
211
  const supplyUsd =
196
- fromBaseUnit(
197
- client.solautoPositionState!.supply.amountUsed.baseAmountUsdValue,
198
- USD_DECIMALS
199
- ) + amountUsdToDcaIn;
212
+ fromBaseUnit(state.supply.amountUsed.baseAmountUsdValue, USD_DECIMALS) +
213
+ amountUsdToDcaIn;
200
214
  const debtUsd = fromBaseUnit(
201
- client.solautoPositionState!.debt.amountUsed.baseAmountUsdValue,
215
+ state.debt.amountUsed.baseAmountUsdValue,
202
216
  USD_DECIMALS
203
217
  );
204
218
  let debtAdjustmentUsd = getDebtAdjustmentUsd(
205
- client.solautoPositionState!.liqThresholdBps,
219
+ state.liqThresholdBps,
206
220
  supplyUsd,
207
221
  debtUsd,
208
222
  targetRateBps,
209
223
  adjustmentFeeBps
210
224
  );
211
225
 
212
- const input = increasingLeverage
213
- ? client.solautoPositionState!.debt
214
- : client.solautoPositionState!.supply;
215
- const inputMarketPrice = increasingLeverage
216
- ? PRICES[client.debtMint.toString()].price
217
- : PRICES[client.supplyMint.toString()].price;
226
+ const input = increasingLeverage ? state.debt : state.supply;
227
+ const inputMarketPrice = increasingLeverage ? debtPrice : supplyPrice;
218
228
 
219
229
  const limitGap = limitGapBps
220
230
  ? fromBps(limitGapBps)
@@ -235,6 +245,7 @@ export function getRebalanceValues(
235
245
  return {
236
246
  increasingLeverage,
237
247
  debtAdjustmentUsd,
248
+ amountToDcaIn: amountToDcaIn ?? 0,
238
249
  amountUsdToDcaIn,
239
250
  };
240
251
  }
@@ -269,7 +280,7 @@ export function getFlashLoanDetails(
269
280
  values.debtAdjustmentUsd > 0
270
281
  ? debtUsd + debtAdjustmentWithSlippage
271
282
  : debtUsd;
272
-
283
+
273
284
  const tempLiqUtilizationRateBps = getLiqUtilzationRateBps(
274
285
  supplyUsd,
275
286
  debtUsd,
@@ -342,7 +353,7 @@ export function getJupSwapRebalanceDetails(
342
353
  inputMint: toWeb3JsPublicKey(input.mint),
343
354
  outputMint: toWeb3JsPublicKey(output.mint),
344
355
  destinationWallet: client.solautoPosition,
345
- slippageBpsIncFactor: 0.25 + ((attemptNum ?? 0) * 0.2),
356
+ slippageBpsIncFactor: 0.25 + (attemptNum ?? 0) * 0.2,
346
357
  amount: rebalancingToZero
347
358
  ? client.solautoPositionState!.debt.amountUsed.baseUnit +
348
359
  BigInt(
package/tests/shared.ts CHANGED
@@ -1,14 +1,17 @@
1
1
  import { Signer, createSignerFromKeypair } from "@metaplex-foundation/umi";
2
- import { Connection, clusterApiUrl } from "@solana/web3.js";
2
+ import { Connection, Keypair, clusterApiUrl } from "@solana/web3.js";
3
3
  import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
4
4
  import { getSecretKey } from "../local/shared";
5
+ import { fromWeb3JsKeypair } from "@metaplex-foundation/umi-web3js-adapters";
5
6
 
6
- export function setupTest(keypairFilename?: string): Signer {
7
+ export function setupTest(keypairFilename?: string, random?: boolean): Signer {
7
8
  const umi = createUmi(
8
9
  new Connection(clusterApiUrl("mainnet-beta"), "confirmed")
9
10
  );
10
11
  const secretKey = getSecretKey(keypairFilename);
11
- const signerKeypair = umi.eddsa.createKeypairFromSecretKey(secretKey);
12
+ const signerKeypair = random
13
+ ? fromWeb3JsKeypair(Keypair.generate())
14
+ : umi.eddsa.createKeypairFromSecretKey(secretKey);
12
15
  const signer = createSignerFromKeypair(umi, signerKeypair);
13
16
 
14
17
  return signer;
@@ -4,7 +4,6 @@ import { NATIVE_MINT } from "@solana/spl-token";
4
4
  import { assert } from "chai";
5
5
  import { SolautoMarginfiClient } from "../../src/clients/solautoMarginfiClient";
6
6
  import { setupTest } from "../shared";
7
- import { MARGINFI_ACCOUNTS } from "../../src/constants/marginfiAccounts";
8
7
  import { getRebalanceValues } from "../../src/utils/solauto/rebalanceUtils";
9
8
  import { publicKey } from "@metaplex-foundation/umi";
10
9
  import { SolautoClient } from "../../src/clients/solautoClient";
@@ -23,18 +22,21 @@ import {
23
22
  } from "../../src/utils/numberUtils";
24
23
  import { USD_DECIMALS } from "../../src/constants/generalAccounts";
25
24
  import {
25
+ createFakePositionState,
26
26
  eligibleForNextAutomationPeriod,
27
27
  getAdjustedSettingsFromAutomation,
28
28
  getSolautoFeesBps,
29
29
  getUpdatedValueFromAutomation,
30
+ positionStateWithPrices,
30
31
  } from "../../src/utils/solauto/generalUtils";
31
32
  import {
32
33
  currentUnixSeconds,
33
34
  getTokenPrices,
34
35
  } from "../../src/utils/generalUtils";
35
36
  import { USDC_MINT } from "../../src/constants/tokenConstants";
37
+ import { PRICES } from "../../src/constants";
36
38
 
37
- const signer = setupTest();
39
+ const signer = setupTest(undefined, true);
38
40
 
39
41
  function assertAccurateRebalance(
40
42
  client: SolautoClient,
@@ -43,7 +45,16 @@ function assertAccurateRebalance(
43
45
  expectedUsdToDcaIn?: number
44
46
  ) {
45
47
  const { increasingLeverage, debtAdjustmentUsd, amountUsdToDcaIn } =
46
- getRebalanceValues(client, targetLiqUtilizationRateBps);
48
+ getRebalanceValues(
49
+ client.solautoPositionState!,
50
+ client.solautoPositionSettings(),
51
+ client.solautoPositionActiveDca(),
52
+ client.solautoPositionData?.feeType ?? FeeType.Small,
53
+ currentUnixSeconds(),
54
+ PRICES[client.supplyMint.toString()].price,
55
+ PRICES[client.debtMint.toString()].price,
56
+ targetLiqUtilizationRateBps
57
+ );
47
58
 
48
59
  let adjustmentFeeBps = 0;
49
60
  if (increasingLeverage) {
@@ -55,7 +66,9 @@ function assertAccurateRebalance(
55
66
 
56
67
  assert(
57
68
  Math.round(amountUsdToDcaIn) === Math.round(expectedUsdToDcaIn ?? 0),
58
- `Expected DCA-in amount does not match ${Math.round(amountUsdToDcaIn)}, ${Math.round(expectedUsdToDcaIn ?? 0)}`
69
+ `Expected DCA-in amount does not match ${Math.round(
70
+ amountUsdToDcaIn
71
+ )}, ${Math.round(expectedUsdToDcaIn ?? 0)}`
59
72
  );
60
73
 
61
74
  const newSupply =
@@ -77,8 +90,9 @@ function assertAccurateRebalance(
77
90
  client.solautoPositionState!.liqThresholdBps
78
91
  );
79
92
  assert(
80
- Math.round(newLiqUtilizationRateBps) === expectedLiqUtilizationRateBps,
81
- `Expected liq utilization rate does not match ${Math.round(newLiqUtilizationRateBps)}, ${expectedLiqUtilizationRateBps}`
93
+ Math.round(newLiqUtilizationRateBps) ===
94
+ Math.round(expectedLiqUtilizationRateBps),
95
+ `Expected liq utilization rate does not match ${newLiqUtilizationRateBps}, ${expectedLiqUtilizationRateBps}`
82
96
  );
83
97
  }
84
98
 
@@ -97,10 +111,37 @@ async function getFakePosition(
97
111
  positionId: 1,
98
112
  signer,
99
113
  supplyMint: new PublicKey(NATIVE_MINT),
100
- debtMint: new PublicKey(MARGINFI_ACCOUNTS.USDC.mint),
114
+ debtMint: new PublicKey(USDC_MINT),
115
+ });
116
+
117
+ const supplyUsd = 1000;
118
+ const maxLtvBps = 6400;
119
+ const liqThresholdBps = 8181;
120
+ client.solautoPositionState = await positionStateWithPrices({
121
+ state: createFakePositionState(
122
+ {
123
+ amountUsedBaseUnit: toBaseUnit(supplyUsd / supplyPrice, 9),
124
+ decimals: 9,
125
+ price: PRICES[NATIVE_MINT.toString()].price,
126
+ mint: NATIVE_MINT,
127
+ },
128
+ {
129
+ amountUsedBaseUnit: toBaseUnit(
130
+ (supplyUsd *
131
+ fromBps(liqThresholdBps) *
132
+ fromBps(fakeLiqUtilizationRateBps)) /
133
+ debtPrice,
134
+ 6
135
+ ),
136
+ decimals: 6,
137
+ price: 1,
138
+ mint: new PublicKey(USDC_MINT),
139
+ },
140
+ maxLtvBps,
141
+ liqThresholdBps
142
+ ),
101
143
  });
102
144
 
103
- const state = await client.getFreshPositionState();
104
145
  client.solautoPositionData = {
105
146
  positionId: [1],
106
147
  bump: [0],
@@ -129,7 +170,7 @@ async function getFakePosition(
129
170
  padding1: [],
130
171
  padding: [],
131
172
  },
132
- state: state!,
173
+ state: client.solautoPositionState!,
133
174
  rebalance: {
134
175
  rebalanceType: SolautoRebalanceType.Regular,
135
176
  targetLiqUtilizationRateBps: 0,
@@ -139,7 +180,7 @@ async function getFakePosition(
139
180
  padding2: [],
140
181
  padding: new Uint8Array([]),
141
182
  },
142
- feeType: FeeType.Small,
183
+ feeType: FeeType.Default,
143
184
  padding1: [],
144
185
  padding2: [],
145
186
  padding: [],
@@ -155,25 +196,14 @@ async function getFakePosition(
155
196
  },
156
197
  };
157
198
 
158
- const supplyUsd = 1000;
159
- client.livePositionUpdates.new({
160
- type: "supply",
161
- value: toBaseUnit(supplyUsd / supplyPrice, state!.supply.decimals),
162
- });
163
- client.livePositionUpdates.new({
164
- type: "debt",
165
- value: toBaseUnit(
166
- (supplyUsd *
167
- fromBps(state!.liqThresholdBps) *
168
- fromBps(fakeLiqUtilizationRateBps)) /
169
- debtPrice,
170
- state!.debt.decimals
171
- ),
172
- });
173
-
174
- client.solautoPositionState = await client.getFreshPositionState();
175
199
  client.solautoPositionState!.lastUpdated = BigInt(currentUnixSeconds());
176
200
 
201
+ assert(
202
+ fakeLiqUtilizationRateBps ===
203
+ client.solautoPositionState!.liqUtilizationRateBps,
204
+ "Fake position not set up correctly"
205
+ );
206
+
177
207
  return client;
178
208
  }
179
209
 
@@ -227,7 +257,8 @@ async function dcaRebalanceFromFakePosition(
227
257
  : adjustedSettings.boostToBps;
228
258
 
229
259
  const expectedDcaInAmount =
230
- dca.debtToAddBaseUnit > 0 && eligibleForNextAutomationPeriod(dca.automation)
260
+ dca.debtToAddBaseUnit > 0 &&
261
+ eligibleForNextAutomationPeriod(dca.automation, currentUnixSeconds())
231
262
  ? dca.debtToAddBaseUnit -
232
263
  BigInt(
233
264
  Math.round(
@@ -265,23 +296,23 @@ describe("Rebalance tests", async () => {
265
296
  });
266
297
 
267
298
  it("Standard rebalance with target rate", async () => {
268
- const client = new SolautoMarginfiClient(
269
- process.env.HELIUS_API_KEY ?? "",
270
- true
271
- );
272
- await client.initialize({
273
- positionId: 1,
274
- signer,
275
- supplyMint: new PublicKey(NATIVE_MINT),
276
- debtMint: new PublicKey(MARGINFI_ACCOUNTS.USDC.mint),
277
- });
278
-
279
- client.livePositionUpdates.new({
280
- type: "supply",
281
- value: BigInt(10000000000),
299
+ const client = await getFakePosition(supplyPrice, debtPrice, 3450, {
300
+ boostToBps: 500,
301
+ boostGap: 100,
302
+ repayToBps: 7000,
303
+ repayGap: 250,
304
+ automation: {
305
+ targetPeriods: 0,
306
+ periodsPassed: 0,
307
+ unixStartDate: BigInt(0),
308
+ intervalSeconds: BigInt(0),
309
+ padding1: [],
310
+ padding: new Uint8Array([]),
311
+ },
312
+ targetBoostToBps: 0,
313
+ padding1: [],
314
+ padding: new Uint8Array([]),
282
315
  });
283
- client.solautoPositionState = await client.getFreshPositionState();
284
- client.solautoPositionState!.lastUpdated = BigInt(currentUnixSeconds());
285
316
 
286
317
  assertAccurateRebalance(client, 5000, 5000);
287
318
  assertAccurateRebalance(client, 1000, 1000);
@@ -393,14 +424,14 @@ describe("Rebalance tests", async () => {
393
424
  it("Rebalance DCA in", async () => {
394
425
  const settings: SolautoSettingsParameters = {
395
426
  automation: {
396
- targetPeriods: 4,
427
+ targetPeriods: 3,
397
428
  periodsPassed: 0,
398
429
  intervalSeconds: BigInt(5),
399
430
  unixStartDate: BigInt(currentUnixSeconds()),
400
431
  padding1: [],
401
432
  padding: new Uint8Array([]),
402
433
  },
403
- targetBoostToBps: 0,
434
+ targetBoostToBps: 5000,
404
435
  boostGap: 1000,
405
436
  boostToBps: 4000,
406
437
  repayGap: 1000,