@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/dist/index.js
CHANGED
|
@@ -9,11 +9,11 @@ var __export = (target, all) => {
|
|
|
9
9
|
for (var name in all)
|
|
10
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
11
|
};
|
|
12
|
-
var __copyProps = (to,
|
|
13
|
-
if (
|
|
14
|
-
for (let key of __getOwnPropNames(
|
|
12
|
+
var __copyProps = (to, from2, except, desc) => {
|
|
13
|
+
if (from2 && typeof from2 === "object" || typeof from2 === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from2))
|
|
15
15
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () =>
|
|
16
|
+
__defProp(to, key, { get: () => from2[key], enumerable: !(desc = __getOwnPropDesc(from2, key)) || desc.enumerable });
|
|
17
17
|
}
|
|
18
18
|
return to;
|
|
19
19
|
};
|
|
@@ -46,8 +46,8 @@ __export(index_exports, {
|
|
|
46
46
|
ERC20: () => ERC20,
|
|
47
47
|
EkuboCLVault: () => EkuboCLVault,
|
|
48
48
|
EkuboCLVaultStrategies: () => EkuboCLVaultStrategies,
|
|
49
|
-
EkuboPricer: () => EkuboPricer,
|
|
50
49
|
EkuboQuoter: () => EkuboQuoter,
|
|
50
|
+
FactoryStrategyType: () => FactoryStrategyType,
|
|
51
51
|
FatalError: () => FatalError,
|
|
52
52
|
FlowChartColors: () => FlowChartColors,
|
|
53
53
|
Global: () => Global,
|
|
@@ -57,6 +57,7 @@ __export(index_exports, {
|
|
|
57
57
|
InstantWithdrawalVault: () => InstantWithdrawalVault,
|
|
58
58
|
LSTAPRService: () => LSTAPRService,
|
|
59
59
|
MarginType: () => MarginType,
|
|
60
|
+
MyNumber: () => MyNumber,
|
|
60
61
|
Network: () => Network,
|
|
61
62
|
PRICE_ROUTER: () => PRICE_ROUTER,
|
|
62
63
|
PasswordJsonCryptoUtil: () => PasswordJsonCryptoUtil,
|
|
@@ -75,7 +76,7 @@ __export(index_exports, {
|
|
|
75
76
|
SourceCodeType: () => SourceCodeType,
|
|
76
77
|
StandardMerkleTree: () => StandardMerkleTree,
|
|
77
78
|
Store: () => Store,
|
|
78
|
-
|
|
79
|
+
StrategyLiveStatus: () => StrategyLiveStatus,
|
|
79
80
|
StrategyTag: () => StrategyTag,
|
|
80
81
|
StrategyType: () => StrategyType,
|
|
81
82
|
TelegramGroupNotif: () => TelegramGroupNotif,
|
|
@@ -87,6 +88,7 @@ __export(index_exports, {
|
|
|
87
88
|
UniversalStrategy: () => UniversalStrategy,
|
|
88
89
|
VESU_SINGLETON: () => VESU_SINGLETON,
|
|
89
90
|
VESU_V2_MODIFY_POSITION_SANITIZER: () => VESU_V2_MODIFY_POSITION_SANITIZER,
|
|
91
|
+
VaultType: () => VaultType,
|
|
90
92
|
VesuAdapter: () => VesuAdapter,
|
|
91
93
|
VesuAmountDenomination: () => VesuAmountDenomination,
|
|
92
94
|
VesuAmountType: () => VesuAmountType,
|
|
@@ -97,23 +99,34 @@ __export(index_exports, {
|
|
|
97
99
|
ZkLend: () => ZkLend,
|
|
98
100
|
assert: () => assert,
|
|
99
101
|
buildStrategyRegistry: () => buildStrategyRegistry,
|
|
102
|
+
createEkuboCLStrategy: () => createEkuboCLStrategy,
|
|
103
|
+
createHyperLSTStrategy: () => createHyperLSTStrategy,
|
|
104
|
+
createSenseiStrategy: () => createSenseiStrategy,
|
|
105
|
+
createStrategy: () => createStrategy,
|
|
106
|
+
createUniversalStrategy: () => createUniversalStrategy2,
|
|
107
|
+
createVesuRebalanceStrategy: () => createVesuRebalanceStrategy2,
|
|
108
|
+
detectCapabilities: () => detectCapabilities,
|
|
100
109
|
extensionMap: () => extensionMap,
|
|
101
110
|
getAPIUsingHeadlessBrowser: () => getAPIUsingHeadlessBrowser,
|
|
102
111
|
getAllStrategyMetadata: () => getAllStrategyMetadata,
|
|
112
|
+
getAllStrategyTags: () => getAllStrategyTags,
|
|
103
113
|
getContractDetails: () => getContractDetails,
|
|
104
114
|
getDefaultStoreConfig: () => getDefaultStoreConfig,
|
|
105
115
|
getFilterMetadata: () => getFilterMetadata,
|
|
106
|
-
getFilteredStrategies: () => getFilteredStrategies,
|
|
107
116
|
getLiveStrategies: () => getLiveStrategies,
|
|
108
117
|
getMainnetConfig: () => getMainnetConfig,
|
|
109
118
|
getNoRiskTags: () => getNoRiskTags,
|
|
110
119
|
getRiskColor: () => getRiskColor,
|
|
111
120
|
getRiskExplaination: () => getRiskExplaination,
|
|
112
121
|
getStrategiesByType: () => getStrategiesByType,
|
|
122
|
+
getStrategyTagDesciption: () => getStrategyTagDesciption,
|
|
123
|
+
getStrategyTypeFromMetadata: () => getStrategyTypeFromMetadata,
|
|
113
124
|
getTrovesEndpoint: () => getTrovesEndpoint,
|
|
114
125
|
getVesuSingletonAddress: () => getVesuSingletonAddress,
|
|
115
126
|
highlightTextWithLinks: () => highlightTextWithLinks,
|
|
127
|
+
isDualTokenStrategy: () => isDualTokenStrategy,
|
|
116
128
|
logger: () => logger,
|
|
129
|
+
toAmountsInfo: () => toAmountsInfo,
|
|
117
130
|
toBigInt: () => toBigInt
|
|
118
131
|
});
|
|
119
132
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -216,7 +229,7 @@ var Web3Number = class _Web3Number2 extends _Web3Number {
|
|
|
216
229
|
[import_util.default.inspect.custom](depth, opts) {
|
|
217
230
|
return this.toString();
|
|
218
231
|
}
|
|
219
|
-
[Symbol.for("nodejs.util.inspect.custom")](depth, inspectOptions, inspect) {
|
|
232
|
+
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")](depth, inspectOptions, inspect) {
|
|
220
233
|
return this.toString();
|
|
221
234
|
}
|
|
222
235
|
inspect(depth, opts) {
|
|
@@ -258,6 +271,126 @@ var ContractAddr = class _ContractAddr {
|
|
|
258
271
|
}
|
|
259
272
|
};
|
|
260
273
|
|
|
274
|
+
// src/dataTypes/mynumber.ts
|
|
275
|
+
var import_bignumber3 = __toESM(require("bignumber.js"));
|
|
276
|
+
var import_ethers = require("ethers");
|
|
277
|
+
var customInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
278
|
+
import_bignumber3.default.config({
|
|
279
|
+
DECIMAL_PLACES: 18
|
|
280
|
+
});
|
|
281
|
+
var MyNumber = class _MyNumber {
|
|
282
|
+
constructor(bigNumber, decimals) {
|
|
283
|
+
this.bigNumber = new import_bignumber3.default(bigNumber);
|
|
284
|
+
this.decimals = decimals;
|
|
285
|
+
}
|
|
286
|
+
static fromEther(num12, decimals) {
|
|
287
|
+
try {
|
|
288
|
+
return new _MyNumber(
|
|
289
|
+
Number(
|
|
290
|
+
import_ethers.ethers.parseUnits(Number(num12).toFixed(10), decimals)
|
|
291
|
+
).toFixed(6),
|
|
292
|
+
decimals
|
|
293
|
+
);
|
|
294
|
+
} catch (e) {
|
|
295
|
+
console.error("fromEther", e, num12, decimals);
|
|
296
|
+
throw e;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
static fromZero() {
|
|
300
|
+
return new _MyNumber("0", 0);
|
|
301
|
+
}
|
|
302
|
+
toString() {
|
|
303
|
+
return this.bigNumber.toFixed();
|
|
304
|
+
}
|
|
305
|
+
toEtherStr() {
|
|
306
|
+
return import_ethers.ethers.formatUnits(this.bigNumber.toFixed(), this.decimals);
|
|
307
|
+
}
|
|
308
|
+
toFixedStr(decimals) {
|
|
309
|
+
return Number(this.toEtherStr()).toFixed(decimals);
|
|
310
|
+
}
|
|
311
|
+
toEtherToFixedDecimals(decimals) {
|
|
312
|
+
if (this.bigNumber.isNaN()) {
|
|
313
|
+
return "NaN";
|
|
314
|
+
}
|
|
315
|
+
return (Math.floor(parseFloat(this.toEtherStr()) * 10 ** decimals) / 10 ** decimals).toFixed(decimals);
|
|
316
|
+
}
|
|
317
|
+
isZero() {
|
|
318
|
+
return this.bigNumber.eq("0");
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
*
|
|
322
|
+
* @param amountEther in token terms without decimal e.g. 1 for 1 STRK
|
|
323
|
+
* @param command BigNumber compare funds. e.g. gte, gt, lt
|
|
324
|
+
* @returns
|
|
325
|
+
* @dev Add more commands as needed
|
|
326
|
+
*/
|
|
327
|
+
compare(amountEther, command) {
|
|
328
|
+
const fullNum = new import_bignumber3.default(
|
|
329
|
+
import_ethers.ethers.parseUnits(amountEther, this.decimals).toString()
|
|
330
|
+
);
|
|
331
|
+
return this.bigNumber[command](fullNum);
|
|
332
|
+
}
|
|
333
|
+
operate(command, value) {
|
|
334
|
+
const bn = new import_bignumber3.default(Number(value).toFixed(6));
|
|
335
|
+
return new _MyNumber(
|
|
336
|
+
this.bigNumber[command](bn).toFixed(0),
|
|
337
|
+
this.decimals
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
subtract(value) {
|
|
341
|
+
const bn = this.bigNumber.minus(value.bigNumber);
|
|
342
|
+
return new _MyNumber(bn.toString(), this.decimals);
|
|
343
|
+
}
|
|
344
|
+
static min(a, b) {
|
|
345
|
+
if (a.decimals !== b.decimals) {
|
|
346
|
+
const diff = Math.abs(a.decimals - b.decimals);
|
|
347
|
+
if (a.decimals > b.decimals) {
|
|
348
|
+
b = new _MyNumber(
|
|
349
|
+
b.bigNumber.times(10 ** diff).toString(),
|
|
350
|
+
a.decimals
|
|
351
|
+
);
|
|
352
|
+
} else {
|
|
353
|
+
a = new _MyNumber(
|
|
354
|
+
a.bigNumber.times(10 ** diff).toString(),
|
|
355
|
+
b.decimals
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const bn = import_bignumber3.default.min(a.bigNumber, b.bigNumber);
|
|
360
|
+
return new _MyNumber(
|
|
361
|
+
bn.toString(),
|
|
362
|
+
a.decimals > b.decimals ? a.decimals : b.decimals
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
static max(a, b) {
|
|
366
|
+
if (a.decimals !== b.decimals) {
|
|
367
|
+
const diff = Math.abs(a.decimals - b.decimals);
|
|
368
|
+
if (a.decimals > b.decimals) {
|
|
369
|
+
b = new _MyNumber(
|
|
370
|
+
b.bigNumber.times(10 ** diff).toString(),
|
|
371
|
+
a.decimals
|
|
372
|
+
);
|
|
373
|
+
} else {
|
|
374
|
+
a = new _MyNumber(
|
|
375
|
+
a.bigNumber.times(10 ** diff).toString(),
|
|
376
|
+
b.decimals
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
const bn = import_bignumber3.default.max(a.bigNumber, b.bigNumber);
|
|
381
|
+
return new _MyNumber(
|
|
382
|
+
bn.toString(),
|
|
383
|
+
a.decimals > b.decimals ? a.decimals : b.decimals
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
[customInspectSymbol](depth, inspectOptions, inspect) {
|
|
387
|
+
return JSON.stringify({
|
|
388
|
+
raw: this.toString(),
|
|
389
|
+
decimals: this.decimals
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
261
394
|
// src/utils/logger.node.ts
|
|
262
395
|
var import_winston = __toESM(require("winston"));
|
|
263
396
|
var colors = {
|
|
@@ -268,9 +401,10 @@ var colors = {
|
|
|
268
401
|
debug: "white"
|
|
269
402
|
};
|
|
270
403
|
import_winston.default.addColors(colors);
|
|
404
|
+
var logLevel = (process.env.LOG_LEVEL || process.env.SDK_LOG_LEVEL || "debug").toLowerCase();
|
|
271
405
|
var logger = import_winston.default.createLogger({
|
|
272
|
-
level:
|
|
273
|
-
// Set the minimum logging level
|
|
406
|
+
level: logLevel,
|
|
407
|
+
// Set the minimum logging level from environment variable
|
|
274
408
|
format: import_winston.format.combine(
|
|
275
409
|
import_winston.format.colorize({ all: true }),
|
|
276
410
|
// Apply custom colors
|
|
@@ -278,11 +412,14 @@ var logger = import_winston.default.createLogger({
|
|
|
278
412
|
// Add timestamp to log messages
|
|
279
413
|
import_winston.format.printf(({ timestamp, level, message, ...meta }) => {
|
|
280
414
|
let msg = `${timestamp} ${level}: ${message}`;
|
|
281
|
-
if (meta && meta[Symbol.for("splat")]) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
415
|
+
if (meta && meta[/* @__PURE__ */ Symbol.for("splat")]) {
|
|
416
|
+
const splat = meta[/* @__PURE__ */ Symbol.for("splat")];
|
|
417
|
+
if (Array.isArray(splat)) {
|
|
418
|
+
for (const arg of splat) {
|
|
419
|
+
if (arg instanceof Error) {
|
|
420
|
+
msg += `
|
|
285
421
|
${arg.stack}`;
|
|
422
|
+
}
|
|
286
423
|
}
|
|
287
424
|
}
|
|
288
425
|
}
|
|
@@ -332,11 +469,20 @@ var defaultTokens = [{
|
|
|
332
469
|
coingeckId: void 0,
|
|
333
470
|
priceCheckAmount: 0.1,
|
|
334
471
|
displayDecimals: 6
|
|
472
|
+
}, {
|
|
473
|
+
name: "USDC.e",
|
|
474
|
+
symbol: "USDC.e",
|
|
475
|
+
logo: "https://assets.troves.fi/integrations/tokens/usdc.svg",
|
|
476
|
+
address: ContractAddr.from("0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"),
|
|
477
|
+
decimals: 6,
|
|
478
|
+
coingeckId: void 0,
|
|
479
|
+
displayDecimals: 2,
|
|
480
|
+
priceCheckAmount: 1e3
|
|
335
481
|
}, {
|
|
336
482
|
name: "USDC",
|
|
337
483
|
symbol: "USDC",
|
|
338
484
|
logo: "https://assets.troves.fi/integrations/tokens/usdc.svg",
|
|
339
|
-
address: ContractAddr.from("
|
|
485
|
+
address: ContractAddr.from("0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb"),
|
|
340
486
|
decimals: 6,
|
|
341
487
|
coingeckId: void 0,
|
|
342
488
|
displayDecimals: 2,
|
|
@@ -400,6 +546,7 @@ var defaultTokens = [{
|
|
|
400
546
|
decimals: 8,
|
|
401
547
|
coingeckId: void 0,
|
|
402
548
|
displayDecimals: 6,
|
|
549
|
+
priceProxySymbol: "WBTC",
|
|
403
550
|
priceCheckAmount: 1e-3
|
|
404
551
|
// 112000 * 0.0001 = $110.2
|
|
405
552
|
}, {
|
|
@@ -422,8 +569,9 @@ var defaultTokens = [{
|
|
|
422
569
|
decimals: 18,
|
|
423
570
|
coingeckId: void 0,
|
|
424
571
|
displayDecimals: 6,
|
|
425
|
-
priceCheckAmount: 1e-3
|
|
572
|
+
priceCheckAmount: 1e-3,
|
|
426
573
|
// 112000 * 0.0001 = $110.2
|
|
574
|
+
priceProxySymbol: "WBTC"
|
|
427
575
|
}, {
|
|
428
576
|
name: "xLBTC",
|
|
429
577
|
symbol: "xLBTC",
|
|
@@ -507,6 +655,18 @@ var _Global = class _Global {
|
|
|
507
655
|
}
|
|
508
656
|
return token;
|
|
509
657
|
}
|
|
658
|
+
static async getTokenInfoFromName(tokenName) {
|
|
659
|
+
if (tokens.length == defaultTokens.length) {
|
|
660
|
+
await _Global.getTokens();
|
|
661
|
+
}
|
|
662
|
+
const token = tokens.find(
|
|
663
|
+
(token2) => token2.name.toLowerCase() === tokenName.toLowerCase()
|
|
664
|
+
);
|
|
665
|
+
if (!token) {
|
|
666
|
+
throw new FatalError(`Token not found: ${tokenName}`);
|
|
667
|
+
}
|
|
668
|
+
return token;
|
|
669
|
+
}
|
|
510
670
|
static setGlobalCache(key, data, ttl = 6e4) {
|
|
511
671
|
_Global.cache[key] = {
|
|
512
672
|
value: data,
|
|
@@ -538,6 +698,178 @@ var PricerBase = class {
|
|
|
538
698
|
}
|
|
539
699
|
};
|
|
540
700
|
|
|
701
|
+
// src/modules/avnu.ts
|
|
702
|
+
var import_starknet4 = require("starknet");
|
|
703
|
+
var import_avnu_sdk = require("@avnu/avnu-sdk");
|
|
704
|
+
|
|
705
|
+
// src/utils/oz-merkle.ts
|
|
706
|
+
var import_bytes = require("@ericnordelo/strk-merkle-tree/dist/bytes");
|
|
707
|
+
var import_core = require("@ericnordelo/strk-merkle-tree/dist/core");
|
|
708
|
+
var import_hashes = require("@ericnordelo/strk-merkle-tree/dist/hashes");
|
|
709
|
+
var import_merkletree = require("@ericnordelo/strk-merkle-tree/dist/merkletree");
|
|
710
|
+
var import_starknet2 = require("starknet");
|
|
711
|
+
var import_starknet3 = require("@scure/starknet");
|
|
712
|
+
function hash_leaf(leaf) {
|
|
713
|
+
if (leaf.data.length < 1) {
|
|
714
|
+
throw new Error("Invalid leaf data");
|
|
715
|
+
}
|
|
716
|
+
let firstElement = leaf.data[0];
|
|
717
|
+
let value = firstElement;
|
|
718
|
+
for (let i = 1; i < leaf.data.length; i++) {
|
|
719
|
+
value = pedersen_hash(value, leaf.data[i]);
|
|
720
|
+
}
|
|
721
|
+
return `0x${import_starknet2.num.toHexString(value).replace(/^0x/, "").padStart(64, "0")}`;
|
|
722
|
+
}
|
|
723
|
+
function pedersen_hash(a, b) {
|
|
724
|
+
return BigInt((0, import_starknet3.pedersen)(a, b).toString());
|
|
725
|
+
}
|
|
726
|
+
var StandardMerkleTree = class _StandardMerkleTree extends import_merkletree.MerkleTreeImpl {
|
|
727
|
+
constructor(tree, values, leafEncoding) {
|
|
728
|
+
super(tree, values, (leaf) => {
|
|
729
|
+
return hash_leaf(leaf);
|
|
730
|
+
});
|
|
731
|
+
this.tree = tree;
|
|
732
|
+
this.values = values;
|
|
733
|
+
this.leafEncoding = leafEncoding;
|
|
734
|
+
}
|
|
735
|
+
static of(values, leafEncoding = [], options = {}) {
|
|
736
|
+
const [tree, indexedValues] = import_merkletree.MerkleTreeImpl.prepare(values, options, (leaf) => {
|
|
737
|
+
return hash_leaf(leaf);
|
|
738
|
+
});
|
|
739
|
+
return new _StandardMerkleTree(tree, indexedValues, leafEncoding);
|
|
740
|
+
}
|
|
741
|
+
static verify(root, leafEncoding, leaf, proof) {
|
|
742
|
+
return (0, import_bytes.toHex)(root) === (0, import_core.processProof)((0, import_hashes.standardLeafHash)(leafEncoding, leaf), proof);
|
|
743
|
+
}
|
|
744
|
+
static verifyMultiProof(root, leafEncoding, multiproof) {
|
|
745
|
+
return (0, import_bytes.toHex)(root) === (0, import_core.processMultiProof)({
|
|
746
|
+
leaves: multiproof.leaves.map((leaf) => (0, import_hashes.standardLeafHash)(leafEncoding, leaf)),
|
|
747
|
+
proof: multiproof.proof,
|
|
748
|
+
proofFlags: multiproof.proofFlags
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
dump() {
|
|
752
|
+
return {
|
|
753
|
+
format: "standard-v1",
|
|
754
|
+
leafEncoding: this.leafEncoding,
|
|
755
|
+
tree: this.tree,
|
|
756
|
+
values: this.values
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
// src/utils/strategy-utils.ts
|
|
762
|
+
function toAmountsInfo(tvlInfo) {
|
|
763
|
+
if ("token0" in tvlInfo) {
|
|
764
|
+
return {
|
|
765
|
+
usdValue: tvlInfo.usdValue,
|
|
766
|
+
amounts: [tvlInfo.token0, tvlInfo.token1]
|
|
767
|
+
};
|
|
768
|
+
} else {
|
|
769
|
+
return {
|
|
770
|
+
usdValue: tvlInfo.usdValue,
|
|
771
|
+
amounts: [tvlInfo]
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
function detectCapabilities(strategy) {
|
|
776
|
+
return {
|
|
777
|
+
hasMatchInputAmounts: typeof strategy.matchInputAmounts === "function",
|
|
778
|
+
hasNetAPY: typeof strategy.netAPY === "function",
|
|
779
|
+
hasGetInvestmentFlows: typeof strategy.getInvestmentFlows === "function",
|
|
780
|
+
hasGetPendingRewards: typeof strategy.getPendingRewards === "function",
|
|
781
|
+
hasHarvest: typeof strategy.harvest === "function",
|
|
782
|
+
hasRebalance: typeof strategy.getRebalanceCall === "function"
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
function isDualTokenStrategy(strategy) {
|
|
786
|
+
return typeof strategy.matchInputAmounts === "function";
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// src/utils/index.ts
|
|
790
|
+
function assert(condition, message) {
|
|
791
|
+
if (!condition) {
|
|
792
|
+
throw new Error(message);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
function getTrovesEndpoint() {
|
|
796
|
+
return process.env.TROVES_ENDPOINT || "https://app.troves.fi";
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// src/modules/avnu.ts
|
|
800
|
+
var AvnuWrapper = class {
|
|
801
|
+
async getQuotes(fromToken, toToken, amountWei, taker, retry = 0, excludeSources = ["Haiko(Solvers)"]) {
|
|
802
|
+
const MAX_RETRY = 5;
|
|
803
|
+
const params = {
|
|
804
|
+
sellTokenAddress: fromToken,
|
|
805
|
+
buyTokenAddress: toToken,
|
|
806
|
+
sellAmount: amountWei,
|
|
807
|
+
takerAddress: taker,
|
|
808
|
+
// excludeSources: ['Nostra', 'Haiko(Solvers)']
|
|
809
|
+
excludeSources
|
|
810
|
+
// excludeSources: ['Haiko(Solvers)'] // to resolve InvalidOraclePrice error
|
|
811
|
+
};
|
|
812
|
+
assert(fromToken != toToken, "From and to tokens are the same");
|
|
813
|
+
const quotes = await (0, import_avnu_sdk.fetchQuotes)(params);
|
|
814
|
+
const filteredQuotes = quotes.filter((q) => q.sellAmount.toString() == amountWei);
|
|
815
|
+
if (filteredQuotes.length == 0) {
|
|
816
|
+
if (retry < MAX_RETRY) {
|
|
817
|
+
await new Promise((res) => setTimeout(res, 3e3));
|
|
818
|
+
return await this.getQuotes(fromToken, toToken, amountWei, taker, retry + 1);
|
|
819
|
+
}
|
|
820
|
+
throw new Error("no quotes found");
|
|
821
|
+
}
|
|
822
|
+
return filteredQuotes[0];
|
|
823
|
+
}
|
|
824
|
+
async getSwapInfo(quote, taker, integratorFeeBps, integratorFeeRecipient, minAmount, options) {
|
|
825
|
+
const calldata = await (0, import_avnu_sdk.fetchBuildExecuteTransaction)(quote.quoteId, taker, void 0, void 0, options);
|
|
826
|
+
const call = calldata.calls[1];
|
|
827
|
+
const callData = call.calldata;
|
|
828
|
+
const routesLen = Number(callData[11]);
|
|
829
|
+
assert(routesLen > 0, "No routes found");
|
|
830
|
+
let startIndex = 12;
|
|
831
|
+
const routes = [];
|
|
832
|
+
for (let i = 0; i < routesLen; ++i) {
|
|
833
|
+
const swap_params_len = Number(callData[startIndex + 4]);
|
|
834
|
+
const route = {
|
|
835
|
+
token_from: callData[startIndex],
|
|
836
|
+
token_to: callData[startIndex + 1],
|
|
837
|
+
exchange_address: callData[startIndex + 2],
|
|
838
|
+
percent: Number(callData[startIndex + 3]),
|
|
839
|
+
additional_swap_params: swap_params_len > 0 ? callData.slice(startIndex + 5, startIndex + 5 + swap_params_len) : []
|
|
840
|
+
};
|
|
841
|
+
routes.push(route);
|
|
842
|
+
startIndex += 5 + swap_params_len;
|
|
843
|
+
}
|
|
844
|
+
const _minAmount = minAmount || (quote.buyAmount * 95n / 100n).toString();
|
|
845
|
+
const swapInfo = {
|
|
846
|
+
token_from_address: quote.sellTokenAddress,
|
|
847
|
+
token_from_amount: import_starknet4.uint256.bnToUint256(quote.sellAmount),
|
|
848
|
+
token_to_address: quote.buyTokenAddress,
|
|
849
|
+
token_to_amount: import_starknet4.uint256.bnToUint256(_minAmount),
|
|
850
|
+
token_to_min_amount: import_starknet4.uint256.bnToUint256(_minAmount),
|
|
851
|
+
beneficiary: taker,
|
|
852
|
+
integrator_fee_amount_bps: integratorFeeBps,
|
|
853
|
+
integrator_fee_recipient: integratorFeeRecipient,
|
|
854
|
+
routes
|
|
855
|
+
};
|
|
856
|
+
return swapInfo;
|
|
857
|
+
}
|
|
858
|
+
static buildZeroSwap(tokenToSell, beneficiary, tokenToBuy = tokenToSell) {
|
|
859
|
+
return {
|
|
860
|
+
token_from_address: tokenToSell.address,
|
|
861
|
+
token_from_amount: import_starknet4.uint256.bnToUint256(0),
|
|
862
|
+
token_to_address: tokenToBuy.address,
|
|
863
|
+
token_to_amount: import_starknet4.uint256.bnToUint256(0),
|
|
864
|
+
token_to_min_amount: import_starknet4.uint256.bnToUint256(0),
|
|
865
|
+
beneficiary,
|
|
866
|
+
integrator_fee_amount_bps: 0,
|
|
867
|
+
integrator_fee_recipient: beneficiary,
|
|
868
|
+
routes: []
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
|
|
541
873
|
// src/modules/pricer.ts
|
|
542
874
|
var Pricer = class extends PricerBase {
|
|
543
875
|
// e.g. ETH/USDC
|
|
@@ -552,8 +884,9 @@ var Pricer = class extends PricerBase {
|
|
|
552
884
|
/**
|
|
553
885
|
* TOKENA and TOKENB are the two token names to get price of TokenA in terms of TokenB
|
|
554
886
|
*/
|
|
887
|
+
// ! switch to USDC (new) later
|
|
555
888
|
this.PRICE_API = `https://api.coinbase.com/v2/prices/{{PRICER_KEY}}/buy`;
|
|
556
|
-
this.EKUBO_API = "https://
|
|
889
|
+
this.EKUBO_API = "https://prod-api-quoter.ekubo.org/23448594291968334/{{AMOUNT}}/{{TOKEN_ADDRESS}}/0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb";
|
|
557
890
|
this.refreshInterval = refreshInterval;
|
|
558
891
|
this.staleTime = staleTime;
|
|
559
892
|
}
|
|
@@ -609,7 +942,7 @@ var Pricer = class extends PricerBase {
|
|
|
609
942
|
let retry = 0;
|
|
610
943
|
while (retry < MAX_RETRIES) {
|
|
611
944
|
try {
|
|
612
|
-
if (token.symbol === "USDT") {
|
|
945
|
+
if (token.symbol === "USDT" || token.symbol === "USDC") {
|
|
613
946
|
this.prices[token.symbol] = {
|
|
614
947
|
price: 1,
|
|
615
948
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -687,6 +1020,15 @@ var Pricer = class extends PricerBase {
|
|
|
687
1020
|
console.warn(`Ekubo: price err [${token.symbol}]: `, error.message);
|
|
688
1021
|
console.warn(`Ekubo: price err [${token.symbol}]: `, Object.keys(error));
|
|
689
1022
|
}
|
|
1023
|
+
case "Avnu":
|
|
1024
|
+
try {
|
|
1025
|
+
const result = await this._getAvnuPrice(token, new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals));
|
|
1026
|
+
this.methodToUse[token.symbol] = "Avnu";
|
|
1027
|
+
return result;
|
|
1028
|
+
} catch (error) {
|
|
1029
|
+
console.warn(`Avnu: price err [${token.symbol}]: `, error.message);
|
|
1030
|
+
console.warn(`Avnu: price err [${token.symbol}]: `, Object.keys(error));
|
|
1031
|
+
}
|
|
690
1032
|
}
|
|
691
1033
|
if (defaultMethod == "all") {
|
|
692
1034
|
return await this._getPrice(token, "Coinbase");
|
|
@@ -702,7 +1044,24 @@ var Pricer = class extends PricerBase {
|
|
|
702
1044
|
async _getPriceCoinMarketCap(token) {
|
|
703
1045
|
throw new Error("Not implemented");
|
|
704
1046
|
}
|
|
1047
|
+
async _getAvnuPrice(token, amountIn = new Web3Number(1, token.decimals), retry = 0) {
|
|
1048
|
+
logger.verbose(`Getting price of ${token.symbol} using Ekubo, amountIn: ${amountIn.toWei()}`);
|
|
1049
|
+
const avnuWrapper = new AvnuWrapper();
|
|
1050
|
+
const usdcAddress = "0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb";
|
|
1051
|
+
const quote = await avnuWrapper.getQuotes(token.address.toString(), usdcAddress, amountIn.toWei(), "0x1");
|
|
1052
|
+
const multiplier = 1 / amountIn.toNumber();
|
|
1053
|
+
const outputUSDC = Number(Web3Number.fromWei(quote.buyAmount.toString(), 6).toFixed(6)) * multiplier;
|
|
1054
|
+
logger.verbose(`Avnu: ${token.symbol} -> USDC: ${outputUSDC}, retry: ${retry}`);
|
|
1055
|
+
if (outputUSDC === 0 && retry < 3) {
|
|
1056
|
+
const amountIn2 = new Web3Number(100, token.decimals);
|
|
1057
|
+
return await this._getAvnuPrice(token, amountIn2, retry + 1);
|
|
1058
|
+
}
|
|
1059
|
+
const usdcPrice = 1;
|
|
1060
|
+
logger.verbose(`USDC Price: ${usdcPrice}`);
|
|
1061
|
+
return outputUSDC * usdcPrice;
|
|
1062
|
+
}
|
|
705
1063
|
async _getPriceEkubo(token, amountIn = new Web3Number(1, token.decimals), retry = 0) {
|
|
1064
|
+
logger.verbose(`Getting price of ${token.symbol} using Ekubo, amountIn: ${amountIn.toWei()}`);
|
|
706
1065
|
const url = this.EKUBO_API.replace("{{TOKEN_ADDRESS}}", token.address.toString()).replace("{{AMOUNT}}", amountIn.toWei());
|
|
707
1066
|
const result = await import_axios2.default.get(url);
|
|
708
1067
|
const data = result.data;
|
|
@@ -720,7 +1079,7 @@ var Pricer = class extends PricerBase {
|
|
|
720
1079
|
};
|
|
721
1080
|
|
|
722
1081
|
// src/modules/pragma.ts
|
|
723
|
-
var
|
|
1082
|
+
var import_starknet5 = require("starknet");
|
|
724
1083
|
|
|
725
1084
|
// src/data/pragma.abi.json
|
|
726
1085
|
var pragma_abi_default = [
|
|
@@ -825,7 +1184,7 @@ var Pragma = class extends PricerBase {
|
|
|
825
1184
|
constructor(config, tokens2) {
|
|
826
1185
|
super(config, tokens2);
|
|
827
1186
|
this.contractAddr = "0x023fb3afbff2c0e3399f896dcf7400acf1a161941cfb386e34a123f228c62832";
|
|
828
|
-
this.contract = new
|
|
1187
|
+
this.contract = new import_starknet5.Contract({
|
|
829
1188
|
abi: pragma_abi_default,
|
|
830
1189
|
address: this.contractAddr,
|
|
831
1190
|
providerOrAccount: config.provider
|
|
@@ -1047,7 +1406,7 @@ var apolloClient = new import_client.ApolloClient({
|
|
|
1047
1406
|
var import_client2 = require("@apollo/client");
|
|
1048
1407
|
|
|
1049
1408
|
// src/modules/ekubo-pricer.ts
|
|
1050
|
-
var
|
|
1409
|
+
var import_starknet6 = require("starknet");
|
|
1051
1410
|
|
|
1052
1411
|
// src/data/ekubo-price-fethcer.abi.json
|
|
1053
1412
|
var ekubo_price_fethcer_abi_default = [
|
|
@@ -1323,14 +1682,14 @@ var EkuboPricer = class extends PricerBase {
|
|
|
1323
1682
|
this.EKUBO_PRICE_FETCHER_ADDRESS = "0x04946fb4ad5237d97bbb1256eba2080c4fe1de156da6a7f83e3b4823bb6d7da1";
|
|
1324
1683
|
this.USDC_ADDRESS = "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8";
|
|
1325
1684
|
this.USDC_DECIMALS = 6;
|
|
1326
|
-
this.contract = new
|
|
1685
|
+
this.contract = new import_starknet6.Contract({
|
|
1327
1686
|
abi: ekubo_price_fethcer_abi_default,
|
|
1328
1687
|
address: this.EKUBO_PRICE_FETCHER_ADDRESS,
|
|
1329
1688
|
providerOrAccount: config.provider
|
|
1330
1689
|
});
|
|
1331
1690
|
}
|
|
1332
|
-
div2Power128(
|
|
1333
|
-
return Number(
|
|
1691
|
+
div2Power128(num12) {
|
|
1692
|
+
return Number(num12 * BigInt(1e18) / BigInt(2 ** 128)) / 1e18;
|
|
1334
1693
|
}
|
|
1335
1694
|
async getPrice(tokenAddr, blockIdentifier = "latest") {
|
|
1336
1695
|
if (!tokenAddr) {
|
|
@@ -1534,7 +1893,7 @@ var PricerFromApi = class extends PricerBase {
|
|
|
1534
1893
|
};
|
|
1535
1894
|
|
|
1536
1895
|
// src/modules/erc20.ts
|
|
1537
|
-
var
|
|
1896
|
+
var import_starknet7 = require("starknet");
|
|
1538
1897
|
|
|
1539
1898
|
// src/data/erc20.abi.json
|
|
1540
1899
|
var erc20_abi_default = [
|
|
@@ -2667,7 +3026,7 @@ var ERC20 = class {
|
|
|
2667
3026
|
}
|
|
2668
3027
|
contract(addr) {
|
|
2669
3028
|
const _addr = typeof addr === "string" ? addr : addr.address;
|
|
2670
|
-
return new
|
|
3029
|
+
return new import_starknet7.Contract({ abi: erc20_abi_default, address: _addr, providerOrAccount: this.config.provider });
|
|
2671
3030
|
}
|
|
2672
3031
|
async balanceOf(token, address, tokenDecimals) {
|
|
2673
3032
|
const contract = this.contract(token);
|
|
@@ -2681,157 +3040,13 @@ var ERC20 = class {
|
|
|
2681
3040
|
}
|
|
2682
3041
|
};
|
|
2683
3042
|
|
|
2684
|
-
// src/modules/avnu.ts
|
|
2685
|
-
var import_starknet7 = require("starknet");
|
|
2686
|
-
var import_avnu_sdk = require("@avnu/avnu-sdk");
|
|
2687
|
-
|
|
2688
|
-
// src/utils/oz-merkle.ts
|
|
2689
|
-
var import_bytes = require("@ericnordelo/strk-merkle-tree/dist/bytes");
|
|
2690
|
-
var import_core = require("@ericnordelo/strk-merkle-tree/dist/core");
|
|
2691
|
-
var import_hashes = require("@ericnordelo/strk-merkle-tree/dist/hashes");
|
|
2692
|
-
var import_merkletree = require("@ericnordelo/strk-merkle-tree/dist/merkletree");
|
|
2693
|
-
var import_starknet5 = require("starknet");
|
|
2694
|
-
var import_starknet6 = require("@scure/starknet");
|
|
2695
|
-
function hash_leaf(leaf) {
|
|
2696
|
-
if (leaf.data.length < 1) {
|
|
2697
|
-
throw new Error("Invalid leaf data");
|
|
2698
|
-
}
|
|
2699
|
-
let firstElement = leaf.data[0];
|
|
2700
|
-
let value = firstElement;
|
|
2701
|
-
for (let i = 1; i < leaf.data.length; i++) {
|
|
2702
|
-
value = pedersen_hash(value, leaf.data[i]);
|
|
2703
|
-
}
|
|
2704
|
-
return `0x${import_starknet5.num.toHexString(value).replace(/^0x/, "").padStart(64, "0")}`;
|
|
2705
|
-
}
|
|
2706
|
-
function pedersen_hash(a, b) {
|
|
2707
|
-
return BigInt((0, import_starknet6.pedersen)(a, b).toString());
|
|
2708
|
-
}
|
|
2709
|
-
var StandardMerkleTree = class _StandardMerkleTree extends import_merkletree.MerkleTreeImpl {
|
|
2710
|
-
constructor(tree, values, leafEncoding) {
|
|
2711
|
-
super(tree, values, (leaf) => {
|
|
2712
|
-
return hash_leaf(leaf);
|
|
2713
|
-
});
|
|
2714
|
-
this.tree = tree;
|
|
2715
|
-
this.values = values;
|
|
2716
|
-
this.leafEncoding = leafEncoding;
|
|
2717
|
-
}
|
|
2718
|
-
static of(values, leafEncoding = [], options = {}) {
|
|
2719
|
-
const [tree, indexedValues] = import_merkletree.MerkleTreeImpl.prepare(values, options, (leaf) => {
|
|
2720
|
-
return hash_leaf(leaf);
|
|
2721
|
-
});
|
|
2722
|
-
return new _StandardMerkleTree(tree, indexedValues, leafEncoding);
|
|
2723
|
-
}
|
|
2724
|
-
static verify(root, leafEncoding, leaf, proof) {
|
|
2725
|
-
return (0, import_bytes.toHex)(root) === (0, import_core.processProof)((0, import_hashes.standardLeafHash)(leafEncoding, leaf), proof);
|
|
2726
|
-
}
|
|
2727
|
-
static verifyMultiProof(root, leafEncoding, multiproof) {
|
|
2728
|
-
return (0, import_bytes.toHex)(root) === (0, import_core.processMultiProof)({
|
|
2729
|
-
leaves: multiproof.leaves.map((leaf) => (0, import_hashes.standardLeafHash)(leafEncoding, leaf)),
|
|
2730
|
-
proof: multiproof.proof,
|
|
2731
|
-
proofFlags: multiproof.proofFlags
|
|
2732
|
-
});
|
|
2733
|
-
}
|
|
2734
|
-
dump() {
|
|
2735
|
-
return {
|
|
2736
|
-
format: "standard-v1",
|
|
2737
|
-
leafEncoding: this.leafEncoding,
|
|
2738
|
-
tree: this.tree,
|
|
2739
|
-
values: this.values
|
|
2740
|
-
};
|
|
2741
|
-
}
|
|
2742
|
-
};
|
|
2743
|
-
|
|
2744
|
-
// src/utils/index.ts
|
|
2745
|
-
function assert(condition, message) {
|
|
2746
|
-
if (!condition) {
|
|
2747
|
-
throw new Error(message);
|
|
2748
|
-
}
|
|
2749
|
-
}
|
|
2750
|
-
function getTrovesEndpoint() {
|
|
2751
|
-
return process.env.TROVES_ENDPOINT || "https://app.troves.fi";
|
|
2752
|
-
}
|
|
2753
|
-
|
|
2754
|
-
// src/modules/avnu.ts
|
|
2755
|
-
var AvnuWrapper = class {
|
|
2756
|
-
async getQuotes(fromToken, toToken, amountWei, taker, retry = 0, excludeSources = ["Haiko(Solvers)"]) {
|
|
2757
|
-
const MAX_RETRY = 5;
|
|
2758
|
-
const params = {
|
|
2759
|
-
sellTokenAddress: fromToken,
|
|
2760
|
-
buyTokenAddress: toToken,
|
|
2761
|
-
sellAmount: amountWei,
|
|
2762
|
-
takerAddress: taker,
|
|
2763
|
-
// excludeSources: ['Nostra', 'Haiko(Solvers)']
|
|
2764
|
-
excludeSources
|
|
2765
|
-
// excludeSources: ['Haiko(Solvers)'] // to resolve InvalidOraclePrice error
|
|
2766
|
-
};
|
|
2767
|
-
assert(fromToken != toToken, "From and to tokens are the same");
|
|
2768
|
-
const quotes = await (0, import_avnu_sdk.fetchQuotes)(params);
|
|
2769
|
-
const filteredQuotes = quotes.filter((q) => q.sellAmount.toString() == amountWei);
|
|
2770
|
-
if (filteredQuotes.length == 0) {
|
|
2771
|
-
if (retry < MAX_RETRY) {
|
|
2772
|
-
await new Promise((res) => setTimeout(res, 3e3));
|
|
2773
|
-
return await this.getQuotes(fromToken, toToken, amountWei, taker, retry + 1);
|
|
2774
|
-
}
|
|
2775
|
-
throw new Error("no quotes found");
|
|
2776
|
-
}
|
|
2777
|
-
return filteredQuotes[0];
|
|
2778
|
-
}
|
|
2779
|
-
async getSwapInfo(quote, taker, integratorFeeBps, integratorFeeRecipient, minAmount, options) {
|
|
2780
|
-
const calldata = await (0, import_avnu_sdk.fetchBuildExecuteTransaction)(quote.quoteId, taker, void 0, void 0, options);
|
|
2781
|
-
const call = calldata.calls[1];
|
|
2782
|
-
const callData = call.calldata;
|
|
2783
|
-
const routesLen = Number(callData[11]);
|
|
2784
|
-
assert(routesLen > 0, "No routes found");
|
|
2785
|
-
let startIndex = 12;
|
|
2786
|
-
const routes = [];
|
|
2787
|
-
for (let i = 0; i < routesLen; ++i) {
|
|
2788
|
-
const swap_params_len = Number(callData[startIndex + 4]);
|
|
2789
|
-
const route = {
|
|
2790
|
-
token_from: callData[startIndex],
|
|
2791
|
-
token_to: callData[startIndex + 1],
|
|
2792
|
-
exchange_address: callData[startIndex + 2],
|
|
2793
|
-
percent: Number(callData[startIndex + 3]),
|
|
2794
|
-
additional_swap_params: swap_params_len > 0 ? callData.slice(startIndex + 5, startIndex + 5 + swap_params_len) : []
|
|
2795
|
-
};
|
|
2796
|
-
routes.push(route);
|
|
2797
|
-
startIndex += 5 + swap_params_len;
|
|
2798
|
-
}
|
|
2799
|
-
const _minAmount = minAmount || (quote.buyAmount * 95n / 100n).toString();
|
|
2800
|
-
const swapInfo = {
|
|
2801
|
-
token_from_address: quote.sellTokenAddress,
|
|
2802
|
-
token_from_amount: import_starknet7.uint256.bnToUint256(quote.sellAmount),
|
|
2803
|
-
token_to_address: quote.buyTokenAddress,
|
|
2804
|
-
token_to_amount: import_starknet7.uint256.bnToUint256(_minAmount),
|
|
2805
|
-
token_to_min_amount: import_starknet7.uint256.bnToUint256(_minAmount),
|
|
2806
|
-
beneficiary: taker,
|
|
2807
|
-
integrator_fee_amount_bps: integratorFeeBps,
|
|
2808
|
-
integrator_fee_recipient: integratorFeeRecipient,
|
|
2809
|
-
routes
|
|
2810
|
-
};
|
|
2811
|
-
return swapInfo;
|
|
2812
|
-
}
|
|
2813
|
-
static buildZeroSwap(tokenToSell, beneficiary, tokenToBuy = tokenToSell) {
|
|
2814
|
-
return {
|
|
2815
|
-
token_from_address: tokenToSell.address,
|
|
2816
|
-
token_from_amount: import_starknet7.uint256.bnToUint256(0),
|
|
2817
|
-
token_to_address: tokenToBuy.address,
|
|
2818
|
-
token_to_amount: import_starknet7.uint256.bnToUint256(0),
|
|
2819
|
-
token_to_min_amount: import_starknet7.uint256.bnToUint256(0),
|
|
2820
|
-
beneficiary,
|
|
2821
|
-
integrator_fee_amount_bps: 0,
|
|
2822
|
-
integrator_fee_recipient: beneficiary,
|
|
2823
|
-
routes: []
|
|
2824
|
-
};
|
|
2825
|
-
}
|
|
2826
|
-
};
|
|
2827
|
-
|
|
2828
3043
|
// src/modules/ekubo-quoter.ts
|
|
2829
3044
|
var import_axios5 = __toESM(require("axios"));
|
|
2830
3045
|
var EkuboQuoter = class {
|
|
2831
3046
|
// e.g. ETH/USDC'
|
|
2832
3047
|
constructor(config) {
|
|
2833
3048
|
this.config = config;
|
|
2834
|
-
this.ENDPOINT = "https://
|
|
3049
|
+
this.ENDPOINT = "https://prod-api-quoter.ekubo.org/23448594291968334/{{AMOUNT}}/{{TOKEN_FROM_ADDRESS}}/{{TOKEN_TO_ADDRESS}}";
|
|
2835
3050
|
}
|
|
2836
3051
|
/**
|
|
2837
3052
|
*
|
|
@@ -2910,20 +3125,17 @@ var Network = /* @__PURE__ */ ((Network2) => {
|
|
|
2910
3125
|
Network2["devnet"] = "devnet";
|
|
2911
3126
|
return Network2;
|
|
2912
3127
|
})(Network || {});
|
|
2913
|
-
var
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
var StrategyTag = /* @__PURE__ */ ((StrategyTag2) => {
|
|
2920
|
-
StrategyTag2["EKUBO"] = "Ekubo";
|
|
2921
|
-
StrategyTag2["EVERGREEN"] = "Evergreen";
|
|
2922
|
-
StrategyTag2["HYPER_LST"] = "Hyper-LST";
|
|
2923
|
-
StrategyTag2["VESU"] = "Vesu";
|
|
2924
|
-
StrategyTag2["SENSEI"] = "Sensei";
|
|
2925
|
-
return StrategyTag2;
|
|
3128
|
+
var StrategyTag = /* @__PURE__ */ ((StrategyTag3) => {
|
|
3129
|
+
StrategyTag3["META_VAULT"] = "Meta Vaults";
|
|
3130
|
+
StrategyTag3["LEVERED"] = "Maxx";
|
|
3131
|
+
StrategyTag3["AUTOMATED_LP"] = "Ekubo";
|
|
3132
|
+
StrategyTag3["BTC"] = "BTC";
|
|
3133
|
+
return StrategyTag3;
|
|
2926
3134
|
})(StrategyTag || {});
|
|
3135
|
+
var VaultType = /* @__PURE__ */ ((VaultType2) => {
|
|
3136
|
+
VaultType2["FARMING"] = "farming";
|
|
3137
|
+
return VaultType2;
|
|
3138
|
+
})(VaultType || {});
|
|
2927
3139
|
var AuditStatus = /* @__PURE__ */ ((AuditStatus2) => {
|
|
2928
3140
|
AuditStatus2["AUDITED"] = "Audited";
|
|
2929
3141
|
AuditStatus2["NOT_AUDITED"] = "Not Audited";
|
|
@@ -2950,6 +3162,15 @@ var FlowChartColors = /* @__PURE__ */ ((FlowChartColors2) => {
|
|
|
2950
3162
|
FlowChartColors2["Purple"] = "#6e53dc";
|
|
2951
3163
|
return FlowChartColors2;
|
|
2952
3164
|
})(FlowChartColors || {});
|
|
3165
|
+
var StrategyLiveStatus = /* @__PURE__ */ ((StrategyLiveStatus2) => {
|
|
3166
|
+
StrategyLiveStatus2["ACTIVE"] = "Active";
|
|
3167
|
+
StrategyLiveStatus2["NEW"] = "New";
|
|
3168
|
+
StrategyLiveStatus2["COMING_SOON"] = "Coming Soon";
|
|
3169
|
+
StrategyLiveStatus2["DEPRECATED"] = "Deprecated";
|
|
3170
|
+
StrategyLiveStatus2["RETIRED"] = "Retired";
|
|
3171
|
+
StrategyLiveStatus2["HOT"] = "Hot & New \u{1F525}";
|
|
3172
|
+
return StrategyLiveStatus2;
|
|
3173
|
+
})(StrategyLiveStatus || {});
|
|
2953
3174
|
function getMainnetConfig(rpcUrl = "https://starknet-mainnet.public.blastapi.io", blockIdentifier = import_starknet8.BlockTag.LATEST) {
|
|
2954
3175
|
return {
|
|
2955
3176
|
provider: new import_starknet8.RpcProvider({
|
|
@@ -2961,6 +3182,21 @@ function getMainnetConfig(rpcUrl = "https://starknet-mainnet.public.blastapi.io"
|
|
|
2961
3182
|
network: "mainnet" /* mainnet */
|
|
2962
3183
|
};
|
|
2963
3184
|
}
|
|
3185
|
+
var getStrategyTagDesciption = (tag) => {
|
|
3186
|
+
switch (tag) {
|
|
3187
|
+
case "Meta Vaults" /* META_VAULT */:
|
|
3188
|
+
return "A meta vault is a vault that auto allocates funds to multiple vaults based on optimal yield opportunities";
|
|
3189
|
+
case "Maxx" /* LEVERED */:
|
|
3190
|
+
return "Looping vaults on Endur LSTs with leveraged borrowing of STRK or BTC to increase yield (2-4x higher yield than simply staking)";
|
|
3191
|
+
case "Ekubo" /* AUTOMATED_LP */:
|
|
3192
|
+
return "Automated LP vaults on Ekubo that rebalance position automatically, ensuring you earn fees efficiently";
|
|
3193
|
+
case "BTC" /* BTC */:
|
|
3194
|
+
return "BTC linked vaults";
|
|
3195
|
+
}
|
|
3196
|
+
};
|
|
3197
|
+
var getAllStrategyTags = () => {
|
|
3198
|
+
return Object.values(StrategyTag);
|
|
3199
|
+
};
|
|
2964
3200
|
var getRiskExplaination = (riskType) => {
|
|
2965
3201
|
switch (riskType) {
|
|
2966
3202
|
case "Market Risk" /* MARKET_RISK */:
|
|
@@ -4629,9 +4865,15 @@ var BaseStrategy = class extends CacheClass {
|
|
|
4629
4865
|
async getVaultPositions() {
|
|
4630
4866
|
throw new Error("Not implemented");
|
|
4631
4867
|
}
|
|
4868
|
+
async netAPY(blockIdentifier, sinceBlocks, timeperiod) {
|
|
4869
|
+
throw new Error("Not implemented");
|
|
4870
|
+
}
|
|
4632
4871
|
async getPendingRewards() {
|
|
4633
4872
|
return [];
|
|
4634
4873
|
}
|
|
4874
|
+
async getUserRealizedAPY(blockIdentifier, sinceBlocks) {
|
|
4875
|
+
throw new Error("Not implemented");
|
|
4876
|
+
}
|
|
4635
4877
|
};
|
|
4636
4878
|
|
|
4637
4879
|
// src/node/headless.browser.ts
|
|
@@ -4652,6 +4894,7 @@ var Harvests = class _Harvests {
|
|
|
4652
4894
|
}
|
|
4653
4895
|
async getUnHarvestedRewards(addr) {
|
|
4654
4896
|
const rewards = await this.getHarvests(addr);
|
|
4897
|
+
logger.verbose(`${_Harvests.name}: getUnHarvestedRewards => rewards length: ${rewards.length}`);
|
|
4655
4898
|
if (rewards.length == 0) return [];
|
|
4656
4899
|
const unClaimed = [];
|
|
4657
4900
|
const sortedRewards = rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime());
|
|
@@ -4678,27 +4921,30 @@ var Harvests = class _Harvests {
|
|
|
4678
4921
|
}
|
|
4679
4922
|
};
|
|
4680
4923
|
var STRK = "0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d";
|
|
4681
|
-
var EkuboHarvests = class extends Harvests {
|
|
4924
|
+
var EkuboHarvests = class _EkuboHarvests extends Harvests {
|
|
4682
4925
|
async getHarvests(addr) {
|
|
4683
|
-
|
|
4926
|
+
logger.verbose(`${_EkuboHarvests.name}: getHarvests => addr: ${addr.address}`);
|
|
4927
|
+
const EKUBO_API = `https://prod-api.ekubo.org/claims/${addr.address}`;
|
|
4684
4928
|
const resultEkubo = await fetch(EKUBO_API);
|
|
4685
|
-
const
|
|
4929
|
+
const data = await resultEkubo.json();
|
|
4930
|
+
const claims = data.claims || [];
|
|
4931
|
+
logger.verbose(`${_EkuboHarvests.name}: getHarvests => claims length: ${claims.length}`);
|
|
4686
4932
|
const rewards = [];
|
|
4687
|
-
for (let i = 0; i <
|
|
4688
|
-
const
|
|
4689
|
-
assert(
|
|
4933
|
+
for (let i = 0; i < claims.length; ++i) {
|
|
4934
|
+
const claimData = claims[i];
|
|
4935
|
+
assert(claimData.key.token == STRK, "expected strk token only");
|
|
4690
4936
|
rewards.push({
|
|
4691
|
-
rewardsContract: ContractAddr.from(
|
|
4937
|
+
rewardsContract: ContractAddr.from(claimData.dropAddress),
|
|
4692
4938
|
token: ContractAddr.from(STRK),
|
|
4693
|
-
startDate: new Date(
|
|
4694
|
-
endDate: new Date(
|
|
4939
|
+
startDate: /* @__PURE__ */ new Date(0),
|
|
4940
|
+
endDate: /* @__PURE__ */ new Date(0),
|
|
4695
4941
|
claim: {
|
|
4696
|
-
id:
|
|
4697
|
-
amount: Web3Number.fromWei(
|
|
4698
|
-
claimee: ContractAddr.from(
|
|
4942
|
+
id: claimData.claim.index,
|
|
4943
|
+
amount: Web3Number.fromWei(claimData.claim.amount, 18),
|
|
4944
|
+
claimee: ContractAddr.from(claimData.claim.account)
|
|
4699
4945
|
},
|
|
4700
|
-
actualReward: Web3Number.fromWei(
|
|
4701
|
-
proof:
|
|
4946
|
+
actualReward: Web3Number.fromWei(claimData.claim.amount, 18),
|
|
4947
|
+
proof: claimData.proof
|
|
4702
4948
|
});
|
|
4703
4949
|
}
|
|
4704
4950
|
return rewards.sort((a, b) => b.endDate.getTime() - a.endDate.getTime());
|
|
@@ -10393,7 +10639,7 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
10393
10639
|
};
|
|
10394
10640
|
}
|
|
10395
10641
|
static async getAllPossibleVerifiedPools(asset) {
|
|
10396
|
-
const data = await getAPIUsingHeadlessBrowser(`${ENDPOINTS.
|
|
10642
|
+
const data = await getAPIUsingHeadlessBrowser(`${ENDPOINTS.VESU_BASE}/pools`);
|
|
10397
10643
|
const verifiedPools = data.data.filter((d) => d.isVerified);
|
|
10398
10644
|
const pools = verifiedPools.map((p) => {
|
|
10399
10645
|
const hasMyAsset = p.assets.find((a) => asset.eqString(a.address));
|
|
@@ -10570,7 +10816,7 @@ var VesuRebalance = class _VesuRebalance extends BaseStrategy {
|
|
|
10570
10816
|
let pools = [];
|
|
10571
10817
|
try {
|
|
10572
10818
|
const data = await getAPIUsingHeadlessBrowser(
|
|
10573
|
-
`${ENDPOINTS.
|
|
10819
|
+
`${ENDPOINTS.VESU_BASE}/pools`
|
|
10574
10820
|
);
|
|
10575
10821
|
pools = data.data;
|
|
10576
10822
|
for (const pool of vesu_pools_default.data) {
|
|
@@ -10918,6 +11164,57 @@ var _riskFactor = [
|
|
|
10918
11164
|
{ type: "Oracle Risk" /* ORACLE_RISK */, value: 0.5, weight: 25, reason: "Uses Pragma price feeds, Most reputable price feed on Starknet" }
|
|
10919
11165
|
];
|
|
10920
11166
|
var AUDIT_URL = "https://assets.troves.fi/strkfarm/audit_report_vesu_and_ekubo_strats.pdf";
|
|
11167
|
+
var getVesuRebalanceRisk = () => ({
|
|
11168
|
+
riskFactor: _riskFactor,
|
|
11169
|
+
netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
11170
|
+
notARisks: getNoRiskTags(_riskFactor)
|
|
11171
|
+
});
|
|
11172
|
+
var createVesuRebalanceSettings = (tokenSymbol) => {
|
|
11173
|
+
const depositToken = Global.getDefaultTokens().find(
|
|
11174
|
+
(t) => t.symbol === tokenSymbol
|
|
11175
|
+
);
|
|
11176
|
+
return {
|
|
11177
|
+
maxTVL: Web3Number.fromWei("0", depositToken.decimals),
|
|
11178
|
+
isPaused: false,
|
|
11179
|
+
liveStatus: "Active" /* ACTIVE */,
|
|
11180
|
+
isAudited: true,
|
|
11181
|
+
isInstantWithdrawal: true,
|
|
11182
|
+
quoteToken: depositToken,
|
|
11183
|
+
alerts: []
|
|
11184
|
+
};
|
|
11185
|
+
};
|
|
11186
|
+
var createVesuRebalanceStrategy = (idSymbol, name, tokenSymbol, address) => ({
|
|
11187
|
+
id: `vesu_fusion_${idSymbol.toLowerCase()}`,
|
|
11188
|
+
name,
|
|
11189
|
+
description: _description.replace("{{TOKEN}}", tokenSymbol),
|
|
11190
|
+
address: ContractAddr.from(address),
|
|
11191
|
+
launchBlock: 0,
|
|
11192
|
+
type: "ERC4626",
|
|
11193
|
+
vaultType: {
|
|
11194
|
+
type: "farming" /* FARMING */,
|
|
11195
|
+
description: "this is a yield farming vault"
|
|
11196
|
+
},
|
|
11197
|
+
depositTokens: [
|
|
11198
|
+
Global.getDefaultTokens().find((t) => t.symbol === tokenSymbol)
|
|
11199
|
+
],
|
|
11200
|
+
protocols: [_protocol],
|
|
11201
|
+
auditUrl: AUDIT_URL,
|
|
11202
|
+
curator: {
|
|
11203
|
+
name: "Unwrap Labs",
|
|
11204
|
+
logo: "https://assets.troves.fi/integrations/unwraplabs/white.png"
|
|
11205
|
+
},
|
|
11206
|
+
settings: createVesuRebalanceSettings(tokenSymbol),
|
|
11207
|
+
risk: getVesuRebalanceRisk(),
|
|
11208
|
+
additionalInfo: {
|
|
11209
|
+
feeBps: 1e3
|
|
11210
|
+
},
|
|
11211
|
+
faqs,
|
|
11212
|
+
contractDetails: [],
|
|
11213
|
+
investmentSteps: [],
|
|
11214
|
+
tags: [],
|
|
11215
|
+
security: VESU_SECURITY,
|
|
11216
|
+
redemptionInfo: VESU_REDEMPTION_INFO
|
|
11217
|
+
});
|
|
10921
11218
|
var VESU_SECURITY = {
|
|
10922
11219
|
auditStatus: "Audited" /* AUDITED */,
|
|
10923
11220
|
sourceCode: {
|
|
@@ -10976,142 +11273,30 @@ var faqs = [
|
|
|
10976
11273
|
}
|
|
10977
11274
|
];
|
|
10978
11275
|
var VesuRebalanceStrategies = [
|
|
10979
|
-
|
|
10980
|
-
|
|
10981
|
-
|
|
10982
|
-
|
|
10983
|
-
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
|
|
11001
|
-
|
|
11002
|
-
|
|
11003
|
-
investmentSteps: [],
|
|
11004
|
-
category: "all" /* ALL */,
|
|
11005
|
-
tags: ["Vesu" /* VESU */],
|
|
11006
|
-
security: VESU_SECURITY,
|
|
11007
|
-
redemptionInfo: VESU_REDEMPTION_INFO
|
|
11008
|
-
},
|
|
11009
|
-
{
|
|
11010
|
-
name: "Vesu Fusion ETH",
|
|
11011
|
-
description: _description.replace("{{TOKEN}}", "ETH"),
|
|
11012
|
-
address: ContractAddr.from(
|
|
11013
|
-
"0x5eaf5ee75231cecf79921ff8ded4b5ffe96be718bcb3daf206690ad1a9ad0ca"
|
|
11014
|
-
),
|
|
11015
|
-
launchBlock: 0,
|
|
11016
|
-
type: "ERC4626",
|
|
11017
|
-
auditUrl: AUDIT_URL,
|
|
11018
|
-
depositTokens: [
|
|
11019
|
-
Global.getDefaultTokens().find((t) => t.symbol === "ETH")
|
|
11020
|
-
],
|
|
11021
|
-
protocols: [_protocol],
|
|
11022
|
-
maxTVL: Web3Number.fromWei("0", 18),
|
|
11023
|
-
risk: {
|
|
11024
|
-
riskFactor: _riskFactor,
|
|
11025
|
-
netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
11026
|
-
notARisks: getNoRiskTags(_riskFactor)
|
|
11027
|
-
},
|
|
11028
|
-
additionalInfo: {
|
|
11029
|
-
feeBps: 1e3
|
|
11030
|
-
},
|
|
11031
|
-
faqs,
|
|
11032
|
-
contractDetails: [],
|
|
11033
|
-
investmentSteps: [],
|
|
11034
|
-
category: "all" /* ALL */,
|
|
11035
|
-
tags: ["Vesu" /* VESU */],
|
|
11036
|
-
security: VESU_SECURITY,
|
|
11037
|
-
redemptionInfo: VESU_REDEMPTION_INFO
|
|
11038
|
-
},
|
|
11039
|
-
{
|
|
11040
|
-
name: "Vesu Fusion USDC",
|
|
11041
|
-
description: _description.replace("{{TOKEN}}", "USDC"),
|
|
11042
|
-
address: ContractAddr.from(
|
|
11043
|
-
"0xa858c97e9454f407d1bd7c57472fc8d8d8449a777c822b41d18e387816f29c"
|
|
11044
|
-
),
|
|
11045
|
-
launchBlock: 0,
|
|
11046
|
-
type: "ERC4626",
|
|
11047
|
-
auditUrl: AUDIT_URL,
|
|
11048
|
-
depositTokens: [
|
|
11049
|
-
Global.getDefaultTokens().find((t) => t.symbol === "USDC")
|
|
11050
|
-
],
|
|
11051
|
-
protocols: [_protocol],
|
|
11052
|
-
maxTVL: Web3Number.fromWei("0", 6),
|
|
11053
|
-
risk: {
|
|
11054
|
-
riskFactor: _riskFactor,
|
|
11055
|
-
netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
11056
|
-
notARisks: getNoRiskTags(_riskFactor)
|
|
11057
|
-
},
|
|
11058
|
-
additionalInfo: {
|
|
11059
|
-
feeBps: 1e3
|
|
11060
|
-
},
|
|
11061
|
-
faqs,
|
|
11062
|
-
contractDetails: [],
|
|
11063
|
-
investmentSteps: [],
|
|
11064
|
-
category: "all" /* ALL */,
|
|
11065
|
-
tags: ["Vesu" /* VESU */],
|
|
11066
|
-
security: VESU_SECURITY,
|
|
11067
|
-
redemptionInfo: VESU_REDEMPTION_INFO
|
|
11068
|
-
},
|
|
11069
|
-
{
|
|
11070
|
-
name: "Vesu Fusion USDT",
|
|
11071
|
-
description: _description.replace("{{TOKEN}}", "USDT"),
|
|
11072
|
-
address: ContractAddr.from(
|
|
11073
|
-
"0x115e94e722cfc4c77a2f15c4aefb0928c1c0029e5a57570df24c650cb7cec2c"
|
|
11074
|
-
),
|
|
11075
|
-
launchBlock: 0,
|
|
11076
|
-
type: "ERC4626",
|
|
11077
|
-
depositTokens: [
|
|
11078
|
-
Global.getDefaultTokens().find((t) => t.symbol === "USDT")
|
|
11079
|
-
],
|
|
11080
|
-
auditUrl: AUDIT_URL,
|
|
11081
|
-
protocols: [_protocol],
|
|
11082
|
-
maxTVL: Web3Number.fromWei("0", 6),
|
|
11083
|
-
risk: {
|
|
11084
|
-
riskFactor: _riskFactor,
|
|
11085
|
-
netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
11086
|
-
notARisks: getNoRiskTags(_riskFactor)
|
|
11087
|
-
},
|
|
11088
|
-
additionalInfo: {
|
|
11089
|
-
feeBps: 1e3
|
|
11090
|
-
},
|
|
11091
|
-
faqs,
|
|
11092
|
-
contractDetails: [],
|
|
11093
|
-
investmentSteps: [],
|
|
11094
|
-
category: "all" /* ALL */,
|
|
11095
|
-
tags: ["Vesu" /* VESU */],
|
|
11096
|
-
security: VESU_SECURITY,
|
|
11097
|
-
redemptionInfo: VESU_REDEMPTION_INFO
|
|
11098
|
-
// }, {
|
|
11099
|
-
// name: 'Vesu Fusion WBTC',
|
|
11100
|
-
// description: _description.replace('{{TOKEN}}', 'WBTC'),
|
|
11101
|
-
// address: ContractAddr.from('0x778007f8136a5b827325d21613803e796bda4d676fbe1e34aeab0b2a2ec027f'),
|
|
11102
|
-
// type: 'ERC4626',
|
|
11103
|
-
// depositTokens: [Global.getDefaultTokens().find(t => t.symbol === 'WBTC')!],
|
|
11104
|
-
// auditUrl: AUDIT_URL,
|
|
11105
|
-
// protocols: [_protocol],
|
|
11106
|
-
// maxTVL: Web3Number.fromWei('0', 8),
|
|
11107
|
-
// risk: {
|
|
11108
|
-
// riskFactor: _riskFactor,
|
|
11109
|
-
// netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
11110
|
-
// },
|
|
11111
|
-
// additionalInfo: {
|
|
11112
|
-
// feeBps: 1000,
|
|
11113
|
-
// },
|
|
11114
|
-
}
|
|
11276
|
+
createVesuRebalanceStrategy(
|
|
11277
|
+
"strk",
|
|
11278
|
+
"Vesu Fusion STRK",
|
|
11279
|
+
"STRK",
|
|
11280
|
+
"0x7fb5bcb8525954a60fde4e8fb8220477696ce7117ef264775a1770e23571929"
|
|
11281
|
+
),
|
|
11282
|
+
createVesuRebalanceStrategy(
|
|
11283
|
+
"eth",
|
|
11284
|
+
"Vesu Fusion ETH",
|
|
11285
|
+
"ETH",
|
|
11286
|
+
"0x5eaf5ee75231cecf79921ff8ded4b5ffe96be718bcb3daf206690ad1a9ad0ca"
|
|
11287
|
+
),
|
|
11288
|
+
createVesuRebalanceStrategy(
|
|
11289
|
+
"usdc",
|
|
11290
|
+
"Vesu Fusion USDC.e",
|
|
11291
|
+
"USDC.e",
|
|
11292
|
+
"0xa858c97e9454f407d1bd7c57472fc8d8d8449a777c822b41d18e387816f29c"
|
|
11293
|
+
),
|
|
11294
|
+
createVesuRebalanceStrategy(
|
|
11295
|
+
"usdt",
|
|
11296
|
+
"Vesu Fusion USDT",
|
|
11297
|
+
"USDT",
|
|
11298
|
+
"0x115e94e722cfc4c77a2f15c4aefb0928c1c0029e5a57570df24c650cb7cec2c"
|
|
11299
|
+
)
|
|
11115
11300
|
];
|
|
11116
11301
|
VesuRebalanceStrategies.forEach((s) => {
|
|
11117
11302
|
s.contractDetails = [
|
|
@@ -16450,7 +16635,7 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
16450
16635
|
* @returns {Promise<number>} The weighted average APY across all pools
|
|
16451
16636
|
*/
|
|
16452
16637
|
async netAPY(blockIdentifier = "latest", sinceBlocks = 6e5, timeperiod = "24h") {
|
|
16453
|
-
const isUSDCQouteToken = this.metadata.additionalInfo.quoteAsset.symbol === "USDC";
|
|
16638
|
+
const isUSDCQouteToken = this.metadata.additionalInfo.quoteAsset.symbol === "USDC.e" || this.metadata.additionalInfo.quoteAsset.symbol === "USDC";
|
|
16454
16639
|
if (!isUSDCQouteToken) {
|
|
16455
16640
|
return this.netSharesBasedTrueAPY(blockIdentifier, sinceBlocks);
|
|
16456
16641
|
} else {
|
|
@@ -16682,8 +16867,8 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
16682
16867
|
upperTick: _EkuboCLVault.i129ToNumber(result.bounds.upper)
|
|
16683
16868
|
};
|
|
16684
16869
|
}
|
|
16685
|
-
static div2Power128(
|
|
16686
|
-
return Number(BigInt(
|
|
16870
|
+
static div2Power128(num12) {
|
|
16871
|
+
return Number(BigInt(num12.toString()) * BigInt(1e18) / BigInt(2 ** 128)) / 1e18;
|
|
16687
16872
|
}
|
|
16688
16873
|
static priceToTick(price, isRoundDown, tickSpacing) {
|
|
16689
16874
|
const value = isRoundDown ? Math.floor(Math.log(price) / Math.log(1.000001)) : Math.ceil(Math.log(price) / Math.log(1.000001));
|
|
@@ -16867,6 +17052,12 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
16867
17052
|
amount1: availableAmount1.minus(y),
|
|
16868
17053
|
ratio: 0
|
|
16869
17054
|
};
|
|
17055
|
+
} else if (ratio.eq(Infinity)) {
|
|
17056
|
+
return {
|
|
17057
|
+
amount0: availableAmount0,
|
|
17058
|
+
amount1: Web3Number.fromWei("0", availableAmount1.decimals),
|
|
17059
|
+
ratio: Infinity
|
|
17060
|
+
};
|
|
16870
17061
|
}
|
|
16871
17062
|
return {
|
|
16872
17063
|
amount0: availableAmount0.plus(x),
|
|
@@ -16909,7 +17100,7 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
16909
17100
|
}
|
|
16910
17101
|
};
|
|
16911
17102
|
}
|
|
16912
|
-
async getSwapInfoToHandleUnused(considerRebalance = true, newBounds = null, maxIterations = 20, priceRatioPrecision = 4) {
|
|
17103
|
+
async getSwapInfoToHandleUnused(considerRebalance = true, newBounds = null, maxIterations = 20, priceRatioPrecision = 4, getQuoteCallback = this.avnu.getQuotes) {
|
|
16913
17104
|
const poolKey = await this.getPoolKey();
|
|
16914
17105
|
const unusedBalances = await this.unusedBalances(poolKey);
|
|
16915
17106
|
const { amount: token0Bal1, usdValue: token0PriceUsd } = unusedBalances.token0;
|
|
@@ -16949,7 +17140,8 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
16949
17140
|
token1Bal,
|
|
16950
17141
|
ekuboBounds,
|
|
16951
17142
|
maxIterations,
|
|
16952
|
-
priceRatioPrecision
|
|
17143
|
+
priceRatioPrecision,
|
|
17144
|
+
getQuoteCallback
|
|
16953
17145
|
);
|
|
16954
17146
|
}
|
|
16955
17147
|
assertValidBounds(bounds) {
|
|
@@ -16973,6 +17165,7 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
16973
17165
|
// Helper to determine which token to sell, which to buy, and the amounts to use
|
|
16974
17166
|
getSwapParams(expectedAmounts, poolKey, token0Bal, token1Bal) {
|
|
16975
17167
|
const tokenToSell = expectedAmounts.amount0.lessThan(token0Bal) ? poolKey.token0 : poolKey.token1;
|
|
17168
|
+
logger.verbose(`getSwapParams => tokenToSell: ${tokenToSell.address}, expectedAmounts: ${expectedAmounts.amount0.toString()}, bal0: ${token0Bal.toString()}`);
|
|
16976
17169
|
const tokenToBuy = tokenToSell == poolKey.token0 ? poolKey.token1 : poolKey.token0;
|
|
16977
17170
|
const amountToSell = tokenToSell == poolKey.token0 ? token0Bal.minus(expectedAmounts.amount0) : token1Bal.minus(expectedAmounts.amount1);
|
|
16978
17171
|
if (amountToSell.eq(0)) {
|
|
@@ -16994,7 +17187,7 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
16994
17187
|
* @returns {Promise<SwapInfo>}
|
|
16995
17188
|
*
|
|
16996
17189
|
*/
|
|
16997
|
-
async getSwapInfoGivenAmounts(poolKey, token0Bal, token1Bal, bounds, maxIterations = 20, priceRatioPrecision = 4) {
|
|
17190
|
+
async getSwapInfoGivenAmounts(poolKey, token0Bal, token1Bal, bounds, maxIterations = 20, priceRatioPrecision = 4, getQuoteCallback = this.avnu.getQuotes) {
|
|
16998
17191
|
logger.verbose(
|
|
16999
17192
|
`${_EkuboCLVault.name}: getSwapInfoGivenAmounts::pre => token0Bal: ${token0Bal.toString()}, token1Bal: ${token1Bal.toString()}`
|
|
17000
17193
|
);
|
|
@@ -17029,12 +17222,7 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
17029
17222
|
if (amountToSell.eq(0)) {
|
|
17030
17223
|
return AvnuWrapper.buildZeroSwap(tokenToSell, this.address.address);
|
|
17031
17224
|
}
|
|
17032
|
-
const quote = await this.
|
|
17033
|
-
tokenToSell.address,
|
|
17034
|
-
tokenToBuy.address,
|
|
17035
|
-
amountToSell.toWei(),
|
|
17036
|
-
this.address.address
|
|
17037
|
-
);
|
|
17225
|
+
const quote = await getQuoteCallback(tokenToSell.address, tokenToBuy.address, amountToSell.toWei(), this.address.address);
|
|
17038
17226
|
if (remainingSellAmount.eq(0)) {
|
|
17039
17227
|
const minAmountOut = Web3Number.fromWei(
|
|
17040
17228
|
quote.buyAmount.toString(),
|
|
@@ -17117,14 +17305,22 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
17117
17305
|
* @param retry - Current retry attempt number (default 0)
|
|
17118
17306
|
* @param adjustmentFactor - Percentage to adjust swap amount by (default 1)
|
|
17119
17307
|
* @param isToken0Deficit - Whether token0 balance needs increasing (default true)
|
|
17308
|
+
* @param MAX_RETRIES - Maximum number of retries (default 40)
|
|
17309
|
+
* @param sameErrorCount - For certain errors, we just retry with same amount again. This is the count of such retries (default { count: 0, error: null })
|
|
17310
|
+
* @param MAX_SAME_ERROR_COUNT - For certain errors, we just retry with same amount again. This limits such retries (default 10)
|
|
17120
17311
|
* @returns Array of contract calls needed for rebalancing
|
|
17121
|
-
* @throws Error if max retries reached without successful rebalance
|
|
17312
|
+
* @throws Error if max retries reached without successful rebalance or max same errors reached
|
|
17122
17313
|
*/
|
|
17123
|
-
async rebalanceIter(swapInfo, acc, estimateCall, isSellTokenToken0 = true, retry = 0, lowerLimit = 0n, upperLimit = 0n, MAX_RETRIES = 40) {
|
|
17314
|
+
async rebalanceIter(swapInfo, acc, estimateCall, isSellTokenToken0 = true, retry = 0, lowerLimit = 0n, upperLimit = 0n, MAX_RETRIES = 40, sameErrorCount = { count: 0, error: null }, MAX_SAME_ERROR_COUNT = 10) {
|
|
17124
17315
|
logger.verbose(
|
|
17125
|
-
`Rebalancing ${this.metadata.name}: retry=${retry}, lowerLimit=${lowerLimit}, upperLimit=${upperLimit}, isSellTokenToken0=${isSellTokenToken0}`
|
|
17316
|
+
`Rebalancing ${this.metadata.name}: retry=${retry}, lowerLimit=${lowerLimit}, upperLimit=${upperLimit}, isSellTokenToken0=${isSellTokenToken0}, MAX_RETRIES=${MAX_RETRIES}, sameErrorCount=${sameErrorCount.error} (${sameErrorCount.count})`
|
|
17126
17317
|
);
|
|
17318
|
+
if (sameErrorCount.count >= MAX_SAME_ERROR_COUNT) {
|
|
17319
|
+
logger.error(`Rebalance failed after ${MAX_SAME_ERROR_COUNT} same errors`);
|
|
17320
|
+
throw new Error(`Rebalance failed after ${MAX_SAME_ERROR_COUNT} same errors`);
|
|
17321
|
+
}
|
|
17127
17322
|
const fromAmount = import_starknet12.uint256.uint256ToBN(swapInfo.token_from_amount);
|
|
17323
|
+
const fromTokenInfo = await Global.getTokenInfoFromAddr(ContractAddr.from(swapInfo.token_from_address));
|
|
17128
17324
|
logger.verbose(
|
|
17129
17325
|
`Selling ${fromAmount.toString()} of token ${swapInfo.token_from_address}`
|
|
17130
17326
|
);
|
|
@@ -17141,8 +17337,8 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
17141
17337
|
`Rebalance attempt ${retry + 1} failed, adjusting swap amount...`
|
|
17142
17338
|
);
|
|
17143
17339
|
const newSwapInfo = { ...swapInfo };
|
|
17144
|
-
const currentAmount = Web3Number.fromWei(fromAmount.toString(),
|
|
17145
|
-
logger.verbose(`Current amount: ${currentAmount.toString()}`);
|
|
17340
|
+
const currentAmount = Web3Number.fromWei(fromAmount.toString(), fromTokenInfo.decimals);
|
|
17341
|
+
logger.verbose(`Current amount: ${currentAmount.toString()}, lowerLimit: ${lowerLimit.toString()}, upperLimit: ${upperLimit.toString()}`);
|
|
17146
17342
|
if (err.message.includes("invalid token0 balance") || err.message.includes("invalid token0 amount")) {
|
|
17147
17343
|
if (!isSellTokenToken0) {
|
|
17148
17344
|
logger.verbose("Reducing swap amount - excess token0");
|
|
@@ -17189,6 +17385,30 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
17189
17385
|
}
|
|
17190
17386
|
newSwapInfo.token_from_amount = import_starknet12.uint256.bnToUint256(nextAmount);
|
|
17191
17387
|
}
|
|
17388
|
+
} else if (err.message.includes("Residual tokens")) {
|
|
17389
|
+
logger.error("Residual tokens");
|
|
17390
|
+
if (sameErrorCount.error == "Residual tokens") {
|
|
17391
|
+
sameErrorCount.count++;
|
|
17392
|
+
} else {
|
|
17393
|
+
sameErrorCount.error = "Residual tokens";
|
|
17394
|
+
sameErrorCount.count = 1;
|
|
17395
|
+
}
|
|
17396
|
+
} else if (err.message.includes("Insufficient tokens received")) {
|
|
17397
|
+
logger.error("Insufficient tokens received");
|
|
17398
|
+
if (sameErrorCount.error == "Insufficient tokens received") {
|
|
17399
|
+
sameErrorCount.count++;
|
|
17400
|
+
} else {
|
|
17401
|
+
sameErrorCount.error = "Insufficient tokens received";
|
|
17402
|
+
sameErrorCount.count = 1;
|
|
17403
|
+
}
|
|
17404
|
+
} else if (err.message.includes("Could not reach the end of the program")) {
|
|
17405
|
+
logger.error("Could not reach the end of the program, may be the block is full (could be a temp/permanent gas issue)");
|
|
17406
|
+
if (sameErrorCount.error == "Could not reach the end of the program") {
|
|
17407
|
+
sameErrorCount.count++;
|
|
17408
|
+
} else {
|
|
17409
|
+
sameErrorCount.error = "Could not reach the end of the program";
|
|
17410
|
+
sameErrorCount.count = 1;
|
|
17411
|
+
}
|
|
17192
17412
|
} else {
|
|
17193
17413
|
logger.error("Unexpected error:", err);
|
|
17194
17414
|
throw err;
|
|
@@ -17201,7 +17421,10 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
17201
17421
|
isSellTokenToken0,
|
|
17202
17422
|
retry + 1,
|
|
17203
17423
|
lowerLimit,
|
|
17204
|
-
upperLimit
|
|
17424
|
+
upperLimit,
|
|
17425
|
+
MAX_RETRIES,
|
|
17426
|
+
sameErrorCount,
|
|
17427
|
+
MAX_SAME_ERROR_COUNT
|
|
17205
17428
|
);
|
|
17206
17429
|
}
|
|
17207
17430
|
}
|
|
@@ -17530,7 +17753,8 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
17530
17753
|
return harvestCall;
|
|
17531
17754
|
}
|
|
17532
17755
|
async getInvestmentFlows() {
|
|
17533
|
-
const
|
|
17756
|
+
const blocksDiff = this.metadata.additionalInfo.lstContract ? 6e5 : 6e5 / 4;
|
|
17757
|
+
const netYield = await this.netAPY("latest", blocksDiff, "7d");
|
|
17534
17758
|
const poolKey = await this.getPoolKey();
|
|
17535
17759
|
const linkedFlow = {
|
|
17536
17760
|
title: this.metadata.name,
|
|
@@ -17653,6 +17877,7 @@ function getLSTFAQs(lstSymbol) {
|
|
|
17653
17877
|
];
|
|
17654
17878
|
}
|
|
17655
17879
|
var xSTRKSTRK = {
|
|
17880
|
+
id: "ekubo_cl_xstrkstrk",
|
|
17656
17881
|
name: "Ekubo xSTRK/STRK",
|
|
17657
17882
|
description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
|
|
17658
17883
|
address: ContractAddr.from(
|
|
@@ -17660,6 +17885,10 @@ var xSTRKSTRK = {
|
|
|
17660
17885
|
),
|
|
17661
17886
|
launchBlock: 1209881,
|
|
17662
17887
|
type: "Other",
|
|
17888
|
+
vaultType: {
|
|
17889
|
+
type: "farming" /* FARMING */,
|
|
17890
|
+
description: "this is a yield farming vault"
|
|
17891
|
+
},
|
|
17663
17892
|
// must be same order as poolKey token0 and token1
|
|
17664
17893
|
depositTokens: [
|
|
17665
17894
|
Global.getDefaultTokens().find((t) => t.symbol === "xSTRK"),
|
|
@@ -17667,7 +17896,10 @@ var xSTRKSTRK = {
|
|
|
17667
17896
|
],
|
|
17668
17897
|
protocols: [_protocol2],
|
|
17669
17898
|
auditUrl: AUDIT_URL2,
|
|
17670
|
-
|
|
17899
|
+
curator: {
|
|
17900
|
+
name: "Unwrap Labs",
|
|
17901
|
+
logo: "https://assets.troves.fi/integrations/unwraplabs/white.png"
|
|
17902
|
+
},
|
|
17671
17903
|
risk: {
|
|
17672
17904
|
riskFactor: _lstPoolRiskFactors,
|
|
17673
17905
|
netRisk: _lstPoolRiskFactors.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _lstPoolRiskFactors.reduce((acc, curr) => acc + curr.weight, 0),
|
|
@@ -17690,6 +17922,41 @@ var xSTRKSTRK = {
|
|
|
17690
17922
|
},
|
|
17691
17923
|
quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "STRK")
|
|
17692
17924
|
},
|
|
17925
|
+
settings: {
|
|
17926
|
+
maxTVL: Web3Number.fromWei("0", 18),
|
|
17927
|
+
isAudited: true,
|
|
17928
|
+
isPaused: false,
|
|
17929
|
+
liveStatus: "Active" /* ACTIVE */,
|
|
17930
|
+
isInstantWithdrawal: true,
|
|
17931
|
+
hideNetEarnings: true,
|
|
17932
|
+
isTransactionHistDisabled: true,
|
|
17933
|
+
quoteToken: Global.getDefaultTokens().find((t) => t.symbol === "STRK"),
|
|
17934
|
+
alerts: [
|
|
17935
|
+
{
|
|
17936
|
+
type: "info",
|
|
17937
|
+
text: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { children: [
|
|
17938
|
+
"Depending on the current position range and price, your input amounts are automatically adjusted to nearest required amounts. If you have insufficient tokens, you can acquire the required tokens on",
|
|
17939
|
+
" ",
|
|
17940
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
17941
|
+
"a",
|
|
17942
|
+
{
|
|
17943
|
+
href: "https://avnu.fi",
|
|
17944
|
+
target: "_blank",
|
|
17945
|
+
rel: "noopener noreferrer",
|
|
17946
|
+
children: "Avnu"
|
|
17947
|
+
}
|
|
17948
|
+
)
|
|
17949
|
+
] }),
|
|
17950
|
+
tab: "deposit"
|
|
17951
|
+
},
|
|
17952
|
+
{
|
|
17953
|
+
type: "info",
|
|
17954
|
+
text: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: "Depending on the current position range and price, you may receive both of the tokens or one of the tokens depending on the price" }),
|
|
17955
|
+
tab: "withdraw"
|
|
17956
|
+
}
|
|
17957
|
+
],
|
|
17958
|
+
tags: ["Ekubo" /* AUTOMATED_LP */]
|
|
17959
|
+
},
|
|
17693
17960
|
faqs: getLSTFAQs("xSTRK"),
|
|
17694
17961
|
points: [{
|
|
17695
17962
|
multiplier: 1,
|
|
@@ -17698,8 +17965,7 @@ var xSTRKSTRK = {
|
|
|
17698
17965
|
}],
|
|
17699
17966
|
contractDetails: [],
|
|
17700
17967
|
investmentSteps: [],
|
|
17701
|
-
|
|
17702
|
-
tags: ["Ekubo" /* EKUBO */],
|
|
17968
|
+
tags: ["Ekubo" /* AUTOMATED_LP */],
|
|
17703
17969
|
security: {
|
|
17704
17970
|
auditStatus: "Audited" /* AUDITED */,
|
|
17705
17971
|
sourceCode: {
|
|
@@ -17716,121 +17982,215 @@ var xSTRKSTRK = {
|
|
|
17716
17982
|
instantWithdrawalVault: "Yes" /* YES */
|
|
17717
17983
|
}
|
|
17718
17984
|
};
|
|
17985
|
+
var getLSTAlerts = () => [
|
|
17986
|
+
{
|
|
17987
|
+
tab: "deposit",
|
|
17988
|
+
text: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
17989
|
+
"To acquire the LST, please visit",
|
|
17990
|
+
" ",
|
|
17991
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
17992
|
+
"a",
|
|
17993
|
+
{
|
|
17994
|
+
href: "https://app.endur.fi",
|
|
17995
|
+
target: "_blank",
|
|
17996
|
+
rel: "noopener noreferrer",
|
|
17997
|
+
children: "endur.fi"
|
|
17998
|
+
}
|
|
17999
|
+
)
|
|
18000
|
+
] }),
|
|
18001
|
+
type: "info"
|
|
18002
|
+
},
|
|
18003
|
+
{
|
|
18004
|
+
type: "info",
|
|
18005
|
+
text: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { children: [
|
|
18006
|
+
"Depending on the current position range and price, your input amounts are automatically adjusted to nearest required amounts. If you have insufficient tokens, you can acquire the required tokens on",
|
|
18007
|
+
" ",
|
|
18008
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
18009
|
+
"a",
|
|
18010
|
+
{
|
|
18011
|
+
href: "https://avnu.fi",
|
|
18012
|
+
target: "_blank",
|
|
18013
|
+
rel: "noopener noreferrer",
|
|
18014
|
+
children: "Avnu"
|
|
18015
|
+
}
|
|
18016
|
+
)
|
|
18017
|
+
] }),
|
|
18018
|
+
tab: "deposit"
|
|
18019
|
+
},
|
|
18020
|
+
{
|
|
18021
|
+
type: "info",
|
|
18022
|
+
text: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: "Depending on the current position range and price, you may receive both of the tokens or one of the tokens depending on the price" }),
|
|
18023
|
+
tab: "withdraw"
|
|
18024
|
+
}
|
|
18025
|
+
];
|
|
18026
|
+
var createLSTSettings = (quoteTokenSymbol) => ({
|
|
18027
|
+
...xSTRKSTRK.settings,
|
|
18028
|
+
isAudited: true,
|
|
18029
|
+
liveStatus: "Active" /* ACTIVE */,
|
|
18030
|
+
isInstantWithdrawal: true,
|
|
18031
|
+
hideNetEarnings: true,
|
|
18032
|
+
isTransactionHistDisabled: true,
|
|
18033
|
+
quoteToken: Global.getDefaultTokens().find(
|
|
18034
|
+
(t) => t.symbol === quoteTokenSymbol
|
|
18035
|
+
),
|
|
18036
|
+
alerts: getLSTAlerts(),
|
|
18037
|
+
tags: ["Ekubo" /* AUTOMATED_LP */]
|
|
18038
|
+
});
|
|
18039
|
+
var createLSTStrategy = (params) => ({
|
|
18040
|
+
...xSTRKSTRK,
|
|
18041
|
+
id: params.id,
|
|
18042
|
+
name: params.name,
|
|
18043
|
+
description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
|
|
18044
|
+
// must be same order as poolKey token0 and token1
|
|
18045
|
+
address: ContractAddr.from(params.address),
|
|
18046
|
+
launchBlock: params.launchBlock,
|
|
18047
|
+
vaultType: {
|
|
18048
|
+
type: "farming" /* FARMING */,
|
|
18049
|
+
description: "this is a yield farming vault"
|
|
18050
|
+
},
|
|
18051
|
+
depositTokens: [
|
|
18052
|
+
Global.getDefaultTokens().find(
|
|
18053
|
+
(t) => t.symbol === params.depositToken0Symbol
|
|
18054
|
+
),
|
|
18055
|
+
Global.getDefaultTokens().find((t) => t.symbol === params.depositToken1Symbol)
|
|
18056
|
+
],
|
|
18057
|
+
additionalInfo: {
|
|
18058
|
+
...xSTRKSTRK.additionalInfo,
|
|
18059
|
+
quoteAsset: Global.getDefaultTokens().find(
|
|
18060
|
+
(t) => t.symbol === params.quoteTokenSymbol
|
|
18061
|
+
),
|
|
18062
|
+
lstContract: params.lstContractAddress ? ContractAddr.from(params.lstContractAddress) : Global.getDefaultTokens().find((t) => t.symbol === params.lstSymbol).address
|
|
18063
|
+
},
|
|
18064
|
+
settings: createLSTSettings(params.quoteTokenSymbol),
|
|
18065
|
+
faqs: getLSTFAQs(params.lstSymbol),
|
|
18066
|
+
points: [],
|
|
18067
|
+
contractDetails: [],
|
|
18068
|
+
investmentSteps: [],
|
|
18069
|
+
tags: params.id.toLowerCase().includes("btc") ? ["BTC" /* BTC */, "Ekubo" /* AUTOMATED_LP */] : ["Ekubo" /* AUTOMATED_LP */]
|
|
18070
|
+
});
|
|
17719
18071
|
var lstStrategies = [
|
|
17720
18072
|
xSTRKSTRK,
|
|
17721
|
-
{
|
|
17722
|
-
|
|
18073
|
+
createLSTStrategy({
|
|
18074
|
+
id: "ekubo_cl_xwbtcwbtc",
|
|
17723
18075
|
name: "Ekubo xWBTC/WBTC",
|
|
17724
|
-
|
|
17725
|
-
address: ContractAddr.from(
|
|
17726
|
-
"0x2ea99b4971d3c277fa4a9b4beb7d4d7d169e683393a29eef263d5d57b4380a"
|
|
17727
|
-
),
|
|
18076
|
+
address: "0x2ea99b4971d3c277fa4a9b4beb7d4d7d169e683393a29eef263d5d57b4380a",
|
|
17728
18077
|
launchBlock: 2338309,
|
|
17729
|
-
|
|
17730
|
-
|
|
17731
|
-
|
|
17732
|
-
|
|
17733
|
-
|
|
17734
|
-
|
|
17735
|
-
|
|
17736
|
-
quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "WBTC"),
|
|
17737
|
-
lstContract: Global.getDefaultTokens().find((t) => t.symbol === "xWBTC").address
|
|
17738
|
-
},
|
|
17739
|
-
faqs: getLSTFAQs("xWBTC"),
|
|
17740
|
-
points: [],
|
|
17741
|
-
contractDetails: [],
|
|
17742
|
-
investmentSteps: [],
|
|
17743
|
-
category: "btc" /* BTC */,
|
|
17744
|
-
tags: ["Ekubo" /* EKUBO */]
|
|
17745
|
-
},
|
|
17746
|
-
{
|
|
17747
|
-
...xSTRKSTRK,
|
|
18078
|
+
depositToken0Symbol: "WBTC",
|
|
18079
|
+
depositToken1Symbol: "xWBTC",
|
|
18080
|
+
quoteTokenSymbol: "WBTC",
|
|
18081
|
+
lstSymbol: "xWBTC"
|
|
18082
|
+
}),
|
|
18083
|
+
createLSTStrategy({
|
|
18084
|
+
id: "ekubo_cl_xtbtctbtc",
|
|
17748
18085
|
name: "Ekubo xtBTC/tBTC",
|
|
17749
|
-
|
|
17750
|
-
address: ContractAddr.from(
|
|
17751
|
-
"0x785dc3dfc4e80ef2690a99512481e3ed3a5266180adda5a47e856245d68a4af"
|
|
17752
|
-
),
|
|
18086
|
+
address: "0x785dc3dfc4e80ef2690a99512481e3ed3a5266180adda5a47e856245d68a4af",
|
|
17753
18087
|
launchBlock: 2415667,
|
|
17754
|
-
|
|
17755
|
-
|
|
17756
|
-
|
|
17757
|
-
|
|
17758
|
-
|
|
17759
|
-
|
|
17760
|
-
|
|
17761
|
-
quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "tBTC"),
|
|
17762
|
-
lstContract: Global.getDefaultTokens().find((t) => t.symbol === "xtBTC").address
|
|
17763
|
-
},
|
|
17764
|
-
faqs: getLSTFAQs("xtBTC"),
|
|
17765
|
-
points: [],
|
|
17766
|
-
contractDetails: [],
|
|
17767
|
-
investmentSteps: [],
|
|
17768
|
-
category: "btc" /* BTC */,
|
|
17769
|
-
tags: ["Ekubo" /* EKUBO */]
|
|
17770
|
-
},
|
|
17771
|
-
{
|
|
17772
|
-
...xSTRKSTRK,
|
|
18088
|
+
depositToken0Symbol: "xtBTC",
|
|
18089
|
+
depositToken1Symbol: "tBTC",
|
|
18090
|
+
quoteTokenSymbol: "tBTC",
|
|
18091
|
+
lstSymbol: "xtBTC"
|
|
18092
|
+
}),
|
|
18093
|
+
createLSTStrategy({
|
|
18094
|
+
id: "ekubo_cl_xsbtcsolvbtc",
|
|
17773
18095
|
name: "Ekubo xsBTC/solvBTC",
|
|
17774
|
-
|
|
17775
|
-
address: ContractAddr.from(
|
|
17776
|
-
"0x3af1c7faa7c464cf2c494e988972ad1939f1103dbfb6e47e9bf0c47e49b14ef"
|
|
17777
|
-
),
|
|
18096
|
+
address: "0x3af1c7faa7c464cf2c494e988972ad1939f1103dbfb6e47e9bf0c47e49b14ef",
|
|
17778
18097
|
launchBlock: 2344809,
|
|
17779
|
-
|
|
17780
|
-
|
|
17781
|
-
|
|
17782
|
-
|
|
17783
|
-
|
|
17784
|
-
|
|
17785
|
-
|
|
17786
|
-
quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "solvBTC"),
|
|
17787
|
-
lstContract: Global.getDefaultTokens().find((t) => t.symbol === "xsBTC").address
|
|
17788
|
-
},
|
|
17789
|
-
faqs: getLSTFAQs("xsBTC"),
|
|
17790
|
-
points: [],
|
|
17791
|
-
contractDetails: [],
|
|
17792
|
-
investmentSteps: [],
|
|
17793
|
-
category: "btc" /* BTC */,
|
|
17794
|
-
tags: ["Ekubo" /* EKUBO */]
|
|
17795
|
-
},
|
|
17796
|
-
{
|
|
17797
|
-
...xSTRKSTRK,
|
|
18098
|
+
depositToken0Symbol: "xsBTC",
|
|
18099
|
+
depositToken1Symbol: "solvBTC",
|
|
18100
|
+
quoteTokenSymbol: "solvBTC",
|
|
18101
|
+
lstSymbol: "xsBTC"
|
|
18102
|
+
}),
|
|
18103
|
+
createLSTStrategy({
|
|
18104
|
+
id: "ekubo_cl_xlbtclbtc",
|
|
17798
18105
|
name: "Ekubo xLBTC/LBTC",
|
|
17799
|
-
|
|
17800
|
-
address: ContractAddr.from(
|
|
17801
|
-
"0x314c4653ab1aa01f5465773cb879f525d7e369a137bc3ae084761aee99a1712"
|
|
17802
|
-
),
|
|
18106
|
+
address: "0x314c4653ab1aa01f5465773cb879f525d7e369a137bc3ae084761aee99a1712",
|
|
17803
18107
|
launchBlock: 2412442,
|
|
17804
|
-
|
|
17805
|
-
|
|
17806
|
-
|
|
17807
|
-
|
|
17808
|
-
|
|
17809
|
-
|
|
17810
|
-
|
|
17811
|
-
|
|
17812
|
-
|
|
17813
|
-
|
|
17814
|
-
|
|
17815
|
-
|
|
17816
|
-
|
|
17817
|
-
|
|
17818
|
-
|
|
17819
|
-
|
|
18108
|
+
depositToken0Symbol: "LBTC",
|
|
18109
|
+
depositToken1Symbol: "xLBTC",
|
|
18110
|
+
quoteTokenSymbol: "LBTC",
|
|
18111
|
+
lstSymbol: "xLBTC"
|
|
18112
|
+
})
|
|
18113
|
+
];
|
|
18114
|
+
var getRe7Alerts = () => [
|
|
18115
|
+
{
|
|
18116
|
+
type: "info",
|
|
18117
|
+
text: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { children: [
|
|
18118
|
+
"Depending on the current position range and price, your input amounts are automatically adjusted to nearest required amounts. If you have insufficient tokens, you can acquire the required tokens on",
|
|
18119
|
+
" ",
|
|
18120
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
18121
|
+
"a",
|
|
18122
|
+
{
|
|
18123
|
+
href: "https://avnu.fi",
|
|
18124
|
+
target: "_blank",
|
|
18125
|
+
rel: "noopener noreferrer",
|
|
18126
|
+
children: "Avnu"
|
|
18127
|
+
}
|
|
18128
|
+
)
|
|
18129
|
+
] }),
|
|
18130
|
+
tab: "deposit"
|
|
18131
|
+
},
|
|
18132
|
+
{
|
|
18133
|
+
type: "info",
|
|
18134
|
+
text: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: "Depending on the current position range and price, you may receive both of the tokens or one of the tokens depending on the price" }),
|
|
18135
|
+
tab: "withdraw"
|
|
18136
|
+
}
|
|
18137
|
+
];
|
|
18138
|
+
var createRe7Settings = (quoteTokenSymbol, isBTC, isDeprecated) => ({
|
|
18139
|
+
...xSTRKSTRK.settings,
|
|
18140
|
+
isAudited: true,
|
|
18141
|
+
liveStatus: isDeprecated ? "Deprecated" /* DEPRECATED */ : "Active" /* ACTIVE */,
|
|
18142
|
+
isInstantWithdrawal: true,
|
|
18143
|
+
hideNetEarnings: true,
|
|
18144
|
+
isTransactionHistDisabled: false,
|
|
18145
|
+
quoteToken: Global.getDefaultTokens().find(
|
|
18146
|
+
(t) => t.symbol === quoteTokenSymbol
|
|
18147
|
+
),
|
|
18148
|
+
alerts: getRe7Alerts(),
|
|
18149
|
+
tags: isBTC ? ["BTC" /* BTC */, "Ekubo" /* AUTOMATED_LP */] : ["Ekubo" /* AUTOMATED_LP */]
|
|
18150
|
+
});
|
|
18151
|
+
var getRe7FAQs = () => [
|
|
18152
|
+
...faqs2,
|
|
18153
|
+
{
|
|
18154
|
+
question: "Who is the curator of this strategy?",
|
|
18155
|
+
answer: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
18156
|
+
"Re7 Labs is the curator of this strategy. Re7 Labs is a well-known Web3 asset management firm. This strategy is completely managed by them, including ownership of the vault. Troves is developer of the smart contracts and maintains infrastructure to help users access these strategies. You can find more information about them on their website",
|
|
18157
|
+
" ",
|
|
18158
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
18159
|
+
"a",
|
|
18160
|
+
{
|
|
18161
|
+
href: "https://www.re7labs.xyz",
|
|
18162
|
+
style: {
|
|
18163
|
+
textDecoration: "underline",
|
|
18164
|
+
marginLeft: "2px"
|
|
18165
|
+
},
|
|
18166
|
+
target: "_blank",
|
|
18167
|
+
children: "here"
|
|
18168
|
+
}
|
|
18169
|
+
),
|
|
18170
|
+
"."
|
|
18171
|
+
] })
|
|
18172
|
+
},
|
|
18173
|
+
{
|
|
18174
|
+
question: "How is the APY calculated?",
|
|
18175
|
+
answer: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: "It's an annualized fee APY, calculated as fees earned in the last 24h divided by TVL. Factors like impermanent loss are not considered." })
|
|
17820
18176
|
}
|
|
17821
18177
|
];
|
|
17822
|
-
var
|
|
18178
|
+
var createRe7Strategy = (id, name, address, launchBlock, depositToken0Symbol, depositToken1Symbol, quoteTokenSymbol, risk, isBTC) => ({
|
|
17823
18179
|
...xSTRKSTRK,
|
|
17824
|
-
|
|
18180
|
+
id,
|
|
18181
|
+
name,
|
|
17825
18182
|
description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
|
|
17826
|
-
address: ContractAddr.from(
|
|
17827
|
-
|
|
17828
|
-
|
|
17829
|
-
|
|
17830
|
-
|
|
18183
|
+
address: ContractAddr.from(address),
|
|
18184
|
+
launchBlock,
|
|
18185
|
+
vaultType: {
|
|
18186
|
+
type: "farming" /* FARMING */,
|
|
18187
|
+
description: "this is a yield farming vault"
|
|
18188
|
+
},
|
|
17831
18189
|
depositTokens: [
|
|
17832
|
-
Global.getDefaultTokens().find(
|
|
17833
|
-
|
|
18190
|
+
Global.getDefaultTokens().find(
|
|
18191
|
+
(t) => t.symbol === depositToken0Symbol
|
|
18192
|
+
),
|
|
18193
|
+
Global.getDefaultTokens().find((t) => t.symbol === depositToken1Symbol)
|
|
17834
18194
|
],
|
|
17835
18195
|
apyMethodology: "Annualized fee APY, calculated as fees earned in the last 7d divided by TVL",
|
|
17836
18196
|
additionalInfo: {
|
|
@@ -17842,154 +18202,169 @@ var ETHUSDCRe7Strategy = {
|
|
|
17842
18202
|
minWaitHours: 6,
|
|
17843
18203
|
direction: "any"
|
|
17844
18204
|
},
|
|
17845
|
-
quoteAsset: Global.getDefaultTokens().find(
|
|
18205
|
+
quoteAsset: Global.getDefaultTokens().find(
|
|
18206
|
+
(t) => t.symbol === quoteTokenSymbol
|
|
18207
|
+
)
|
|
17846
18208
|
},
|
|
17847
|
-
|
|
17848
|
-
|
|
17849
|
-
|
|
17850
|
-
question: "Who is the curator of this strategy?",
|
|
17851
|
-
answer: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
17852
|
-
"Re7 Labs is the curator of this strategy. Re7 Labs is a well-known Web3 asset management firm. This strategy is completely managed by them, including ownership of the vault. Troves is developer of the smart contracts and maintains infrastructure to help users access these strategies. You can find more information about them on their website ",
|
|
17853
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href: "https://www.re7labs.xyz", style: { textDecoration: "underline", marginLeft: "2px" }, target: "_blank", children: "here" }),
|
|
17854
|
-
"."
|
|
17855
|
-
] })
|
|
17856
|
-
},
|
|
17857
|
-
{
|
|
17858
|
-
question: "How is the APY calculated?",
|
|
17859
|
-
answer: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: "It's an annualized fee APY, calculated as fees earned in the last 24h divided by TVL. Factors like impermanent loss are not considered." })
|
|
17860
|
-
}
|
|
17861
|
-
],
|
|
17862
|
-
risk: highRisk,
|
|
18209
|
+
settings: createRe7Settings(quoteTokenSymbol, isBTC, name.toLowerCase().includes("usdc.e")),
|
|
18210
|
+
faqs: getRe7FAQs(),
|
|
18211
|
+
risk,
|
|
17863
18212
|
points: [],
|
|
17864
18213
|
curator: { name: "Re7 Labs", logo: "https://www.re7labs.xyz/favicon.ico" },
|
|
17865
|
-
|
|
17866
|
-
|
|
18214
|
+
tags: isBTC ? ["BTC" /* BTC */, "Ekubo" /* AUTOMATED_LP */] : ["Ekubo" /* AUTOMATED_LP */]
|
|
18215
|
+
});
|
|
18216
|
+
var ETHUSDCRe7Strategy = createRe7Strategy(
|
|
18217
|
+
"ekubo_cl_ethusdc",
|
|
18218
|
+
"Ekubo ETH/USDC.e",
|
|
18219
|
+
"0x160d8fa4569ef6a12e6bf47cb943d7b5ebba8a41a69a14c1d943050ba5ff947",
|
|
18220
|
+
1504232,
|
|
18221
|
+
"ETH",
|
|
18222
|
+
"USDC.e",
|
|
18223
|
+
"USDC.e",
|
|
18224
|
+
highRisk,
|
|
18225
|
+
false
|
|
18226
|
+
// isBTC
|
|
18227
|
+
);
|
|
18228
|
+
var stableCoinRisk = {
|
|
18229
|
+
riskFactor: _stableCoinPoolRiskFactors,
|
|
18230
|
+
netRisk: _stableCoinPoolRiskFactors.reduce(
|
|
18231
|
+
(acc, curr) => acc + curr.value * curr.weight,
|
|
18232
|
+
0
|
|
18233
|
+
) / _stableCoinPoolRiskFactors.reduce((acc, curr) => acc + curr.weight, 0),
|
|
18234
|
+
notARisks: getNoRiskTags(_stableCoinPoolRiskFactors)
|
|
17867
18235
|
};
|
|
17868
18236
|
var RE7Strategies = [
|
|
17869
18237
|
ETHUSDCRe7Strategy,
|
|
17870
|
-
|
|
17871
|
-
|
|
17872
|
-
|
|
17873
|
-
|
|
17874
|
-
|
|
17875
|
-
|
|
17876
|
-
|
|
17877
|
-
|
|
17878
|
-
|
|
17879
|
-
|
|
17880
|
-
|
|
17881
|
-
|
|
17882
|
-
|
|
17883
|
-
|
|
17884
|
-
|
|
17885
|
-
|
|
17886
|
-
|
|
17887
|
-
|
|
17888
|
-
|
|
17889
|
-
|
|
17890
|
-
|
|
17891
|
-
|
|
17892
|
-
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
|
|
17899
|
-
|
|
17900
|
-
|
|
17901
|
-
|
|
17902
|
-
|
|
17903
|
-
|
|
17904
|
-
|
|
17905
|
-
|
|
17906
|
-
|
|
17907
|
-
|
|
17908
|
-
|
|
17909
|
-
|
|
17910
|
-
|
|
17911
|
-
|
|
17912
|
-
|
|
17913
|
-
|
|
17914
|
-
|
|
17915
|
-
|
|
17916
|
-
//
|
|
17917
|
-
|
|
17918
|
-
|
|
17919
|
-
|
|
17920
|
-
|
|
17921
|
-
|
|
17922
|
-
|
|
17923
|
-
|
|
17924
|
-
|
|
17925
|
-
|
|
17926
|
-
|
|
17927
|
-
|
|
17928
|
-
|
|
17929
|
-
|
|
17930
|
-
|
|
17931
|
-
|
|
17932
|
-
|
|
17933
|
-
|
|
17934
|
-
|
|
17935
|
-
|
|
17936
|
-
|
|
17937
|
-
|
|
17938
|
-
|
|
17939
|
-
|
|
17940
|
-
|
|
17941
|
-
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
|
|
17947
|
-
|
|
17948
|
-
|
|
17949
|
-
|
|
17950
|
-
//
|
|
17951
|
-
|
|
17952
|
-
|
|
17953
|
-
|
|
17954
|
-
|
|
17955
|
-
|
|
17956
|
-
|
|
17957
|
-
|
|
17958
|
-
|
|
17959
|
-
|
|
17960
|
-
|
|
17961
|
-
|
|
17962
|
-
|
|
17963
|
-
|
|
17964
|
-
|
|
17965
|
-
|
|
17966
|
-
|
|
17967
|
-
|
|
17968
|
-
|
|
17969
|
-
|
|
17970
|
-
|
|
17971
|
-
|
|
17972
|
-
|
|
17973
|
-
|
|
17974
|
-
|
|
17975
|
-
|
|
17976
|
-
|
|
17977
|
-
|
|
17978
|
-
|
|
17979
|
-
|
|
17980
|
-
|
|
17981
|
-
|
|
17982
|
-
|
|
17983
|
-
|
|
17984
|
-
|
|
17985
|
-
|
|
17986
|
-
|
|
17987
|
-
|
|
17988
|
-
|
|
17989
|
-
|
|
17990
|
-
|
|
17991
|
-
|
|
17992
|
-
|
|
18238
|
+
createRe7Strategy(
|
|
18239
|
+
"ekubo_cl_usdcusdt",
|
|
18240
|
+
"Ekubo USDC.e/USDT",
|
|
18241
|
+
"0x3a4f8debaf12af97bb911099bc011d63d6c208d4c5ba8e15d7f437785b0aaa2",
|
|
18242
|
+
1506139,
|
|
18243
|
+
"USDC.e",
|
|
18244
|
+
"USDT",
|
|
18245
|
+
"USDC.e",
|
|
18246
|
+
stableCoinRisk,
|
|
18247
|
+
false
|
|
18248
|
+
// isBTC
|
|
18249
|
+
),
|
|
18250
|
+
createRe7Strategy(
|
|
18251
|
+
"ekubo_cl_strkusdc",
|
|
18252
|
+
"Ekubo STRK/USDC.e",
|
|
18253
|
+
"0x351b36d0d9d8b40010658825adeeddb1397436cd41acd0ff6c6e23aaa8b5b30",
|
|
18254
|
+
1504079,
|
|
18255
|
+
"STRK",
|
|
18256
|
+
"USDC.e",
|
|
18257
|
+
"USDC.e",
|
|
18258
|
+
highRisk,
|
|
18259
|
+
false
|
|
18260
|
+
// isBTC
|
|
18261
|
+
),
|
|
18262
|
+
createRe7Strategy(
|
|
18263
|
+
"ekubo_cl_strketh",
|
|
18264
|
+
"Ekubo STRK/ETH",
|
|
18265
|
+
"0x4ce3024b0ee879009112d7b0e073f8a87153dd35b029347d4247ffe48d28f51",
|
|
18266
|
+
1504149,
|
|
18267
|
+
"STRK",
|
|
18268
|
+
"ETH",
|
|
18269
|
+
"USDC",
|
|
18270
|
+
highRisk,
|
|
18271
|
+
false
|
|
18272
|
+
// isBTC
|
|
18273
|
+
),
|
|
18274
|
+
createRe7Strategy(
|
|
18275
|
+
"ekubo_cl_wbtcusdc",
|
|
18276
|
+
"Ekubo WBTC/USDC.e",
|
|
18277
|
+
"0x2bcaef2eb7706875a5fdc6853dd961a0590f850bc3a031c59887189b5e84ba1",
|
|
18278
|
+
1506144,
|
|
18279
|
+
"WBTC",
|
|
18280
|
+
"USDC.e",
|
|
18281
|
+
"USDC.e",
|
|
18282
|
+
mediumRisk,
|
|
18283
|
+
true
|
|
18284
|
+
// isBTC
|
|
18285
|
+
),
|
|
18286
|
+
// createRe7Strategy(
|
|
18287
|
+
// "ekubo_cl_tbtcusdce",
|
|
18288
|
+
// "Ekubo tBTC/USDC.e",
|
|
18289
|
+
// "0x4aad891a2d4432fba06b6558631bb13f6bbd7f6f33ab8c3111e344889ea4456",
|
|
18290
|
+
// 1501764,
|
|
18291
|
+
// "tBTC",
|
|
18292
|
+
// "USDC.e",
|
|
18293
|
+
// "USDC.e",
|
|
18294
|
+
// mediumRisk,
|
|
18295
|
+
// ),
|
|
18296
|
+
createRe7Strategy(
|
|
18297
|
+
"ekubo_cl_wbtceth",
|
|
18298
|
+
"Ekubo WBTC/ETH",
|
|
18299
|
+
"0x1c9232b8186d9317652f05055615f18a120c2ad9e5ee96c39e031c257fb945b",
|
|
18300
|
+
1506145,
|
|
18301
|
+
"WBTC",
|
|
18302
|
+
"ETH",
|
|
18303
|
+
"USDC",
|
|
18304
|
+
mediumRisk,
|
|
18305
|
+
true
|
|
18306
|
+
// isBTC
|
|
18307
|
+
),
|
|
18308
|
+
createRe7Strategy(
|
|
18309
|
+
"ekubo_cl_wbtcstrk",
|
|
18310
|
+
"Ekubo WBTC/STRK",
|
|
18311
|
+
"0x1248e385c23a929a015ec298a26560fa7745bbd6e41a886550e337b02714b1b",
|
|
18312
|
+
1506147,
|
|
18313
|
+
"WBTC",
|
|
18314
|
+
"STRK",
|
|
18315
|
+
"USDC",
|
|
18316
|
+
highRisk,
|
|
18317
|
+
true
|
|
18318
|
+
// isBTC
|
|
18319
|
+
),
|
|
18320
|
+
createRe7Strategy(
|
|
18321
|
+
"ekubo_cl_usdc_v2usdt",
|
|
18322
|
+
"Ekubo USDC/USDT",
|
|
18323
|
+
"0x5203a08b471e46bf33990ac83aff577bbe5a5d789e61de2c6531e3c4773d1c9",
|
|
18324
|
+
3998018,
|
|
18325
|
+
"USDC",
|
|
18326
|
+
"USDT",
|
|
18327
|
+
"USDC",
|
|
18328
|
+
stableCoinRisk,
|
|
18329
|
+
false
|
|
18330
|
+
// isBTC
|
|
18331
|
+
),
|
|
18332
|
+
createRe7Strategy(
|
|
18333
|
+
"ekubo_cl_ethusdc_v2",
|
|
18334
|
+
"Ekubo ETH/USDC",
|
|
18335
|
+
"0x4d00c7423b3c0fae3640f6099ac97acbfd8708f099e09bfe3a7a6a680399228",
|
|
18336
|
+
3998025,
|
|
18337
|
+
"USDC",
|
|
18338
|
+
"ETH",
|
|
18339
|
+
"USDC",
|
|
18340
|
+
highRisk,
|
|
18341
|
+
false
|
|
18342
|
+
// isBTC
|
|
18343
|
+
),
|
|
18344
|
+
createRe7Strategy(
|
|
18345
|
+
"ekubo_cl_strkusdc_v2",
|
|
18346
|
+
"Ekubo STRK/USDC",
|
|
18347
|
+
"0x4de22bd0a8eb4d0a18736e66dd36d20ba50bc106346bbfac3dbeaac1ab37ce1",
|
|
18348
|
+
3998030,
|
|
18349
|
+
"USDC",
|
|
18350
|
+
"STRK",
|
|
18351
|
+
"USDC",
|
|
18352
|
+
highRisk,
|
|
18353
|
+
false
|
|
18354
|
+
// isBTC
|
|
18355
|
+
),
|
|
18356
|
+
createRe7Strategy(
|
|
18357
|
+
"ekubo_cl_wbtcusdc_v2",
|
|
18358
|
+
"Ekubo WBTC/USDC",
|
|
18359
|
+
"0x76101c3b80af1103c9c6d541ca627f61b5ae7ae79d7fce96ccdf7bdb648450d",
|
|
18360
|
+
3998034,
|
|
18361
|
+
"USDC",
|
|
18362
|
+
"WBTC",
|
|
18363
|
+
"USDC",
|
|
18364
|
+
mediumRisk,
|
|
18365
|
+
true
|
|
18366
|
+
// isBTC
|
|
18367
|
+
)
|
|
17993
18368
|
];
|
|
17994
18369
|
var EkuboCLVaultStrategies = [
|
|
17995
18370
|
...lstStrategies,
|
|
@@ -18039,7 +18414,7 @@ EkuboCLVaultStrategies.forEach((s) => {
|
|
|
18039
18414
|
});
|
|
18040
18415
|
|
|
18041
18416
|
// src/strategies/sensei.ts
|
|
18042
|
-
var
|
|
18417
|
+
var import_starknet15 = require("starknet");
|
|
18043
18418
|
|
|
18044
18419
|
// src/data/sensei.abi.json
|
|
18045
18420
|
var sensei_abi_default = [
|
|
@@ -19802,311 +20177,7 @@ var sensei_abi_default = [
|
|
|
19802
20177
|
}
|
|
19803
20178
|
];
|
|
19804
20179
|
|
|
19805
|
-
// src/strategies/
|
|
19806
|
-
var SenseiVault = class extends BaseStrategy {
|
|
19807
|
-
constructor(config, pricer, metadata) {
|
|
19808
|
-
super(config);
|
|
19809
|
-
this.getSettings = async () => {
|
|
19810
|
-
const settings = await this.contract.call("get_settings", []);
|
|
19811
|
-
logger.verbose("getSettings", settings);
|
|
19812
|
-
return settings;
|
|
19813
|
-
};
|
|
19814
|
-
this.address = metadata.address;
|
|
19815
|
-
this.pricer = pricer;
|
|
19816
|
-
this.metadata = metadata;
|
|
19817
|
-
this.contract = new import_starknet13.Contract({ abi: sensei_abi_default, address: this.address.address, providerOrAccount: this.config.provider });
|
|
19818
|
-
if (metadata.depositTokens.length === 0) {
|
|
19819
|
-
throw new Error("Deposit tokens are not defined in metadata");
|
|
19820
|
-
}
|
|
19821
|
-
}
|
|
19822
|
-
async getUserTVL(user, blockIdentifier = "latest") {
|
|
19823
|
-
const result = await this.contract.call(
|
|
19824
|
-
"describe_position",
|
|
19825
|
-
[user.address],
|
|
19826
|
-
{
|
|
19827
|
-
blockIdentifier
|
|
19828
|
-
}
|
|
19829
|
-
);
|
|
19830
|
-
const amount = Web3Number.fromWei(
|
|
19831
|
-
import_starknet13.uint256.uint256ToBN(result[1].estimated_size).toString(),
|
|
19832
|
-
this.metadata.depositTokens[0].decimals
|
|
19833
|
-
);
|
|
19834
|
-
const blockNumber = typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint" ? Number(blockIdentifier) : void 0;
|
|
19835
|
-
const price = await this.pricer.getPrice(
|
|
19836
|
-
this.metadata.depositTokens[0].symbol,
|
|
19837
|
-
blockNumber
|
|
19838
|
-
);
|
|
19839
|
-
return {
|
|
19840
|
-
usdValue: Number(amount.toFixed(6)) * price.price,
|
|
19841
|
-
amount,
|
|
19842
|
-
tokenInfo: this.metadata.depositTokens[0]
|
|
19843
|
-
};
|
|
19844
|
-
}
|
|
19845
|
-
async getTVL() {
|
|
19846
|
-
try {
|
|
19847
|
-
const {
|
|
19848
|
-
collateralXSTRK,
|
|
19849
|
-
collateralUSDValue,
|
|
19850
|
-
debtSTRK,
|
|
19851
|
-
debtUSDValue,
|
|
19852
|
-
xSTRKPrice,
|
|
19853
|
-
collateralInSTRK
|
|
19854
|
-
} = await this.getPositionInfo();
|
|
19855
|
-
const usdValue = Number(collateralUSDValue.toFixed(6)) - Number(debtUSDValue.toFixed(6));
|
|
19856
|
-
return {
|
|
19857
|
-
usdValue,
|
|
19858
|
-
amount: new Web3Number(
|
|
19859
|
-
(collateralInSTRK - Number(debtSTRK.toFixed(6))).toFixed(6),
|
|
19860
|
-
collateralXSTRK.decimals
|
|
19861
|
-
),
|
|
19862
|
-
tokenInfo: this.metadata.depositTokens[0]
|
|
19863
|
-
};
|
|
19864
|
-
} catch (error) {
|
|
19865
|
-
console.error("Error fetching TVL:", error);
|
|
19866
|
-
return {
|
|
19867
|
-
usdValue: 0,
|
|
19868
|
-
amount: new Web3Number("0", this.metadata.depositTokens[0].decimals),
|
|
19869
|
-
tokenInfo: this.metadata.depositTokens[0]
|
|
19870
|
-
};
|
|
19871
|
-
}
|
|
19872
|
-
}
|
|
19873
|
-
async depositCall(amountInfo, receiver) {
|
|
19874
|
-
const mainTokenContract = new import_starknet13.Contract({
|
|
19875
|
-
abi: erc20_abi_default,
|
|
19876
|
-
address: this.metadata.depositTokens[0].address.address,
|
|
19877
|
-
providerOrAccount: this.config.provider
|
|
19878
|
-
});
|
|
19879
|
-
const call1 = mainTokenContract.populate("approve", [
|
|
19880
|
-
this.address.address,
|
|
19881
|
-
import_starknet13.uint256.bnToUint256(amountInfo.amount.toWei())
|
|
19882
|
-
]);
|
|
19883
|
-
const call2 = this.contract.populate("deposit", [
|
|
19884
|
-
import_starknet13.uint256.bnToUint256(amountInfo.amount.toWei()),
|
|
19885
|
-
receiver.address
|
|
19886
|
-
]);
|
|
19887
|
-
const calls = [call1, call2];
|
|
19888
|
-
return calls;
|
|
19889
|
-
}
|
|
19890
|
-
async withdrawCall(amountInfo, receiver, owner) {
|
|
19891
|
-
const call = this.contract.populate("withdraw", [
|
|
19892
|
-
import_starknet13.uint256.bnToUint256(amountInfo.amount.toWei()),
|
|
19893
|
-
receiver.address,
|
|
19894
|
-
300
|
|
19895
|
-
// 3% max slippage
|
|
19896
|
-
]);
|
|
19897
|
-
return [call];
|
|
19898
|
-
}
|
|
19899
|
-
async getPositionInfo() {
|
|
19900
|
-
const CACHE_KEY = "positionInfo";
|
|
19901
|
-
const existingCacheData = this.getCache(CACHE_KEY);
|
|
19902
|
-
if (existingCacheData) return existingCacheData;
|
|
19903
|
-
const resp = await fetch(
|
|
19904
|
-
`${getTrovesEndpoint()}/vesu/positions?walletAddress=${this.address.address}`
|
|
19905
|
-
);
|
|
19906
|
-
const data = await resp.json();
|
|
19907
|
-
if (!data.data || data.data.length == 0) {
|
|
19908
|
-
throw new Error("No positions found");
|
|
19909
|
-
}
|
|
19910
|
-
const collateralXSTRK = Web3Number.fromWei(
|
|
19911
|
-
data.data[0].collateral.value,
|
|
19912
|
-
data.data[0].collateral.decimals
|
|
19913
|
-
);
|
|
19914
|
-
const collateralUSDValue = Web3Number.fromWei(
|
|
19915
|
-
data.data[0].collateral.usdPrice.value,
|
|
19916
|
-
data.data[0].collateral.usdPrice.decimals
|
|
19917
|
-
);
|
|
19918
|
-
const debtSTRK = Web3Number.fromWei(
|
|
19919
|
-
data.data[0].debt.value,
|
|
19920
|
-
data.data[0].debt.decimals
|
|
19921
|
-
);
|
|
19922
|
-
const debtUSDValue = Web3Number.fromWei(
|
|
19923
|
-
data.data[0].debt.usdPrice.value,
|
|
19924
|
-
data.data[0].debt.usdPrice.decimals
|
|
19925
|
-
);
|
|
19926
|
-
const xSTRKPrice = await this.getSecondaryTokenPriceRelativeToMain();
|
|
19927
|
-
const collateralInSTRK = Number(collateralXSTRK.toFixed(6)) * xSTRKPrice;
|
|
19928
|
-
const STRKUSDPrice = Number(debtUSDValue.toFixed(6)) / Number(debtSTRK.toFixed(6));
|
|
19929
|
-
const actualCollateralUSDValue = collateralInSTRK * STRKUSDPrice;
|
|
19930
|
-
const cacheData = {
|
|
19931
|
-
collateralXSTRK,
|
|
19932
|
-
collateralUSDValue: new Web3Number(
|
|
19933
|
-
actualCollateralUSDValue.toFixed(6),
|
|
19934
|
-
collateralUSDValue.decimals
|
|
19935
|
-
),
|
|
19936
|
-
debtSTRK,
|
|
19937
|
-
debtUSDValue,
|
|
19938
|
-
xSTRKPrice,
|
|
19939
|
-
collateralInSTRK
|
|
19940
|
-
};
|
|
19941
|
-
this.setCache(CACHE_KEY, cacheData);
|
|
19942
|
-
return cacheData;
|
|
19943
|
-
}
|
|
19944
|
-
async getSecondaryTokenPriceRelativeToMain(retry = 0) {
|
|
19945
|
-
const CACHE_KEY = "xSTRKPrice";
|
|
19946
|
-
const existingCacheData = this.getCache(CACHE_KEY);
|
|
19947
|
-
if (existingCacheData) return existingCacheData;
|
|
19948
|
-
const params = {
|
|
19949
|
-
sellTokenAddress: this.metadata.additionalInfo.secondaryToken.address.address,
|
|
19950
|
-
buyTokenAddress: this.metadata.additionalInfo.mainToken.address.address,
|
|
19951
|
-
sellAmount: BigInt(new Web3Number("1", 18).toWei()),
|
|
19952
|
-
takerAddress: this.address.address
|
|
19953
|
-
};
|
|
19954
|
-
logger.verbose("getSecondaryTokenPriceRelativeToMain [1]", params);
|
|
19955
|
-
let avnu = new AvnuWrapper();
|
|
19956
|
-
const quote = await avnu.getQuotes(
|
|
19957
|
-
params.sellTokenAddress,
|
|
19958
|
-
params.buyTokenAddress,
|
|
19959
|
-
params.sellAmount?.toString() || "0",
|
|
19960
|
-
params.takerAddress
|
|
19961
|
-
);
|
|
19962
|
-
if (!quote) {
|
|
19963
|
-
throw new Error("No quotes found to compute secondary token price relative to main token");
|
|
19964
|
-
}
|
|
19965
|
-
const firstQuote = quote;
|
|
19966
|
-
const price = Number(
|
|
19967
|
-
Web3Number.fromWei(firstQuote.buyAmount.toString(), 18).toFixed(
|
|
19968
|
-
6
|
|
19969
|
-
)
|
|
19970
|
-
);
|
|
19971
|
-
logger.verbose("getSecondaryTokenPriceRelativeToMain [2]", price);
|
|
19972
|
-
this.setCache(CACHE_KEY, price);
|
|
19973
|
-
return price;
|
|
19974
|
-
}
|
|
19975
|
-
/**
|
|
19976
|
-
* Calculates user realized APY based on position growth accounting for deposits and withdrawals.
|
|
19977
|
-
* Returns the APY as a number.
|
|
19978
|
-
*/
|
|
19979
|
-
async getUserRealizedAPY(userAddress, blockIdentifier = "latest", sinceBlocks = 6e5) {
|
|
19980
|
-
throw new Error("getUserRealizedAPY not implemented yet for Sensei strategy");
|
|
19981
|
-
}
|
|
19982
|
-
};
|
|
19983
|
-
var senseiDescription = `Deposit your {{token1}} to automatically loop your funds via Endur ({{token2}}) and Vesu to create a delta neutral position. This strategy is designed to maximize your yield on {{token1}}. Your position is automatically adjusted periodically to maintain a healthy health factor. You receive a NFT as representation for your stake on Troves. You can withdraw anytime by redeeming your NFT for {{token1}}.`;
|
|
19984
|
-
var vesuProtocol = {
|
|
19985
|
-
name: "Vesu",
|
|
19986
|
-
logo: "https://static-assets-8zct.onrender.com/integrations/vesu/logo.png"
|
|
19987
|
-
};
|
|
19988
|
-
var endurProtocol = {
|
|
19989
|
-
name: "Endur",
|
|
19990
|
-
logo: "https://app.endur.fi/logo.png"
|
|
19991
|
-
};
|
|
19992
|
-
var _riskFactor2 = [
|
|
19993
|
-
{ type: "Smart Contract Risk" /* SMART_CONTRACT_RISK */, value: 0.5, weight: 25, reason: "Audited by CSC" },
|
|
19994
|
-
{ type: "Depeg Risk" /* DEPEG_RISK */, value: 0.25, weight: 25, reason: "Depending on prevailing market conditions and trading activity, xSTRK may lose its peg to the underlying asset." },
|
|
19995
|
-
{ type: "Liquidation Risk" /* LIQUIDATION_RISK */, value: 0.1, weight: 10, reason: "Liquidation risk is low due to the nature of the Re7 Pool on Vesu" },
|
|
19996
|
-
{ type: "Low Liquidity Risk" /* LOW_LIQUIDITY_RISK */, value: 0.5, weight: 50, reason: "xSTRK can be sometimes illiquid near true price" }
|
|
19997
|
-
];
|
|
19998
|
-
var FAQS = [
|
|
19999
|
-
{
|
|
20000
|
-
question: "What is xSTRK Sensei?",
|
|
20001
|
-
answer: "xSTRK Sensei is a leveraged looping strategy involving xSTRK and STRK. It uses xSTRK as collateral on Vesu, borrows STRK, and buys more xSTRK with it to create up to 4x leverage and boost yields."
|
|
20002
|
-
},
|
|
20003
|
-
{
|
|
20004
|
-
question: "What is the benefit of using xSTRK Sensei?",
|
|
20005
|
-
answer: "The strategy amplifies your xSTRK exposure and yield through leverage. It also helps you accumulate more Endur points faster."
|
|
20006
|
-
},
|
|
20007
|
-
{
|
|
20008
|
-
question: "What is the maximum leverage possible?",
|
|
20009
|
-
answer: "The strategy may allow up to ~4x leverage, depending on your collateral ratio and market conditions on Vesu. This strategy tries to maintain a health factor of 1.1 on Vesu"
|
|
20010
|
-
},
|
|
20011
|
-
{
|
|
20012
|
-
question: "Isn't 1.1 health factor risky?",
|
|
20013
|
-
answer: "Based on Re7's xSTRK pool configuration on Vesu, xSTRK uses STRK price as its oracle source. This means collateral and debt will always move in the same direction, making 1.1 HF safe. However, if debt increases too much (over months), liquidation may occur, which we try to avoid by actively monitoring the position."
|
|
20014
|
-
},
|
|
20015
|
-
{
|
|
20016
|
-
question: "Are there any risks involved?",
|
|
20017
|
-
answer: "Yes. The major risks are related to xSTRK's illiquidity and price volatility. During volatility or low liquidity, exiting a position can result in loss."
|
|
20018
|
-
},
|
|
20019
|
-
{
|
|
20020
|
-
question: "Does the position always grow?",
|
|
20021
|
-
answer: "No. While xSTRK's true value increases over time, its DEX price may not grow continuously and can fluctuate or move in discrete steps."
|
|
20022
|
-
},
|
|
20023
|
-
{
|
|
20024
|
-
question: "Can I lose money using this strategy?",
|
|
20025
|
-
answer: "Yes. If the xSTRK price drops sharply or becomes illiquid, you may face slippage or loss when trying to exit the looped position."
|
|
20026
|
-
},
|
|
20027
|
-
{
|
|
20028
|
-
question: "What affects the DEX price of xSTRK?",
|
|
20029
|
-
answer: "xSTRK's DEX price depends on supply, demand, and liquidity. Unlike its true value which grows steadily, the DEX price can fluctuate due to market activity."
|
|
20030
|
-
},
|
|
20031
|
-
{
|
|
20032
|
-
question: "Why is xSTRK considered illiquid?",
|
|
20033
|
-
answer: "Since xSTRK is a evolving LST with limited trading volume, sudden large trades can cause high slippage, making it harder to enter or exit positions efficiently. Such conditions normalize over time. Enter and exit positions with caution."
|
|
20034
|
-
},
|
|
20035
|
-
{
|
|
20036
|
-
question: "Do I earn Endur points on looped xSTRK?",
|
|
20037
|
-
answer: "Yes. All xSTRK in the looped position contributes to your Endur points, allowing you to farm points more effectively with leverage. Visit endur.fi/leaderboard to see your points."
|
|
20038
|
-
}
|
|
20039
|
-
];
|
|
20040
|
-
var SenseiStrategies = [
|
|
20041
|
-
{
|
|
20042
|
-
name: "xSTRK Sensei",
|
|
20043
|
-
description: highlightTextWithLinks(
|
|
20044
|
-
senseiDescription.replaceAll("{{token1}}", "STRK").replaceAll("{{token2}}", "xSTRK"),
|
|
20045
|
-
[{
|
|
20046
|
-
highlight: "Endur",
|
|
20047
|
-
link: "https://endur.fi"
|
|
20048
|
-
}, {
|
|
20049
|
-
highlight: "Vesu",
|
|
20050
|
-
link: "https://vesu.xyz"
|
|
20051
|
-
}, {
|
|
20052
|
-
highlight: "delta neutral position",
|
|
20053
|
-
link: "https://www.investopedia.com/terms/d/deltaneutral.asp"
|
|
20054
|
-
}]
|
|
20055
|
-
),
|
|
20056
|
-
address: ContractAddr.from(
|
|
20057
|
-
"0x7023a5cadc8a5db80e4f0fde6b330cbd3c17bbbf9cb145cbabd7bd5e6fb7b0b"
|
|
20058
|
-
),
|
|
20059
|
-
launchBlock: 1053811,
|
|
20060
|
-
type: "Other",
|
|
20061
|
-
depositTokens: [
|
|
20062
|
-
Global.getDefaultTokens().find((t) => t.symbol === "STRK")
|
|
20063
|
-
],
|
|
20064
|
-
protocols: [endurProtocol, vesuProtocol],
|
|
20065
|
-
maxTVL: new Web3Number("1500000", 18),
|
|
20066
|
-
risk: {
|
|
20067
|
-
riskFactor: _riskFactor2,
|
|
20068
|
-
netRisk: _riskFactor2.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor2.reduce((acc, curr) => acc + curr.weight, 0),
|
|
20069
|
-
notARisks: getNoRiskTags(_riskFactor2)
|
|
20070
|
-
},
|
|
20071
|
-
additionalInfo: {
|
|
20072
|
-
mainToken: Global.getDefaultTokens().find((t) => t.symbol === "STRK"),
|
|
20073
|
-
secondaryToken: Global.getDefaultTokens().find((t) => t.symbol === "xSTRK"),
|
|
20074
|
-
targetHfBps: 11e3,
|
|
20075
|
-
// 1.1 health factor
|
|
20076
|
-
feeBps: 2e3
|
|
20077
|
-
// 2% fee on profits
|
|
20078
|
-
},
|
|
20079
|
-
faqs: FAQS,
|
|
20080
|
-
contractDetails: [],
|
|
20081
|
-
investmentSteps: [
|
|
20082
|
-
"Swap STRK for xSTRK",
|
|
20083
|
-
"Deposit xSTRK to Vesu's Re7 xSTRK Pool",
|
|
20084
|
-
"Borrow STRK against your xSTRK collateral",
|
|
20085
|
-
"Buy more xSTRK with borrowed STRK",
|
|
20086
|
-
"Repeat the process to loop your position",
|
|
20087
|
-
"Claim DeFi spring (STRK) rewards weekly and reinvest"
|
|
20088
|
-
],
|
|
20089
|
-
category: "all" /* ALL */,
|
|
20090
|
-
tags: ["Sensei" /* SENSEI */],
|
|
20091
|
-
security: {
|
|
20092
|
-
auditStatus: "Audited" /* AUDITED */,
|
|
20093
|
-
sourceCode: {
|
|
20094
|
-
type: "Closed Source" /* CLOSED_SOURCE */,
|
|
20095
|
-
contractLink: "https://github.com/trovesfi/troves-contracts"
|
|
20096
|
-
},
|
|
20097
|
-
accessControl: {
|
|
20098
|
-
type: "Standard Account" /* STANDARD_ACCOUNT */,
|
|
20099
|
-
addresses: [ContractAddr.from("0x0")],
|
|
20100
|
-
timeLock: "2 Days"
|
|
20101
|
-
}
|
|
20102
|
-
},
|
|
20103
|
-
redemptionInfo: {
|
|
20104
|
-
instantWithdrawalVault: "Yes" /* YES */
|
|
20105
|
-
}
|
|
20106
|
-
}
|
|
20107
|
-
];
|
|
20108
|
-
|
|
20109
|
-
// src/strategies/universal-adapters/baseAdapter.ts
|
|
20180
|
+
// src/strategies/universal-adapters/vesu-adapter.ts
|
|
20110
20181
|
var import_starknet14 = require("starknet");
|
|
20111
20182
|
|
|
20112
20183
|
// src/strategies/universal-adapters/adapter-utils.ts
|
|
@@ -20129,6 +20200,7 @@ function toBigInt(value) {
|
|
|
20129
20200
|
}
|
|
20130
20201
|
|
|
20131
20202
|
// src/strategies/universal-adapters/baseAdapter.ts
|
|
20203
|
+
var import_starknet13 = require("starknet");
|
|
20132
20204
|
var APYType = /* @__PURE__ */ ((APYType2) => {
|
|
20133
20205
|
APYType2["BASE"] = "base";
|
|
20134
20206
|
APYType2["REWARD"] = "reward";
|
|
@@ -20184,14 +20256,14 @@ var BaseAdapter = class extends CacheClass {
|
|
|
20184
20256
|
constructSimpleLeafData(params, sanitizer = SIMPLE_SANITIZER) {
|
|
20185
20257
|
const { id, target, method, packedArguments } = params;
|
|
20186
20258
|
return {
|
|
20187
|
-
id: BigInt(
|
|
20259
|
+
id: BigInt(import_starknet13.num.getDecimalString(import_starknet13.shortString.encodeShortString(id))),
|
|
20188
20260
|
readableId: id,
|
|
20189
20261
|
data: [
|
|
20190
20262
|
sanitizer.toBigInt(),
|
|
20191
20263
|
// sanitizer address
|
|
20192
20264
|
target.toBigInt(),
|
|
20193
20265
|
// contract
|
|
20194
|
-
toBigInt(
|
|
20266
|
+
toBigInt(import_starknet13.hash.getSelectorFromName(method)),
|
|
20195
20267
|
// method name
|
|
20196
20268
|
BigInt(packedArguments.length),
|
|
20197
20269
|
...packedArguments
|
|
@@ -20288,183 +20360,6 @@ var BaseAdapter = class extends CacheClass {
|
|
|
20288
20360
|
// }
|
|
20289
20361
|
};
|
|
20290
20362
|
|
|
20291
|
-
// src/strategies/universal-adapters/common-adapter.ts
|
|
20292
|
-
var import_starknet15 = require("starknet");
|
|
20293
|
-
var CommonAdapter = class extends BaseAdapter {
|
|
20294
|
-
constructor(config) {
|
|
20295
|
-
super();
|
|
20296
|
-
this.config = config;
|
|
20297
|
-
}
|
|
20298
|
-
getFlashloanAdapter() {
|
|
20299
|
-
const manageCall = this.getFlashloanCall.bind(this)({ amount: Web3Number.fromWei("0", 6), data: [] });
|
|
20300
|
-
const packedArguments = [
|
|
20301
|
-
this.config.manager.toBigInt(),
|
|
20302
|
-
// receiver
|
|
20303
|
-
this.config.asset.toBigInt(),
|
|
20304
|
-
// asset
|
|
20305
|
-
toBigInt(0)
|
|
20306
|
-
// is legacy false
|
|
20307
|
-
];
|
|
20308
|
-
const leaf = this.constructSimpleLeafData({
|
|
20309
|
-
id: this.config.id,
|
|
20310
|
-
target: manageCall.call.contractAddress,
|
|
20311
|
-
method: "flash_loan",
|
|
20312
|
-
packedArguments
|
|
20313
|
-
});
|
|
20314
|
-
return { leaf, callConstructor: this.getFlashloanCall.bind(this) };
|
|
20315
|
-
}
|
|
20316
|
-
getFlashloanCall(params) {
|
|
20317
|
-
const uint256Amount = import_starknet15.uint256.bnToUint256(params.amount.toWei());
|
|
20318
|
-
return {
|
|
20319
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
20320
|
-
call: {
|
|
20321
|
-
contractAddress: this.config.manager,
|
|
20322
|
-
selector: import_starknet15.hash.getSelectorFromName("flash_loan"),
|
|
20323
|
-
calldata: [
|
|
20324
|
-
this.config.manager.toBigInt(),
|
|
20325
|
-
// receiver
|
|
20326
|
-
this.config.asset.toBigInt(),
|
|
20327
|
-
// asset
|
|
20328
|
-
toBigInt(uint256Amount.low.toString()),
|
|
20329
|
-
// amount low
|
|
20330
|
-
toBigInt(uint256Amount.high.toString()),
|
|
20331
|
-
// amount high
|
|
20332
|
-
toBigInt(0),
|
|
20333
|
-
// is legacy false
|
|
20334
|
-
BigInt(params.data.length),
|
|
20335
|
-
...params.data
|
|
20336
|
-
]
|
|
20337
|
-
}
|
|
20338
|
-
};
|
|
20339
|
-
}
|
|
20340
|
-
getApproveAdapter(token, spender, id) {
|
|
20341
|
-
return () => ({
|
|
20342
|
-
leaf: this.constructSimpleLeafData({
|
|
20343
|
-
id,
|
|
20344
|
-
target: token,
|
|
20345
|
-
method: "approve",
|
|
20346
|
-
packedArguments: [
|
|
20347
|
-
spender.toBigInt()
|
|
20348
|
-
// spender
|
|
20349
|
-
]
|
|
20350
|
-
}),
|
|
20351
|
-
callConstructor: this.getApproveCall(token, spender).bind(this)
|
|
20352
|
-
});
|
|
20353
|
-
}
|
|
20354
|
-
getApproveCall(token, spender) {
|
|
20355
|
-
return (params) => {
|
|
20356
|
-
const uint256Amount = import_starknet15.uint256.bnToUint256(params.amount.toWei());
|
|
20357
|
-
return {
|
|
20358
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
20359
|
-
call: {
|
|
20360
|
-
contractAddress: token,
|
|
20361
|
-
selector: import_starknet15.hash.getSelectorFromName("approve"),
|
|
20362
|
-
calldata: [
|
|
20363
|
-
spender.toBigInt(),
|
|
20364
|
-
// spender
|
|
20365
|
-
toBigInt(uint256Amount.low.toString()),
|
|
20366
|
-
// amount low
|
|
20367
|
-
toBigInt(uint256Amount.high.toString())
|
|
20368
|
-
// amount high
|
|
20369
|
-
]
|
|
20370
|
-
}
|
|
20371
|
-
};
|
|
20372
|
-
};
|
|
20373
|
-
}
|
|
20374
|
-
getBringLiquidityAdapter(id) {
|
|
20375
|
-
return () => ({
|
|
20376
|
-
leaf: this.constructSimpleLeafData({
|
|
20377
|
-
id,
|
|
20378
|
-
target: this.config.vaultAddress,
|
|
20379
|
-
method: "bring_liquidity",
|
|
20380
|
-
packedArguments: []
|
|
20381
|
-
}),
|
|
20382
|
-
callConstructor: this.getBringLiquidityCall().bind(this)
|
|
20383
|
-
});
|
|
20384
|
-
}
|
|
20385
|
-
getBringLiquidityCall() {
|
|
20386
|
-
return (params) => {
|
|
20387
|
-
const uint256Amount = import_starknet15.uint256.bnToUint256(params.amount.toWei());
|
|
20388
|
-
return {
|
|
20389
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
20390
|
-
call: {
|
|
20391
|
-
contractAddress: this.config.vaultAddress,
|
|
20392
|
-
selector: import_starknet15.hash.getSelectorFromName("bring_liquidity"),
|
|
20393
|
-
calldata: [
|
|
20394
|
-
toBigInt(uint256Amount.low.toString()),
|
|
20395
|
-
// amount low
|
|
20396
|
-
toBigInt(uint256Amount.high.toString())
|
|
20397
|
-
// amount high
|
|
20398
|
-
]
|
|
20399
|
-
}
|
|
20400
|
-
};
|
|
20401
|
-
};
|
|
20402
|
-
}
|
|
20403
|
-
getAvnuAdapter(fromToken, toToken, id, isMiddleware) {
|
|
20404
|
-
return () => ({
|
|
20405
|
-
leaf: this.constructSimpleLeafData({
|
|
20406
|
-
id,
|
|
20407
|
-
target: isMiddleware ? AVNU_MIDDLEWARE : AVNU_EXCHANGE,
|
|
20408
|
-
method: "multi_route_swap",
|
|
20409
|
-
packedArguments: [
|
|
20410
|
-
fromToken.toBigInt(),
|
|
20411
|
-
toToken.toBigInt(),
|
|
20412
|
-
this.config.vaultAllocator.toBigInt()
|
|
20413
|
-
]
|
|
20414
|
-
}),
|
|
20415
|
-
callConstructor: this.getAvnuCall(fromToken, toToken, isMiddleware).bind(this)
|
|
20416
|
-
});
|
|
20417
|
-
}
|
|
20418
|
-
getAvnuCall(fromToken, toToken, isMiddleware) {
|
|
20419
|
-
return (params) => {
|
|
20420
|
-
return {
|
|
20421
|
-
sanitizer: SIMPLE_SANITIZER,
|
|
20422
|
-
call: {
|
|
20423
|
-
contractAddress: isMiddleware ? AVNU_MIDDLEWARE : AVNU_EXCHANGE,
|
|
20424
|
-
selector: import_starknet15.hash.getSelectorFromName("multi_route_swap"),
|
|
20425
|
-
calldata: [
|
|
20426
|
-
fromToken.toBigInt(),
|
|
20427
|
-
// sell_token_address
|
|
20428
|
-
toBigInt(params.props.token_from_amount.low.toString()),
|
|
20429
|
-
// sell_token_amount low
|
|
20430
|
-
toBigInt(params.props.token_from_amount.high.toString()),
|
|
20431
|
-
// sell_token_amount high
|
|
20432
|
-
toToken.toBigInt(),
|
|
20433
|
-
// buy_token_address
|
|
20434
|
-
toBigInt(params.props.token_to_amount.low.toString()),
|
|
20435
|
-
// buy_token_amount low
|
|
20436
|
-
toBigInt(params.props.token_to_amount.high.toString()),
|
|
20437
|
-
// buy_token_amount high
|
|
20438
|
-
toBigInt(params.props.token_to_min_amount.low.toString()),
|
|
20439
|
-
// buy_token_min_amount low
|
|
20440
|
-
toBigInt(params.props.token_to_min_amount.high.toString()),
|
|
20441
|
-
// buy_token_min_amount high
|
|
20442
|
-
this.config.vaultAllocator.toBigInt(),
|
|
20443
|
-
// beneficiary
|
|
20444
|
-
toBigInt(0),
|
|
20445
|
-
// integrator_fee_amount_bps
|
|
20446
|
-
this.config.vaultAllocator.toBigInt(),
|
|
20447
|
-
// integrator_fee_recipient
|
|
20448
|
-
// unpack routes
|
|
20449
|
-
BigInt(params.props.routes.length),
|
|
20450
|
-
...params.props.routes.map((r) => [
|
|
20451
|
-
BigInt(import_starknet15.num.hexToDecimalString(r.token_from)),
|
|
20452
|
-
BigInt(import_starknet15.num.hexToDecimalString(r.token_to)),
|
|
20453
|
-
BigInt(import_starknet15.num.hexToDecimalString(r.exchange_address)),
|
|
20454
|
-
BigInt(r.percent),
|
|
20455
|
-
BigInt(r.additional_swap_params.length),
|
|
20456
|
-
...r.additional_swap_params.map((p) => BigInt(import_starknet15.num.hexToDecimalString(p)))
|
|
20457
|
-
]).flat()
|
|
20458
|
-
]
|
|
20459
|
-
}
|
|
20460
|
-
};
|
|
20461
|
-
};
|
|
20462
|
-
}
|
|
20463
|
-
};
|
|
20464
|
-
|
|
20465
|
-
// src/strategies/universal-adapters/vesu-adapter.ts
|
|
20466
|
-
var import_starknet16 = require("starknet");
|
|
20467
|
-
|
|
20468
20363
|
// src/data/vesu-singleton.abi.json
|
|
20469
20364
|
var vesu_singleton_abi_default = [
|
|
20470
20365
|
{
|
|
@@ -27508,7 +27403,7 @@ function getVesuMultiplyParams(isIncrease, params) {
|
|
|
27508
27403
|
if (isIncrease) {
|
|
27509
27404
|
const _params2 = params;
|
|
27510
27405
|
return {
|
|
27511
|
-
action: new
|
|
27406
|
+
action: new import_starknet14.CairoCustomEnum({ IncreaseLever: {
|
|
27512
27407
|
pool_id: _params2.pool_id.toBigInt(),
|
|
27513
27408
|
collateral_asset: _params2.collateral_asset.toBigInt(),
|
|
27514
27409
|
debt_asset: _params2.debt_asset.toBigInt(),
|
|
@@ -27521,9 +27416,9 @@ function getVesuMultiplyParams(isIncrease, params) {
|
|
|
27521
27416
|
token1: route.pool_key.token1.toBigInt(),
|
|
27522
27417
|
fee: route.pool_key.fee,
|
|
27523
27418
|
tick_spacing: route.pool_key.tick_spacing,
|
|
27524
|
-
extension: BigInt(
|
|
27419
|
+
extension: BigInt(import_starknet14.num.hexToDecimalString(route.pool_key.extension))
|
|
27525
27420
|
},
|
|
27526
|
-
sqrt_ratio_limit:
|
|
27421
|
+
sqrt_ratio_limit: import_starknet14.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
|
|
27527
27422
|
skip_ahead: BigInt(100)
|
|
27528
27423
|
})),
|
|
27529
27424
|
token_amount: {
|
|
@@ -27539,9 +27434,9 @@ function getVesuMultiplyParams(isIncrease, params) {
|
|
|
27539
27434
|
token1: route.pool_key.token1.toBigInt(),
|
|
27540
27435
|
fee: route.pool_key.fee,
|
|
27541
27436
|
tick_spacing: route.pool_key.tick_spacing,
|
|
27542
|
-
extension: BigInt(
|
|
27437
|
+
extension: BigInt(import_starknet14.num.hexToDecimalString(route.pool_key.extension))
|
|
27543
27438
|
},
|
|
27544
|
-
sqrt_ratio_limit:
|
|
27439
|
+
sqrt_ratio_limit: import_starknet14.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
|
|
27545
27440
|
skip_ahead: BigInt(100)
|
|
27546
27441
|
})),
|
|
27547
27442
|
token_amount: {
|
|
@@ -27555,7 +27450,7 @@ function getVesuMultiplyParams(isIncrease, params) {
|
|
|
27555
27450
|
}
|
|
27556
27451
|
const _params = params;
|
|
27557
27452
|
return {
|
|
27558
|
-
action: new
|
|
27453
|
+
action: new import_starknet14.CairoCustomEnum({ DecreaseLever: {
|
|
27559
27454
|
pool_id: _params.pool_id.toBigInt(),
|
|
27560
27455
|
collateral_asset: _params.collateral_asset.toBigInt(),
|
|
27561
27456
|
debt_asset: _params.debt_asset.toBigInt(),
|
|
@@ -27571,7 +27466,7 @@ function getVesuMultiplyParams(isIncrease, params) {
|
|
|
27571
27466
|
tick_spacing: route.pool_key.tick_spacing,
|
|
27572
27467
|
extension: ContractAddr.from(route.pool_key.extension).toBigInt()
|
|
27573
27468
|
},
|
|
27574
|
-
sqrt_ratio_limit:
|
|
27469
|
+
sqrt_ratio_limit: import_starknet14.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
|
|
27575
27470
|
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
27576
27471
|
})),
|
|
27577
27472
|
token_amount: {
|
|
@@ -27590,7 +27485,7 @@ function getVesuMultiplyParams(isIncrease, params) {
|
|
|
27590
27485
|
tick_spacing: route.pool_key.tick_spacing,
|
|
27591
27486
|
extension: ContractAddr.from(route.pool_key.extension).toBigInt()
|
|
27592
27487
|
},
|
|
27593
|
-
sqrt_ratio_limit:
|
|
27488
|
+
sqrt_ratio_limit: import_starknet14.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
|
|
27594
27489
|
skip_ahead: BigInt(route.skip_ahead.toWei())
|
|
27595
27490
|
})),
|
|
27596
27491
|
token_amount: {
|
|
@@ -27607,7 +27502,8 @@ function getVesuMultiplyParams(isIncrease, params) {
|
|
|
27607
27502
|
var VesuPools = {
|
|
27608
27503
|
Genesis: ContractAddr.from("0x4dc4f0ca6ea4961e4c8373265bfd5317678f4fe374d76f3fd7135f57763bf28"),
|
|
27609
27504
|
Re7xSTRK: ContractAddr.from("0x052fb52363939c3aa848f8f4ac28f0a51379f8d1b971d8444de25fbd77d8f161"),
|
|
27610
|
-
Re7xBTC: ContractAddr.from("0x3a8416bf20d036df5b1cf3447630a2e1cb04685f6b0c3a70ed7fb1473548ecf")
|
|
27505
|
+
Re7xBTC: ContractAddr.from("0x3a8416bf20d036df5b1cf3447630a2e1cb04685f6b0c3a70ed7fb1473548ecf"),
|
|
27506
|
+
Prime: ContractAddr.from("0x451fe483d5921a2919ddd81d0de6696669bccdacd859f72a4fba7656b97c3b5")
|
|
27611
27507
|
};
|
|
27612
27508
|
var extensionMap = {};
|
|
27613
27509
|
extensionMap[VesuPools.Re7xSTRK.address] = ContractAddr.from("0x04e06e04b8d624d039aa1c3ca8e0aa9e21dc1ccba1d88d0d650837159e0ee054");
|
|
@@ -27655,7 +27551,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27655
27551
|
amount_type: this.formatAmountTypeEnum(params.collateralAmount.amount_type),
|
|
27656
27552
|
denomination: this.formatAmountDenominationEnum(params.collateralAmount.denomination),
|
|
27657
27553
|
value: {
|
|
27658
|
-
abs:
|
|
27554
|
+
abs: import_starknet14.uint256.bnToUint256(params.collateralAmount.value.abs.toWei()),
|
|
27659
27555
|
is_negative: params.collateralAmount.value.abs.isZero() ? false : params.collateralAmount.value.is_negative
|
|
27660
27556
|
}
|
|
27661
27557
|
};
|
|
@@ -27664,7 +27560,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27664
27560
|
amount_type: this.formatAmountTypeEnum(params.debtAmount.amount_type),
|
|
27665
27561
|
denomination: this.formatAmountDenominationEnum(params.debtAmount.denomination),
|
|
27666
27562
|
value: {
|
|
27667
|
-
abs:
|
|
27563
|
+
abs: import_starknet14.uint256.bnToUint256(params.debtAmount.value.abs.toWei()),
|
|
27668
27564
|
is_negative: params.debtAmount.value.abs.isZero() ? false : params.debtAmount.value.is_negative
|
|
27669
27565
|
}
|
|
27670
27566
|
};
|
|
@@ -27691,7 +27587,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27691
27587
|
sanitizer: isV2 ? VESU_V2_MODIFY_POSITION_SANITIZER : SIMPLE_SANITIZER,
|
|
27692
27588
|
call: {
|
|
27693
27589
|
contractAddress: ContractAddr.from(contract.address),
|
|
27694
|
-
selector:
|
|
27590
|
+
selector: import_starknet14.hash.getSelectorFromName("modify_position"),
|
|
27695
27591
|
calldata: [
|
|
27696
27592
|
...call.calldata
|
|
27697
27593
|
]
|
|
@@ -27728,7 +27624,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27728
27624
|
}
|
|
27729
27625
|
const { isV2 } = getVesuSingletonAddress(this.config.poolId);
|
|
27730
27626
|
const VESU_MULTIPLY = isV2 ? this.VESU_MULTIPLY : this.VESU_MULTIPLY_V1;
|
|
27731
|
-
const multiplyContract = new
|
|
27627
|
+
const multiplyContract = new import_starknet14.Contract({ abi: vesu_multiple_abi_default, address: VESU_MULTIPLY.toString(), providerOrAccount: new import_starknet14.RpcProvider({ nodeUrl: "" }) });
|
|
27732
27628
|
const call = multiplyContract.populate("modify_lever", {
|
|
27733
27629
|
modify_lever_params: getVesuMultiplyParams(isIncrease, {
|
|
27734
27630
|
...multiplyParams,
|
|
@@ -27743,7 +27639,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27743
27639
|
sanitizer: SIMPLE_SANITIZER_V2,
|
|
27744
27640
|
call: {
|
|
27745
27641
|
contractAddress: VESU_MULTIPLY,
|
|
27746
|
-
selector:
|
|
27642
|
+
selector: import_starknet14.hash.getSelectorFromName("modify_lever"),
|
|
27747
27643
|
calldata: [
|
|
27748
27644
|
...call.calldata
|
|
27749
27645
|
]
|
|
@@ -27785,7 +27681,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27785
27681
|
sanitizer: isV2 ? SIMPLE_SANITIZER_V2 : SIMPLE_SANITIZER_VESU_V1_DELEGATIONS,
|
|
27786
27682
|
call: {
|
|
27787
27683
|
contractAddress: VESU_SINGLETON2,
|
|
27788
|
-
selector:
|
|
27684
|
+
selector: import_starknet14.hash.getSelectorFromName("modify_delegation"),
|
|
27789
27685
|
calldata: [
|
|
27790
27686
|
...call.calldata
|
|
27791
27687
|
]
|
|
@@ -27796,14 +27692,14 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27796
27692
|
return () => {
|
|
27797
27693
|
const packedArguments = [];
|
|
27798
27694
|
const output = {
|
|
27799
|
-
id: BigInt(
|
|
27695
|
+
id: BigInt(import_starknet14.num.getDecimalString(import_starknet14.shortString.encodeShortString(id))),
|
|
27800
27696
|
readableId: id,
|
|
27801
27697
|
data: [
|
|
27802
27698
|
SIMPLE_SANITIZER.toBigInt(),
|
|
27803
27699
|
// sanitizer address
|
|
27804
27700
|
VESU_REWARDS_CONTRACT.toBigInt(),
|
|
27805
27701
|
// contract
|
|
27806
|
-
toBigInt(
|
|
27702
|
+
toBigInt(import_starknet14.hash.getSelectorFromName("claim")),
|
|
27807
27703
|
// method name
|
|
27808
27704
|
BigInt(packedArguments.length),
|
|
27809
27705
|
...packedArguments
|
|
@@ -27817,11 +27713,11 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27817
27713
|
sanitizer: SIMPLE_SANITIZER,
|
|
27818
27714
|
call: {
|
|
27819
27715
|
contractAddress: VESU_REWARDS_CONTRACT,
|
|
27820
|
-
selector:
|
|
27716
|
+
selector: import_starknet14.hash.getSelectorFromName("claim"),
|
|
27821
27717
|
calldata: [
|
|
27822
27718
|
BigInt(params.amount.toWei()),
|
|
27823
27719
|
BigInt(params.proofs.length),
|
|
27824
|
-
...params.proofs.map((proof) => BigInt(
|
|
27720
|
+
...params.proofs.map((proof) => BigInt(import_starknet14.num.hexToDecimalString(proof)))
|
|
27825
27721
|
]
|
|
27826
27722
|
}
|
|
27827
27723
|
});
|
|
@@ -27851,18 +27747,18 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27851
27747
|
formatAmountTypeEnum(amountType) {
|
|
27852
27748
|
switch (amountType) {
|
|
27853
27749
|
case 0 /* Delta */:
|
|
27854
|
-
return new
|
|
27750
|
+
return new import_starknet14.CairoCustomEnum({ Delta: {} });
|
|
27855
27751
|
case 1 /* Target */:
|
|
27856
|
-
return new
|
|
27752
|
+
return new import_starknet14.CairoCustomEnum({ Target: {} });
|
|
27857
27753
|
}
|
|
27858
27754
|
throw new Error(`Unknown VesuAmountType: ${amountType}`);
|
|
27859
27755
|
}
|
|
27860
27756
|
formatAmountDenominationEnum(denomination) {
|
|
27861
27757
|
switch (denomination) {
|
|
27862
27758
|
case 0 /* Native */:
|
|
27863
|
-
return new
|
|
27759
|
+
return new import_starknet14.CairoCustomEnum({ Native: {} });
|
|
27864
27760
|
case 1 /* Assets */:
|
|
27865
|
-
return new
|
|
27761
|
+
return new import_starknet14.CairoCustomEnum({ Assets: {} });
|
|
27866
27762
|
}
|
|
27867
27763
|
throw new Error(`Unknown VesuAmountDenomination: ${denomination}`);
|
|
27868
27764
|
}
|
|
@@ -27870,7 +27766,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27870
27766
|
const { addr: VESU_SINGLETON2, isV2 } = getVesuSingletonAddress(poolId);
|
|
27871
27767
|
const ABI = isV2 ? vesu_pool_v2_abi_default : vesu_singleton_abi_default;
|
|
27872
27768
|
return {
|
|
27873
|
-
contract: new
|
|
27769
|
+
contract: new import_starknet14.Contract({ abi: ABI, address: VESU_SINGLETON2.address, providerOrAccount: config.provider }),
|
|
27874
27770
|
isV2
|
|
27875
27771
|
};
|
|
27876
27772
|
}
|
|
@@ -27881,7 +27777,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27881
27777
|
if (!extensionAddr) {
|
|
27882
27778
|
throw new Error("Extension address not found");
|
|
27883
27779
|
}
|
|
27884
|
-
const extensionContract = new
|
|
27780
|
+
const extensionContract = new import_starknet14.Contract({ abi: vesu_extension_abi_default, address: extensionAddr.address, providerOrAccount: config.provider });
|
|
27885
27781
|
const output2 = await extensionContract.call("debt_caps", [this.config.poolId.address, this.config.collateral.address.address, this.config.debt.address.address]);
|
|
27886
27782
|
logger.verbose(`${this.config.debt.symbol}::VesuAdapter::getDebtCap debt_cap: ${output2.toString()}`);
|
|
27887
27783
|
return Web3Number.fromWei(output2.toString(), this.config.debt.decimals);
|
|
@@ -27911,7 +27807,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27911
27807
|
if (!extensionAddr) {
|
|
27912
27808
|
throw new Error("Extension address not found");
|
|
27913
27809
|
}
|
|
27914
|
-
interestRateConfigContract = new
|
|
27810
|
+
interestRateConfigContract = new import_starknet14.Contract({ abi: vesu_extension_abi_default, address: extensionAddr.address, providerOrAccount: config.provider });
|
|
27915
27811
|
}
|
|
27916
27812
|
const _interestRateConfig = await interestRateConfigContract.call(
|
|
27917
27813
|
"interest_rate_config",
|
|
@@ -27934,14 +27830,15 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
27934
27830
|
const assetConfig = isV2 ? _assetConfig : _assetConfig["0"];
|
|
27935
27831
|
const timeDelta = assetConfig.last_updated;
|
|
27936
27832
|
const lastFullUtilizationRate = assetConfig.last_full_utilization_rate;
|
|
27937
|
-
const
|
|
27833
|
+
const debtSharePrice = Web3Number.fromWei(assetConfig.last_rate_accumulator, 18);
|
|
27834
|
+
const currentDebt = new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals).multipliedBy(debtSharePrice);
|
|
27938
27835
|
const totalSupply = currentDebt.plus(Web3Number.fromWei(assetConfig.reserve, asset.decimals));
|
|
27939
27836
|
const ratePerSecond = BigInt(Math.round(maxBorrowAPY / 365 / 24 / 60 / 60 * Number(SCALE)));
|
|
27940
27837
|
const maxUtilisation = this.getMaxUtilizationGivenRatePerSecond(interestRateConfig, ratePerSecond, timeDelta, lastFullUtilizationRate);
|
|
27941
27838
|
logger.verbose(`${asset.symbol}::VesuAdapter::getMaxBorrowableByInterestRate maxUtilisation: ${Number(maxUtilisation) / 1e18}, totalSupply: ${totalSupply.toString()}`);
|
|
27942
27839
|
const maxDebtToHave = totalSupply.multipliedBy(Number(maxUtilisation) / 1e18);
|
|
27943
27840
|
logger.verbose(`${asset.symbol}::VesuAdapter::getMaxBorrowableByInterestRate currentDebt: ${currentDebt.toString()}, maxDebtToHave: ${maxDebtToHave.toString()}`);
|
|
27944
|
-
return maxDebtToHave.minus(currentDebt);
|
|
27841
|
+
return { maxDebtToHave: maxDebtToHave.minus(currentDebt), currentDebt, totalSupply };
|
|
27945
27842
|
}
|
|
27946
27843
|
async getLTVConfig(config, blockNumber = "latest") {
|
|
27947
27844
|
const CACHE_KEY = `ltv_config_${blockNumber}`;
|
|
@@ -28069,7 +27966,7 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
28069
27966
|
let pools = [];
|
|
28070
27967
|
try {
|
|
28071
27968
|
const data = await getAPIUsingHeadlessBrowser(
|
|
28072
|
-
`${ENDPOINTS.
|
|
27969
|
+
`${ENDPOINTS.VESU_BASE}/pools`
|
|
28073
27970
|
);
|
|
28074
27971
|
pools = data.data;
|
|
28075
27972
|
for (const pool of vesu_pools_default.data) {
|
|
@@ -28170,6 +28067,678 @@ var VesuAdapter = class _VesuAdapter extends BaseAdapter {
|
|
|
28170
28067
|
}
|
|
28171
28068
|
};
|
|
28172
28069
|
|
|
28070
|
+
// src/modules/lst-apr.ts
|
|
28071
|
+
var LSTAPRService = class {
|
|
28072
|
+
// 5 minutes
|
|
28073
|
+
/**
|
|
28074
|
+
* Fetches LST stats from Endur API with caching
|
|
28075
|
+
* @returns Promise<LSTStats[]> Array of LST statistics
|
|
28076
|
+
*/
|
|
28077
|
+
static async getLSTStats() {
|
|
28078
|
+
const now = Date.now();
|
|
28079
|
+
if (this.cache && now - this.cacheTimestamp < this.CACHE_DURATION) {
|
|
28080
|
+
logger.verbose(`LSTAPRService: Returning cached LST stats`);
|
|
28081
|
+
return this.cache;
|
|
28082
|
+
}
|
|
28083
|
+
try {
|
|
28084
|
+
logger.verbose(`LSTAPRService: Fetching LST stats from Endur API`);
|
|
28085
|
+
const response = await fetch(this.ENDUR_API_URL);
|
|
28086
|
+
if (!response.ok) {
|
|
28087
|
+
throw new Error(`Failed to fetch LST stats: ${response.status} ${response.statusText}`);
|
|
28088
|
+
}
|
|
28089
|
+
const data = await response.json();
|
|
28090
|
+
if (!Array.isArray(data)) {
|
|
28091
|
+
throw new Error("Invalid response format: expected array");
|
|
28092
|
+
}
|
|
28093
|
+
this.cache = data;
|
|
28094
|
+
this.cacheTimestamp = now;
|
|
28095
|
+
logger.verbose(`LSTAPRService: Successfully fetched ${data.length} LST stats`);
|
|
28096
|
+
return data;
|
|
28097
|
+
} catch (error) {
|
|
28098
|
+
logger.error(`LSTAPRService: Error fetching LST stats: ${error}`);
|
|
28099
|
+
if (this.cache) {
|
|
28100
|
+
logger.warn(`LSTAPRService: Returning stale cached data due to API error`);
|
|
28101
|
+
return this.cache;
|
|
28102
|
+
}
|
|
28103
|
+
throw error;
|
|
28104
|
+
}
|
|
28105
|
+
}
|
|
28106
|
+
/**
|
|
28107
|
+
* Gets LST APR for a specific asset address
|
|
28108
|
+
* @param assetAddress - The contract address of the underlying asset
|
|
28109
|
+
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
28110
|
+
*/
|
|
28111
|
+
static async getLSTAPR(assetAddress) {
|
|
28112
|
+
const stats = await this.getLSTStats();
|
|
28113
|
+
const lstStat = stats.find(
|
|
28114
|
+
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
28115
|
+
);
|
|
28116
|
+
if (!lstStat) {
|
|
28117
|
+
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
28118
|
+
return 0;
|
|
28119
|
+
}
|
|
28120
|
+
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy} (${lstStat.apyInPercentage})`);
|
|
28121
|
+
return lstStat.apy;
|
|
28122
|
+
}
|
|
28123
|
+
/**
|
|
28124
|
+
* Gets LST APR for multiple asset addresses
|
|
28125
|
+
* @param assetAddresses - Array of contract addresses
|
|
28126
|
+
* @returns Promise<Map<string, number>> Map of asset address to LST APR
|
|
28127
|
+
*/
|
|
28128
|
+
static async getLSTAPRs(assetAddresses) {
|
|
28129
|
+
const stats = await this.getLSTStats();
|
|
28130
|
+
const result = /* @__PURE__ */ new Map();
|
|
28131
|
+
for (const assetAddress of assetAddresses) {
|
|
28132
|
+
const lstStat = stats.find(
|
|
28133
|
+
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
28134
|
+
);
|
|
28135
|
+
if (lstStat) {
|
|
28136
|
+
result.set(assetAddress.address, lstStat.apy);
|
|
28137
|
+
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy}`);
|
|
28138
|
+
} else {
|
|
28139
|
+
result.set(assetAddress.address, 0);
|
|
28140
|
+
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
28141
|
+
}
|
|
28142
|
+
}
|
|
28143
|
+
return result;
|
|
28144
|
+
}
|
|
28145
|
+
/**
|
|
28146
|
+
* Gets all available LST assets and their APRs
|
|
28147
|
+
* @returns Promise<Map<string, LSTStats>> Map of asset address to LST stats
|
|
28148
|
+
*/
|
|
28149
|
+
static async getAllLSTStats() {
|
|
28150
|
+
const stats = await this.getLSTStats();
|
|
28151
|
+
const result = /* @__PURE__ */ new Map();
|
|
28152
|
+
for (const stat of stats) {
|
|
28153
|
+
result.set(stat.assetAddress, stat);
|
|
28154
|
+
}
|
|
28155
|
+
return result;
|
|
28156
|
+
}
|
|
28157
|
+
/**
|
|
28158
|
+
* Clears the cache (useful for testing or forcing refresh)
|
|
28159
|
+
*/
|
|
28160
|
+
static clearCache() {
|
|
28161
|
+
this.cache = null;
|
|
28162
|
+
this.cacheTimestamp = 0;
|
|
28163
|
+
logger.verbose(`LSTAPRService: Cache cleared`);
|
|
28164
|
+
}
|
|
28165
|
+
};
|
|
28166
|
+
LSTAPRService.ENDUR_API_URL = "https://app.endur.fi/api/lst/stats";
|
|
28167
|
+
LSTAPRService.cache = null;
|
|
28168
|
+
LSTAPRService.cacheTimestamp = 0;
|
|
28169
|
+
LSTAPRService.CACHE_DURATION = 5 * 60 * 1e3;
|
|
28170
|
+
|
|
28171
|
+
// src/strategies/sensei.ts
|
|
28172
|
+
var SenseiVault = class _SenseiVault extends BaseStrategy {
|
|
28173
|
+
constructor(config, pricer, metadata) {
|
|
28174
|
+
super(config);
|
|
28175
|
+
this.getSettings = async () => {
|
|
28176
|
+
const settings = await this.contract.call("get_settings", []);
|
|
28177
|
+
logger.verbose("getSettings", settings);
|
|
28178
|
+
return settings;
|
|
28179
|
+
};
|
|
28180
|
+
this.address = metadata.address;
|
|
28181
|
+
this.pricer = pricer;
|
|
28182
|
+
this.metadata = metadata;
|
|
28183
|
+
this.contract = new import_starknet15.Contract({ abi: sensei_abi_default, address: this.address.address, providerOrAccount: this.config.provider });
|
|
28184
|
+
if (metadata.depositTokens.length === 0) {
|
|
28185
|
+
throw new Error("Deposit tokens are not defined in metadata");
|
|
28186
|
+
}
|
|
28187
|
+
}
|
|
28188
|
+
async getUserTVL(user, blockIdentifier = "latest") {
|
|
28189
|
+
const result = await this.contract.call(
|
|
28190
|
+
"describe_position",
|
|
28191
|
+
[user.address],
|
|
28192
|
+
{
|
|
28193
|
+
blockIdentifier
|
|
28194
|
+
}
|
|
28195
|
+
);
|
|
28196
|
+
const amount = Web3Number.fromWei(
|
|
28197
|
+
import_starknet15.uint256.uint256ToBN(result[1].estimated_size).toString(),
|
|
28198
|
+
this.metadata.depositTokens[0].decimals
|
|
28199
|
+
);
|
|
28200
|
+
const blockNumber = typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint" ? Number(blockIdentifier) : void 0;
|
|
28201
|
+
const price = await this.pricer.getPrice(
|
|
28202
|
+
this.metadata.depositTokens[0].symbol,
|
|
28203
|
+
blockNumber
|
|
28204
|
+
);
|
|
28205
|
+
return {
|
|
28206
|
+
usdValue: Number(amount.toFixed(6)) * price.price,
|
|
28207
|
+
amount,
|
|
28208
|
+
tokenInfo: this.metadata.depositTokens[0]
|
|
28209
|
+
};
|
|
28210
|
+
}
|
|
28211
|
+
async getTVL() {
|
|
28212
|
+
try {
|
|
28213
|
+
const {
|
|
28214
|
+
collateralXSTRK,
|
|
28215
|
+
collateralUSDValue,
|
|
28216
|
+
debtSTRK,
|
|
28217
|
+
debtUSDValue,
|
|
28218
|
+
xSTRKPrice,
|
|
28219
|
+
collateralInSTRK
|
|
28220
|
+
} = await this.getPositionInfo();
|
|
28221
|
+
const usdValue = Number(collateralUSDValue.toFixed(6)) - Number(debtUSDValue.toFixed(6));
|
|
28222
|
+
return {
|
|
28223
|
+
usdValue,
|
|
28224
|
+
amount: new Web3Number(
|
|
28225
|
+
(collateralInSTRK - Number(debtSTRK.toFixed(6))).toFixed(6),
|
|
28226
|
+
collateralXSTRK.decimals
|
|
28227
|
+
),
|
|
28228
|
+
tokenInfo: this.metadata.depositTokens[0]
|
|
28229
|
+
};
|
|
28230
|
+
} catch (error) {
|
|
28231
|
+
console.error("Error fetching TVL:", error);
|
|
28232
|
+
return {
|
|
28233
|
+
usdValue: 0,
|
|
28234
|
+
amount: new Web3Number("0", this.metadata.depositTokens[0].decimals),
|
|
28235
|
+
tokenInfo: this.metadata.depositTokens[0]
|
|
28236
|
+
};
|
|
28237
|
+
}
|
|
28238
|
+
}
|
|
28239
|
+
async depositCall(amountInfo, receiver) {
|
|
28240
|
+
const mainTokenContract = new import_starknet15.Contract({
|
|
28241
|
+
abi: erc20_abi_default,
|
|
28242
|
+
address: this.metadata.depositTokens[0].address.address,
|
|
28243
|
+
providerOrAccount: this.config.provider
|
|
28244
|
+
});
|
|
28245
|
+
const call1 = mainTokenContract.populate("approve", [
|
|
28246
|
+
this.address.address,
|
|
28247
|
+
import_starknet15.uint256.bnToUint256(amountInfo.amount.toWei())
|
|
28248
|
+
]);
|
|
28249
|
+
const call2 = this.contract.populate("deposit", [
|
|
28250
|
+
import_starknet15.uint256.bnToUint256(amountInfo.amount.toWei()),
|
|
28251
|
+
receiver.address
|
|
28252
|
+
]);
|
|
28253
|
+
const calls = [call1, call2];
|
|
28254
|
+
return calls;
|
|
28255
|
+
}
|
|
28256
|
+
async withdrawCall(amountInfo, receiver, owner) {
|
|
28257
|
+
const call = this.contract.populate("withdraw", [
|
|
28258
|
+
import_starknet15.uint256.bnToUint256(amountInfo.amount.toWei()),
|
|
28259
|
+
receiver.address,
|
|
28260
|
+
300
|
|
28261
|
+
// 3% max slippage
|
|
28262
|
+
]);
|
|
28263
|
+
return [call];
|
|
28264
|
+
}
|
|
28265
|
+
async getPositionInfo() {
|
|
28266
|
+
const CACHE_KEY = "positionInfo";
|
|
28267
|
+
const existingCacheData = this.getCache(CACHE_KEY);
|
|
28268
|
+
if (existingCacheData) return existingCacheData;
|
|
28269
|
+
const resp = await fetch(
|
|
28270
|
+
`${getTrovesEndpoint()}/vesu/positions?walletAddress=${this.address.address}`
|
|
28271
|
+
);
|
|
28272
|
+
const data = await resp.json();
|
|
28273
|
+
if (!data.data || data.data.length == 0) {
|
|
28274
|
+
throw new Error("No positions found");
|
|
28275
|
+
}
|
|
28276
|
+
const collateralXSTRK = Web3Number.fromWei(
|
|
28277
|
+
data.data[0].collateral.value,
|
|
28278
|
+
data.data[0].collateral.decimals
|
|
28279
|
+
);
|
|
28280
|
+
const collateralUSDValue = Web3Number.fromWei(
|
|
28281
|
+
data.data[0].collateral.usdPrice.value,
|
|
28282
|
+
data.data[0].collateral.usdPrice.decimals
|
|
28283
|
+
);
|
|
28284
|
+
const debtSTRK = Web3Number.fromWei(
|
|
28285
|
+
data.data[0].debt.value,
|
|
28286
|
+
data.data[0].debt.decimals
|
|
28287
|
+
);
|
|
28288
|
+
const debtUSDValue = Web3Number.fromWei(
|
|
28289
|
+
data.data[0].debt.usdPrice.value,
|
|
28290
|
+
data.data[0].debt.usdPrice.decimals
|
|
28291
|
+
);
|
|
28292
|
+
const xSTRKPrice = await this.getSecondaryTokenPriceRelativeToMain();
|
|
28293
|
+
const collateralInSTRK = Number(collateralXSTRK.toFixed(6)) * xSTRKPrice;
|
|
28294
|
+
const STRKUSDPrice = Number(debtUSDValue.toFixed(6)) / Number(debtSTRK.toFixed(6));
|
|
28295
|
+
const actualCollateralUSDValue = collateralInSTRK * STRKUSDPrice;
|
|
28296
|
+
const cacheData = {
|
|
28297
|
+
collateralXSTRK,
|
|
28298
|
+
collateralUSDValue: new Web3Number(
|
|
28299
|
+
actualCollateralUSDValue.toFixed(6),
|
|
28300
|
+
collateralUSDValue.decimals
|
|
28301
|
+
),
|
|
28302
|
+
debtSTRK,
|
|
28303
|
+
debtUSDValue,
|
|
28304
|
+
xSTRKPrice,
|
|
28305
|
+
collateralInSTRK
|
|
28306
|
+
};
|
|
28307
|
+
this.setCache(CACHE_KEY, cacheData);
|
|
28308
|
+
return cacheData;
|
|
28309
|
+
}
|
|
28310
|
+
async getSecondaryTokenPriceRelativeToMain(retry = 0) {
|
|
28311
|
+
const CACHE_KEY = "xSTRKPrice";
|
|
28312
|
+
const existingCacheData = this.getCache(CACHE_KEY);
|
|
28313
|
+
if (existingCacheData) return existingCacheData;
|
|
28314
|
+
const params = {
|
|
28315
|
+
sellTokenAddress: this.metadata.additionalInfo.secondaryToken.address.address,
|
|
28316
|
+
buyTokenAddress: this.metadata.additionalInfo.mainToken.address.address,
|
|
28317
|
+
sellAmount: BigInt(new Web3Number("1", 18).toWei()),
|
|
28318
|
+
takerAddress: this.address.address
|
|
28319
|
+
};
|
|
28320
|
+
logger.verbose("getSecondaryTokenPriceRelativeToMain [1]", params);
|
|
28321
|
+
let avnu = new AvnuWrapper();
|
|
28322
|
+
const quote = await avnu.getQuotes(
|
|
28323
|
+
params.sellTokenAddress,
|
|
28324
|
+
params.buyTokenAddress,
|
|
28325
|
+
params.sellAmount?.toString() || "0",
|
|
28326
|
+
params.takerAddress
|
|
28327
|
+
);
|
|
28328
|
+
if (!quote) {
|
|
28329
|
+
throw new Error("No quotes found to compute secondary token price relative to main token");
|
|
28330
|
+
}
|
|
28331
|
+
const firstQuote = quote;
|
|
28332
|
+
const price = Number(
|
|
28333
|
+
Web3Number.fromWei(firstQuote.buyAmount.toString(), 18).toFixed(
|
|
28334
|
+
6
|
|
28335
|
+
)
|
|
28336
|
+
);
|
|
28337
|
+
logger.verbose("getSecondaryTokenPriceRelativeToMain [2]", price);
|
|
28338
|
+
this.setCache(CACHE_KEY, price);
|
|
28339
|
+
return price;
|
|
28340
|
+
}
|
|
28341
|
+
async netAPY() {
|
|
28342
|
+
try {
|
|
28343
|
+
const { pools } = await VesuAdapter.getVesuPools();
|
|
28344
|
+
const re7PoolId = VesuPools.Re7xSTRK;
|
|
28345
|
+
const pool = pools.find(
|
|
28346
|
+
(p) => ContractAddr.from(import_starknet15.num.getHexString(p.id)).eq(re7PoolId)
|
|
28347
|
+
);
|
|
28348
|
+
if (!pool) {
|
|
28349
|
+
logger.warn(`${_SenseiVault.name}::netAPY - Re7 xSTRK pool not found`);
|
|
28350
|
+
return 0;
|
|
28351
|
+
}
|
|
28352
|
+
const mainSymbol = this.metadata.additionalInfo.mainToken.symbol.toLowerCase();
|
|
28353
|
+
const secondarySymbol = this.metadata.additionalInfo.secondaryToken.symbol.toLowerCase();
|
|
28354
|
+
const collateralAssetStats = pool.assets.find(
|
|
28355
|
+
(a) => String(a.symbol).toLowerCase() === secondarySymbol
|
|
28356
|
+
)?.stats;
|
|
28357
|
+
const debtAssetStats = pool.assets.find(
|
|
28358
|
+
(a) => String(a.symbol).toLowerCase() === mainSymbol
|
|
28359
|
+
)?.stats;
|
|
28360
|
+
if (!collateralAssetStats || !debtAssetStats) {
|
|
28361
|
+
logger.warn(
|
|
28362
|
+
`${_SenseiVault.name}::netAPY - Missing collateral/debt stats on Vesu pool`
|
|
28363
|
+
);
|
|
28364
|
+
return 0;
|
|
28365
|
+
}
|
|
28366
|
+
const xstrkSupplyAPY = Number(collateralAssetStats.supplyApy?.value || 0) / 1e18;
|
|
28367
|
+
const strkRewardsAPR = collateralAssetStats.defiSpringSupplyApr ? Number(collateralAssetStats.defiSpringSupplyApr.value || 0) / 1e18 : 0;
|
|
28368
|
+
const borrowAPY = Number(debtAssetStats.borrowApr?.value || 0) / 1e18;
|
|
28369
|
+
const lstAPY = await LSTAPRService.getLSTAPR(
|
|
28370
|
+
this.metadata.additionalInfo.mainToken.address
|
|
28371
|
+
);
|
|
28372
|
+
const collateralAPY = xstrkSupplyAPY + lstAPY + strkRewardsAPR;
|
|
28373
|
+
const feeFactor = this.metadata.additionalInfo.feeBps / 1e4;
|
|
28374
|
+
const feeAdjustedColAPY = collateralAPY - strkRewardsAPR * feeFactor;
|
|
28375
|
+
const { collateralUSDValue, debtUSDValue } = await this.getPositionInfo();
|
|
28376
|
+
const collateralUSD = Number(collateralUSDValue.toFixed(6));
|
|
28377
|
+
const debtUSD = Number(debtUSDValue.toFixed(6));
|
|
28378
|
+
const targetHf = this.metadata.additionalInfo.targetHfBps / 1e4;
|
|
28379
|
+
const xSTRKPrice = await this.getSecondaryTokenPriceRelativeToMain();
|
|
28380
|
+
const denominator = targetHf * xSTRKPrice - 0.87;
|
|
28381
|
+
if (denominator <= 0) {
|
|
28382
|
+
logger.warn(
|
|
28383
|
+
`${_SenseiVault.name}::netAPY - Invalid denominator in leverage calc`
|
|
28384
|
+
);
|
|
28385
|
+
return 0;
|
|
28386
|
+
}
|
|
28387
|
+
const borrowedSTRK = 0.87 * xSTRKPrice / denominator;
|
|
28388
|
+
const expectedLeverage = 1 + borrowedSTRK;
|
|
28389
|
+
if (!Number.isFinite(expectedLeverage) || expectedLeverage <= 0) {
|
|
28390
|
+
logger.warn(
|
|
28391
|
+
`${_SenseiVault.name}::netAPY - Non-positive or invalid expectedLeverage`
|
|
28392
|
+
);
|
|
28393
|
+
return 0;
|
|
28394
|
+
}
|
|
28395
|
+
const payoff = collateralUSD * feeAdjustedColAPY - debtUSD * borrowAPY;
|
|
28396
|
+
const investment = collateralUSD - debtUSD;
|
|
28397
|
+
if (investment === 0) {
|
|
28398
|
+
return 0;
|
|
28399
|
+
}
|
|
28400
|
+
const netAPY = payoff / investment;
|
|
28401
|
+
return Number.isFinite(netAPY) ? netAPY : 0;
|
|
28402
|
+
} catch (error) {
|
|
28403
|
+
logger.error(`${_SenseiVault.name}::netAPY - Error`, error);
|
|
28404
|
+
return 0;
|
|
28405
|
+
}
|
|
28406
|
+
}
|
|
28407
|
+
/**
|
|
28408
|
+
* Calculates user realized APY based on position growth accounting for deposits and withdrawals.
|
|
28409
|
+
* Returns the APY as a number.
|
|
28410
|
+
* Not implemented for Sensei Strategy yet.
|
|
28411
|
+
*/
|
|
28412
|
+
async getUserRealizedAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
|
|
28413
|
+
throw new Error("getUserRealizedAPY not implemented yet for Sensei strategy");
|
|
28414
|
+
}
|
|
28415
|
+
};
|
|
28416
|
+
var senseiDescription = `Deposit your {{token1}} to automatically loop your funds via Endur ({{token2}}) and Vesu to create a delta neutral position. This strategy is designed to maximize your yield on {{token1}}. Your position is automatically adjusted periodically to maintain a healthy health factor. You receive a NFT as representation for your stake on Troves. You can withdraw anytime by redeeming your NFT for {{token1}}.`;
|
|
28417
|
+
var vesuProtocol = {
|
|
28418
|
+
name: "Vesu",
|
|
28419
|
+
logo: "https://static-assets-8zct.onrender.com/integrations/vesu/logo.png"
|
|
28420
|
+
};
|
|
28421
|
+
var endurProtocol = {
|
|
28422
|
+
name: "Endur",
|
|
28423
|
+
logo: "https://app.endur.fi/logo.png"
|
|
28424
|
+
};
|
|
28425
|
+
var _riskFactor2 = [
|
|
28426
|
+
{ type: "Smart Contract Risk" /* SMART_CONTRACT_RISK */, value: 0.5, weight: 25, reason: "Audited by CSC" },
|
|
28427
|
+
{ type: "Depeg Risk" /* DEPEG_RISK */, value: 0.25, weight: 25, reason: "Depending on prevailing market conditions and trading activity, xSTRK may lose its peg to the underlying asset." },
|
|
28428
|
+
{ type: "Liquidation Risk" /* LIQUIDATION_RISK */, value: 0.1, weight: 10, reason: "Liquidation risk is low due to the nature of the Re7 Pool on Vesu" },
|
|
28429
|
+
{ type: "Low Liquidity Risk" /* LOW_LIQUIDITY_RISK */, value: 0.5, weight: 50, reason: "xSTRK can be sometimes illiquid near true price" }
|
|
28430
|
+
];
|
|
28431
|
+
var FAQS = [
|
|
28432
|
+
{
|
|
28433
|
+
question: "What is xSTRK Sensei?",
|
|
28434
|
+
answer: "xSTRK Sensei is a leveraged looping strategy involving xSTRK and STRK. It uses xSTRK as collateral on Vesu, borrows STRK, and buys more xSTRK with it to create up to 4x leverage and boost yields."
|
|
28435
|
+
},
|
|
28436
|
+
{
|
|
28437
|
+
question: "What is the benefit of using xSTRK Sensei?",
|
|
28438
|
+
answer: "The strategy amplifies your xSTRK exposure and yield through leverage. It also helps you accumulate more Endur points faster."
|
|
28439
|
+
},
|
|
28440
|
+
{
|
|
28441
|
+
question: "What is the maximum leverage possible?",
|
|
28442
|
+
answer: "The strategy may allow up to ~4x leverage, depending on your collateral ratio and market conditions on Vesu. This strategy tries to maintain a health factor of 1.1 on Vesu"
|
|
28443
|
+
},
|
|
28444
|
+
{
|
|
28445
|
+
question: "Isn't 1.1 health factor risky?",
|
|
28446
|
+
answer: "Based on Re7's xSTRK pool configuration on Vesu, xSTRK uses STRK price as its oracle source. This means collateral and debt will always move in the same direction, making 1.1 HF safe. However, if debt increases too much (over months), liquidation may occur, which we try to avoid by actively monitoring the position."
|
|
28447
|
+
},
|
|
28448
|
+
{
|
|
28449
|
+
question: "Are there any risks involved?",
|
|
28450
|
+
answer: "Yes. The major risks are related to xSTRK's illiquidity and price volatility. During volatility or low liquidity, exiting a position can result in loss."
|
|
28451
|
+
},
|
|
28452
|
+
{
|
|
28453
|
+
question: "Does the position always grow?",
|
|
28454
|
+
answer: "No. While xSTRK's true value increases over time, its DEX price may not grow continuously and can fluctuate or move in discrete steps."
|
|
28455
|
+
},
|
|
28456
|
+
{
|
|
28457
|
+
question: "Can I lose money using this strategy?",
|
|
28458
|
+
answer: "Yes. If the xSTRK price drops sharply or becomes illiquid, you may face slippage or loss when trying to exit the looped position."
|
|
28459
|
+
},
|
|
28460
|
+
{
|
|
28461
|
+
question: "What affects the DEX price of xSTRK?",
|
|
28462
|
+
answer: "xSTRK's DEX price depends on supply, demand, and liquidity. Unlike its true value which grows steadily, the DEX price can fluctuate due to market activity."
|
|
28463
|
+
},
|
|
28464
|
+
{
|
|
28465
|
+
question: "Why is xSTRK considered illiquid?",
|
|
28466
|
+
answer: "Since xSTRK is a evolving LST with limited trading volume, sudden large trades can cause high slippage, making it harder to enter or exit positions efficiently. Such conditions normalize over time. Enter and exit positions with caution."
|
|
28467
|
+
},
|
|
28468
|
+
{
|
|
28469
|
+
question: "Do I earn Endur points on looped xSTRK?",
|
|
28470
|
+
answer: "Yes. All xSTRK in the looped position contributes to your Endur points, allowing you to farm points more effectively with leverage. Visit endur.fi/leaderboard to see your points."
|
|
28471
|
+
}
|
|
28472
|
+
];
|
|
28473
|
+
var SenseiStrategies = [
|
|
28474
|
+
{
|
|
28475
|
+
id: "xstrk_sensei",
|
|
28476
|
+
name: "xSTRK Sensei",
|
|
28477
|
+
description: highlightTextWithLinks(
|
|
28478
|
+
senseiDescription.replace("{{token1}}", "STRK").replace("{{token2}}", "xSTRK"),
|
|
28479
|
+
[{
|
|
28480
|
+
highlight: "Endur",
|
|
28481
|
+
link: "https://endur.fi"
|
|
28482
|
+
}, {
|
|
28483
|
+
highlight: "Vesu",
|
|
28484
|
+
link: "https://vesu.xyz"
|
|
28485
|
+
}, {
|
|
28486
|
+
highlight: "delta neutral position",
|
|
28487
|
+
link: "https://www.investopedia.com/terms/d/deltaneutral.asp"
|
|
28488
|
+
}]
|
|
28489
|
+
),
|
|
28490
|
+
address: ContractAddr.from(
|
|
28491
|
+
"0x7023a5cadc8a5db80e4f0fde6b330cbd3c17bbbf9cb145cbabd7bd5e6fb7b0b"
|
|
28492
|
+
),
|
|
28493
|
+
launchBlock: 1053811,
|
|
28494
|
+
type: "Other",
|
|
28495
|
+
curator: {
|
|
28496
|
+
name: "Unwrap Labs",
|
|
28497
|
+
logo: "https://assets.troves.fi/integrations/unwraplabs/white.png"
|
|
28498
|
+
},
|
|
28499
|
+
vaultType: {
|
|
28500
|
+
type: "farming" /* FARMING */,
|
|
28501
|
+
description: "this is a yield farming vault"
|
|
28502
|
+
},
|
|
28503
|
+
depositTokens: [
|
|
28504
|
+
Global.getDefaultTokens().find((t) => t.symbol === "STRK")
|
|
28505
|
+
],
|
|
28506
|
+
protocols: [endurProtocol, vesuProtocol],
|
|
28507
|
+
settings: {
|
|
28508
|
+
maxTVL: new Web3Number("1500000", 18),
|
|
28509
|
+
alerts: [
|
|
28510
|
+
{
|
|
28511
|
+
type: "info",
|
|
28512
|
+
text: "Depeg-risk: If xSTRK price on DEXes deviates from expected price, you may lose money or may have to wait for the price to recover.",
|
|
28513
|
+
tab: "all"
|
|
28514
|
+
}
|
|
28515
|
+
],
|
|
28516
|
+
liveStatus: "Active" /* ACTIVE */,
|
|
28517
|
+
isPaused: false,
|
|
28518
|
+
isInMaintenance: false,
|
|
28519
|
+
isAudited: false,
|
|
28520
|
+
isInstantWithdrawal: true,
|
|
28521
|
+
isTransactionHistDisabled: true,
|
|
28522
|
+
quoteToken: Global.getDefaultTokens().find(
|
|
28523
|
+
(t) => t.symbol === "STRK"
|
|
28524
|
+
)
|
|
28525
|
+
},
|
|
28526
|
+
risk: {
|
|
28527
|
+
riskFactor: _riskFactor2,
|
|
28528
|
+
netRisk: _riskFactor2.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor2.reduce((acc, curr) => acc + curr.weight, 0),
|
|
28529
|
+
notARisks: getNoRiskTags(_riskFactor2)
|
|
28530
|
+
},
|
|
28531
|
+
additionalInfo: {
|
|
28532
|
+
mainToken: Global.getDefaultTokens().find((t) => t.symbol === "STRK"),
|
|
28533
|
+
secondaryToken: Global.getDefaultTokens().find((t) => t.symbol === "xSTRK"),
|
|
28534
|
+
targetHfBps: 11e3,
|
|
28535
|
+
// 1.1 health factor
|
|
28536
|
+
feeBps: 2e3
|
|
28537
|
+
// 2% fee on profits
|
|
28538
|
+
},
|
|
28539
|
+
faqs: FAQS,
|
|
28540
|
+
contractDetails: [],
|
|
28541
|
+
investmentSteps: [
|
|
28542
|
+
"Swap STRK for xSTRK",
|
|
28543
|
+
"Deposit xSTRK to Vesu's Re7 xSTRK Pool",
|
|
28544
|
+
"Borrow STRK against your xSTRK collateral",
|
|
28545
|
+
"Buy more xSTRK with borrowed STRK",
|
|
28546
|
+
"Repeat the process to loop your position",
|
|
28547
|
+
"Claim DeFi spring (STRK) rewards weekly and reinvest"
|
|
28548
|
+
],
|
|
28549
|
+
tags: ["Maxx" /* LEVERED */],
|
|
28550
|
+
security: {
|
|
28551
|
+
auditStatus: "Audited" /* AUDITED */,
|
|
28552
|
+
sourceCode: {
|
|
28553
|
+
type: "Closed Source" /* CLOSED_SOURCE */,
|
|
28554
|
+
contractLink: "https://github.com/trovesfi/troves-contracts"
|
|
28555
|
+
},
|
|
28556
|
+
accessControl: {
|
|
28557
|
+
type: "Standard Account" /* STANDARD_ACCOUNT */,
|
|
28558
|
+
addresses: [ContractAddr.from("0x0")],
|
|
28559
|
+
timeLock: "2 Days"
|
|
28560
|
+
}
|
|
28561
|
+
},
|
|
28562
|
+
redemptionInfo: {
|
|
28563
|
+
instantWithdrawalVault: "Yes" /* YES */
|
|
28564
|
+
}
|
|
28565
|
+
}
|
|
28566
|
+
];
|
|
28567
|
+
|
|
28568
|
+
// src/strategies/universal-adapters/common-adapter.ts
|
|
28569
|
+
var import_starknet16 = require("starknet");
|
|
28570
|
+
var CommonAdapter = class extends BaseAdapter {
|
|
28571
|
+
constructor(config) {
|
|
28572
|
+
super();
|
|
28573
|
+
this.config = config;
|
|
28574
|
+
}
|
|
28575
|
+
getFlashloanAdapter() {
|
|
28576
|
+
const manageCall = this.getFlashloanCall.bind(this)({ amount: Web3Number.fromWei("0", 6), data: [] });
|
|
28577
|
+
const packedArguments = [
|
|
28578
|
+
this.config.manager.toBigInt(),
|
|
28579
|
+
// receiver
|
|
28580
|
+
this.config.asset.toBigInt(),
|
|
28581
|
+
// asset
|
|
28582
|
+
toBigInt(0)
|
|
28583
|
+
// is legacy false
|
|
28584
|
+
];
|
|
28585
|
+
const leaf = this.constructSimpleLeafData({
|
|
28586
|
+
id: this.config.id,
|
|
28587
|
+
target: manageCall.call.contractAddress,
|
|
28588
|
+
method: "flash_loan",
|
|
28589
|
+
packedArguments
|
|
28590
|
+
});
|
|
28591
|
+
return { leaf, callConstructor: this.getFlashloanCall.bind(this) };
|
|
28592
|
+
}
|
|
28593
|
+
getFlashloanCall(params) {
|
|
28594
|
+
const uint256Amount = import_starknet16.uint256.bnToUint256(params.amount.toWei());
|
|
28595
|
+
return {
|
|
28596
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
28597
|
+
call: {
|
|
28598
|
+
contractAddress: this.config.manager,
|
|
28599
|
+
selector: import_starknet16.hash.getSelectorFromName("flash_loan"),
|
|
28600
|
+
calldata: [
|
|
28601
|
+
this.config.manager.toBigInt(),
|
|
28602
|
+
// receiver
|
|
28603
|
+
this.config.asset.toBigInt(),
|
|
28604
|
+
// asset
|
|
28605
|
+
toBigInt(uint256Amount.low.toString()),
|
|
28606
|
+
// amount low
|
|
28607
|
+
toBigInt(uint256Amount.high.toString()),
|
|
28608
|
+
// amount high
|
|
28609
|
+
toBigInt(0),
|
|
28610
|
+
// is legacy false
|
|
28611
|
+
BigInt(params.data.length),
|
|
28612
|
+
...params.data
|
|
28613
|
+
]
|
|
28614
|
+
}
|
|
28615
|
+
};
|
|
28616
|
+
}
|
|
28617
|
+
getApproveAdapter(token, spender, id) {
|
|
28618
|
+
return () => ({
|
|
28619
|
+
leaf: this.constructSimpleLeafData({
|
|
28620
|
+
id,
|
|
28621
|
+
target: token,
|
|
28622
|
+
method: "approve",
|
|
28623
|
+
packedArguments: [
|
|
28624
|
+
spender.toBigInt()
|
|
28625
|
+
// spender
|
|
28626
|
+
]
|
|
28627
|
+
}),
|
|
28628
|
+
callConstructor: this.getApproveCall(token, spender).bind(this)
|
|
28629
|
+
});
|
|
28630
|
+
}
|
|
28631
|
+
getApproveCall(token, spender) {
|
|
28632
|
+
return (params) => {
|
|
28633
|
+
const uint256Amount = import_starknet16.uint256.bnToUint256(params.amount.toWei());
|
|
28634
|
+
return {
|
|
28635
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
28636
|
+
call: {
|
|
28637
|
+
contractAddress: token,
|
|
28638
|
+
selector: import_starknet16.hash.getSelectorFromName("approve"),
|
|
28639
|
+
calldata: [
|
|
28640
|
+
spender.toBigInt(),
|
|
28641
|
+
// spender
|
|
28642
|
+
toBigInt(uint256Amount.low.toString()),
|
|
28643
|
+
// amount low
|
|
28644
|
+
toBigInt(uint256Amount.high.toString())
|
|
28645
|
+
// amount high
|
|
28646
|
+
]
|
|
28647
|
+
}
|
|
28648
|
+
};
|
|
28649
|
+
};
|
|
28650
|
+
}
|
|
28651
|
+
getBringLiquidityAdapter(id) {
|
|
28652
|
+
return () => ({
|
|
28653
|
+
leaf: this.constructSimpleLeafData({
|
|
28654
|
+
id,
|
|
28655
|
+
target: this.config.vaultAddress,
|
|
28656
|
+
method: "bring_liquidity",
|
|
28657
|
+
packedArguments: []
|
|
28658
|
+
}),
|
|
28659
|
+
callConstructor: this.getBringLiquidityCall().bind(this)
|
|
28660
|
+
});
|
|
28661
|
+
}
|
|
28662
|
+
getBringLiquidityCall() {
|
|
28663
|
+
return (params) => {
|
|
28664
|
+
const uint256Amount = import_starknet16.uint256.bnToUint256(params.amount.toWei());
|
|
28665
|
+
return {
|
|
28666
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
28667
|
+
call: {
|
|
28668
|
+
contractAddress: this.config.vaultAddress,
|
|
28669
|
+
selector: import_starknet16.hash.getSelectorFromName("bring_liquidity"),
|
|
28670
|
+
calldata: [
|
|
28671
|
+
toBigInt(uint256Amount.low.toString()),
|
|
28672
|
+
// amount low
|
|
28673
|
+
toBigInt(uint256Amount.high.toString())
|
|
28674
|
+
// amount high
|
|
28675
|
+
]
|
|
28676
|
+
}
|
|
28677
|
+
};
|
|
28678
|
+
};
|
|
28679
|
+
}
|
|
28680
|
+
getAvnuAdapter(fromToken, toToken, id, isMiddleware) {
|
|
28681
|
+
return () => ({
|
|
28682
|
+
leaf: this.constructSimpleLeafData({
|
|
28683
|
+
id,
|
|
28684
|
+
target: isMiddleware ? AVNU_MIDDLEWARE : AVNU_EXCHANGE,
|
|
28685
|
+
method: "multi_route_swap",
|
|
28686
|
+
packedArguments: [
|
|
28687
|
+
fromToken.toBigInt(),
|
|
28688
|
+
toToken.toBigInt(),
|
|
28689
|
+
this.config.vaultAllocator.toBigInt()
|
|
28690
|
+
]
|
|
28691
|
+
}),
|
|
28692
|
+
callConstructor: this.getAvnuCall(fromToken, toToken, isMiddleware).bind(this)
|
|
28693
|
+
});
|
|
28694
|
+
}
|
|
28695
|
+
getAvnuCall(fromToken, toToken, isMiddleware) {
|
|
28696
|
+
return (params) => {
|
|
28697
|
+
return {
|
|
28698
|
+
sanitizer: SIMPLE_SANITIZER,
|
|
28699
|
+
call: {
|
|
28700
|
+
contractAddress: isMiddleware ? AVNU_MIDDLEWARE : AVNU_EXCHANGE,
|
|
28701
|
+
selector: import_starknet16.hash.getSelectorFromName("multi_route_swap"),
|
|
28702
|
+
calldata: [
|
|
28703
|
+
fromToken.toBigInt(),
|
|
28704
|
+
// sell_token_address
|
|
28705
|
+
toBigInt(params.props.token_from_amount.low.toString()),
|
|
28706
|
+
// sell_token_amount low
|
|
28707
|
+
toBigInt(params.props.token_from_amount.high.toString()),
|
|
28708
|
+
// sell_token_amount high
|
|
28709
|
+
toToken.toBigInt(),
|
|
28710
|
+
// buy_token_address
|
|
28711
|
+
toBigInt(params.props.token_to_amount.low.toString()),
|
|
28712
|
+
// buy_token_amount low
|
|
28713
|
+
toBigInt(params.props.token_to_amount.high.toString()),
|
|
28714
|
+
// buy_token_amount high
|
|
28715
|
+
toBigInt(params.props.token_to_min_amount.low.toString()),
|
|
28716
|
+
// buy_token_min_amount low
|
|
28717
|
+
toBigInt(params.props.token_to_min_amount.high.toString()),
|
|
28718
|
+
// buy_token_min_amount high
|
|
28719
|
+
this.config.vaultAllocator.toBigInt(),
|
|
28720
|
+
// beneficiary
|
|
28721
|
+
toBigInt(0),
|
|
28722
|
+
// integrator_fee_amount_bps
|
|
28723
|
+
this.config.vaultAllocator.toBigInt(),
|
|
28724
|
+
// integrator_fee_recipient
|
|
28725
|
+
// unpack routes
|
|
28726
|
+
BigInt(params.props.routes.length),
|
|
28727
|
+
...params.props.routes.map((r) => [
|
|
28728
|
+
BigInt(import_starknet16.num.hexToDecimalString(r.token_from)),
|
|
28729
|
+
BigInt(import_starknet16.num.hexToDecimalString(r.token_to)),
|
|
28730
|
+
BigInt(import_starknet16.num.hexToDecimalString(r.exchange_address)),
|
|
28731
|
+
BigInt(r.percent),
|
|
28732
|
+
BigInt(r.additional_swap_params.length),
|
|
28733
|
+
...r.additional_swap_params.map((p) => BigInt(import_starknet16.num.hexToDecimalString(p)))
|
|
28734
|
+
]).flat()
|
|
28735
|
+
]
|
|
28736
|
+
}
|
|
28737
|
+
};
|
|
28738
|
+
};
|
|
28739
|
+
}
|
|
28740
|
+
};
|
|
28741
|
+
|
|
28173
28742
|
// src/strategies/universal-strategy.tsx
|
|
28174
28743
|
var import_starknet17 = require("starknet");
|
|
28175
28744
|
|
|
@@ -30756,7 +31325,6 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
|
|
|
30756
31325
|
const lastReportTime = await this.contract.call("last_report_timestamp", []);
|
|
30757
31326
|
const netAPY = await this.netAPY();
|
|
30758
31327
|
const defispringAPY = (netAPY.splits.find((s) => s.id === "defispring")?.apy || 0) * 0.8;
|
|
30759
|
-
if (!defispringAPY) throw new Error("DefiSpring APY not found");
|
|
30760
31328
|
const timeDiff = Math.round(Date.now() / 1e3) - Number(lastReportTime);
|
|
30761
31329
|
const growthRate = timeDiff * defispringAPY / (365 * 24 * 60 * 60);
|
|
30762
31330
|
const rewardAssets = prevAum.multipliedBy(growthRate);
|
|
@@ -31164,8 +31732,8 @@ var usdcVaultSettings = {
|
|
|
31164
31732
|
aumOracle: ContractAddr.from("0x6faf45ed185dec13ef723c9ead4266cab98d06f2cb237e331b1fa5c2aa79afe"),
|
|
31165
31733
|
leafAdapters: [],
|
|
31166
31734
|
adapters: [],
|
|
31167
|
-
targetHealthFactor: 1.
|
|
31168
|
-
minHealthFactor: 1.
|
|
31735
|
+
targetHealthFactor: 1.25,
|
|
31736
|
+
minHealthFactor: 1.15
|
|
31169
31737
|
};
|
|
31170
31738
|
var wbtcVaultSettings = {
|
|
31171
31739
|
vaultAddress: ContractAddr.from("0x5a4c1651b913aa2ea7afd9024911603152a19058624c3e425405370d62bf80c"),
|
|
@@ -31175,8 +31743,8 @@ var wbtcVaultSettings = {
|
|
|
31175
31743
|
aumOracle: ContractAddr.from("0x2edf4edbed3f839e7f07dcd913e92299898ff4cf0ba532f8c572c66c5b331b2"),
|
|
31176
31744
|
leafAdapters: [],
|
|
31177
31745
|
adapters: [],
|
|
31178
|
-
targetHealthFactor: 1.
|
|
31179
|
-
minHealthFactor: 1.
|
|
31746
|
+
targetHealthFactor: 1.2,
|
|
31747
|
+
minHealthFactor: 1.15
|
|
31180
31748
|
};
|
|
31181
31749
|
var ethVaultSettings = {
|
|
31182
31750
|
vaultAddress: ContractAddr.from("0x446c22d4d3f5cb52b4950ba832ba1df99464c6673a37c092b1d9622650dbd8"),
|
|
@@ -31186,8 +31754,8 @@ var ethVaultSettings = {
|
|
|
31186
31754
|
aumOracle: ContractAddr.from("0x4b747f2e75c057bed9aa2ce46fbdc2159dc684c15bd32d4f95983a6ecf39a05"),
|
|
31187
31755
|
leafAdapters: [],
|
|
31188
31756
|
adapters: [],
|
|
31189
|
-
targetHealthFactor: 1.
|
|
31190
|
-
minHealthFactor: 1.
|
|
31757
|
+
targetHealthFactor: 1.25,
|
|
31758
|
+
minHealthFactor: 1.21
|
|
31191
31759
|
};
|
|
31192
31760
|
var strkVaultSettings = {
|
|
31193
31761
|
vaultAddress: ContractAddr.from("0x55d012f57e58c96e0a5c7ebbe55853989d01e6538b15a95e7178aca4af05c21"),
|
|
@@ -31197,8 +31765,8 @@ var strkVaultSettings = {
|
|
|
31197
31765
|
aumOracle: ContractAddr.from("0x6d7dbfad4bb51715da211468389a623da00c0625f8f6efbea822ee5ac5231f4"),
|
|
31198
31766
|
leafAdapters: [],
|
|
31199
31767
|
adapters: [],
|
|
31200
|
-
targetHealthFactor: 1.
|
|
31201
|
-
minHealthFactor: 1.
|
|
31768
|
+
targetHealthFactor: 1.2,
|
|
31769
|
+
minHealthFactor: 1.15
|
|
31202
31770
|
};
|
|
31203
31771
|
var usdtVaultSettings = {
|
|
31204
31772
|
vaultAddress: ContractAddr.from("0x1c4933d1880c6778585e597154eaca7b428579d72f3aae425ad2e4d26c6bb3"),
|
|
@@ -31208,8 +31776,8 @@ var usdtVaultSettings = {
|
|
|
31208
31776
|
aumOracle: ContractAddr.from("0x7018f8040c8066a4ab929e6760ae52dd43b6a3a289172f514750a61fcc565cc"),
|
|
31209
31777
|
leafAdapters: [],
|
|
31210
31778
|
adapters: [],
|
|
31211
|
-
targetHealthFactor: 1.
|
|
31212
|
-
minHealthFactor: 1.
|
|
31779
|
+
targetHealthFactor: 1.25,
|
|
31780
|
+
minHealthFactor: 1.15
|
|
31213
31781
|
};
|
|
31214
31782
|
function MetaVaultDescription(allowedSources) {
|
|
31215
31783
|
const logos = {
|
|
@@ -31249,7 +31817,7 @@ function MetaVaultDescription(allowedSources) {
|
|
|
31249
31817
|
};
|
|
31250
31818
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: containerStyle, children: [
|
|
31251
31819
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { style: { fontSize: "18px", marginBottom: "10px" }, children: "Meta Vault \u2014 Automated Yield Router" }),
|
|
31252
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }, children: "This Evergreen vault is a tokenized Meta Vault, auto-compounding strategy that continuously allocates your deposited
|
|
31820
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }, children: "This Evergreen vault is a tokenized Meta Vault, auto-compounding strategy that continuously allocates your deposited represent a proportional claim on the underlying assets and accrued yield. Allocation shifts are handled programmatically based on on-chain signals and risk filters, minimizing idle capital and maximizing net APY." }),
|
|
31253
31821
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { style: { fontSize: "13px", color: "#ccc" }, children: [
|
|
31254
31822
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: "Withdrawals:" }),
|
|
31255
31823
|
" Requests can take up to ",
|
|
@@ -31346,6 +31914,30 @@ var investmentSteps = [
|
|
|
31346
31914
|
"Request withdrawal and vault manager processes it in 1-2 hours"
|
|
31347
31915
|
];
|
|
31348
31916
|
var AUDIT_URL3 = "https://docs.troves.fi/p/security#starknet-vault-kit";
|
|
31917
|
+
var getUniversalRisk = () => ({
|
|
31918
|
+
riskFactor: _riskFactor3,
|
|
31919
|
+
netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
|
|
31920
|
+
notARisks: getNoRiskTags(_riskFactor3)
|
|
31921
|
+
});
|
|
31922
|
+
var createUniversalSettings = (tokenSymbol, maxTVLDecimals) => ({
|
|
31923
|
+
maxTVL: Web3Number.fromWei(0, maxTVLDecimals),
|
|
31924
|
+
isAudited: true,
|
|
31925
|
+
liveStatus: "Active" /* ACTIVE */,
|
|
31926
|
+
isPaused: false,
|
|
31927
|
+
isInstantWithdrawal: false,
|
|
31928
|
+
hideHarvestInfo: true,
|
|
31929
|
+
quoteToken: Global.getDefaultTokens().find(
|
|
31930
|
+
(token) => token.symbol === tokenSymbol
|
|
31931
|
+
),
|
|
31932
|
+
alerts: [
|
|
31933
|
+
{
|
|
31934
|
+
tab: "withdraw",
|
|
31935
|
+
text: "On withdrawal, you will receive an NFT representing your withdrawal request. The funds will be automatically sent to your wallet (NFT owner) in 1-2 hours. You can monitor the status in transactions tab.",
|
|
31936
|
+
type: "info"
|
|
31937
|
+
}
|
|
31938
|
+
],
|
|
31939
|
+
showWithdrawalWarningModal: true
|
|
31940
|
+
});
|
|
31349
31941
|
var EVERGREEN_SECURITY = {
|
|
31350
31942
|
auditStatus: "Audited" /* AUDITED */,
|
|
31351
31943
|
sourceCode: {
|
|
@@ -31366,127 +31958,93 @@ var EVERGREEN_REDEMPTION_INFO = {
|
|
|
31366
31958
|
above10M: "2-3 Days"
|
|
31367
31959
|
}
|
|
31368
31960
|
};
|
|
31961
|
+
var createUniversalStrategy = (params) => ({
|
|
31962
|
+
id: `evergreen_${params.tokenSymbol.toLowerCase()}`,
|
|
31963
|
+
name: `${params.tokenSymbol} Evergreen`,
|
|
31964
|
+
description: getDescription(params.tokenSymbol, params.allowedSources),
|
|
31965
|
+
address: ContractAddr.from(params.address),
|
|
31966
|
+
launchBlock: 0,
|
|
31967
|
+
type: "ERC4626",
|
|
31968
|
+
vaultType: {
|
|
31969
|
+
type: "farming" /* FARMING */,
|
|
31970
|
+
description: "this is a yield farming vault"
|
|
31971
|
+
},
|
|
31972
|
+
depositTokens: [
|
|
31973
|
+
Global.getDefaultTokens().find((token) => token.symbol === params.tokenSymbol)
|
|
31974
|
+
],
|
|
31975
|
+
additionalInfo: getLooperSettings(
|
|
31976
|
+
params.token1Symbol,
|
|
31977
|
+
params.token2Symbol,
|
|
31978
|
+
params.vaultSettings,
|
|
31979
|
+
VesuPools.Genesis,
|
|
31980
|
+
VesuPools.Genesis
|
|
31981
|
+
),
|
|
31982
|
+
risk: getUniversalRisk(),
|
|
31983
|
+
auditUrl: AUDIT_URL3,
|
|
31984
|
+
protocols: [Protocols.VESU],
|
|
31985
|
+
curator: {
|
|
31986
|
+
name: "Unwrap Labs",
|
|
31987
|
+
logo: "https://assets.troves.fi/integrations/unwraplabs/white.png"
|
|
31988
|
+
},
|
|
31989
|
+
settings: createUniversalSettings(params.tokenSymbol, params.maxTVLDecimals),
|
|
31990
|
+
contractDetails: getContractDetails(params.vaultSettings),
|
|
31991
|
+
faqs: getFAQs(),
|
|
31992
|
+
investmentSteps,
|
|
31993
|
+
tags: params.tags,
|
|
31994
|
+
security: EVERGREEN_SECURITY,
|
|
31995
|
+
redemptionInfo: EVERGREEN_REDEMPTION_INFO
|
|
31996
|
+
});
|
|
31369
31997
|
var UniversalStrategies = [
|
|
31370
|
-
{
|
|
31371
|
-
|
|
31372
|
-
|
|
31373
|
-
|
|
31374
|
-
|
|
31375
|
-
|
|
31376
|
-
|
|
31377
|
-
|
|
31378
|
-
|
|
31379
|
-
|
|
31380
|
-
|
|
31381
|
-
|
|
31382
|
-
|
|
31383
|
-
|
|
31384
|
-
|
|
31385
|
-
|
|
31386
|
-
|
|
31387
|
-
|
|
31388
|
-
|
|
31389
|
-
|
|
31390
|
-
|
|
31391
|
-
|
|
31392
|
-
|
|
31393
|
-
|
|
31394
|
-
|
|
31395
|
-
|
|
31396
|
-
|
|
31397
|
-
|
|
31398
|
-
|
|
31399
|
-
|
|
31400
|
-
|
|
31401
|
-
|
|
31402
|
-
|
|
31403
|
-
|
|
31404
|
-
|
|
31405
|
-
|
|
31406
|
-
|
|
31407
|
-
|
|
31408
|
-
|
|
31409
|
-
|
|
31410
|
-
|
|
31411
|
-
|
|
31412
|
-
|
|
31413
|
-
|
|
31414
|
-
|
|
31415
|
-
|
|
31416
|
-
|
|
31417
|
-
|
|
31418
|
-
|
|
31419
|
-
|
|
31420
|
-
description: getDescription("ETH", ["vesu", "extended"]),
|
|
31421
|
-
address: ContractAddr.from("0x446c22d4d3f5cb52b4950ba832ba1df99464c6673a37c092b1d9622650dbd8"),
|
|
31422
|
-
launchBlock: 0,
|
|
31423
|
-
type: "ERC4626",
|
|
31424
|
-
depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === "ETH")],
|
|
31425
|
-
additionalInfo: getLooperSettings("ETH", "WBTC", ethVaultSettings, VesuPools.Genesis, VesuPools.Genesis),
|
|
31426
|
-
risk: {
|
|
31427
|
-
riskFactor: _riskFactor3,
|
|
31428
|
-
netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
|
|
31429
|
-
notARisks: getNoRiskTags(_riskFactor3)
|
|
31430
|
-
},
|
|
31431
|
-
protocols: [Protocols.VESU],
|
|
31432
|
-
maxTVL: Web3Number.fromWei(0, 18),
|
|
31433
|
-
contractDetails: getContractDetails(ethVaultSettings),
|
|
31434
|
-
faqs: getFAQs(),
|
|
31435
|
-
investmentSteps,
|
|
31436
|
-
auditUrl: AUDIT_URL3,
|
|
31437
|
-
category: "meta-vaults" /* META_VAULTS */,
|
|
31438
|
-
tags: ["Evergreen" /* EVERGREEN */],
|
|
31439
|
-
security: EVERGREEN_SECURITY,
|
|
31440
|
-
redemptionInfo: EVERGREEN_REDEMPTION_INFO
|
|
31441
|
-
},
|
|
31442
|
-
{
|
|
31443
|
-
name: "STRK Evergreen",
|
|
31444
|
-
description: getDescription("STRK", ["vesu", "endur", "extended"]),
|
|
31445
|
-
address: ContractAddr.from("0x55d012f57e58c96e0a5c7ebbe55853989d01e6538b15a95e7178aca4af05c21"),
|
|
31446
|
-
launchBlock: 0,
|
|
31447
|
-
type: "ERC4626",
|
|
31448
|
-
depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === "STRK")],
|
|
31449
|
-
additionalInfo: getLooperSettings("STRK", "ETH", strkVaultSettings, VesuPools.Genesis, VesuPools.Genesis),
|
|
31450
|
-
risk: {
|
|
31451
|
-
riskFactor: _riskFactor3,
|
|
31452
|
-
netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
|
|
31453
|
-
notARisks: getNoRiskTags(_riskFactor3)
|
|
31454
|
-
},
|
|
31455
|
-
protocols: [Protocols.VESU],
|
|
31456
|
-
maxTVL: Web3Number.fromWei(0, 18),
|
|
31457
|
-
contractDetails: getContractDetails(strkVaultSettings),
|
|
31458
|
-
faqs: getFAQs(),
|
|
31459
|
-
investmentSteps,
|
|
31460
|
-
auditUrl: AUDIT_URL3,
|
|
31461
|
-
category: "meta-vaults" /* META_VAULTS */,
|
|
31462
|
-
tags: ["Evergreen" /* EVERGREEN */],
|
|
31463
|
-
security: EVERGREEN_SECURITY,
|
|
31464
|
-
redemptionInfo: EVERGREEN_REDEMPTION_INFO
|
|
31465
|
-
},
|
|
31466
|
-
{
|
|
31467
|
-
name: "USDT Evergreen",
|
|
31468
|
-
description: getDescription("USDT", ["vesu"]),
|
|
31469
|
-
address: ContractAddr.from("0x1c4933d1880c6778585e597154eaca7b428579d72f3aae425ad2e4d26c6bb3"),
|
|
31470
|
-
launchBlock: 0,
|
|
31471
|
-
type: "ERC4626",
|
|
31472
|
-
depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === "USDT")],
|
|
31473
|
-
additionalInfo: getLooperSettings("USDT", "ETH", usdtVaultSettings, VesuPools.Genesis, VesuPools.Genesis),
|
|
31474
|
-
risk: {
|
|
31475
|
-
riskFactor: _riskFactor3,
|
|
31476
|
-
netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
|
|
31477
|
-
notARisks: getNoRiskTags(_riskFactor3)
|
|
31478
|
-
},
|
|
31479
|
-
protocols: [Protocols.VESU],
|
|
31480
|
-
maxTVL: Web3Number.fromWei(0, 6),
|
|
31481
|
-
contractDetails: getContractDetails(usdtVaultSettings),
|
|
31482
|
-
faqs: getFAQs(),
|
|
31483
|
-
investmentSteps,
|
|
31484
|
-
auditUrl: AUDIT_URL3,
|
|
31485
|
-
category: "meta-vaults" /* META_VAULTS */,
|
|
31486
|
-
tags: ["Evergreen" /* EVERGREEN */],
|
|
31487
|
-
security: EVERGREEN_SECURITY,
|
|
31488
|
-
redemptionInfo: EVERGREEN_REDEMPTION_INFO
|
|
31489
|
-
}
|
|
31998
|
+
createUniversalStrategy({
|
|
31999
|
+
tokenSymbol: "USDC.e",
|
|
32000
|
+
address: "0x7e6498cf6a1bfc7e6fc89f1831865e2dacb9756def4ec4b031a9138788a3b5e",
|
|
32001
|
+
vaultSettings: usdcVaultSettings,
|
|
32002
|
+
token1Symbol: "USDC.e",
|
|
32003
|
+
token2Symbol: "ETH",
|
|
32004
|
+
maxTVLDecimals: 6,
|
|
32005
|
+
allowedSources: ["vesu", "extended"],
|
|
32006
|
+
tags: ["Meta Vaults" /* META_VAULT */]
|
|
32007
|
+
}),
|
|
32008
|
+
createUniversalStrategy({
|
|
32009
|
+
tokenSymbol: "WBTC",
|
|
32010
|
+
address: "0x5a4c1651b913aa2ea7afd9024911603152a19058624c3e425405370d62bf80c",
|
|
32011
|
+
vaultSettings: wbtcVaultSettings,
|
|
32012
|
+
token1Symbol: "WBTC",
|
|
32013
|
+
token2Symbol: "ETH",
|
|
32014
|
+
maxTVLDecimals: 8,
|
|
32015
|
+
allowedSources: ["vesu", "endur", "extended"],
|
|
32016
|
+
tags: ["BTC" /* BTC */, "Meta Vaults" /* META_VAULT */]
|
|
32017
|
+
}),
|
|
32018
|
+
createUniversalStrategy({
|
|
32019
|
+
tokenSymbol: "ETH",
|
|
32020
|
+
address: "0x446c22d4d3f5cb52b4950ba832ba1df99464c6673a37c092b1d9622650dbd8",
|
|
32021
|
+
vaultSettings: ethVaultSettings,
|
|
32022
|
+
token1Symbol: "ETH",
|
|
32023
|
+
token2Symbol: "WBTC",
|
|
32024
|
+
maxTVLDecimals: 18,
|
|
32025
|
+
allowedSources: ["vesu", "extended"],
|
|
32026
|
+
tags: ["Meta Vaults" /* META_VAULT */]
|
|
32027
|
+
}),
|
|
32028
|
+
createUniversalStrategy({
|
|
32029
|
+
tokenSymbol: "STRK",
|
|
32030
|
+
address: "0x55d012f57e58c96e0a5c7ebbe55853989d01e6538b15a95e7178aca4af05c21",
|
|
32031
|
+
vaultSettings: strkVaultSettings,
|
|
32032
|
+
token1Symbol: "STRK",
|
|
32033
|
+
token2Symbol: "ETH",
|
|
32034
|
+
maxTVLDecimals: 18,
|
|
32035
|
+
allowedSources: ["vesu", "endur", "extended"],
|
|
32036
|
+
tags: ["Meta Vaults" /* META_VAULT */]
|
|
32037
|
+
}),
|
|
32038
|
+
createUniversalStrategy({
|
|
32039
|
+
tokenSymbol: "USDT",
|
|
32040
|
+
address: "0x1c4933d1880c6778585e597154eaca7b428579d72f3aae425ad2e4d26c6bb3",
|
|
32041
|
+
vaultSettings: usdtVaultSettings,
|
|
32042
|
+
token1Symbol: "USDT",
|
|
32043
|
+
token2Symbol: "ETH",
|
|
32044
|
+
maxTVLDecimals: 6,
|
|
32045
|
+
allowedSources: ["vesu"],
|
|
32046
|
+
tags: ["Meta Vaults" /* META_VAULT */]
|
|
32047
|
+
})
|
|
31490
32048
|
];
|
|
31491
32049
|
|
|
31492
32050
|
// src/strategies/universal-lst-muliplier-strategy.tsx
|
|
@@ -31541,14 +32099,14 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31541
32099
|
}
|
|
31542
32100
|
}
|
|
31543
32101
|
asset() {
|
|
31544
|
-
return this.getVesuSameTokenAdapter().config.collateral;
|
|
32102
|
+
return this.getVesuSameTokenAdapter(this.metadata.additionalInfo.defaultPoolId).config.collateral;
|
|
31545
32103
|
}
|
|
31546
32104
|
getTag() {
|
|
31547
32105
|
return `${_UniversalLstMultiplierStrategy.name}:${this.metadata.name}`;
|
|
31548
32106
|
}
|
|
31549
32107
|
// Vesu adapter with LST and base token match
|
|
31550
|
-
getVesuSameTokenAdapter() {
|
|
31551
|
-
const baseAdapter = this.getAdapter(getVesuLegId("vesu_leg1" /* VESU_LEG1 */, this.metadata.additionalInfo.underlyingToken.symbol));
|
|
32108
|
+
getVesuSameTokenAdapter(poolId) {
|
|
32109
|
+
const baseAdapter = this.getAdapter(getVesuLegId("vesu_leg1" /* VESU_LEG1 */, this.metadata.additionalInfo.underlyingToken.symbol, poolId.toString()));
|
|
31552
32110
|
baseAdapter.networkConfig = this.config;
|
|
31553
32111
|
baseAdapter.pricer = this.pricer;
|
|
31554
32112
|
return baseAdapter;
|
|
@@ -31557,18 +32115,20 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31557
32115
|
// todo support lending assets of underlying as well (like if xSTRK looping is not viable, simply supply STRK)
|
|
31558
32116
|
getVesuAdapters() {
|
|
31559
32117
|
const adapters = [];
|
|
31560
|
-
const
|
|
31561
|
-
|
|
31562
|
-
const
|
|
31563
|
-
|
|
31564
|
-
|
|
31565
|
-
|
|
31566
|
-
|
|
31567
|
-
|
|
31568
|
-
|
|
31569
|
-
|
|
31570
|
-
|
|
31571
|
-
|
|
32118
|
+
for (const poolId of [this.metadata.additionalInfo.defaultPoolId, ...this.metadata.additionalInfo.altSupportedPoolIds]) {
|
|
32119
|
+
const baseAdapter = this.getVesuSameTokenAdapter(poolId);
|
|
32120
|
+
for (const asset of this.metadata.additionalInfo.borrowable_assets) {
|
|
32121
|
+
const vesuAdapter1 = new VesuAdapter({
|
|
32122
|
+
poolId: baseAdapter.config.poolId,
|
|
32123
|
+
collateral: this.asset(),
|
|
32124
|
+
debt: asset,
|
|
32125
|
+
vaultAllocator: this.metadata.additionalInfo.vaultAllocator,
|
|
32126
|
+
id: ""
|
|
32127
|
+
});
|
|
32128
|
+
vesuAdapter1.pricer = this.pricer;
|
|
32129
|
+
vesuAdapter1.networkConfig = this.config;
|
|
32130
|
+
adapters.push(vesuAdapter1);
|
|
32131
|
+
}
|
|
31572
32132
|
}
|
|
31573
32133
|
return adapters;
|
|
31574
32134
|
}
|
|
@@ -31689,7 +32249,8 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31689
32249
|
const debtAmountInLST = debtAmount.abs().dividedBy(lstDEXPrice);
|
|
31690
32250
|
const calls = await this.getVesuMultiplyCall({
|
|
31691
32251
|
isDeposit: false,
|
|
31692
|
-
leg1DepositAmount: debtAmountInLST
|
|
32252
|
+
leg1DepositAmount: debtAmountInLST,
|
|
32253
|
+
poolId: vesuAdapter.config.poolId
|
|
31693
32254
|
});
|
|
31694
32255
|
assert(calls.length == 1, `Expected 1 call for unwind, got ${calls.length}`);
|
|
31695
32256
|
return calls[0];
|
|
@@ -31700,7 +32261,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31700
32261
|
const manageCall0 = manage0Info.callConstructor({
|
|
31701
32262
|
amount: newDepositAmount
|
|
31702
32263
|
});
|
|
31703
|
-
const STEP1 = getVesuLegId("vesu_leg1" /* VESU_LEG1 */, vesuAdapter.config.debt.symbol);
|
|
32264
|
+
const STEP1 = getVesuLegId("vesu_leg1" /* VESU_LEG1 */, vesuAdapter.config.debt.symbol, vesuAdapter.config.poolId.toString());
|
|
31704
32265
|
const manage1Info = this.getProofs(STEP1);
|
|
31705
32266
|
const manageCall1 = manage1Info.callConstructor(VesuAdapter.getDefaultModifyPositionCallParams({
|
|
31706
32267
|
collateralAmount: newDepositAmount,
|
|
@@ -31755,7 +32316,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31755
32316
|
const manageCall4 = manage4Info.callConstructor({
|
|
31756
32317
|
amount: minAmount
|
|
31757
32318
|
});
|
|
31758
|
-
const STEP5 = getVesuLegId("vesu_leg1" /* VESU_LEG1 */, vesuAdapter.config.debt.symbol);
|
|
32319
|
+
const STEP5 = getVesuLegId("vesu_leg1" /* VESU_LEG1 */, vesuAdapter.config.debt.symbol, vesuAdapter.config.poolId.toString());
|
|
31759
32320
|
const manage5Info = this.getProofs(STEP5);
|
|
31760
32321
|
const manageCall5 = manage5Info.callConstructor(VesuAdapter.getDefaultModifyPositionCallParams({
|
|
31761
32322
|
collateralAmount: minAmount,
|
|
@@ -31855,7 +32416,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31855
32416
|
*/
|
|
31856
32417
|
async getVesuMultiplyCall(params) {
|
|
31857
32418
|
const maxEkuboPriceImpact = params.maxEkuboPriceImpact || 0.01;
|
|
31858
|
-
const vesuAdapter1 = this.getVesuSameTokenAdapter();
|
|
32419
|
+
const vesuAdapter1 = this.getVesuSameTokenAdapter(params.poolId);
|
|
31859
32420
|
const legLTV = await vesuAdapter1.getLTVConfig(this.config);
|
|
31860
32421
|
logger.verbose(`${this.getTag()}::getVesuMultiplyCall legLTV: ${legLTV}`);
|
|
31861
32422
|
if (!params.isDeposit) {
|
|
@@ -31894,11 +32455,12 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31894
32455
|
debtAmount,
|
|
31895
32456
|
lstDexPriceInUnderlying: dexPrice,
|
|
31896
32457
|
isIncrease: debtAmount.greaterThan(0),
|
|
31897
|
-
maxEkuboPriceImpact
|
|
32458
|
+
maxEkuboPriceImpact,
|
|
32459
|
+
poolId: params.poolId
|
|
31898
32460
|
});
|
|
31899
32461
|
}
|
|
31900
32462
|
getLSTUnderlyingTokenInfo() {
|
|
31901
|
-
const vesuAdapter1 = this.getVesuSameTokenAdapter();
|
|
32463
|
+
const vesuAdapter1 = this.getVesuSameTokenAdapter(this.metadata.additionalInfo.defaultPoolId);
|
|
31902
32464
|
return vesuAdapter1.config.debt;
|
|
31903
32465
|
}
|
|
31904
32466
|
async getMaxBorrowableAmount(params = { isAPYComputation: false }) {
|
|
@@ -31906,7 +32468,9 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31906
32468
|
let netMaxBorrowableAmount = Web3Number.fromWei("0", this.getLSTUnderlyingTokenInfo().decimals);
|
|
31907
32469
|
const maxBorrowables = [];
|
|
31908
32470
|
for (const vesuAdapter of vesuAdapters) {
|
|
31909
|
-
|
|
32471
|
+
const output = await this.getMaxBorrowableAmountByVesuAdapter(vesuAdapter, params.isAPYComputation);
|
|
32472
|
+
const ltv = await vesuAdapter.getLTVConfig(this.config);
|
|
32473
|
+
maxBorrowables.push({ ...output, ltv });
|
|
31910
32474
|
}
|
|
31911
32475
|
maxBorrowables.sort((a, b) => b.amount.toNumber() - a.amount.toNumber());
|
|
31912
32476
|
netMaxBorrowableAmount = maxBorrowables.reduce((acc, curr) => acc.plus(curr.amount), Web3Number.fromWei("0", this.getLSTUnderlyingTokenInfo().decimals));
|
|
@@ -31932,9 +32496,13 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31932
32496
|
async getMaxBorrowableAmountByVesuAdapter(vesuAdapter, isAPYComputation) {
|
|
31933
32497
|
const lstAPY = await this.getLSTAPR(this.getLSTUnderlyingTokenInfo().address);
|
|
31934
32498
|
const maxInterestRate = lstAPY * 0.8;
|
|
31935
|
-
const maxBorrowableAmount = await vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxInterestRate);
|
|
32499
|
+
const { maxDebtToHave: maxBorrowableAmount, currentDebt } = await vesuAdapter.getMaxBorrowableByInterestRate(this.config, vesuAdapter.config.debt, maxInterestRate);
|
|
31936
32500
|
const debtCap = await vesuAdapter.getDebtCap(this.config);
|
|
31937
|
-
|
|
32501
|
+
if (currentDebt.gte(debtCap)) {
|
|
32502
|
+
return { amount: Web3Number.fromWei("0", vesuAdapter.config.debt.decimals), dexSwappableAmount: Web3Number.fromWei("0", vesuAdapter.config.debt.decimals), maxBorrowableAmount: Web3Number.fromWei("0", vesuAdapter.config.debt.decimals), borrowableAsset: vesuAdapter.config.debt };
|
|
32503
|
+
}
|
|
32504
|
+
const availableToBorrow = debtCap.minus(currentDebt);
|
|
32505
|
+
const maxBorrowable = maxBorrowableAmount.minimum(availableToBorrow).multipliedBy(0.999);
|
|
31938
32506
|
if (vesuAdapter.config.debt.address.eq(this.getLSTUnderlyingTokenInfo().address) || isAPYComputation) {
|
|
31939
32507
|
return { amount: maxBorrowable, dexSwappableAmount: maxBorrowable, maxBorrowableAmount: maxBorrowable, borrowableAsset: vesuAdapter.config.debt };
|
|
31940
32508
|
}
|
|
@@ -31956,7 +32524,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31956
32524
|
*/
|
|
31957
32525
|
async getLSTAPR(_address) {
|
|
31958
32526
|
try {
|
|
31959
|
-
const vesuAdapter1 = this.getVesuSameTokenAdapter();
|
|
32527
|
+
const vesuAdapter1 = this.getVesuSameTokenAdapter(this.metadata.additionalInfo.defaultPoolId);
|
|
31960
32528
|
const apr = await LSTAPRService.getLSTAPR(vesuAdapter1.config.debt.address);
|
|
31961
32529
|
if (!apr) {
|
|
31962
32530
|
throw new Error("Failed to get LST APR");
|
|
@@ -31989,29 +32557,21 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
31989
32557
|
}
|
|
31990
32558
|
async maxNewDeposits(params = { isAPYComputation: false }) {
|
|
31991
32559
|
const maxBorrowableAmounts = await this.getMaxBorrowableAmount(params);
|
|
32560
|
+
let numerator = 0;
|
|
31992
32561
|
let ltv = void 0;
|
|
31993
32562
|
for (let adapter of this.getVesuAdapters()) {
|
|
31994
|
-
const
|
|
31995
|
-
if (!
|
|
32563
|
+
const maxBorrowableAmountInfo = maxBorrowableAmounts.maxBorrowables.find((b) => b.borrowableAsset.address.eq(adapter.config.debt.address));
|
|
32564
|
+
if (!maxBorrowableAmountInfo || !maxBorrowableAmountInfo?.amount) {
|
|
31996
32565
|
throw new Error(`Max borrowable amount not found for adapter: ${adapter.config.debt.symbol}`);
|
|
31997
32566
|
}
|
|
31998
|
-
|
|
31999
|
-
if (!ltv) {
|
|
32000
|
-
ltv = maxLTV;
|
|
32001
|
-
} else if (ltv != maxLTV) {
|
|
32002
|
-
throw new Error(`LTV mismatch for adapter: ${adapter.config.debt.symbol}`);
|
|
32003
|
-
}
|
|
32567
|
+
numerator += this.metadata.additionalInfo.targetHealthFactor * maxBorrowableAmountInfo.amount.toNumber() / maxBorrowableAmountInfo.ltv;
|
|
32004
32568
|
}
|
|
32005
|
-
if (!ltv) {
|
|
32006
|
-
throw new Error("LTV not found");
|
|
32007
|
-
}
|
|
32008
|
-
const numerator = this.metadata.additionalInfo.targetHealthFactor * maxBorrowableAmounts.netMaxBorrowableAmount.toNumber() / ltv;
|
|
32009
32569
|
return numerator - maxBorrowableAmounts.netMaxBorrowableAmount.toNumber();
|
|
32010
32570
|
}
|
|
32011
32571
|
// todo revisit cases where 0th adapters is used
|
|
32012
32572
|
async getUnusedBalanceAPY() {
|
|
32013
32573
|
const unusedBalance = await this.getUnusedBalance();
|
|
32014
|
-
const vesuAdapter = this.getVesuSameTokenAdapter();
|
|
32574
|
+
const vesuAdapter = this.getVesuSameTokenAdapter(this.metadata.additionalInfo.defaultPoolId);
|
|
32015
32575
|
const underlying = vesuAdapter.config.debt;
|
|
32016
32576
|
const lstAPY = await this.getLSTAPR(underlying.address);
|
|
32017
32577
|
return {
|
|
@@ -32020,7 +32580,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
32020
32580
|
};
|
|
32021
32581
|
}
|
|
32022
32582
|
async getLSTExchangeRate() {
|
|
32023
|
-
const vesuAdapter1 = this.getVesuSameTokenAdapter();
|
|
32583
|
+
const vesuAdapter1 = this.getVesuSameTokenAdapter(this.metadata.additionalInfo.defaultPoolId);
|
|
32024
32584
|
const lstTokenInfo = vesuAdapter1.config.collateral;
|
|
32025
32585
|
const lstABI = new import_starknet18.Contract({
|
|
32026
32586
|
abi: erc4626_abi_default,
|
|
@@ -32039,7 +32599,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
32039
32599
|
async getModifyLeverCall(params) {
|
|
32040
32600
|
logger.verbose(`${this.getTag()}::getModifyLeverCall marginAmount: ${params.marginAmount}, debtAmount: ${params.debtAmount}, lstDexPriceInUnderlying: ${params.lstDexPriceInUnderlying}, isIncrease: ${params.isIncrease}`);
|
|
32041
32601
|
assert(!params.marginAmount.isZero() || !params.debtAmount.isZero(), "Deposit/debt must be non-0");
|
|
32042
|
-
const vesuAdapter1 = this.getVesuSameTokenAdapter();
|
|
32602
|
+
const vesuAdapter1 = this.getVesuSameTokenAdapter(params.poolId);
|
|
32043
32603
|
const lstTokenInfo = this.asset();
|
|
32044
32604
|
const lstUnderlyingTokenInfo = vesuAdapter1.config.debt;
|
|
32045
32605
|
const maxAmounts = lstTokenInfo.symbol == "xSTRK" ? 5e5 : 0.5;
|
|
@@ -32049,7 +32609,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
32049
32609
|
const proofsIDs = [];
|
|
32050
32610
|
const manageCalls = [];
|
|
32051
32611
|
if (params.marginAmount.greaterThan(0)) {
|
|
32052
|
-
const STEP1_ID = "multiple_approve" /* MULTIPLE_APPROVE
|
|
32612
|
+
const STEP1_ID = getVesuGenericLegId(params.poolId.toString(), "multiple_approve" /* MULTIPLE_APPROVE */);
|
|
32053
32613
|
const manage1Info = this.getProofs(STEP1_ID);
|
|
32054
32614
|
const depositAmount = params.marginAmount;
|
|
32055
32615
|
const manageCall1 = manage1Info.callConstructor({
|
|
@@ -32082,12 +32642,12 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
32082
32642
|
const maxUsedCollateralInLST = params.debtAmount.abs().dividedBy(lstTrueExchangeRate).multipliedBy(1.005);
|
|
32083
32643
|
logger.verbose(`${this.getTag()}::getModifyLeverCall maxUsedCollateralInLST: ${maxUsedCollateralInLST}, maxUsedCollateral: ${maxUsedCollateral}`);
|
|
32084
32644
|
maxUsedCollateral = maxUsedCollateralInLST;
|
|
32085
|
-
const STEP2_ID = "switch_delegation_on" /* SWITCH_DELEGATION_ON
|
|
32645
|
+
const STEP2_ID = getVesuGenericLegId(params.poolId.toString(), "switch_delegation_on" /* SWITCH_DELEGATION_ON */);
|
|
32086
32646
|
const manage2Info = this.getProofs(STEP2_ID);
|
|
32087
32647
|
const manageCall2 = manage2Info.callConstructor({
|
|
32088
32648
|
delegation: true
|
|
32089
32649
|
});
|
|
32090
|
-
const STEP3_ID = getVesuLegId("multiply_vesu" /* MULTIPLY_VESU */, vesuAdapter1.config.debt.symbol);
|
|
32650
|
+
const STEP3_ID = getVesuLegId("multiply_vesu" /* MULTIPLY_VESU */, vesuAdapter1.config.debt.symbol, vesuAdapter1.config.poolId.toString());
|
|
32091
32651
|
const manage3Info = this.getProofs(STEP3_ID);
|
|
32092
32652
|
const multiplyParams = params.isIncrease ? {
|
|
32093
32653
|
isIncrease: true,
|
|
@@ -32114,7 +32674,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
32114
32674
|
}
|
|
32115
32675
|
};
|
|
32116
32676
|
const manageCall3 = manage3Info.callConstructor(multiplyParams);
|
|
32117
|
-
const STEP4_ID = "switch_delegation_off" /* SWITCH_DELEGATION_OFF
|
|
32677
|
+
const STEP4_ID = getVesuGenericLegId(params.poolId.toString(), "switch_delegation_off" /* SWITCH_DELEGATION_OFF */);
|
|
32118
32678
|
const manage4Info = this.getProofs(STEP4_ID);
|
|
32119
32679
|
const manageCall4 = manage4Info.callConstructor({
|
|
32120
32680
|
delegation: false
|
|
@@ -32174,20 +32734,46 @@ function getDescription2(tokenSymbol, underlyingSymbol) {
|
|
|
32174
32734
|
function getAvnuManageIDs(baseID, debtTokenSymbol) {
|
|
32175
32735
|
return `${baseID}_${debtTokenSymbol.toLowerCase()}`;
|
|
32176
32736
|
}
|
|
32177
|
-
function
|
|
32178
|
-
return `${
|
|
32737
|
+
function getVesuGenericLegId(poolId, action) {
|
|
32738
|
+
return `${action}_${poolId.slice(-4).toLowerCase()}`;
|
|
32179
32739
|
}
|
|
32180
|
-
function
|
|
32181
|
-
|
|
32740
|
+
function getVesuLegId(baseID, debtTokenSymbol, poolId) {
|
|
32741
|
+
return `${baseID}_${debtTokenSymbol.toLowerCase()}_${poolId.slice(-4).toLowerCase()}`;
|
|
32742
|
+
}
|
|
32743
|
+
function addVesuLeaves(poolId, lstSymbol, underlyingSymbol, vaultSettings, commonAdapter) {
|
|
32182
32744
|
const lstToken = Global.getDefaultTokens().find((token) => token.symbol === lstSymbol);
|
|
32183
32745
|
const underlyingToken = Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol);
|
|
32184
32746
|
const vesuAdapterLST = new VesuAdapter({
|
|
32185
|
-
poolId
|
|
32747
|
+
poolId,
|
|
32186
32748
|
collateral: lstToken,
|
|
32187
32749
|
debt: underlyingToken,
|
|
32188
32750
|
vaultAllocator: vaultSettings.vaultAllocator,
|
|
32189
|
-
id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, underlyingToken.symbol)
|
|
32751
|
+
id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, underlyingToken.symbol, poolId.toString())
|
|
32190
32752
|
});
|
|
32753
|
+
vaultSettings.adapters.push(...[{
|
|
32754
|
+
id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, underlyingToken.symbol, poolId.toString()),
|
|
32755
|
+
adapter: vesuAdapterLST
|
|
32756
|
+
}]);
|
|
32757
|
+
const { isV2, addr: _ } = getVesuSingletonAddress(poolId);
|
|
32758
|
+
const VESU_MULTIPLY = isV2 ? vesuAdapterLST.VESU_MULTIPLY : vesuAdapterLST.VESU_MULTIPLY_V1;
|
|
32759
|
+
const leafIdApprove = getVesuGenericLegId(poolId.toString(), "multiple_approve" /* MULTIPLE_APPROVE */);
|
|
32760
|
+
vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, VESU_MULTIPLY, leafIdApprove).bind(commonAdapter));
|
|
32761
|
+
const leafIdDelegationOn = getVesuGenericLegId(poolId.toString(), "switch_delegation_on" /* SWITCH_DELEGATION_ON */);
|
|
32762
|
+
vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter(leafIdDelegationOn).bind(vesuAdapterLST));
|
|
32763
|
+
const leafIdDelegationOff = getVesuGenericLegId(poolId.toString(), "switch_delegation_off" /* SWITCH_DELEGATION_OFF */);
|
|
32764
|
+
vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter(leafIdDelegationOff).bind(vesuAdapterLST));
|
|
32765
|
+
const multiplID = getVesuLegId("multiply_vesu" /* MULTIPLY_VESU */, underlyingToken.symbol, poolId.toString());
|
|
32766
|
+
vaultSettings.leafAdapters.push(vesuAdapterLST.getMultiplyAdapter(multiplID).bind(vesuAdapterLST));
|
|
32767
|
+
return vesuAdapterLST;
|
|
32768
|
+
}
|
|
32769
|
+
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, defaultPoolId, altSupportedPoolIds = []) {
|
|
32770
|
+
vaultSettings.leafAdapters = [];
|
|
32771
|
+
const pool1 = vaultSettings.defaultPoolId;
|
|
32772
|
+
if (!pool1.eq(defaultPoolId)) {
|
|
32773
|
+
throw new Error(`Dont include default pool id in supported pool ids`);
|
|
32774
|
+
}
|
|
32775
|
+
const lstToken = Global.getDefaultTokens().find((token) => token.symbol === lstSymbol);
|
|
32776
|
+
const underlyingToken = Global.getDefaultTokens().find((token) => token.symbol === underlyingSymbol);
|
|
32191
32777
|
const commonAdapter = new CommonAdapter({
|
|
32192
32778
|
manager: vaultSettings.manager,
|
|
32193
32779
|
asset: lstToken.address,
|
|
@@ -32196,17 +32782,11 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
|
|
|
32196
32782
|
vaultAllocator: vaultSettings.vaultAllocator
|
|
32197
32783
|
});
|
|
32198
32784
|
vaultSettings.adapters.push(...[{
|
|
32199
|
-
id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, underlyingToken.symbol),
|
|
32200
|
-
adapter: vesuAdapterLST
|
|
32201
|
-
}, {
|
|
32202
32785
|
id: "common_adapter" /* COMMON */,
|
|
32203
32786
|
adapter: commonAdapter
|
|
32204
32787
|
}]);
|
|
32205
|
-
const
|
|
32206
|
-
|
|
32207
|
-
vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, VESU_MULTIPLY, "multiple_approve" /* MULTIPLE_APPROVE */).bind(commonAdapter));
|
|
32208
|
-
vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter("switch_delegation_on" /* SWITCH_DELEGATION_ON */).bind(vesuAdapterLST));
|
|
32209
|
-
vaultSettings.leafAdapters.push(vesuAdapterLST.getVesuModifyDelegationAdapter("switch_delegation_off" /* SWITCH_DELEGATION_OFF */).bind(vesuAdapterLST));
|
|
32788
|
+
const vesuAdapterLST = addVesuLeaves(defaultPoolId, lstSymbol, underlyingSymbol, vaultSettings, commonAdapter);
|
|
32789
|
+
altSupportedPoolIds.map((poolId) => addVesuLeaves(poolId, lstSymbol, underlyingSymbol, vaultSettings, commonAdapter));
|
|
32210
32790
|
vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, AVNU_EXCHANGE, "avnu_mul_approve_withdr" /* AVNU_MULTIPLY_APPROVE_WITHDRAW */).bind(commonAdapter));
|
|
32211
32791
|
for (let borrowableAsset of vaultSettings.borrowable_assets) {
|
|
32212
32792
|
const debtAsset = borrowableAsset;
|
|
@@ -32221,12 +32801,14 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
|
|
|
32221
32801
|
collateral: lstToken,
|
|
32222
32802
|
debt: debtAsset,
|
|
32223
32803
|
vaultAllocator: vaultSettings.vaultAllocator,
|
|
32224
|
-
id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, debtAsset.symbol)
|
|
32804
|
+
id: getVesuLegId("vesu_leg1" /* VESU_LEG1 */, debtAsset.symbol, pool1.toString())
|
|
32225
32805
|
});
|
|
32806
|
+
const { isV2, addr: poolAddr } = getVesuSingletonAddress(pool1);
|
|
32226
32807
|
vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, poolAddr, "approve_token1" /* APPROVE_TOKEN1 */).bind(commonAdapter));
|
|
32227
32808
|
vaultSettings.leafAdapters.push(vesuAdapter.getModifyPosition.bind(vesuAdapter));
|
|
32228
|
-
|
|
32229
|
-
|
|
32809
|
+
if (borrowableAsset.address.eq(underlyingToken.address)) {
|
|
32810
|
+
continue;
|
|
32811
|
+
}
|
|
32230
32812
|
}
|
|
32231
32813
|
vaultSettings.leafAdapters.push(commonAdapter.getApproveAdapter(lstToken.address, vaultSettings.vaultAddress, "approve_bring_liquidity" /* APPROVE_BRING_LIQUIDITY */).bind(commonAdapter));
|
|
32232
32814
|
vaultSettings.leafAdapters.push(commonAdapter.getBringLiquidityAdapter("bring_liquidity" /* BRING_LIQUIDITY */).bind(commonAdapter));
|
|
@@ -32306,7 +32888,9 @@ var hyperxSTRK = {
|
|
|
32306
32888
|
targetHealthFactor: 1.1,
|
|
32307
32889
|
minHealthFactor: 1.05,
|
|
32308
32890
|
borrowable_assets: Global.getDefaultTokens().filter((token) => token.symbol === "STRK"),
|
|
32309
|
-
underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "STRK")
|
|
32891
|
+
underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "STRK"),
|
|
32892
|
+
defaultPoolId: VesuPools.Re7xSTRK,
|
|
32893
|
+
altSupportedPoolIds: [VesuPools.Prime]
|
|
32310
32894
|
};
|
|
32311
32895
|
var hyperxWBTC = {
|
|
32312
32896
|
vaultAddress: ContractAddr.from("0x2da9d0f96a46b453f55604313785dc866424240b1c6811d13bef594343db818"),
|
|
@@ -32319,7 +32903,10 @@ var hyperxWBTC = {
|
|
|
32319
32903
|
targetHealthFactor: 1.1,
|
|
32320
32904
|
minHealthFactor: 1.05,
|
|
32321
32905
|
borrowable_assets: borrowableAssets.map((asset) => Global.getDefaultTokens().find((token) => token.symbol === asset)),
|
|
32322
|
-
underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "WBTC")
|
|
32906
|
+
underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "WBTC"),
|
|
32907
|
+
defaultPoolId: VesuPools.Re7xBTC,
|
|
32908
|
+
altSupportedPoolIds: [VesuPools.Prime],
|
|
32909
|
+
redemptionRouter: ContractAddr.from("0x6ea649f402898f69baf775c1afdd08522c071c640b9c4460192070ec2b96417")
|
|
32323
32910
|
};
|
|
32324
32911
|
var hyperxtBTC = {
|
|
32325
32912
|
vaultAddress: ContractAddr.from("0x47d5f68477e5637ce0e56436c6b5eee5a354e6828995dae106b11a48679328"),
|
|
@@ -32332,7 +32919,10 @@ var hyperxtBTC = {
|
|
|
32332
32919
|
targetHealthFactor: 1.1,
|
|
32333
32920
|
minHealthFactor: 1.05,
|
|
32334
32921
|
borrowable_assets: Global.getDefaultTokens().filter((token) => token.symbol === "tBTC" || token.symbol === "WBTC"),
|
|
32335
|
-
underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "tBTC")
|
|
32922
|
+
underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "tBTC"),
|
|
32923
|
+
defaultPoolId: VesuPools.Re7xBTC,
|
|
32924
|
+
altSupportedPoolIds: [],
|
|
32925
|
+
redemptionRouter: ContractAddr.from("0x3de9c409d1e357e25778fb7a3e2e2393666956846a5c2caa607296fa8e76b5d")
|
|
32336
32926
|
};
|
|
32337
32927
|
var hyperxsBTC = {
|
|
32338
32928
|
vaultAddress: ContractAddr.from("0x437ef1e7d0f100b2e070b7a65cafec0b2be31b0290776da8b4112f5473d8d9"),
|
|
@@ -32345,7 +32935,9 @@ var hyperxsBTC = {
|
|
|
32345
32935
|
targetHealthFactor: 1.1,
|
|
32346
32936
|
minHealthFactor: 1.05,
|
|
32347
32937
|
borrowable_assets: Global.getDefaultTokens().filter((token) => token.symbol === "solvBTC"),
|
|
32348
|
-
underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "solvBTC")
|
|
32938
|
+
underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "solvBTC"),
|
|
32939
|
+
defaultPoolId: VesuPools.Re7xBTC,
|
|
32940
|
+
altSupportedPoolIds: []
|
|
32349
32941
|
};
|
|
32350
32942
|
var hyperxLBTC = {
|
|
32351
32943
|
vaultAddress: ContractAddr.from("0x64cf24d4883fe569926419a0569ab34497c6956a1a308fa883257f7486d7030"),
|
|
@@ -32358,7 +32950,9 @@ var hyperxLBTC = {
|
|
|
32358
32950
|
targetHealthFactor: 1.1,
|
|
32359
32951
|
minHealthFactor: 1.05,
|
|
32360
32952
|
borrowable_assets: Global.getDefaultTokens().filter((token) => token.symbol === "LBTC"),
|
|
32361
|
-
underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "LBTC")
|
|
32953
|
+
underlyingToken: Global.getDefaultTokens().find((token) => token.symbol === "LBTC"),
|
|
32954
|
+
defaultPoolId: VesuPools.Re7xBTC,
|
|
32955
|
+
altSupportedPoolIds: []
|
|
32362
32956
|
};
|
|
32363
32957
|
function getInvestmentSteps(lstSymbol, underlyingSymbol) {
|
|
32364
32958
|
return [
|
|
@@ -32369,50 +32963,133 @@ function getInvestmentSteps(lstSymbol, underlyingSymbol) {
|
|
|
32369
32963
|
`If required, adjust leverage or re-allocate assets within LST pool on Vesu to optimize yield`
|
|
32370
32964
|
];
|
|
32371
32965
|
}
|
|
32966
|
+
function getMaxTVL(lstSymbol) {
|
|
32967
|
+
const lstMaxTVLs = {
|
|
32968
|
+
xWBTC: 5,
|
|
32969
|
+
xLBTC: 5,
|
|
32970
|
+
xtBTC: 5,
|
|
32971
|
+
xsBTC: 5,
|
|
32972
|
+
xSTRK: 55e4
|
|
32973
|
+
};
|
|
32974
|
+
const maxTVLValue = lstMaxTVLs[lstSymbol] || 0;
|
|
32975
|
+
const token = Global.getDefaultTokens().find(
|
|
32976
|
+
(token2) => token2.symbol === lstSymbol
|
|
32977
|
+
);
|
|
32978
|
+
if (!token) {
|
|
32979
|
+
return Web3Number.fromWei(0, 18);
|
|
32980
|
+
}
|
|
32981
|
+
return Web3Number.fromWei(maxTVLValue, token.decimals);
|
|
32982
|
+
}
|
|
32983
|
+
function createHyperLSTSettings(lstSymbol, underlyingSymbol) {
|
|
32984
|
+
const depositToken = Global.getDefaultTokens().find(
|
|
32985
|
+
(token) => token.symbol === lstSymbol
|
|
32986
|
+
);
|
|
32987
|
+
return {
|
|
32988
|
+
maxTVL: getMaxTVL(lstSymbol),
|
|
32989
|
+
isPaused: false,
|
|
32990
|
+
liveStatus: "Hot & New \u{1F525}" /* HOT */,
|
|
32991
|
+
isAudited: true,
|
|
32992
|
+
isInstantWithdrawal: false,
|
|
32993
|
+
hideHarvestInfo: true,
|
|
32994
|
+
quoteToken: depositToken,
|
|
32995
|
+
showWithdrawalWarningModal: false,
|
|
32996
|
+
alerts: [
|
|
32997
|
+
{
|
|
32998
|
+
tab: "withdraw",
|
|
32999
|
+
text: "On withdrawal, you will receive an NFT representing your withdrawal request. The funds will be automatically sent to your wallet (NFT owner) in 24 hours (In this initial phase of Launch). You can monitor the status in transactions tab.",
|
|
33000
|
+
type: "info"
|
|
33001
|
+
},
|
|
33002
|
+
{
|
|
33003
|
+
tab: "deposit",
|
|
33004
|
+
text: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
33005
|
+
"To acquire the LST, please visit",
|
|
33006
|
+
" ",
|
|
33007
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
33008
|
+
"a",
|
|
33009
|
+
{
|
|
33010
|
+
href: "https://app.endur.fi",
|
|
33011
|
+
target: "_blank",
|
|
33012
|
+
rel: "noopener noreferrer",
|
|
33013
|
+
children: "endur.fi"
|
|
33014
|
+
}
|
|
33015
|
+
)
|
|
33016
|
+
] }),
|
|
33017
|
+
type: "info"
|
|
33018
|
+
},
|
|
33019
|
+
{
|
|
33020
|
+
tab: "deposit",
|
|
33021
|
+
text: "It may take up to one week for your deposit to appreciate in value. This delay occurs because the LST price is sourced from DEXes and liquidity is usually rebased once a week.",
|
|
33022
|
+
type: "info"
|
|
33023
|
+
}
|
|
33024
|
+
]
|
|
33025
|
+
};
|
|
33026
|
+
}
|
|
33027
|
+
var HYPER_LST_SECURITY = {
|
|
33028
|
+
auditStatus: "Audited" /* AUDITED */,
|
|
33029
|
+
sourceCode: {
|
|
33030
|
+
type: "Closed Source" /* CLOSED_SOURCE */,
|
|
33031
|
+
contractLink: "https://github.com/trovesfi/troves-contracts"
|
|
33032
|
+
},
|
|
33033
|
+
accessControl: {
|
|
33034
|
+
type: "Standard Account" /* STANDARD_ACCOUNT */,
|
|
33035
|
+
addresses: [ContractAddr.from("0x0")],
|
|
33036
|
+
timeLock: "2 Days"
|
|
33037
|
+
}
|
|
33038
|
+
};
|
|
33039
|
+
var HYPER_LST_REDEMPTION_INFO = {
|
|
33040
|
+
instantWithdrawalVault: "No" /* NO */,
|
|
33041
|
+
expectedRedemptionTime: {
|
|
33042
|
+
upto1M: "1-2hrs",
|
|
33043
|
+
upto10M: "24hrs",
|
|
33044
|
+
above10M: "2-3 Days"
|
|
33045
|
+
}
|
|
33046
|
+
};
|
|
32372
33047
|
function getStrategySettings(lstSymbol, underlyingSymbol, addresses, isPreview = false) {
|
|
32373
33048
|
return {
|
|
33049
|
+
id: `hyper_${lstSymbol.toLowerCase()}`,
|
|
32374
33050
|
name: `Hyper ${lstSymbol}`,
|
|
32375
33051
|
description: getDescription2(lstSymbol, underlyingSymbol),
|
|
32376
33052
|
address: addresses.vaultAddress,
|
|
32377
33053
|
launchBlock: 0,
|
|
32378
33054
|
type: "Other",
|
|
32379
|
-
|
|
32380
|
-
|
|
33055
|
+
vaultType: {
|
|
33056
|
+
type: "farming" /* FARMING */,
|
|
33057
|
+
description: "this is a yield farming vault"
|
|
33058
|
+
},
|
|
33059
|
+
depositTokens: [
|
|
33060
|
+
Global.getDefaultTokens().find(
|
|
33061
|
+
(token) => token.symbol === lstSymbol
|
|
33062
|
+
)
|
|
33063
|
+
],
|
|
33064
|
+
additionalInfo: getLooperSettings2(
|
|
33065
|
+
lstSymbol,
|
|
33066
|
+
underlyingSymbol,
|
|
33067
|
+
addresses,
|
|
33068
|
+
lstSymbol === "xSTRK" ? VesuPools.Re7xSTRK : VesuPools.Re7xBTC
|
|
33069
|
+
),
|
|
32381
33070
|
risk: {
|
|
32382
33071
|
riskFactor: _riskFactor4,
|
|
32383
|
-
netRisk: _riskFactor4.reduce(
|
|
33072
|
+
netRisk: _riskFactor4.reduce(
|
|
33073
|
+
(acc, curr) => acc + curr.value * curr.weight,
|
|
33074
|
+
0
|
|
33075
|
+
) / _riskFactor4.reduce((acc, curr) => acc + curr.weight, 0),
|
|
32384
33076
|
notARisks: getNoRiskTags(_riskFactor4)
|
|
32385
33077
|
},
|
|
32386
33078
|
auditUrl: AUDIT_URL4,
|
|
32387
33079
|
protocols: [Protocols.ENDUR, Protocols.VESU],
|
|
32388
|
-
|
|
33080
|
+
curator: {
|
|
33081
|
+
name: "Unwrap Labs",
|
|
33082
|
+
logo: "https://assets.troves.fi/integrations/unwraplabs/white.png"
|
|
33083
|
+
},
|
|
33084
|
+
settings: createHyperLSTSettings(lstSymbol, underlyingSymbol),
|
|
32389
33085
|
contractDetails: getContractDetails(addresses),
|
|
32390
33086
|
faqs: getFAQs2(lstSymbol, underlyingSymbol),
|
|
32391
33087
|
investmentSteps: getInvestmentSteps(lstSymbol, underlyingSymbol),
|
|
32392
33088
|
isPreview,
|
|
32393
33089
|
apyMethodology: "Current annualized APY in terms of base asset of the LST. There is no additional fee taken by Troves on LST APY. We charge a 10% performance fee on the additional gain which is already accounted in the APY shown.",
|
|
32394
|
-
|
|
32395
|
-
|
|
32396
|
-
|
|
32397
|
-
auditStatus: "Audited" /* AUDITED */,
|
|
32398
|
-
sourceCode: {
|
|
32399
|
-
type: "Closed Source" /* CLOSED_SOURCE */,
|
|
32400
|
-
contractLink: "https://github.com/trovesfi/troves-contracts"
|
|
32401
|
-
},
|
|
32402
|
-
accessControl: {
|
|
32403
|
-
type: "Standard Account" /* STANDARD_ACCOUNT */,
|
|
32404
|
-
addresses: [ContractAddr.from("0x0")],
|
|
32405
|
-
timeLock: "2 Days"
|
|
32406
|
-
}
|
|
32407
|
-
},
|
|
32408
|
-
redemptionInfo: {
|
|
32409
|
-
instantWithdrawalVault: "No" /* NO */,
|
|
32410
|
-
expectedRedemptionTime: {
|
|
32411
|
-
upto1M: "1-2hrs",
|
|
32412
|
-
upto10M: "24hrs",
|
|
32413
|
-
above10M: "2-3 Days"
|
|
32414
|
-
}
|
|
32415
|
-
}
|
|
33090
|
+
tags: lstSymbol.includes("BTC") ? ["BTC" /* BTC */, "Maxx" /* LEVERED */] : ["Maxx" /* LEVERED */],
|
|
33091
|
+
security: HYPER_LST_SECURITY,
|
|
33092
|
+
redemptionInfo: HYPER_LST_REDEMPTION_INFO
|
|
32416
33093
|
};
|
|
32417
33094
|
}
|
|
32418
33095
|
var HyperLSTStrategies = [
|
|
@@ -32503,7 +33180,6 @@ function getAllStrategyMetadata() {
|
|
|
32503
33180
|
type: entry.type,
|
|
32504
33181
|
assets: extractAssets(entry.metadata),
|
|
32505
33182
|
protocols: entry.metadata.protocols.map((p) => p.name.toLowerCase()),
|
|
32506
|
-
category: entry.metadata.category,
|
|
32507
33183
|
tags: entry.metadata.tags || [],
|
|
32508
33184
|
curator: entry.metadata.curator,
|
|
32509
33185
|
isRetired: isRetired(entry.metadata)
|
|
@@ -32516,7 +33192,16 @@ function getFilterMetadata() {
|
|
|
32516
33192
|
allMetadata.forEach((meta) => {
|
|
32517
33193
|
meta.assets.forEach((asset) => assetSet.add(asset));
|
|
32518
33194
|
});
|
|
32519
|
-
const
|
|
33195
|
+
const allowedAssets = /* @__PURE__ */ new Set(["eth", "btc", "strk", "usdt", "usdc"]);
|
|
33196
|
+
const assets = Array.from(assetSet).filter((asset) => allowedAssets.has(asset.toLowerCase())).sort((a, b) => {
|
|
33197
|
+
const order = ["eth", "btc", "strk", "usdt", "usdc"];
|
|
33198
|
+
const aIndex = order.indexOf(a.toLowerCase());
|
|
33199
|
+
const bIndex = order.indexOf(b.toLowerCase());
|
|
33200
|
+
if (aIndex === -1 && bIndex === -1) return 0;
|
|
33201
|
+
if (aIndex === -1) return 1;
|
|
33202
|
+
if (bIndex === -1) return -1;
|
|
33203
|
+
return aIndex - bIndex;
|
|
33204
|
+
}).map((id) => ({
|
|
32520
33205
|
id,
|
|
32521
33206
|
label: id.toUpperCase()
|
|
32522
33207
|
}));
|
|
@@ -32526,25 +33211,15 @@ function getFilterMetadata() {
|
|
|
32526
33211
|
});
|
|
32527
33212
|
const protocols = Array.from(protocolSet).sort().map((id) => ({
|
|
32528
33213
|
id,
|
|
32529
|
-
label: id
|
|
32530
|
-
}));
|
|
32531
|
-
const categorySet = /* @__PURE__ */ new Set();
|
|
32532
|
-
allMetadata.forEach((meta) => {
|
|
32533
|
-
if (meta.category) categorySet.add(meta.category);
|
|
32534
|
-
});
|
|
32535
|
-
const categories = Array.from(categorySet).sort().map((id) => ({
|
|
32536
|
-
id,
|
|
32537
|
-
label: id === "btc" ? "BTC" : id === "meta-vaults" ? "Meta Vaults" : "All"
|
|
33214
|
+
label: id.charAt(0).toUpperCase() + id.slice(1)
|
|
32538
33215
|
}));
|
|
32539
33216
|
const quickFilters = [
|
|
32540
33217
|
{ id: "all", label: "All Strategies" },
|
|
32541
|
-
{ id: "
|
|
32542
|
-
{ id: "meta-vaults", label: "Meta Vaults" }
|
|
33218
|
+
...getAllStrategyTags().map((tag) => ({ id: tag.toLowerCase().replaceAll(" ", "-"), label: tag }))
|
|
32543
33219
|
];
|
|
32544
33220
|
return {
|
|
32545
33221
|
assets,
|
|
32546
33222
|
protocols,
|
|
32547
|
-
categories,
|
|
32548
33223
|
quickFilters
|
|
32549
33224
|
};
|
|
32550
33225
|
}
|
|
@@ -32556,31 +33231,87 @@ function getStrategiesByType(type) {
|
|
|
32556
33231
|
const registry = buildStrategyRegistry();
|
|
32557
33232
|
return registry.filter((entry) => entry.type === type);
|
|
32558
33233
|
}
|
|
32559
|
-
|
|
32560
|
-
|
|
32561
|
-
|
|
32562
|
-
|
|
32563
|
-
|
|
32564
|
-
|
|
32565
|
-
|
|
32566
|
-
|
|
32567
|
-
|
|
32568
|
-
|
|
32569
|
-
|
|
33234
|
+
|
|
33235
|
+
// src/strategies/factory.ts
|
|
33236
|
+
var FactoryStrategyType = /* @__PURE__ */ ((FactoryStrategyType2) => {
|
|
33237
|
+
FactoryStrategyType2["UNIVERSAL"] = "UNIVERSAL";
|
|
33238
|
+
FactoryStrategyType2["EKUBO_CL"] = "EKUBO_CL";
|
|
33239
|
+
FactoryStrategyType2["HYPER_LST"] = "HYPER_LST";
|
|
33240
|
+
FactoryStrategyType2["VESU_REBALANCE"] = "VESU_REBALANCE";
|
|
33241
|
+
FactoryStrategyType2["SENSEI"] = "SENSEI";
|
|
33242
|
+
return FactoryStrategyType2;
|
|
33243
|
+
})(FactoryStrategyType || {});
|
|
33244
|
+
function createUniversalStrategy2(config, pricer, metadata) {
|
|
33245
|
+
return new UniversalStrategy(config, pricer, metadata);
|
|
33246
|
+
}
|
|
33247
|
+
function createEkuboCLStrategy(config, pricer, metadata) {
|
|
33248
|
+
return new EkuboCLVault(config, pricer, metadata);
|
|
33249
|
+
}
|
|
33250
|
+
function createHyperLSTStrategy(config, pricer, metadata) {
|
|
33251
|
+
return new UniversalLstMultiplierStrategy(config, pricer, metadata);
|
|
33252
|
+
}
|
|
33253
|
+
function createVesuRebalanceStrategy2(config, pricer, metadata) {
|
|
33254
|
+
return new VesuRebalance(config, pricer, metadata);
|
|
33255
|
+
}
|
|
33256
|
+
function createSenseiStrategy(config, pricer, metadata) {
|
|
33257
|
+
return new SenseiVault(config, pricer, metadata);
|
|
33258
|
+
}
|
|
33259
|
+
function getStrategyTypeFromMetadata(metadata) {
|
|
33260
|
+
const info = metadata.additionalInfo;
|
|
33261
|
+
if (info && "borrowable_assets" in info && "underlyingToken" in info) {
|
|
33262
|
+
return "HYPER_LST" /* HYPER_LST */;
|
|
32570
33263
|
}
|
|
32571
|
-
if (
|
|
32572
|
-
|
|
32573
|
-
(meta) => meta.protocols.some(
|
|
32574
|
-
(protocol) => criteria.protocols.includes(protocol.toLowerCase())
|
|
32575
|
-
)
|
|
32576
|
-
);
|
|
33264
|
+
if (info && ("newBounds" in info || typeof info.newBounds !== "undefined") && "rebalanceConditions" in info && "quoteAsset" in info) {
|
|
33265
|
+
return "EKUBO_CL" /* EKUBO_CL */;
|
|
32577
33266
|
}
|
|
32578
|
-
if (
|
|
32579
|
-
|
|
32580
|
-
|
|
32581
|
-
|
|
33267
|
+
if (info && "mainToken" in info && "secondaryToken" in info && "targetHfBps" in info) {
|
|
33268
|
+
return "SENSEI" /* SENSEI */;
|
|
33269
|
+
}
|
|
33270
|
+
if (info && "feeBps" in info && Object.keys(info).length <= 2) {
|
|
33271
|
+
return "VESU_REBALANCE" /* VESU_REBALANCE */;
|
|
33272
|
+
}
|
|
33273
|
+
if (info && "vaultAddress" in info && "manager" in info && "vaultAllocator" in info) {
|
|
33274
|
+
return "UNIVERSAL" /* UNIVERSAL */;
|
|
33275
|
+
}
|
|
33276
|
+
throw new Error(
|
|
33277
|
+
`Unable to determine strategy type from metadata: ${metadata.id}`
|
|
33278
|
+
);
|
|
33279
|
+
}
|
|
33280
|
+
function createStrategy(type, config, pricer, metadata) {
|
|
33281
|
+
switch (type) {
|
|
33282
|
+
case "UNIVERSAL" /* UNIVERSAL */:
|
|
33283
|
+
return createUniversalStrategy2(
|
|
33284
|
+
config,
|
|
33285
|
+
pricer,
|
|
33286
|
+
metadata
|
|
33287
|
+
);
|
|
33288
|
+
case "EKUBO_CL" /* EKUBO_CL */:
|
|
33289
|
+
return createEkuboCLStrategy(
|
|
33290
|
+
config,
|
|
33291
|
+
pricer,
|
|
33292
|
+
metadata
|
|
33293
|
+
);
|
|
33294
|
+
case "HYPER_LST" /* HYPER_LST */:
|
|
33295
|
+
return createHyperLSTStrategy(
|
|
33296
|
+
config,
|
|
33297
|
+
pricer,
|
|
33298
|
+
metadata
|
|
33299
|
+
);
|
|
33300
|
+
case "VESU_REBALANCE" /* VESU_REBALANCE */:
|
|
33301
|
+
return createVesuRebalanceStrategy2(
|
|
33302
|
+
config,
|
|
33303
|
+
pricer,
|
|
33304
|
+
metadata
|
|
33305
|
+
);
|
|
33306
|
+
case "SENSEI" /* SENSEI */:
|
|
33307
|
+
return createSenseiStrategy(
|
|
33308
|
+
config,
|
|
33309
|
+
pricer,
|
|
33310
|
+
metadata
|
|
33311
|
+
);
|
|
33312
|
+
default:
|
|
33313
|
+
throw new Error(`Unknown strategy type: ${type}`);
|
|
32582
33314
|
}
|
|
32583
|
-
return allMetadata;
|
|
32584
33315
|
}
|
|
32585
33316
|
|
|
32586
33317
|
// src/modules/pricer-lst.ts
|
|
@@ -32592,7 +33323,7 @@ var PricerLST2 = class extends Pricer {
|
|
|
32592
33323
|
const staleTime = 6e4;
|
|
32593
33324
|
const allTokens = tokenMaps.map((map) => [map.lst, map.underlying]).flat();
|
|
32594
33325
|
super(config, allTokens, refreshInterval, staleTime);
|
|
32595
|
-
this.EKUBO_API = "https://
|
|
33326
|
+
this.EKUBO_API = "https://prod-api-quoter.ekubo.org/23448594291968334/{{AMOUNT}}/{{TOKEN_ADDRESS}}/{{UNDERLYING_ADDRESS}}";
|
|
32596
33327
|
this.tokenMaps = tokenMaps;
|
|
32597
33328
|
}
|
|
32598
33329
|
isUnderlying(token) {
|
|
@@ -32633,107 +33364,6 @@ var PricerLST2 = class extends Pricer {
|
|
|
32633
33364
|
}
|
|
32634
33365
|
};
|
|
32635
33366
|
|
|
32636
|
-
// src/modules/lst-apr.ts
|
|
32637
|
-
var LSTAPRService = class {
|
|
32638
|
-
// 5 minutes
|
|
32639
|
-
/**
|
|
32640
|
-
* Fetches LST stats from Endur API with caching
|
|
32641
|
-
* @returns Promise<LSTStats[]> Array of LST statistics
|
|
32642
|
-
*/
|
|
32643
|
-
static async getLSTStats() {
|
|
32644
|
-
const now = Date.now();
|
|
32645
|
-
if (this.cache && now - this.cacheTimestamp < this.CACHE_DURATION) {
|
|
32646
|
-
logger.verbose(`LSTAPRService: Returning cached LST stats`);
|
|
32647
|
-
return this.cache;
|
|
32648
|
-
}
|
|
32649
|
-
try {
|
|
32650
|
-
logger.verbose(`LSTAPRService: Fetching LST stats from Endur API`);
|
|
32651
|
-
const response = await fetch(this.ENDUR_API_URL);
|
|
32652
|
-
if (!response.ok) {
|
|
32653
|
-
throw new Error(`Failed to fetch LST stats: ${response.status} ${response.statusText}`);
|
|
32654
|
-
}
|
|
32655
|
-
const data = await response.json();
|
|
32656
|
-
if (!Array.isArray(data)) {
|
|
32657
|
-
throw new Error("Invalid response format: expected array");
|
|
32658
|
-
}
|
|
32659
|
-
this.cache = data;
|
|
32660
|
-
this.cacheTimestamp = now;
|
|
32661
|
-
logger.verbose(`LSTAPRService: Successfully fetched ${data.length} LST stats`);
|
|
32662
|
-
return data;
|
|
32663
|
-
} catch (error) {
|
|
32664
|
-
logger.error(`LSTAPRService: Error fetching LST stats: ${error}`);
|
|
32665
|
-
if (this.cache) {
|
|
32666
|
-
logger.warn(`LSTAPRService: Returning stale cached data due to API error`);
|
|
32667
|
-
return this.cache;
|
|
32668
|
-
}
|
|
32669
|
-
throw error;
|
|
32670
|
-
}
|
|
32671
|
-
}
|
|
32672
|
-
/**
|
|
32673
|
-
* Gets LST APR for a specific asset address
|
|
32674
|
-
* @param assetAddress - The contract address of the underlying asset
|
|
32675
|
-
* @returns Promise<number> The LST APR (not divided by 1e18)
|
|
32676
|
-
*/
|
|
32677
|
-
static async getLSTAPR(assetAddress) {
|
|
32678
|
-
const stats = await this.getLSTStats();
|
|
32679
|
-
const lstStat = stats.find(
|
|
32680
|
-
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
32681
|
-
);
|
|
32682
|
-
if (!lstStat) {
|
|
32683
|
-
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
32684
|
-
return 0;
|
|
32685
|
-
}
|
|
32686
|
-
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy} (${lstStat.apyInPercentage})`);
|
|
32687
|
-
return lstStat.apy;
|
|
32688
|
-
}
|
|
32689
|
-
/**
|
|
32690
|
-
* Gets LST APR for multiple asset addresses
|
|
32691
|
-
* @param assetAddresses - Array of contract addresses
|
|
32692
|
-
* @returns Promise<Map<string, number>> Map of asset address to LST APR
|
|
32693
|
-
*/
|
|
32694
|
-
static async getLSTAPRs(assetAddresses) {
|
|
32695
|
-
const stats = await this.getLSTStats();
|
|
32696
|
-
const result = /* @__PURE__ */ new Map();
|
|
32697
|
-
for (const assetAddress of assetAddresses) {
|
|
32698
|
-
const lstStat = stats.find(
|
|
32699
|
-
(stat) => ContractAddr.eqString(stat.assetAddress, assetAddress.address)
|
|
32700
|
-
);
|
|
32701
|
-
if (lstStat) {
|
|
32702
|
-
result.set(assetAddress.address, lstStat.apy);
|
|
32703
|
-
logger.verbose(`LSTAPRService: Found LST APR for ${lstStat.asset}: ${lstStat.apy}`);
|
|
32704
|
-
} else {
|
|
32705
|
-
result.set(assetAddress.address, 0);
|
|
32706
|
-
logger.warn(`LSTAPRService: No LST stats found for asset address ${assetAddress.address}`);
|
|
32707
|
-
}
|
|
32708
|
-
}
|
|
32709
|
-
return result;
|
|
32710
|
-
}
|
|
32711
|
-
/**
|
|
32712
|
-
* Gets all available LST assets and their APRs
|
|
32713
|
-
* @returns Promise<Map<string, LSTStats>> Map of asset address to LST stats
|
|
32714
|
-
*/
|
|
32715
|
-
static async getAllLSTStats() {
|
|
32716
|
-
const stats = await this.getLSTStats();
|
|
32717
|
-
const result = /* @__PURE__ */ new Map();
|
|
32718
|
-
for (const stat of stats) {
|
|
32719
|
-
result.set(stat.assetAddress, stat);
|
|
32720
|
-
}
|
|
32721
|
-
return result;
|
|
32722
|
-
}
|
|
32723
|
-
/**
|
|
32724
|
-
* Clears the cache (useful for testing or forcing refresh)
|
|
32725
|
-
*/
|
|
32726
|
-
static clearCache() {
|
|
32727
|
-
this.cache = null;
|
|
32728
|
-
this.cacheTimestamp = 0;
|
|
32729
|
-
logger.verbose(`LSTAPRService: Cache cleared`);
|
|
32730
|
-
}
|
|
32731
|
-
};
|
|
32732
|
-
LSTAPRService.ENDUR_API_URL = "https://app.endur.fi/api/lst/stats";
|
|
32733
|
-
LSTAPRService.cache = null;
|
|
32734
|
-
LSTAPRService.cacheTimestamp = 0;
|
|
32735
|
-
LSTAPRService.CACHE_DURATION = 5 * 60 * 1e3;
|
|
32736
|
-
|
|
32737
33367
|
// src/notifs/telegram.ts
|
|
32738
33368
|
var import_node_telegram_bot_api = __toESM(require("node-telegram-bot-api"));
|
|
32739
33369
|
var TelegramNotif = class {
|
|
@@ -33288,8 +33918,8 @@ var deployer_default = Deployer;
|
|
|
33288
33918
|
ERC20,
|
|
33289
33919
|
EkuboCLVault,
|
|
33290
33920
|
EkuboCLVaultStrategies,
|
|
33291
|
-
EkuboPricer,
|
|
33292
33921
|
EkuboQuoter,
|
|
33922
|
+
FactoryStrategyType,
|
|
33293
33923
|
FatalError,
|
|
33294
33924
|
FlowChartColors,
|
|
33295
33925
|
Global,
|
|
@@ -33299,6 +33929,7 @@ var deployer_default = Deployer;
|
|
|
33299
33929
|
InstantWithdrawalVault,
|
|
33300
33930
|
LSTAPRService,
|
|
33301
33931
|
MarginType,
|
|
33932
|
+
MyNumber,
|
|
33302
33933
|
Network,
|
|
33303
33934
|
PRICE_ROUTER,
|
|
33304
33935
|
PasswordJsonCryptoUtil,
|
|
@@ -33317,7 +33948,7 @@ var deployer_default = Deployer;
|
|
|
33317
33948
|
SourceCodeType,
|
|
33318
33949
|
StandardMerkleTree,
|
|
33319
33950
|
Store,
|
|
33320
|
-
|
|
33951
|
+
StrategyLiveStatus,
|
|
33321
33952
|
StrategyTag,
|
|
33322
33953
|
StrategyType,
|
|
33323
33954
|
TelegramGroupNotif,
|
|
@@ -33329,6 +33960,7 @@ var deployer_default = Deployer;
|
|
|
33329
33960
|
UniversalStrategy,
|
|
33330
33961
|
VESU_SINGLETON,
|
|
33331
33962
|
VESU_V2_MODIFY_POSITION_SANITIZER,
|
|
33963
|
+
VaultType,
|
|
33332
33964
|
VesuAdapter,
|
|
33333
33965
|
VesuAmountDenomination,
|
|
33334
33966
|
VesuAmountType,
|
|
@@ -33339,22 +33971,33 @@ var deployer_default = Deployer;
|
|
|
33339
33971
|
ZkLend,
|
|
33340
33972
|
assert,
|
|
33341
33973
|
buildStrategyRegistry,
|
|
33974
|
+
createEkuboCLStrategy,
|
|
33975
|
+
createHyperLSTStrategy,
|
|
33976
|
+
createSenseiStrategy,
|
|
33977
|
+
createStrategy,
|
|
33978
|
+
createUniversalStrategy,
|
|
33979
|
+
createVesuRebalanceStrategy,
|
|
33980
|
+
detectCapabilities,
|
|
33342
33981
|
extensionMap,
|
|
33343
33982
|
getAPIUsingHeadlessBrowser,
|
|
33344
33983
|
getAllStrategyMetadata,
|
|
33984
|
+
getAllStrategyTags,
|
|
33345
33985
|
getContractDetails,
|
|
33346
33986
|
getDefaultStoreConfig,
|
|
33347
33987
|
getFilterMetadata,
|
|
33348
|
-
getFilteredStrategies,
|
|
33349
33988
|
getLiveStrategies,
|
|
33350
33989
|
getMainnetConfig,
|
|
33351
33990
|
getNoRiskTags,
|
|
33352
33991
|
getRiskColor,
|
|
33353
33992
|
getRiskExplaination,
|
|
33354
33993
|
getStrategiesByType,
|
|
33994
|
+
getStrategyTagDesciption,
|
|
33995
|
+
getStrategyTypeFromMetadata,
|
|
33355
33996
|
getTrovesEndpoint,
|
|
33356
33997
|
getVesuSingletonAddress,
|
|
33357
33998
|
highlightTextWithLinks,
|
|
33999
|
+
isDualTokenStrategy,
|
|
33358
34000
|
logger,
|
|
34001
|
+
toAmountsInfo,
|
|
33359
34002
|
toBigInt
|
|
33360
34003
|
});
|