@strkfarm/sdk 1.1.70 → 2.0.0-dev.2

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 (53) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/cli.mjs +2 -2
  3. package/dist/index.browser.global.js +67016 -59681
  4. package/dist/index.browser.mjs +29832 -23221
  5. package/dist/index.d.ts +2006 -787
  6. package/dist/index.js +25403 -18769
  7. package/dist/index.mjs +25333 -18739
  8. package/package.json +80 -76
  9. package/src/data/extended-deposit.abi.json +3613 -0
  10. package/src/data/universal-vault.abi.json +135 -20
  11. package/src/dataTypes/address.ts +7 -0
  12. package/src/global.ts +240 -193
  13. package/src/interfaces/common.tsx +26 -2
  14. package/src/modules/ExtendedWrapperSDk/index.ts +62 -0
  15. package/src/modules/ExtendedWrapperSDk/types.ts +311 -0
  16. package/src/modules/ExtendedWrapperSDk/wrapper.ts +395 -0
  17. package/src/modules/avnu.ts +17 -4
  18. package/src/modules/ekubo-quoter.ts +99 -10
  19. package/src/modules/erc20.ts +67 -21
  20. package/src/modules/harvests.ts +16 -29
  21. package/src/modules/index.ts +5 -1
  22. package/src/modules/lst-apr.ts +36 -0
  23. package/src/modules/midas.ts +159 -0
  24. package/src/modules/pricer-from-api.ts +2 -2
  25. package/src/modules/pricer-lst.ts +1 -1
  26. package/src/modules/pricer.ts +3 -38
  27. package/src/modules/token-market-data.ts +202 -0
  28. package/src/node/deployer.ts +1 -36
  29. package/src/strategies/autoCompounderStrk.ts +1 -1
  30. package/src/strategies/base-strategy.ts +20 -3
  31. package/src/strategies/ekubo-cl-vault.tsx +123 -306
  32. package/src/strategies/index.ts +4 -1
  33. package/src/strategies/svk-strategy.ts +247 -0
  34. package/src/strategies/universal-adapters/adapter-optimizer.ts +65 -0
  35. package/src/strategies/universal-adapters/adapter-utils.ts +5 -1
  36. package/src/strategies/universal-adapters/avnu-adapter.ts +411 -0
  37. package/src/strategies/universal-adapters/baseAdapter.ts +181 -153
  38. package/src/strategies/universal-adapters/common-adapter.ts +98 -77
  39. package/src/strategies/universal-adapters/extended-adapter.ts +661 -0
  40. package/src/strategies/universal-adapters/index.ts +5 -1
  41. package/src/strategies/universal-adapters/unused-balance-adapter.ts +109 -0
  42. package/src/strategies/universal-adapters/vesu-adapter.ts +220 -218
  43. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +924 -0
  44. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +58 -51
  45. package/src/strategies/universal-lst-muliplier-strategy.tsx +707 -774
  46. package/src/strategies/universal-strategy.tsx +1098 -1180
  47. package/src/strategies/vesu-extended-strategy/services/operationService.ts +34 -0
  48. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +77 -0
  49. package/src/strategies/vesu-extended-strategy/utils/constants.ts +49 -0
  50. package/src/strategies/vesu-extended-strategy/utils/helper.ts +376 -0
  51. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +1134 -0
  52. package/src/strategies/vesu-rebalance.tsx +16 -19
  53. package/src/utils/health-factor-math.ts +11 -5
@@ -5,7 +5,6 @@ import { IConfig } from "@/interfaces/common";
5
5
  import { Web3Number } from "@/dataTypes";
6
6
  import { PricerBase } from "./pricerBase";
7
7
  import { logger } from "@/utils/logger";
8
- import { AvnuWrapper } from "./avnu";
9
8
 
10
9
  export interface PriceInfo {
11
10
  price: number,
@@ -22,14 +21,13 @@ export class Pricer extends PricerBase {
22
21
 
23
22
  // code populates this map during runtime to determine which method to use for a given token
24
23
  // The method set will be the first one to try after first attempt
25
- protected methodToUse: {[tokenSymbol: string]: 'Ekubo' | 'Coinbase' | 'Coinmarketcap' | 'Avnu'} = {};
24
+ protected methodToUse: {[tokenSymbol: string]: 'Ekubo' | 'Coinbase' | 'Coinmarketcap'} = {};
26
25
 
27
26
  /**
28
27
  * TOKENA and TOKENB are the two token names to get price of TokenA in terms of TokenB
29
28
  */
30
- // ! switch to USDC (new) later
31
29
  protected PRICE_API = `https://api.coinbase.com/v2/prices/{{PRICER_KEY}}/buy`;
32
- protected EKUBO_API = 'https://prod-api-quoter.ekubo.org/23448594291968334/{{AMOUNT}}/{{TOKEN_ADDRESS}}/0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb'; // e.g. ETH/USDC
30
+ protected EKUBO_API = 'https://quoter-mainnet-api.ekubo.org/{{AMOUNT}}/{{TOKEN_ADDRESS}}/0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8'; // e.g. ETH/USDC
33
31
 
34
32
  constructor(config: IConfig, tokens: TokenInfo[], refreshInterval = 30000, staleTime = 60000) {
35
33
  super(config, tokens);
@@ -95,7 +93,7 @@ export class Pricer extends PricerBase {
95
93
  let retry = 0;
96
94
  while (retry < MAX_RETRIES) {
97
95
  try {
98
- if (token.symbol === 'USDT' || token.symbol === 'USDC') {
96
+ if (token.symbol === 'USDT') {
99
97
  this.prices[token.symbol] = {
100
98
  price: 1,
101
99
  timestamp: new Date()
@@ -176,15 +174,6 @@ export class Pricer extends PricerBase {
176
174
  console.warn(`Ekubo: price err [${token.symbol}]: `, Object.keys(error));
177
175
  // do nothing, try next
178
176
  }
179
- case 'Avnu':
180
- try {
181
- const result = await this._getAvnuPrice(token, new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals));
182
- this.methodToUse[token.symbol] = 'Avnu';
183
- return result;
184
- } catch (error: any) {
185
- console.warn(`Avnu: price err [${token.symbol}]: `, error.message);
186
- console.warn(`Avnu: price err [${token.symbol}]: `, Object.keys(error));
187
- }
188
177
  }
189
178
 
190
179
  // if methodToUse is the default one, pass Coinbase to try all from start
@@ -211,31 +200,7 @@ export class Pricer extends PricerBase {
211
200
  throw new Error("Not implemented");
212
201
  }
213
202
 
214
- async _getAvnuPrice(token: TokenInfo, amountIn = new Web3Number(1, token.decimals), retry = 0): Promise<number> {
215
- logger.verbose(`Getting price of ${token.symbol} using Ekubo, amountIn: ${amountIn.toWei()}`);
216
-
217
- const avnuWrapper = new AvnuWrapper();
218
- const usdcAddress = '0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb';
219
- const quote = await avnuWrapper.getQuotes(token.address.toString(), usdcAddress, amountIn.toWei(), '0x1');
220
- const multiplier = 1 / amountIn.toNumber();
221
- const outputUSDC = Number(Web3Number.fromWei(quote.buyAmount.toString(), 6).toFixed(6)) * multiplier;
222
- logger.verbose(`Avnu: ${token.symbol} -> USDC: ${outputUSDC}, retry: ${retry}`);
223
- if (outputUSDC === 0 && retry < 3) {
224
- // try again with a higher amount
225
- const amountIn = new Web3Number(100, token.decimals); // 100 unit of token
226
- return await this._getAvnuPrice(token, amountIn, retry + 1);
227
- }
228
-
229
- // if usdc depegs, it will not longer be 1 USD
230
- // so we need to get the price of USDC in USD
231
- // and then convert the outputUSDC to USD
232
- const usdcPrice = 1; // (await this.getPrice('USDC')).price;
233
- logger.verbose(`USDC Price: ${usdcPrice}`);
234
- return outputUSDC * usdcPrice;
235
- }
236
-
237
203
  async _getPriceEkubo(token: TokenInfo, amountIn = new Web3Number(1, token.decimals), retry = 0): Promise<number> {
238
- logger.verbose(`Getting price of ${token.symbol} using Ekubo, amountIn: ${amountIn.toWei()}`);
239
204
  const url = this.EKUBO_API.replace("{{TOKEN_ADDRESS}}", token.address.toString()).replace("{{AMOUNT}}", amountIn.toWei());
240
205
  const result = await axios.get(url);
241
206
  const data: any = result.data;
@@ -0,0 +1,202 @@
1
+ import { ContractAddr, Web3Number } from '../dataTypes';
2
+ import { TokenInfo, IConfig } from '../interfaces';
3
+ import { PricerBase } from './pricerBase';
4
+ import { LSTAPRService } from './lst-apr';
5
+ import { Midas } from './midas';
6
+ import { SingleTokenInfo } from '../strategies/base-strategy';
7
+ import { logger } from '../utils/logger';
8
+ import { Contract } from 'starknet';
9
+ import { uint256 } from 'starknet';
10
+ import ERC4626Abi from '../data/erc4626.abi.json';
11
+
12
+ /**
13
+ * TokenMarketData class that combines LST APR and Midas modules
14
+ * to provide unified APY, price, and TVL functions for tokens
15
+ */
16
+ export class TokenMarketData {
17
+ private pricer: PricerBase;
18
+ private config: IConfig;
19
+
20
+ constructor(pricer: PricerBase, config: IConfig) {
21
+ this.pricer = pricer;
22
+ this.config = config;
23
+ }
24
+
25
+ /**
26
+ * Get APY for a token
27
+ * - If it's an LST token, returns LST APY
28
+ * - If it's a Midas token, returns Midas APY
29
+ * - Otherwise returns 0
30
+ * @param tokenInfo The token to get APY for
31
+ * @returns APY in absolute terms (not percentage)
32
+ */
33
+ async getAPY(tokenInfo: TokenInfo): Promise<number> {
34
+ try {
35
+ // Check if it's an LST token
36
+ if (LSTAPRService.isLST(tokenInfo.address)) {
37
+ const underlying = LSTAPRService.getUnderlyingFromLST(tokenInfo.address);
38
+ const lstApr = await LSTAPRService.getLSTAPR(underlying.address);
39
+ logger.verbose(`TokenMarketData: LST APY for ${tokenInfo.symbol}: ${lstApr}`);
40
+ return lstApr;
41
+ }
42
+
43
+ // Check if it's a Midas token by trying to get symbol
44
+ if (Midas.isSupported(tokenInfo.address)) {
45
+ const midasApy = await Midas.getAPY(tokenInfo.address);
46
+ logger.verbose(`TokenMarketData: Midas APY for ${tokenInfo.symbol}: ${midasApy}`);
47
+ return midasApy;
48
+ }
49
+
50
+ // Default to 0 for unsupported tokens
51
+ logger.verbose(`TokenMarketData: No APY data available for ${tokenInfo.symbol}, returning 0`);
52
+ return 0;
53
+ } catch (error) {
54
+ logger.error(`TokenMarketData: Error getting APY for ${tokenInfo.symbol}:`, error);
55
+ return 0;
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Get price for a token using the pricer module
61
+ * @param tokenInfo The token to get price for
62
+ * @returns Price as a number
63
+ * @throws Error if price is 0 or unavailable
64
+ */
65
+ async getPrice(tokenInfo: TokenInfo): Promise<number> {
66
+ try {
67
+ const priceInfo = await this.pricer.getPrice(tokenInfo.symbol);
68
+
69
+ if (priceInfo.price === 0) {
70
+ throw new Error(`Price is 0 for token ${tokenInfo.symbol}`);
71
+ }
72
+
73
+ logger.verbose(`TokenMarketData: Price for ${tokenInfo.symbol}: ${priceInfo.price}`);
74
+ return priceInfo.price;
75
+ } catch (error) {
76
+ logger.error(`TokenMarketData: Error getting price for ${tokenInfo.symbol}:`, error);
77
+ throw new Error(`Failed to get price for ${tokenInfo.symbol}: ${error instanceof Error ? error.message : 'Unknown error'}`);
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Get true price for a token
83
+ * - For LST tokens: Uses convert_to_assets to get true exchange rate
84
+ * - For Midas tokens: Uses Midas price API
85
+ * - For other tokens: Falls back to regular pricer
86
+ * @param tokenInfo The token to get true price for
87
+ * @returns True price as a number
88
+ * @throws Error if price is 0 or unavailable
89
+ */
90
+ async getTruePrice(tokenInfo: TokenInfo): Promise<number> {
91
+ try {
92
+ // For LST tokens, use convert_to_assets
93
+ if (LSTAPRService.isLST(tokenInfo.address)) {
94
+ const lstABI = new Contract({
95
+ abi: ERC4626Abi,
96
+ address: tokenInfo.address.address,
97
+ providerOrAccount: this.config.provider
98
+ });
99
+
100
+ const price: any = await lstABI.call('convert_to_assets', [
101
+ uint256.bnToUint256((new Web3Number(1, tokenInfo.decimals)).toWei())
102
+ ]);
103
+ const exchangeRate = Number(uint256.uint256ToBN(price).toString()) / Math.pow(10, tokenInfo.decimals);
104
+
105
+ if (exchangeRate === 0) {
106
+ throw new Error(`True price is 0 for LST token ${tokenInfo.symbol}`);
107
+ }
108
+
109
+ logger.verbose(`TokenMarketData: LST true price for ${tokenInfo.symbol}: ${exchangeRate}`);
110
+ return exchangeRate;
111
+ }
112
+
113
+ // For Midas tokens, use Midas price API
114
+ if (Midas.isSupported(tokenInfo.address)) {
115
+ const midasPrice = await Midas.getPrice(tokenInfo.address);
116
+
117
+ if (midasPrice === 0) {
118
+ throw new Error(`True price is 0 for Midas token ${tokenInfo.symbol}`);
119
+ }
120
+
121
+ logger.verbose(`TokenMarketData: Midas true price for ${tokenInfo.symbol}: ${midasPrice}`);
122
+ return midasPrice;
123
+ }
124
+
125
+ // For other tokens, fall back to regular pricer
126
+ const price = await this.getPrice(tokenInfo);
127
+
128
+ if (price === 0) {
129
+ throw new Error(`True price is 0 for token ${tokenInfo.symbol}`);
130
+ }
131
+
132
+ logger.verbose(`TokenMarketData: Regular price for ${tokenInfo.symbol}: ${price}`);
133
+ return price;
134
+ } catch (error) {
135
+ logger.error(`TokenMarketData: Error getting true price for ${tokenInfo.symbol}:`, error);
136
+ throw new Error(`Failed to get true price for ${tokenInfo.symbol}: ${error instanceof Error ? error.message : 'Unknown error'}`);
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Get TVL for a token
142
+ * - If it's a Midas token, returns Midas TVL data
143
+ * - Otherwise returns 0
144
+ * @param tokenInfo The token to get TVL for
145
+ * @returns TVL as SingleTokenInfo or 0
146
+ */
147
+ async getTVL(tokenInfo: TokenInfo): Promise<SingleTokenInfo> {
148
+ // Check if it's a Midas token by trying to get TVL
149
+ if (Midas.isSupported(tokenInfo.address)) {
150
+ const midasTvl = await Midas.getTVL(tokenInfo.address);
151
+
152
+ // Handle different TVL response formats
153
+ let usdValue: number;
154
+ let nativeAmount: number;
155
+
156
+ if (typeof midasTvl === 'number') {
157
+ // Simple number format (e.g., mre7: 18193466)
158
+ usdValue = midasTvl;
159
+ nativeAmount = 0; // We don't have native amount in this format
160
+ } else if (typeof midasTvl === 'object' && 'usd' in midasTvl && 'native' in midasTvl) {
161
+ // Object format with usd and native (e.g., mre7btc: {usd: 998826, native: 9.3228})
162
+ usdValue = midasTvl.usd;
163
+ nativeAmount = midasTvl.native;
164
+ } else {
165
+ throw new Error(`Unexpected TVL format for ${tokenInfo.symbol}`);
166
+ }
167
+
168
+ const tvlInfo: SingleTokenInfo = {
169
+ tokenInfo,
170
+ amount: Web3Number.fromWei(nativeAmount, tokenInfo.decimals),
171
+ usdValue
172
+ };
173
+
174
+ logger.verbose(`TokenMarketData: Midas TVL for ${tokenInfo.symbol}: USD=${usdValue}, Native=${nativeAmount}`);
175
+ return tvlInfo;
176
+ }
177
+
178
+ return {
179
+ tokenInfo,
180
+ amount: Web3Number.fromWei('0', tokenInfo.decimals),
181
+ usdValue: 0
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Check if a token is supported for APY data
187
+ * @param tokenInfo The token to check
188
+ * @returns True if the token has APY data available
189
+ */
190
+ isAPYSupported(tokenInfo: TokenInfo): boolean {
191
+ return LSTAPRService.isLST(tokenInfo.address) || Midas.isSupported(tokenInfo.address);
192
+ }
193
+
194
+ /**
195
+ * Check if a token is supported for TVL data
196
+ * @param tokenInfo The token to check
197
+ * @returns True if the token has TVL data available
198
+ */
199
+ isTVLSupported(tokenInfo: TokenInfo): boolean {
200
+ return Midas.isSupported(tokenInfo.address);
201
+ }
202
+ }
@@ -4,7 +4,6 @@ import { readFileSync, existsSync, writeFileSync } from 'fs'
4
4
  import { IConfig } from '../interfaces';
5
5
  import { Store, getDefaultStoreConfig } from '../utils/store';
6
6
  import { add } from 'winston';
7
- import { logger } from '@/utils';
8
7
 
9
8
  function getContracts() {
10
9
  const PATH = './contracts.json'
@@ -208,47 +207,13 @@ async function executeTransactions(
208
207
  return tx;
209
208
  }
210
209
 
211
- async function myWaitForTransaction(
212
- transaction_hash: string,
213
- provider: RpcProvider,
214
- retry = 0
215
- ) {
216
- const MAX_RETRIES = 60;
217
- logger.verbose(`Waiting for transaction: ${transaction_hash}, retry: ${retry}`);
218
- try {
219
- const status = await provider.getTransactionStatus(transaction_hash);
220
- logger.verbose(`Transaction status: ${JSON.stringify(status.execution_status)}`);
221
- if (status.execution_status == TransactionExecutionStatus.SUCCEEDED) {
222
- return true;
223
- }
224
- if (status.execution_status == TransactionExecutionStatus.REVERTED) {
225
- throw new Error(`Transaction reverted: ${transaction_hash}`);
226
- }
227
- if (retry > MAX_RETRIES) {
228
- throw new Error(`Transaction not found: ${transaction_hash}`);
229
- }
230
- await new Promise(resolve => setTimeout(resolve, 1000));
231
- return myWaitForTransaction(transaction_hash, provider, retry + 1);
232
- } catch (error) {
233
- if (error instanceof Error && error.message.includes('Transaction reverted')) {
234
- throw new Error(`Transaction reverted: ${transaction_hash}`);
235
- }
236
- if (retry > MAX_RETRIES) {
237
- throw error;
238
- }
239
- await new Promise(resolve => setTimeout(resolve, 1000));
240
- return myWaitForTransaction(transaction_hash, provider, retry + 1);
241
- }
242
- }
243
-
244
210
  const Deployer = {
245
211
  getAccount,
246
212
  myDeclare,
247
213
  deployContract,
248
214
  prepareMultiDeployContracts,
249
215
  executeDeployCalls,
250
- executeTransactions,
251
- myWaitForTransaction
216
+ executeTransactions
252
217
  }
253
218
 
254
219
  export default Deployer;
@@ -48,7 +48,7 @@ export class AutoCompounderSTRK {
48
48
 
49
49
  /** Returns shares of user */
50
50
  async balanceOf(user: ContractAddr) {
51
- const result = await this.contract!.balanceOf(user.address);
51
+ const result = await this.contract!.balance_of(user.address);
52
52
  return Web3Number.fromWei(result.toString(), this.metadata.decimals);
53
53
  }
54
54
 
@@ -1,8 +1,8 @@
1
1
  import { ContractAddr, Web3Number } from "@/dataTypes";
2
2
  import { IConfig, TokenInfo, VaultPosition } from "@/interfaces";
3
- import { HarvestInfo } from "@/modules/harvests";
4
3
  import { CacheClass } from "@/utils/cacheClass";
5
4
  import { Call } from "starknet";
5
+ import { PositionInfo } from "./universal-adapters";
6
6
 
7
7
  export interface SingleActionAmount {
8
8
  tokenInfo: TokenInfo,
@@ -13,6 +13,11 @@ export interface SingleTokenInfo extends SingleActionAmount {
13
13
  usdValue: number
14
14
  };
15
15
 
16
+ export interface APYInfo {
17
+ net: number;
18
+ splits: { apy: number; id: string; }[];
19
+ };
20
+
16
21
  export interface DualActionAmount {
17
22
  token0: SingleActionAmount,
18
23
  token1: SingleActionAmount
@@ -57,7 +62,19 @@ export class BaseStrategy<TVLInfo, ActionInfo> extends CacheClass {
57
62
  throw new Error("Not implemented");
58
63
  }
59
64
 
60
- async getPendingRewards(): Promise<HarvestInfo[]> {
61
- return [];
65
+ async getUnusedBalance(): Promise<SingleTokenInfo> {
66
+ throw new Error("Not implemented");
67
+ }
68
+
69
+ async netAPY(): Promise<APYInfo> {
70
+ throw new Error("Not implemented");
71
+ }
72
+
73
+ async getAUM(): Promise<{net: SingleTokenInfo, prevAum: Web3Number, splits: PositionInfo[]}> {
74
+ throw new Error("Not implemented");
75
+ }
76
+
77
+ async getHealthFactors(): Promise<number[]> {
78
+ throw new Error("Not implemented");
62
79
  }
63
80
  }