@strkfarm/sdk 1.0.38 → 1.0.39
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 +38 -712
- package/dist/cli.mjs +37 -715
- package/dist/index.browser.global.js +101 -25
- package/dist/index.browser.mjs +101 -25
- package/dist/index.d.ts +19 -50
- package/dist/index.js +129 -23
- package/dist/index.mjs +129 -23
- package/package.json +3 -3
- package/src/dataTypes/_bignumber.ts +49 -47
- package/src/global.ts +1 -33
- package/src/interfaces/common.ts +1 -0
- package/src/interfaces/lending.ts +1 -2
- package/src/modules/avnu.ts +1 -1
- package/src/modules/erc20.ts +6 -0
- package/src/modules/harvests.ts +1 -1
- package/src/modules/pragma.ts +1 -1
- package/src/modules/pricer-from-api.ts +3 -3
- package/src/modules/pricer.ts +2 -1
- package/src/modules/zkLend.ts +2 -1
- package/src/node/pricer-redis.ts +2 -1
- package/src/notifs/telegram.ts +1 -1
- package/src/strategies/ekubo-cl-vault.tsx +91 -19
- package/src/strategies/vesu-rebalance.tsx +6 -1
- package/src/utils/index.ts +2 -0
- package/src/utils/logger.browser.ts +20 -0
- package/src/utils/logger.node.ts +35 -0
- package/src/utils/logger.ts +1 -0
- package/src/utils/store.ts +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import inquirer from "inquirer";
|
|
|
6
6
|
|
|
7
7
|
// src/utils/store.ts
|
|
8
8
|
import fs, { readFileSync, writeFileSync } from "fs";
|
|
9
|
-
import { Account
|
|
9
|
+
import { Account, constants } from "starknet";
|
|
10
10
|
import * as crypto2 from "crypto";
|
|
11
11
|
|
|
12
12
|
// src/utils/encrypt.ts
|
|
@@ -58,720 +58,42 @@ var PasswordJsonCryptoUtil = class {
|
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
// src/
|
|
62
|
-
import
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// src/dataTypes/_bignumber.ts
|
|
71
|
-
import BigNumber from "bignumber.js";
|
|
72
|
-
var _Web3Number = class extends BigNumber {
|
|
73
|
-
constructor(value, decimals) {
|
|
74
|
-
super(value);
|
|
75
|
-
this.decimals = decimals;
|
|
76
|
-
}
|
|
77
|
-
toWei() {
|
|
78
|
-
return this.mul(10 ** this.decimals).toFixed(0);
|
|
79
|
-
}
|
|
80
|
-
multipliedBy(value) {
|
|
81
|
-
const _value = this.getStandardString(value);
|
|
82
|
-
return this.construct(this.mul(_value).toString(), this.decimals);
|
|
83
|
-
}
|
|
84
|
-
dividedBy(value) {
|
|
85
|
-
const _value = this.getStandardString(value);
|
|
86
|
-
return this.construct(this.div(_value).toString(), this.decimals);
|
|
87
|
-
}
|
|
88
|
-
plus(value) {
|
|
89
|
-
const _value = this.getStandardString(value);
|
|
90
|
-
return this.construct(this.add(_value).toString(), this.decimals);
|
|
91
|
-
}
|
|
92
|
-
minus(n, base) {
|
|
93
|
-
const _value = this.getStandardString(n);
|
|
94
|
-
return this.construct(super.minus(_value, base).toString(), this.decimals);
|
|
95
|
-
}
|
|
96
|
-
construct(value, decimals) {
|
|
97
|
-
return new this.constructor(value, decimals);
|
|
98
|
-
}
|
|
99
|
-
toString(decimals = this.maxToFixedDecimals()) {
|
|
100
|
-
return super.toFixed(decimals);
|
|
101
|
-
}
|
|
102
|
-
toJSON() {
|
|
103
|
-
return this.toString();
|
|
104
|
-
}
|
|
105
|
-
valueOf() {
|
|
106
|
-
return this.toString();
|
|
107
|
-
}
|
|
108
|
-
maxToFixedDecimals() {
|
|
109
|
-
return Math.min(this.decimals, 18);
|
|
110
|
-
}
|
|
111
|
-
getStandardString(value) {
|
|
112
|
-
if (typeof value == "string") {
|
|
113
|
-
return value;
|
|
114
|
-
}
|
|
115
|
-
return value.toFixed(this.maxToFixedDecimals());
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
BigNumber.config({ DECIMAL_PLACES: 18, ROUNDING_MODE: BigNumber.ROUND_DOWN });
|
|
119
|
-
_Web3Number.config({ DECIMAL_PLACES: 18, ROUNDING_MODE: BigNumber.ROUND_DOWN });
|
|
120
|
-
|
|
121
|
-
// src/dataTypes/bignumber.node.ts
|
|
122
|
-
var Web3Number = class _Web3Number2 extends _Web3Number {
|
|
123
|
-
static fromWei(weiNumber, decimals) {
|
|
124
|
-
const bn = new _Web3Number2(weiNumber, decimals).dividedBy(10 ** decimals);
|
|
125
|
-
return new _Web3Number2(bn.toString(), decimals);
|
|
126
|
-
}
|
|
127
|
-
[util.inspect.custom](depth, opts) {
|
|
128
|
-
return this.toString();
|
|
129
|
-
}
|
|
130
|
-
[Symbol.for("nodejs.util.inspect.custom")](depth, inspectOptions, inspect) {
|
|
131
|
-
return this.toString();
|
|
132
|
-
}
|
|
133
|
-
inspect(depth, opts) {
|
|
134
|
-
return this.toString();
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
// src/dataTypes/address.ts
|
|
139
|
-
import { num } from "starknet";
|
|
140
|
-
var ContractAddr = class _ContractAddr {
|
|
141
|
-
constructor(address) {
|
|
142
|
-
this.address = _ContractAddr.standardise(address);
|
|
143
|
-
}
|
|
144
|
-
static from(address) {
|
|
145
|
-
return new _ContractAddr(address);
|
|
146
|
-
}
|
|
147
|
-
eq(other) {
|
|
148
|
-
return this.address === other.address;
|
|
149
|
-
}
|
|
150
|
-
eqString(other) {
|
|
151
|
-
return this.address === _ContractAddr.standardise(other);
|
|
152
|
-
}
|
|
153
|
-
static standardise(address) {
|
|
154
|
-
let _a = address;
|
|
155
|
-
if (!address) {
|
|
156
|
-
_a = "0";
|
|
157
|
-
}
|
|
158
|
-
const a = num.getHexString(num.getDecimalString(_a.toString()));
|
|
159
|
-
return a;
|
|
160
|
-
}
|
|
161
|
-
static eqString(a, b) {
|
|
162
|
-
return _ContractAddr.standardise(a) === _ContractAddr.standardise(b);
|
|
163
|
-
}
|
|
164
|
-
toString() {
|
|
165
|
-
return this.address;
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// src/global.ts
|
|
170
|
-
var logger = {
|
|
171
|
-
...console,
|
|
172
|
-
verbose(message) {
|
|
173
|
-
console.log(`[VERBOSE] ${message}`);
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
var FatalError = class extends Error {
|
|
177
|
-
constructor(message, err) {
|
|
178
|
-
super(message);
|
|
179
|
-
logger.error(message);
|
|
180
|
-
if (err)
|
|
181
|
-
logger.error(err.message);
|
|
182
|
-
this.name = "FatalError";
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
var defaultTokens = [{
|
|
186
|
-
name: "Starknet",
|
|
187
|
-
symbol: "STRK",
|
|
188
|
-
logo: "https://assets.strkfarm.com/integrations/tokens/strk.svg",
|
|
189
|
-
address: ContractAddr.from("0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d"),
|
|
190
|
-
decimals: 18,
|
|
191
|
-
coingeckId: "starknet",
|
|
192
|
-
displayDecimals: 2
|
|
193
|
-
}, {
|
|
194
|
-
name: "xSTRK",
|
|
195
|
-
symbol: "xSTRK",
|
|
196
|
-
logo: "https://assets.strkfarm.com/integrations/tokens/xstrk.svg",
|
|
197
|
-
address: ContractAddr.from("0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"),
|
|
198
|
-
decimals: 18,
|
|
199
|
-
coingeckId: void 0,
|
|
200
|
-
displayDecimals: 2
|
|
201
|
-
}, {
|
|
202
|
-
name: "ETH",
|
|
203
|
-
symbol: "ETH",
|
|
204
|
-
logo: "https://assets.strkfarm.com/integrations/tokens/eth.svg",
|
|
205
|
-
address: ContractAddr.from("0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"),
|
|
206
|
-
decimals: 18,
|
|
207
|
-
coingeckId: void 0,
|
|
208
|
-
displayDecimals: 4
|
|
209
|
-
}, {
|
|
210
|
-
name: "USDC",
|
|
211
|
-
symbol: "USDC",
|
|
212
|
-
logo: "https://assets.strkfarm.com/integrations/tokens/usdc.svg",
|
|
213
|
-
address: ContractAddr.from("0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"),
|
|
214
|
-
decimals: 6,
|
|
215
|
-
coingeckId: void 0,
|
|
216
|
-
displayDecimals: 2
|
|
217
|
-
}, {
|
|
218
|
-
name: "USDT",
|
|
219
|
-
symbol: "USDT",
|
|
220
|
-
logo: "https://assets.strkfarm.com/integrations/tokens/usdt.svg",
|
|
221
|
-
address: ContractAddr.from("0x68f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8"),
|
|
222
|
-
decimals: 6,
|
|
223
|
-
coingeckId: void 0,
|
|
224
|
-
displayDecimals: 2
|
|
225
|
-
}, {
|
|
226
|
-
name: "WBTC",
|
|
227
|
-
symbol: "WBTC",
|
|
228
|
-
logo: "https://assets.strkfarm.com/integrations/tokens/wbtc.svg",
|
|
229
|
-
address: ContractAddr.from("0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac"),
|
|
230
|
-
decimals: 8,
|
|
231
|
-
coingeckId: void 0,
|
|
232
|
-
displayDecimals: 6
|
|
233
|
-
}];
|
|
234
|
-
var tokens = defaultTokens;
|
|
235
|
-
var Global = class _Global {
|
|
236
|
-
static fatalError(message, err) {
|
|
237
|
-
logger.error(message);
|
|
238
|
-
console.error(message, err);
|
|
239
|
-
if (err)
|
|
240
|
-
console.error(err);
|
|
241
|
-
process.exit(1);
|
|
242
|
-
}
|
|
243
|
-
static httpError(url, err, message) {
|
|
244
|
-
logger.error(`${url}: ${message}`);
|
|
245
|
-
console.error(err);
|
|
246
|
-
}
|
|
247
|
-
static getDefaultTokens() {
|
|
248
|
-
return tokens;
|
|
249
|
-
}
|
|
250
|
-
static async getTokens() {
|
|
251
|
-
if (tokens.length) return tokens;
|
|
252
|
-
const data = await axios.get("https://assets.strkfarm.com/integrations/tokens.json");
|
|
253
|
-
const tokensData = data.data.content;
|
|
254
|
-
tokensData.forEach((token) => {
|
|
255
|
-
if (!token.tags.includes("AVNU") || !token.tags.includes("Verified")) {
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
tokens.push({
|
|
259
|
-
name: token.name,
|
|
260
|
-
symbol: token.symbol,
|
|
261
|
-
address: ContractAddr.from(token.address),
|
|
262
|
-
decimals: token.decimals,
|
|
263
|
-
logo: token.logoUri,
|
|
264
|
-
coingeckId: token.extensions.coingeckoId,
|
|
265
|
-
displayDecimals: 2
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
console.log(tokens);
|
|
269
|
-
return tokens;
|
|
270
|
-
}
|
|
271
|
-
static assert(condition, message) {
|
|
272
|
-
if (!condition) {
|
|
273
|
-
throw new FatalError(message);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
static async getTokenInfoFromAddr(addr) {
|
|
277
|
-
if (tokens.length == defaultTokens.length) {
|
|
278
|
-
await _Global.getTokens();
|
|
279
|
-
}
|
|
280
|
-
const token = tokens.find((token2) => addr.eq(token2.address));
|
|
281
|
-
if (!token) {
|
|
282
|
-
throw new FatalError(`Token not found: ${addr.address}`);
|
|
283
|
-
}
|
|
284
|
-
return token;
|
|
285
|
-
}
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
// src/modules/pragma.ts
|
|
289
|
-
import { Contract } from "starknet";
|
|
290
|
-
|
|
291
|
-
// src/modules/zkLend.ts
|
|
292
|
-
import axios3 from "axios";
|
|
293
|
-
|
|
294
|
-
// src/dataTypes/bignumber.browser.ts
|
|
295
|
-
var Web3Number2 = class _Web3Number2 extends _Web3Number {
|
|
296
|
-
static fromWei(weiNumber, decimals) {
|
|
297
|
-
const bn = new _Web3Number2(weiNumber, decimals).dividedBy(10 ** decimals);
|
|
298
|
-
return new _Web3Number2(bn.toString(), decimals);
|
|
299
|
-
}
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
// src/interfaces/lending.ts
|
|
303
|
-
var ILending = class {
|
|
304
|
-
constructor(config, metadata) {
|
|
305
|
-
this.tokens = [];
|
|
306
|
-
this.initialised = false;
|
|
307
|
-
this.metadata = metadata;
|
|
308
|
-
this.config = config;
|
|
309
|
-
this.init();
|
|
310
|
-
}
|
|
311
|
-
/** Wait for initialisation */
|
|
312
|
-
waitForInitilisation() {
|
|
313
|
-
return new Promise((resolve, reject) => {
|
|
314
|
-
const interval = setInterval(() => {
|
|
315
|
-
logger.verbose(`Waiting for ${this.metadata.name} to initialise`);
|
|
316
|
-
if (this.initialised) {
|
|
317
|
-
logger.verbose(`${this.metadata.name} initialised`);
|
|
318
|
-
clearInterval(interval);
|
|
319
|
-
resolve();
|
|
320
|
-
}
|
|
321
|
-
}, 1e3);
|
|
322
|
-
});
|
|
323
|
-
}
|
|
61
|
+
// src/utils/logger.node.ts
|
|
62
|
+
import winston, { format } from "winston";
|
|
63
|
+
var colors = {
|
|
64
|
+
error: "red",
|
|
65
|
+
warn: "yellow",
|
|
66
|
+
info: "blue",
|
|
67
|
+
verbose: "white",
|
|
68
|
+
debug: "white"
|
|
324
69
|
};
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
})
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
data.forEach((pool) => {
|
|
343
|
-
let collareralFactor = new Web3Number2(0, 0);
|
|
344
|
-
if (pool.collateral_factor) {
|
|
345
|
-
collareralFactor = Web3Number2.fromWei(pool.collateral_factor.value, pool.collateral_factor.decimals);
|
|
70
|
+
winston.addColors(colors);
|
|
71
|
+
var logger = winston.createLogger({
|
|
72
|
+
level: "verbose",
|
|
73
|
+
// Set the minimum logging level
|
|
74
|
+
format: format.combine(
|
|
75
|
+
format.colorize({ all: true }),
|
|
76
|
+
// Apply custom colors
|
|
77
|
+
format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
|
|
78
|
+
// Add timestamp to log messages
|
|
79
|
+
format.printf(({ timestamp, level, message, ...meta }) => {
|
|
80
|
+
let msg = `${timestamp} ${level}: ${message}`;
|
|
81
|
+
if (meta && meta[Symbol.for("splat")]) {
|
|
82
|
+
for (const arg of meta[Symbol.for("splat")]) {
|
|
83
|
+
if (arg instanceof Error) {
|
|
84
|
+
msg += `
|
|
85
|
+
${arg.stack}`;
|
|
86
|
+
}
|
|
346
87
|
}
|
|
347
|
-
const savedTokenInfo = savedTokens.find((t) => t.symbol == pool.token.symbol);
|
|
348
|
-
const token = {
|
|
349
|
-
name: pool.token.name,
|
|
350
|
-
symbol: pool.token.symbol,
|
|
351
|
-
address: savedTokenInfo?.address || ContractAddr.from(""),
|
|
352
|
-
logo: "",
|
|
353
|
-
decimals: pool.token.decimals,
|
|
354
|
-
borrowFactor: Web3Number2.fromWei(pool.borrow_factor.value, pool.borrow_factor.decimals),
|
|
355
|
-
collareralFactor,
|
|
356
|
-
displayDecimals: 2
|
|
357
|
-
};
|
|
358
|
-
this.tokens.push(token);
|
|
359
|
-
});
|
|
360
|
-
logger.info(`Initialised ${this.metadata.name} with ${this.tokens.length} tokens`);
|
|
361
|
-
this.initialised = true;
|
|
362
|
-
} catch (error) {
|
|
363
|
-
return Global.httpError(_ZkLend.POOLS_URL, error);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* @description Get the health factor of the user for given lending and debt tokens
|
|
368
|
-
* @param lending_tokens
|
|
369
|
-
* @param debt_tokens
|
|
370
|
-
* @param user
|
|
371
|
-
* @returns hf (e.g. returns 1.5 for 150% health factor)
|
|
372
|
-
*/
|
|
373
|
-
async get_health_factor_tokenwise(lending_tokens, debt_tokens, user) {
|
|
374
|
-
const positions = await this.getPositions(user);
|
|
375
|
-
logger.verbose(`${this.metadata.name}:: Positions: ${JSON.stringify(positions)}`);
|
|
376
|
-
let effectiveDebt = new Web3Number2(0, 6);
|
|
377
|
-
positions.filter((pos) => {
|
|
378
|
-
return debt_tokens.find((t) => t.symbol === pos.tokenSymbol);
|
|
379
|
-
}).forEach((pos) => {
|
|
380
|
-
const token = this.tokens.find((t) => t.symbol === pos.tokenSymbol);
|
|
381
|
-
if (!token) {
|
|
382
|
-
throw new FatalError(`Token ${pos.tokenName} not found in ${this.metadata.name}`);
|
|
383
|
-
}
|
|
384
|
-
effectiveDebt = effectiveDebt.plus(pos.debtUSD.dividedBy(token.borrowFactor.toFixed(6)).toString());
|
|
385
|
-
});
|
|
386
|
-
logger.verbose(`${this.metadata.name}:: Effective debt: ${effectiveDebt}`);
|
|
387
|
-
if (effectiveDebt.isZero()) {
|
|
388
|
-
return Infinity;
|
|
389
|
-
}
|
|
390
|
-
let effectiveCollateral = new Web3Number2(0, 6);
|
|
391
|
-
positions.filter((pos) => {
|
|
392
|
-
const exp1 = lending_tokens.find((t) => t.symbol === pos.tokenSymbol);
|
|
393
|
-
const exp2 = pos.marginType === "shared" /* SHARED */;
|
|
394
|
-
return exp1 && exp2;
|
|
395
|
-
}).forEach((pos) => {
|
|
396
|
-
const token = this.tokens.find((t) => t.symbol === pos.tokenSymbol);
|
|
397
|
-
if (!token) {
|
|
398
|
-
throw new FatalError(`Token ${pos.tokenName} not found in ${this.metadata.name}`);
|
|
399
|
-
}
|
|
400
|
-
logger.verbose(`${this.metadata.name}:: Token: ${pos.tokenName}, Collateral factor: ${token.collareralFactor.toFixed(6)}`);
|
|
401
|
-
effectiveCollateral = effectiveCollateral.plus(pos.supplyUSD.multipliedBy(token.collareralFactor.toFixed(6)).toString());
|
|
402
|
-
});
|
|
403
|
-
logger.verbose(`${this.metadata.name}:: Effective collateral: ${effectiveCollateral}`);
|
|
404
|
-
const healthFactor = effectiveCollateral.dividedBy(effectiveDebt.toFixed(6)).toNumber();
|
|
405
|
-
logger.verbose(`${this.metadata.name}:: Health factor: ${healthFactor}`);
|
|
406
|
-
return healthFactor;
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* @description Get the health factor of the user
|
|
410
|
-
* - Considers all tokens for collateral and debt
|
|
411
|
-
*/
|
|
412
|
-
async get_health_factor(user) {
|
|
413
|
-
return this.get_health_factor_tokenwise(this.tokens, this.tokens, user);
|
|
414
|
-
}
|
|
415
|
-
async getPositionsSummary(user) {
|
|
416
|
-
const pos = await this.getPositions(user);
|
|
417
|
-
const collateralUSD = pos.reduce((acc, p) => acc + p.supplyUSD.toNumber(), 0);
|
|
418
|
-
const debtUSD = pos.reduce((acc, p) => acc + p.debtUSD.toNumber(), 0);
|
|
419
|
-
return {
|
|
420
|
-
collateralUSD,
|
|
421
|
-
debtUSD
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* @description Get the token-wise collateral and debt positions of the user
|
|
426
|
-
* @param user Contract address of the user
|
|
427
|
-
* @returns Promise<ILendingPosition[]>
|
|
428
|
-
*/
|
|
429
|
-
async getPositions(user) {
|
|
430
|
-
const url = this.POSITION_URL.replace("{{USER_ADDR}}", user.address);
|
|
431
|
-
const result = await axios3.get(url);
|
|
432
|
-
const data = result.data;
|
|
433
|
-
const lendingPosition = [];
|
|
434
|
-
logger.verbose(`${this.metadata.name}:: Positions: ${JSON.stringify(data)}`);
|
|
435
|
-
for (let i = 0; i < data.pools.length; i++) {
|
|
436
|
-
const pool = data.pools[i];
|
|
437
|
-
const token = this.tokens.find((t) => {
|
|
438
|
-
return t.symbol === pool.token_symbol;
|
|
439
|
-
});
|
|
440
|
-
if (!token) {
|
|
441
|
-
throw new FatalError(`Token ${pool.token_symbol} not found in ${this.metadata.name}`);
|
|
442
88
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
debtUSD: debtAmount.multipliedBy(price.toFixed(6)),
|
|
452
|
-
supplyAmount,
|
|
453
|
-
supplyUSD: supplyAmount.multipliedBy(price.toFixed(6))
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
;
|
|
457
|
-
return lendingPosition;
|
|
458
|
-
}
|
|
459
|
-
};
|
|
460
|
-
_ZkLend.POOLS_URL = "https://app.zklend.com/api/pools";
|
|
461
|
-
var ZkLend = _ZkLend;
|
|
462
|
-
|
|
463
|
-
// src/modules/pricer-from-api.ts
|
|
464
|
-
import axios4 from "axios";
|
|
465
|
-
|
|
466
|
-
// src/modules/erc20.ts
|
|
467
|
-
import { Contract as Contract2 } from "starknet";
|
|
468
|
-
|
|
469
|
-
// src/modules/avnu.ts
|
|
470
|
-
import { uint256 } from "starknet";
|
|
471
|
-
import { fetchBuildExecuteTransaction, fetchQuotes } from "@avnu/avnu-sdk";
|
|
472
|
-
|
|
473
|
-
// src/interfaces/common.ts
|
|
474
|
-
import { RpcProvider as RpcProvider2 } from "starknet";
|
|
475
|
-
var RiskType = /* @__PURE__ */ ((RiskType2) => {
|
|
476
|
-
RiskType2["MARKET_RISK"] = "Market Risk";
|
|
477
|
-
RiskType2["IMPERMANENT_LOSS"] = "Impermanent Loss Risk";
|
|
478
|
-
RiskType2["LIQUIDATION_RISK"] = "Liquidation Risk";
|
|
479
|
-
RiskType2["LOW_LIQUIDITY_RISK"] = "Low Liquidity Risk";
|
|
480
|
-
RiskType2["SMART_CONTRACT_RISK"] = "Smart Contract Risk";
|
|
481
|
-
RiskType2["ORACLE_RISK"] = "Oracle Risk";
|
|
482
|
-
RiskType2["TECHNICAL_RISK"] = "Technical Risk";
|
|
483
|
-
RiskType2["COUNTERPARTY_RISK"] = "Counterparty Risk";
|
|
484
|
-
return RiskType2;
|
|
485
|
-
})(RiskType || {});
|
|
486
|
-
var getNoRiskTags = (risks) => {
|
|
487
|
-
const noRisks1 = risks.filter((risk) => risk.value === 0).map((risk) => risk.type);
|
|
488
|
-
const noRisks2 = Object.values(RiskType).filter(
|
|
489
|
-
(risk) => !risks.map((risk2) => risk2.type).includes(risk)
|
|
490
|
-
);
|
|
491
|
-
const mergedUnique = [.../* @__PURE__ */ new Set([...noRisks1, ...noRisks2])];
|
|
492
|
-
return mergedUnique.map((risk) => `No ${risk}`);
|
|
493
|
-
};
|
|
494
|
-
|
|
495
|
-
// src/strategies/autoCompounderStrk.ts
|
|
496
|
-
import { Contract as Contract3, uint256 as uint2562 } from "starknet";
|
|
497
|
-
|
|
498
|
-
// src/strategies/vesu-rebalance.tsx
|
|
499
|
-
import { CairoCustomEnum, Contract as Contract5, num as num3, uint256 as uint2563 } from "starknet";
|
|
500
|
-
|
|
501
|
-
// src/node/headless.browser.ts
|
|
502
|
-
import axios5 from "axios";
|
|
503
|
-
|
|
504
|
-
// src/modules/harvests.ts
|
|
505
|
-
import { Contract as Contract4, num as num2 } from "starknet";
|
|
506
|
-
|
|
507
|
-
// src/strategies/vesu-rebalance.tsx
|
|
508
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
509
|
-
var _description = "Automatically diversify {{TOKEN}} holdings into different Vesu pools while reducing risk and maximizing yield. Defi spring STRK Rewards are auto-compounded as well.";
|
|
510
|
-
var _protocol = {
|
|
511
|
-
name: "Vesu",
|
|
512
|
-
logo: "https://static-assets-8zct.onrender.com/integrations/vesu/logo.png"
|
|
513
|
-
};
|
|
514
|
-
var _riskFactor = [
|
|
515
|
-
{ type: "Smart Contract Risk" /* SMART_CONTRACT_RISK */, value: 0.5, weight: 25 },
|
|
516
|
-
{ type: "Counterparty Risk" /* COUNTERPARTY_RISK */, value: 1, weight: 50 },
|
|
517
|
-
{ type: "Oracle Risk" /* ORACLE_RISK */, value: 0.5, weight: 25 }
|
|
518
|
-
];
|
|
519
|
-
var AUDIT_URL = "https://assets.strkfarm.com/strkfarm/audit_report_vesu_and_ekubo_strats.pdf";
|
|
520
|
-
var faqs = [
|
|
521
|
-
{
|
|
522
|
-
question: "What is the Vesu Rebalancing Strategy?",
|
|
523
|
-
answer: "The Vesu Rebalancing Strategy is an automated investment strategy that diversifies your holdings across multiple Vesu pools. It optimizes yield by rebalancing assets based on pool performance while adhering to risk constraints."
|
|
524
|
-
},
|
|
525
|
-
{
|
|
526
|
-
question: "Will I earn Vesu points?",
|
|
527
|
-
answer: "Yes, of course! You will earn Vesu points for your deposits."
|
|
528
|
-
},
|
|
529
|
-
{
|
|
530
|
-
question: "How does the strategy optimize yield?",
|
|
531
|
-
answer: "The strategy calculates the weighted average APY across all pools and reallocates assets to maximize returns. It prioritizes high-performing pools while ensuring compliance with maximum weight constraints."
|
|
532
|
-
},
|
|
533
|
-
{
|
|
534
|
-
question: "What are the risks associated with this strategy?",
|
|
535
|
-
answer: "The strategy involves usual DeFi risks such as smart contract vulnerabilities, counterparty risks, and oracle inaccuracies. However, we try our best to reduce these risks through audits and careful pool selection."
|
|
536
|
-
},
|
|
537
|
-
{
|
|
538
|
-
question: "How are fees calculated and deducted?",
|
|
539
|
-
answer: "Fees are calculated based on the performance of the strategy and deducted proportionally from the total assets. We charge a 10% performance fee and is already accounted in the APY shown."
|
|
540
|
-
},
|
|
541
|
-
{
|
|
542
|
-
question: "What happens if a pool exceeds its maximum weight?",
|
|
543
|
-
answer: "If a pool exceeds its maximum weight, the strategy rebalances by withdrawing excess funds and reallocating them to other pools with available capacity."
|
|
544
|
-
},
|
|
545
|
-
{
|
|
546
|
-
question: "Can I withdraw my assets at any time?",
|
|
547
|
-
answer: "Yes, you can withdraw your assets at any time. In rare circumstances, if debt utilisation is high for certain pools on Vesu, it may not be possible to withdraw until markets restore balance."
|
|
548
|
-
},
|
|
549
|
-
{
|
|
550
|
-
question: "What happens to my Defi Spring STRK rewards?",
|
|
551
|
-
answer: "STRK rewards are automatically harvested and reinvested into the strategy every week to maximize compounding returns."
|
|
552
|
-
},
|
|
553
|
-
{
|
|
554
|
-
question: "Is the strategy audited?",
|
|
555
|
-
answer: /* @__PURE__ */ jsxs("div", { children: [
|
|
556
|
-
"Yes, the strategy has been audited. You can review the audit report in our docs ",
|
|
557
|
-
/* @__PURE__ */ jsx("a", { href: "https://docs.strkfarm.com/p/strategies/vesu-fusion-rebalancing-vaults#technical-details", style: { textDecoration: "underline", marginLeft: "5px" }, children: "Here" }),
|
|
558
|
-
"."
|
|
559
|
-
] })
|
|
560
|
-
}
|
|
561
|
-
];
|
|
562
|
-
var VesuRebalanceStrategies = [
|
|
563
|
-
{
|
|
564
|
-
name: "Vesu Fusion STRK",
|
|
565
|
-
description: _description.replace("{{TOKEN}}", "STRK"),
|
|
566
|
-
address: ContractAddr.from(
|
|
567
|
-
"0x7fb5bcb8525954a60fde4e8fb8220477696ce7117ef264775a1770e23571929"
|
|
568
|
-
),
|
|
569
|
-
type: "ERC4626",
|
|
570
|
-
depositTokens: [
|
|
571
|
-
Global.getDefaultTokens().find((t) => t.symbol === "STRK")
|
|
572
|
-
],
|
|
573
|
-
protocols: [_protocol],
|
|
574
|
-
auditUrl: AUDIT_URL,
|
|
575
|
-
maxTVL: Web3Number.fromWei("0", 18),
|
|
576
|
-
risk: {
|
|
577
|
-
riskFactor: _riskFactor,
|
|
578
|
-
netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
579
|
-
notARisks: getNoRiskTags(_riskFactor)
|
|
580
|
-
},
|
|
581
|
-
additionalInfo: {
|
|
582
|
-
feeBps: 1e3
|
|
583
|
-
},
|
|
584
|
-
faqs
|
|
585
|
-
},
|
|
586
|
-
{
|
|
587
|
-
name: "Vesu Fusion ETH",
|
|
588
|
-
description: _description.replace("{{TOKEN}}", "ETH"),
|
|
589
|
-
address: ContractAddr.from(
|
|
590
|
-
"0x5eaf5ee75231cecf79921ff8ded4b5ffe96be718bcb3daf206690ad1a9ad0ca"
|
|
591
|
-
),
|
|
592
|
-
type: "ERC4626",
|
|
593
|
-
auditUrl: AUDIT_URL,
|
|
594
|
-
depositTokens: [
|
|
595
|
-
Global.getDefaultTokens().find((t) => t.symbol === "ETH")
|
|
596
|
-
],
|
|
597
|
-
protocols: [_protocol],
|
|
598
|
-
maxTVL: Web3Number.fromWei("0", 18),
|
|
599
|
-
risk: {
|
|
600
|
-
riskFactor: _riskFactor,
|
|
601
|
-
netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
602
|
-
notARisks: getNoRiskTags(_riskFactor)
|
|
603
|
-
},
|
|
604
|
-
additionalInfo: {
|
|
605
|
-
feeBps: 1e3
|
|
606
|
-
},
|
|
607
|
-
faqs
|
|
608
|
-
},
|
|
609
|
-
{
|
|
610
|
-
name: "Vesu Fusion USDC",
|
|
611
|
-
description: _description.replace("{{TOKEN}}", "USDC"),
|
|
612
|
-
address: ContractAddr.from(
|
|
613
|
-
"0xa858c97e9454f407d1bd7c57472fc8d8d8449a777c822b41d18e387816f29c"
|
|
614
|
-
),
|
|
615
|
-
type: "ERC4626",
|
|
616
|
-
auditUrl: AUDIT_URL,
|
|
617
|
-
depositTokens: [
|
|
618
|
-
Global.getDefaultTokens().find((t) => t.symbol === "USDC")
|
|
619
|
-
],
|
|
620
|
-
protocols: [_protocol],
|
|
621
|
-
maxTVL: Web3Number.fromWei("0", 6),
|
|
622
|
-
risk: {
|
|
623
|
-
riskFactor: _riskFactor,
|
|
624
|
-
netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
625
|
-
notARisks: getNoRiskTags(_riskFactor)
|
|
626
|
-
},
|
|
627
|
-
additionalInfo: {
|
|
628
|
-
feeBps: 1e3
|
|
629
|
-
},
|
|
630
|
-
faqs
|
|
631
|
-
},
|
|
632
|
-
{
|
|
633
|
-
name: "Vesu Fusion USDT",
|
|
634
|
-
description: _description.replace("{{TOKEN}}", "USDT"),
|
|
635
|
-
address: ContractAddr.from(
|
|
636
|
-
"0x115e94e722cfc4c77a2f15c4aefb0928c1c0029e5a57570df24c650cb7cec2c"
|
|
637
|
-
),
|
|
638
|
-
type: "ERC4626",
|
|
639
|
-
depositTokens: [
|
|
640
|
-
Global.getDefaultTokens().find((t) => t.symbol === "USDT")
|
|
641
|
-
],
|
|
642
|
-
auditUrl: AUDIT_URL,
|
|
643
|
-
protocols: [_protocol],
|
|
644
|
-
maxTVL: Web3Number.fromWei("0", 6),
|
|
645
|
-
risk: {
|
|
646
|
-
riskFactor: _riskFactor,
|
|
647
|
-
netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
648
|
-
notARisks: getNoRiskTags(_riskFactor)
|
|
649
|
-
},
|
|
650
|
-
additionalInfo: {
|
|
651
|
-
feeBps: 1e3
|
|
652
|
-
},
|
|
653
|
-
faqs
|
|
654
|
-
// }, {
|
|
655
|
-
// name: 'Vesu Fusion WBTC',
|
|
656
|
-
// description: _description.replace('{{TOKEN}}', 'WBTC'),
|
|
657
|
-
// address: ContractAddr.from('0x778007f8136a5b827325d21613803e796bda4d676fbe1e34aeab0b2a2ec027f'),
|
|
658
|
-
// type: 'ERC4626',
|
|
659
|
-
// depositTokens: [Global.getDefaultTokens().find(t => t.symbol === 'WBTC')!],
|
|
660
|
-
// auditUrl: AUDIT_URL,
|
|
661
|
-
// protocols: [_protocol],
|
|
662
|
-
// maxTVL: Web3Number.fromWei('0', 8),
|
|
663
|
-
// risk: {
|
|
664
|
-
// riskFactor: _riskFactor,
|
|
665
|
-
// netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
666
|
-
// },
|
|
667
|
-
// additionalInfo: {
|
|
668
|
-
// feeBps: 1000,
|
|
669
|
-
// },
|
|
670
|
-
}
|
|
671
|
-
];
|
|
672
|
-
|
|
673
|
-
// src/strategies/ekubo-cl-vault.tsx
|
|
674
|
-
import {
|
|
675
|
-
Contract as Contract6,
|
|
676
|
-
num as num4,
|
|
677
|
-
uint256 as uint2564
|
|
678
|
-
} from "starknet";
|
|
679
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
680
|
-
var _description2 = "Deploys your {{POOL_NAME}} into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce the need for manual adjustments. Trading fees and DeFi Spring rewards are automatically compounded back into the strategy. In return, you receive an ERC-20 token representing your share of the strategy. The APY is calculated based on 7-day historical performance.";
|
|
681
|
-
var _protocol2 = {
|
|
682
|
-
name: "Ekubo",
|
|
683
|
-
logo: "https://app.ekubo.org/favicon.ico"
|
|
684
|
-
};
|
|
685
|
-
var _riskFactor2 = [
|
|
686
|
-
{ type: "Smart Contract Risk" /* SMART_CONTRACT_RISK */, value: 0.5, weight: 25 },
|
|
687
|
-
{ type: "Impermanent Loss Risk" /* IMPERMANENT_LOSS */, value: 1, weight: 75 }
|
|
688
|
-
];
|
|
689
|
-
var AUDIT_URL2 = "https://assets.strkfarm.com/strkfarm/audit_report_vesu_and_ekubo_strats.pdf";
|
|
690
|
-
var faqs2 = [
|
|
691
|
-
{
|
|
692
|
-
question: "What is the Ekubo CL Vault strategy?",
|
|
693
|
-
answer: "The Ekubo CL Vault strategy deploys your assets into an Ekubo liquidity pool, automatically rebalancing positions around the current price to optimize yield and reduce manual adjustments."
|
|
694
|
-
},
|
|
695
|
-
{
|
|
696
|
-
question: "How are trading fees and rewards handled?",
|
|
697
|
-
answer: "Trading fees and DeFi Spring rewards are automatically compounded back into the strategy, increasing your overall returns."
|
|
698
|
-
},
|
|
699
|
-
{
|
|
700
|
-
question: "What happens during withdrawal?",
|
|
701
|
-
answer: "During withdrawal, you may receive either or both tokens depending on market conditions and prevailing prices."
|
|
702
|
-
},
|
|
703
|
-
{
|
|
704
|
-
question: "Is the strategy audited?",
|
|
705
|
-
answer: /* @__PURE__ */ jsxs2("div", { children: [
|
|
706
|
-
"Yes, the strategy has been audited. You can review the audit report in our docs ",
|
|
707
|
-
/* @__PURE__ */ jsx2("a", { href: "https://docs.strkfarm.com/p/ekubo-cl-vaults#technical-details", style: { textDecoration: "underline", marginLeft: "5px" }, children: "Here" }),
|
|
708
|
-
"."
|
|
709
|
-
] })
|
|
710
|
-
}
|
|
711
|
-
];
|
|
712
|
-
var EkuboCLVaultStrategies = [
|
|
713
|
-
{
|
|
714
|
-
name: "Ekubo xSTRK/STRK",
|
|
715
|
-
description: /* @__PURE__ */ jsxs2("div", { children: [
|
|
716
|
-
/* @__PURE__ */ jsx2("p", { children: _description2.replace("{{POOL_NAME}}", "xSTRK/STRK") }),
|
|
717
|
-
/* @__PURE__ */ jsxs2(
|
|
718
|
-
"ul",
|
|
719
|
-
{
|
|
720
|
-
style: {
|
|
721
|
-
marginLeft: "20px",
|
|
722
|
-
listStyle: "circle",
|
|
723
|
-
fontSize: "12px"
|
|
724
|
-
},
|
|
725
|
-
children: [
|
|
726
|
-
/* @__PURE__ */ jsx2("li", { style: { marginTop: "10px" }, children: "During withdrawal, you may receive either or both tokens depending on market conditions and prevailing prices." }),
|
|
727
|
-
/* @__PURE__ */ jsx2("li", { style: { marginTop: "10px" }, children: "Sometimes you might see a negative APY \u2014 this is usually not a big deal. It happens when xSTRK's price drops on DEXes, but things typically bounce back within a few days or a week." })
|
|
728
|
-
]
|
|
729
|
-
}
|
|
730
|
-
)
|
|
731
|
-
] }),
|
|
732
|
-
address: ContractAddr.from(
|
|
733
|
-
"0x01f083b98674bc21effee29ef443a00c7b9a500fd92cf30341a3da12c73f2324"
|
|
734
|
-
),
|
|
735
|
-
type: "Other",
|
|
736
|
-
// must be same order as poolKey token0 and token1
|
|
737
|
-
depositTokens: [
|
|
738
|
-
Global.getDefaultTokens().find((t) => t.symbol === "xSTRK"),
|
|
739
|
-
Global.getDefaultTokens().find((t) => t.symbol === "STRK")
|
|
740
|
-
],
|
|
741
|
-
protocols: [_protocol2],
|
|
742
|
-
auditUrl: AUDIT_URL2,
|
|
743
|
-
maxTVL: Web3Number.fromWei("0", 18),
|
|
744
|
-
risk: {
|
|
745
|
-
riskFactor: _riskFactor2,
|
|
746
|
-
netRisk: _riskFactor2.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor2.reduce((acc, curr) => acc + curr.weight, 0),
|
|
747
|
-
notARisks: getNoRiskTags(_riskFactor2)
|
|
748
|
-
},
|
|
749
|
-
apyMethodology: "APY based on 7-day historical performance, including fees and rewards.",
|
|
750
|
-
additionalInfo: {
|
|
751
|
-
newBounds: {
|
|
752
|
-
lower: -1,
|
|
753
|
-
upper: 1
|
|
754
|
-
},
|
|
755
|
-
lstContract: ContractAddr.from(
|
|
756
|
-
"0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a"
|
|
757
|
-
),
|
|
758
|
-
feeBps: 1e3
|
|
759
|
-
},
|
|
760
|
-
faqs: [
|
|
761
|
-
...faqs2,
|
|
762
|
-
{
|
|
763
|
-
question: "Why might I see a negative APY?",
|
|
764
|
-
answer: "A negative APY can occur when xSTRK's price drops on DEXes. This is usually temporary and tends to recover within a few days or a week."
|
|
765
|
-
}
|
|
766
|
-
]
|
|
767
|
-
}
|
|
768
|
-
];
|
|
769
|
-
|
|
770
|
-
// src/notifs/telegram.ts
|
|
771
|
-
import TelegramBot from "node-telegram-bot-api";
|
|
772
|
-
|
|
773
|
-
// src/node/pricer-redis.ts
|
|
774
|
-
import { createClient } from "redis";
|
|
89
|
+
return msg;
|
|
90
|
+
})
|
|
91
|
+
),
|
|
92
|
+
transports: [
|
|
93
|
+
new winston.transports.Console()
|
|
94
|
+
// Output logs to the console
|
|
95
|
+
]
|
|
96
|
+
});
|
|
775
97
|
|
|
776
98
|
// src/utils/store.ts
|
|
777
99
|
function getDefaultStoreConfig(network) {
|
|
@@ -815,7 +137,7 @@ var Store = class _Store {
|
|
|
815
137
|
}
|
|
816
138
|
logger.verbose(`Account loaded: ${accountKey} from network: ${this.config.network}`);
|
|
817
139
|
logger.verbose(`Address: ${data.address}`);
|
|
818
|
-
const acc = new
|
|
140
|
+
const acc = new Account(this.config.provider, data.address, data.pk, void 0, txVersion);
|
|
819
141
|
return acc;
|
|
820
142
|
}
|
|
821
143
|
addAccount(accountKey, address, pk) {
|
|
@@ -879,11 +201,11 @@ var Store = class _Store {
|
|
|
879
201
|
|
|
880
202
|
// src/cli.ts
|
|
881
203
|
import chalk from "chalk";
|
|
882
|
-
import { RpcProvider
|
|
204
|
+
import { RpcProvider } from "starknet";
|
|
883
205
|
var program = new Command();
|
|
884
206
|
var getConfig = (network) => {
|
|
885
207
|
return {
|
|
886
|
-
provider: new
|
|
208
|
+
provider: new RpcProvider({
|
|
887
209
|
nodeUrl: "https://starknet-mainnet.public.blastapi.io"
|
|
888
210
|
}),
|
|
889
211
|
network,
|