@strkfarm/sdk 2.0.0-dev.40 → 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.
- package/dist/index.browser.global.js +407 -208
- package/dist/index.browser.mjs +425 -225
- package/dist/index.d.ts +38 -14
- package/dist/index.js +427 -225
- package/dist/index.mjs +426 -225
- package/package.json +4 -5
- package/src/global.ts +36 -34
- package/src/interfaces/common.tsx +6 -0
- package/src/modules/index.ts +1 -0
- package/src/modules/pricer-avnu-api.ts +114 -0
- package/src/modules/pricer.ts +63 -45
- package/src/node/pricer-redis.ts +1 -0
- package/src/strategies/ekubo-cl-vault.tsx +3 -0
- package/src/strategies/svk-strategy.ts +159 -2
- package/src/strategies/token-boosted-xstrk-carry-strategy.tsx +46 -9
- package/src/strategies/universal-lst-muliplier-strategy.tsx +90 -19
- package/src/strategies/universal-strategy.tsx +216 -372
- package/src/strategies/yoloVault.ts +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strkfarm/sdk",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.41",
|
|
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",
|
|
@@ -38,9 +38,6 @@
|
|
|
38
38
|
"keywords": [],
|
|
39
39
|
"author": "",
|
|
40
40
|
"license": "ISC",
|
|
41
|
-
"publishConfig": {
|
|
42
|
-
"tag": "dev"
|
|
43
|
-
},
|
|
44
41
|
"devDependencies": {
|
|
45
42
|
"@types/jest": "^29.5.12",
|
|
46
43
|
"@types/node-telegram-bot-api": "^0.64.7",
|
|
@@ -59,6 +56,9 @@
|
|
|
59
56
|
"react": "19.1.2",
|
|
60
57
|
"starknet": "9.2.1"
|
|
61
58
|
},
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"tag": "staging"
|
|
61
|
+
},
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@apollo/client": "3.11.8",
|
|
64
64
|
"@avnu/avnu-sdk": "3.0.2",
|
|
@@ -70,7 +70,6 @@
|
|
|
70
70
|
"browser-assert": "^1.2.1",
|
|
71
71
|
"chalk": "^4.1.2",
|
|
72
72
|
"commander": "^12.1.0",
|
|
73
|
-
"dotenv": "^17.2.3",
|
|
74
73
|
"ethers": "^6.13.5",
|
|
75
74
|
"graphql": "16.9.0",
|
|
76
75
|
"inquirer": "^10.1.2",
|
package/src/global.ts
CHANGED
|
@@ -48,7 +48,7 @@ const defaultTokens: TokenInfo[] = [
|
|
|
48
48
|
coingeckId: undefined,
|
|
49
49
|
priceCheckAmount: 0.1,
|
|
50
50
|
displayDecimals: 6,
|
|
51
|
-
}, {
|
|
51
|
+
}, {
|
|
52
52
|
name: 'USDC.e',
|
|
53
53
|
symbol: 'USDC.e',
|
|
54
54
|
logo: 'https://assets.troves.fi/integrations/tokens/usdc.svg',
|
|
@@ -58,7 +58,7 @@ const defaultTokens: TokenInfo[] = [
|
|
|
58
58
|
displayDecimals: 2,
|
|
59
59
|
priceCheckAmount: 1000,
|
|
60
60
|
priceProxySymbol: 'USDC'
|
|
61
|
-
}, {
|
|
61
|
+
}, {
|
|
62
62
|
name: 'USDC',
|
|
63
63
|
symbol: 'USDC',
|
|
64
64
|
logo: 'https://assets.troves.fi/integrations/tokens/usdc.svg',
|
|
@@ -169,7 +169,7 @@ const defaultTokens: TokenInfo[] = [
|
|
|
169
169
|
displayDecimals: 6,
|
|
170
170
|
priceCheckAmount: 0.001, // 112000 * 0.0001 = $110.2
|
|
171
171
|
priceProxySymbol: 'WBTC',
|
|
172
|
-
}, {
|
|
172
|
+
}, {
|
|
173
173
|
name: 'xLBTC',
|
|
174
174
|
symbol: 'xLBTC',
|
|
175
175
|
logo: 'https://assets.strkfarm.com/integrations/tokens/xlbtc.svg',
|
|
@@ -191,19 +191,18 @@ const defaultTokens: TokenInfo[] = [
|
|
|
191
191
|
coingeckId: undefined,
|
|
192
192
|
displayDecimals: 6,
|
|
193
193
|
priceCheckAmount: 0.0001, // 112000 * 0.0001 = $11.2
|
|
194
|
-
|
|
195
|
-
{
|
|
196
|
-
name:
|
|
197
|
-
symbol:
|
|
198
|
-
logo:
|
|
199
|
-
address: ContractAddr.from(
|
|
200
|
-
"0x4be8945e61dc3e19ebadd1579a6bd53b262f51ba89e6f8b0c4bc9a7e3c633fc"
|
|
201
|
-
),
|
|
194
|
+
dontPrice: true,
|
|
195
|
+
}, {
|
|
196
|
+
name: 'mRe7YIELD',
|
|
197
|
+
symbol: 'mRe7YIELD',
|
|
198
|
+
logo: 'https://midas.app/assets/mre7-BcOOHm7i.svg',
|
|
199
|
+
address: ContractAddr.from('0x4be8945e61dc3e19ebadd1579a6bd53b262f51ba89e6f8b0c4bc9a7e3c633fc'),
|
|
202
200
|
decimals: 18,
|
|
203
201
|
coingeckId: undefined,
|
|
204
202
|
displayDecimals: 2,
|
|
205
203
|
priceCheckAmount: 100,
|
|
206
|
-
|
|
204
|
+
dontPrice: true,
|
|
205
|
+
}, {
|
|
207
206
|
name: "fyWBTC",
|
|
208
207
|
symbol: "fyWBTC",
|
|
209
208
|
logo: 'https://assets.strkfarm.com/integrations/tokens/wbtc.svg',
|
|
@@ -212,7 +211,8 @@ const defaultTokens: TokenInfo[] = [
|
|
|
212
211
|
coingeckId: undefined,
|
|
213
212
|
displayDecimals: 6,
|
|
214
213
|
priceCheckAmount: 0.001, // 112000 * 0.0001 = $110.2
|
|
215
|
-
|
|
214
|
+
dontPrice: true,
|
|
215
|
+
}, {
|
|
216
216
|
name: "fyETH",
|
|
217
217
|
symbol: "fyETH",
|
|
218
218
|
logo: 'https://assets.strkfarm.com/integrations/tokens/eth.svg',
|
|
@@ -221,7 +221,8 @@ const defaultTokens: TokenInfo[] = [
|
|
|
221
221
|
coingeckId: undefined,
|
|
222
222
|
displayDecimals: 4,
|
|
223
223
|
priceCheckAmount: 0.1,
|
|
224
|
-
|
|
224
|
+
dontPrice: true,
|
|
225
|
+
}, {
|
|
225
226
|
name: "fyUSDC",
|
|
226
227
|
symbol: "fyUSDC",
|
|
227
228
|
logo: 'https://assets.strkfarm.com/integrations/tokens/usdc.svg',
|
|
@@ -230,7 +231,8 @@ const defaultTokens: TokenInfo[] = [
|
|
|
230
231
|
coingeckId: undefined,
|
|
231
232
|
displayDecimals: 2,
|
|
232
233
|
priceCheckAmount: 100,
|
|
233
|
-
|
|
234
|
+
dontPrice: true,
|
|
235
|
+
}, {
|
|
234
236
|
name: 'strkBTC',
|
|
235
237
|
symbol: 'strkBTC',
|
|
236
238
|
logo: 'https://assets.troves.fi/integrations/tokens/strkbtc.svg',
|
|
@@ -240,7 +242,7 @@ const defaultTokens: TokenInfo[] = [
|
|
|
240
242
|
displayDecimals: 6,
|
|
241
243
|
priceCheckAmount: 0.001, // 112000 * 0.0001 = $110.2
|
|
242
244
|
priceProxySymbol: 'WBTC',
|
|
243
|
-
}, {
|
|
245
|
+
}, {
|
|
244
246
|
name: 'xstrkBTC',
|
|
245
247
|
symbol: 'xstrkBTC',
|
|
246
248
|
logo: 'https://assets.troves.fi/integrations/tokens/xstrkbtc.svg',
|
|
@@ -250,7 +252,7 @@ const defaultTokens: TokenInfo[] = [
|
|
|
250
252
|
displayDecimals: 6,
|
|
251
253
|
priceCheckAmount: 0.001,
|
|
252
254
|
priceProxySymbol: 'WBTC',
|
|
253
|
-
},]
|
|
255
|
+
},]
|
|
254
256
|
const tokens: TokenInfo[] = defaultTokens;
|
|
255
257
|
|
|
256
258
|
/** Contains globally useful functions.
|
|
@@ -333,14 +335,14 @@ export class Global {
|
|
|
333
335
|
static async getTokenInfoFromName(tokenName: string) {
|
|
334
336
|
// if tokens are not loaded, load them
|
|
335
337
|
if (tokens.length == defaultTokens.length) {
|
|
336
|
-
|
|
338
|
+
await Global.getTokens();
|
|
337
339
|
}
|
|
338
340
|
|
|
339
341
|
const token = tokens.find(
|
|
340
|
-
|
|
342
|
+
(token) => token.name.toLowerCase() === tokenName.toLowerCase()
|
|
341
343
|
);
|
|
342
344
|
if (!token) {
|
|
343
|
-
|
|
345
|
+
throw new FatalError(`Token not found: ${tokenName}`);
|
|
344
346
|
}
|
|
345
347
|
return token;
|
|
346
348
|
}
|
|
@@ -348,30 +350,30 @@ export class Global {
|
|
|
348
350
|
static async getTokenInfoFromAddr(addr: ContractAddr) {
|
|
349
351
|
// if tokens are not loaded, load them
|
|
350
352
|
if (tokens.length == defaultTokens.length) {
|
|
351
|
-
|
|
353
|
+
await Global.getTokens();
|
|
352
354
|
}
|
|
353
355
|
const token = tokens.find((token) => addr.eq(token.address));
|
|
354
356
|
if (!token) {
|
|
355
|
-
|
|
357
|
+
throw new FatalError(`Token not found: ${addr.address}`);
|
|
356
358
|
}
|
|
357
359
|
return token;
|
|
358
360
|
}
|
|
359
361
|
|
|
360
362
|
static setGlobalCache(key: string, data: any, ttl: number = 60000) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
363
|
+
Global.cache[key] = {
|
|
364
|
+
value: data,
|
|
365
|
+
ttl,
|
|
366
|
+
timestamp: Date.now()
|
|
367
|
+
};
|
|
366
368
|
}
|
|
367
369
|
|
|
368
370
|
static getGlobalCache<T>(key: string): T | null {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
371
|
+
const cached = Global.cache[key];
|
|
372
|
+
if (!cached) return null;
|
|
373
|
+
if (Date.now() - cached.timestamp > cached.ttl) {
|
|
374
|
+
delete Global.cache[key];
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
return cached.value;
|
|
376
378
|
}
|
|
377
379
|
}
|
|
@@ -35,6 +35,7 @@ export interface TokenInfo {
|
|
|
35
35
|
displayDecimals: number;
|
|
36
36
|
priceProxySymbol?: string; // for tokens like illiquid tokens, we use a proxy symbol to get the price
|
|
37
37
|
priceCheckAmount?: number; // for tokens like BTC, doing 1BTC price check may not be ideal, esp on illiquid netwrks like sn
|
|
38
|
+
dontPrice?: boolean; // a flag that skips pricer to check these tokens.
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export enum Network {
|
|
@@ -174,6 +175,10 @@ export interface StrategyApyHistoryUIConfig {
|
|
|
174
175
|
noApyHistoryMessage?: string;
|
|
175
176
|
}
|
|
176
177
|
|
|
178
|
+
export interface FeeBps {
|
|
179
|
+
performanceFeeBps: number;
|
|
180
|
+
}
|
|
181
|
+
|
|
177
182
|
/**
|
|
178
183
|
* @property risk.riskFactor.factor - The risk factors that are considered for the strategy.
|
|
179
184
|
* @property risk.riskFactor.factor - The value of the risk factor from 0 to 10, 0 being the lowest and 10 being the highest.
|
|
@@ -214,6 +219,7 @@ export interface IStrategyMetadata<T> {
|
|
|
214
219
|
};
|
|
215
220
|
apyMethodology?: string;
|
|
216
221
|
realizedApyMethodology?: string;
|
|
222
|
+
feeBps?: FeeBps;
|
|
217
223
|
additionalInfo: T;
|
|
218
224
|
contractDetails: {
|
|
219
225
|
address: ContractAddr;
|
package/src/modules/index.ts
CHANGED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { TokenInfo } from "@/interfaces/common";
|
|
3
|
+
import { IConfig } from "@/interfaces/common";
|
|
4
|
+
import { PricerBase } from "./pricerBase";
|
|
5
|
+
import { PriceInfo } from "./pricer";
|
|
6
|
+
import { logger } from "@/utils/logger";
|
|
7
|
+
import { ContractAddr } from "@/dataTypes";
|
|
8
|
+
|
|
9
|
+
const AVNU_TOKENS_API = "https://starknet.impulse.avnu.fi/v3/tokens";
|
|
10
|
+
|
|
11
|
+
interface AvnuTokenApiEntry {
|
|
12
|
+
address: string;
|
|
13
|
+
symbol: string;
|
|
14
|
+
starknet?: {
|
|
15
|
+
usd?: number;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Polls Avnu impulse tokens API and keeps USD prices in memory for configured tokens.
|
|
21
|
+
* Price timestamp is set when each poll request completes.
|
|
22
|
+
*/
|
|
23
|
+
export class PricerAvnuApi extends PricerBase {
|
|
24
|
+
protected prices: { [key: string]: PriceInfo } = {};
|
|
25
|
+
|
|
26
|
+
readonly refreshInterval = 15_000;
|
|
27
|
+
readonly staleTime = 5 * 60 * 1000;
|
|
28
|
+
|
|
29
|
+
private pollTimer: ReturnType<typeof setInterval> | null = null;
|
|
30
|
+
private loading = false;
|
|
31
|
+
|
|
32
|
+
constructor(config: IConfig, tokens: TokenInfo[]) {
|
|
33
|
+
super(config, tokens);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
start() {
|
|
37
|
+
this._loadPrices();
|
|
38
|
+
this.pollTimer = setInterval(() => {
|
|
39
|
+
this._loadPrices();
|
|
40
|
+
}, this.refreshInterval);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
stop() {
|
|
44
|
+
if (this.pollTimer) {
|
|
45
|
+
clearInterval(this.pollTimer);
|
|
46
|
+
this.pollTimer = null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
isStale(timestamp: Date) {
|
|
51
|
+
return Date.now() - timestamp.getTime() > this.staleTime;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
hasPrice(tokenSymbol: string) {
|
|
55
|
+
const info = this.prices[tokenSymbol];
|
|
56
|
+
return !!info && !this.isStale(info.timestamp);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async getPrice(tokenSymbol: string): Promise<PriceInfo> {
|
|
60
|
+
const info = this.prices[tokenSymbol];
|
|
61
|
+
if (!info) {
|
|
62
|
+
throw new Error(`AvnuApi: price of ${tokenSymbol} not found`);
|
|
63
|
+
}
|
|
64
|
+
if (this.isStale(info.timestamp)) {
|
|
65
|
+
throw new Error(`AvnuApi: price of ${tokenSymbol} is stale`);
|
|
66
|
+
}
|
|
67
|
+
return info;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
protected async _loadPrices() {
|
|
71
|
+
if (this.loading) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
this.loading = true;
|
|
75
|
+
const timestamp = new Date();
|
|
76
|
+
try {
|
|
77
|
+
const result = await axios.get<AvnuTokenApiEntry[]>(AVNU_TOKENS_API);
|
|
78
|
+
const priceByAddress = new Map<string, number>();
|
|
79
|
+
for (const entry of result.data) {
|
|
80
|
+
const usd = entry.starknet?.usd;
|
|
81
|
+
if (usd != null && usd > 0) {
|
|
82
|
+
priceByAddress.set(ContractAddr.standardise(entry.address), usd);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
for (const token of this.tokens) {
|
|
87
|
+
if (token.symbol === "USDT" || token.symbol === "USDC") {
|
|
88
|
+
this.prices[token.symbol] = { price: 1, timestamp };
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const targetToken = token.priceProxySymbol
|
|
93
|
+
? this.tokens.find((t) => t.symbol === token.priceProxySymbol)
|
|
94
|
+
: token;
|
|
95
|
+
if (!targetToken) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const addr = targetToken.address.address;
|
|
100
|
+
const price = priceByAddress.get(addr);
|
|
101
|
+
if (price != null) {
|
|
102
|
+
this.prices[token.symbol] = { price, timestamp };
|
|
103
|
+
logger.verbose(
|
|
104
|
+
`AvnuApi: ${token.symbol} -> $${price}`,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
} catch (error: any) {
|
|
109
|
+
logger.warn(`AvnuApi: failed to fetch tokens: ${error?.message ?? error}`);
|
|
110
|
+
} finally {
|
|
111
|
+
this.loading = false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
package/src/modules/pricer.ts
CHANGED
|
@@ -7,12 +7,23 @@ import { PricerBase } from "./pricerBase";
|
|
|
7
7
|
import { logger } from "@/utils/logger";
|
|
8
8
|
import { AvnuWrapper } from "./avnu";
|
|
9
9
|
import { BlockIdentifier } from "starknet";
|
|
10
|
+
import { PricerAvnuApi } from "./pricer-avnu-api";
|
|
10
11
|
|
|
11
12
|
export interface PriceInfo {
|
|
12
13
|
price: number,
|
|
13
14
|
timestamp: Date
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
type PriceMethod = 'AvnuApi' | 'Coinbase' | 'Coinmarketcap' | 'Ekubo' | 'Avnu';
|
|
18
|
+
|
|
19
|
+
const PRICE_METHOD_PRIORITY: PriceMethod[] = [
|
|
20
|
+
'AvnuApi',
|
|
21
|
+
'Coinbase',
|
|
22
|
+
'Coinmarketcap',
|
|
23
|
+
'Ekubo',
|
|
24
|
+
'Avnu',
|
|
25
|
+
];
|
|
26
|
+
|
|
16
27
|
export class Pricer extends PricerBase {
|
|
17
28
|
protected prices: {
|
|
18
29
|
[key: string]: PriceInfo
|
|
@@ -21,9 +32,11 @@ export class Pricer extends PricerBase {
|
|
|
21
32
|
refreshInterval = 30000;
|
|
22
33
|
staleTime = 60000;
|
|
23
34
|
|
|
35
|
+
protected readonly avnuApiPricer: PricerAvnuApi;
|
|
36
|
+
|
|
24
37
|
// code populates this map during runtime to determine which method to use for a given token
|
|
25
38
|
// The method set will be the first one to try after first attempt
|
|
26
|
-
protected methodToUse: {[tokenSymbol: string]:
|
|
39
|
+
protected methodToUse: {[tokenSymbol: string]: PriceMethod} = {};
|
|
27
40
|
|
|
28
41
|
/**
|
|
29
42
|
* TOKENA and TOKENB are the two token names to get price of TokenA in terms of TokenB
|
|
@@ -36,6 +49,7 @@ export class Pricer extends PricerBase {
|
|
|
36
49
|
super(config, tokens);
|
|
37
50
|
this.refreshInterval = refreshInterval;
|
|
38
51
|
this.staleTime = staleTime;
|
|
52
|
+
this.avnuApiPricer = new PricerAvnuApi(config, tokens);
|
|
39
53
|
}
|
|
40
54
|
|
|
41
55
|
isReady() {
|
|
@@ -69,6 +83,7 @@ export class Pricer extends PricerBase {
|
|
|
69
83
|
}
|
|
70
84
|
|
|
71
85
|
start() {
|
|
86
|
+
this.avnuApiPricer.start();
|
|
72
87
|
this._loadPrices();
|
|
73
88
|
setInterval(() => {
|
|
74
89
|
this._loadPrices();
|
|
@@ -96,6 +111,9 @@ export class Pricer extends PricerBase {
|
|
|
96
111
|
let retry = 0;
|
|
97
112
|
while (retry < MAX_RETRIES) {
|
|
98
113
|
try {
|
|
114
|
+
if (token.dontPrice) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
99
117
|
if (token.symbol === 'USDT' || token.symbol === 'USDC') {
|
|
100
118
|
this.prices[token.symbol] = {
|
|
101
119
|
price: 1,
|
|
@@ -145,56 +163,56 @@ export class Pricer extends PricerBase {
|
|
|
145
163
|
}
|
|
146
164
|
}
|
|
147
165
|
|
|
148
|
-
async _getPrice(token: TokenInfo
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
166
|
+
async _getPrice(token: TokenInfo): Promise<number> {
|
|
167
|
+
const pinned = this.methodToUse[token.symbol];
|
|
168
|
+
if (pinned) {
|
|
169
|
+
logger.verbose(`Fetching price of ${token.symbol} using pinned ${pinned}`);
|
|
170
|
+
try {
|
|
171
|
+
return await this._tryPriceMethod(token, pinned);
|
|
172
|
+
} catch (error: any) {
|
|
173
|
+
console.warn(`${pinned}: pinned price failed [${token.symbol}]: `, error.message);
|
|
174
|
+
delete this.methodToUse[token.symbol];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
for (const method of PRICE_METHOD_PRIORITY) {
|
|
179
|
+
logger.verbose(`Fetching price of ${token.symbol} using ${method}`);
|
|
180
|
+
try {
|
|
181
|
+
const result = await this._tryPriceMethod(token, method);
|
|
182
|
+
this.methodToUse[token.symbol] = method;
|
|
183
|
+
return result;
|
|
184
|
+
} catch (error: any) {
|
|
185
|
+
console.warn(`${method}: price err [${token.symbol}]: `, error.message);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
throw new FatalError(`Price not found for ${token.symbol}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
protected async _tryPriceMethod(token: TokenInfo, method: PriceMethod): Promise<number> {
|
|
193
|
+
switch (method) {
|
|
194
|
+
case 'AvnuApi':
|
|
195
|
+
return await this._getPriceAvnuApi(token);
|
|
152
196
|
case 'Coinbase':
|
|
153
|
-
|
|
154
|
-
// const result = await this._getPriceCoinbase(token);
|
|
155
|
-
// this.methodToUse[token.symbol] = 'Coinbase';
|
|
156
|
-
// return result;
|
|
157
|
-
// } catch (error: any) {
|
|
158
|
-
// console.warn(`Coinbase: price err: message [${token.symbol}]: `, error.message);
|
|
159
|
-
// // do nothing, try next
|
|
160
|
-
// }
|
|
197
|
+
return await this._getPriceCoinbase(token);
|
|
161
198
|
case 'Coinmarketcap':
|
|
162
|
-
|
|
163
|
-
const result = await this._getPriceCoinMarketCap(token);
|
|
164
|
-
this.methodToUse[token.symbol] = 'Coinmarketcap';
|
|
165
|
-
return result;
|
|
166
|
-
} catch (error: any) {
|
|
167
|
-
console.warn(`CoinMarketCap: price err [${token.symbol}]: `, Object.keys(error));
|
|
168
|
-
console.warn(`CoinMarketCap: price err [${token.symbol}]: `, error.message);
|
|
169
|
-
}
|
|
199
|
+
return await this._getPriceCoinMarketCap(token);
|
|
170
200
|
case 'Ekubo':
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
} catch (error: any) {
|
|
176
|
-
console.warn(`Ekubo: price err [${token.symbol}]: `, error.message);
|
|
177
|
-
console.warn(`Ekubo: price err [${token.symbol}]: `, Object.keys(error));
|
|
178
|
-
// do nothing, try next
|
|
179
|
-
}
|
|
201
|
+
return await this._getPriceEkubo(
|
|
202
|
+
token,
|
|
203
|
+
new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals),
|
|
204
|
+
);
|
|
180
205
|
case 'Avnu':
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
} catch (error: any) {
|
|
186
|
-
console.warn(`Avnu: price err [${token.symbol}]: `, error.message);
|
|
187
|
-
console.warn(`Avnu: price err [${token.symbol}]: `, Object.keys(error));
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// if methodToUse is the default one, pass Coinbase to try all from start
|
|
192
|
-
if (defaultMethod == 'all') {
|
|
193
|
-
// try again with coinbase
|
|
194
|
-
return await this._getPrice(token, 'Coinbase');
|
|
206
|
+
return await this._getAvnuPrice(
|
|
207
|
+
token,
|
|
208
|
+
new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals),
|
|
209
|
+
);
|
|
195
210
|
}
|
|
211
|
+
}
|
|
196
212
|
|
|
197
|
-
|
|
213
|
+
async _getPriceAvnuApi(token: TokenInfo): Promise<number> {
|
|
214
|
+
const priceInfo = await this.avnuApiPricer.getPrice(token.symbol);
|
|
215
|
+
return priceInfo.price;
|
|
198
216
|
}
|
|
199
217
|
|
|
200
218
|
async _getPriceCoinbase(token: TokenInfo) {
|
package/src/node/pricer-redis.ts
CHANGED
|
@@ -18,6 +18,7 @@ export class PricerRedis extends Pricer {
|
|
|
18
18
|
await this.initRedis(redisUrl);
|
|
19
19
|
|
|
20
20
|
logger.info(`Starting Pricer with Redis`);
|
|
21
|
+
this.avnuApiPricer.start();
|
|
21
22
|
this._loadPrices(this._setRedisPrices.bind(this));
|
|
22
23
|
setInterval(() => {
|
|
23
24
|
this._loadPrices(this._setRedisPrices.bind(this));
|
|
@@ -2452,6 +2452,9 @@ const xSTRKSTRK: IStrategyMetadata<CLVaultStrategySettings> = {
|
|
|
2452
2452
|
apyMethodology:
|
|
2453
2453
|
"APY based on 30-day historical performance, including fees and rewards.",
|
|
2454
2454
|
realizedApyMethodology: "The realizedAPY is based on past 14 days performance by the vault",
|
|
2455
|
+
feeBps: {
|
|
2456
|
+
performanceFeeBps: 1000,
|
|
2457
|
+
},
|
|
2455
2458
|
additionalInfo: {
|
|
2456
2459
|
newBounds: {
|
|
2457
2460
|
lower: -1,
|