@strkfarm/sdk 2.0.0-staging.1 → 2.0.0-staging.11
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 +10 -6
- package/dist/cli.mjs +10 -6
- package/dist/index.browser.global.js +53062 -28963
- package/dist/index.browser.mjs +2429 -1799
- package/dist/index.d.ts +188 -46
- package/dist/index.js +2122 -1479
- package/dist/index.mjs +2698 -2068
- package/package.json +79 -81
- package/src/dataTypes/index.ts +3 -2
- package/src/dataTypes/mynumber.ts +141 -0
- package/src/global.ts +27 -1
- package/src/index.browser.ts +2 -1
- package/src/interfaces/common.tsx +98 -13
- package/src/modules/ekubo-quoter.ts +1 -1
- package/src/modules/harvests.ts +17 -14
- package/src/modules/index.ts +0 -1
- package/src/modules/pricer-lst.ts +1 -1
- package/src/modules/pricer.ts +38 -3
- package/src/strategies/base-strategy.ts +25 -0
- package/src/strategies/ekubo-cl-vault.tsx +547 -269
- package/src/strategies/factory.ts +159 -0
- package/src/strategies/index.ts +1 -0
- package/src/strategies/registry.ts +50 -113
- package/src/strategies/sensei.ts +134 -7
- package/src/strategies/universal-adapters/vesu-adapter.ts +7 -5
- package/src/strategies/universal-lst-muliplier-strategy.tsx +279 -118
- package/src/strategies/universal-strategy.tsx +144 -144
- package/src/strategies/vesu-rebalance.tsx +95 -150
- package/src/utils/index.ts +1 -0
- package/src/utils/logger.node.ts +11 -4
- package/src/utils/strategy-utils.ts +57 -0
package/package.json
CHANGED
|
@@ -1,84 +1,82 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
"name": "@strkfarm/sdk",
|
|
3
|
+
"version": "2.0.0-staging.11",
|
|
4
|
+
"description": "STRKFarm TS SDK (Meant for our internal use, but feel free to use it)",
|
|
5
|
+
"typings": "dist/index.d.ts",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"accountsecure": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"browser": "./dist/index.browser.mjs",
|
|
14
|
+
"default": "./dist/index.mjs"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"browser": "./dist/index.browser.global.js",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"browser": "./dist/index.browser.global.js",
|
|
21
|
+
"types": "./dist/index.d.ts"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"src"
|
|
27
|
+
],
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"tag": "staging"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"test": "jest",
|
|
33
|
+
"build": "tsup --clean && pnpm run build:esm && npm run build:dts && npm run build:iife && npm run build-cli && pnpm run build:iife-esm",
|
|
34
|
+
"build:esm": "tsup --clean false --format esm --platform node",
|
|
35
|
+
"build-cli:esm": "tsup ./src/cli.ts --clean false --format esm --platform node",
|
|
36
|
+
"build-cli": "tsup ./src/cli.ts --clean false && pnpm run build-cli:esm",
|
|
37
|
+
"build:dts": "tsup --clean false --dts-only",
|
|
38
|
+
"build:iife": "tsup --clean false --format iife --platform browser",
|
|
39
|
+
"build:iife-esm": "tsup --clean false --format iife --format esm --platform browser"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [],
|
|
42
|
+
"author": "",
|
|
43
|
+
"license": "ISC",
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/jest": "^29.5.12",
|
|
46
|
+
"@types/node-telegram-bot-api": "^0.64.7",
|
|
47
|
+
"jest": "^29.7.0",
|
|
48
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
49
|
+
"request": "^2.88.2",
|
|
50
|
+
"ts-jest": "^29.1.5",
|
|
51
|
+
"ts-node": "^10.9.2",
|
|
52
|
+
"tsup": "^8.1.0",
|
|
53
|
+
"typedoc": "^0.26.3",
|
|
54
|
+
"typescript": "^5.5.3"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@types/react": "^19.1.2",
|
|
58
|
+
"axios": "^1.7.2",
|
|
59
|
+
"react": "19.1.2",
|
|
60
|
+
"starknet": "9.2.1"
|
|
61
|
+
},
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"@apollo/client": "3.11.8",
|
|
64
|
+
"@avnu/avnu-sdk": "3.0.2",
|
|
65
|
+
"@ericnordelo/strk-merkle-tree": "^1.0.0",
|
|
66
|
+
"@noble/curves": "^1.0.0",
|
|
67
|
+
"@noble/hashes": "^2.0.0",
|
|
68
|
+
"@scure/starknet": "^2.0.0",
|
|
69
|
+
"bignumber.js": "4.0.4",
|
|
70
|
+
"browser-assert": "^1.2.1",
|
|
71
|
+
"chalk": "^4.1.2",
|
|
72
|
+
"commander": "^12.1.0",
|
|
73
|
+
"ethers": "^6.13.5",
|
|
74
|
+
"graphql": "16.9.0",
|
|
75
|
+
"inquirer": "^10.1.2",
|
|
76
|
+
"node-telegram-bot-api": "^0.66.0",
|
|
77
|
+
"proxy-from-env": "^1.1.0",
|
|
78
|
+
"redis": "^4.7.0",
|
|
79
|
+
"stacktrace-js": "^2.0.2",
|
|
80
|
+
"winston": "^3.13.0"
|
|
23
81
|
}
|
|
24
|
-
},
|
|
25
|
-
"files": [
|
|
26
|
-
"dist",
|
|
27
|
-
"src"
|
|
28
|
-
],
|
|
29
|
-
"publishConfig": {
|
|
30
|
-
"tag": "staging"
|
|
31
|
-
},
|
|
32
|
-
"scripts": {
|
|
33
|
-
"test": "jest",
|
|
34
|
-
"build": "tsup --clean && pnpm run build:esm && npm run build:dts && npm run build:iife && npm run build-cli && pnpm run build:iife-esm",
|
|
35
|
-
"build:esm": "tsup --clean false --format esm --platform node",
|
|
36
|
-
"build-cli:esm": "tsup ./src/cli.ts --clean false --format esm --platform node",
|
|
37
|
-
"build-cli": "tsup ./src/cli.ts --clean false && pnpm run build-cli:esm",
|
|
38
|
-
"build:dts": "tsup --clean false --dts-only",
|
|
39
|
-
"build:iife": "tsup --clean false --format iife --platform browser",
|
|
40
|
-
"build:iife-esm": "tsup --clean false --format iife --format esm --platform browser"
|
|
41
|
-
},
|
|
42
|
-
"keywords": [],
|
|
43
|
-
"author": "",
|
|
44
|
-
"license": "ISC",
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@types/jest": "^29.5.12",
|
|
47
|
-
"@types/node-telegram-bot-api": "^0.64.7",
|
|
48
|
-
"jest": "^29.7.0",
|
|
49
|
-
"jest-environment-jsdom": "^29.7.0",
|
|
50
|
-
"request": "^2.88.2",
|
|
51
|
-
"ts-jest": "^29.1.5",
|
|
52
|
-
"ts-node": "^10.9.2",
|
|
53
|
-
"tsup": "^8.1.0",
|
|
54
|
-
"typedoc": "^0.26.3",
|
|
55
|
-
"typescript": "^5.5.3"
|
|
56
|
-
},
|
|
57
|
-
"peerDependencies": {
|
|
58
|
-
"@types/react": "^19.1.2",
|
|
59
|
-
"axios": "^1.7.2",
|
|
60
|
-
"react": "19.1.0",
|
|
61
|
-
"starknet": "8.5.2"
|
|
62
|
-
},
|
|
63
|
-
"dependencies": {
|
|
64
|
-
"@apollo/client": "3.11.8",
|
|
65
|
-
"@avnu/avnu-sdk": "3.0.2",
|
|
66
|
-
"@ericnordelo/strk-merkle-tree": "^1.0.0",
|
|
67
|
-
"@noble/curves": "^1.0.0",
|
|
68
|
-
"@noble/hashes": "^2.0.0",
|
|
69
|
-
"@scure/starknet": "^2.0.0",
|
|
70
|
-
"@strkfarm/sdk": "link:",
|
|
71
|
-
"bignumber.js": "4.0.4",
|
|
72
|
-
"browser-assert": "^1.2.1",
|
|
73
|
-
"chalk": "^4.1.2",
|
|
74
|
-
"commander": "^12.1.0",
|
|
75
|
-
"ethers": "^6.13.5",
|
|
76
|
-
"graphql": "16.9.0",
|
|
77
|
-
"inquirer": "^10.1.2",
|
|
78
|
-
"node-telegram-bot-api": "^0.66.0",
|
|
79
|
-
"proxy-from-env": "^1.1.0",
|
|
80
|
-
"redis": "^4.7.0",
|
|
81
|
-
"stacktrace-js": "^2.0.2",
|
|
82
|
-
"winston": "^3.13.0"
|
|
83
|
-
}
|
|
84
82
|
}
|
package/src/dataTypes/index.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
1
|
+
export * from "@/dataTypes/bignumber";
|
|
2
|
+
export * from "./address";
|
|
3
|
+
export * from "./mynumber";
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import { ethers } from "ethers";
|
|
3
|
+
|
|
4
|
+
const customInspectSymbol = Symbol.for("nodejs.util.inspect.custom");
|
|
5
|
+
|
|
6
|
+
BigNumber.config({
|
|
7
|
+
DECIMAL_PLACES: 18
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export class MyNumber {
|
|
11
|
+
bigNumber: BigNumber;
|
|
12
|
+
decimals: number;
|
|
13
|
+
|
|
14
|
+
constructor(bigNumber: string, decimals: number) {
|
|
15
|
+
this.bigNumber = new BigNumber(bigNumber);
|
|
16
|
+
this.decimals = decimals;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static fromEther(num: string, decimals: number) {
|
|
20
|
+
try {
|
|
21
|
+
return new MyNumber(
|
|
22
|
+
Number(
|
|
23
|
+
ethers.parseUnits(Number(num).toFixed(10), decimals)
|
|
24
|
+
).toFixed(6),
|
|
25
|
+
decimals
|
|
26
|
+
);
|
|
27
|
+
} catch (e) {
|
|
28
|
+
console.error("fromEther", e, num, decimals);
|
|
29
|
+
throw e;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static fromZero() {
|
|
34
|
+
return new MyNumber("0", 0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
toString() {
|
|
38
|
+
return this.bigNumber.toFixed();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
toEtherStr() {
|
|
42
|
+
return ethers.formatUnits(this.bigNumber.toFixed(), this.decimals);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
toFixedStr(decimals: number) {
|
|
46
|
+
return Number(this.toEtherStr()).toFixed(decimals);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
toEtherToFixedDecimals(decimals: number) {
|
|
50
|
+
// rounding down
|
|
51
|
+
if (this.bigNumber.isNaN()) {
|
|
52
|
+
return "NaN";
|
|
53
|
+
}
|
|
54
|
+
return (
|
|
55
|
+
Math.floor(parseFloat(this.toEtherStr()) * 10 ** decimals) /
|
|
56
|
+
10 ** decimals
|
|
57
|
+
).toFixed(decimals);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
isZero() {
|
|
61
|
+
return this.bigNumber.eq("0");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
* @param amountEther in token terms without decimal e.g. 1 for 1 STRK
|
|
67
|
+
* @param command BigNumber compare funds. e.g. gte, gt, lt
|
|
68
|
+
* @returns
|
|
69
|
+
* @dev Add more commands as needed
|
|
70
|
+
*/
|
|
71
|
+
compare(amountEther: string, command: "gte" | "gt" | "lt") {
|
|
72
|
+
const fullNum = new BigNumber(
|
|
73
|
+
ethers.parseUnits(amountEther, this.decimals).toString()
|
|
74
|
+
);
|
|
75
|
+
return this.bigNumber[command](fullNum);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
operate(command: "div" | "plus" | "mul", value: string | number) {
|
|
79
|
+
const bn = new BigNumber(Number(value).toFixed(6));
|
|
80
|
+
return new MyNumber(
|
|
81
|
+
this.bigNumber[command](bn).toFixed(0),
|
|
82
|
+
this.decimals
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
subtract(value: MyNumber) {
|
|
87
|
+
const bn = this.bigNumber.minus(value.bigNumber);
|
|
88
|
+
return new MyNumber(bn.toString(), this.decimals);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static min(a: MyNumber, b: MyNumber) {
|
|
92
|
+
if (a.decimals !== b.decimals) {
|
|
93
|
+
const diff = Math.abs(a.decimals - b.decimals);
|
|
94
|
+
if (a.decimals > b.decimals) {
|
|
95
|
+
b = new MyNumber(
|
|
96
|
+
b.bigNumber.times(10 ** diff).toString(),
|
|
97
|
+
a.decimals
|
|
98
|
+
);
|
|
99
|
+
} else {
|
|
100
|
+
a = new MyNumber(
|
|
101
|
+
a.bigNumber.times(10 ** diff).toString(),
|
|
102
|
+
b.decimals
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const bn = BigNumber.min(a.bigNumber, b.bigNumber);
|
|
107
|
+
return new MyNumber(
|
|
108
|
+
bn.toString(),
|
|
109
|
+
a.decimals > b.decimals ? a.decimals : b.decimals
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static max(a: MyNumber, b: MyNumber) {
|
|
114
|
+
if (a.decimals !== b.decimals) {
|
|
115
|
+
const diff = Math.abs(a.decimals - b.decimals);
|
|
116
|
+
if (a.decimals > b.decimals) {
|
|
117
|
+
b = new MyNumber(
|
|
118
|
+
b.bigNumber.times(10 ** diff).toString(),
|
|
119
|
+
a.decimals
|
|
120
|
+
);
|
|
121
|
+
} else {
|
|
122
|
+
a = new MyNumber(
|
|
123
|
+
a.bigNumber.times(10 ** diff).toString(),
|
|
124
|
+
b.decimals
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const bn = BigNumber.max(a.bigNumber, b.bigNumber);
|
|
129
|
+
return new MyNumber(
|
|
130
|
+
bn.toString(),
|
|
131
|
+
a.decimals > b.decimals ? a.decimals : b.decimals
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
[customInspectSymbol](depth: any, inspectOptions: any, inspect: any) {
|
|
136
|
+
return JSON.stringify({
|
|
137
|
+
raw: this.toString(),
|
|
138
|
+
decimals: this.decimals
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
package/src/global.ts
CHANGED
|
@@ -41,11 +41,20 @@ const defaultTokens: TokenInfo[] = [{
|
|
|
41
41
|
coingeckId: undefined,
|
|
42
42
|
priceCheckAmount: 0.1,
|
|
43
43
|
displayDecimals: 6,
|
|
44
|
+
}, {
|
|
45
|
+
name: 'USDC.e',
|
|
46
|
+
symbol: 'USDC.e',
|
|
47
|
+
logo: 'https://assets.troves.fi/integrations/tokens/usdc.svg',
|
|
48
|
+
address: ContractAddr.from('0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8'),
|
|
49
|
+
decimals: 6,
|
|
50
|
+
coingeckId: undefined,
|
|
51
|
+
displayDecimals: 2,
|
|
52
|
+
priceCheckAmount: 1000,
|
|
44
53
|
}, {
|
|
45
54
|
name: 'USDC',
|
|
46
55
|
symbol: 'USDC',
|
|
47
56
|
logo: 'https://assets.troves.fi/integrations/tokens/usdc.svg',
|
|
48
|
-
address: ContractAddr.from('
|
|
57
|
+
address: ContractAddr.from('0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb'),
|
|
49
58
|
decimals: 6,
|
|
50
59
|
coingeckId: undefined,
|
|
51
60
|
displayDecimals: 2,
|
|
@@ -105,6 +114,7 @@ const defaultTokens: TokenInfo[] = [{
|
|
|
105
114
|
decimals: 8,
|
|
106
115
|
coingeckId: undefined,
|
|
107
116
|
displayDecimals: 6,
|
|
117
|
+
priceProxySymbol: 'WBTC',
|
|
108
118
|
priceCheckAmount: 0.001, // 112000 * 0.0001 = $110.2
|
|
109
119
|
}, {
|
|
110
120
|
name: 'xsBTC',
|
|
@@ -126,6 +136,7 @@ const defaultTokens: TokenInfo[] = [{
|
|
|
126
136
|
coingeckId: undefined,
|
|
127
137
|
displayDecimals: 6,
|
|
128
138
|
priceCheckAmount: 0.001, // 112000 * 0.0001 = $110.2
|
|
139
|
+
priceProxySymbol: 'WBTC',
|
|
129
140
|
}, {
|
|
130
141
|
name: 'xLBTC',
|
|
131
142
|
symbol: 'xLBTC',
|
|
@@ -244,6 +255,21 @@ export class Global {
|
|
|
244
255
|
return token;
|
|
245
256
|
}
|
|
246
257
|
|
|
258
|
+
static async getTokenInfoFromName(tokenName: string) {
|
|
259
|
+
// if tokens are not loaded, load them
|
|
260
|
+
if (tokens.length == defaultTokens.length) {
|
|
261
|
+
await Global.getTokens();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const token = tokens.find(
|
|
265
|
+
(token) => token.name.toLowerCase() === tokenName.toLowerCase()
|
|
266
|
+
);
|
|
267
|
+
if (!token) {
|
|
268
|
+
throw new FatalError(`Token not found: ${tokenName}`);
|
|
269
|
+
}
|
|
270
|
+
return token;
|
|
271
|
+
}
|
|
272
|
+
|
|
247
273
|
static setGlobalCache(key: string, data: any, ttl: number = 60000) {
|
|
248
274
|
Global.cache[key] = {
|
|
249
275
|
value: data,
|
package/src/index.browser.ts
CHANGED
|
@@ -55,19 +55,15 @@ export interface IProtocol {
|
|
|
55
55
|
logo: string;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
export enum StrategyTag {
|
|
59
|
+
META_VAULT = "Meta Vaults",
|
|
60
|
+
LEVERED = "Maxx",
|
|
61
|
+
AUTOMATED_LP = "Ekubo",
|
|
62
|
+
BTC = "BTC"
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
export enum
|
|
66
|
-
|
|
67
|
-
EVERGREEN = "Evergreen",
|
|
68
|
-
HYPER_LST = "Hyper-LST",
|
|
69
|
-
VESU = "Vesu",
|
|
70
|
-
SENSEI = "Sensei",
|
|
65
|
+
export enum VaultType {
|
|
66
|
+
FARMING = "farming"
|
|
71
67
|
}
|
|
72
68
|
|
|
73
69
|
// Security metadata enums
|
|
@@ -132,6 +128,38 @@ export interface FAQ {
|
|
|
132
128
|
answer: string | React.ReactNode;
|
|
133
129
|
}
|
|
134
130
|
|
|
131
|
+
export enum StrategyLiveStatus {
|
|
132
|
+
ACTIVE = "Active",
|
|
133
|
+
NEW = "New",
|
|
134
|
+
COMING_SOON = "Coming Soon",
|
|
135
|
+
DEPRECATED = "Deprecated", // active but not recommended
|
|
136
|
+
RETIRED = "Retired", // not active anymore
|
|
137
|
+
HOT = "Hot & New 🔥"
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface StrategyAlert {
|
|
141
|
+
type: "warning" | "info";
|
|
142
|
+
text: string | React.ReactNode;
|
|
143
|
+
tab: "all" | "deposit" | "withdraw";
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface StrategySettings {
|
|
147
|
+
maxTVL?: Web3Number;
|
|
148
|
+
liveStatus?: StrategyLiveStatus;
|
|
149
|
+
isPaused?: boolean;
|
|
150
|
+
isInMaintenance?: boolean;
|
|
151
|
+
isAudited: boolean;
|
|
152
|
+
isInstantWithdrawal?: boolean;
|
|
153
|
+
hideHarvestInfo?: boolean;
|
|
154
|
+
is_promoted?: boolean;
|
|
155
|
+
isTransactionHistDisabled?: boolean;
|
|
156
|
+
quoteToken: TokenInfo;
|
|
157
|
+
hideNetEarnings?: boolean;
|
|
158
|
+
showWithdrawalWarningModal?: boolean;
|
|
159
|
+
alerts?: StrategyAlert[];
|
|
160
|
+
tags?: StrategyTag[];
|
|
161
|
+
}
|
|
162
|
+
|
|
135
163
|
/**
|
|
136
164
|
* @property risk.riskFactor.factor - The risk factors that are considered for the strategy.
|
|
137
165
|
* @property risk.riskFactor.factor - The value of the risk factor from 0 to 10, 0 being the lowest and 10 being the highest.
|
|
@@ -139,15 +167,19 @@ export interface FAQ {
|
|
|
139
167
|
* @property redemptionInfo - Redemption information including instant withdrawal availability and expected redemption times.
|
|
140
168
|
*/
|
|
141
169
|
export interface IStrategyMetadata<T> {
|
|
170
|
+
id: string;
|
|
142
171
|
name: string;
|
|
143
172
|
description: string | React.ReactNode;
|
|
144
173
|
address: ContractAddr;
|
|
145
174
|
launchBlock: number;
|
|
146
175
|
type: "ERC4626" | "ERC721" | "Other";
|
|
176
|
+
vaultType: {
|
|
177
|
+
type: VaultType;
|
|
178
|
+
description: string;
|
|
179
|
+
};
|
|
147
180
|
depositTokens: TokenInfo[];
|
|
148
181
|
protocols: IProtocol[];
|
|
149
182
|
auditUrl?: string;
|
|
150
|
-
maxTVL: Web3Number;
|
|
151
183
|
risk: {
|
|
152
184
|
riskFactor: RiskFactor[];
|
|
153
185
|
netRisk: number;
|
|
@@ -166,10 +198,22 @@ export interface IStrategyMetadata<T> {
|
|
|
166
198
|
investmentSteps: string[];
|
|
167
199
|
curator?: { name: string, logo: string },
|
|
168
200
|
isPreview?: boolean;
|
|
169
|
-
category: StrategyCategory;
|
|
170
201
|
tags?: StrategyTag[];
|
|
171
202
|
security: SecurityMetadata;
|
|
172
203
|
redemptionInfo: RedemptionInfo;
|
|
204
|
+
settings?: StrategySettings;
|
|
205
|
+
// Legacy field for multi-step strategies (deprecated, use investmentFlows instead)
|
|
206
|
+
actions?: Array<{
|
|
207
|
+
name?: string;
|
|
208
|
+
pool?: {
|
|
209
|
+
protocol?: { name: string; logo: string };
|
|
210
|
+
pool?: { name: string; logos?: string[] };
|
|
211
|
+
apr?: number;
|
|
212
|
+
borrow?: { apr?: number };
|
|
213
|
+
};
|
|
214
|
+
amount?: string | number;
|
|
215
|
+
isDeposit?: boolean;
|
|
216
|
+
}>;
|
|
173
217
|
}
|
|
174
218
|
|
|
175
219
|
export interface IInvestmentFlow {
|
|
@@ -196,6 +240,23 @@ export function getMainnetConfig(
|
|
|
196
240
|
};
|
|
197
241
|
}
|
|
198
242
|
|
|
243
|
+
export const getStrategyTagDesciption = (tag: StrategyTag): string => {
|
|
244
|
+
switch (tag) {
|
|
245
|
+
case StrategyTag.META_VAULT:
|
|
246
|
+
return "A meta vault is a vault that auto allocates funds to multiple vaults based on optimal yield opportunities";
|
|
247
|
+
case StrategyTag.LEVERED:
|
|
248
|
+
return "Looping vaults on Endur LSTs with leveraged borrowing of STRK or BTC to increase yield (2-4x higher yield than simply staking)";
|
|
249
|
+
case StrategyTag.AUTOMATED_LP:
|
|
250
|
+
return "Automated LP vaults on Ekubo that rebalance position automatically, ensuring you earn fees efficiently";
|
|
251
|
+
case StrategyTag.BTC:
|
|
252
|
+
return "BTC linked vaults";
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export const getAllStrategyTags = (): StrategyTag[] => {
|
|
257
|
+
return Object.values(StrategyTag);
|
|
258
|
+
}
|
|
259
|
+
|
|
199
260
|
export const getRiskExplaination = (riskType: RiskType) => {
|
|
200
261
|
switch (riskType) {
|
|
201
262
|
case RiskType.MARKET_RISK:
|
|
@@ -286,6 +347,30 @@ export interface VaultPosition {
|
|
|
286
347
|
remarks: string
|
|
287
348
|
}
|
|
288
349
|
|
|
350
|
+
export interface AmountInfo {
|
|
351
|
+
amount: Web3Number;
|
|
352
|
+
usdValue: number;
|
|
353
|
+
tokenInfo: TokenInfo;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export interface AmountsInfo {
|
|
357
|
+
usdValue: number;
|
|
358
|
+
amounts: AmountInfo[];
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Strategy capabilities interface
|
|
363
|
+
* Describes what optional methods a strategy instance supports
|
|
364
|
+
*/
|
|
365
|
+
export interface StrategyCapabilities {
|
|
366
|
+
hasMatchInputAmounts: boolean;
|
|
367
|
+
hasNetAPY: boolean;
|
|
368
|
+
hasGetInvestmentFlows: boolean;
|
|
369
|
+
hasGetPendingRewards: boolean;
|
|
370
|
+
hasHarvest: boolean;
|
|
371
|
+
hasRebalance: boolean;
|
|
372
|
+
}
|
|
373
|
+
|
|
289
374
|
const VesuProtocol: IProtocol = {
|
|
290
375
|
name: "Vesu",
|
|
291
376
|
logo: "https://static-assets-8zct.onrender.com/integrations/vesu/logo.png"
|
|
@@ -28,7 +28,7 @@ export interface EkuboQuote {
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
export class EkuboQuoter {
|
|
31
|
-
ENDPOINT = 'https://
|
|
31
|
+
ENDPOINT = 'https://prod-api-quoter.ekubo.org/23448594291968334/{{AMOUNT}}/{{TOKEN_FROM_ADDRESS}}/{{TOKEN_TO_ADDRESS}}'; // e.g. ETH/USDC'
|
|
32
32
|
|
|
33
33
|
constructor(private readonly config: IConfig) {}
|
|
34
34
|
|
package/src/modules/harvests.ts
CHANGED
|
@@ -29,6 +29,7 @@ export class Harvests {
|
|
|
29
29
|
|
|
30
30
|
async getUnHarvestedRewards(addr: ContractAddr) {
|
|
31
31
|
const rewards = await this.getHarvests(addr);
|
|
32
|
+
logger.verbose(`${Harvests.name}: getUnHarvestedRewards => rewards length: ${rewards.length}`);
|
|
32
33
|
if (rewards.length == 0) return [];
|
|
33
34
|
|
|
34
35
|
const unClaimed: HarvestInfo[] = [];
|
|
@@ -66,26 +67,28 @@ const STRK = '0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d'
|
|
|
66
67
|
|
|
67
68
|
export class EkuboHarvests extends Harvests {
|
|
68
69
|
async getHarvests(addr: ContractAddr) {
|
|
69
|
-
|
|
70
|
+
logger.verbose(`${EkuboHarvests.name}: getHarvests => addr: ${addr.address}`);
|
|
71
|
+
const EKUBO_API = `https://prod-api.ekubo.org/claims/${addr.address}`
|
|
70
72
|
const resultEkubo = await fetch(EKUBO_API);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
+
const data = (await resultEkubo.json());
|
|
74
|
+
const claims = data.claims || [];
|
|
75
|
+
logger.verbose(`${EkuboHarvests.name}: getHarvests => claims length: ${claims.length}`);
|
|
73
76
|
const rewards: HarvestInfo[] = [];
|
|
74
|
-
for (let i=0; i<
|
|
75
|
-
const
|
|
76
|
-
assert(
|
|
77
|
+
for (let i=0; i<claims.length; ++i) {
|
|
78
|
+
const claimData = claims[i];
|
|
79
|
+
assert(claimData.key.token == STRK, 'expected strk token only')
|
|
77
80
|
rewards.push({
|
|
78
|
-
rewardsContract: ContractAddr.from(
|
|
81
|
+
rewardsContract: ContractAddr.from(claimData.dropAddress),
|
|
79
82
|
token: ContractAddr.from(STRK),
|
|
80
|
-
startDate: new Date(
|
|
81
|
-
endDate: new Date(
|
|
83
|
+
startDate: new Date(0),
|
|
84
|
+
endDate: new Date(0),
|
|
82
85
|
claim: {
|
|
83
|
-
id:
|
|
84
|
-
amount: Web3Number.fromWei(
|
|
85
|
-
claimee: ContractAddr.from(
|
|
86
|
+
id: claimData.claim.index,
|
|
87
|
+
amount: Web3Number.fromWei(claimData.claim.amount, 18),
|
|
88
|
+
claimee: ContractAddr.from(claimData.claim.account)
|
|
86
89
|
},
|
|
87
|
-
actualReward: Web3Number.fromWei(
|
|
88
|
-
proof:
|
|
90
|
+
actualReward: Web3Number.fromWei(claimData.claim.amount, 18),
|
|
91
|
+
proof: claimData.proof
|
|
89
92
|
});
|
|
90
93
|
}
|
|
91
94
|
return rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime());
|
package/src/modules/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ import axios from "axios";
|
|
|
6
6
|
|
|
7
7
|
export class PricerLST extends Pricer {
|
|
8
8
|
private tokenMaps: {lst: TokenInfo, underlying: TokenInfo}[];
|
|
9
|
-
protected EKUBO_API = 'https://
|
|
9
|
+
protected EKUBO_API = 'https://prod-api-quoter.ekubo.org/23448594291968334/{{AMOUNT}}/{{TOKEN_ADDRESS}}/{{UNDERLYING_ADDRESS}}'; // e.g. xSTRK/STRK
|
|
10
10
|
|
|
11
11
|
constructor(config: IConfig, tokenMaps: {lst: TokenInfo, underlying: TokenInfo}[]) {
|
|
12
12
|
const refreshInterval = 5000;
|