@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/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, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
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: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
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
- StrategyCategory: () => StrategyCategory,
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: "debug",
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
- for (const arg of meta[Symbol.for("splat")]) {
283
- if (arg instanceof Error) {
284
- msg += `
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("0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"),
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://quoter-mainnet-api.ekubo.org/{{AMOUNT}}/{{TOKEN_ADDRESS}}/0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8";
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 import_starknet2 = require("starknet");
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 import_starknet2.Contract({
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 import_starknet3 = require("starknet");
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 import_starknet3.Contract({
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(num11) {
1333
- return Number(num11 * BigInt(1e18) / BigInt(2 ** 128)) / 1e18;
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 import_starknet4 = require("starknet");
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 import_starknet4.Contract({ abi: erc20_abi_default, address: _addr, providerOrAccount: this.config.provider });
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://quoter-mainnet-api.ekubo.org/{{AMOUNT}}/{{TOKEN_FROM_ADDRESS}}/{{TOKEN_TO_ADDRESS}}";
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 StrategyCategory = /* @__PURE__ */ ((StrategyCategory2) => {
2914
- StrategyCategory2["ALL"] = "all";
2915
- StrategyCategory2["BTC"] = "btc";
2916
- StrategyCategory2["META_VAULTS"] = "meta-vaults";
2917
- return StrategyCategory2;
2918
- })(StrategyCategory || {});
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
- const EKUBO_API = `https://starknet-mainnet-api.ekubo.org/airdrops/${addr.address}?token=${STRK}`;
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 items = await resultEkubo.json();
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 < items.length; ++i) {
4688
- const info = items[i];
4689
- assert(info.token == STRK, "expected strk token only");
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(info.contract_address),
4937
+ rewardsContract: ContractAddr.from(claimData.dropAddress),
4692
4938
  token: ContractAddr.from(STRK),
4693
- startDate: new Date(info.start_date),
4694
- endDate: new Date(info.end_date),
4939
+ startDate: /* @__PURE__ */ new Date(0),
4940
+ endDate: /* @__PURE__ */ new Date(0),
4695
4941
  claim: {
4696
- id: info.claim.id,
4697
- amount: Web3Number.fromWei(info.claim.amount, 18),
4698
- claimee: ContractAddr.from(info.claim.claimee)
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(info.claim.amount, 18),
4701
- proof: info.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.VESU_BASE_STAGING}/pools`);
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.VESU_BASE_STAGING}/pools`
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
- name: "Vesu Fusion STRK",
10981
- description: _description,
10982
- address: ContractAddr.from(
10983
- "0x7fb5bcb8525954a60fde4e8fb8220477696ce7117ef264775a1770e23571929"
10984
- ),
10985
- launchBlock: 0,
10986
- type: "ERC4626",
10987
- depositTokens: [
10988
- Global.getDefaultTokens().find((t) => t.symbol === "STRK")
10989
- ],
10990
- protocols: [_protocol],
10991
- auditUrl: AUDIT_URL,
10992
- maxTVL: Web3Number.fromWei("0", 18),
10993
- risk: {
10994
- riskFactor: _riskFactor,
10995
- netRisk: _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
10996
- notARisks: getNoRiskTags(_riskFactor)
10997
- },
10998
- additionalInfo: {
10999
- feeBps: 1e3
11000
- },
11001
- faqs,
11002
- contractDetails: [],
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(num11) {
16686
- return Number(BigInt(num11.toString()) * BigInt(1e18) / BigInt(2 ** 128)) / 1e18;
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.avnu.getQuotes(
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(), 18);
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 netYield = await this.netAPY();
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
- maxTVL: Web3Number.fromWei("0", 18),
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
- category: "all" /* ALL */,
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
- ...xSTRKSTRK,
18073
+ createLSTStrategy({
18074
+ id: "ekubo_cl_xwbtcwbtc",
17723
18075
  name: "Ekubo xWBTC/WBTC",
17724
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17725
- address: ContractAddr.from(
17726
- "0x2ea99b4971d3c277fa4a9b4beb7d4d7d169e683393a29eef263d5d57b4380a"
17727
- ),
18076
+ address: "0x2ea99b4971d3c277fa4a9b4beb7d4d7d169e683393a29eef263d5d57b4380a",
17728
18077
  launchBlock: 2338309,
17729
- // must be same order as poolKey token0 and token1
17730
- depositTokens: [
17731
- Global.getDefaultTokens().find((t) => t.symbol === "WBTC"),
17732
- Global.getDefaultTokens().find((t) => t.symbol === "xWBTC")
17733
- ],
17734
- additionalInfo: {
17735
- ...xSTRKSTRK.additionalInfo,
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
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17750
- address: ContractAddr.from(
17751
- "0x785dc3dfc4e80ef2690a99512481e3ed3a5266180adda5a47e856245d68a4af"
17752
- ),
18086
+ address: "0x785dc3dfc4e80ef2690a99512481e3ed3a5266180adda5a47e856245d68a4af",
17753
18087
  launchBlock: 2415667,
17754
- // must be same order as poolKey token0 and token1
17755
- depositTokens: [
17756
- Global.getDefaultTokens().find((t) => t.symbol === "xtBTC"),
17757
- Global.getDefaultTokens().find((t) => t.symbol === "tBTC")
17758
- ],
17759
- additionalInfo: {
17760
- ...xSTRKSTRK.additionalInfo,
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
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17775
- address: ContractAddr.from(
17776
- "0x3af1c7faa7c464cf2c494e988972ad1939f1103dbfb6e47e9bf0c47e49b14ef"
17777
- ),
18096
+ address: "0x3af1c7faa7c464cf2c494e988972ad1939f1103dbfb6e47e9bf0c47e49b14ef",
17778
18097
  launchBlock: 2344809,
17779
- // must be same order as poolKey token0 and token1
17780
- depositTokens: [
17781
- Global.getDefaultTokens().find((t) => t.symbol === "xsBTC"),
17782
- Global.getDefaultTokens().find((t) => t.symbol === "solvBTC")
17783
- ],
17784
- additionalInfo: {
17785
- ...xSTRKSTRK.additionalInfo,
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
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17800
- address: ContractAddr.from(
17801
- "0x314c4653ab1aa01f5465773cb879f525d7e369a137bc3ae084761aee99a1712"
17802
- ),
18106
+ address: "0x314c4653ab1aa01f5465773cb879f525d7e369a137bc3ae084761aee99a1712",
17803
18107
  launchBlock: 2412442,
17804
- // must be same order as poolKey token0 and token1
17805
- depositTokens: [
17806
- Global.getDefaultTokens().find((t) => t.symbol === "LBTC"),
17807
- Global.getDefaultTokens().find((t) => t.symbol === "xLBTC")
17808
- ],
17809
- additionalInfo: {
17810
- ...xSTRKSTRK.additionalInfo,
17811
- quoteAsset: Global.getDefaultTokens().find((t) => t.symbol === "LBTC"),
17812
- lstContract: Global.getDefaultTokens().find((t) => t.symbol === "xLBTC").address
17813
- },
17814
- faqs: getLSTFAQs("xLBTC"),
17815
- points: [],
17816
- contractDetails: [],
17817
- investmentSteps: [],
17818
- category: "btc" /* BTC */,
17819
- tags: ["Ekubo" /* EKUBO */]
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 ETHUSDCRe7Strategy = {
18178
+ var createRe7Strategy = (id, name, address, launchBlock, depositToken0Symbol, depositToken1Symbol, quoteTokenSymbol, risk, isBTC) => ({
17823
18179
  ...xSTRKSTRK,
17824
- name: "Ekubo ETH/USDC",
18180
+ id,
18181
+ name,
17825
18182
  description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17826
- address: ContractAddr.from(
17827
- "0x160d8fa4569ef6a12e6bf47cb943d7b5ebba8a41a69a14c1d943050ba5ff947"
17828
- ),
17829
- launchBlock: 1504232,
17830
- // must be same order as poolKey token0 and token1
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((t) => t.symbol === "ETH"),
17833
- Global.getDefaultTokens().find((t) => t.symbol === "USDC")
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((t) => t.symbol === "USDC")
18205
+ quoteAsset: Global.getDefaultTokens().find(
18206
+ (t) => t.symbol === quoteTokenSymbol
18207
+ )
17846
18208
  },
17847
- faqs: [
17848
- ...faqs2,
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
- category: "all" /* ALL */,
17866
- tags: ["Ekubo" /* EKUBO */]
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
- ...ETHUSDCRe7Strategy,
17872
- name: "Ekubo USDC/USDT",
17873
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17874
- address: ContractAddr.from(
17875
- "0x3a4f8debaf12af97bb911099bc011d63d6c208d4c5ba8e15d7f437785b0aaa2"
17876
- ),
17877
- launchBlock: 1506139,
17878
- // must be same order as poolKey token0 and token1
17879
- depositTokens: [
17880
- Global.getDefaultTokens().find((t) => t.symbol === "USDC"),
17881
- Global.getDefaultTokens().find((t) => t.symbol === "USDT")
17882
- ],
17883
- risk: {
17884
- riskFactor: _stableCoinPoolRiskFactors,
17885
- netRisk: _stableCoinPoolRiskFactors.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _stableCoinPoolRiskFactors.reduce((acc, curr) => acc + curr.weight, 0),
17886
- notARisks: getNoRiskTags(_stableCoinPoolRiskFactors)
17887
- },
17888
- category: "all" /* ALL */,
17889
- tags: ["Ekubo" /* EKUBO */]
17890
- },
17891
- {
17892
- ...ETHUSDCRe7Strategy,
17893
- name: "Ekubo STRK/USDC",
17894
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17895
- address: ContractAddr.from(
17896
- "0x351b36d0d9d8b40010658825adeeddb1397436cd41acd0ff6c6e23aaa8b5b30"
17897
- ),
17898
- launchBlock: 1504079,
17899
- // must be same order as poolKey token0 and token1
17900
- depositTokens: [
17901
- Global.getDefaultTokens().find((t) => t.symbol === "STRK"),
17902
- Global.getDefaultTokens().find((t) => t.symbol === "USDC")
17903
- ],
17904
- risk: highRisk,
17905
- category: "all" /* ALL */,
17906
- tags: ["Ekubo" /* EKUBO */]
17907
- },
17908
- {
17909
- ...ETHUSDCRe7Strategy,
17910
- name: "Ekubo STRK/ETH",
17911
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17912
- address: ContractAddr.from(
17913
- "0x4ce3024b0ee879009112d7b0e073f8a87153dd35b029347d4247ffe48d28f51"
17914
- ),
17915
- launchBlock: 1504149,
17916
- // must be same order as poolKey token0 and token1
17917
- depositTokens: [
17918
- Global.getDefaultTokens().find((t) => t.symbol === "STRK"),
17919
- Global.getDefaultTokens().find((t) => t.symbol === "ETH")
17920
- ],
17921
- risk: highRisk,
17922
- category: "all" /* ALL */,
17923
- tags: ["Ekubo" /* EKUBO */]
17924
- },
17925
- {
17926
- ...ETHUSDCRe7Strategy,
17927
- name: "Ekubo WBTC/USDC",
17928
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17929
- address: ContractAddr.from(
17930
- "0x2bcaef2eb7706875a5fdc6853dd961a0590f850bc3a031c59887189b5e84ba1"
17931
- ),
17932
- launchBlock: 1506144,
17933
- // must be same order as poolKey token0 and token1
17934
- depositTokens: [
17935
- Global.getDefaultTokens().find((t) => t.symbol === "WBTC"),
17936
- Global.getDefaultTokens().find((t) => t.symbol === "USDC")
17937
- ],
17938
- risk: mediumRisk,
17939
- category: "btc" /* BTC */,
17940
- tags: ["Ekubo" /* EKUBO */]
17941
- },
17942
- {
17943
- ...ETHUSDCRe7Strategy,
17944
- name: "Ekubo tBTC/USDC",
17945
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17946
- address: ContractAddr.from(
17947
- "0x4aad891a2d4432fba06b6558631bb13f6bbd7f6f33ab8c3111e344889ea4456"
17948
- ),
17949
- launchBlock: 1501764,
17950
- // must be same order as poolKey token0 and token1
17951
- depositTokens: [
17952
- Global.getDefaultTokens().find((t) => t.symbol === "tBTC"),
17953
- Global.getDefaultTokens().find((t) => t.symbol === "USDC")
17954
- ],
17955
- risk: mediumRisk,
17956
- category: "btc" /* BTC */,
17957
- tags: ["Ekubo" /* EKUBO */]
17958
- },
17959
- {
17960
- ...ETHUSDCRe7Strategy,
17961
- name: "Ekubo WBTC/ETH",
17962
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17963
- address: ContractAddr.from(
17964
- "0x1c9232b8186d9317652f05055615f18a120c2ad9e5ee96c39e031c257fb945b"
17965
- ),
17966
- launchBlock: 1506145,
17967
- // must be same order as poolKey token0 and token1
17968
- depositTokens: [
17969
- Global.getDefaultTokens().find((t) => t.symbol === "WBTC"),
17970
- Global.getDefaultTokens().find((t) => t.symbol === "ETH")
17971
- ],
17972
- risk: mediumRisk,
17973
- category: "btc" /* BTC */,
17974
- tags: ["Ekubo" /* EKUBO */]
17975
- },
17976
- {
17977
- ...ETHUSDCRe7Strategy,
17978
- name: "Ekubo WBTC/STRK",
17979
- description: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}),
17980
- address: ContractAddr.from(
17981
- "0x1248e385c23a929a015ec298a26560fa7745bbd6e41a886550e337b02714b1b"
17982
- ),
17983
- launchBlock: 1506147,
17984
- // must be same order as poolKey token0 and token1
17985
- depositTokens: [
17986
- Global.getDefaultTokens().find((t) => t.symbol === "WBTC"),
17987
- Global.getDefaultTokens().find((t) => t.symbol === "STRK")
17988
- ],
17989
- risk: highRisk,
17990
- category: "btc" /* BTC */,
17991
- tags: ["Ekubo" /* EKUBO */]
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 import_starknet13 = require("starknet");
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/sensei.ts
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(import_starknet14.num.getDecimalString(import_starknet14.shortString.encodeShortString(id))),
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(import_starknet14.hash.getSelectorFromName(method)),
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 import_starknet16.CairoCustomEnum({ IncreaseLever: {
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(import_starknet16.num.hexToDecimalString(route.pool_key.extension))
27419
+ extension: BigInt(import_starknet14.num.hexToDecimalString(route.pool_key.extension))
27525
27420
  },
27526
- sqrt_ratio_limit: import_starknet16.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
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(import_starknet16.num.hexToDecimalString(route.pool_key.extension))
27437
+ extension: BigInt(import_starknet14.num.hexToDecimalString(route.pool_key.extension))
27543
27438
  },
27544
- sqrt_ratio_limit: import_starknet16.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
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 import_starknet16.CairoCustomEnum({ DecreaseLever: {
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: import_starknet16.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
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: import_starknet16.uint256.bnToUint256(route.sqrt_ratio_limit.toWei()),
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: import_starknet16.uint256.bnToUint256(params.collateralAmount.value.abs.toWei()),
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: import_starknet16.uint256.bnToUint256(params.debtAmount.value.abs.toWei()),
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: import_starknet16.hash.getSelectorFromName("modify_position"),
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 import_starknet16.Contract({ abi: vesu_multiple_abi_default, address: VESU_MULTIPLY.toString(), providerOrAccount: new import_starknet16.RpcProvider({ nodeUrl: "" }) });
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: import_starknet16.hash.getSelectorFromName("modify_lever"),
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: import_starknet16.hash.getSelectorFromName("modify_delegation"),
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(import_starknet16.num.getDecimalString(import_starknet16.shortString.encodeShortString(id))),
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(import_starknet16.hash.getSelectorFromName("claim")),
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: import_starknet16.hash.getSelectorFromName("claim"),
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(import_starknet16.num.hexToDecimalString(proof)))
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 import_starknet16.CairoCustomEnum({ Delta: {} });
27750
+ return new import_starknet14.CairoCustomEnum({ Delta: {} });
27855
27751
  case 1 /* Target */:
27856
- return new import_starknet16.CairoCustomEnum({ Target: {} });
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 import_starknet16.CairoCustomEnum({ Native: {} });
27759
+ return new import_starknet14.CairoCustomEnum({ Native: {} });
27864
27760
  case 1 /* Assets */:
27865
- return new import_starknet16.CairoCustomEnum({ Assets: {} });
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 import_starknet16.Contract({ abi: ABI, address: VESU_SINGLETON2.address, providerOrAccount: config.provider }),
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 import_starknet16.Contract({ abi: vesu_extension_abi_default, address: extensionAddr.address, providerOrAccount: config.provider });
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 import_starknet16.Contract({ abi: vesu_extension_abi_default, address: extensionAddr.address, providerOrAccount: config.provider });
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 currentDebt = new Web3Number((Number(assetConfig.total_nominal_debt) / 1e18).toFixed(9), asset.decimals);
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.VESU_BASE_STAGING}/pools`
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.3,
31168
- minHealthFactor: 1.25
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.3,
31179
- minHealthFactor: 1.25
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.3,
31190
- minHealthFactor: 1.25
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.3,
31201
- minHealthFactor: 1.25
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.3,
31212
- minHealthFactor: 1.25
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 asset to the best available yield source in the ecosystem. Depositors receive vault shares that 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." }),
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
- name: "USDC Evergreen",
31372
- description: getDescription("USDC", ["vesu", "extended"]),
31373
- address: ContractAddr.from("0x7e6498cf6a1bfc7e6fc89f1831865e2dacb9756def4ec4b031a9138788a3b5e"),
31374
- launchBlock: 0,
31375
- type: "ERC4626",
31376
- depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === "USDC")],
31377
- additionalInfo: getLooperSettings("USDC", "ETH", usdcVaultSettings, VesuPools.Genesis, VesuPools.Genesis),
31378
- risk: {
31379
- riskFactor: _riskFactor3,
31380
- netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
31381
- notARisks: getNoRiskTags(_riskFactor3)
31382
- },
31383
- auditUrl: AUDIT_URL3,
31384
- protocols: [Protocols.VESU],
31385
- maxTVL: Web3Number.fromWei(0, 6),
31386
- contractDetails: getContractDetails(usdcVaultSettings),
31387
- faqs: getFAQs(),
31388
- investmentSteps,
31389
- category: "meta-vaults" /* META_VAULTS */,
31390
- tags: ["Evergreen" /* EVERGREEN */],
31391
- security: EVERGREEN_SECURITY,
31392
- redemptionInfo: EVERGREEN_REDEMPTION_INFO
31393
- },
31394
- {
31395
- name: "WBTC Evergreen",
31396
- description: getDescription("WBTC", ["vesu", "endur", "extended"]),
31397
- address: ContractAddr.from("0x5a4c1651b913aa2ea7afd9024911603152a19058624c3e425405370d62bf80c"),
31398
- launchBlock: 0,
31399
- type: "ERC4626",
31400
- depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === "WBTC")],
31401
- additionalInfo: getLooperSettings("WBTC", "ETH", wbtcVaultSettings, VesuPools.Genesis, VesuPools.Genesis),
31402
- risk: {
31403
- riskFactor: _riskFactor3,
31404
- netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
31405
- notARisks: getNoRiskTags(_riskFactor3)
31406
- },
31407
- protocols: [Protocols.VESU],
31408
- maxTVL: Web3Number.fromWei(0, 8),
31409
- contractDetails: getContractDetails(wbtcVaultSettings),
31410
- faqs: getFAQs(),
31411
- investmentSteps,
31412
- auditUrl: AUDIT_URL3,
31413
- category: "meta-vaults" /* META_VAULTS */,
31414
- tags: ["Evergreen" /* EVERGREEN */],
31415
- security: EVERGREEN_SECURITY,
31416
- redemptionInfo: EVERGREEN_REDEMPTION_INFO
31417
- },
31418
- {
31419
- name: "ETH Evergreen",
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 baseAdapter = this.getVesuSameTokenAdapter();
31561
- for (const asset of this.metadata.additionalInfo.borrowable_assets) {
31562
- const vesuAdapter1 = new VesuAdapter({
31563
- poolId: baseAdapter.config.poolId,
31564
- collateral: this.asset(),
31565
- debt: asset,
31566
- vaultAllocator: this.metadata.additionalInfo.vaultAllocator,
31567
- id: ""
31568
- });
31569
- vesuAdapter1.pricer = this.pricer;
31570
- vesuAdapter1.networkConfig = this.config;
31571
- adapters.push(vesuAdapter1);
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
- maxBorrowables.push(await this.getMaxBorrowableAmountByVesuAdapter(vesuAdapter, params.isAPYComputation));
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
- const maxBorrowable = maxBorrowableAmount.minimum(debtCap).multipliedBy(0.999);
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 maxBorrowableAmount = maxBorrowableAmounts.maxBorrowables.find((b) => b.borrowableAsset.address.eq(adapter.config.debt.address))?.amount;
31995
- if (!maxBorrowableAmount) {
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
- const maxLTV = await adapter.getLTVConfig(this.config);
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 getVesuLegId(baseID, debtTokenSymbol) {
32178
- return `${baseID}_${debtTokenSymbol.toLowerCase()}`;
32737
+ function getVesuGenericLegId(poolId, action) {
32738
+ return `${action}_${poolId.slice(-4).toLowerCase()}`;
32179
32739
  }
32180
- function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
32181
- vaultSettings.leafAdapters = [];
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: pool1,
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 { isV2, addr: poolAddr } = getVesuSingletonAddress(pool1);
32206
- const VESU_MULTIPLY = isV2 ? vesuAdapterLST.VESU_MULTIPLY : vesuAdapterLST.VESU_MULTIPLY_V1;
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
- const multiplID = getVesuLegId("multiply_vesu" /* MULTIPLY_VESU */, debtAsset.symbol);
32229
- vaultSettings.leafAdapters.push(vesuAdapter.getMultiplyAdapter(multiplID).bind(vesuAdapter));
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
- depositTokens: [Global.getDefaultTokens().find((token) => token.symbol === lstSymbol)],
32380
- additionalInfo: getLooperSettings2(lstSymbol, underlyingSymbol, addresses, lstSymbol === "xSTRK" ? VesuPools.Re7xSTRK : VesuPools.Re7xBTC),
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((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor4.reduce((acc, curr) => acc + curr.weight, 0),
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
- maxTVL: Web3Number.fromWei(0, 18),
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
- category: "meta-vaults" /* META_VAULTS */,
32395
- tags: ["Hyper-LST" /* HYPER_LST */],
32396
- security: {
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 assets = Array.from(assetSet).sort().map((id) => ({
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 === "meta-vaults" ? "Meta Vaults" : id.charAt(0).toUpperCase() + id.slice(1)
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: "btc", label: "BTC" },
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
- function getFilteredStrategies(criteria) {
32560
- let allMetadata = getAllStrategyMetadata();
32561
- if (!criteria.showRetired) {
32562
- allMetadata = allMetadata.filter((meta) => !meta.isRetired);
32563
- }
32564
- if (criteria.assets && criteria.assets.length > 0) {
32565
- allMetadata = allMetadata.filter(
32566
- (meta) => meta.assets.some(
32567
- (asset) => criteria.assets.includes(asset.toLowerCase())
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 (criteria.protocols && criteria.protocols.length > 0) {
32572
- allMetadata = allMetadata.filter(
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 (criteria.categories && criteria.categories.length > 0) {
32579
- allMetadata = allMetadata.filter(
32580
- (meta) => criteria.categories.includes(meta.category)
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://quoter-mainnet-api.ekubo.org/{{AMOUNT}}/{{TOKEN_ADDRESS}}/{{UNDERLYING_ADDRESS}}";
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
- StrategyCategory,
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
  });