@strkfarm/sdk 1.1.22 → 1.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.global.js +14140 -1682
- package/dist/index.browser.mjs +144 -21
- package/dist/index.d.ts +12 -1
- package/dist/index.js +145 -22
- package/dist/index.mjs +145 -22
- package/package.json +3 -1
- package/src/modules/apollo-client.ts +8 -0
- package/src/notifs/telegram-group.ts +1 -1
- package/src/strategies/ekubo-cl-vault.tsx +133 -7
- package/src/strategies/universal-lst-muliplier-strategy.tsx +25 -16
- package/src/strategies/universal-strategy.tsx +7 -0
package/dist/index.mjs
CHANGED
|
@@ -15288,6 +15288,17 @@ var erc4626_abi_default = [
|
|
|
15288
15288
|
}
|
|
15289
15289
|
];
|
|
15290
15290
|
|
|
15291
|
+
// src/strategies/ekubo-cl-vault.tsx
|
|
15292
|
+
import { gql } from "@apollo/client";
|
|
15293
|
+
|
|
15294
|
+
// src/modules/apollo-client.ts
|
|
15295
|
+
import { ApolloClient, InMemoryCache } from "@apollo/client";
|
|
15296
|
+
var apolloClient = new ApolloClient({
|
|
15297
|
+
uri: "https://api.troves.fi/",
|
|
15298
|
+
cache: new InMemoryCache()
|
|
15299
|
+
});
|
|
15300
|
+
var apollo_client_default = apolloClient;
|
|
15301
|
+
|
|
15291
15302
|
// src/strategies/ekubo-cl-vault.tsx
|
|
15292
15303
|
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
15293
15304
|
var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
@@ -15445,11 +15456,75 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
15445
15456
|
handleFeesCall() {
|
|
15446
15457
|
return [this.contract.populate("handle_fees", [])];
|
|
15447
15458
|
}
|
|
15448
|
-
|
|
15449
|
-
|
|
15450
|
-
|
|
15451
|
-
|
|
15452
|
-
|
|
15459
|
+
async getFeeHistory(timePeriod = "24h") {
|
|
15460
|
+
const { data } = await apollo_client_default.query({
|
|
15461
|
+
query: gql`
|
|
15462
|
+
query ContractFeeEarnings(
|
|
15463
|
+
$timeframe: String!
|
|
15464
|
+
$contract: String!
|
|
15465
|
+
) {
|
|
15466
|
+
contractFeeEarnings(timeframe: $timeframe, contract: $contract) {
|
|
15467
|
+
contract
|
|
15468
|
+
dailyEarnings {
|
|
15469
|
+
date
|
|
15470
|
+
tokenAddress
|
|
15471
|
+
amount
|
|
15472
|
+
}
|
|
15473
|
+
totalCollections
|
|
15474
|
+
}
|
|
15475
|
+
}
|
|
15476
|
+
`,
|
|
15477
|
+
variables: {
|
|
15478
|
+
timeframe: timePeriod,
|
|
15479
|
+
contract: this.address.address
|
|
15480
|
+
},
|
|
15481
|
+
fetchPolicy: "no-cache"
|
|
15482
|
+
});
|
|
15483
|
+
const poolKey = await this.getPoolKey();
|
|
15484
|
+
const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
|
|
15485
|
+
const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
|
|
15486
|
+
const price0 = await this.pricer.getPrice(token0Info.symbol);
|
|
15487
|
+
const price1 = await this.pricer.getPrice(token1Info.symbol);
|
|
15488
|
+
let totalToken0Amount = Web3Number.fromWei(0, token0Info.decimals);
|
|
15489
|
+
let totalToken1Amount = Web3Number.fromWei(0, token1Info.decimals);
|
|
15490
|
+
let totalToken0Usd = 0;
|
|
15491
|
+
let totalToken1Usd = 0;
|
|
15492
|
+
const parsedFeeInfo = [];
|
|
15493
|
+
const feeInfo = data.contractFeeEarnings.dailyEarnings;
|
|
15494
|
+
for (const d of feeInfo) {
|
|
15495
|
+
const tokenInfo = await Global.getTokenInfoFromAddr(ContractAddr.from(d.tokenAddress));
|
|
15496
|
+
const amount = Web3Number.fromWei(d.amount, tokenInfo.decimals);
|
|
15497
|
+
if (tokenInfo.address.eq(poolKey.token0)) {
|
|
15498
|
+
totalToken0Amount = totalToken0Amount.plus(amount);
|
|
15499
|
+
totalToken0Usd = totalToken0Usd + amount.multipliedBy(price0.price).toNumber();
|
|
15500
|
+
} else {
|
|
15501
|
+
totalToken1Amount = totalToken1Amount.plus(amount);
|
|
15502
|
+
totalToken1Usd = totalToken1Usd + amount.multipliedBy(price1.price).toNumber();
|
|
15503
|
+
}
|
|
15504
|
+
parsedFeeInfo.push({
|
|
15505
|
+
date: d.date,
|
|
15506
|
+
tokenInfo,
|
|
15507
|
+
amount: Web3Number.fromWei(d.amount, tokenInfo.decimals)
|
|
15508
|
+
});
|
|
15509
|
+
}
|
|
15510
|
+
return {
|
|
15511
|
+
summary: {
|
|
15512
|
+
usdValue: totalToken0Usd + totalToken1Usd,
|
|
15513
|
+
token0: {
|
|
15514
|
+
tokenInfo: token0Info,
|
|
15515
|
+
amount: totalToken0Amount,
|
|
15516
|
+
usdValue: totalToken0Usd
|
|
15517
|
+
},
|
|
15518
|
+
token1: {
|
|
15519
|
+
tokenInfo: token1Info,
|
|
15520
|
+
amount: totalToken1Amount,
|
|
15521
|
+
usdValue: totalToken1Usd
|
|
15522
|
+
}
|
|
15523
|
+
},
|
|
15524
|
+
history: parsedFeeInfo
|
|
15525
|
+
};
|
|
15526
|
+
}
|
|
15527
|
+
async netSharesBasedTrueAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
|
|
15453
15528
|
const tvlNow = await this._getTVL(blockIdentifier);
|
|
15454
15529
|
const supplyNow = await this.totalSupply(blockIdentifier);
|
|
15455
15530
|
const priceNow = await this.getCurrentPrice(blockIdentifier);
|
|
@@ -15487,6 +15562,23 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
|
|
|
15487
15562
|
) / 1e4;
|
|
15488
15563
|
return apyForGivenBlocks * (365 * 24 * 3600) / timeDiffSeconds;
|
|
15489
15564
|
}
|
|
15565
|
+
async feeBasedAPY(timeperiod = "24h") {
|
|
15566
|
+
const feeInfo = await this.getFeeHistory(timeperiod);
|
|
15567
|
+
const tvlNow = await this.getTVL("latest");
|
|
15568
|
+
return feeInfo.summary.usdValue * 365 / tvlNow.usdValue;
|
|
15569
|
+
}
|
|
15570
|
+
/**
|
|
15571
|
+
* Calculates assets before and now in a given token of TVL per share to observe growth
|
|
15572
|
+
* @returns {Promise<number>} The weighted average APY across all pools
|
|
15573
|
+
*/
|
|
15574
|
+
async netAPY(blockIdentifier = "latest", sinceBlocks = 6e5, timeperiod = "24h") {
|
|
15575
|
+
const isUSDCQouteToken = this.metadata.additionalInfo.quoteAsset.symbol === "USDC";
|
|
15576
|
+
if (!isUSDCQouteToken) {
|
|
15577
|
+
return this.netSharesBasedTrueAPY(blockIdentifier, sinceBlocks);
|
|
15578
|
+
} else {
|
|
15579
|
+
return this.feeBasedAPY(timeperiod);
|
|
15580
|
+
}
|
|
15581
|
+
}
|
|
15490
15582
|
async getHarvestRewardShares(fromBlock, toBlock) {
|
|
15491
15583
|
const len = Number(await this.contract.call("get_total_rewards"));
|
|
15492
15584
|
let shares = Web3Number.fromWei(0, 18);
|
|
@@ -16501,7 +16593,7 @@ var highRisk = {
|
|
|
16501
16593
|
netRisk: highVolatilityPoolRiskFactors.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / highVolatilityPoolRiskFactors.reduce((acc, curr) => acc + curr.weight, 0),
|
|
16502
16594
|
notARisks: getNoRiskTags(highVolatilityPoolRiskFactors)
|
|
16503
16595
|
};
|
|
16504
|
-
var AUDIT_URL2 = "https://
|
|
16596
|
+
var AUDIT_URL2 = "https://docs.troves.fi/p/security#ekubo-vault";
|
|
16505
16597
|
var faqs2 = [
|
|
16506
16598
|
{
|
|
16507
16599
|
question: "What is the Ekubo CL Vault strategy?",
|
|
@@ -16700,7 +16792,7 @@ var ETHUSDCRe7Strategy = {
|
|
|
16700
16792
|
Global.getDefaultTokens().find((t) => t.symbol === "ETH"),
|
|
16701
16793
|
Global.getDefaultTokens().find((t) => t.symbol === "USDC")
|
|
16702
16794
|
],
|
|
16703
|
-
apyMethodology: "APY
|
|
16795
|
+
apyMethodology: "Annualized fee APY, calculated as fees earned in the last 24h divided by TVL",
|
|
16704
16796
|
additionalInfo: {
|
|
16705
16797
|
newBounds: "Managed by Re7",
|
|
16706
16798
|
truePrice: 1,
|
|
@@ -16721,6 +16813,10 @@ var ETHUSDCRe7Strategy = {
|
|
|
16721
16813
|
/* @__PURE__ */ jsx3("a", { href: "https://www.re7labs.xyz", style: { textDecoration: "underline", marginLeft: "2px" }, target: "_blank", children: "here" }),
|
|
16722
16814
|
"."
|
|
16723
16815
|
] })
|
|
16816
|
+
},
|
|
16817
|
+
{
|
|
16818
|
+
question: "How is the APY calculated?",
|
|
16819
|
+
answer: /* @__PURE__ */ jsx3("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." })
|
|
16724
16820
|
}
|
|
16725
16821
|
],
|
|
16726
16822
|
risk: highRisk,
|
|
@@ -27328,6 +27424,7 @@ var investmentSteps = [
|
|
|
27328
27424
|
"Vault manager reports asset under management (AUM) regularly to the vault",
|
|
27329
27425
|
"Request withdrawal and vault manager processes it in 1-2 hours"
|
|
27330
27426
|
];
|
|
27427
|
+
var AUDIT_URL3 = "https://docs.troves.fi/p/security#starknet-vault-kit";
|
|
27331
27428
|
var UniversalStrategies = [
|
|
27332
27429
|
{
|
|
27333
27430
|
name: "USDC Evergreen",
|
|
@@ -27342,6 +27439,7 @@ var UniversalStrategies = [
|
|
|
27342
27439
|
netRisk: _riskFactor3.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor3.reduce((acc, curr) => acc + curr.weight, 0),
|
|
27343
27440
|
notARisks: getNoRiskTags(_riskFactor3)
|
|
27344
27441
|
},
|
|
27442
|
+
auditUrl: AUDIT_URL3,
|
|
27345
27443
|
protocols: [Protocols.VESU],
|
|
27346
27444
|
maxTVL: Web3Number.fromWei(0, 6),
|
|
27347
27445
|
contractDetails: getContractDetails(usdcVaultSettings),
|
|
@@ -27365,7 +27463,8 @@ var UniversalStrategies = [
|
|
|
27365
27463
|
maxTVL: Web3Number.fromWei(0, 8),
|
|
27366
27464
|
contractDetails: getContractDetails(wbtcVaultSettings),
|
|
27367
27465
|
faqs: getFAQs(),
|
|
27368
|
-
investmentSteps
|
|
27466
|
+
investmentSteps,
|
|
27467
|
+
auditUrl: AUDIT_URL3
|
|
27369
27468
|
},
|
|
27370
27469
|
{
|
|
27371
27470
|
name: "ETH Evergreen",
|
|
@@ -27384,7 +27483,8 @@ var UniversalStrategies = [
|
|
|
27384
27483
|
maxTVL: Web3Number.fromWei(0, 18),
|
|
27385
27484
|
contractDetails: getContractDetails(ethVaultSettings),
|
|
27386
27485
|
faqs: getFAQs(),
|
|
27387
|
-
investmentSteps
|
|
27486
|
+
investmentSteps,
|
|
27487
|
+
auditUrl: AUDIT_URL3
|
|
27388
27488
|
},
|
|
27389
27489
|
{
|
|
27390
27490
|
name: "STRK Evergreen",
|
|
@@ -27403,7 +27503,8 @@ var UniversalStrategies = [
|
|
|
27403
27503
|
maxTVL: Web3Number.fromWei(0, 18),
|
|
27404
27504
|
contractDetails: getContractDetails(strkVaultSettings),
|
|
27405
27505
|
faqs: getFAQs(),
|
|
27406
|
-
investmentSteps
|
|
27506
|
+
investmentSteps,
|
|
27507
|
+
auditUrl: AUDIT_URL3
|
|
27407
27508
|
},
|
|
27408
27509
|
{
|
|
27409
27510
|
name: "USDT Evergreen",
|
|
@@ -27422,7 +27523,8 @@ var UniversalStrategies = [
|
|
|
27422
27523
|
maxTVL: Web3Number.fromWei(0, 6),
|
|
27423
27524
|
contractDetails: getContractDetails(usdtVaultSettings),
|
|
27424
27525
|
faqs: getFAQs(),
|
|
27425
|
-
investmentSteps
|
|
27526
|
+
investmentSteps,
|
|
27527
|
+
auditUrl: AUDIT_URL3
|
|
27426
27528
|
}
|
|
27427
27529
|
];
|
|
27428
27530
|
|
|
@@ -27632,7 +27734,7 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
27632
27734
|
return [this.getManageCall(proofsIDs, manageCalls)];
|
|
27633
27735
|
}
|
|
27634
27736
|
};
|
|
27635
|
-
function VaultDescription() {
|
|
27737
|
+
function VaultDescription(lstSymbol, underlyingSymbol) {
|
|
27636
27738
|
const containerStyle = {
|
|
27637
27739
|
maxWidth: "800px",
|
|
27638
27740
|
margin: "0 auto",
|
|
@@ -27642,8 +27744,27 @@ function VaultDescription() {
|
|
|
27642
27744
|
borderRadius: "12px"
|
|
27643
27745
|
};
|
|
27644
27746
|
return /* @__PURE__ */ jsxs4("div", { style: containerStyle, children: [
|
|
27645
|
-
/* @__PURE__ */
|
|
27646
|
-
|
|
27747
|
+
/* @__PURE__ */ jsxs4("h1", { style: { fontSize: "18px", marginBottom: "10px" }, children: [
|
|
27748
|
+
"Liquidation risk managed leverged ",
|
|
27749
|
+
lstSymbol,
|
|
27750
|
+
" Vault"
|
|
27751
|
+
] }),
|
|
27752
|
+
/* @__PURE__ */ jsxs4("p", { style: { fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }, children: [
|
|
27753
|
+
"This Levered Endur ",
|
|
27754
|
+
lstSymbol,
|
|
27755
|
+
" vault is a tokenized leveraged Vault, auto-compounding strategy that takes upto 5x leverage on ",
|
|
27756
|
+
lstSymbol,
|
|
27757
|
+
" by borrow ",
|
|
27758
|
+
underlyingSymbol,
|
|
27759
|
+
". Borrowed amount is swapped to ",
|
|
27760
|
+
lstSymbol,
|
|
27761
|
+
" to create leverage. Depositors receive vault shares that represent a proportional claim on the underlying assets and accrued yield."
|
|
27762
|
+
] }),
|
|
27763
|
+
/* @__PURE__ */ jsxs4("p", { style: { fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }, children: [
|
|
27764
|
+
"This vault uses Vesu for lending and borrowing. The oracle used by this pool is a ",
|
|
27765
|
+
highlightTextWithLinks("conversion rate oracle", [{ highlight: "conversion rate oracle", link: "https://docs.pragma.build/starknet/development#conversion-rate" }]),
|
|
27766
|
+
"which is resilient to liquidity issues and price volatility, hence reducing the risk of liquidation. However, overtime, if left un-monitored, debt can increase enough to trigger a liquidation. But no worries, our continuous monitoring systems look for situations with reduced health factor and balance collateral/debt to bring it back to safe levels. With Troves, you can have a peaceful sleep."
|
|
27767
|
+
] }),
|
|
27647
27768
|
/* @__PURE__ */ jsx5("div", { style: { backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }, children: /* @__PURE__ */ jsxs4("p", { style: { fontSize: "13px", color: "#ccc" }, children: [
|
|
27648
27769
|
/* @__PURE__ */ jsx5("strong", { children: "Withdrawals:" }),
|
|
27649
27770
|
" Requests can take up to ",
|
|
@@ -27652,8 +27773,8 @@ function VaultDescription() {
|
|
|
27652
27773
|
] }) })
|
|
27653
27774
|
] });
|
|
27654
27775
|
}
|
|
27655
|
-
function getDescription2(tokenSymbol) {
|
|
27656
|
-
return VaultDescription();
|
|
27776
|
+
function getDescription2(tokenSymbol, underlyingSymbol) {
|
|
27777
|
+
return VaultDescription(tokenSymbol, underlyingSymbol);
|
|
27657
27778
|
}
|
|
27658
27779
|
function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
|
|
27659
27780
|
vaultSettings.leafAdapters = [];
|
|
@@ -27694,11 +27815,12 @@ function getLooperSettings2(lstSymbol, underlyingSymbol, vaultSettings, pool1) {
|
|
|
27694
27815
|
vaultSettings.leafAdapters.push(commonAdapter.getAvnuAdapter(STRKToken.address, lstToken.address, "avnu_swap_rewards" /* AVNU_SWAP_REWARDS */).bind(commonAdapter));
|
|
27695
27816
|
return vaultSettings;
|
|
27696
27817
|
}
|
|
27818
|
+
var AUDIT_URL4 = "https://docs.troves.fi/p/security#starknet-vault-kit";
|
|
27697
27819
|
function getFAQs2(lstSymbol, underlyingSymbol) {
|
|
27698
27820
|
return [
|
|
27699
27821
|
{
|
|
27700
27822
|
question: `What is the Hyper ${lstSymbol} Vault?`,
|
|
27701
|
-
answer: `The Hyper ${lstSymbol} Vault is a tokenized strategy that automatically loops your ${
|
|
27823
|
+
answer: `The Hyper ${lstSymbol} Vault is a tokenized strategy that automatically loops your ${lstSymbol} to create up to 5x leverage to hence yield in a very low risk manner.`
|
|
27702
27824
|
},
|
|
27703
27825
|
{
|
|
27704
27826
|
question: "How does yield allocation work?",
|
|
@@ -27742,8 +27864,9 @@ function getFAQs2(lstSymbol, underlyingSymbol) {
|
|
|
27742
27864
|
}
|
|
27743
27865
|
var _riskFactor4 = [
|
|
27744
27866
|
{ type: "Smart Contract Risk" /* SMART_CONTRACT_RISK */, value: 2 /* WELL_AUDITED */, weight: 25, reason: "Audited by Zellic" },
|
|
27745
|
-
{ type: "Liquidation Risk" /* LIQUIDATION_RISK */, value: 1 /* VERY_LOW_PROBABILITY */, weight:
|
|
27746
|
-
{ type: "Technical Risk" /* TECHNICAL_RISK */, value: 1 /* STABLE_INFRASTRUCTURE */, weight:
|
|
27867
|
+
{ type: "Liquidation Risk" /* LIQUIDATION_RISK */, value: 1 /* VERY_LOW_PROBABILITY */, weight: 25, reason: "The collateral and debt are highly correlated" },
|
|
27868
|
+
{ type: "Technical Risk" /* TECHNICAL_RISK */, value: 1 /* STABLE_INFRASTRUCTURE */, weight: 25, reason: "Liquidation can only happen if vault is left un-monitored for weeks, which is highly unlikely. We actively monitor all services on a daily basis." },
|
|
27869
|
+
{ type: "Depeg Risk" /* DEPEG_RISK */, value: 2 /* GENERALLY_STABLE */, weight: 25, reason: "Generally stable pegged assets" }
|
|
27747
27870
|
];
|
|
27748
27871
|
var hyperxSTRK = {
|
|
27749
27872
|
vaultAddress: ContractAddr.from("0x46c7a54c82b1fe374353859f554a40b8bd31d3e30f742901579e7b57b1b5960"),
|
|
@@ -27806,14 +27929,13 @@ function getInvestmentSteps(lstSymbol, underlyingSymbol) {
|
|
|
27806
27929
|
`The vault manager loops the ${underlyingSymbol} to buy ${lstSymbol}`,
|
|
27807
27930
|
`The vault manager collateralizes the ${lstSymbol} on Vesu`,
|
|
27808
27931
|
`The vault manager borrows more ${underlyingSymbol} to loop further`,
|
|
27809
|
-
`Claim BTCFi STRK rewards weekly to swap to ${lstSymbol} and reinvest`,
|
|
27810
27932
|
`If required, adjust leverage or re-allocate assets within LST pool on Vesu to optimize yield`
|
|
27811
27933
|
];
|
|
27812
27934
|
}
|
|
27813
27935
|
function getStrategySettings(lstSymbol, underlyingSymbol, addresses, isPreview = false) {
|
|
27814
27936
|
return {
|
|
27815
27937
|
name: `Hyper ${lstSymbol}`,
|
|
27816
|
-
description: getDescription2(lstSymbol),
|
|
27938
|
+
description: getDescription2(lstSymbol, underlyingSymbol),
|
|
27817
27939
|
address: addresses.vaultAddress,
|
|
27818
27940
|
launchBlock: 0,
|
|
27819
27941
|
type: "Other",
|
|
@@ -27824,6 +27946,7 @@ function getStrategySettings(lstSymbol, underlyingSymbol, addresses, isPreview =
|
|
|
27824
27946
|
netRisk: _riskFactor4.reduce((acc, curr) => acc + curr.value * curr.weight, 0) / _riskFactor4.reduce((acc, curr) => acc + curr.weight, 0),
|
|
27825
27947
|
notARisks: getNoRiskTags(_riskFactor4)
|
|
27826
27948
|
},
|
|
27949
|
+
auditUrl: AUDIT_URL4,
|
|
27827
27950
|
protocols: [Protocols.ENDUR, Protocols.VESU],
|
|
27828
27951
|
maxTVL: Web3Number.fromWei(0, 18),
|
|
27829
27952
|
contractDetails: getContractDetails(addresses),
|
|
@@ -27936,7 +28059,7 @@ var TelegramNotif = class {
|
|
|
27936
28059
|
import TelegramBot2 from "node-telegram-bot-api";
|
|
27937
28060
|
var TelegramGroupNotif = class {
|
|
27938
28061
|
constructor(token, groupId, topicId) {
|
|
27939
|
-
this.bot = new TelegramBot2(token, { polling:
|
|
28062
|
+
this.bot = new TelegramBot2(token, { polling: false });
|
|
27940
28063
|
this.groupId = groupId;
|
|
27941
28064
|
this.topicId = topicId;
|
|
27942
28065
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strkfarm/sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.24",
|
|
4
4
|
"description": "STRKFarm TS SDK (Meant for our internal use, but feel free to use it)",
|
|
5
5
|
"typings": "dist/index.d.ts",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"starknet": "8.5.2"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
+
"@apollo/client": "3.11.8",
|
|
60
61
|
"@avnu/avnu-sdk": "3.0.2",
|
|
61
62
|
"@ericnordelo/strk-merkle-tree": "^1.0.0",
|
|
62
63
|
"@noble/curves": "^1.0.0",
|
|
@@ -68,6 +69,7 @@
|
|
|
68
69
|
"chalk": "^4.1.2",
|
|
69
70
|
"commander": "^12.1.0",
|
|
70
71
|
"ethers": "^6.13.5",
|
|
72
|
+
"graphql": "16.9.0",
|
|
71
73
|
"inquirer": "^10.1.2",
|
|
72
74
|
"node-telegram-bot-api": "^0.66.0",
|
|
73
75
|
"proxy-from-env": "^1.1.0",
|
|
@@ -7,7 +7,7 @@ export class TelegramGroupNotif {
|
|
|
7
7
|
private topicId?: number;
|
|
8
8
|
|
|
9
9
|
constructor(token: string, groupId: string, topicId?: number) {
|
|
10
|
-
this.bot = new TelegramBot(token, { polling:
|
|
10
|
+
this.bot = new TelegramBot(token, { polling: false });
|
|
11
11
|
this.groupId = groupId;
|
|
12
12
|
this.topicId = topicId;
|
|
13
13
|
}
|
|
@@ -37,6 +37,8 @@ import { EkuboHarvests } from "@/modules/harvests";
|
|
|
37
37
|
import { logger } from "@/utils/logger";
|
|
38
38
|
import { COMMON_CONTRACTS } from "./constants";
|
|
39
39
|
import { DepegRiskLevel, ImpermanentLossLevel, MarketRiskLevel, SmartContractRiskLevel } from "@/interfaces/risks";
|
|
40
|
+
import { gql } from "@apollo/client";
|
|
41
|
+
import apolloClient from "@/modules/apollo-client";
|
|
40
42
|
|
|
41
43
|
export interface EkuboPoolKey {
|
|
42
44
|
token0: ContractAddr;
|
|
@@ -51,6 +53,12 @@ export interface EkuboBounds {
|
|
|
51
53
|
upperTick: bigint;
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
interface FeeHistory {
|
|
57
|
+
date: string;
|
|
58
|
+
tokenInfo: TokenInfo;
|
|
59
|
+
amount: Web3Number;
|
|
60
|
+
}
|
|
61
|
+
|
|
54
62
|
/**
|
|
55
63
|
* Settings for the CLVaultStrategy
|
|
56
64
|
*
|
|
@@ -285,11 +293,97 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
285
293
|
return [this.contract.populate("handle_fees", [])];
|
|
286
294
|
}
|
|
287
295
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
296
|
+
async getFeeHistory(timePeriod: '24h' | '30d' | '3m' = '24h'): Promise<{
|
|
297
|
+
summary: DualTokenInfo,
|
|
298
|
+
history: FeeHistory[]
|
|
299
|
+
}> {
|
|
300
|
+
const { data } = await apolloClient.query({
|
|
301
|
+
query: gql`
|
|
302
|
+
query ContractFeeEarnings(
|
|
303
|
+
$timeframe: String!
|
|
304
|
+
$contract: String!
|
|
305
|
+
) {
|
|
306
|
+
contractFeeEarnings(timeframe: $timeframe, contract: $contract) {
|
|
307
|
+
contract
|
|
308
|
+
dailyEarnings {
|
|
309
|
+
date
|
|
310
|
+
tokenAddress
|
|
311
|
+
amount
|
|
312
|
+
}
|
|
313
|
+
totalCollections
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
`,
|
|
317
|
+
variables: {
|
|
318
|
+
timeframe: timePeriod,
|
|
319
|
+
contract: this.address.address
|
|
320
|
+
},
|
|
321
|
+
fetchPolicy: 'no-cache',
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// Sample response type:
|
|
325
|
+
// {
|
|
326
|
+
// contractFeeEarnings: {
|
|
327
|
+
// contract: '0x2bcaef2eb7706875a5fdc6853dd961a0590f850bc3a031c59887189b5e84ba1',
|
|
328
|
+
// dailyEarnings: [ [Object], [Object], [Object], [Object] ],
|
|
329
|
+
// totalCollections: 3,
|
|
330
|
+
// __typename: 'FeeSummary'
|
|
331
|
+
// }
|
|
332
|
+
// }
|
|
333
|
+
// dailyEarnings: {
|
|
334
|
+
// date: '2025-09-27',
|
|
335
|
+
// tokenAddress: '0x3fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac',
|
|
336
|
+
// amount: '15404',
|
|
337
|
+
// __typename: 'DailyFeeEarnings'
|
|
338
|
+
// }[]
|
|
339
|
+
|
|
340
|
+
// get pool key and token info
|
|
341
|
+
const poolKey = await this.getPoolKey();
|
|
342
|
+
const token0Info = await Global.getTokenInfoFromAddr(poolKey.token0);
|
|
343
|
+
const token1Info = await Global.getTokenInfoFromAddr(poolKey.token1);
|
|
344
|
+
const price0 = await this.pricer.getPrice(token0Info.symbol);
|
|
345
|
+
const price1 = await this.pricer.getPrice(token1Info.symbol);
|
|
346
|
+
let totalToken0Amount = Web3Number.fromWei(0, token0Info.decimals);
|
|
347
|
+
let totalToken1Amount = Web3Number.fromWei(0, token1Info.decimals);
|
|
348
|
+
let totalToken0Usd = 0;
|
|
349
|
+
let totalToken1Usd = 0;
|
|
350
|
+
const parsedFeeInfo: FeeHistory[] = [];
|
|
351
|
+
const feeInfo = data.contractFeeEarnings.dailyEarnings;
|
|
352
|
+
for (const d of feeInfo) {
|
|
353
|
+
const tokenInfo = await Global.getTokenInfoFromAddr(ContractAddr.from(d.tokenAddress));
|
|
354
|
+
const amount = Web3Number.fromWei(d.amount, tokenInfo.decimals);
|
|
355
|
+
if (tokenInfo.address.eq(poolKey.token0)) {
|
|
356
|
+
totalToken0Amount = totalToken0Amount.plus(amount);
|
|
357
|
+
totalToken0Usd = totalToken0Usd + amount.multipliedBy(price0.price).toNumber();
|
|
358
|
+
} else {
|
|
359
|
+
totalToken1Amount = totalToken1Amount.plus(amount);
|
|
360
|
+
totalToken1Usd = totalToken1Usd + amount.multipliedBy(price1.price).toNumber();
|
|
361
|
+
}
|
|
362
|
+
parsedFeeInfo.push({
|
|
363
|
+
date: d.date,
|
|
364
|
+
tokenInfo,
|
|
365
|
+
amount: Web3Number.fromWei(d.amount, tokenInfo.decimals)
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
summary: {
|
|
370
|
+
usdValue: totalToken0Usd + totalToken1Usd,
|
|
371
|
+
token0: {
|
|
372
|
+
tokenInfo: token0Info,
|
|
373
|
+
amount: totalToken0Amount,
|
|
374
|
+
usdValue: totalToken0Usd
|
|
375
|
+
},
|
|
376
|
+
token1: {
|
|
377
|
+
tokenInfo: token1Info,
|
|
378
|
+
amount: totalToken1Amount,
|
|
379
|
+
usdValue: totalToken1Usd
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
history: parsedFeeInfo
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
async netSharesBasedTrueAPY(
|
|
293
387
|
blockIdentifier: BlockIdentifier = "latest",
|
|
294
388
|
sinceBlocks = 600000
|
|
295
389
|
): Promise<number> {
|
|
@@ -354,6 +448,33 @@ export class EkuboCLVault extends BaseStrategy<
|
|
|
354
448
|
return (apyForGivenBlocks * (365 * 24 * 3600)) / timeDiffSeconds;
|
|
355
449
|
}
|
|
356
450
|
|
|
451
|
+
async feeBasedAPY(
|
|
452
|
+
timeperiod: '24h' | '30d' | '3m' = '24h'
|
|
453
|
+
): Promise<number> {
|
|
454
|
+
const feeInfo = await this.getFeeHistory(timeperiod);
|
|
455
|
+
const tvlNow = await this.getTVL('latest');
|
|
456
|
+
return feeInfo.summary.usdValue * 365 / tvlNow.usdValue;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Calculates assets before and now in a given token of TVL per share to observe growth
|
|
461
|
+
* @returns {Promise<number>} The weighted average APY across all pools
|
|
462
|
+
*/
|
|
463
|
+
async netAPY(
|
|
464
|
+
blockIdentifier: BlockIdentifier = "latest",
|
|
465
|
+
sinceBlocks = 600000,
|
|
466
|
+
timeperiod: '24h' | '30d' | '3m' = '24h' // temp thing for fee based APY
|
|
467
|
+
): Promise<number> {
|
|
468
|
+
const isUSDCQouteToken = this.metadata.additionalInfo.quoteAsset.symbol === "USDC";
|
|
469
|
+
if (!isUSDCQouteToken) {
|
|
470
|
+
// good for LSTs and stables
|
|
471
|
+
return this.netSharesBasedTrueAPY(blockIdentifier, sinceBlocks);
|
|
472
|
+
} else {
|
|
473
|
+
// good for non-stables
|
|
474
|
+
return this.feeBasedAPY(timeperiod);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
357
478
|
async getHarvestRewardShares(fromBlock: number, toBlock: number) {
|
|
358
479
|
const len = Number(await this.contract.call("get_total_rewards"));
|
|
359
480
|
let shares = Web3Number.fromWei(0, 18);
|
|
@@ -1680,7 +1801,7 @@ const highRisk = {
|
|
|
1680
1801
|
|
|
1681
1802
|
|
|
1682
1803
|
const AUDIT_URL =
|
|
1683
|
-
"https://
|
|
1804
|
+
"https://docs.troves.fi/p/security#ekubo-vault";
|
|
1684
1805
|
|
|
1685
1806
|
const faqs: FAQ[] = [
|
|
1686
1807
|
{
|
|
@@ -1893,7 +2014,7 @@ const ETHUSDCRe7Strategy: IStrategyMetadata<CLVaultStrategySettings> = {
|
|
|
1893
2014
|
Global.getDefaultTokens().find((t) => t.symbol === "USDC")!
|
|
1894
2015
|
],
|
|
1895
2016
|
apyMethodology:
|
|
1896
|
-
"APY
|
|
2017
|
+
"Annualized fee APY, calculated as fees earned in the last 24h divided by TVL",
|
|
1897
2018
|
additionalInfo: {
|
|
1898
2019
|
newBounds: "Managed by Re7",
|
|
1899
2020
|
truePrice: 1,
|
|
@@ -1913,6 +2034,11 @@ const ETHUSDCRe7Strategy: IStrategyMetadata<CLVaultStrategySettings> = {
|
|
|
1913
2034
|
answer:
|
|
1914
2035
|
<div>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 <a href='https://www.re7labs.xyz' style={{textDecoration: "underline", marginLeft: "2px"}} target="_blank">here</a>.</div>
|
|
1915
2036
|
},
|
|
2037
|
+
{
|
|
2038
|
+
question: "How is the APY calculated?",
|
|
2039
|
+
answer:
|
|
2040
|
+
<div>It's an annualized fee APY, calculated as fees earned in the last 24h divided by TVL. Factors like impermanent loss are not considered.</div>
|
|
2041
|
+
},
|
|
1916
2042
|
],
|
|
1917
2043
|
risk: highRisk,
|
|
1918
2044
|
points: [],
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { FAQ, getNoRiskTags, IConfig, IStrategyMetadata, Protocols, RiskFactor, RiskType } from "@/interfaces";
|
|
1
|
+
import { FAQ, getNoRiskTags, highlightTextWithLinks, IConfig, IStrategyMetadata, Protocols, RiskFactor, RiskType } from "@/interfaces";
|
|
2
2
|
import { AUMTypes, getContractDetails, UNIVERSAL_ADAPTERS, UNIVERSAL_MANAGE_IDS, UniversalManageCall, UniversalStrategy, UniversalStrategySettings } from "./universal-strategy";
|
|
3
3
|
import { PricerBase } from "@/modules/pricerBase";
|
|
4
4
|
import { ContractAddr, Web3Number } from "@/dataTypes";
|
|
5
5
|
import { Global } from "@/global";
|
|
6
6
|
import { ApproveCallParams, CommonAdapter, getVesuSingletonAddress, ManageCall, Swap, VesuAdapter, VesuModifyDelegationCallParams, VesuMultiplyCallParams, VesuPools } from "./universal-adapters";
|
|
7
7
|
import { AVNU_MIDDLEWARE } from "./universal-adapters/adapter-utils";
|
|
8
|
-
import { LiquidationRiskLevel, SmartContractRiskLevel, TechnicalRiskLevel } from "@/interfaces/risks";
|
|
8
|
+
import { DepegRiskLevel, LiquidationRiskLevel, SmartContractRiskLevel, TechnicalRiskLevel } from "@/interfaces/risks";
|
|
9
9
|
import { EkuboQuoter, ERC20, PricerLST } from "@/modules";
|
|
10
10
|
import { assert, logger } from "@/utils";
|
|
11
11
|
import { SingleTokenInfo } from "./base-strategy";
|
|
@@ -293,7 +293,10 @@ export class UniversalLstMultiplierStrategy extends UniversalStrategy<UniversalS
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
export default function VaultDescription(
|
|
296
|
+
export default function VaultDescription(
|
|
297
|
+
lstSymbol: string,
|
|
298
|
+
underlyingSymbol: string
|
|
299
|
+
) {
|
|
297
300
|
const containerStyle = {
|
|
298
301
|
maxWidth: "800px",
|
|
299
302
|
margin: "0 auto",
|
|
@@ -305,13 +308,16 @@ export default function VaultDescription() {
|
|
|
305
308
|
|
|
306
309
|
return (
|
|
307
310
|
<div style={containerStyle}>
|
|
308
|
-
<h1 style={{ fontSize: "18px", marginBottom: "10px" }}>
|
|
311
|
+
<h1 style={{ fontSize: "18px", marginBottom: "10px" }}>Liquidation risk managed leverged {lstSymbol} Vault</h1>
|
|
312
|
+
<p style={{ fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }}>
|
|
313
|
+
This Levered Endur {lstSymbol} vault is a tokenized leveraged Vault, auto-compounding strategy that takes upto 5x leverage on {lstSymbol} by borrow {underlyingSymbol}. Borrowed amount
|
|
314
|
+
is swapped to {lstSymbol} to create leverage. Depositors receive vault shares that
|
|
315
|
+
represent a proportional claim on the underlying assets and accrued yield.
|
|
316
|
+
</p>
|
|
317
|
+
|
|
309
318
|
<p style={{ fontSize: "14px", lineHeight: "1.5", marginBottom: "16px" }}>
|
|
310
|
-
This
|
|
311
|
-
|
|
312
|
-
represent a proportional claim on the underlying assets and accrued yield. Allocation shifts are
|
|
313
|
-
handled programmatically based on on-chain signals and risk filters, minimizing idle capital and
|
|
314
|
-
maximizing net APY.
|
|
319
|
+
This vault uses Vesu for lending and borrowing. The oracle used by this pool is a {highlightTextWithLinks("conversion rate oracle", [{highlight: "conversion rate oracle", link: "https://docs.pragma.build/starknet/development#conversion-rate"}])}
|
|
320
|
+
which is resilient to liquidity issues and price volatility, hence reducing the risk of liquidation. However, overtime, if left un-monitored, debt can increase enough to trigger a liquidation. But no worries, our continuous monitoring systems look for situations with reduced health factor and balance collateral/debt to bring it back to safe levels. With Troves, you can have a peaceful sleep.
|
|
315
321
|
</p>
|
|
316
322
|
|
|
317
323
|
<div style={{ backgroundColor: "#222", padding: "10px", borderRadius: "8px", marginBottom: "20px", border: "1px solid #444" }}>
|
|
@@ -324,8 +330,8 @@ export default function VaultDescription() {
|
|
|
324
330
|
}
|
|
325
331
|
|
|
326
332
|
|
|
327
|
-
function getDescription(tokenSymbol: string) {
|
|
328
|
-
return VaultDescription();
|
|
333
|
+
function getDescription(tokenSymbol: string, underlyingSymbol: string) {
|
|
334
|
+
return VaultDescription(tokenSymbol, underlyingSymbol);
|
|
329
335
|
}
|
|
330
336
|
|
|
331
337
|
enum LST_MULTIPLIER_MANAGE_IDS {
|
|
@@ -393,12 +399,14 @@ function getLooperSettings(
|
|
|
393
399
|
return vaultSettings;
|
|
394
400
|
}
|
|
395
401
|
|
|
402
|
+
const AUDIT_URL = 'https://docs.troves.fi/p/security#starknet-vault-kit'
|
|
403
|
+
|
|
396
404
|
function getFAQs(lstSymbol: string, underlyingSymbol: string): FAQ[] {
|
|
397
405
|
return [
|
|
398
406
|
{
|
|
399
407
|
question: `What is the Hyper ${lstSymbol} Vault?`,
|
|
400
408
|
answer:
|
|
401
|
-
`The Hyper ${lstSymbol} Vault is a tokenized strategy that automatically loops your ${
|
|
409
|
+
`The Hyper ${lstSymbol} Vault is a tokenized strategy that automatically loops your ${lstSymbol} to create up to 5x leverage to hence yield in a very low risk manner.`,
|
|
402
410
|
},
|
|
403
411
|
{
|
|
404
412
|
question: "How does yield allocation work?",
|
|
@@ -447,8 +455,9 @@ function getFAQs(lstSymbol: string, underlyingSymbol: string): FAQ[] {
|
|
|
447
455
|
|
|
448
456
|
const _riskFactor: RiskFactor[] = [
|
|
449
457
|
{ type: RiskType.SMART_CONTRACT_RISK, value: SmartContractRiskLevel.WELL_AUDITED, weight: 25, reason: "Audited by Zellic" },
|
|
450
|
-
{ type: RiskType.LIQUIDATION_RISK, value: LiquidationRiskLevel.VERY_LOW_PROBABILITY, weight:
|
|
451
|
-
{ type: RiskType.TECHNICAL_RISK, value: TechnicalRiskLevel.STABLE_INFRASTRUCTURE, weight:
|
|
458
|
+
{ type: RiskType.LIQUIDATION_RISK, value: LiquidationRiskLevel.VERY_LOW_PROBABILITY, weight: 25, reason: "The collateral and debt are highly correlated" },
|
|
459
|
+
{ type: RiskType.TECHNICAL_RISK, value: TechnicalRiskLevel.STABLE_INFRASTRUCTURE, weight: 25, reason: "Liquidation can only happen if vault is left un-monitored for weeks, which is highly unlikely. We actively monitor all services on a daily basis." },
|
|
460
|
+
{type: RiskType.DEPEG_RISK, value: DepegRiskLevel.GENERALLY_STABLE, weight: 25, reason: "Generally stable pegged assets" },
|
|
452
461
|
];
|
|
453
462
|
|
|
454
463
|
const hyperxSTRK: UniversalStrategySettings = {
|
|
@@ -517,7 +526,6 @@ function getInvestmentSteps(lstSymbol: string, underlyingSymbol: string) {
|
|
|
517
526
|
`The vault manager loops the ${underlyingSymbol} to buy ${lstSymbol}`,
|
|
518
527
|
`The vault manager collateralizes the ${lstSymbol} on Vesu`,
|
|
519
528
|
`The vault manager borrows more ${underlyingSymbol} to loop further`,
|
|
520
|
-
`Claim BTCFi STRK rewards weekly to swap to ${lstSymbol} and reinvest`,
|
|
521
529
|
`If required, adjust leverage or re-allocate assets within LST pool on Vesu to optimize yield`
|
|
522
530
|
]
|
|
523
531
|
}
|
|
@@ -525,7 +533,7 @@ function getInvestmentSteps(lstSymbol: string, underlyingSymbol: string) {
|
|
|
525
533
|
function getStrategySettings(lstSymbol: string, underlyingSymbol: string, addresses: UniversalStrategySettings, isPreview: boolean = false): IStrategyMetadata<UniversalStrategySettings> {
|
|
526
534
|
return {
|
|
527
535
|
name: `Hyper ${lstSymbol}`,
|
|
528
|
-
description: getDescription(lstSymbol),
|
|
536
|
+
description: getDescription(lstSymbol, underlyingSymbol),
|
|
529
537
|
address: addresses.vaultAddress,
|
|
530
538
|
launchBlock: 0,
|
|
531
539
|
type: 'Other',
|
|
@@ -538,6 +546,7 @@ function getStrategySettings(lstSymbol: string, underlyingSymbol: string, addres
|
|
|
538
546
|
_riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
|
|
539
547
|
notARisks: getNoRiskTags(_riskFactor)
|
|
540
548
|
},
|
|
549
|
+
auditUrl: AUDIT_URL,
|
|
541
550
|
protocols: [Protocols.ENDUR, Protocols.VESU],
|
|
542
551
|
maxTVL: Web3Number.fromWei(0, 18),
|
|
543
552
|
contractDetails: getContractDetails(addresses),
|