@strkfarm/sdk 2.0.0-dev.5 → 2.0.0-dev.51

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.
Files changed (80) hide show
  1. package/dist/cli.js +190 -36
  2. package/dist/cli.mjs +188 -34
  3. package/dist/index.browser.global.js +118889 -92229
  4. package/dist/index.browser.mjs +13381 -11153
  5. package/dist/index.d.ts +2284 -1938
  6. package/dist/index.js +13794 -11360
  7. package/dist/index.mjs +14253 -11843
  8. package/package.json +59 -60
  9. package/src/data/avnu.abi.json +840 -0
  10. package/src/data/ekubo-price-fethcer.abi.json +265 -0
  11. package/src/data/redeem-request-nft.abi.json +752 -0
  12. package/src/data/universal-vault.abi.json +8 -7
  13. package/src/dataTypes/_bignumber.ts +13 -4
  14. package/src/dataTypes/bignumber.browser.ts +10 -1
  15. package/src/dataTypes/bignumber.node.ts +10 -1
  16. package/src/dataTypes/index.ts +3 -2
  17. package/src/dataTypes/mynumber.ts +141 -0
  18. package/src/global.ts +280 -233
  19. package/src/index.browser.ts +2 -1
  20. package/src/interfaces/common.tsx +229 -6
  21. package/src/modules/apollo-client-config.ts +28 -0
  22. package/src/modules/avnu.ts +21 -12
  23. package/src/modules/ekubo-pricer.ts +99 -0
  24. package/src/modules/ekubo-quoter.ts +48 -30
  25. package/src/modules/erc20.ts +17 -0
  26. package/src/modules/harvests.ts +43 -29
  27. package/src/modules/index.ts +2 -1
  28. package/src/modules/pragma.ts +23 -8
  29. package/src/modules/pricer-avnu-api.ts +114 -0
  30. package/src/modules/pricer-from-api.ts +159 -15
  31. package/src/modules/pricer-lst.ts +1 -1
  32. package/src/modules/pricer-quote-utils.ts +54 -0
  33. package/src/modules/pricer.ts +157 -54
  34. package/src/modules/pricerBase.ts +2 -1
  35. package/src/modules/zkLend.ts +3 -2
  36. package/src/node/deployer.ts +36 -1
  37. package/src/node/pricer-redis.ts +3 -1
  38. package/src/strategies/base-strategy.ts +168 -16
  39. package/src/strategies/constants.ts +8 -3
  40. package/src/strategies/ekubo-cl-vault.tsx +1048 -355
  41. package/src/strategies/factory.ts +199 -0
  42. package/src/strategies/index.ts +5 -3
  43. package/src/strategies/registry.ts +262 -0
  44. package/src/strategies/sensei.ts +354 -10
  45. package/src/strategies/svk-strategy.ts +292 -31
  46. package/src/strategies/token-boosted-xstrk-carry-strategy.tsx +1261 -0
  47. package/src/strategies/types.ts +4 -0
  48. package/src/strategies/universal-adapters/adapter-utils.ts +4 -1
  49. package/src/strategies/universal-adapters/avnu-adapter.ts +196 -272
  50. package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
  51. package/src/strategies/universal-adapters/common-adapter.ts +206 -203
  52. package/src/strategies/universal-adapters/index.ts +10 -8
  53. package/src/strategies/universal-adapters/svk-troves-adapter.ts +511 -0
  54. package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
  55. package/src/strategies/universal-adapters/vesu-adapter.ts +120 -82
  56. package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +525 -0
  57. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +866 -860
  58. package/src/strategies/universal-adapters/vesu-position-common.ts +258 -0
  59. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
  60. package/src/strategies/universal-lst-muliplier-strategy.tsx +895 -416
  61. package/src/strategies/universal-strategy.tsx +1332 -1173
  62. package/src/strategies/vesu-rebalance.tsx +254 -153
  63. package/src/strategies/yoloVault.ts +1096 -0
  64. package/src/utils/cacheClass.ts +11 -2
  65. package/src/utils/health-factor-math.ts +33 -1
  66. package/src/utils/index.ts +3 -1
  67. package/src/utils/logger.browser.ts +22 -4
  68. package/src/utils/logger.node.ts +259 -24
  69. package/src/utils/starknet-call-parser.ts +1036 -0
  70. package/src/utils/strategy-utils.ts +61 -0
  71. package/src/modules/ExtendedWrapperSDk/index.ts +0 -62
  72. package/src/modules/ExtendedWrapperSDk/types.ts +0 -311
  73. package/src/modules/ExtendedWrapperSDk/wrapper.ts +0 -395
  74. package/src/strategies/universal-adapters/extended-adapter.ts +0 -662
  75. package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
  76. package/src/strategies/vesu-extended-strategy/services/operationService.ts +0 -34
  77. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +0 -77
  78. package/src/strategies/vesu-extended-strategy/utils/constants.ts +0 -49
  79. package/src/strategies/vesu-extended-strategy/utils/helper.ts +0 -372
  80. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +0 -1140
@@ -0,0 +1,258 @@
1
+ import { ContractAddr, Web3Number } from "@/dataTypes";
2
+ import { IConfig, IProtocol, TokenInfo } from "@/interfaces";
3
+ import { TokenMarketData } from "@/modules";
4
+ import { logger } from "@/utils";
5
+ import { HealthFactorMath } from "@/utils/health-factor-math";
6
+ import { num } from "starknet";
7
+ import {
8
+ APYType,
9
+ PositionAPY,
10
+ PositionAmount,
11
+ PositionInfo,
12
+ SupportedPosition,
13
+ } from "./baseAdapter";
14
+ import { VesuAdapter } from "./vesu-adapter";
15
+
16
+ export type VesuPositionCommonContext = {
17
+ adapterName: string;
18
+ protocol: IProtocol;
19
+ poolId: ContractAddr;
20
+ collateral: TokenInfo;
21
+ debt: TokenInfo;
22
+ networkConfig: IConfig;
23
+ pricer: {
24
+ getPrice: (symbol: string) => Promise<{ price: number }>;
25
+ };
26
+ vesuAdapter: VesuAdapter;
27
+ tokenMarketData: TokenMarketData;
28
+ targetHealthFactor: number;
29
+ getCache: <T>(key: string) => T | null | undefined;
30
+ setCache: <T>(key: string, value: T, ttlMs: number) => void;
31
+ getUSDValue: (asset: TokenInfo, amount: Web3Number) => Promise<number>;
32
+ };
33
+
34
+ export async function getVesuCommonAPY(
35
+ ctx: VesuPositionCommonContext,
36
+ supportedPosition: SupportedPosition,
37
+ ): Promise<PositionAPY> {
38
+ const cacheKey = `apy_${ctx.poolId.address}_${supportedPosition.asset.symbol}`;
39
+ const cacheData = ctx.getCache<PositionAPY>(cacheKey);
40
+ if (cacheData) {
41
+ return cacheData;
42
+ }
43
+
44
+ try {
45
+ const allVesuPools = await VesuAdapter.getVesuPools();
46
+ const asset = supportedPosition.asset;
47
+ const pool = allVesuPools.pools.find((p) =>
48
+ ctx.poolId.eqString(num.getHexString(p.id)),
49
+ );
50
+ if (!pool) {
51
+ logger.warn(`${ctx.adapterName}: Pool not found for token ${asset.symbol}`);
52
+ return { apy: 0, type: APYType.BASE };
53
+ }
54
+
55
+ const assetStats = pool.assets.find(
56
+ (a: any) => a.symbol.toLowerCase() === asset.symbol.toLowerCase(),
57
+ )?.stats;
58
+ if (!assetStats) {
59
+ logger.warn(`${ctx.adapterName}: Asset stats not found for token ${asset.symbol}`);
60
+ return { apy: 0, type: APYType.BASE };
61
+ }
62
+
63
+ let apy = 0;
64
+ if (supportedPosition.isDebt) {
65
+ apy = Number(assetStats.borrowApr?.value || 0) / 1e18;
66
+ } else {
67
+ const isAssetBTC = asset.symbol.toLowerCase().includes("btc");
68
+ const baseAPY =
69
+ Number(
70
+ isAssetBTC
71
+ ? assetStats.btcFiSupplyApr?.value + assetStats.supplyApy?.value
72
+ : assetStats.supplyApy?.value || 0,
73
+ ) / 1e18;
74
+ const rewardAPY = Number(assetStats.defiSpringSupplyApr?.value || "0") / 1e18;
75
+ apy = baseAPY + rewardAPY;
76
+ if (ctx.tokenMarketData.isAPYSupported(asset)) {
77
+ apy += await ctx.tokenMarketData.getAPY(asset);
78
+ }
79
+ }
80
+
81
+ const result = { apy, type: APYType.BASE };
82
+ ctx.setCache(cacheKey, result, 300000);
83
+ return result;
84
+ } catch (error) {
85
+ logger.error(`${ctx.adapterName}: Error getting APY for ${supportedPosition.asset.symbol}:`, error);
86
+ throw error;
87
+ }
88
+ }
89
+
90
+ export async function getVesuCommonPosition(
91
+ ctx: VesuPositionCommonContext,
92
+ supportedPosition: SupportedPosition,
93
+ ): Promise<PositionAmount> {
94
+ const cacheKey = `position_${ctx.poolId.address}_${supportedPosition.asset.symbol}`;
95
+ const cacheData = ctx.getCache<PositionAmount>(cacheKey);
96
+ if (cacheData) {
97
+ return cacheData;
98
+ }
99
+
100
+ try {
101
+ ctx.vesuAdapter.networkConfig = ctx.networkConfig;
102
+ ctx.vesuAdapter.pricer = ctx.pricer as any;
103
+ const positions = await ctx.vesuAdapter.getPositions(ctx.networkConfig);
104
+ let position = positions.find((p) => p.token.address.eq(supportedPosition.asset.address));
105
+ if (!position) {
106
+ logger.warn(`${ctx.adapterName}: Position not found for token ${supportedPosition.asset.symbol}`);
107
+ return {
108
+ amount: new Web3Number("0", supportedPosition.asset.decimals),
109
+ remarks: "Position not found",
110
+ };
111
+ }
112
+ if (supportedPosition.isDebt) {
113
+ position.amount = position.amount.multipliedBy(-1);
114
+ position.usdValue = position.usdValue * -1;
115
+ }
116
+ const result = { amount: position.amount, remarks: position.remarks };
117
+ ctx.setCache(cacheKey, result, 60000);
118
+ return result;
119
+ } catch (error) {
120
+ logger.error(`${ctx.adapterName}: Error getting position for ${supportedPosition.asset.symbol}:`, error);
121
+ throw error;
122
+ }
123
+ }
124
+
125
+ export async function getVesuCommonMaxBorrowableAPY(
126
+ ctx: VesuPositionCommonContext,
127
+ ): Promise<number> {
128
+ const collateralAPY = await getVesuCommonAPY(ctx, {
129
+ asset: ctx.collateral,
130
+ isDebt: false,
131
+ });
132
+ return collateralAPY.apy * 0.8;
133
+ }
134
+
135
+ /// @dev this function is used to calculate the max deposit amount based on the available debt capacity
136
+ export async function getVesuCommonMaxDeposit(
137
+ ctx: VesuPositionCommonContext,
138
+ amount?: Web3Number,
139
+ ): Promise<{collateralPosition: PositionInfo, debtPosition: PositionInfo}> {
140
+ const collateral = ctx.collateral;
141
+ const debt = ctx.debt;
142
+ try {
143
+ ctx.vesuAdapter.networkConfig = ctx.networkConfig;
144
+ ctx.vesuAdapter.pricer = ctx.pricer as any;
145
+
146
+ const positions = await ctx.vesuAdapter.getPositions(ctx.networkConfig);
147
+ const collateralPosition = positions.find((p) => p.token.address.eq(collateral.address));
148
+ const debtPosition = positions.find((p) => p.token.address.eq(debt.address));
149
+ if (!collateralPosition || !debtPosition) {
150
+ throw new Error("Could not find current positions");
151
+ }
152
+
153
+ const maxBorrowableAPY = await getVesuCommonMaxBorrowableAPY(ctx);
154
+ const maxBorrowableResult = await ctx.vesuAdapter.getMaxBorrowableByInterestRate(
155
+ ctx.networkConfig,
156
+ debt,
157
+ maxBorrowableAPY,
158
+ );
159
+ const maxBorrowable = maxBorrowableResult.maxDebtToHave;
160
+ const debtCap = await ctx.vesuAdapter.getDebtCap(ctx.networkConfig);
161
+ const actualMaxBorrowable = maxBorrowable.minimum(debtCap);
162
+ const maxLTV = await ctx.vesuAdapter.getLTVConfig(ctx.networkConfig);
163
+
164
+ const collateralPrice = await ctx.pricer.getPrice(collateral.symbol);
165
+ if (collateralPrice.price === 0) {
166
+ throw new Error("Collateral price is 0");
167
+ }
168
+ const debtPrice = await ctx.pricer.getPrice(debt.symbol);
169
+ if (debtPrice.price === 0) {
170
+ throw new Error("Debt price is 0");
171
+ }
172
+
173
+ /**
174
+ * We use existing collateral and debt also in the calculations.
175
+ * This will ensure any new collateral requirement also considers low ltv possibilities + new debt being created.
176
+ */
177
+ const maxCollateralFromDebt = HealthFactorMath.getCollateralRequired(
178
+ actualMaxBorrowable.plus(debtPosition.amount), // net new debt
179
+ debtPrice.price,
180
+ ctx.targetHealthFactor,
181
+ maxLTV,
182
+ collateralPrice.price,
183
+ collateral,
184
+ );
185
+ const maxNewCollateral = maxCollateralFromDebt.minus(collateralPosition.amount).minimum(0); // net new collateral
186
+ const maxDepositAmount = amount ? amount.minimum(maxNewCollateral) : maxNewCollateral;
187
+ const usdValue = await ctx.getUSDValue(collateral, maxDepositAmount);
188
+ const apys = await Promise.all([
189
+ getVesuCommonAPY(ctx, { asset: collateral, isDebt: false }),
190
+ getVesuCommonAPY(ctx, { asset: debt, isDebt: true }),
191
+ ]);
192
+
193
+ const borrowAmountUSD = actualMaxBorrowable.multipliedBy(debtPrice.price);
194
+
195
+ return {collateralPosition: {
196
+ tokenInfo: collateral,
197
+ amount: maxDepositAmount,
198
+ usdValue,
199
+ remarks: "Max deposit based on available debt capacity",
200
+ apy: { apy: apys[0].apy, type: APYType.BASE },
201
+ protocol: ctx.protocol,
202
+ }, debtPosition: {
203
+ tokenInfo: debt,
204
+ amount: actualMaxBorrowable,
205
+ usdValue: borrowAmountUSD.toNumber(),
206
+ remarks: "Max borrow based on available debt capacity",
207
+ apy: { apy: apys[1].apy, type: APYType.BASE },
208
+ protocol: ctx.protocol,
209
+ }};
210
+ } catch (error) {
211
+ logger.error(`${ctx.adapterName}: Error calculating max deposit:`, error);
212
+ throw error;
213
+ }
214
+ }
215
+
216
+ export async function getVesuCommonMaxWithdraw(
217
+ ctx: VesuPositionCommonContext,
218
+ ): Promise<{collateralPosition: PositionInfo, debtPosition: PositionInfo}> {
219
+ const collateral = ctx.collateral;
220
+ const debt = ctx.debt;
221
+ try {
222
+ ctx.vesuAdapter.networkConfig = ctx.networkConfig;
223
+ ctx.vesuAdapter.pricer = ctx.pricer as any;
224
+ const positions = await ctx.vesuAdapter.getPositions(ctx.networkConfig);
225
+ const collateralPosition = positions.find((p) => p.token.address.eq(collateral.address));
226
+ const debtPosition = positions.find((p) => p.token.address.eq(debt.address));
227
+ if (!collateralPosition || !debtPosition) {
228
+ throw new Error("Could not find current positions");
229
+ }
230
+
231
+ const apys = await Promise.all([
232
+ getVesuCommonAPY(ctx, { asset: collateral, isDebt: false }),
233
+ getVesuCommonAPY(ctx, { asset: debt, isDebt: true }),
234
+ ]);
235
+
236
+ return {
237
+ collateralPosition: {
238
+ tokenInfo: collateral,
239
+ amount: collateralPosition.amount,
240
+ usdValue: collateralPosition.usdValue,
241
+ remarks: "Max withdraw based on health factor",
242
+ apy: { apy: apys[0].apy, type: APYType.BASE },
243
+ protocol: ctx.protocol,
244
+ },
245
+ debtPosition: {
246
+ tokenInfo: debt,
247
+ amount: debtPosition.amount,
248
+ usdValue: debtPosition.usdValue,
249
+ remarks: "Max withdraw based on health factor",
250
+ apy: { apy: apys[1].apy, type: APYType.BASE },
251
+ protocol: ctx.protocol,
252
+ },
253
+ };
254
+ } catch (error) {
255
+ logger.error(`${ctx.adapterName}: Error calculating max withdraw:`, error);
256
+ throw error;
257
+ }
258
+ }
@@ -24,6 +24,18 @@ export class VesuSupplyOnlyAdapter extends BaseAdapter<DepositParams, WithdrawPa
24
24
  this.tokenMarketData = new TokenMarketData(this.config.pricer, this.config.networkConfig);
25
25
  }
26
26
 
27
+ private _depositApproveProofReadableId(): string {
28
+ return `appr_dep_vtkn_${this.config.vTokenContract.shortString()}`;
29
+ }
30
+
31
+ private _depositCallProofReadableId(): string {
32
+ return `deposit_vtoken_${this.config.vTokenContract.shortString()}`;
33
+ }
34
+
35
+ private _withdrawCallProofReadableId(): string {
36
+ return `withdraw_vtoken_${this.config.vTokenContract.shortString()}`;
37
+ }
38
+
27
39
  protected async getAPY(supportedPosition: SupportedPosition): Promise<PositionAPY> {
28
40
  const CACHE_KEY = `apy_${this.config.vTokenContract.address}`;
29
41
  const cacheData = this.getCache<PositionAPY>(CACHE_KEY);
@@ -193,7 +205,7 @@ export class VesuSupplyOnlyAdapter extends BaseAdapter<DepositParams, WithdrawPa
193
205
  vTokenContract.toBigInt(), // spender
194
206
  ],
195
207
  sanitizer: SIMPLE_SANITIZER,
196
- id: `appr_dep_vtkn_${this.config.vTokenContract.shortString()}`
208
+ id: this._depositApproveProofReadableId()
197
209
  },
198
210
  // Deposit step
199
211
  {
@@ -203,7 +215,7 @@ export class VesuSupplyOnlyAdapter extends BaseAdapter<DepositParams, WithdrawPa
203
215
  this.config.vaultAllocator.toBigInt(),
204
216
  ],
205
217
  sanitizer: SIMPLE_SANITIZER,
206
- id: `deposit_vtoken_${this.config.vTokenContract.shortString()}`
218
+ id: this._depositCallProofReadableId()
207
219
  }
208
220
  ];
209
221
  }
@@ -227,7 +239,7 @@ export class VesuSupplyOnlyAdapter extends BaseAdapter<DepositParams, WithdrawPa
227
239
  this.config.vaultAllocator.toBigInt(),
228
240
  ],
229
241
  sanitizer: SIMPLE_SANITIZER,
230
- id: `withdraw_vtoken_${this.config.vTokenContract.shortString()}`
242
+ id: this._withdrawCallProofReadableId()
231
243
  }
232
244
  ];
233
245
  }
@@ -272,6 +284,7 @@ export class VesuSupplyOnlyAdapter extends BaseAdapter<DepositParams, WithdrawPa
272
284
  return [
273
285
  // Approval call
274
286
  {
287
+ proofReadableId: this._depositApproveProofReadableId(),
275
288
  sanitizer: SIMPLE_SANITIZER,
276
289
  call: {
277
290
  contractAddress: baseToken.address,
@@ -285,6 +298,7 @@ export class VesuSupplyOnlyAdapter extends BaseAdapter<DepositParams, WithdrawPa
285
298
  },
286
299
  // Deposit call
287
300
  {
301
+ proofReadableId: this._depositCallProofReadableId(),
288
302
  sanitizer: SIMPLE_SANITIZER,
289
303
  call: {
290
304
  contractAddress: vTokenContract,
@@ -308,6 +322,7 @@ export class VesuSupplyOnlyAdapter extends BaseAdapter<DepositParams, WithdrawPa
308
322
  return [
309
323
  // Withdraw call
310
324
  {
325
+ proofReadableId: this._withdrawCallProofReadableId(),
311
326
  sanitizer: SIMPLE_SANITIZER,
312
327
  call: {
313
328
  contractAddress: vTokenContract,