@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/dist/cli.js +0 -0
- package/dist/cli.mjs +0 -0
- package/dist/index.browser.global.js +5949 -5865
- package/dist/index.browser.mjs +179 -2093
- package/dist/index.d.ts +7 -1
- package/dist/index.js +193 -2101
- package/dist/index.mjs +192 -2107
- package/package.json +3 -2
- package/src/interfaces/common.tsx +5 -3
- package/src/node/deployer.ts +1 -1
- package/src/strategies/universal-strategy.ts +158 -13
- 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
|
@@ -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,
|
|
@@ -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
|
|
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
|
|
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)
|
|
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
|
-
|
|
276
|
-
|
|
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:
|
|
330
|
+
id: AUMTypes.FINALISED,
|
|
282
331
|
aum: aumToken
|
|
283
332
|
}, {
|
|
284
|
-
id:
|
|
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
|
]
|
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
|
}
|