@strkfarm/sdk 1.0.57 → 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/dist/cli.js +0 -0
- package/dist/cli.mjs +0 -0
- package/dist/index.browser.global.js +5951 -5863
- package/dist/index.browser.mjs +181 -2091
- package/dist/index.d.ts +8 -1
- package/dist/index.js +196 -2100
- package/dist/index.mjs +195 -2106
- package/package.json +3 -2
- package/src/interfaces/common.tsx +5 -3
- package/src/node/deployer.ts +2 -2
- package/src/strategies/universal-strategy.ts +162 -10
- package/src/utils/cacheClass.ts +28 -28
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strkfarm/sdk",
|
|
3
|
-
"version": "1.0.
|
|
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": "
|
|
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
|
package/src/node/deployer.ts
CHANGED
|
@@ -36,7 +36,7 @@ function getAccount(
|
|
|
36
36
|
PASSWORD: password
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
return store.getAccount(accountKey);
|
|
39
|
+
return store.getAccount(accountKey, '0x3');
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
async function myDeclare(contract_name: string, package_name: string = 'strkfarm', config: IConfig, acc: Account) {
|
|
@@ -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.
|
|
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,
|
|
@@ -9,17 +9,23 @@ import UniversalVaultAbi from '../data/universal-vault.abi.json';
|
|
|
9
9
|
import ManagerAbi from '../data/vault-manager.abi.json';
|
|
10
10
|
import { ApproveCallParams, BaseAdapter, CommonAdapter, FlashloanCallParams, GenerateCallFn, LeafAdapterFn, ManageCall, VesuAdapter, VesuModifyPositionCallParams, VesuPools } from "./universal-adapters";
|
|
11
11
|
import { Global } from "@/global";
|
|
12
|
+
import { ERC20 } from "@/modules";
|
|
12
13
|
|
|
13
14
|
export interface UniversalStrategySettings {
|
|
14
15
|
manager: ContractAddr,
|
|
15
16
|
vaultAllocator: ContractAddr,
|
|
16
17
|
redeemRequestNFT: ContractAddr,
|
|
18
|
+
aumOracle: ContractAddr,
|
|
17
19
|
leafAdapters: LeafAdapterFn<any>[],
|
|
18
20
|
adapters: {id: string, adapter: BaseAdapter}[],
|
|
19
21
|
targetHealthFactor: number,
|
|
20
22
|
minHealthFactor: number
|
|
21
23
|
}
|
|
22
24
|
|
|
25
|
+
export enum AUMTypes {
|
|
26
|
+
FINALISED = 'finalised',
|
|
27
|
+
DEFISPRING = 'defispring'
|
|
28
|
+
}
|
|
23
29
|
|
|
24
30
|
export class UniversalStrategy<
|
|
25
31
|
S extends UniversalStrategySettings
|
|
@@ -139,6 +145,20 @@ export class UniversalStrategy<
|
|
|
139
145
|
return [call1, call2];
|
|
140
146
|
}
|
|
141
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
|
+
|
|
142
162
|
/**
|
|
143
163
|
* Calculates the Total Value Locked (TVL) for a specific user.
|
|
144
164
|
* @param user - Address of the user
|
|
@@ -190,14 +210,22 @@ export class UniversalStrategy<
|
|
|
190
210
|
const debt2APY = Number(debtAsset2.borrowApr.value) / 1e18;
|
|
191
211
|
|
|
192
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
|
+
}
|
|
193
221
|
const weights = positions.map((p, index) => p.usdValue * (index % 2 == 0 ? 1 : -1));
|
|
194
222
|
const baseAPYs = [collateral1APY, debt1APY, collateral2APY, debt2APY];
|
|
195
223
|
assert(positions.length == baseAPYs.length, "Positions and APYs length mismatch");
|
|
196
224
|
const rewardAPYs = [Number(collateralAsset1.defiSpringSupplyApr.value) / 1e18, 0, Number(collateralAsset2.defiSpringSupplyApr.value) / 1e18, 0];
|
|
197
225
|
const baseAPY = this.computeAPY(baseAPYs, weights);
|
|
198
226
|
const rewardAPY = this.computeAPY(rewardAPYs, weights);
|
|
199
|
-
const apys = [...baseAPYs, ...rewardAPYs];
|
|
200
227
|
const netAPY = baseAPY + rewardAPY;
|
|
228
|
+
logger.verbose(`${this.metadata.name}::netAPY: net: ${netAPY}, baseAPY: ${baseAPY}, rewardAPY: ${rewardAPY}`);
|
|
201
229
|
return { net: netAPY, splits: [{
|
|
202
230
|
apy: baseAPY, id: 'base'
|
|
203
231
|
}, {
|
|
@@ -233,6 +261,17 @@ export class UniversalStrategy<
|
|
|
233
261
|
};
|
|
234
262
|
}
|
|
235
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
|
+
|
|
236
275
|
async getAUM(): Promise<{net: SingleTokenInfo, prevAum: Web3Number, splits: {id: string, aum: Web3Number}[]}> {
|
|
237
276
|
const currentAUM: bigint = await this.contract.call('aum', []) as bigint;
|
|
238
277
|
const lastReportTime = await this.contract.call('last_report_timestamp', []);
|
|
@@ -244,10 +283,29 @@ export class UniversalStrategy<
|
|
|
244
283
|
const leg1AUM = await vesuAdapter1.getPositions(this.config);
|
|
245
284
|
const leg2AUM = await vesuAdapter2.getPositions(this.config);
|
|
246
285
|
|
|
247
|
-
const
|
|
286
|
+
const balance = await this.getUnusedBalance();
|
|
287
|
+
logger.verbose(`${this.getTag()} unused balance: ${balance.amount.toNumber()}`);
|
|
288
|
+
|
|
289
|
+
const vesuAum = leg1AUM[0].amount
|
|
248
290
|
.plus(leg2AUM[0].usdValue / token1Price.price)
|
|
249
291
|
.minus(leg1AUM[1].usdValue / token1Price.price)
|
|
250
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);
|
|
251
309
|
logger.verbose(`${this.getTag()} Actual AUM: ${aumToken}`);
|
|
252
310
|
|
|
253
311
|
// calculate estimated growth from strk rewards
|
|
@@ -257,7 +315,6 @@ export class UniversalStrategy<
|
|
|
257
315
|
|
|
258
316
|
const timeDiff = (Math.round(Date.now() / 1000) - Number(lastReportTime));
|
|
259
317
|
const growthRate = timeDiff * defispringAPY / (365 * 24 * 60 * 60);
|
|
260
|
-
const prevAum = Web3Number.fromWei(currentAUM.toString(), this.asset().decimals);
|
|
261
318
|
const rewardAssets = prevAum.multipliedBy(growthRate);
|
|
262
319
|
logger.verbose(`${this.getTag()} DefiSpring AUM time difference: ${timeDiff}`);
|
|
263
320
|
logger.verbose(`${this.getTag()} Current AUM: ${currentAUM}`);
|
|
@@ -267,16 +324,13 @@ export class UniversalStrategy<
|
|
|
267
324
|
const newAUM = aumToken.plus(rewardAssets);
|
|
268
325
|
logger.verbose(`${this.getTag()} New AUM: ${newAUM}`);
|
|
269
326
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
amount: newAUM,
|
|
273
|
-
usdValue: newAUM.multipliedBy(token1Price.price).toNumber()
|
|
274
|
-
};
|
|
327
|
+
net.amount = newAUM;
|
|
328
|
+
net.usdValue = newAUM.multipliedBy(token1Price.price).toNumber();
|
|
275
329
|
const splits = [{
|
|
276
|
-
id:
|
|
330
|
+
id: AUMTypes.FINALISED,
|
|
277
331
|
aum: aumToken
|
|
278
332
|
}, {
|
|
279
|
-
id:
|
|
333
|
+
id: AUMTypes.DEFISPRING,
|
|
280
334
|
aum: rewardAssets
|
|
281
335
|
}];
|
|
282
336
|
return { net, splits, prevAum };
|
|
@@ -632,6 +686,7 @@ const usdcVaultSettings: UniversalStrategySettings = {
|
|
|
632
686
|
manager: ContractAddr.from('0xf41a2b1f498a7f9629db0b8519259e66e964260a23d20003f3e42bb1997a07'),
|
|
633
687
|
vaultAllocator: ContractAddr.from('0x228cca1005d3f2b55cbaba27cb291dacf1b9a92d1d6b1638195fbd3d0c1e3ba'),
|
|
634
688
|
redeemRequestNFT: ContractAddr.from('0x906d03590010868cbf7590ad47043959d7af8e782089a605d9b22567b64fda'),
|
|
689
|
+
aumOracle: ContractAddr.from("0x6faf45ed185dec13ef723c9ead4266cab98d06f2cb237e331b1fa5c2aa79afe"),
|
|
635
690
|
leafAdapters: [],
|
|
636
691
|
adapters: [],
|
|
637
692
|
targetHealthFactor: 1.3,
|
|
@@ -642,6 +697,40 @@ const wbtcVaultSettings: UniversalStrategySettings = {
|
|
|
642
697
|
manager: ContractAddr.from('0xef8a664ffcfe46a6af550766d27c28937bf1b77fb4ab54d8553e92bca5ba34'),
|
|
643
698
|
vaultAllocator: ContractAddr.from('0x1e01c25f0d9494570226ad28a7fa856c0640505e809c366a9fab4903320e735'),
|
|
644
699
|
redeemRequestNFT: ContractAddr.from('0x4fec59a12f8424281c1e65a80b5de51b4e754625c60cddfcd00d46941ec37b2'),
|
|
700
|
+
aumOracle: ContractAddr.from("0x2edf4edbed3f839e7f07dcd913e92299898ff4cf0ba532f8c572c66c5b331b2"),
|
|
701
|
+
leafAdapters: [],
|
|
702
|
+
adapters: [],
|
|
703
|
+
targetHealthFactor: 1.3,
|
|
704
|
+
minHealthFactor: 1.25
|
|
705
|
+
}
|
|
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"),
|
|
645
734
|
leafAdapters: [],
|
|
646
735
|
adapters: [],
|
|
647
736
|
targetHealthFactor: 1.3,
|
|
@@ -692,4 +781,67 @@ export const UniversalStrategies: IStrategyMetadata<UniversalStrategySettings>[]
|
|
|
692
781
|
faqs: [],
|
|
693
782
|
investmentSteps: [],
|
|
694
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
|
+
}
|
|
695
847
|
]
|
package/src/utils/cacheClass.ts
CHANGED
|
@@ -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
|
}
|