@strkfarm/sdk 2.0.0-dev.27 → 2.0.0-dev.28

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 (70) hide show
  1. package/dist/cli.js +190 -36
  2. package/dist/cli.mjs +188 -34
  3. package/dist/index.browser.global.js +79130 -49357
  4. package/dist/index.browser.mjs +18039 -11434
  5. package/dist/index.d.ts +2869 -898
  6. package/dist/index.js +19036 -12210
  7. package/dist/index.mjs +18942 -12161
  8. package/package.json +1 -1
  9. package/src/data/avnu.abi.json +840 -0
  10. package/src/data/ekubo-price-fethcer.abi.json +265 -0
  11. package/src/dataTypes/_bignumber.ts +13 -4
  12. package/src/dataTypes/index.ts +3 -2
  13. package/src/dataTypes/mynumber.ts +141 -0
  14. package/src/global.ts +76 -41
  15. package/src/index.browser.ts +2 -1
  16. package/src/interfaces/common.tsx +167 -2
  17. package/src/modules/ExtendedWrapperSDk/types.ts +26 -4
  18. package/src/modules/ExtendedWrapperSDk/wrapper.ts +110 -67
  19. package/src/modules/apollo-client-config.ts +28 -0
  20. package/src/modules/avnu.ts +4 -4
  21. package/src/modules/ekubo-pricer.ts +79 -0
  22. package/src/modules/ekubo-quoter.ts +46 -30
  23. package/src/modules/erc20.ts +17 -0
  24. package/src/modules/harvests.ts +43 -29
  25. package/src/modules/pragma.ts +23 -8
  26. package/src/modules/pricer-from-api.ts +156 -15
  27. package/src/modules/pricer-lst.ts +1 -1
  28. package/src/modules/pricer.ts +40 -4
  29. package/src/modules/pricerBase.ts +2 -1
  30. package/src/node/deployer.ts +36 -1
  31. package/src/node/pricer-redis.ts +2 -1
  32. package/src/strategies/base-strategy.ts +78 -10
  33. package/src/strategies/ekubo-cl-vault.tsx +906 -347
  34. package/src/strategies/factory.ts +159 -0
  35. package/src/strategies/index.ts +6 -1
  36. package/src/strategies/registry.ts +239 -0
  37. package/src/strategies/sensei.ts +335 -7
  38. package/src/strategies/svk-strategy.ts +97 -27
  39. package/src/strategies/types.ts +4 -0
  40. package/src/strategies/universal-adapters/adapter-utils.ts +2 -1
  41. package/src/strategies/universal-adapters/avnu-adapter.ts +177 -268
  42. package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
  43. package/src/strategies/universal-adapters/common-adapter.ts +206 -203
  44. package/src/strategies/universal-adapters/extended-adapter.ts +155 -336
  45. package/src/strategies/universal-adapters/index.ts +9 -8
  46. package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
  47. package/src/strategies/universal-adapters/usdc<>usdce-adapter.ts +200 -0
  48. package/src/strategies/universal-adapters/vesu-adapter.ts +110 -75
  49. package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +476 -0
  50. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +762 -844
  51. package/src/strategies/universal-adapters/vesu-position-common.ts +251 -0
  52. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
  53. package/src/strategies/universal-lst-muliplier-strategy.tsx +396 -204
  54. package/src/strategies/universal-strategy.tsx +1426 -1178
  55. package/src/strategies/vesu-extended-strategy/services/executionService.ts +2251 -0
  56. package/src/strategies/vesu-extended-strategy/services/extended-vesu-state-manager.ts +2941 -0
  57. package/src/strategies/vesu-extended-strategy/services/operationService.ts +12 -1
  58. package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +52 -0
  59. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +1 -0
  60. package/src/strategies/vesu-extended-strategy/utils/constants.ts +2 -0
  61. package/src/strategies/vesu-extended-strategy/utils/helper.ts +158 -124
  62. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +377 -1788
  63. package/src/strategies/vesu-rebalance.tsx +255 -152
  64. package/src/utils/health-factor-math.ts +4 -1
  65. package/src/utils/index.ts +2 -1
  66. package/src/utils/logger.browser.ts +22 -4
  67. package/src/utils/logger.node.ts +259 -24
  68. package/src/utils/starknet-call-parser.ts +1036 -0
  69. package/src/utils/strategy-utils.ts +61 -0
  70. package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
@@ -0,0 +1,251 @@
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: supportedPosition.isDebt ? "Vesu debt" : "Vesu collateral" };
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
+ export async function getVesuCommonMaxDeposit(
136
+ ctx: VesuPositionCommonContext,
137
+ amount?: Web3Number,
138
+ ): Promise<PositionInfo> {
139
+ const collateral = ctx.collateral;
140
+ const debt = ctx.debt;
141
+ try {
142
+ ctx.vesuAdapter.networkConfig = ctx.networkConfig;
143
+ ctx.vesuAdapter.pricer = ctx.pricer as any;
144
+
145
+ const positions = await ctx.vesuAdapter.getPositions(ctx.networkConfig);
146
+ const collateralPosition = positions.find((p) => p.token.address.eq(collateral.address));
147
+ const debtPosition = positions.find((p) => p.token.address.eq(debt.address));
148
+ if (!collateralPosition || !debtPosition) {
149
+ throw new Error("Could not find current positions");
150
+ }
151
+
152
+ const maxBorrowableAPY = await getVesuCommonMaxBorrowableAPY(ctx);
153
+ const maxBorrowableResult = await ctx.vesuAdapter.getMaxBorrowableByInterestRate(
154
+ ctx.networkConfig,
155
+ debt,
156
+ maxBorrowableAPY,
157
+ );
158
+ const maxBorrowable = maxBorrowableResult.maxDebtToHave;
159
+ const debtCap = await ctx.vesuAdapter.getDebtCap(ctx.networkConfig);
160
+ const actualMaxBorrowable = maxBorrowable.minimum(debtCap);
161
+ const maxLTV = await ctx.vesuAdapter.getLTVConfig(ctx.networkConfig);
162
+
163
+ const collateralPrice = await ctx.pricer.getPrice(collateral.symbol);
164
+ if (collateralPrice.price === 0) {
165
+ throw new Error("Collateral price is 0");
166
+ }
167
+ const debtPrice = await ctx.pricer.getPrice(debt.symbol);
168
+ if (debtPrice.price === 0) {
169
+ throw new Error("Debt price is 0");
170
+ }
171
+
172
+ const maxCollateralFromDebt = HealthFactorMath.getMinCollateralRequiredOnLooping(
173
+ actualMaxBorrowable,
174
+ debtPrice.price,
175
+ ctx.targetHealthFactor,
176
+ maxLTV,
177
+ collateralPrice.price,
178
+ collateral,
179
+ );
180
+ const maxDepositAmount = amount ? amount.minimum(maxCollateralFromDebt) : maxCollateralFromDebt;
181
+ const usdValue = await ctx.getUSDValue(collateral, maxDepositAmount);
182
+ const apys = await Promise.all([
183
+ getVesuCommonAPY(ctx, { asset: collateral, isDebt: false }),
184
+ getVesuCommonAPY(ctx, { asset: debt, isDebt: true }),
185
+ ]);
186
+
187
+ const borrowAmountUSD = actualMaxBorrowable.multipliedBy(debtPrice.price);
188
+ const netCollateralUSD = usdValue + borrowAmountUSD.toNumber();
189
+ const netAPY =
190
+ (apys[0].apy * netCollateralUSD + apys[1].apy * borrowAmountUSD.toNumber()) /
191
+ usdValue;
192
+
193
+ return {
194
+ tokenInfo: collateral,
195
+ amount: maxDepositAmount,
196
+ usdValue,
197
+ remarks: "Max deposit based on available debt capacity",
198
+ apy: { apy: netAPY, type: APYType.BASE },
199
+ protocol: ctx.protocol,
200
+ };
201
+ } catch (error) {
202
+ logger.error(`${ctx.adapterName}: Error calculating max deposit:`, error);
203
+ throw error;
204
+ }
205
+ }
206
+
207
+ export async function getVesuCommonMaxWithdraw(
208
+ ctx: VesuPositionCommonContext,
209
+ ): Promise<PositionInfo> {
210
+ const collateral = ctx.collateral;
211
+ const debt = ctx.debt;
212
+ try {
213
+ ctx.vesuAdapter.networkConfig = ctx.networkConfig;
214
+ ctx.vesuAdapter.pricer = ctx.pricer as any;
215
+ const positions = await ctx.vesuAdapter.getPositions(ctx.networkConfig);
216
+ const collateralPosition = positions.find((p) => p.token.address.eq(collateral.address));
217
+ const debtPosition = positions.find((p) => p.token.address.eq(debt.address));
218
+ if (!collateralPosition || !debtPosition) {
219
+ throw new Error("Could not find current positions");
220
+ }
221
+
222
+ const collateralPrice = collateralPosition.usdValue / collateralPosition.amount.toNumber();
223
+ const debtInCollateral = debtPosition.usdValue / collateralPrice;
224
+ const maxWithdrawable = collateralPosition.amount.minus(debtInCollateral);
225
+ const result = maxWithdrawable.greaterThan(0)
226
+ ? maxWithdrawable
227
+ : new Web3Number("0", collateral.decimals);
228
+ const usdValue = await ctx.getUSDValue(collateral, result);
229
+ const debtUSD = debtPosition.usdValue;
230
+ const apys = await Promise.all([
231
+ getVesuCommonAPY(ctx, { asset: collateral, isDebt: false }),
232
+ getVesuCommonAPY(ctx, { asset: debt, isDebt: true }),
233
+ ]);
234
+ const netAPY =
235
+ usdValue - debtUSD > 0
236
+ ? (apys[0].apy * usdValue + apys[1].apy * debtUSD) / (usdValue - debtUSD)
237
+ : 0;
238
+
239
+ return {
240
+ tokenInfo: collateral,
241
+ amount: result,
242
+ usdValue,
243
+ remarks: "Max withdraw based on health factor",
244
+ apy: { apy: netAPY, type: APYType.BASE },
245
+ protocol: ctx.protocol,
246
+ };
247
+ } catch (error) {
248
+ logger.error(`${ctx.adapterName}: Error calculating max withdraw:`, error);
249
+ throw error;
250
+ }
251
+ }
@@ -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,