@haven-fi/solauto-sdk 1.0.127 → 1.0.129

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.
@@ -12,7 +12,6 @@ const generalUtils_1 = require("../utils/generalUtils");
12
12
  const marginfi_sdk_1 = require("../marginfi-sdk");
13
13
  const marginfiUtils_1 = require("../utils/marginfiUtils");
14
14
  const numberUtils_1 = require("../utils/numberUtils");
15
- const constants_1 = require("../constants");
16
15
  const utils_1 = require("../utils");
17
16
  class SolautoMarginfiClient extends solautoClient_1.SolautoClient {
18
17
  constructor() {
@@ -418,8 +417,8 @@ class SolautoMarginfiClient extends solautoClient_1.SolautoClient {
418
417
  const freshState = await (0, marginfiUtils_1.getMarginfiAccountPositionState)(this.umi, this.marginfiAccountPk, this.supplyMint, this.debtMint, this.livePositionUpdates);
419
418
  if (freshState) {
420
419
  this.log("Fresh state", freshState);
421
- const supplyPrice = constants_1.PRICES[(freshState?.supply.mint ?? web3_js_1.PublicKey.default).toString()].price;
422
- const debtPrice = constants_1.PRICES[(freshState?.debt.mint ?? web3_js_1.PublicKey.default).toString()].price;
420
+ const supplyPrice = (0, generalUtils_1.safeGetPrice)(freshState?.supply.mint);
421
+ const debtPrice = (0, generalUtils_1.safeGetPrice)(freshState?.debt.mint);
423
422
  this.log("Supply price: ", supplyPrice);
424
423
  this.log("Debt price: ", debtPrice);
425
424
  this.log("Liq threshold bps:", freshState.liqThresholdBps);
@@ -1 +1 @@
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;AAElC,OAAO,EAAE,SAAS,EAA8B,MAAM,iBAAiB,CAAC;AAKxE,OAAO,EAEL,aAAa,EASd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA6MzD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,EAAE,EAAE,kBAAkB,EACtB,sBAAsB,EAAE,MAAM,EAAE,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CA+G7B;AAmLD,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,CA4HA;AAED,wBAAsB,gCAAgC,CACpD,GAAG,EAAE,GAAG,EACR,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,SAAS,GACtB,OAAO,CAAC,CAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,CAmCrD"}
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;AAElC,OAAO,EAAE,SAAS,EAA8B,MAAM,iBAAiB,CAAC;AAKxE,OAAO,EAEL,aAAa,EASd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA8MzD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,EAAE,EAAE,kBAAkB,EACtB,sBAAsB,EAAE,MAAM,EAAE,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CA+G7B;AAmLD,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,CA4HA;AAED,wBAAsB,gCAAgC,CACpD,GAAG,EAAE,GAAG,EACR,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,SAAS,GACtB,OAAO,CAAC,CAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,CAmCrD"}
@@ -17,7 +17,6 @@ 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");
21
20
  function getWSolUsage(client, solautoActions, initiatingDcaIn, cancellingDcaIn) {
22
21
  const supplyIsWsol = client.supplyMint.equals(spl_token_1.NATIVE_MINT);
23
22
  const debtIsWsol = client.debtMint.equals(spl_token_1.NATIVE_MINT);
@@ -331,7 +330,7 @@ async function buildSolautoRebalanceTransaction(client, targetLiqUtilizationRate
331
330
  client.log("Not eligible for a rebalance");
332
331
  return undefined;
333
332
  }
334
- const values = (0, rebalanceUtils_1.getRebalanceValues)(client.solautoPositionState, client.solautoPositionSettings(), client.solautoPositionActiveDca(), (0, generalUtils_1.currentUnixSeconds)(), constants_1.PRICES[client.supplyMint.toString()].price, constants_1.PRICES[client.debtMint.toString()].price, targetLiqUtilizationRateBps);
333
+ const values = (0, rebalanceUtils_1.getRebalanceValues)(client.solautoPositionState, client.solautoPositionSettings(), client.solautoPositionActiveDca(), (0, generalUtils_1.currentUnixSeconds)(), (0, generalUtils_1.safeGetPrice)(client.supplyMint), (0, generalUtils_1.safeGetPrice)(client.debtMint), targetLiqUtilizationRateBps);
335
334
  client.log("Rebalance values: ", values);
336
335
  const swapDetails = (0, rebalanceUtils_1.getJupSwapRebalanceDetails)(client, values, targetLiqUtilizationRateBps, attemptNum);
337
336
  const { jupQuote, lookupTableAddresses, setupInstructions, tokenLedgerIx, swapIx, } = await (0, jupiterUtils_1.getJupSwapTransaction)(client.signer, swapDetails, attemptNum);
@@ -211,13 +211,13 @@ class TransactionsManager {
211
211
  choresBefore.prepend(updateLookupTable.updateLutTx);
212
212
  }
213
213
  if (choresBefore.getInstructions().length > 0) {
214
- const chore = new TransactionItem(async () => ({ tx: choresBefore }), "create account(s)");
214
+ const chore = new TransactionItem(async () => ({ tx: choresBefore }));
215
215
  await chore.initialize();
216
216
  items.unshift(chore);
217
217
  this.txHandler.log("Chores before: ", choresBefore.getInstructions().length);
218
218
  }
219
219
  if (choresAfter.getInstructions().length > 0) {
220
- const chore = new TransactionItem(async () => ({ tx: choresAfter }));
220
+ const chore = new TransactionItem(async () => ({ tx: choresAfter }), "closing temp accounts");
221
221
  await chore.initialize();
222
222
  items.push(chore);
223
223
  this.txHandler.log("Chores after: ", choresAfter.getInstructions().length);
@@ -1,12 +1,13 @@
1
1
  import { PublicKey } from "@solana/web3.js";
2
- import { MaybeRpcAccount, Umi } from "@metaplex-foundation/umi";
2
+ import { MaybeRpcAccount, Umi, PublicKey as UmiPublicKey } from "@metaplex-foundation/umi";
3
3
  export declare function generateRandomU8(): number;
4
4
  export declare function generateRandomU64(): bigint;
5
5
  export declare function currentUnixSeconds(): number;
6
6
  export declare function getSolanaAccountCreated(umi: Umi, pk: PublicKey): Promise<boolean>;
7
7
  export declare function rpcAccountCreated(account: MaybeRpcAccount): boolean;
8
8
  export declare function arraysAreEqual(arrayA: number[], arrayB: number[]): boolean;
9
- export declare function getTokenPrices(mints: PublicKey[]): Promise<number[]>;
9
+ export declare function fetchTokenPrices(mints: PublicKey[]): Promise<number[]>;
10
+ export declare function safeGetPrice(mint: PublicKey | UmiPublicKey): number | undefined;
10
11
  export type ErrorsToThrow = Array<new (...args: any[]) => Error>;
11
12
  export declare function retryWithExponentialBackoff<T>(fn: (attemptNum: number) => Promise<T>, retries?: number, delay?: number, errorsToThrow?: ErrorsToThrow): Promise<T>;
12
13
  //# sourceMappingURL=generalUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generalUtils.d.ts","sourceRoot":"","sources":["../../src/utils/generalUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAa,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAK3E,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAO1C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,GAAG,EACR,EAAE,EAAE,SAAS,GACZ,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAEnE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAU1E;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA+C1E;AAED,MAAM,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,KAAK,CAAC,CAAC;AAEjE,wBAAgB,2BAA2B,CAAC,CAAC,EAC3C,EAAE,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,OAAO,GAAE,MAAU,EACnB,KAAK,GAAE,MAAY,EACnB,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,CAAC,CAAC,CA8BZ"}
1
+ {"version":3,"file":"generalUtils.d.ts","sourceRoot":"","sources":["../../src/utils/generalUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAa,GAAG,EAAE,SAAS,IAAI,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKtG,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAO1C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,GAAG,EACR,EAAE,EAAE,SAAS,GACZ,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAEnE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAU1E;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA+C5E;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,YAAY,GAAG,MAAM,GAAG,SAAS,CAK/E;AAED,MAAM,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,KAAK,CAAC,CAAC;AAEjE,wBAAgB,2BAA2B,CAAC,CAAC,EAC3C,EAAE,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,OAAO,GAAE,MAAU,EACnB,KAAK,GAAE,MAAY,EACnB,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,CAAC,CAAC,CA8BZ"}
@@ -6,7 +6,8 @@ exports.currentUnixSeconds = currentUnixSeconds;
6
6
  exports.getSolanaAccountCreated = getSolanaAccountCreated;
7
7
  exports.rpcAccountCreated = rpcAccountCreated;
8
8
  exports.arraysAreEqual = arraysAreEqual;
9
- exports.getTokenPrices = getTokenPrices;
9
+ exports.fetchTokenPrices = fetchTokenPrices;
10
+ exports.safeGetPrice = safeGetPrice;
10
11
  exports.retryWithExponentialBackoff = retryWithExponentialBackoff;
11
12
  const umi_1 = require("@metaplex-foundation/umi");
12
13
  const pythConstants_1 = require("../constants/pythConstants");
@@ -44,7 +45,7 @@ function arraysAreEqual(arrayA, arrayB) {
44
45
  }
45
46
  return true;
46
47
  }
47
- async function getTokenPrices(mints) {
48
+ async function fetchTokenPrices(mints) {
48
49
  const currentTime = currentUnixSeconds();
49
50
  if (!mints.some((mint) => !(mint.toString() in solautoConstants_1.PRICES) ||
50
51
  currentTime - solautoConstants_1.PRICES[mint.toString()].time > 3)) {
@@ -79,6 +80,12 @@ async function getTokenPrices(mints) {
79
80
  }
80
81
  return prices;
81
82
  }
83
+ function safeGetPrice(mint) {
84
+ if (mint.toString() in solautoConstants_1.PRICES) {
85
+ return solautoConstants_1.PRICES[mint.toString()].price;
86
+ }
87
+ return undefined;
88
+ }
82
89
  function retryWithExponentialBackoff(fn, retries = 5, delay = 150, errorsToThrow) {
83
90
  return new Promise((resolve, reject) => {
84
91
  const attempt = (attemptNum) => {
@@ -11,7 +11,6 @@ const umi_web3js_adapters_1 = require("@metaplex-foundation/umi-web3js-adapters"
11
11
  const marginfi_sdk_1 = require("../marginfi-sdk");
12
12
  const generalUtils_1 = require("./generalUtils");
13
13
  const numberUtils_1 = require("./numberUtils");
14
- const solautoConstants_1 = require("../constants/solautoConstants");
15
14
  const marginfiAccounts_1 = require("../constants/marginfiAccounts");
16
15
  const generalAccounts_1 = require("../constants/generalAccounts");
17
16
  const solanaUtils_1 = require("./solanaUtils");
@@ -36,7 +35,7 @@ async function getMaxLtvAndLiqThreshold(umi, supply, debt, supplyPrice) {
36
35
  debt.bank = await (0, marginfi_sdk_1.safeFetchBank)(umi, (0, umi_1.publicKey)(marginfiAccounts_1.MARGINFI_ACCOUNTS[debt.mint.toString()].bank));
37
36
  }
38
37
  if (!supplyPrice) {
39
- const [price] = await (0, generalUtils_1.getTokenPrices)([
38
+ const [price] = await (0, generalUtils_1.fetchTokenPrices)([
40
39
  (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(supply.bank.mint),
41
40
  ]);
42
41
  supplyPrice = price;
@@ -101,7 +100,7 @@ async function getTokenUsage(umi, bank, isAsset, shares, amountUsedAdjustment) {
101
100
  let amountCanBeUsed = 0;
102
101
  let marketPrice = 0;
103
102
  if (bank !== null) {
104
- [marketPrice] = await (0, generalUtils_1.getTokenPrices)([(0, umi_web3js_adapters_1.toWeb3JsPublicKey)(bank.mint)]);
103
+ [marketPrice] = await (0, generalUtils_1.fetchTokenPrices)([(0, umi_web3js_adapters_1.toWeb3JsPublicKey)(bank.mint)]);
105
104
  const [assetShareValue, liabilityShareValue] = await getUpToDateShareValues(umi, bank);
106
105
  const shareValue = isAsset ? assetShareValue : liabilityShareValue;
107
106
  amountUsed = shares * shareValue + Number(amountUsedAdjustment ?? 0);
@@ -181,7 +180,7 @@ async function getMarginfiAccountPositionState(umi, marginfiAccountPk, supplyMin
181
180
  if (!debtUsage) {
182
181
  debtUsage = await getTokenUsage(umi, debtBank, false, 0, livePositionUpdates?.debtAdjustment);
183
182
  }
184
- const supplyPrice = solautoConstants_1.PRICES[supplyMint.toString()].price;
183
+ const supplyPrice = (0, generalUtils_1.safeGetPrice)(supplyMint);
185
184
  let [maxLtv, liqThreshold] = await getMaxLtvAndLiqThreshold(umi, {
186
185
  mint: (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(supplyBank.mint),
187
186
  bank: supplyBank,
@@ -69,9 +69,9 @@ function getDebtAdjustmentUsd(liqThresholdBps, supplyUsd, debtUsd, targetLiqUtil
69
69
  function getSolautoFeesBps(isReferred, targetLiqUtilizationRateBps, positionNetWorthUsd) {
70
70
  const minSize = 10000; // Minimum position size
71
71
  const maxSize = 500000; // Maximum position size
72
- const maxFeeBps = 500; // Fee in basis points for minSize (5%)
72
+ const maxFeeBps = 200; // Fee in basis points for minSize (2%)
73
73
  const minFeeBps = 50; // Fee in basis points for maxSize (0.5%)
74
- const k = 0.55;
74
+ const k = 1.5;
75
75
  let feeBps = 0;
76
76
  if (targetLiqUtilizationRateBps !== undefined) {
77
77
  feeBps = minFeeBps;
@@ -213,7 +213,7 @@ async function getAllPositionsByAuthority(umi, user) {
213
213
  }
214
214
  async function positionStateWithLatestPrices(state, supplyPrice, debtPrice) {
215
215
  if (!supplyPrice || !debtPrice) {
216
- [supplyPrice, debtPrice] = await (0, generalUtils_1.getTokenPrices)([
216
+ [supplyPrice, debtPrice] = await (0, generalUtils_1.fetchTokenPrices)([
217
217
  (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(state.supply.mint),
218
218
  (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(state.debt.mint),
219
219
  ]);
@@ -138,11 +138,11 @@ function getFlashLoanDetails(client, values, jupQuote) {
138
138
  let flashLoanTokenPrice = 0;
139
139
  if (values.increasingLeverage) {
140
140
  flashLoanToken = client.solautoPositionState.debt;
141
- flashLoanTokenPrice = solautoConstants_1.PRICES[client.debtMint.toString()].price;
141
+ flashLoanTokenPrice = (0, generalUtils_2.safeGetPrice)(client.debtMint);
142
142
  }
143
143
  else {
144
144
  flashLoanToken = client.solautoPositionState.supply;
145
- flashLoanTokenPrice = solautoConstants_1.PRICES[client.supplyMint.toString()].price;
145
+ flashLoanTokenPrice = (0, generalUtils_2.safeGetPrice)(client.supplyMint);
146
146
  }
147
147
  const exactAmountBaseUnit = jupQuote && jupQuote.swapMode === "ExactOut"
148
148
  ? BigInt(parseInt(jupQuote.inAmount))
@@ -166,15 +166,15 @@ function getJupSwapRebalanceDetails(client, values, targetLiqUtilizationRateBps,
166
166
  : client.solautoPositionState.debt;
167
167
  const usdToSwap = Math.abs(values.debtAdjustmentUsd) + values.amountUsdToDcaIn;
168
168
  const inputPrice = values.increasingLeverage
169
- ? solautoConstants_1.PRICES[client.debtMint.toString()].price
170
- : solautoConstants_1.PRICES[client.supplyMint.toString()].price;
169
+ ? (0, generalUtils_2.safeGetPrice)(client.debtMint)
170
+ : (0, generalUtils_2.safeGetPrice)(client.supplyMint);
171
171
  const inputAmount = (0, numberUtils_1.toBaseUnit)(usdToSwap / inputPrice, input.decimals);
172
172
  const rebalancingToZero = targetLiqUtilizationRateBps === 0;
173
173
  return {
174
174
  inputMint: (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(input.mint),
175
175
  outputMint: (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(output.mint),
176
176
  destinationWallet: client.solautoPosition,
177
- slippageBpsIncFactor: 0.25 + (attemptNum ?? 0) * 0.2,
177
+ slippageBpsIncFactor: 0.5 + (attemptNum ?? 0) * 0.2,
178
178
  amount: rebalancingToZero
179
179
  ? client.solautoPositionState.debt.amountUsed.baseUnit +
180
180
  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.127",
3
+ "version": "1.0.129",
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",
@@ -32,7 +32,7 @@ import {
32
32
  marginfiRefreshData,
33
33
  } from "../generated";
34
34
  import { getMarginfiAccountPDA, getTokenAccount } from "../utils/accountUtils";
35
- import { generateRandomU64 } from "../utils/generalUtils";
35
+ import { generateRandomU64, safeGetPrice } from "../utils/generalUtils";
36
36
  import {
37
37
  MARGINFI_PROGRAM_ID,
38
38
  MarginfiAccount,
@@ -630,8 +630,8 @@ export class SolautoMarginfiClient extends SolautoClient {
630
630
 
631
631
  if (freshState) {
632
632
  this.log("Fresh state", freshState);
633
- const supplyPrice = PRICES[(freshState?.supply.mint ?? PublicKey.default).toString()].price;
634
- const debtPrice = PRICES[(freshState?.debt.mint ?? PublicKey.default).toString()].price;
633
+ const supplyPrice = safeGetPrice(freshState?.supply.mint)!;
634
+ const debtPrice = safeGetPrice(freshState?.debt.mint)!;
635
635
  this.log("Supply price: ", supplyPrice);
636
636
  this.log("Debt price: ", debtPrice);
637
637
  this.log("Liq threshold bps:", freshState.liqThresholdBps);
@@ -39,6 +39,7 @@ import {
39
39
  currentUnixSeconds,
40
40
  getSolanaAccountCreated,
41
41
  rpcAccountCreated,
42
+ safeGetPrice,
42
43
  } from "../utils/generalUtils";
43
44
  import { SolautoMarginfiClient } from "../clients/solautoMarginfiClient";
44
45
  import {
@@ -586,8 +587,8 @@ export async function buildSolautoRebalanceTransaction(
586
587
  client.solautoPositionSettings(),
587
588
  client.solautoPositionActiveDca(),
588
589
  currentUnixSeconds(),
589
- PRICES[client.supplyMint.toString()].price,
590
- PRICES[client.debtMint.toString()].price,
590
+ safeGetPrice(client.supplyMint)!,
591
+ safeGetPrice(client.debtMint)!,
591
592
  targetLiqUtilizationRateBps
592
593
  );
593
594
  client.log("Rebalance values: ", values);
@@ -320,10 +320,7 @@ export class TransactionsManager {
320
320
  choresBefore.prepend(updateLookupTable.updateLutTx);
321
321
  }
322
322
  if (choresBefore.getInstructions().length > 0) {
323
- const chore = new TransactionItem(
324
- async () => ({ tx: choresBefore }),
325
- "create account(s)"
326
- );
323
+ const chore = new TransactionItem(async () => ({ tx: choresBefore }));
327
324
  await chore.initialize();
328
325
  items.unshift(chore);
329
326
  this.txHandler.log(
@@ -332,7 +329,10 @@ export class TransactionsManager {
332
329
  );
333
330
  }
334
331
  if (choresAfter.getInstructions().length > 0) {
335
- const chore = new TransactionItem(async () => ({ tx: choresAfter }));
332
+ const chore = new TransactionItem(
333
+ async () => ({ tx: choresAfter }),
334
+ "closing temp accounts"
335
+ );
336
336
  await chore.initialize();
337
337
  items.push(chore);
338
338
  this.txHandler.log(
@@ -1,5 +1,5 @@
1
1
  import { PublicKey } from "@solana/web3.js";
2
- import { MaybeRpcAccount, publicKey, Umi } from "@metaplex-foundation/umi";
2
+ import { MaybeRpcAccount, publicKey, Umi, PublicKey as UmiPublicKey } from "@metaplex-foundation/umi";
3
3
  import { PYTH_PRICE_FEED_IDS } from "../constants/pythConstants";
4
4
  import { fromBaseUnit, toBaseUnit } from "./numberUtils";
5
5
  import { PRICES } from "../constants/solautoConstants";
@@ -45,7 +45,7 @@ export function arraysAreEqual(arrayA: number[], arrayB: number[]): boolean {
45
45
  return true;
46
46
  }
47
47
 
48
- export async function getTokenPrices(mints: PublicKey[]): Promise<number[]> {
48
+ export async function fetchTokenPrices(mints: PublicKey[]): Promise<number[]> {
49
49
  const currentTime = currentUnixSeconds();
50
50
  if (
51
51
  !mints.some(
@@ -94,6 +94,13 @@ export async function getTokenPrices(mints: PublicKey[]): Promise<number[]> {
94
94
  return prices;
95
95
  }
96
96
 
97
+ export function safeGetPrice(mint: PublicKey | UmiPublicKey): number | undefined {
98
+ if (mint.toString() in PRICES) {
99
+ return PRICES[mint.toString()].price;
100
+ }
101
+ return undefined;
102
+ }
103
+
97
104
  export type ErrorsToThrow = Array<new (...args: any[]) => Error>;
98
105
 
99
106
  export function retryWithExponentialBackoff<T>(
@@ -8,7 +8,7 @@ import {
8
8
  safeFetchBank,
9
9
  safeFetchMarginfiAccount,
10
10
  } from "../marginfi-sdk";
11
- import { currentUnixSeconds, getTokenPrices } from "./generalUtils";
11
+ import { currentUnixSeconds, fetchTokenPrices, safeGetPrice } from "./generalUtils";
12
12
  import {
13
13
  bytesToI80F48,
14
14
  fromBaseUnit,
@@ -72,7 +72,7 @@ export async function getMaxLtvAndLiqThreshold(
72
72
  }
73
73
 
74
74
  if (!supplyPrice) {
75
- const [price] = await getTokenPrices([
75
+ const [price] = await fetchTokenPrices([
76
76
  toWeb3JsPublicKey(supply.bank!.mint),
77
77
  ]);
78
78
  supplyPrice = price;
@@ -177,7 +177,7 @@ async function getTokenUsage(
177
177
  let marketPrice = 0;
178
178
 
179
179
  if (bank !== null) {
180
- [marketPrice] = await getTokenPrices([toWeb3JsPublicKey(bank.mint)]);
180
+ [marketPrice] = await fetchTokenPrices([toWeb3JsPublicKey(bank.mint)]);
181
181
  const [assetShareValue, liabilityShareValue] = await getUpToDateShareValues(
182
182
  umi,
183
183
  bank
@@ -335,7 +335,7 @@ export async function getMarginfiAccountPositionState(
335
335
  );
336
336
  }
337
337
 
338
- const supplyPrice = PRICES[supplyMint!.toString()].price;
338
+ const supplyPrice = safeGetPrice(supplyMint!)!;
339
339
  let [maxLtv, liqThreshold] = await getMaxLtvAndLiqThreshold(
340
340
  umi,
341
341
  {
@@ -97,9 +97,9 @@ export function getSolautoFeesBps(
97
97
  } {
98
98
  const minSize = 10_000; // Minimum position size
99
99
  const maxSize = 500_000; // Maximum position size
100
- const maxFeeBps = 500; // Fee in basis points for minSize (5%)
100
+ const maxFeeBps = 200; // Fee in basis points for minSize (2%)
101
101
  const minFeeBps = 50; // Fee in basis points for maxSize (0.5%)
102
- const k = 0.55;
102
+ const k = 1.5;
103
103
 
104
104
  let feeBps: number = 0;
105
105
 
@@ -13,7 +13,7 @@ import {
13
13
  getSolautoPositionAccountDataSerializer,
14
14
  getSolautoPositionSize,
15
15
  } from "../../generated";
16
- import { currentUnixSeconds, getTokenPrices } from "../generalUtils";
16
+ import { currentUnixSeconds, fetchTokenPrices } from "../generalUtils";
17
17
  import {
18
18
  fromBaseUnit,
19
19
  getLiqUtilzationRateBps,
@@ -323,7 +323,7 @@ export async function positionStateWithLatestPrices(
323
323
  debtPrice?: number
324
324
  ): Promise<PositionState> {
325
325
  if (!supplyPrice || !debtPrice) {
326
- [supplyPrice, debtPrice] = await getTokenPrices([
326
+ [supplyPrice, debtPrice] = await fetchTokenPrices([
327
327
  toWeb3JsPublicKey(state.supply.mint),
328
328
  toWeb3JsPublicKey(state.debt.mint),
329
329
  ]);
@@ -14,7 +14,7 @@ import {
14
14
  import { toWeb3JsPublicKey } from "@metaplex-foundation/umi-web3js-adapters";
15
15
  import { QuoteResponse } from "@jup-ag/api";
16
16
  import { JupSwapDetails } from "../jupiterUtils";
17
- import { currentUnixSeconds } from "../generalUtils";
17
+ import { currentUnixSeconds, safeGetPrice } from "../generalUtils";
18
18
  import {
19
19
  fromBaseUnit,
20
20
  fromBps,
@@ -300,10 +300,10 @@ export function getFlashLoanDetails(
300
300
  let flashLoanTokenPrice = 0;
301
301
  if (values.increasingLeverage) {
302
302
  flashLoanToken = client.solautoPositionState!.debt;
303
- flashLoanTokenPrice = PRICES[client.debtMint.toString()].price;
303
+ flashLoanTokenPrice = safeGetPrice(client.debtMint)!;
304
304
  } else {
305
305
  flashLoanToken = client.solautoPositionState!.supply;
306
- flashLoanTokenPrice = PRICES[client.supplyMint.toString()].price;
306
+ flashLoanTokenPrice = safeGetPrice(client.supplyMint)!;
307
307
  }
308
308
 
309
309
  const exactAmountBaseUnit =
@@ -346,8 +346,8 @@ export function getJupSwapRebalanceDetails(
346
346
  Math.abs(values.debtAdjustmentUsd) + values.amountUsdToDcaIn;
347
347
 
348
348
  const inputPrice = values.increasingLeverage
349
- ? PRICES[client.debtMint.toString()].price
350
- : PRICES[client.supplyMint.toString()].price;
349
+ ? safeGetPrice(client.debtMint)
350
+ : safeGetPrice(client.supplyMint);
351
351
  const inputAmount = toBaseUnit(usdToSwap / inputPrice!, input.decimals);
352
352
 
353
353
  const rebalancingToZero = targetLiqUtilizationRateBps === 0;
@@ -355,7 +355,7 @@ export function getJupSwapRebalanceDetails(
355
355
  inputMint: toWeb3JsPublicKey(input.mint),
356
356
  outputMint: toWeb3JsPublicKey(output.mint),
357
357
  destinationWallet: client.solautoPosition,
358
- slippageBpsIncFactor: 0.25 + (attemptNum ?? 0) * 0.2,
358
+ slippageBpsIncFactor: 0.5 + (attemptNum ?? 0) * 0.2,
359
359
  amount: rebalancingToZero
360
360
  ? client.solautoPositionState!.debt.amountUsed.baseUnit +
361
361
  BigInt(
@@ -1,22 +1,17 @@
1
1
  import { describe, it } from "mocha";
2
2
  import { none, publicKey, some } from "@metaplex-foundation/umi";
3
3
  import { setupTest } from "../shared";
4
- import { SolautoMarginfiClient } from "../../src/clients/solautoMarginfiClient";
4
+ import {
5
+ SolautoMarginfiClient,
6
+ } from "../../src/clients/solautoMarginfiClient";
5
7
  import {
6
8
  solautoAction,
7
9
  SolautoSettingsParametersInpArgs,
8
10
  } from "../../src/generated";
9
11
  import { buildSolautoRebalanceTransaction } from "../../src/transactions/transactionUtils";
10
- import {
11
- getDebtAdjustmentUsd,
12
- getLiqUtilzationRateBps,
13
- maxBoostToBps,
14
- maxRepayFromBps,
15
- maxRepayToBps,
16
- toBaseUnit,
17
- } from "../../src/utils/numberUtils";
12
+ import { maxBoostToBps, maxRepayFromBps, maxRepayToBps, toBaseUnit } from "../../src/utils/numberUtils";
18
13
  import { NATIVE_MINT } from "@solana/spl-token";
19
- import { getTokenPrices } from "../../src/utils/generalUtils";
14
+ import { fetchTokenPrices } from "../../src/utils/generalUtils";
20
15
  import {
21
16
  TransactionItem,
22
17
  TransactionsManager,
@@ -33,22 +28,25 @@ describe("Solauto Marginfi tests", async () => {
33
28
  const positionId = 1;
34
29
 
35
30
  it("open - deposit - borrow - rebalance to 0 - withdraw - close", async () => {
31
+
36
32
  const client = new SolautoMarginfiClient(process.env.HELIUS_API_KEY!, true);
37
33
 
38
34
  const supply = NATIVE_MINT;
39
35
  const supplyDecimals = 9;
40
36
  const debtDecimals = 6;
41
37
 
42
- await client.initialize({
43
- signer,
44
- positionId,
45
- authority: new PublicKey("E5BBsR1sUToPc3jXVwhrK5ttSiy6xhWJDMdQLvkgNppe")
46
- // marginfiAccount: new PublicKey(
47
- // "4nNvUXF5YqHFcH2nGweSiuvy1ct7V5FXfoCLKFYUN36z"
48
- // ),
49
- // supplyMint: NATIVE_MINT,
50
- // debtMint: new PublicKey(USDC_MINT),
51
- });
38
+ await client.initialize(
39
+ {
40
+ signer,
41
+ positionId,
42
+ authority: new PublicKey("AprYCPiVeKMCgjQ2ZufwChMzvQ5kFjJo2ekTLSkXsQDm")
43
+ // marginfiAccount: new PublicKey(
44
+ // "4nNvUXF5YqHFcH2nGweSiuvy1ct7V5FXfoCLKFYUN36z"
45
+ // ),
46
+ // supplyMint: NATIVE_MINT,
47
+ // debtMint: new PublicKey(USDC_MINT),
48
+ }
49
+ );
52
50
 
53
51
  const transactionItems: TransactionItem[] = [];
54
52
  // const settingParams: SolautoSettingsParametersInpArgs = {
@@ -72,7 +70,7 @@ describe("Solauto Marginfi tests", async () => {
72
70
  // const initialSupplyUsd = 150;
73
71
  // transactionItems.push(
74
72
  // new TransactionItem(async () => {
75
- // const [supplyPrice] = await getTokenPrices([supply]);
73
+ // const [supplyPrice] = await fetchTokenPrices([supply]);
76
74
  // return {
77
75
  // tx: client.protocolInteraction(
78
76
  // solautoAction("Deposit", [
@@ -111,7 +109,7 @@ describe("Solauto Marginfi tests", async () => {
111
109
  // const initialSupplyUsd = 50;
112
110
  // transactionItems.push(
113
111
  // new TransactionItem(async () => {
114
- // const [supplyPrice] = await getTokenPrices([supply]);
112
+ // const [supplyPrice] = await fetchTokenPrices([supply]);
115
113
  // return {
116
114
  // tx: client.protocolInteraction(
117
115
  // solautoAction("Deposit", [
@@ -122,13 +120,13 @@ describe("Solauto Marginfi tests", async () => {
122
120
  // }, "deposit")
123
121
  // );
124
122
 
125
- // transactionItems.push(
126
- // new TransactionItem(
127
- // async (attemptNum) =>
128
- // await buildSolautoRebalanceTransaction(client, 1500, attemptNum),
129
- // "rebalance"
130
- // )
131
- // );
123
+ transactionItems.push(
124
+ new TransactionItem(
125
+ async (attemptNum) =>
126
+ await buildSolautoRebalanceTransaction(client, undefined, attemptNum),
127
+ "rebalance"
128
+ )
129
+ );
132
130
 
133
131
  // transactionItems.push(
134
132
  // new TransactionItem(
@@ -157,19 +155,11 @@ describe("Solauto Marginfi tests", async () => {
157
155
  // )
158
156
  // );
159
157
 
160
- // await new TransactionsManager(
161
- // client,
162
- // undefined,
163
- // !payForTransactions ? "only-simulate" : "normal",
164
- // useJitoBundle
165
- // ).clientSend(transactionItems);
166
-
167
- // const debtAdjustment = getDebtAdjustmentUsd(8696, 366, 165, 7000);
168
- // const newLiqUtilizationRate = getLiqUtilzationRateBps(366 + debtAdjustment, 165 + debtAdjustment, 8696);
169
- // console.log(newLiqUtilizationRate);
170
-
171
- console.log("CURRENT", Number(client.solautoPositionState?.supply.amountUsed.baseUnit));
172
- const freshState = await client.getFreshPositionState();
173
- console.log("FRESH", Number(freshState!.supply.amountUsed.baseUnit));
158
+ await new TransactionsManager(
159
+ client,
160
+ undefined,
161
+ !payForTransactions ? "only-simulate" : "normal",
162
+ useJitoBundle
163
+ ).clientSend(transactionItems);
174
164
  });
175
165
  });
@@ -31,7 +31,8 @@ import {
31
31
  } from "../../src/utils/solauto/generalUtils";
32
32
  import {
33
33
  currentUnixSeconds,
34
- getTokenPrices,
34
+ fetchTokenPrices,
35
+ safeGetPrice,
35
36
  } from "../../src/utils/generalUtils";
36
37
  import { USDC_MINT } from "../../src/constants/tokenConstants";
37
38
  import { PRICES } from "../../src/constants";
@@ -50,8 +51,8 @@ function assertAccurateRebalance(
50
51
  client.solautoPositionSettings(),
51
52
  client.solautoPositionActiveDca(),
52
53
  currentUnixSeconds(),
53
- PRICES[client.supplyMint.toString()].price,
54
- PRICES[client.debtMint.toString()].price,
54
+ safeGetPrice(client.supplyMint)!,
55
+ safeGetPrice(client.debtMint)!,
55
56
  targetLiqUtilizationRateBps
56
57
  );
57
58
 
@@ -124,7 +125,7 @@ async function getFakePosition(
124
125
  createFakePositionState(
125
126
  {
126
127
  amountUsed: supplyUsd / supplyPrice,
127
- price: PRICES[NATIVE_MINT.toString()].price,
128
+ price: safeGetPrice(NATIVE_MINT)!,
128
129
  mint: NATIVE_MINT,
129
130
  },
130
131
  {
@@ -282,7 +283,7 @@ describe("Rebalance tests", async () => {
282
283
  let supplyPrice: number, debtPrice: number;
283
284
 
284
285
  before(async () => {
285
- [supplyPrice, debtPrice] = await getTokenPrices([
286
+ [supplyPrice, debtPrice] = await fetchTokenPrices([
286
287
  NATIVE_MINT,
287
288
  new PublicKey(USDC_MINT),
288
289
  ]);