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

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 (79) hide show
  1. package/dist/cli.js +190 -36
  2. package/dist/cli.mjs +188 -34
  3. package/dist/index.browser.global.js +119400 -92821
  4. package/dist/index.browser.mjs +13293 -11146
  5. package/dist/index.d.ts +2281 -1938
  6. package/dist/index.js +13532 -11179
  7. package/dist/index.mjs +14165 -11836
  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 +279 -233
  19. package/src/index.browser.ts +2 -1
  20. package/src/interfaces/common.tsx +228 -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 +80 -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 +156 -15
  31. package/src/modules/pricer-lst.ts +1 -1
  32. package/src/modules/pricer.ts +107 -41
  33. package/src/modules/pricerBase.ts +2 -1
  34. package/src/modules/zkLend.ts +3 -2
  35. package/src/node/deployer.ts +36 -1
  36. package/src/node/pricer-redis.ts +3 -1
  37. package/src/strategies/base-strategy.ts +168 -16
  38. package/src/strategies/constants.ts +8 -3
  39. package/src/strategies/ekubo-cl-vault.tsx +1048 -355
  40. package/src/strategies/factory.ts +199 -0
  41. package/src/strategies/index.ts +5 -3
  42. package/src/strategies/registry.ts +262 -0
  43. package/src/strategies/sensei.ts +354 -10
  44. package/src/strategies/svk-strategy.ts +292 -31
  45. package/src/strategies/token-boosted-xstrk-carry-strategy.tsx +1261 -0
  46. package/src/strategies/types.ts +4 -0
  47. package/src/strategies/universal-adapters/adapter-utils.ts +4 -1
  48. package/src/strategies/universal-adapters/avnu-adapter.ts +196 -272
  49. package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
  50. package/src/strategies/universal-adapters/common-adapter.ts +206 -203
  51. package/src/strategies/universal-adapters/index.ts +10 -8
  52. package/src/strategies/universal-adapters/svk-troves-adapter.ts +511 -0
  53. package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
  54. package/src/strategies/universal-adapters/vesu-adapter.ts +120 -82
  55. package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +525 -0
  56. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +866 -860
  57. package/src/strategies/universal-adapters/vesu-position-common.ts +258 -0
  58. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
  59. package/src/strategies/universal-lst-muliplier-strategy.tsx +895 -416
  60. package/src/strategies/universal-strategy.tsx +1332 -1173
  61. package/src/strategies/vesu-rebalance.tsx +254 -153
  62. package/src/strategies/yoloVault.ts +1096 -0
  63. package/src/utils/cacheClass.ts +11 -2
  64. package/src/utils/health-factor-math.ts +33 -1
  65. package/src/utils/index.ts +3 -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/modules/ExtendedWrapperSDk/index.ts +0 -62
  71. package/src/modules/ExtendedWrapperSDk/types.ts +0 -311
  72. package/src/modules/ExtendedWrapperSDk/wrapper.ts +0 -395
  73. package/src/strategies/universal-adapters/extended-adapter.ts +0 -662
  74. package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
  75. package/src/strategies/vesu-extended-strategy/services/operationService.ts +0 -34
  76. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +0 -77
  77. package/src/strategies/vesu-extended-strategy/utils/constants.ts +0 -49
  78. package/src/strategies/vesu-extended-strategy/utils/helper.ts +0 -372
  79. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +0 -1140
@@ -1,9 +1,9 @@
1
1
  import { ContractAddr, Web3Number } from "@/dataTypes";
2
- import { IConfig, IStrategyMetadata, TokenInfo, VaultPosition } from "@/interfaces";
2
+ import { IConfig, IStrategyMetadata, Protocols, TokenInfo, VaultPosition } from "@/interfaces";
3
3
  import { PricerBase } from "@/modules/pricerBase";
4
4
  import { ERC20 } from "@/modules";
5
- import { BaseStrategy, SingleActionAmount, SingleTokenInfo } from "./base-strategy";
6
- import { Call, Contract, num } from "starknet";
5
+ import { BaseStrategy, SingleActionAmount, SingleTokenInfo, UserPositionCard, UserPositionCardsInput } from "./base-strategy";
6
+ import { BlockIdentifier, Call, Contract, num, uint256 } from "starknet";
7
7
  import { assert, LeafData, logger, StandardMerkleTree } from "@/utils";
8
8
  import { UniversalStrategySettings } from "./universal-strategy";
9
9
  import { UNIVERSAL_MANAGE_IDS } from "./universal-strategy";
@@ -15,9 +15,9 @@ import { ManageCall, PositionInfo } from "./universal-adapters";
15
15
  * Base class for all SVK (Starknet Vault Kit) strategies.
16
16
  * Contains common functions that are shared across all SVK strategies.
17
17
  */
18
- export abstract class SVKStrategy<S extends UniversalStrategySettings>
18
+ export abstract class SVKStrategy<S extends UniversalStrategySettings>
19
19
  extends BaseStrategy<SingleTokenInfo, SingleActionAmount> {
20
-
20
+
21
21
  /** Contract address of the strategy */
22
22
  readonly address: ContractAddr;
23
23
  /** Pricer instance for token price calculations */
@@ -36,13 +36,13 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
36
36
  this.pricer = pricer;
37
37
  this.metadata = metadata;
38
38
  this.address = metadata.address;
39
-
39
+
40
40
  this.contract = new Contract({
41
41
  abi: UniversalVaultAbi,
42
42
  address: this.address.address,
43
43
  providerOrAccount: this.config.provider
44
44
  });
45
-
45
+
46
46
  this.managerContract = new Contract({
47
47
  abi: ManagerAbi,
48
48
  address: this.metadata.additionalInfo.manager.address,
@@ -57,14 +57,81 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
57
57
  return this.metadata.depositTokens[0];
58
58
  }
59
59
 
60
+ async depositCall(amountInfo: SingleActionAmount, receiver: ContractAddr): Promise<Call[]> {
61
+ // Technically its not erc4626 abi, but we just need approve call
62
+ // so, its ok to use it
63
+ assert(
64
+ amountInfo.tokenInfo.address.eq(this.asset().address),
65
+ "Deposit token mismatch"
66
+ );
67
+ const assetContract = new Contract({
68
+ abi: UniversalVaultAbi,
69
+ address: this.asset().address.address,
70
+ providerOrAccount: this.config.provider
71
+ });
72
+ const call1 = assetContract.populate("approve", [
73
+ this.address.address,
74
+ uint256.bnToUint256(amountInfo.amount.toWei())
75
+ ]);
76
+ const call2 = this.contract.populate("deposit", [
77
+ uint256.bnToUint256(amountInfo.amount.toWei()),
78
+ receiver.address
79
+ ]);
80
+ return [call1, call2];
81
+ }
82
+
83
+ async withdrawCall(amountInfo: SingleActionAmount, receiver: ContractAddr, owner: ContractAddr, isMaxWithdraw: boolean = false): Promise<Call[]> {
84
+ assert(
85
+ amountInfo.tokenInfo.address.eq(this.asset().address),
86
+ "Withdraw token mismatch"
87
+ );
88
+ const shares = isMaxWithdraw
89
+ ? await this.contract.call("balanceOf", [receiver.address])
90
+ : await this.contract.call('convert_to_shares', [uint256.bnToUint256(amountInfo.amount.toWei())]);
91
+ const call = this.contract.populate("request_redeem", [
92
+ uint256.bnToUint256(shares.toString()),
93
+ receiver.address,
94
+ owner.address
95
+ ]);
96
+ return [call];
97
+ }
98
+
99
+ async getUserTVL(user: ContractAddr, blockIdentifier: BlockIdentifier = "latest"): Promise<SingleTokenInfo> {
100
+ const shares: any = await this.contract.call("balanceOf", [user.address], { blockIdentifier });
101
+ const assets: any = await this.contract.call(
102
+ "convert_to_assets",
103
+ [uint256.bnToUint256(shares)],
104
+ { blockIdentifier }
105
+ );
106
+ const amount = Web3Number.fromWei(
107
+ assets.toString(),
108
+ this.metadata.depositTokens[0].decimals
109
+ );
110
+
111
+ const blockNumber = typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint"
112
+ ? Number(blockIdentifier)
113
+ : undefined;
114
+
115
+ const price = await this.pricer.getPrice(
116
+ this.metadata.depositTokens[0].symbol,
117
+ blockNumber
118
+ );
119
+ const usdValue = Number(amount.toFixed(6)) * price.price;
120
+ return {
121
+ tokenInfo: this.asset(),
122
+ amount,
123
+ usdValue
124
+ };
125
+ }
126
+
60
127
  /**
61
128
  * Returns the unused balance in the vault allocator.
62
129
  * Note: This function is common for any SVK strategy.
63
130
  */
64
131
  async getUnusedBalance(): Promise<SingleTokenInfo> {
65
132
  const balance = await (new ERC20(this.config)).balanceOf(
66
- this.asset().address,
67
- this.metadata.additionalInfo.vaultAllocator,
133
+ this.asset().address,
134
+ this.metadata.additionalInfo.vaultAllocator,
68
135
  this.asset().decimals
69
136
  );
70
137
  const price = await this.pricer.getPrice(this.metadata.depositTokens[0].symbol);
@@ -76,6 +143,24 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
76
143
  };
77
144
  }
78
145
 
146
+ /**
147
+ * Builds a manage call from an adapter's proof tree.
148
+ * DRY helper for the repeated getProofs → getManageCall pattern.
149
+ */
150
+ protected async buildManageCallFromAdapter(
151
+ adapter: { getProofs: (isDeposit: boolean, tree: any) => any },
152
+ isDeposit: boolean,
153
+ amount: Web3Number,
154
+ additionalParams?: Record<string, any>,
155
+ ): Promise<Call> {
156
+ const proofsInfo = adapter.getProofs(isDeposit, this.getMerkleTree());
157
+ const manageCalls = await proofsInfo.callConstructor({ amount, ...additionalParams });
158
+ return this.getManageCall(
159
+ this.getProofGroupsForManageCalls(manageCalls),
160
+ manageCalls,
161
+ );
162
+ }
163
+
79
164
  /**
80
165
  * Bridges liquidity from the vault allocator back to the vault.
81
166
  * Note: This function is common for any SVK strategy.
@@ -85,37 +170,54 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
85
170
  const approveAdapter = this.metadata.additionalInfo.leafAdapters.find(
86
171
  adapter => adapter().leaves.find(leaf => leaf.readableId === UNIVERSAL_MANAGE_IDS.APPROVE_BRING_LIQUIDITY)
87
172
  );
88
-
173
+
89
174
  if (!approveAdapter) {
90
175
  throw new Error(`${this.getTag()}::getBringLiquidityCall: approve adapter not found`);
91
176
  }
92
-
177
+
93
178
  // Find bring liquidity leaf adapter
94
179
  const bringLiquidityAdapter = this.metadata.additionalInfo.leafAdapters.find(
95
180
  adapter => adapter().leaves.find(leaf => leaf.readableId === UNIVERSAL_MANAGE_IDS.BRING_LIQUIDITY)
96
181
  );
97
-
182
+
98
183
  if (!bringLiquidityAdapter) {
99
184
  throw new Error(`${this.getTag()}::getBringLiquidityCall: bring liquidity adapter not found`);
100
185
  }
101
-
102
- // Get proofs
103
- const tree = this.getMerkleTree();
104
- const proofGroups: string[][] = [];
105
- for (const [i, v] of tree.entries()) {
106
- if (v.readableId === UNIVERSAL_MANAGE_IDS.APPROVE_BRING_LIQUIDITY ||
107
- v.readableId === UNIVERSAL_MANAGE_IDS.BRING_LIQUIDITY) {
108
- proofGroups.push(tree.getProof(i));
109
- }
110
- }
111
-
186
+
112
187
  // Construct calls
113
188
  logger.verbose("approve adapter amount", params.amount);
114
189
  const approveCalls = await approveAdapter().callConstructor({ amount: params.amount });
115
190
  const bringLiquidityCalls = await bringLiquidityAdapter().callConstructor({ amount: params.amount });
116
-
191
+ const manageCalls = [...approveCalls, ...bringLiquidityCalls];
192
+
117
193
  // Combine into final call
118
- return this.getManageCall(proofGroups, [...approveCalls, ...bringLiquidityCalls]);
194
+ return this.getManageCall(this.getProofGroupsForManageCalls(manageCalls), manageCalls);
195
+ }
196
+
197
+ /**
198
+ * Resolves ordered merkle proofs from emitted manage calls.
199
+ * This ensures only runtime-required proofs are passed to manager calls.
200
+ */
201
+ protected getProofGroupsForManageCalls(manageCalls: ManageCall[]): string[][] {
202
+ const tree = this.getMerkleTree();
203
+ const proofByReadableId = new Map<string, string[]>();
204
+ for (const [i, v] of tree.entries()) {
205
+ if (proofByReadableId.has(v.readableId)) {
206
+ throw new Error(`Duplicate readableId found in merkle tree: ${v.readableId}`);
207
+ }
208
+ proofByReadableId.set(v.readableId, tree.getProof(i));
209
+ }
210
+
211
+ return manageCalls.map((manageCall, index) => {
212
+ if (!manageCall.proofReadableId) {
213
+ throw new Error(`Missing proofReadableId for manage call at index ${index}`);
214
+ }
215
+ const proof = proofByReadableId.get(manageCall.proofReadableId);
216
+ if (!proof) {
217
+ throw new Error(`Proof not found for readableId: ${manageCall.proofReadableId}`);
218
+ }
219
+ return proof;
220
+ });
119
221
  }
120
222
 
121
223
  /**
@@ -157,10 +259,10 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
157
259
  */
158
260
  getManageCall(proofGroups: string[][], manageCalls: ManageCall[]): Call {
159
261
  assert(
160
- proofGroups.length == manageCalls.length,
262
+ proofGroups.length == manageCalls.length,
161
263
  `Proof IDs and Manage Calls length mismatch: ${proofGroups.length} != ${manageCalls.length}`
162
264
  );
163
-
265
+
164
266
  return this.managerContract.populate('manage_vault_with_merkle_verification', {
165
267
  proofs: proofGroups.map(group => group),
166
268
  decoder_and_sanitizers: manageCalls.map(call => call.sanitizer.address),
@@ -176,7 +278,7 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
176
278
  */
177
279
  getSetManagerCall(strategist: ContractAddr, root = this.getMerkleRoot()): Call {
178
280
  return this.managerContract.populate('set_manage_root', [
179
- strategist.address,
281
+ strategist.address,
180
282
  num.getHexString(root)
181
283
  ]);
182
284
  }
@@ -194,7 +296,19 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
194
296
  */
195
297
  async getVaultPositions(): Promise<VaultPosition[]> {
196
298
  const positions = await Promise.all(
197
- this.metadata.additionalInfo.adapters.map(adapter => adapter.adapter.getPositions())
299
+ [
300
+ ...this.metadata.additionalInfo.adapters.map(adapter => adapter.adapter.getPositions()),
301
+ (async () => {
302
+ const unused = await this.getUnusedBalance();
303
+ return {
304
+ amount: unused.amount,
305
+ usdValue: unused.usdValue,
306
+ remarks: "Unused Balance",
307
+ tokenInfo: this.asset(),
308
+ protocol: Protocols.NONE
309
+ };
310
+ })()
311
+ ]
198
312
  )
199
313
  return positions.flat().map((position) => ({
200
314
  amount: position.amount,
@@ -222,10 +336,151 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
222
336
  const netAPY = weightedAPYs / totalHoldingsUSDValue;
223
337
  return {
224
338
  net: netAPY,
225
- splits: allPositions.map(p => ({apy: p.apy.apy, id: p.remarks ?? ''}))
339
+ splits: allPositions.map(p => ({ apy: p.apy.apy, id: p.remarks ?? '' }))
226
340
  };
227
341
  }
228
342
 
343
+ async getTVL(): Promise<SingleTokenInfo> {
344
+ const tvl = await this.contract.call('total_assets', []) as bigint;
345
+ const amount = Web3Number.fromWei(tvl.toString(), this.asset().decimals);
346
+ const price = await this.pricer.getPrice(this.asset().symbol);
347
+ const usdValue = Number(amount.toFixed(6)) * price.price;
348
+ return {
349
+ tokenInfo: this.asset(),
350
+ amount,
351
+ usdValue
352
+ };
353
+ }
354
+
355
+ async getUserRealizedAPY(
356
+ blockIdentifier: BlockIdentifier = "latest",
357
+ sinceBlocks = 600000
358
+ ): Promise<number> {
359
+ logger.verbose(
360
+ `${this.getTag()}: getUserRealizedAPY => starting with blockIdentifier=${blockIdentifier}, sinceBlocks=${sinceBlocks}`
361
+ );
362
+
363
+ const blockNow =
364
+ typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint"
365
+ ? Number(blockIdentifier)
366
+ : (await this.config.provider.getBlockLatestAccepted()).block_number;
367
+ const blockNowTime =
368
+ typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint"
369
+ ? (await this.config.provider.getBlockWithTxs(blockIdentifier)).timestamp
370
+ : new Date().getTime() / 1000;
371
+
372
+ const blockBefore = Math.max(
373
+ blockNow - sinceBlocks,
374
+ this.metadata.launchBlock
375
+ );
376
+
377
+ const assetsNowRaw: bigint = await this.contract.call("total_assets", [], {
378
+ blockIdentifier,
379
+ }) as bigint;
380
+ const amountNow = Web3Number.fromWei(
381
+ assetsNowRaw.toString(),
382
+ this.metadata.depositTokens[0].decimals
383
+ );
384
+
385
+ const supplyNowRaw: bigint = await this.contract.call("total_supply", [], {
386
+ blockIdentifier,
387
+ }) as bigint;
388
+ const supplyNow = Web3Number.fromWei(supplyNowRaw.toString(), 18);
389
+
390
+ const assetsBeforeRaw: bigint = await this.contract.call(
391
+ "total_assets",
392
+ [],
393
+ { blockIdentifier: blockBefore }
394
+ ) as bigint;
395
+ const amountBefore = Web3Number.fromWei(
396
+ assetsBeforeRaw.toString(),
397
+ this.metadata.depositTokens[0].decimals
398
+ );
399
+
400
+ const supplyBeforeRaw: bigint = await this.contract.call(
401
+ "total_supply",
402
+ [],
403
+ { blockIdentifier: blockBefore }
404
+ ) as bigint;
405
+ const supplyBefore = Web3Number.fromWei(supplyBeforeRaw.toString(), 18);
406
+
407
+ const blockBeforeInfo = await this.config.provider.getBlockWithTxs(
408
+ blockBefore
409
+ );
410
+
411
+ const assetsPerShareNow = amountNow
412
+ .multipliedBy(1e18)
413
+ .dividedBy(supplyNow.toString());
414
+
415
+ const assetsPerShareBf = amountBefore
416
+ .multipliedBy(1e18)
417
+ .dividedBy(supplyBefore.toString());
418
+
419
+ const timeDiffSeconds = blockNowTime - blockBeforeInfo.timestamp;
420
+
421
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsNow: ${amountNow.toString()}`);
422
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsBefore: ${amountBefore.toString()}`);
423
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsPerShareNow: ${assetsPerShareNow.toString()}`);
424
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsPerShareBf: ${assetsPerShareBf.toString()}`);
425
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] Supply before: ${supplyBefore.toString()}`);
426
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] Supply now: ${supplyNow.toString()}`);
427
+ logger.verbose(`${this.getTag()} [getUserRealizedAPY] Time diff in seconds: ${timeDiffSeconds}`);
428
+
429
+ const apyForGivenBlocks =
430
+ Number(
431
+ assetsPerShareNow
432
+ .minus(assetsPerShareBf)
433
+ .multipliedBy(10000)
434
+ .dividedBy(assetsPerShareBf)
435
+ ) / 10000;
436
+
437
+ return (apyForGivenBlocks * (365 * 24 * 3600)) / timeDiffSeconds;
438
+ }
439
+
440
+ async getUserPositionCards(input: UserPositionCardsInput): Promise<UserPositionCard[]> {
441
+ const { user, investmentFlows = [] } = input;
442
+ const [userTVL] = await Promise.all([
443
+ this.getUserTVL(user),
444
+ ]);
445
+ const cards: UserPositionCard[] = [
446
+ {
447
+ title: "Your Holdings",
448
+ tooltip: "Your Holdings",
449
+ value: this.formatTokenAmountForCard(userTVL.amount, userTVL.tokenInfo),
450
+ subValue: `≈ ${this.formatUSDForCard(userTVL.usdValue)}`,
451
+ subValueColor: "positive",
452
+ },
453
+ ];
454
+
455
+ let lifetimeAmount = userTVL.amount.multipliedBy(0);
456
+ let lifetimeTokenInfo = userTVL.tokenInfo;
457
+ let lifetimeUsdValue = 0;
458
+ if (investmentFlows.length > 0) {
459
+ try {
460
+ const earningsResult = this.getLifetimeEarnings(userTVL, investmentFlows);
461
+ lifetimeAmount = earningsResult.lifetimeEarnings;
462
+ lifetimeTokenInfo = earningsResult.tokenInfo.tokenInfo;
463
+ const userAmount = userTVL.amount.toNumber();
464
+ if (Number.isFinite(userAmount) && userAmount > 0) {
465
+ const pricePerToken = userTVL.usdValue / userAmount;
466
+ lifetimeUsdValue = lifetimeAmount.toNumber() * pricePerToken;
467
+ }
468
+ } catch (error) {
469
+ logger.warn(`${this.getTag()}::getUserPositionCards lifetime earnings fallback`, error);
470
+ }
471
+ }
472
+
473
+ cards.push({
474
+ title: "Lifetime Earnings",
475
+ tooltip: "Lifetime Earnings",
476
+ value: this.formatTokenAmountForCard(lifetimeAmount, lifetimeTokenInfo),
477
+ subValue: `≈ ${this.formatUSDForCard(lifetimeUsdValue)}`,
478
+ subValueColor: this.getSubValueColorFromSignedNumber(lifetimeUsdValue),
479
+ });
480
+
481
+ return cards;
482
+ }
483
+
229
484
  async getPrevAUM() {
230
485
  const currentAUM: bigint = await this.contract.call('aum', []) as bigint;
231
486
  const prevAum = Web3Number.fromWei(currentAUM.toString(), this.asset().decimals);
@@ -243,5 +498,11 @@ export abstract class SVKStrategy<S extends UniversalStrategySettings>
243
498
  return maxWithdrawables;
244
499
  }
245
500
 
246
- }
247
501
 
502
+ async getMaxTVL(): Promise<Web3Number> {
503
+ const lstToken = this.asset();
504
+ const depositLimit: any = await this.contract.call("get_deposit_limit", []);
505
+ const limitBN = uint256.uint256ToBN(depositLimit);
506
+ return Web3Number.fromWei(limitBN.toString(), lstToken.decimals);
507
+ }
508
+ }