@strkfarm/sdk 2.0.0-dev.4 → 2.0.0-dev.41

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