@strkfarm/sdk 1.0.58 → 1.0.59

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strkfarm/sdk",
3
- "version": "1.0.58",
3
+ "version": "1.0.59",
4
4
  "description": "STRKFarm TS SDK (Meant for our internal use, but feel free to use it)",
5
5
  "typings": "dist/index.d.ts",
6
6
  "types": "dist/index.d.ts",
@@ -54,11 +54,12 @@
54
54
  "@types/react": "^19.1.2",
55
55
  "axios": "^1.7.2",
56
56
  "react": "19.1.0",
57
- "starknet": "^6.11.0"
57
+ "starknet": "7.6.4"
58
58
  },
59
59
  "dependencies": {
60
60
  "@avnu/avnu-sdk": "3.0.2",
61
61
  "@ericnordelo/strk-merkle-tree": "^1.0.0",
62
+ "@scure/starknet": "^2.0.0",
62
63
  "bignumber.js": "4.0.4",
63
64
  "browser-assert": "^1.2.1",
64
65
  "chalk": "^4.1.2",
@@ -1,5 +1,5 @@
1
1
  import { ContractAddr, Web3Number } from "@/dataTypes";
2
- import { BlockIdentifier, RpcProvider } from "starknet";
2
+ import { BlockIdentifier, constants, RpcProvider } from "starknet";
3
3
  import React, { ReactNode } from "react";
4
4
 
5
5
  export enum RiskType {
@@ -107,12 +107,14 @@ export interface IInvestmentFlow {
107
107
 
108
108
  export function getMainnetConfig(
109
109
  rpcUrl: string = 'https://starknet-mainnet.public.blastapi.io',
110
- blockIdentifier: BlockIdentifier = "pending"
110
+ blockIdentifier: BlockIdentifier = "pending",
111
+ // specVersion = constants.SupportedRpcVersion.v0_8_1
111
112
  ): IConfig {
112
113
  return {
113
114
  provider: new RpcProvider({
114
115
  nodeUrl: rpcUrl,
115
- blockIdentifier: blockIdentifier
116
+ blockIdentifier: blockIdentifier,
117
+ // specVersion
116
118
  }),
117
119
  stage: "production",
118
120
  network: Network.mainnet
@@ -96,7 +96,7 @@ async function deployContract(contract_name: string, classHash: string, construc
96
96
  classHash,
97
97
  constructorCalldata: constructorData,
98
98
  })
99
- console.log("Deploy fee", contract_name, Number(fee.suggestedMaxFee) / 10 ** 18, 'ETH')
99
+ console.log("Deploy fee", contract_name, Number(fee.overall_fee) / 10 ** 18, 'ETH')
100
100
 
101
101
  const tx = await acc.deployContract({
102
102
  classHash,
@@ -22,6 +22,10 @@ export interface UniversalStrategySettings {
22
22
  minHealthFactor: number
23
23
  }
24
24
 
25
+ export enum AUMTypes {
26
+ FINALISED = 'finalised',
27
+ DEFISPRING = 'defispring'
28
+ }
25
29
 
26
30
  export class UniversalStrategy<
27
31
  S extends UniversalStrategySettings
@@ -141,6 +145,20 @@ export class UniversalStrategy<
141
145
  return [call1, call2];
142
146
  }
143
147
 
148
+ async withdrawCall(amountInfo: SingleActionAmount, receiver: ContractAddr, owner: ContractAddr): Promise<Call[]> {
149
+ assert(
150
+ amountInfo.tokenInfo.address.eq(this.asset().address),
151
+ "Withdraw token mismatch"
152
+ );
153
+ const shares = await this.contract.call('convert_to_shares', [uint256.bnToUint256(amountInfo.amount.toWei())]);
154
+ const call = this.contract.populate("request_redeem", [
155
+ uint256.bnToUint256(shares.toString()),
156
+ receiver.address,
157
+ owner.address
158
+ ]);
159
+ return [call];
160
+ }
161
+
144
162
  /**
145
163
  * Calculates the Total Value Locked (TVL) for a specific user.
146
164
  * @param user - Address of the user
@@ -192,14 +210,22 @@ export class UniversalStrategy<
192
210
  const debt2APY = Number(debtAsset2.borrowApr.value) / 1e18;
193
211
 
194
212
  const positions = await this.getVaultPositions();
213
+ logger.verbose(`${this.metadata.name}::netAPY: positions: ${JSON.stringify(positions)}`);
214
+ if (positions.every(p => p.amount.isZero())) {
215
+ return { net: 0, splits: [{
216
+ apy: 0, id: 'base'
217
+ }, {
218
+ apy: 0, id: 'defispring'
219
+ }]};
220
+ }
195
221
  const weights = positions.map((p, index) => p.usdValue * (index % 2 == 0 ? 1 : -1));
196
222
  const baseAPYs = [collateral1APY, debt1APY, collateral2APY, debt2APY];
197
223
  assert(positions.length == baseAPYs.length, "Positions and APYs length mismatch");
198
224
  const rewardAPYs = [Number(collateralAsset1.defiSpringSupplyApr.value) / 1e18, 0, Number(collateralAsset2.defiSpringSupplyApr.value) / 1e18, 0];
199
225
  const baseAPY = this.computeAPY(baseAPYs, weights);
200
226
  const rewardAPY = this.computeAPY(rewardAPYs, weights);
201
- const apys = [...baseAPYs, ...rewardAPYs];
202
227
  const netAPY = baseAPY + rewardAPY;
228
+ logger.verbose(`${this.metadata.name}::netAPY: net: ${netAPY}, baseAPY: ${baseAPY}, rewardAPY: ${rewardAPY}`);
203
229
  return { net: netAPY, splits: [{
204
230
  apy: baseAPY, id: 'base'
205
231
  }, {
@@ -235,6 +261,17 @@ export class UniversalStrategy<
235
261
  };
236
262
  }
237
263
 
264
+ async getUnusedBalance(): Promise<SingleTokenInfo> {
265
+ const balance = await (new ERC20(this.config)).balanceOf(this.asset().address, this.metadata.additionalInfo.vaultAllocator, this.asset().decimals);
266
+ const price = await this.pricer.getPrice(this.metadata.depositTokens[0].symbol);
267
+ const usdValue = Number(balance.toFixed(6)) * price.price;
268
+ return {
269
+ tokenInfo: this.asset(),
270
+ amount: balance,
271
+ usdValue
272
+ };
273
+ }
274
+
238
275
  async getAUM(): Promise<{net: SingleTokenInfo, prevAum: Web3Number, splits: {id: string, aum: Web3Number}[]}> {
239
276
  const currentAUM: bigint = await this.contract.call('aum', []) as bigint;
240
277
  const lastReportTime = await this.contract.call('last_report_timestamp', []);
@@ -246,13 +283,29 @@ export class UniversalStrategy<
246
283
  const leg1AUM = await vesuAdapter1.getPositions(this.config);
247
284
  const leg2AUM = await vesuAdapter2.getPositions(this.config);
248
285
 
249
- const balance = await (new ERC20(this.config)).balanceOf(this.asset().address, this.metadata.additionalInfo.vaultAllocator, this.asset().decimals);
250
- logger.verbose(`${this.getTag()} unused balance: ${balance}`);
286
+ const balance = await this.getUnusedBalance();
287
+ logger.verbose(`${this.getTag()} unused balance: ${balance.amount.toNumber()}`);
251
288
 
252
- const aumToken = leg1AUM[0].amount
289
+ const vesuAum = leg1AUM[0].amount
253
290
  .plus(leg2AUM[0].usdValue / token1Price.price)
254
291
  .minus(leg1AUM[1].usdValue / token1Price.price)
255
- .minus(leg2AUM[1].amount).plus(balance);
292
+ .minus(leg2AUM[1].amount);
293
+
294
+ const zeroAmt = Web3Number.fromWei('0', this.asset().decimals);
295
+ const net = {
296
+ tokenInfo: this.asset(),
297
+ amount: zeroAmt,
298
+ usdValue: 0
299
+ };
300
+ const prevAum = Web3Number.fromWei(currentAUM.toString(), this.asset().decimals);
301
+ if (vesuAum.isZero()) {
302
+ return { net, splits: [{
303
+ aum: zeroAmt, id: AUMTypes.FINALISED
304
+ }, {
305
+ aum: zeroAmt, id: AUMTypes.DEFISPRING
306
+ }], prevAum};
307
+ }
308
+ const aumToken = vesuAum.plus(balance.amount);
256
309
  logger.verbose(`${this.getTag()} Actual AUM: ${aumToken}`);
257
310
 
258
311
  // calculate estimated growth from strk rewards
@@ -262,7 +315,6 @@ export class UniversalStrategy<
262
315
 
263
316
  const timeDiff = (Math.round(Date.now() / 1000) - Number(lastReportTime));
264
317
  const growthRate = timeDiff * defispringAPY / (365 * 24 * 60 * 60);
265
- const prevAum = Web3Number.fromWei(currentAUM.toString(), this.asset().decimals);
266
318
  const rewardAssets = prevAum.multipliedBy(growthRate);
267
319
  logger.verbose(`${this.getTag()} DefiSpring AUM time difference: ${timeDiff}`);
268
320
  logger.verbose(`${this.getTag()} Current AUM: ${currentAUM}`);
@@ -272,16 +324,13 @@ export class UniversalStrategy<
272
324
  const newAUM = aumToken.plus(rewardAssets);
273
325
  logger.verbose(`${this.getTag()} New AUM: ${newAUM}`);
274
326
 
275
- const net = {
276
- tokenInfo: this.asset(),
277
- amount: newAUM,
278
- usdValue: newAUM.multipliedBy(token1Price.price).toNumber()
279
- };
327
+ net.amount = newAUM;
328
+ net.usdValue = newAUM.multipliedBy(token1Price.price).toNumber();
280
329
  const splits = [{
281
- id: 'finalised',
330
+ id: AUMTypes.FINALISED,
282
331
  aum: aumToken
283
332
  }, {
284
- id: 'defispring',
333
+ id: AUMTypes.DEFISPRING,
285
334
  aum: rewardAssets
286
335
  }];
287
336
  return { net, splits, prevAum };
@@ -655,6 +704,39 @@ const wbtcVaultSettings: UniversalStrategySettings = {
655
704
  minHealthFactor: 1.25
656
705
  }
657
706
 
707
+ const ethVaultSettings: UniversalStrategySettings = {
708
+ manager: ContractAddr.from('0x494888b37206616bd09d759dcda61e5118470b9aa7f58fb84f21c778a7b8f97'),
709
+ vaultAllocator: ContractAddr.from('0x4acc0ad6bea58cb578d60ff7c31f06f44369a7a9a7bbfffe4701f143e427bd'),
710
+ redeemRequestNFT: ContractAddr.from('0x2e6cd71e5060a254d4db00655e420db7bf89da7755bb0d5f922e2f00c76ac49'),
711
+ aumOracle: ContractAddr.from("0x4b747f2e75c057bed9aa2ce46fbdc2159dc684c15bd32d4f95983a6ecf39a05"),
712
+ leafAdapters: [],
713
+ adapters: [],
714
+ targetHealthFactor: 1.3,
715
+ minHealthFactor: 1.25
716
+ }
717
+
718
+ const strkVaultSettings: UniversalStrategySettings = {
719
+ manager: ContractAddr.from('0xcc6a5153ca56293405506eb20826a379d982cd738008ef7e808454d318fb81'),
720
+ vaultAllocator: ContractAddr.from('0xf29d2f82e896c0ed74c9eff220af34ac148e8b99846d1ace9fbb02c9191d01'),
721
+ redeemRequestNFT: ContractAddr.from('0x46902423bd632c428376b84fcee9cac5dbe016214e93a8103bcbde6e1de656b'),
722
+ aumOracle: ContractAddr.from("0x6d7dbfad4bb51715da211468389a623da00c0625f8f6efbea822ee5ac5231f4"),
723
+ leafAdapters: [],
724
+ adapters: [],
725
+ targetHealthFactor: 1.3,
726
+ minHealthFactor: 1.25
727
+ }
728
+
729
+ const usdtVaultSettings: UniversalStrategySettings = {
730
+ manager: ContractAddr.from('0x39bb9843503799b552b7ed84b31c06e4ff10c0537edcddfbf01fe944b864029'),
731
+ vaultAllocator: ContractAddr.from('0x56437d18c43727ac971f6c7086031cad7d9d6ccb340f4f3785a74cc791c931a'),
732
+ redeemRequestNFT: ContractAddr.from('0x5af0c2a657eaa8e23ed78e855dac0c51e4f69e2cf91a18c472041a1f75bb41f'),
733
+ aumOracle: ContractAddr.from("0x7018f8040c8066a4ab929e6760ae52dd43b6a3a289172f514750a61fcc565cc"),
734
+ leafAdapters: [],
735
+ adapters: [],
736
+ targetHealthFactor: 1.3,
737
+ minHealthFactor: 1.25
738
+ }
739
+
658
740
  export const UniversalStrategies: IStrategyMetadata<UniversalStrategySettings>[] =
659
741
  [
660
742
  {
@@ -699,4 +781,67 @@ export const UniversalStrategies: IStrategyMetadata<UniversalStrategySettings>[]
699
781
  faqs: [],
700
782
  investmentSteps: [],
701
783
  },
784
+ {
785
+ name: "ETH Evergreen",
786
+ description: "A universal strategy for managing ETH assets",
787
+ address: ContractAddr.from('0x446c22d4d3f5cb52b4950ba832ba1df99464c6673a37c092b1d9622650dbd8'),
788
+ launchBlock: 0,
789
+ type: 'ERC4626',
790
+ depositTokens: [Global.getDefaultTokens().find(token => token.symbol === 'ETH')!],
791
+ additionalInfo: getLooperSettings('ETH', 'WBTC', ethVaultSettings, VesuPools.Genesis, VesuPools.Genesis),
792
+ risk: {
793
+ riskFactor: _riskFactor,
794
+ netRisk:
795
+ _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
796
+ _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
797
+ notARisks: getNoRiskTags(_riskFactor)
798
+ },
799
+ protocols: [Protocols.VESU],
800
+ maxTVL: Web3Number.fromWei(0, 18),
801
+ contractDetails: [],
802
+ faqs: [],
803
+ investmentSteps: [],
804
+ },
805
+ {
806
+ name: "STRK Evergreen",
807
+ description: "A universal strategy for managing STRK assets",
808
+ address: ContractAddr.from('0x55d012f57e58c96e0a5c7ebbe55853989d01e6538b15a95e7178aca4af05c21'),
809
+ launchBlock: 0,
810
+ type: 'ERC4626',
811
+ depositTokens: [Global.getDefaultTokens().find(token => token.symbol === 'STRK')!],
812
+ additionalInfo: getLooperSettings('STRK', 'ETH', strkVaultSettings, VesuPools.Genesis, VesuPools.Genesis),
813
+ risk: {
814
+ riskFactor: _riskFactor,
815
+ netRisk:
816
+ _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
817
+ _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
818
+ notARisks: getNoRiskTags(_riskFactor)
819
+ },
820
+ protocols: [Protocols.VESU],
821
+ maxTVL: Web3Number.fromWei(0, 18),
822
+ contractDetails: [],
823
+ faqs: [],
824
+ investmentSteps: [],
825
+ },
826
+ {
827
+ name: "USDT Evergreen",
828
+ description: "A universal strategy for managing USDT assets",
829
+ address: ContractAddr.from('0x1c4933d1880c6778585e597154eaca7b428579d72f3aae425ad2e4d26c6bb3'),
830
+ launchBlock: 0,
831
+ type: 'ERC4626',
832
+ depositTokens: [Global.getDefaultTokens().find(token => token.symbol === 'USDT')!],
833
+ additionalInfo: getLooperSettings('USDT', 'ETH', usdtVaultSettings, VesuPools.Genesis, VesuPools.Genesis),
834
+ risk: {
835
+ riskFactor: _riskFactor,
836
+ netRisk:
837
+ _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
838
+ _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
839
+ notARisks: getNoRiskTags(_riskFactor)
840
+ },
841
+ protocols: [Protocols.VESU],
842
+ maxTVL: Web3Number.fromWei(0, 6),
843
+ contractDetails: [],
844
+ faqs: [],
845
+ investmentSteps: [],
846
+ }
702
847
  ]
@@ -1,29 +1,29 @@
1
- interface CacheData {
2
- timestamp: number;
3
- ttl: number;
4
- data: any;
5
- }
6
- export class CacheClass {
7
- readonly cache: Map<string, CacheData> = new Map();
8
-
9
- setCache(key: string, data: any, ttl: number = 60000): void {
10
- const timestamp = Date.now();
11
- this.cache.set(key, { timestamp, ttl, data });
12
- }
13
-
14
- getCache<T>(key: string): T | null {
15
- const cachedData = this.cache.get(key);
16
- if (!cachedData || !this.isCacheValid(key)) {
17
- return null;
18
- }
19
- return cachedData.data;
20
- }
21
-
22
- isCacheValid(key: string): boolean {
23
- const cachedData = this.cache.get(key);
24
- if (!cachedData) return false;
25
-
26
- const { timestamp, ttl } = cachedData;
27
- return Date.now() - timestamp <= ttl;
28
- }
1
+ interface CacheData {
2
+ timestamp: number;
3
+ ttl: number;
4
+ data: any;
5
+ }
6
+ export class CacheClass {
7
+ readonly cache: Map<string, CacheData> = new Map();
8
+
9
+ setCache(key: string, data: any, ttl: number = 60000): void {
10
+ const timestamp = Date.now();
11
+ this.cache.set(key, { timestamp, ttl, data });
12
+ }
13
+
14
+ getCache<T>(key: string): T | null {
15
+ const cachedData = this.cache.get(key);
16
+ if (!cachedData || !this.isCacheValid(key)) {
17
+ return null;
18
+ }
19
+ return cachedData.data;
20
+ }
21
+
22
+ isCacheValid(key: string): boolean {
23
+ const cachedData = this.cache.get(key);
24
+ if (!cachedData) return false;
25
+
26
+ const { timestamp, ttl } = cachedData;
27
+ return Date.now() - timestamp <= ttl;
28
+ }
29
29
  }