@strkfarm/sdk 2.0.0-dev.9 → 2.0.0-staging.2

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.
Files changed (64) hide show
  1. package/dist/index.browser.global.js +111371 -93151
  2. package/dist/index.browser.mjs +27815 -32690
  3. package/dist/index.d.ts +1095 -2011
  4. package/dist/index.js +27425 -32309
  5. package/dist/index.mjs +27590 -32452
  6. package/package.json +6 -5
  7. package/src/data/ekubo-price-fethcer.abi.json +265 -0
  8. package/src/data/universal-vault.abi.json +20 -135
  9. package/src/dataTypes/address.ts +0 -7
  10. package/src/dataTypes/index.ts +3 -2
  11. package/src/dataTypes/mynumber.ts +141 -0
  12. package/src/global.ts +296 -288
  13. package/src/index.browser.ts +6 -5
  14. package/src/interfaces/common.tsx +324 -184
  15. package/src/modules/apollo-client-config.ts +28 -0
  16. package/src/modules/avnu.ts +4 -17
  17. package/src/modules/ekubo-pricer.ts +79 -0
  18. package/src/modules/ekubo-quoter.ts +11 -88
  19. package/src/modules/erc20.ts +21 -67
  20. package/src/modules/harvests.ts +26 -15
  21. package/src/modules/index.ts +11 -13
  22. package/src/modules/lst-apr.ts +0 -36
  23. package/src/modules/pragma.ts +23 -8
  24. package/src/modules/pricer-from-api.ts +150 -14
  25. package/src/modules/pricer.ts +2 -1
  26. package/src/modules/pricerBase.ts +2 -1
  27. package/src/node/deployer.ts +36 -1
  28. package/src/node/pricer-redis.ts +2 -1
  29. package/src/strategies/autoCompounderStrk.ts +1 -1
  30. package/src/strategies/base-strategy.ts +5 -22
  31. package/src/strategies/ekubo-cl-vault.tsx +2904 -2175
  32. package/src/strategies/factory.ts +165 -0
  33. package/src/strategies/index.ts +10 -11
  34. package/src/strategies/registry.ts +268 -0
  35. package/src/strategies/sensei.ts +416 -292
  36. package/src/strategies/universal-adapters/adapter-utils.ts +1 -5
  37. package/src/strategies/universal-adapters/baseAdapter.ts +153 -181
  38. package/src/strategies/universal-adapters/common-adapter.ts +77 -98
  39. package/src/strategies/universal-adapters/index.ts +1 -5
  40. package/src/strategies/universal-adapters/vesu-adapter.ts +218 -220
  41. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +51 -58
  42. package/src/strategies/universal-lst-muliplier-strategy.tsx +1952 -992
  43. package/src/strategies/universal-strategy.tsx +1713 -1150
  44. package/src/strategies/vesu-rebalance.tsx +1189 -986
  45. package/src/utils/health-factor-math.ts +5 -11
  46. package/src/utils/index.ts +8 -9
  47. package/src/utils/strategy-utils.ts +57 -0
  48. package/src/data/extended-deposit.abi.json +0 -3613
  49. package/src/modules/ExtendedWrapperSDk/index.ts +0 -62
  50. package/src/modules/ExtendedWrapperSDk/types.ts +0 -311
  51. package/src/modules/ExtendedWrapperSDk/wrapper.ts +0 -395
  52. package/src/modules/midas.ts +0 -159
  53. package/src/modules/token-market-data.ts +0 -202
  54. package/src/strategies/svk-strategy.ts +0 -247
  55. package/src/strategies/universal-adapters/adapter-optimizer.ts +0 -65
  56. package/src/strategies/universal-adapters/avnu-adapter.ts +0 -413
  57. package/src/strategies/universal-adapters/extended-adapter.ts +0 -972
  58. package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
  59. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +0 -1306
  60. package/src/strategies/vesu-extended-strategy/services/operationService.ts +0 -34
  61. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +0 -77
  62. package/src/strategies/vesu-extended-strategy/utils/constants.ts +0 -49
  63. package/src/strategies/vesu-extended-strategy/utils/helper.ts +0 -370
  64. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +0 -1379
@@ -1,7 +1,27 @@
1
- import { getNoRiskTags, highlightTextWithLinks, IConfig, IProtocol, IStrategyMetadata, RiskFactor, RiskType, TokenInfo } from "@/interfaces";
2
- import { BaseStrategy, SingleActionAmount, SingleTokenInfo } from "./base-strategy";
1
+ import {
2
+ getNoRiskTags,
3
+ highlightTextWithLinks,
4
+ IConfig,
5
+ IProtocol,
6
+ IStrategyMetadata,
7
+ RiskFactor,
8
+ RiskType,
9
+ StrategyCategory,
10
+ StrategyTag,
11
+ StrategyLiveStatus,
12
+ TokenInfo,
13
+ AuditStatus,
14
+ SourceCodeType,
15
+ AccessControlType,
16
+ InstantWithdrawalVault
17
+ } from "@/interfaces";
18
+ import {
19
+ BaseStrategy,
20
+ SingleActionAmount,
21
+ SingleTokenInfo
22
+ } from "./base-strategy";
3
23
  import { ContractAddr, Web3Number } from "@/dataTypes";
4
- import { Call, Contract, uint256 } from "starknet";
24
+ import { Call, Contract, uint256, BlockIdentifier } from "starknet";
5
25
  import SenseiABI from "@/data/sensei.abi.json";
6
26
  import { getTrovesEndpoint, logger } from "@/utils";
7
27
  import { Global } from "@/global";
@@ -9,332 +29,436 @@ import { QuoteRequest } from "@avnu/avnu-sdk";
9
29
  import { PricerBase } from "@/modules/pricerBase";
10
30
  import ERC20ABI from "@/data/erc20.abi.json";
11
31
  import { AvnuWrapper } from "@/modules";
32
+ import { gql } from "@apollo/client";
33
+ import apolloClient from "@/modules/apollo-client";
12
34
 
13
35
  export interface SenseiVaultSettings {
14
- mainToken: TokenInfo;
15
- secondaryToken: TokenInfo;
16
- targetHfBps: number; // in bps
17
- feeBps: number; // in bps
36
+ mainToken: TokenInfo;
37
+ secondaryToken: TokenInfo;
38
+ targetHfBps: number; // in bps
39
+ feeBps: number; // in bps
18
40
  }
19
41
 
20
42
  export class SenseiVault extends BaseStrategy<
21
- SingleTokenInfo,
22
- SingleActionAmount
43
+ SingleTokenInfo,
44
+ SingleActionAmount
23
45
  > {
24
- readonly address: ContractAddr;
25
- readonly metadata: IStrategyMetadata<SenseiVaultSettings>;
26
- readonly pricer: PricerBase;
27
- readonly contract: Contract;
28
- constructor(config: IConfig, pricer: PricerBase, metadata: IStrategyMetadata<SenseiVaultSettings>) {
29
- super(config);
30
- this.address = metadata.address;
31
- this.pricer = pricer;
32
- this.metadata = metadata;
33
- this.contract = new Contract({abi: SenseiABI, address: this.address.address, providerOrAccount: this.config.provider});
46
+ readonly address: ContractAddr;
47
+ readonly metadata: IStrategyMetadata<SenseiVaultSettings>;
48
+ readonly pricer: PricerBase;
49
+ readonly contract: Contract;
50
+ constructor(
51
+ config: IConfig,
52
+ pricer: PricerBase,
53
+ metadata: IStrategyMetadata<SenseiVaultSettings>
54
+ ) {
55
+ super(config);
56
+ this.address = metadata.address;
57
+ this.pricer = pricer;
58
+ this.metadata = metadata;
59
+ this.contract = new Contract({
60
+ abi: SenseiABI,
61
+ address: this.address.address,
62
+ providerOrAccount: this.config.provider
63
+ });
34
64
 
35
- if (metadata.depositTokens.length === 0) {
36
- throw new Error("Deposit tokens are not defined in metadata");
65
+ if (metadata.depositTokens.length === 0) {
66
+ throw new Error("Deposit tokens are not defined in metadata");
67
+ }
37
68
  }
38
- }
39
69
 
40
- async getUserTVL(user: ContractAddr): Promise<SingleTokenInfo> {
41
- const result: any = await this.contract.call(
42
- "describe_position",
43
- [user.address],
44
- );
45
- const amount = Web3Number.fromWei(
46
- uint256.uint256ToBN(result[1].estimated_size).toString(),
47
- this.metadata.depositTokens[0].decimals,
48
- )
49
- const price = await this.pricer.getPrice(
50
- this.metadata.depositTokens[0].symbol,
51
- );
52
- return {
53
- usdValue: Number(amount.toFixed(6)) * price.price,
54
- amount,
55
- tokenInfo: this.metadata.depositTokens[0],
56
- }
57
- }
58
-
59
- async getTVL(): Promise<SingleTokenInfo> {
60
- try {
61
- const {
62
- collateralXSTRK,
63
- collateralUSDValue,
64
- debtSTRK,
65
- debtUSDValue,
66
- xSTRKPrice,
67
- collateralInSTRK,
68
- } = await this.getPositionInfo();
70
+ async getUserTVL(
71
+ user: ContractAddr,
72
+ blockIdentifier: BlockIdentifier = "latest"
73
+ ): Promise<SingleTokenInfo> {
74
+ const result: any = await this.contract.call(
75
+ "describe_position",
76
+ [user.address],
77
+ {
78
+ blockIdentifier
79
+ }
80
+ );
81
+ const amount = Web3Number.fromWei(
82
+ uint256.uint256ToBN(result[1].estimated_size).toString(),
83
+ this.metadata.depositTokens[0].decimals
84
+ );
69
85
 
70
- const usdValue =
71
- Number(collateralUSDValue.toFixed(6)) -
72
- Number(debtUSDValue.toFixed(6));
86
+ // Convert blockIdentifier to block number for pricer if it's a number
87
+ const blockNumber =
88
+ typeof blockIdentifier === "number" ||
89
+ typeof blockIdentifier === "bigint"
90
+ ? Number(blockIdentifier)
91
+ : undefined;
73
92
 
74
- return {
75
- usdValue,
76
- amount: new Web3Number(
77
- (collateralInSTRK - Number(debtSTRK.toFixed(6))).toFixed(6),
78
- collateralXSTRK.decimals,
79
- ),
80
- tokenInfo: this.metadata.depositTokens[0],
81
- };
82
- } catch (error) {
83
- console.error('Error fetching TVL:', error);
84
- return {
85
- usdValue: 0,
86
- amount: new Web3Number('0', this.metadata.depositTokens[0].decimals),
87
- tokenInfo: this.metadata.depositTokens[0],
88
- }
93
+ const price = await this.pricer.getPrice(
94
+ this.metadata.depositTokens[0].symbol,
95
+ blockNumber
96
+ );
97
+ return {
98
+ usdValue: Number(amount.toFixed(6)) * price.price,
99
+ amount,
100
+ tokenInfo: this.metadata.depositTokens[0]
101
+ };
89
102
  }
90
- }
91
103
 
92
- async depositCall(amountInfo: SingleActionAmount, receiver: ContractAddr): Promise<Call[]> {
93
- const mainTokenContract = new Contract({
94
- abi: ERC20ABI,
95
- address: this.metadata.depositTokens[0].address.address,
96
- providerOrAccount: this.config.provider,
97
- });
98
- const call1 = mainTokenContract.populate('approve', [
99
- this.address.address,
100
- uint256.bnToUint256(amountInfo.amount.toWei()),
101
- ]);
102
- const call2 = this.contract.populate('deposit', [
103
- uint256.bnToUint256(amountInfo.amount.toWei()),
104
- receiver.address,
105
- ]);
104
+ async getTVL(): Promise<SingleTokenInfo> {
105
+ try {
106
+ const {
107
+ collateralXSTRK,
108
+ collateralUSDValue,
109
+ debtSTRK,
110
+ debtUSDValue,
111
+ xSTRKPrice,
112
+ collateralInSTRK
113
+ } = await this.getPositionInfo();
106
114
 
107
- const calls = [call1, call2];
108
- return calls;
109
- }
115
+ const usdValue =
116
+ Number(collateralUSDValue.toFixed(6)) -
117
+ Number(debtUSDValue.toFixed(6));
110
118
 
111
- async withdrawCall(amountInfo: SingleActionAmount, receiver: ContractAddr, owner: ContractAddr): Promise<Call[]> {
112
- const call = this.contract.populate('withdraw', [
113
- uint256.bnToUint256(amountInfo.amount.toWei()),
114
- receiver.address,
115
- 300, // 3% max slippage
116
- ]);
117
- return [call];
118
- }
119
+ return {
120
+ usdValue,
121
+ amount: new Web3Number(
122
+ (collateralInSTRK - Number(debtSTRK.toFixed(6))).toFixed(6),
123
+ collateralXSTRK.decimals
124
+ ),
125
+ tokenInfo: this.metadata.depositTokens[0]
126
+ };
127
+ } catch (error) {
128
+ console.error("Error fetching TVL:", error);
129
+ return {
130
+ usdValue: 0,
131
+ amount: new Web3Number(
132
+ "0",
133
+ this.metadata.depositTokens[0].decimals
134
+ ),
135
+ tokenInfo: this.metadata.depositTokens[0]
136
+ };
137
+ }
138
+ }
119
139
 
120
- async getPositionInfo(): Promise<{
121
- collateralXSTRK: Web3Number;
122
- collateralUSDValue: Web3Number;
123
- debtSTRK: Web3Number;
124
- debtUSDValue: Web3Number;
125
- xSTRKPrice: number;
126
- collateralInSTRK: number;
127
- }> {
128
- const CACHE_KEY = 'positionInfo';
129
- const existingCacheData = this.getCache<{
130
- collateralXSTRK: Web3Number;
131
- collateralUSDValue: Web3Number;
132
- debtSTRK: Web3Number;
133
- debtUSDValue: Web3Number;
134
- xSTRKPrice: number;
135
- collateralInSTRK: number;
136
- }>(CACHE_KEY);
137
- if (existingCacheData) return existingCacheData;
140
+ async depositCall(
141
+ amountInfo: SingleActionAmount,
142
+ receiver: ContractAddr
143
+ ): Promise<Call[]> {
144
+ const mainTokenContract = new Contract({
145
+ abi: ERC20ABI,
146
+ address: this.metadata.depositTokens[0].address.address,
147
+ providerOrAccount: this.config.provider
148
+ });
149
+ const call1 = mainTokenContract.populate("approve", [
150
+ this.address.address,
151
+ uint256.bnToUint256(amountInfo.amount.toWei())
152
+ ]);
153
+ const call2 = this.contract.populate("deposit", [
154
+ uint256.bnToUint256(amountInfo.amount.toWei()),
155
+ receiver.address
156
+ ]);
138
157
 
139
- const resp = await fetch(
140
- `${getTrovesEndpoint()}/vesu/positions?walletAddress=${this.address.address}`,
141
- );
142
- const data = await resp.json();
143
- if (!data.data || data.data.length == 0) {
144
- throw new Error('No positions found');
158
+ const calls = [call1, call2];
159
+ return calls;
145
160
  }
146
161
 
147
- const collateralXSTRK = Web3Number.fromWei(
148
- data.data[0].collateral.value,
149
- data.data[0].collateral.decimals,
150
- );
151
- const collateralUSDValue = Web3Number.fromWei(
152
- data.data[0].collateral.usdPrice.value,
153
- data.data[0].collateral.usdPrice.decimals,
154
- );
155
- const debtSTRK = Web3Number.fromWei(
156
- data.data[0].debt.value,
157
- data.data[0].debt.decimals,
158
- );
159
- const debtUSDValue = Web3Number.fromWei(
160
- data.data[0].debt.usdPrice.value,
161
- data.data[0].debt.usdPrice.decimals,
162
- );
162
+ async withdrawCall(
163
+ amountInfo: SingleActionAmount,
164
+ receiver: ContractAddr,
165
+ owner: ContractAddr
166
+ ): Promise<Call[]> {
167
+ const call = this.contract.populate("withdraw", [
168
+ uint256.bnToUint256(amountInfo.amount.toWei()),
169
+ receiver.address,
170
+ 300 // 3% max slippage
171
+ ]);
172
+ return [call];
173
+ }
163
174
 
164
- const xSTRKPrice = await this.getSecondaryTokenPriceRelativeToMain();
165
- const collateralInSTRK =
166
- Number(collateralXSTRK.toFixed(6)) * xSTRKPrice;
167
- const STRKUSDPrice =
168
- Number(debtUSDValue.toFixed(6)) /
169
- Number(debtSTRK.toFixed(6));
170
- const actualCollateralUSDValue = collateralInSTRK * STRKUSDPrice;
175
+ async getPositionInfo(): Promise<{
176
+ collateralXSTRK: Web3Number;
177
+ collateralUSDValue: Web3Number;
178
+ debtSTRK: Web3Number;
179
+ debtUSDValue: Web3Number;
180
+ xSTRKPrice: number;
181
+ collateralInSTRK: number;
182
+ }> {
183
+ const CACHE_KEY = "positionInfo";
184
+ const existingCacheData = this.getCache<{
185
+ collateralXSTRK: Web3Number;
186
+ collateralUSDValue: Web3Number;
187
+ debtSTRK: Web3Number;
188
+ debtUSDValue: Web3Number;
189
+ xSTRKPrice: number;
190
+ collateralInSTRK: number;
191
+ }>(CACHE_KEY);
192
+ if (existingCacheData) return existingCacheData;
171
193
 
172
- const cacheData = {
173
- collateralXSTRK,
174
- collateralUSDValue: new Web3Number(
175
- actualCollateralUSDValue.toFixed(6),
176
- collateralUSDValue.decimals,
177
- ),
178
- debtSTRK,
179
- debtUSDValue,
180
- xSTRKPrice,
181
- collateralInSTRK,
182
- };
183
- this.setCache(CACHE_KEY, cacheData); // cache for 1 hour
184
- return cacheData;
185
- }
194
+ const resp = await fetch(
195
+ `${getTrovesEndpoint()}/vesu/positions?walletAddress=${
196
+ this.address.address
197
+ }`
198
+ );
199
+ const data = await resp.json();
200
+ if (!data.data || data.data.length == 0) {
201
+ throw new Error("No positions found");
202
+ }
186
203
 
187
- async getSecondaryTokenPriceRelativeToMain(retry = 0): Promise<number> {
188
- const CACHE_KEY = 'xSTRKPrice';
189
- const existingCacheData = this.getCache<number>(CACHE_KEY);
190
- if (existingCacheData) return existingCacheData;
191
-
192
- const params: QuoteRequest = {
193
- sellTokenAddress: this.metadata.additionalInfo.secondaryToken.address.address,
194
- buyTokenAddress: this.metadata.additionalInfo.mainToken.address.address,
195
- sellAmount: BigInt(new Web3Number('1', 18).toWei()),
196
- takerAddress: this.address.address,
197
- };
198
- logger.verbose('getSecondaryTokenPriceRelativeToMain [1]', params);
199
- let avnu = new AvnuWrapper();
200
- const quote = await avnu.getQuotes(
201
- params.sellTokenAddress,
202
- params.buyTokenAddress,
203
- params.sellAmount?.toString() || '0',
204
- params.takerAddress!
205
- );
206
- if (!quote) {
207
- throw new Error('No quotes found to compute secondary token price relative to main token');
204
+ const collateralXSTRK = Web3Number.fromWei(
205
+ data.data[0].collateral.value,
206
+ data.data[0].collateral.decimals
207
+ );
208
+ const collateralUSDValue = Web3Number.fromWei(
209
+ data.data[0].collateral.usdPrice.value,
210
+ data.data[0].collateral.usdPrice.decimals
211
+ );
212
+ const debtSTRK = Web3Number.fromWei(
213
+ data.data[0].debt.value,
214
+ data.data[0].debt.decimals
215
+ );
216
+ const debtUSDValue = Web3Number.fromWei(
217
+ data.data[0].debt.usdPrice.value,
218
+ data.data[0].debt.usdPrice.decimals
219
+ );
220
+
221
+ const xSTRKPrice = await this.getSecondaryTokenPriceRelativeToMain();
222
+ const collateralInSTRK =
223
+ Number(collateralXSTRK.toFixed(6)) * xSTRKPrice;
224
+ const STRKUSDPrice =
225
+ Number(debtUSDValue.toFixed(6)) / Number(debtSTRK.toFixed(6));
226
+ const actualCollateralUSDValue = collateralInSTRK * STRKUSDPrice;
227
+
228
+ const cacheData = {
229
+ collateralXSTRK,
230
+ collateralUSDValue: new Web3Number(
231
+ actualCollateralUSDValue.toFixed(6),
232
+ collateralUSDValue.decimals
233
+ ),
234
+ debtSTRK,
235
+ debtUSDValue,
236
+ xSTRKPrice,
237
+ collateralInSTRK
238
+ };
239
+ this.setCache(CACHE_KEY, cacheData); // cache for 1 hour
240
+ return cacheData;
208
241
  }
209
242
 
210
- const firstQuote = quote;
211
- const price = Number(
212
- Web3Number.fromWei(firstQuote.buyAmount.toString(), 18).toFixed(
213
- 6,
214
- ),
215
- );
216
- logger.verbose('getSecondaryTokenPriceRelativeToMain [2]', price);
217
- this.setCache(CACHE_KEY, price); // cache for 1 min
218
- return price;
219
- }
243
+ async getSecondaryTokenPriceRelativeToMain(retry = 0): Promise<number> {
244
+ const CACHE_KEY = "xSTRKPrice";
245
+ const existingCacheData = this.getCache<number>(CACHE_KEY);
246
+ if (existingCacheData) return existingCacheData;
247
+
248
+ const params: QuoteRequest = {
249
+ sellTokenAddress:
250
+ this.metadata.additionalInfo.secondaryToken.address.address,
251
+ buyTokenAddress:
252
+ this.metadata.additionalInfo.mainToken.address.address,
253
+ sellAmount: BigInt(new Web3Number("1", 18).toWei()),
254
+ takerAddress: this.address.address
255
+ };
256
+ logger.verbose("getSecondaryTokenPriceRelativeToMain [1]", params);
257
+ let avnu = new AvnuWrapper();
258
+ const quote = await avnu.getQuotes(
259
+ params.sellTokenAddress,
260
+ params.buyTokenAddress,
261
+ params.sellAmount?.toString() || "0",
262
+ params.takerAddress!
263
+ );
264
+ if (!quote) {
265
+ throw new Error(
266
+ "No quotes found to compute secondary token price relative to main token"
267
+ );
268
+ }
269
+
270
+ const firstQuote = quote;
271
+ const price = Number(
272
+ Web3Number.fromWei(firstQuote.buyAmount.toString(), 18).toFixed(6)
273
+ );
274
+ logger.verbose("getSecondaryTokenPriceRelativeToMain [2]", price);
275
+ this.setCache(CACHE_KEY, price); // cache for 1 min
276
+ return price;
277
+ }
220
278
 
221
- getSettings = async () => {
222
- const settings = await this.contract.call('get_settings', []);
223
- logger.verbose('getSettings', settings);
224
- return settings;
225
- };
226
-
279
+ getSettings = async () => {
280
+ const settings = await this.contract.call("get_settings", []);
281
+ logger.verbose("getSettings", settings);
282
+ return settings;
283
+ };
227
284
  }
228
285
 
229
286
  const 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}}.`;
230
287
 
231
288
  const vesuProtocol: IProtocol = {
232
- name: "Vesu",
233
- logo: "https://static-assets-8zct.onrender.com/integrations/vesu/logo.png"
289
+ name: "Vesu",
290
+ logo: "https://static-assets-8zct.onrender.com/integrations/vesu/logo.png"
234
291
  };
235
292
  const endurProtocol: IProtocol = {
236
- name: "Endur",
237
- logo: "https://app.endur.fi/logo.png"
293
+ name: "Endur",
294
+ logo: "https://app.endur.fi/logo.png"
238
295
  };
239
296
  const _riskFactor: RiskFactor[] = [
240
- { type: RiskType.SMART_CONTRACT_RISK, value: 0.5, weight: 25, reason: "Audited by CSC" },
241
- { type: RiskType.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." },
242
- { type: RiskType.LIQUIDATION_RISK, value: 0.1, weight: 10, reason: "Liquidation risk is low due to the nature of the Re7 Pool on Vesu" },
243
- { type: RiskType.LOW_LIQUIDITY_RISK, value: 0.5, weight: 50, reason: "xSTRK can be sometimes illiquid near true price" }
297
+ {
298
+ type: RiskType.SMART_CONTRACT_RISK,
299
+ value: 0.5,
300
+ weight: 25,
301
+ reason: "Audited by CSC"
302
+ },
303
+ {
304
+ type: RiskType.DEPEG_RISK,
305
+ value: 0.25,
306
+ weight: 25,
307
+ reason: "Depending on prevailing market conditions and trading activity, xSTRK may lose its peg to the underlying asset."
308
+ },
309
+ {
310
+ type: RiskType.LIQUIDATION_RISK,
311
+ value: 0.1,
312
+ weight: 10,
313
+ reason: "Liquidation risk is low due to the nature of the Re7 Pool on Vesu"
314
+ },
315
+ {
316
+ type: RiskType.LOW_LIQUIDITY_RISK,
317
+ value: 0.5,
318
+ weight: 50,
319
+ reason: "xSTRK can be sometimes illiquid near true price"
320
+ }
244
321
  ];
245
322
 
246
323
  const FAQS = [
247
- {
248
- question: "What is xSTRK Sensei?",
249
- 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."
250
- },
251
- {
252
- question: "What is the benefit of using xSTRK Sensei?",
253
- answer: "The strategy amplifies your xSTRK exposure and yield through leverage. It also helps you accumulate more Endur points faster."
254
- },
255
- {
256
- question: "What is the maximum leverage possible?",
257
- 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",
258
- },
259
- {
260
- question: "Isn't 1.1 health factor risky?",
261
- 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."
262
- },
263
- {
264
- question: "Are there any risks involved?",
265
- 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."
266
- },
267
- {
268
- question: "Does the position always grow?",
269
- 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."
270
- },
271
- {
272
- question: "Can I lose money using this strategy?",
273
- answer: "Yes. If the xSTRK price drops sharply or becomes illiquid, you may face slippage or loss when trying to exit the looped position."
274
- },
275
- {
276
- question: "What affects the DEX price of xSTRK?",
277
- 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."
278
- },
279
- {
280
- question: "Why is xSTRK considered illiquid?",
281
- 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.",
282
- },
283
- {
284
- question: "Do I earn Endur points on looped xSTRK?",
285
- 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.",
286
- }
324
+ {
325
+ question: "What is xSTRK Sensei?",
326
+ 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."
327
+ },
328
+ {
329
+ question: "What is the benefit of using xSTRK Sensei?",
330
+ answer: "The strategy amplifies your xSTRK exposure and yield through leverage. It also helps you accumulate more Endur points faster."
331
+ },
332
+ {
333
+ question: "What is the maximum leverage possible?",
334
+ 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"
335
+ },
336
+ {
337
+ question: "Isn't 1.1 health factor risky?",
338
+ 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."
339
+ },
340
+ {
341
+ question: "Are there any risks involved?",
342
+ 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."
343
+ },
344
+ {
345
+ question: "Does the position always grow?",
346
+ 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."
347
+ },
348
+ {
349
+ question: "Can I lose money using this strategy?",
350
+ answer: "Yes. If the xSTRK price drops sharply or becomes illiquid, you may face slippage or loss when trying to exit the looped position."
351
+ },
352
+ {
353
+ question: "What affects the DEX price of xSTRK?",
354
+ 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."
355
+ },
356
+ {
357
+ question: "Why is xSTRK considered illiquid?",
358
+ 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."
359
+ },
360
+ {
361
+ question: "Do I earn Endur points on looped xSTRK?",
362
+ 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."
363
+ }
287
364
  ];
288
365
 
289
- export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] =
290
- [
366
+ export const SenseiStrategies: IStrategyMetadata<SenseiVaultSettings>[] = [
291
367
  {
292
- name: "xSTRK Sensei",
293
- description: highlightTextWithLinks(
294
- senseiDescription.replaceAll('{{token1}}', 'STRK').replaceAll('{{token2}}', 'xSTRK'),
295
- [{
296
- highlight: "Endur",
297
- link: "https://endur.fi"
298
- }, {
299
- highlight: "Vesu",
300
- link: "https://vesu.xyz"
301
- }, {
302
- highlight: 'delta neutral position',
303
- link: 'https://www.investopedia.com/terms/d/deltaneutral.asp'
304
- }]
305
- ),
306
- address: ContractAddr.from(
307
- "0x7023a5cadc8a5db80e4f0fde6b330cbd3c17bbbf9cb145cbabd7bd5e6fb7b0b"
308
- ),
309
- launchBlock: 1053811,
310
- type: "Other",
311
- depositTokens: [
312
- Global.getDefaultTokens().find((t) => t.symbol === "STRK")!
313
- ],
314
- protocols: [endurProtocol, vesuProtocol],
315
- maxTVL: new Web3Number("1500000", 18),
316
- risk: {
317
- riskFactor: _riskFactor,
318
- netRisk:
319
- _riskFactor.reduce((acc, curr) => acc + curr.value * curr.weight, 0) /
320
- _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
321
- notARisks: getNoRiskTags(_riskFactor)
322
- },
323
- additionalInfo: {
324
- mainToken: Global.getDefaultTokens().find((t) => t.symbol === "STRK")!,
325
- secondaryToken: Global.getDefaultTokens().find((t) => t.symbol === "xSTRK")!,
326
- targetHfBps: 11000, // 1.1 health factor
327
- feeBps: 2000, // 2% fee on profits
328
- },
329
- faqs: FAQS,
330
- contractDetails: [],
331
- investmentSteps: [
332
- "Swap STRK for xSTRK",
333
- "Deposit xSTRK to Vesu's Re7 xSTRK Pool",
334
- "Borrow STRK against your xSTRK collateral",
335
- "Buy more xSTRK with borrowed STRK",
336
- "Repeat the process to loop your position",
337
- "Claim DeFi spring (STRK) rewards weekly and reinvest",
338
- ]
339
- },
340
- ];
368
+ id: "xstrk_sensei",
369
+ name: "xSTRK Sensei",
370
+ description: highlightTextWithLinks(
371
+ senseiDescription
372
+ .replace(/\{\{token1\}\}/g, "STRK")
373
+ .replace(/\{\{token2\}\}/g, "xSTRK"),
374
+ [
375
+ {
376
+ highlight: "Endur",
377
+ link: "https://endur.fi"
378
+ },
379
+ {
380
+ highlight: "Vesu",
381
+ link: "https://vesu.xyz"
382
+ },
383
+ {
384
+ highlight: "delta neutral position",
385
+ link: "https://www.investopedia.com/terms/d/deltaneutral.asp"
386
+ }
387
+ ]
388
+ ),
389
+ address: ContractAddr.from(
390
+ "0x7023a5cadc8a5db80e4f0fde6b330cbd3c17bbbf9cb145cbabd7bd5e6fb7b0b"
391
+ ),
392
+ launchBlock: 1053811,
393
+ type: "Other",
394
+ depositTokens: [
395
+ Global.getDefaultTokens().find((t) => t.symbol === "STRK")!
396
+ ],
397
+ protocols: [endurProtocol, vesuProtocol],
398
+ settings: {
399
+ maxTVL: new Web3Number("1500000", 18),
400
+ alerts: [
401
+ {
402
+ type: "info",
403
+ 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.",
404
+ tab: "all"
405
+ }
406
+ ],
407
+ liveStatus: StrategyLiveStatus.ACTIVE,
408
+ isPaused: false,
409
+ isInMaintenance: false,
410
+ isAudited: false,
411
+ isInstantWithdrawal: true,
412
+ isTransactionHistDisabled: true,
413
+ quoteToken: Global.getDefaultTokens().find(
414
+ (t) => t.symbol === "STRK"
415
+ )!
416
+ },
417
+ risk: {
418
+ riskFactor: _riskFactor,
419
+ netRisk:
420
+ _riskFactor.reduce(
421
+ (acc, curr) => acc + curr.value * curr.weight,
422
+ 0
423
+ ) / _riskFactor.reduce((acc, curr) => acc + curr.weight, 0),
424
+ notARisks: getNoRiskTags(_riskFactor)
425
+ },
426
+ additionalInfo: {
427
+ mainToken: Global.getDefaultTokens().find(
428
+ (t) => t.symbol === "STRK"
429
+ )!,
430
+ secondaryToken: Global.getDefaultTokens().find(
431
+ (t) => t.symbol === "xSTRK"
432
+ )!,
433
+ targetHfBps: 11000, // 1.1 health factor
434
+ feeBps: 2000 // 2% fee on profits
435
+ },
436
+ faqs: FAQS,
437
+ contractDetails: [],
438
+ investmentSteps: [
439
+ "Swap STRK for xSTRK",
440
+ "Deposit xSTRK to Vesu's Re7 xSTRK Pool",
441
+ "Borrow STRK against your xSTRK collateral",
442
+ "Buy more xSTRK with borrowed STRK",
443
+ "Repeat the process to loop your position",
444
+ "Claim DeFi spring (STRK) rewards weekly and reinvest"
445
+ ],
446
+ category: StrategyCategory.ALL,
447
+ tags: [StrategyTag.SENSEI],
448
+ security: {
449
+ auditStatus: AuditStatus.AUDITED,
450
+ sourceCode: {
451
+ type: SourceCodeType.CLOSED_SOURCE,
452
+ contractLink: "https://github.com/trovesfi/troves-contracts"
453
+ },
454
+ accessControl: {
455
+ type: AccessControlType.STANDARD_ACCOUNT,
456
+ addresses: [ContractAddr.from("0x0")],
457
+ timeLock: "2 Days"
458
+ }
459
+ },
460
+ redemptionInfo: {
461
+ instantWithdrawalVault: InstantWithdrawalVault.YES
462
+ }
463
+ }
464
+ ];