@strkfarm/sdk 2.0.0-dev.40 → 2.0.0-dev.42
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 +415 -216
- package/dist/index.browser.mjs +433 -233
- package/dist/index.d.ts +38 -14
- package/dist/index.js +435 -233
- package/dist/index.mjs +434 -233
- package/package.json +4 -5
- package/src/global.ts +36 -34
- package/src/interfaces/common.tsx +6 -0
- package/src/modules/index.ts +1 -0
- package/src/modules/pricer-avnu-api.ts +114 -0
- package/src/modules/pricer.ts +63 -45
- package/src/node/pricer-redis.ts +1 -0
- package/src/strategies/ekubo-cl-vault.tsx +3 -0
- package/src/strategies/svk-strategy.ts +159 -2
- package/src/strategies/token-boosted-xstrk-carry-strategy.tsx +54 -17
- package/src/strategies/universal-lst-muliplier-strategy.tsx +90 -19
- package/src/strategies/universal-strategy.tsx +216 -372
- package/src/strategies/yoloVault.ts +3 -0
package/dist/index.mjs
CHANGED
|
@@ -664,20 +664,20 @@ var defaultTokens = [
|
|
|
664
664
|
decimals: 18,
|
|
665
665
|
coingeckId: void 0,
|
|
666
666
|
displayDecimals: 6,
|
|
667
|
-
priceCheckAmount: 1e-4
|
|
667
|
+
priceCheckAmount: 1e-4,
|
|
668
668
|
// 112000 * 0.0001 = $11.2
|
|
669
|
+
dontPrice: true
|
|
669
670
|
},
|
|
670
671
|
{
|
|
671
672
|
name: "mRe7YIELD",
|
|
672
673
|
symbol: "mRe7YIELD",
|
|
673
674
|
logo: "https://midas.app/assets/mre7-BcOOHm7i.svg",
|
|
674
|
-
address: ContractAddr.from(
|
|
675
|
-
"0x4be8945e61dc3e19ebadd1579a6bd53b262f51ba89e6f8b0c4bc9a7e3c633fc"
|
|
676
|
-
),
|
|
675
|
+
address: ContractAddr.from("0x4be8945e61dc3e19ebadd1579a6bd53b262f51ba89e6f8b0c4bc9a7e3c633fc"),
|
|
677
676
|
decimals: 18,
|
|
678
677
|
coingeckId: void 0,
|
|
679
678
|
displayDecimals: 2,
|
|
680
|
-
priceCheckAmount: 100
|
|
679
|
+
priceCheckAmount: 100,
|
|
680
|
+
dontPrice: true
|
|
681
681
|
},
|
|
682
682
|
{
|
|
683
683
|
name: "fyWBTC",
|
|
@@ -687,8 +687,9 @@ var defaultTokens = [
|
|
|
687
687
|
decimals: 8,
|
|
688
688
|
coingeckId: void 0,
|
|
689
689
|
displayDecimals: 6,
|
|
690
|
-
priceCheckAmount: 1e-3
|
|
690
|
+
priceCheckAmount: 1e-3,
|
|
691
691
|
// 112000 * 0.0001 = $110.2
|
|
692
|
+
dontPrice: true
|
|
692
693
|
},
|
|
693
694
|
{
|
|
694
695
|
name: "fyETH",
|
|
@@ -698,7 +699,8 @@ var defaultTokens = [
|
|
|
698
699
|
decimals: 18,
|
|
699
700
|
coingeckId: void 0,
|
|
700
701
|
displayDecimals: 4,
|
|
701
|
-
priceCheckAmount: 0.1
|
|
702
|
+
priceCheckAmount: 0.1,
|
|
703
|
+
dontPrice: true
|
|
702
704
|
},
|
|
703
705
|
{
|
|
704
706
|
name: "fyUSDC",
|
|
@@ -708,7 +710,8 @@ var defaultTokens = [
|
|
|
708
710
|
decimals: 6,
|
|
709
711
|
coingeckId: void 0,
|
|
710
712
|
displayDecimals: 2,
|
|
711
|
-
priceCheckAmount: 100
|
|
713
|
+
priceCheckAmount: 100,
|
|
714
|
+
dontPrice: true
|
|
712
715
|
},
|
|
713
716
|
{
|
|
714
717
|
name: "strkBTC",
|
|
@@ -3726,7 +3729,7 @@ var TokenMarketData = class {
|
|
|
3726
3729
|
};
|
|
3727
3730
|
|
|
3728
3731
|
// src/modules/pricer.ts
|
|
3729
|
-
import
|
|
3732
|
+
import axios4 from "axios";
|
|
3730
3733
|
|
|
3731
3734
|
// src/modules/pricerBase.ts
|
|
3732
3735
|
var PricerBase = class {
|
|
@@ -3830,7 +3833,96 @@ var AvnuWrapper = class _AvnuWrapper {
|
|
|
3830
3833
|
}
|
|
3831
3834
|
};
|
|
3832
3835
|
|
|
3836
|
+
// src/modules/pricer-avnu-api.ts
|
|
3837
|
+
import axios3 from "axios";
|
|
3838
|
+
var AVNU_TOKENS_API = "https://starknet.impulse.avnu.fi/v3/tokens";
|
|
3839
|
+
var PricerAvnuApi = class extends PricerBase {
|
|
3840
|
+
constructor(config, tokens2) {
|
|
3841
|
+
super(config, tokens2);
|
|
3842
|
+
this.prices = {};
|
|
3843
|
+
this.refreshInterval = 15e3;
|
|
3844
|
+
this.staleTime = 5 * 60 * 1e3;
|
|
3845
|
+
this.pollTimer = null;
|
|
3846
|
+
this.loading = false;
|
|
3847
|
+
}
|
|
3848
|
+
start() {
|
|
3849
|
+
this._loadPrices();
|
|
3850
|
+
this.pollTimer = setInterval(() => {
|
|
3851
|
+
this._loadPrices();
|
|
3852
|
+
}, this.refreshInterval);
|
|
3853
|
+
}
|
|
3854
|
+
stop() {
|
|
3855
|
+
if (this.pollTimer) {
|
|
3856
|
+
clearInterval(this.pollTimer);
|
|
3857
|
+
this.pollTimer = null;
|
|
3858
|
+
}
|
|
3859
|
+
}
|
|
3860
|
+
isStale(timestamp) {
|
|
3861
|
+
return Date.now() - timestamp.getTime() > this.staleTime;
|
|
3862
|
+
}
|
|
3863
|
+
hasPrice(tokenSymbol) {
|
|
3864
|
+
const info = this.prices[tokenSymbol];
|
|
3865
|
+
return !!info && !this.isStale(info.timestamp);
|
|
3866
|
+
}
|
|
3867
|
+
async getPrice(tokenSymbol) {
|
|
3868
|
+
const info = this.prices[tokenSymbol];
|
|
3869
|
+
if (!info) {
|
|
3870
|
+
throw new Error(`AvnuApi: price of ${tokenSymbol} not found`);
|
|
3871
|
+
}
|
|
3872
|
+
if (this.isStale(info.timestamp)) {
|
|
3873
|
+
throw new Error(`AvnuApi: price of ${tokenSymbol} is stale`);
|
|
3874
|
+
}
|
|
3875
|
+
return info;
|
|
3876
|
+
}
|
|
3877
|
+
async _loadPrices() {
|
|
3878
|
+
if (this.loading) {
|
|
3879
|
+
return;
|
|
3880
|
+
}
|
|
3881
|
+
this.loading = true;
|
|
3882
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
3883
|
+
try {
|
|
3884
|
+
const result = await axios3.get(AVNU_TOKENS_API);
|
|
3885
|
+
const priceByAddress = /* @__PURE__ */ new Map();
|
|
3886
|
+
for (const entry of result.data) {
|
|
3887
|
+
const usd = entry.starknet?.usd;
|
|
3888
|
+
if (usd != null && usd > 0) {
|
|
3889
|
+
priceByAddress.set(ContractAddr.standardise(entry.address), usd);
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
for (const token of this.tokens) {
|
|
3893
|
+
if (token.symbol === "USDT" || token.symbol === "USDC") {
|
|
3894
|
+
this.prices[token.symbol] = { price: 1, timestamp };
|
|
3895
|
+
continue;
|
|
3896
|
+
}
|
|
3897
|
+
const targetToken = token.priceProxySymbol ? this.tokens.find((t) => t.symbol === token.priceProxySymbol) : token;
|
|
3898
|
+
if (!targetToken) {
|
|
3899
|
+
continue;
|
|
3900
|
+
}
|
|
3901
|
+
const addr = targetToken.address.address;
|
|
3902
|
+
const price = priceByAddress.get(addr);
|
|
3903
|
+
if (price != null) {
|
|
3904
|
+
this.prices[token.symbol] = { price, timestamp };
|
|
3905
|
+
logger.verbose(
|
|
3906
|
+
`AvnuApi: ${token.symbol} -> $${price}`
|
|
3907
|
+
);
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
} catch (error) {
|
|
3911
|
+
logger.warn(`AvnuApi: failed to fetch tokens: ${error?.message ?? error}`);
|
|
3912
|
+
} finally {
|
|
3913
|
+
this.loading = false;
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3916
|
+
};
|
|
3917
|
+
|
|
3833
3918
|
// src/modules/pricer.ts
|
|
3919
|
+
var PRICE_METHOD_PRIORITY = [
|
|
3920
|
+
"AvnuApi",
|
|
3921
|
+
"Coinbase",
|
|
3922
|
+
"Coinmarketcap",
|
|
3923
|
+
"Ekubo",
|
|
3924
|
+
"Avnu"
|
|
3925
|
+
];
|
|
3834
3926
|
var Pricer = class extends PricerBase {
|
|
3835
3927
|
// e.g. ETH/USDC
|
|
3836
3928
|
constructor(config, tokens2, refreshInterval = 3e4, staleTime = 6e4) {
|
|
@@ -3849,6 +3941,7 @@ var Pricer = class extends PricerBase {
|
|
|
3849
3941
|
this.EKUBO_API = "https://prod-api-quoter.ekubo.org/23448594291968334/{{AMOUNT}}/{{TOKEN_ADDRESS}}/0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb";
|
|
3850
3942
|
this.refreshInterval = refreshInterval;
|
|
3851
3943
|
this.staleTime = staleTime;
|
|
3944
|
+
this.avnuApiPricer = new PricerAvnuApi(config, tokens2);
|
|
3852
3945
|
}
|
|
3853
3946
|
isReady() {
|
|
3854
3947
|
const allPricesExist = Object.keys(this.prices).length === this.tokens.length;
|
|
@@ -3878,6 +3971,7 @@ var Pricer = class extends PricerBase {
|
|
|
3878
3971
|
});
|
|
3879
3972
|
}
|
|
3880
3973
|
start() {
|
|
3974
|
+
this.avnuApiPricer.start();
|
|
3881
3975
|
this._loadPrices();
|
|
3882
3976
|
setInterval(() => {
|
|
3883
3977
|
this._loadPrices();
|
|
@@ -3902,6 +3996,9 @@ var Pricer = class extends PricerBase {
|
|
|
3902
3996
|
let retry = 0;
|
|
3903
3997
|
while (retry < MAX_RETRIES) {
|
|
3904
3998
|
try {
|
|
3999
|
+
if (token.dontPrice) {
|
|
4000
|
+
return;
|
|
4001
|
+
}
|
|
3905
4002
|
if (token.symbol === "USDT" || token.symbol === "USDC") {
|
|
3906
4003
|
this.prices[token.symbol] = {
|
|
3907
4004
|
price: 1,
|
|
@@ -3944,60 +4041,61 @@ var Pricer = class extends PricerBase {
|
|
|
3944
4041
|
});
|
|
3945
4042
|
if (this.isReady() && this.config.heartbeatUrl) {
|
|
3946
4043
|
console.log(`sending beat`);
|
|
3947
|
-
|
|
4044
|
+
axios4.get(this.config.heartbeatUrl).catch((err) => {
|
|
3948
4045
|
console.error("Pricer: Heartbeat err", err);
|
|
3949
4046
|
});
|
|
3950
4047
|
}
|
|
3951
4048
|
}
|
|
3952
|
-
async _getPrice(token
|
|
3953
|
-
const
|
|
3954
|
-
|
|
3955
|
-
|
|
4049
|
+
async _getPrice(token) {
|
|
4050
|
+
const pinned = this.methodToUse[token.symbol];
|
|
4051
|
+
if (pinned) {
|
|
4052
|
+
logger.verbose(`Fetching price of ${token.symbol} using pinned ${pinned}`);
|
|
4053
|
+
try {
|
|
4054
|
+
return await this._tryPriceMethod(token, pinned);
|
|
4055
|
+
} catch (error) {
|
|
4056
|
+
console.warn(`${pinned}: pinned price failed [${token.symbol}]: `, error.message);
|
|
4057
|
+
delete this.methodToUse[token.symbol];
|
|
4058
|
+
}
|
|
4059
|
+
}
|
|
4060
|
+
for (const method of PRICE_METHOD_PRIORITY) {
|
|
4061
|
+
logger.verbose(`Fetching price of ${token.symbol} using ${method}`);
|
|
4062
|
+
try {
|
|
4063
|
+
const result = await this._tryPriceMethod(token, method);
|
|
4064
|
+
this.methodToUse[token.symbol] = method;
|
|
4065
|
+
return result;
|
|
4066
|
+
} catch (error) {
|
|
4067
|
+
console.warn(`${method}: price err [${token.symbol}]: `, error.message);
|
|
4068
|
+
}
|
|
4069
|
+
}
|
|
4070
|
+
throw new FatalError(`Price not found for ${token.symbol}`);
|
|
4071
|
+
}
|
|
4072
|
+
async _tryPriceMethod(token, method) {
|
|
4073
|
+
switch (method) {
|
|
4074
|
+
case "AvnuApi":
|
|
4075
|
+
return await this._getPriceAvnuApi(token);
|
|
3956
4076
|
case "Coinbase":
|
|
3957
|
-
|
|
3958
|
-
// const result = await this._getPriceCoinbase(token);
|
|
3959
|
-
// this.methodToUse[token.symbol] = 'Coinbase';
|
|
3960
|
-
// return result;
|
|
3961
|
-
// } catch (error: any) {
|
|
3962
|
-
// console.warn(`Coinbase: price err: message [${token.symbol}]: `, error.message);
|
|
3963
|
-
// // do nothing, try next
|
|
3964
|
-
// }
|
|
4077
|
+
return await this._getPriceCoinbase(token);
|
|
3965
4078
|
case "Coinmarketcap":
|
|
3966
|
-
|
|
3967
|
-
const result = await this._getPriceCoinMarketCap(token);
|
|
3968
|
-
this.methodToUse[token.symbol] = "Coinmarketcap";
|
|
3969
|
-
return result;
|
|
3970
|
-
} catch (error) {
|
|
3971
|
-
console.warn(`CoinMarketCap: price err [${token.symbol}]: `, Object.keys(error));
|
|
3972
|
-
console.warn(`CoinMarketCap: price err [${token.symbol}]: `, error.message);
|
|
3973
|
-
}
|
|
4079
|
+
return await this._getPriceCoinMarketCap(token);
|
|
3974
4080
|
case "Ekubo":
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
} catch (error) {
|
|
3980
|
-
console.warn(`Ekubo: price err [${token.symbol}]: `, error.message);
|
|
3981
|
-
console.warn(`Ekubo: price err [${token.symbol}]: `, Object.keys(error));
|
|
3982
|
-
}
|
|
4081
|
+
return await this._getPriceEkubo(
|
|
4082
|
+
token,
|
|
4083
|
+
new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals)
|
|
4084
|
+
);
|
|
3983
4085
|
case "Avnu":
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
} catch (error) {
|
|
3989
|
-
console.warn(`Avnu: price err [${token.symbol}]: `, error.message);
|
|
3990
|
-
console.warn(`Avnu: price err [${token.symbol}]: `, Object.keys(error));
|
|
3991
|
-
}
|
|
3992
|
-
}
|
|
3993
|
-
if (defaultMethod == "all") {
|
|
3994
|
-
return await this._getPrice(token, "Coinbase");
|
|
4086
|
+
return await this._getAvnuPrice(
|
|
4087
|
+
token,
|
|
4088
|
+
new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals)
|
|
4089
|
+
);
|
|
3995
4090
|
}
|
|
3996
|
-
|
|
4091
|
+
}
|
|
4092
|
+
async _getPriceAvnuApi(token) {
|
|
4093
|
+
const priceInfo = await this.avnuApiPricer.getPrice(token.symbol);
|
|
4094
|
+
return priceInfo.price;
|
|
3997
4095
|
}
|
|
3998
4096
|
async _getPriceCoinbase(token) {
|
|
3999
4097
|
const url = this.PRICE_API.replace("{{PRICER_KEY}}", `${token.symbol}-USD`);
|
|
4000
|
-
const result = await
|
|
4098
|
+
const result = await axios4.get(url);
|
|
4001
4099
|
const data = result.data;
|
|
4002
4100
|
return Number(data.data.amount);
|
|
4003
4101
|
}
|
|
@@ -4023,7 +4121,7 @@ var Pricer = class extends PricerBase {
|
|
|
4023
4121
|
async _getPriceEkubo(token, amountIn = new Web3Number(1, token.decimals), retry = 0) {
|
|
4024
4122
|
logger.verbose(`Getting price of ${token.symbol} using Ekubo, amountIn: ${amountIn.toWei()}`);
|
|
4025
4123
|
const url = this.EKUBO_API.replace("{{TOKEN_ADDRESS}}", token.address.toString()).replace("{{AMOUNT}}", amountIn.toWei());
|
|
4026
|
-
const result = await
|
|
4124
|
+
const result = await axios4.get(url);
|
|
4027
4125
|
const data = result.data;
|
|
4028
4126
|
const multiplier = 1 / amountIn.toNumber();
|
|
4029
4127
|
const outputUSDC = Number(Web3Number.fromWei(data.total_calculated, 6).toFixed(6)) * multiplier;
|
|
@@ -4169,7 +4267,7 @@ var Pragma = class extends PricerBase {
|
|
|
4169
4267
|
};
|
|
4170
4268
|
|
|
4171
4269
|
// src/modules/zkLend.ts
|
|
4172
|
-
import
|
|
4270
|
+
import axios5 from "axios";
|
|
4173
4271
|
|
|
4174
4272
|
// src/dataTypes/bignumber.browser.ts
|
|
4175
4273
|
import { uint256 as uint2566 } from "starknet";
|
|
@@ -4228,7 +4326,7 @@ var _ZkLend = class _ZkLend extends ILending {
|
|
|
4228
4326
|
async init() {
|
|
4229
4327
|
try {
|
|
4230
4328
|
logger.verbose(`Initialising ${this.metadata.name}`);
|
|
4231
|
-
const result = await
|
|
4329
|
+
const result = await axios5.get(_ZkLend.POOLS_URL);
|
|
4232
4330
|
const data = result.data;
|
|
4233
4331
|
const savedTokens = await Global.getTokens();
|
|
4234
4332
|
data.forEach((pool) => {
|
|
@@ -4320,7 +4418,7 @@ var _ZkLend = class _ZkLend extends ILending {
|
|
|
4320
4418
|
*/
|
|
4321
4419
|
async getPositions(user) {
|
|
4322
4420
|
const url = this.POSITION_URL.replace("{{USER_ADDR}}", user.address);
|
|
4323
|
-
const result = await
|
|
4421
|
+
const result = await axios5.get(url);
|
|
4324
4422
|
const data = result.data;
|
|
4325
4423
|
const lendingPosition = [];
|
|
4326
4424
|
logger.verbose(`${this.metadata.name}:: Positions: ${JSON.stringify(data)}`);
|
|
@@ -4353,7 +4451,7 @@ _ZkLend.POOLS_URL = "https://app.zklend.com/api/pools";
|
|
|
4353
4451
|
var ZkLend = _ZkLend;
|
|
4354
4452
|
|
|
4355
4453
|
// src/modules/pricer-from-api.ts
|
|
4356
|
-
import
|
|
4454
|
+
import axios6 from "axios";
|
|
4357
4455
|
|
|
4358
4456
|
// src/modules/apollo-client-config.ts
|
|
4359
4457
|
import { ApolloClient, InMemoryCache } from "@apollo/client";
|
|
@@ -4740,7 +4838,7 @@ var PricerFromApi = class extends PricerBase {
|
|
|
4740
4838
|
const MAX_RETRIES = 5;
|
|
4741
4839
|
for (retry = 1; retry < MAX_RETRIES + 1; retry++) {
|
|
4742
4840
|
try {
|
|
4743
|
-
const priceInfo = await
|
|
4841
|
+
const priceInfo = await axios6.get(
|
|
4744
4842
|
`https://api.coinbase.com/v2/prices/${tokenSymbol}-USDT/spot`
|
|
4745
4843
|
);
|
|
4746
4844
|
if (!priceInfo) {
|
|
@@ -6051,7 +6149,7 @@ var ERC20 = class {
|
|
|
6051
6149
|
};
|
|
6052
6150
|
|
|
6053
6151
|
// src/modules/ekubo-quoter.ts
|
|
6054
|
-
import
|
|
6152
|
+
import axios7 from "axios";
|
|
6055
6153
|
import { uint256 as uint2568 } from "starknet";
|
|
6056
6154
|
import { Contract as Contract5 } from "starknet";
|
|
6057
6155
|
var EkuboQuoter = class _EkuboQuoter {
|
|
@@ -6064,7 +6162,7 @@ var EkuboQuoter = class _EkuboQuoter {
|
|
|
6064
6162
|
try {
|
|
6065
6163
|
const url = this.ENDPOINT.replace("{{AMOUNT}}", amount.toWei()).replace("{{TOKEN_FROM_ADDRESS}}", fromToken).replace("{{TOKEN_TO_ADDRESS}}", toToken);
|
|
6066
6164
|
logger.verbose(`EkuboQuoter::_callQuoterApi url: ${url}`);
|
|
6067
|
-
const quote = await
|
|
6165
|
+
const quote = await axios7.get(url);
|
|
6068
6166
|
return quote.data;
|
|
6069
6167
|
} catch (error) {
|
|
6070
6168
|
logger.error(`EkuboQuoter::_callQuoterApi error: ${error.message}`);
|
|
@@ -8075,9 +8173,9 @@ var BaseStrategy = class extends CacheClass {
|
|
|
8075
8173
|
};
|
|
8076
8174
|
|
|
8077
8175
|
// src/node/headless.browser.ts
|
|
8078
|
-
import
|
|
8176
|
+
import axios8 from "axios";
|
|
8079
8177
|
async function getAPIUsingHeadlessBrowser(url) {
|
|
8080
|
-
const res = await
|
|
8178
|
+
const res = await axios8.get(url);
|
|
8081
8179
|
return res.data;
|
|
8082
8180
|
}
|
|
8083
8181
|
|
|
@@ -19586,6 +19684,9 @@ var xSTRKSTRK = {
|
|
|
19586
19684
|
},
|
|
19587
19685
|
apyMethodology: "APY based on 30-day historical performance, including fees and rewards.",
|
|
19588
19686
|
realizedApyMethodology: "The realizedAPY is based on past 14 days performance by the vault",
|
|
19687
|
+
feeBps: {
|
|
19688
|
+
performanceFeeBps: 1e3
|
|
19689
|
+
},
|
|
19589
19690
|
additionalInfo: {
|
|
19590
19691
|
newBounds: {
|
|
19591
19692
|
lower: -1,
|
|
@@ -30312,6 +30413,9 @@ var YoloVaultStrategies = yoloVaultsConfig.map((yoloConfig) => {
|
|
|
30312
30413
|
notARisks: getNoRiskTags(yoloRiskFactors)
|
|
30313
30414
|
},
|
|
30314
30415
|
apyMethodology: "Not a primary yield strategy. Funds earn yield when idle, but the main return comes from BTC price appreciation and your conviction to hold. This vault simply helps you accumulate more BTC.",
|
|
30416
|
+
feeBps: {
|
|
30417
|
+
performanceFeeBps: 1e3
|
|
30418
|
+
},
|
|
30315
30419
|
additionalInfo: {
|
|
30316
30420
|
mainToken: yoloConfig.mainToken,
|
|
30317
30421
|
secondaryToken: yoloConfig.secondaryToken,
|
|
@@ -33092,7 +33196,7 @@ var TokenTransferAdapter = class _TokenTransferAdapter extends BaseAdapter {
|
|
|
33092
33196
|
|
|
33093
33197
|
// src/strategies/universal-adapters/avnu-adapter.ts
|
|
33094
33198
|
import { hash as hash9, uint256 as uint25620 } from "starknet";
|
|
33095
|
-
import
|
|
33199
|
+
import axios9 from "axios";
|
|
33096
33200
|
var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
|
|
33097
33201
|
constructor(config) {
|
|
33098
33202
|
super(config, _AvnuAdapter.name, Protocols.AVNU);
|
|
@@ -33299,7 +33403,7 @@ var AvnuAdapter = class _AvnuAdapter extends BaseAdapter {
|
|
|
33299
33403
|
async fetchQuoteWithRetry(params, retries = 5) {
|
|
33300
33404
|
for (let attempt = 0; attempt < retries; attempt++) {
|
|
33301
33405
|
try {
|
|
33302
|
-
const response = await
|
|
33406
|
+
const response = await axios9.get(this.config.baseUrl, { params });
|
|
33303
33407
|
if (response.data && response.data.length > 0) {
|
|
33304
33408
|
return response;
|
|
33305
33409
|
}
|
|
@@ -36833,6 +36937,29 @@ var SVKStrategy = class extends BaseStrategy {
|
|
|
36833
36937
|
]);
|
|
36834
36938
|
return [call];
|
|
36835
36939
|
}
|
|
36940
|
+
async getUserTVL(user, blockIdentifier = "latest") {
|
|
36941
|
+
const shares = await this.contract.call("balanceOf", [user.address], { blockIdentifier });
|
|
36942
|
+
const assets = await this.contract.call(
|
|
36943
|
+
"convert_to_assets",
|
|
36944
|
+
[uint25622.bnToUint256(shares)],
|
|
36945
|
+
{ blockIdentifier }
|
|
36946
|
+
);
|
|
36947
|
+
const amount = Web3Number.fromWei(
|
|
36948
|
+
assets.toString(),
|
|
36949
|
+
this.metadata.depositTokens[0].decimals
|
|
36950
|
+
);
|
|
36951
|
+
const blockNumber = typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint" ? Number(blockIdentifier) : void 0;
|
|
36952
|
+
const price = await this.pricer.getPrice(
|
|
36953
|
+
this.metadata.depositTokens[0].symbol,
|
|
36954
|
+
blockNumber
|
|
36955
|
+
);
|
|
36956
|
+
const usdValue = Number(amount.toFixed(6)) * price.price;
|
|
36957
|
+
return {
|
|
36958
|
+
tokenInfo: this.asset(),
|
|
36959
|
+
amount,
|
|
36960
|
+
usdValue
|
|
36961
|
+
};
|
|
36962
|
+
}
|
|
36836
36963
|
/**
|
|
36837
36964
|
* Returns the unused balance in the vault allocator.
|
|
36838
36965
|
* Note: This function is common for any SVK strategy.
|
|
@@ -37024,6 +37151,100 @@ var SVKStrategy = class extends BaseStrategy {
|
|
|
37024
37151
|
usdValue
|
|
37025
37152
|
};
|
|
37026
37153
|
}
|
|
37154
|
+
async getUserRealizedAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
|
|
37155
|
+
logger.verbose(
|
|
37156
|
+
`${this.getTag()}: getUserRealizedAPY => starting with blockIdentifier=${blockIdentifier}, sinceBlocks=${sinceBlocks}`
|
|
37157
|
+
);
|
|
37158
|
+
const blockNow = typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint" ? Number(blockIdentifier) : (await this.config.provider.getBlockLatestAccepted()).block_number;
|
|
37159
|
+
const blockNowTime = typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint" ? (await this.config.provider.getBlockWithTxs(blockIdentifier)).timestamp : (/* @__PURE__ */ new Date()).getTime() / 1e3;
|
|
37160
|
+
const blockBefore = Math.max(
|
|
37161
|
+
blockNow - sinceBlocks,
|
|
37162
|
+
this.metadata.launchBlock
|
|
37163
|
+
);
|
|
37164
|
+
const assetsNowRaw = await this.contract.call("total_assets", [], {
|
|
37165
|
+
blockIdentifier
|
|
37166
|
+
});
|
|
37167
|
+
const amountNow = Web3Number.fromWei(
|
|
37168
|
+
assetsNowRaw.toString(),
|
|
37169
|
+
this.metadata.depositTokens[0].decimals
|
|
37170
|
+
);
|
|
37171
|
+
const supplyNowRaw = await this.contract.call("total_supply", [], {
|
|
37172
|
+
blockIdentifier
|
|
37173
|
+
});
|
|
37174
|
+
const supplyNow = Web3Number.fromWei(supplyNowRaw.toString(), 18);
|
|
37175
|
+
const assetsBeforeRaw = await this.contract.call(
|
|
37176
|
+
"total_assets",
|
|
37177
|
+
[],
|
|
37178
|
+
{ blockIdentifier: blockBefore }
|
|
37179
|
+
);
|
|
37180
|
+
const amountBefore = Web3Number.fromWei(
|
|
37181
|
+
assetsBeforeRaw.toString(),
|
|
37182
|
+
this.metadata.depositTokens[0].decimals
|
|
37183
|
+
);
|
|
37184
|
+
const supplyBeforeRaw = await this.contract.call(
|
|
37185
|
+
"total_supply",
|
|
37186
|
+
[],
|
|
37187
|
+
{ blockIdentifier: blockBefore }
|
|
37188
|
+
);
|
|
37189
|
+
const supplyBefore = Web3Number.fromWei(supplyBeforeRaw.toString(), 18);
|
|
37190
|
+
const blockBeforeInfo = await this.config.provider.getBlockWithTxs(
|
|
37191
|
+
blockBefore
|
|
37192
|
+
);
|
|
37193
|
+
const assetsPerShareNow = amountNow.multipliedBy(1e18).dividedBy(supplyNow.toString());
|
|
37194
|
+
const assetsPerShareBf = amountBefore.multipliedBy(1e18).dividedBy(supplyBefore.toString());
|
|
37195
|
+
const timeDiffSeconds = blockNowTime - blockBeforeInfo.timestamp;
|
|
37196
|
+
logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsNow: ${amountNow.toString()}`);
|
|
37197
|
+
logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsBefore: ${amountBefore.toString()}`);
|
|
37198
|
+
logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsPerShareNow: ${assetsPerShareNow.toString()}`);
|
|
37199
|
+
logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsPerShareBf: ${assetsPerShareBf.toString()}`);
|
|
37200
|
+
logger.verbose(`${this.getTag()} [getUserRealizedAPY] Supply before: ${supplyBefore.toString()}`);
|
|
37201
|
+
logger.verbose(`${this.getTag()} [getUserRealizedAPY] Supply now: ${supplyNow.toString()}`);
|
|
37202
|
+
logger.verbose(`${this.getTag()} [getUserRealizedAPY] Time diff in seconds: ${timeDiffSeconds}`);
|
|
37203
|
+
const apyForGivenBlocks = Number(
|
|
37204
|
+
assetsPerShareNow.minus(assetsPerShareBf).multipliedBy(1e4).dividedBy(assetsPerShareBf)
|
|
37205
|
+
) / 1e4;
|
|
37206
|
+
return apyForGivenBlocks * (365 * 24 * 3600) / timeDiffSeconds;
|
|
37207
|
+
}
|
|
37208
|
+
async getUserPositionCards(input) {
|
|
37209
|
+
const { user, investmentFlows = [] } = input;
|
|
37210
|
+
const [userTVL] = await Promise.all([
|
|
37211
|
+
this.getUserTVL(user)
|
|
37212
|
+
]);
|
|
37213
|
+
const cards = [
|
|
37214
|
+
{
|
|
37215
|
+
title: "Your Holdings",
|
|
37216
|
+
tooltip: "Your Holdings",
|
|
37217
|
+
value: this.formatTokenAmountForCard(userTVL.amount, userTVL.tokenInfo),
|
|
37218
|
+
subValue: `\u2248 ${this.formatUSDForCard(userTVL.usdValue)}`,
|
|
37219
|
+
subValueColor: "positive"
|
|
37220
|
+
}
|
|
37221
|
+
];
|
|
37222
|
+
let lifetimeAmount = userTVL.amount.multipliedBy(0);
|
|
37223
|
+
let lifetimeTokenInfo = userTVL.tokenInfo;
|
|
37224
|
+
let lifetimeUsdValue = 0;
|
|
37225
|
+
if (investmentFlows.length > 0) {
|
|
37226
|
+
try {
|
|
37227
|
+
const earningsResult = this.getLifetimeEarnings(userTVL, investmentFlows);
|
|
37228
|
+
lifetimeAmount = earningsResult.lifetimeEarnings;
|
|
37229
|
+
lifetimeTokenInfo = earningsResult.tokenInfo.tokenInfo;
|
|
37230
|
+
const userAmount = userTVL.amount.toNumber();
|
|
37231
|
+
if (Number.isFinite(userAmount) && userAmount > 0) {
|
|
37232
|
+
const pricePerToken = userTVL.usdValue / userAmount;
|
|
37233
|
+
lifetimeUsdValue = lifetimeAmount.toNumber() * pricePerToken;
|
|
37234
|
+
}
|
|
37235
|
+
} catch (error) {
|
|
37236
|
+
logger.warn(`${this.getTag()}::getUserPositionCards lifetime earnings fallback`, error);
|
|
37237
|
+
}
|
|
37238
|
+
}
|
|
37239
|
+
cards.push({
|
|
37240
|
+
title: "Lifetime Earnings",
|
|
37241
|
+
tooltip: "Lifetime Earnings",
|
|
37242
|
+
value: this.formatTokenAmountForCard(lifetimeAmount, lifetimeTokenInfo),
|
|
37243
|
+
subValue: `\u2248 ${this.formatUSDForCard(lifetimeUsdValue)}`,
|
|
37244
|
+
subValueColor: this.getSubValueColorFromSignedNumber(lifetimeUsdValue)
|
|
37245
|
+
});
|
|
37246
|
+
return cards;
|
|
37247
|
+
}
|
|
37027
37248
|
async getPrevAUM() {
|
|
37028
37249
|
const currentAUM = await this.contract.call("aum", []);
|
|
37029
37250
|
const prevAum = Web3Number.fromWei(currentAUM.toString(), this.asset().decimals);
|
|
@@ -37137,29 +37358,6 @@ var UniversalStrategy = class _UniversalStrategy extends SVKStrategy {
|
|
|
37137
37358
|
]);
|
|
37138
37359
|
return [call];
|
|
37139
37360
|
}
|
|
37140
|
-
async getUserTVL(user, blockIdentifier = "latest") {
|
|
37141
|
-
const shares = await this.contract.call("balanceOf", [user.address], { blockIdentifier });
|
|
37142
|
-
const assets = await this.contract.call(
|
|
37143
|
-
"convert_to_assets",
|
|
37144
|
-
[uint25623.bnToUint256(shares)],
|
|
37145
|
-
{ blockIdentifier }
|
|
37146
|
-
);
|
|
37147
|
-
const amount = Web3Number.fromWei(
|
|
37148
|
-
assets.toString(),
|
|
37149
|
-
this.metadata.depositTokens[0].decimals
|
|
37150
|
-
);
|
|
37151
|
-
const blockNumber = typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint" ? Number(blockIdentifier) : void 0;
|
|
37152
|
-
let price = await this.pricer.getPrice(
|
|
37153
|
-
this.metadata.depositTokens[0].symbol,
|
|
37154
|
-
blockNumber
|
|
37155
|
-
);
|
|
37156
|
-
const usdValue = Number(amount.toFixed(6)) * price.price;
|
|
37157
|
-
return {
|
|
37158
|
-
tokenInfo: this.asset(),
|
|
37159
|
-
amount,
|
|
37160
|
-
usdValue
|
|
37161
|
-
};
|
|
37162
|
-
}
|
|
37163
37361
|
async getVesuAPYs() {
|
|
37164
37362
|
const vesuAdapters = this.getVesuAdapters();
|
|
37165
37363
|
const allVesuPools = await VesuAdapter.getVesuPools();
|
|
@@ -37200,13 +37398,16 @@ var UniversalStrategy = class _UniversalStrategy extends SVKStrategy {
|
|
|
37200
37398
|
*/
|
|
37201
37399
|
async netAPY() {
|
|
37202
37400
|
if (this.metadata.isPreview) {
|
|
37203
|
-
return {
|
|
37204
|
-
|
|
37205
|
-
|
|
37206
|
-
|
|
37207
|
-
|
|
37208
|
-
|
|
37209
|
-
|
|
37401
|
+
return {
|
|
37402
|
+
net: 0,
|
|
37403
|
+
splits: [{
|
|
37404
|
+
apy: 0,
|
|
37405
|
+
id: "base"
|
|
37406
|
+
}, {
|
|
37407
|
+
apy: 0,
|
|
37408
|
+
id: "defispring"
|
|
37409
|
+
}]
|
|
37410
|
+
};
|
|
37210
37411
|
}
|
|
37211
37412
|
const { positions, baseAPYs, rewardAPYs } = await this.getVesuAPYs();
|
|
37212
37413
|
const unusedBalanceAPY = await this.getUnusedBalanceAPY();
|
|
@@ -37221,25 +37422,31 @@ var UniversalStrategy = class _UniversalStrategy extends SVKStrategy {
|
|
|
37221
37422
|
}
|
|
37222
37423
|
async returnNetAPY(baseAPYs, rewardAPYs, weights, prevAUMUSD) {
|
|
37223
37424
|
if (weights.every((p) => p == 0)) {
|
|
37224
|
-
return {
|
|
37225
|
-
|
|
37226
|
-
|
|
37227
|
-
|
|
37228
|
-
|
|
37229
|
-
|
|
37230
|
-
|
|
37425
|
+
return {
|
|
37426
|
+
net: 0,
|
|
37427
|
+
splits: [{
|
|
37428
|
+
apy: 0,
|
|
37429
|
+
id: "base"
|
|
37430
|
+
}, {
|
|
37431
|
+
apy: 0,
|
|
37432
|
+
id: "defispring"
|
|
37433
|
+
}]
|
|
37434
|
+
};
|
|
37231
37435
|
}
|
|
37232
37436
|
const baseAPY = this.computeAPY(baseAPYs, weights, prevAUMUSD);
|
|
37233
37437
|
const rewardAPY = this.computeAPY(rewardAPYs, weights, prevAUMUSD);
|
|
37234
37438
|
const netAPY = baseAPY + rewardAPY;
|
|
37235
37439
|
logger.verbose(`${this.metadata.name}::netAPY: net: ${netAPY}, baseAPY: ${baseAPY}, rewardAPY: ${rewardAPY}`);
|
|
37236
|
-
return {
|
|
37237
|
-
|
|
37238
|
-
|
|
37239
|
-
|
|
37240
|
-
|
|
37241
|
-
|
|
37242
|
-
|
|
37440
|
+
return {
|
|
37441
|
+
net: netAPY,
|
|
37442
|
+
splits: [{
|
|
37443
|
+
apy: baseAPY,
|
|
37444
|
+
id: "base"
|
|
37445
|
+
}, {
|
|
37446
|
+
apy: rewardAPY,
|
|
37447
|
+
id: "defispring"
|
|
37448
|
+
}]
|
|
37449
|
+
};
|
|
37243
37450
|
}
|
|
37244
37451
|
async getUnusedBalanceAPY() {
|
|
37245
37452
|
return {
|
|
@@ -37253,104 +37460,6 @@ var UniversalStrategy = class _UniversalStrategy extends SVKStrategy {
|
|
|
37253
37460
|
logger.verbose(`${this.getTag()} computeAPY: apys: ${JSON.stringify(apys)}, weights: ${JSON.stringify(weights)}, weightedSum: ${weightedSum}, currentAUM: ${currentAUM}`);
|
|
37254
37461
|
return weightedSum / currentAUM.toNumber();
|
|
37255
37462
|
}
|
|
37256
|
-
/**
|
|
37257
|
-
* Calculates user realized APY based on trueSharesBasedAPY method.
|
|
37258
|
-
* Returns the APY as a number.
|
|
37259
|
-
*/
|
|
37260
|
-
async getUserRealizedAPY(blockIdentifier = "latest", sinceBlocks = 6e5) {
|
|
37261
|
-
logger.verbose(
|
|
37262
|
-
`${this.getTag()}: getUserRealizedAPY => starting with blockIdentifier=${blockIdentifier}, sinceBlocks=${sinceBlocks}`
|
|
37263
|
-
);
|
|
37264
|
-
let blockNow = typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint" ? Number(blockIdentifier) : (await this.config.provider.getBlockLatestAccepted()).block_number;
|
|
37265
|
-
const blockNowTime = typeof blockIdentifier === "number" || typeof blockIdentifier === "bigint" ? (await this.config.provider.getBlockWithTxs(blockIdentifier)).timestamp : (/* @__PURE__ */ new Date()).getTime() / 1e3;
|
|
37266
|
-
const blockBefore = Math.max(
|
|
37267
|
-
blockNow - sinceBlocks,
|
|
37268
|
-
this.metadata.launchBlock
|
|
37269
|
-
);
|
|
37270
|
-
const assetsNowRaw = await this.contract.call("total_assets", [], {
|
|
37271
|
-
blockIdentifier
|
|
37272
|
-
});
|
|
37273
|
-
const amountNow = Web3Number.fromWei(
|
|
37274
|
-
assetsNowRaw.toString(),
|
|
37275
|
-
this.metadata.depositTokens[0].decimals
|
|
37276
|
-
);
|
|
37277
|
-
const supplyNowRaw = await this.contract.call("total_supply", [], {
|
|
37278
|
-
blockIdentifier
|
|
37279
|
-
});
|
|
37280
|
-
const supplyNow = Web3Number.fromWei(supplyNowRaw.toString(), 18);
|
|
37281
|
-
const assetsBeforeRaw = await this.contract.call(
|
|
37282
|
-
"total_assets",
|
|
37283
|
-
[],
|
|
37284
|
-
{ blockIdentifier: blockBefore }
|
|
37285
|
-
);
|
|
37286
|
-
const amountBefore = Web3Number.fromWei(
|
|
37287
|
-
assetsBeforeRaw.toString(),
|
|
37288
|
-
this.metadata.depositTokens[0].decimals
|
|
37289
|
-
);
|
|
37290
|
-
const supplyBeforeRaw = await this.contract.call(
|
|
37291
|
-
"total_supply",
|
|
37292
|
-
[],
|
|
37293
|
-
{ blockIdentifier: blockBefore }
|
|
37294
|
-
);
|
|
37295
|
-
const supplyBefore = Web3Number.fromWei(supplyBeforeRaw.toString(), 18);
|
|
37296
|
-
const blockBeforeInfo = await this.config.provider.getBlockWithTxs(
|
|
37297
|
-
blockBefore
|
|
37298
|
-
);
|
|
37299
|
-
const assetsPerShareNow = amountNow.multipliedBy(1e18).dividedBy(supplyNow.toString());
|
|
37300
|
-
const assetsPerShareBf = amountBefore.multipliedBy(1e18).dividedBy(supplyBefore.toString());
|
|
37301
|
-
const timeDiffSeconds = blockNowTime - blockBeforeInfo.timestamp;
|
|
37302
|
-
logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsNow: ${amountNow.toString()}`);
|
|
37303
|
-
logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsBefore: ${amountBefore.toString()}`);
|
|
37304
|
-
logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsPerShareNow: ${assetsPerShareNow.toString()}`);
|
|
37305
|
-
logger.verbose(`${this.getTag()} [getUserRealizedAPY] assetsPerShareBf: ${assetsPerShareBf.toString()}`);
|
|
37306
|
-
logger.verbose(`${this.getTag()} [getUserRealizedAPY] Supply before: ${supplyBefore.toString()}`);
|
|
37307
|
-
logger.verbose(`${this.getTag()} [getUserRealizedAPY] Supply now: ${supplyNow.toString()}`);
|
|
37308
|
-
logger.verbose(`${this.getTag()} [getUserRealizedAPY] Time diff in seconds: ${timeDiffSeconds}`);
|
|
37309
|
-
const apyForGivenBlocks = Number(
|
|
37310
|
-
assetsPerShareNow.minus(assetsPerShareBf).multipliedBy(1e4).dividedBy(assetsPerShareBf)
|
|
37311
|
-
) / 1e4;
|
|
37312
|
-
return apyForGivenBlocks * (365 * 24 * 3600) / timeDiffSeconds;
|
|
37313
|
-
}
|
|
37314
|
-
async getUserPositionCards(input) {
|
|
37315
|
-
const { user, investmentFlows = [] } = input;
|
|
37316
|
-
const [userTVL] = await Promise.all([
|
|
37317
|
-
this.getUserTVL(user)
|
|
37318
|
-
]);
|
|
37319
|
-
const cards = [
|
|
37320
|
-
{
|
|
37321
|
-
title: "Your Holdings",
|
|
37322
|
-
tooltip: "Your Holdings",
|
|
37323
|
-
value: this.formatTokenAmountForCard(userTVL.amount, userTVL.tokenInfo),
|
|
37324
|
-
subValue: `\u2248 ${this.formatUSDForCard(userTVL.usdValue)}`,
|
|
37325
|
-
subValueColor: "positive"
|
|
37326
|
-
}
|
|
37327
|
-
];
|
|
37328
|
-
let lifetimeAmount = userTVL.amount.multipliedBy(0);
|
|
37329
|
-
let lifetimeTokenInfo = userTVL.tokenInfo;
|
|
37330
|
-
let lifetimeUsdValue = 0;
|
|
37331
|
-
if (investmentFlows.length > 0) {
|
|
37332
|
-
try {
|
|
37333
|
-
const earningsResult = this.getLifetimeEarnings(userTVL, investmentFlows);
|
|
37334
|
-
lifetimeAmount = earningsResult.lifetimeEarnings;
|
|
37335
|
-
lifetimeTokenInfo = earningsResult.tokenInfo.tokenInfo;
|
|
37336
|
-
const userAmount = userTVL.amount.toNumber();
|
|
37337
|
-
if (Number.isFinite(userAmount) && userAmount > 0) {
|
|
37338
|
-
const pricePerToken = userTVL.usdValue / userAmount;
|
|
37339
|
-
lifetimeUsdValue = lifetimeAmount.toNumber() * pricePerToken;
|
|
37340
|
-
}
|
|
37341
|
-
} catch (error) {
|
|
37342
|
-
logger.warn(`${this.getTag()}::getUserPositionCards lifetime earnings fallback`, error);
|
|
37343
|
-
}
|
|
37344
|
-
}
|
|
37345
|
-
cards.push({
|
|
37346
|
-
title: "Lifetime Earnings",
|
|
37347
|
-
tooltip: "Lifetime Earnings",
|
|
37348
|
-
value: this.formatTokenAmountForCard(lifetimeAmount, lifetimeTokenInfo),
|
|
37349
|
-
subValue: `\u2248 ${this.formatUSDForCard(lifetimeUsdValue)}`,
|
|
37350
|
-
subValueColor: this.getSubValueColorFromSignedNumber(lifetimeUsdValue)
|
|
37351
|
-
});
|
|
37352
|
-
return cards;
|
|
37353
|
-
}
|
|
37354
37463
|
/**
|
|
37355
37464
|
* Calculates the total TVL of the strategy.
|
|
37356
37465
|
* @returns Object containing the total amount in token units and USD value
|
|
@@ -37427,13 +37536,17 @@ var UniversalStrategy = class _UniversalStrategy extends SVKStrategy {
|
|
|
37427
37536
|
};
|
|
37428
37537
|
const aumToken = vesuAum.plus(balance.amount);
|
|
37429
37538
|
if (aumToken.isZero()) {
|
|
37430
|
-
return {
|
|
37431
|
-
|
|
37432
|
-
|
|
37433
|
-
|
|
37434
|
-
|
|
37435
|
-
|
|
37436
|
-
|
|
37539
|
+
return {
|
|
37540
|
+
net,
|
|
37541
|
+
splits: [{
|
|
37542
|
+
aum: zeroAmt,
|
|
37543
|
+
id: "finalised" /* FINALISED */
|
|
37544
|
+
}, {
|
|
37545
|
+
aum: zeroAmt,
|
|
37546
|
+
id: "defispring" /* DEFISPRING */
|
|
37547
|
+
}],
|
|
37548
|
+
prevAum
|
|
37549
|
+
};
|
|
37437
37550
|
}
|
|
37438
37551
|
logger.verbose(`${this.getTag()} Actual AUM: ${aumToken}`);
|
|
37439
37552
|
const rewardAssets = await this.getRewardsAUM(prevAum);
|
|
@@ -38086,6 +38199,9 @@ var createUniversalStrategy = (params) => {
|
|
|
38086
38199
|
auditUrl: AUDIT_URL3,
|
|
38087
38200
|
protocols: [Protocols.VESU],
|
|
38088
38201
|
realizedApyMethodology: "The realizedAPY is based on past 14 days performance by the vault",
|
|
38202
|
+
feeBps: {
|
|
38203
|
+
performanceFeeBps: 1e3
|
|
38204
|
+
},
|
|
38089
38205
|
curator: UnwrapLabsCurator,
|
|
38090
38206
|
settings: createUniversalSettings(params.tokenSymbol, params.maxTVLDecimals),
|
|
38091
38207
|
contractDetails: getContractDetails(params.vaultSettings),
|
|
@@ -38727,11 +38843,15 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
38727
38843
|
remarks: "defispring" /* DEFISPRING */,
|
|
38728
38844
|
protocol: Protocols.NONE
|
|
38729
38845
|
};
|
|
38730
|
-
return {
|
|
38731
|
-
|
|
38732
|
-
|
|
38733
|
-
|
|
38734
|
-
|
|
38846
|
+
return {
|
|
38847
|
+
net: {
|
|
38848
|
+
tokenInfo: underlying,
|
|
38849
|
+
amount: netAUM,
|
|
38850
|
+
usdValue: netAUM.toNumber() * assetPrice.price
|
|
38851
|
+
},
|
|
38852
|
+
prevAum,
|
|
38853
|
+
splits: [realAUM, estimatedAUMDelta]
|
|
38854
|
+
};
|
|
38735
38855
|
}
|
|
38736
38856
|
async getTVLUnrealized() {
|
|
38737
38857
|
return await this.getAUM(true);
|
|
@@ -38749,6 +38869,62 @@ var UniversalLstMultiplierStrategy = class _UniversalLstMultiplierStrategy exten
|
|
|
38749
38869
|
tokenInfo: this.asset()
|
|
38750
38870
|
};
|
|
38751
38871
|
}
|
|
38872
|
+
async getUserPositionCards(input) {
|
|
38873
|
+
const cards = await super.getUserPositionCards(input);
|
|
38874
|
+
try {
|
|
38875
|
+
const [unrealizedResult, userTVL, realizedApyRaw] = await Promise.all([
|
|
38876
|
+
this.getUserUnrealizedGains(input.user),
|
|
38877
|
+
this.getUserTVL(input.user),
|
|
38878
|
+
this.getUserRealizedAPY().catch(() => null)
|
|
38879
|
+
]);
|
|
38880
|
+
const amount = unrealizedResult.unrealizedGains;
|
|
38881
|
+
let usdValue = 0;
|
|
38882
|
+
const userAmount = userTVL.amount.toNumber();
|
|
38883
|
+
if (Number.isFinite(userAmount) && userAmount > 0) {
|
|
38884
|
+
usdValue = userTVL.usdValue / userAmount * amount.toNumber();
|
|
38885
|
+
}
|
|
38886
|
+
cards.push({
|
|
38887
|
+
title: "Unrealized Gains",
|
|
38888
|
+
tooltip: "Unrealized gains based on current market prices vs Endur prices. If you withdraw now, you will forgo these gains.",
|
|
38889
|
+
value: this.formatTokenAmountForCard(amount, unrealizedResult.tokenInfo),
|
|
38890
|
+
subValue: `\u2248 ${this.formatUSDForCard(usdValue)}`,
|
|
38891
|
+
subValueColor: this.getSubValueColorFromSignedNumber(usdValue)
|
|
38892
|
+
});
|
|
38893
|
+
const realizedApy = typeof realizedApyRaw === "number" ? this.formatPercentForCard(realizedApyRaw) : "N/A";
|
|
38894
|
+
cards.push({
|
|
38895
|
+
title: "Realized APY",
|
|
38896
|
+
tooltip: this.metadata.realizedApyMethodology || "Realized APY is based on past 14 days performance",
|
|
38897
|
+
value: realizedApy
|
|
38898
|
+
});
|
|
38899
|
+
} catch (error) {
|
|
38900
|
+
logger.warn(`${this.getTag()}::getUserPositionCards unrealized gains fallback`, error);
|
|
38901
|
+
cards.push({
|
|
38902
|
+
title: "Unrealized Gains",
|
|
38903
|
+
tooltip: "Unrealized gains based on current market prices vs Endur prices. If you withdraw now, you will forgo these gains.",
|
|
38904
|
+
value: this.formatTokenAmountForCard(
|
|
38905
|
+
Web3Number.fromWei("0", this.asset().decimals),
|
|
38906
|
+
this.asset()
|
|
38907
|
+
),
|
|
38908
|
+
subValue: `\u2248 ${this.formatUSDForCard(0)}`,
|
|
38909
|
+
subValueColor: "default"
|
|
38910
|
+
});
|
|
38911
|
+
cards.push({
|
|
38912
|
+
title: "Realized APY",
|
|
38913
|
+
tooltip: this.metadata.realizedApyMethodology || "Realized APY is based on past 14 days performance",
|
|
38914
|
+
value: "N/A"
|
|
38915
|
+
});
|
|
38916
|
+
}
|
|
38917
|
+
if (this.asset().symbol === "xSTRK") {
|
|
38918
|
+
const index = cards.findIndex((card) => card.title === "Lifetime Earnings");
|
|
38919
|
+
if (index >= 0) {
|
|
38920
|
+
cards[index] = {
|
|
38921
|
+
...cards[index],
|
|
38922
|
+
tooltip: "Lifetime earnings of the vault. Due to migration of xSTRK Sensei to this vault, any migrated funds are also seen as lifetime earnings. Team is working to fix this soon."
|
|
38923
|
+
};
|
|
38924
|
+
}
|
|
38925
|
+
}
|
|
38926
|
+
return cards;
|
|
38927
|
+
}
|
|
38752
38928
|
};
|
|
38753
38929
|
function VaultDescription(lstSymbol, underlyingSymbol) {
|
|
38754
38930
|
const containerStyle = {
|
|
@@ -39156,6 +39332,9 @@ function getStrategySettings(lstSymbol, underlyingSymbol, settings, isPreview =
|
|
|
39156
39332
|
isPreview,
|
|
39157
39333
|
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.",
|
|
39158
39334
|
realizedApyMethodology: "The realizedAPY is based on past 14 days performance by the vault",
|
|
39335
|
+
feeBps: {
|
|
39336
|
+
performanceFeeBps: 1e3
|
|
39337
|
+
},
|
|
39159
39338
|
tags: lstSymbol.includes("BTC") ? ["BTC" /* BTC */, "Maxx" /* LEVERED */] : ["Maxx" /* LEVERED */],
|
|
39160
39339
|
security: HYPER_LST_SECURITY,
|
|
39161
39340
|
redemptionInfo: HYPER_LST_REDEMPTION_INFO,
|
|
@@ -39369,6 +39548,23 @@ var BoostedxSTRKCarryStrategy = class _BoostedxSTRKCarryStrategy extends SVKStra
|
|
|
39369
39548
|
usdValue
|
|
39370
39549
|
};
|
|
39371
39550
|
}
|
|
39551
|
+
async getUserPositionCards(input) {
|
|
39552
|
+
const cards = await super.getUserPositionCards(input);
|
|
39553
|
+
const realizedApyRaw = await this.getUserRealizedAPY().catch((error) => {
|
|
39554
|
+
logger.warn(
|
|
39555
|
+
`${this.getTag()}::getUserPositionCards realized APY fallback`,
|
|
39556
|
+
error
|
|
39557
|
+
);
|
|
39558
|
+
return null;
|
|
39559
|
+
});
|
|
39560
|
+
const realizedApy = typeof realizedApyRaw === "number" ? this.formatPercentForCard(realizedApyRaw) : "N/A";
|
|
39561
|
+
cards.push({
|
|
39562
|
+
title: "Realized APY",
|
|
39563
|
+
tooltip: this.metadata.realizedApyMethodology || "Realized APY is based on past 14 days performance",
|
|
39564
|
+
value: realizedApy
|
|
39565
|
+
});
|
|
39566
|
+
return cards;
|
|
39567
|
+
}
|
|
39372
39568
|
async getAUM() {
|
|
39373
39569
|
const underlying = this.asset();
|
|
39374
39570
|
const depositTokenPrice = await this.pricer.getPrice(underlying.symbol);
|
|
@@ -39878,38 +40074,38 @@ var wbtcBoostedSettings = {
|
|
|
39878
40074
|
var boostedCarryRiskFactors = [
|
|
39879
40075
|
{
|
|
39880
40076
|
type: "Smart Contract Risk" /* SMART_CONTRACT_RISK */,
|
|
39881
|
-
value:
|
|
40077
|
+
value: 1 /* BATTLE_TESTED */,
|
|
39882
40078
|
// 20% — core trust assumption; SVK is audited but still multi-contract (vault, manager, adapters).
|
|
39883
40079
|
weight: 20,
|
|
39884
40080
|
reason: "Built on the Starknet Vault Kit (SVK), with audits under the Sherlock-audited branch."
|
|
39885
40081
|
},
|
|
39886
40082
|
{
|
|
39887
40083
|
type: "Liquidation Risk" /* LIQUIDATION_RISK */,
|
|
39888
|
-
value:
|
|
40084
|
+
value: 2 /* LOW_PROBABILITY */,
|
|
39889
40085
|
// 20% — tied with smart contract; uncorrelated collateral/debt is the main principal risk here.
|
|
39890
40086
|
weight: 20,
|
|
39891
40087
|
reason: "Collateral (USDC or WBTC) and STRK debt are not price-correlated. We target ~50% LTV and rebalance above ~55%, with a health-factor buffer, but extreme moves or prolonged monitoring gaps can still trigger liquidation."
|
|
39892
40088
|
},
|
|
39893
40089
|
{
|
|
39894
40090
|
type: "Low Liquidity Risk" /* LOW_LIQUIDITY_RISK */,
|
|
39895
|
-
value:
|
|
40091
|
+
value: 1 /* GOOD_LIQUIDITY */,
|
|
39896
40092
|
// 15% — below liquidation but above ops risks; every unwind/withdraw depends on xSTRK→STRK depth.
|
|
39897
40093
|
weight: 15,
|
|
39898
|
-
reason: "Closing the loop requires selling xSTRK to STRK on DEXes to repay Vesu debt.
|
|
40094
|
+
reason: "Closing the loop requires selling xSTRK to STRK on DEXes to repay Vesu debt. larger withdrawals or rebalances may take longer or complete in smaller chunks."
|
|
39899
40095
|
},
|
|
39900
40096
|
{
|
|
39901
40097
|
type: "Technical Risk" /* TECHNICAL_RISK */,
|
|
39902
40098
|
value: 3 /* SOME_COMPLEXITY */,
|
|
39903
40099
|
// 13% — monitoring/rebalancing stack matters, but usually recoverable without instant loss.
|
|
39904
|
-
weight:
|
|
40100
|
+
weight: 10,
|
|
39905
40101
|
reason: "Yield routes across Vesu, Avnu, and Hyper xSTRK with automated monitoring. Technical failures can delay rebalancing."
|
|
39906
40102
|
},
|
|
39907
40103
|
{
|
|
39908
40104
|
type: "Depeg Risk" /* DEPEG_RISK */,
|
|
39909
|
-
value:
|
|
40105
|
+
value: 2 /* GENERALLY_STABLE */,
|
|
39910
40106
|
// 12% — affects yield and swap notionals; USDC/WBTC depeg is rarer than xSTRK/STRK drift.
|
|
39911
40107
|
weight: 12,
|
|
39912
|
-
reason: "xSTRK
|
|
40108
|
+
reason: "Historically, xSTRK's DEX price has been generally stable compared to its true price."
|
|
39913
40109
|
},
|
|
39914
40110
|
{
|
|
39915
40111
|
type: "Oracle Risk" /* ORACLE_RISK */,
|
|
@@ -39929,7 +40125,7 @@ var boostedCarryRiskFactors = [
|
|
|
39929
40125
|
type: "Market Risk" /* MARKET_RISK */,
|
|
39930
40126
|
value: 3 /* MODERATE_VOLATILITY */,
|
|
39931
40127
|
// 5% — largely captured by liquidation + depeg factors; kept small to avoid double-counting vol.
|
|
39932
|
-
weight:
|
|
40128
|
+
weight: 8,
|
|
39933
40129
|
reason: "STRK, BTC, and stablecoin volatility can move loan-to-value and swap costs."
|
|
39934
40130
|
}
|
|
39935
40131
|
];
|
|
@@ -39958,15 +40154,15 @@ function getBoostedCarryFAQs(depositSymbol, debtSymbol, lstSymbol) {
|
|
|
39958
40154
|
question: "Which protocols are used?",
|
|
39959
40155
|
answer: /* @__PURE__ */ jsxs5("span", { children: [
|
|
39960
40156
|
/* @__PURE__ */ jsx6("strong", { children: "Vesu" }),
|
|
39961
|
-
" for collateral and borrowing,
|
|
39962
|
-
/* @__PURE__ */ jsx6("strong", { children: "Avnu" }),
|
|
40157
|
+
" for collateral and borrowing,",
|
|
39963
40158
|
" ",
|
|
39964
|
-
"
|
|
40159
|
+
/* @__PURE__ */ jsx6("strong", { children: "Avnu" }),
|
|
40160
|
+
" for swaps, ",
|
|
39965
40161
|
/* @__PURE__ */ jsx6("strong", { children: "Endur" }),
|
|
39966
|
-
" for
|
|
39967
|
-
lstSymbol,
|
|
39968
|
-
", and the Troves",
|
|
40162
|
+
" for",
|
|
39969
40163
|
" ",
|
|
40164
|
+
lstSymbol,
|
|
40165
|
+
", and the Troves ",
|
|
39970
40166
|
/* @__PURE__ */ jsxs5("strong", { children: [
|
|
39971
40167
|
"Hyper-",
|
|
39972
40168
|
lstSymbol
|
|
@@ -40054,6 +40250,9 @@ function getStrategySettings2(settings, meta) {
|
|
|
40054
40250
|
]
|
|
40055
40251
|
},
|
|
40056
40252
|
contractDetails: getContractDetails(settings),
|
|
40253
|
+
feeBps: {
|
|
40254
|
+
performanceFeeBps: 1500
|
|
40255
|
+
},
|
|
40057
40256
|
faqs: getBoostedCarryFAQs(
|
|
40058
40257
|
depositToken.symbol,
|
|
40059
40258
|
debtToken.symbol,
|
|
@@ -40374,7 +40573,7 @@ function createStrategy(type, config, pricer, metadata) {
|
|
|
40374
40573
|
}
|
|
40375
40574
|
|
|
40376
40575
|
// src/modules/pricer-lst.ts
|
|
40377
|
-
import
|
|
40576
|
+
import axios10 from "axios";
|
|
40378
40577
|
var PricerLST2 = class extends Pricer {
|
|
40379
40578
|
// e.g. xSTRK/STRK
|
|
40380
40579
|
constructor(config, tokenMaps) {
|
|
@@ -40410,7 +40609,7 @@ var PricerLST2 = class extends Pricer {
|
|
|
40410
40609
|
async _getPriceEkubo(token, amountIn = new Web3Number(1, token.decimals), retry = 0) {
|
|
40411
40610
|
const underlying = this.getUnderlying(token);
|
|
40412
40611
|
const url = this.EKUBO_API.replace("{{TOKEN_ADDRESS}}", token.address.toString()).replace("{{AMOUNT}}", amountIn.toWei()).replace("{{UNDERLYING_ADDRESS}}", underlying.address.toString());
|
|
40413
|
-
const result = await
|
|
40612
|
+
const result = await axios10.get(url);
|
|
40414
40613
|
const data = result.data;
|
|
40415
40614
|
const multiplier = 1 / amountIn.toNumber();
|
|
40416
40615
|
const outputUnderlying = Number(Web3Number.fromWei(data.total_calculated, underlying.decimals).toFixed(6)) * multiplier;
|
|
@@ -40562,6 +40761,7 @@ var PricerRedis = class extends Pricer {
|
|
|
40562
40761
|
async startWithRedis(redisUrl) {
|
|
40563
40762
|
await this.initRedis(redisUrl);
|
|
40564
40763
|
logger.info(`Starting Pricer with Redis`);
|
|
40764
|
+
this.avnuApiPricer.start();
|
|
40565
40765
|
this._loadPrices(this._setRedisPrices.bind(this));
|
|
40566
40766
|
setInterval(() => {
|
|
40567
40767
|
this._loadPrices(this._setRedisPrices.bind(this));
|
|
@@ -41008,6 +41208,7 @@ export {
|
|
|
41008
41208
|
PositionTypeAvnuExtended,
|
|
41009
41209
|
Pragma,
|
|
41010
41210
|
Pricer,
|
|
41211
|
+
PricerAvnuApi,
|
|
41011
41212
|
PricerBase,
|
|
41012
41213
|
PricerFromApi,
|
|
41013
41214
|
PricerLST2 as PricerLST,
|