@strkfarm/sdk 2.0.0-dev.27 → 2.0.0-dev.28

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 (70) hide show
  1. package/dist/cli.js +190 -36
  2. package/dist/cli.mjs +188 -34
  3. package/dist/index.browser.global.js +79130 -49357
  4. package/dist/index.browser.mjs +18039 -11434
  5. package/dist/index.d.ts +2869 -898
  6. package/dist/index.js +19036 -12210
  7. package/dist/index.mjs +18942 -12161
  8. package/package.json +1 -1
  9. package/src/data/avnu.abi.json +840 -0
  10. package/src/data/ekubo-price-fethcer.abi.json +265 -0
  11. package/src/dataTypes/_bignumber.ts +13 -4
  12. package/src/dataTypes/index.ts +3 -2
  13. package/src/dataTypes/mynumber.ts +141 -0
  14. package/src/global.ts +76 -41
  15. package/src/index.browser.ts +2 -1
  16. package/src/interfaces/common.tsx +167 -2
  17. package/src/modules/ExtendedWrapperSDk/types.ts +26 -4
  18. package/src/modules/ExtendedWrapperSDk/wrapper.ts +110 -67
  19. package/src/modules/apollo-client-config.ts +28 -0
  20. package/src/modules/avnu.ts +4 -4
  21. package/src/modules/ekubo-pricer.ts +79 -0
  22. package/src/modules/ekubo-quoter.ts +46 -30
  23. package/src/modules/erc20.ts +17 -0
  24. package/src/modules/harvests.ts +43 -29
  25. package/src/modules/pragma.ts +23 -8
  26. package/src/modules/pricer-from-api.ts +156 -15
  27. package/src/modules/pricer-lst.ts +1 -1
  28. package/src/modules/pricer.ts +40 -4
  29. package/src/modules/pricerBase.ts +2 -1
  30. package/src/node/deployer.ts +36 -1
  31. package/src/node/pricer-redis.ts +2 -1
  32. package/src/strategies/base-strategy.ts +78 -10
  33. package/src/strategies/ekubo-cl-vault.tsx +906 -347
  34. package/src/strategies/factory.ts +159 -0
  35. package/src/strategies/index.ts +6 -1
  36. package/src/strategies/registry.ts +239 -0
  37. package/src/strategies/sensei.ts +335 -7
  38. package/src/strategies/svk-strategy.ts +97 -27
  39. package/src/strategies/types.ts +4 -0
  40. package/src/strategies/universal-adapters/adapter-utils.ts +2 -1
  41. package/src/strategies/universal-adapters/avnu-adapter.ts +177 -268
  42. package/src/strategies/universal-adapters/baseAdapter.ts +263 -251
  43. package/src/strategies/universal-adapters/common-adapter.ts +206 -203
  44. package/src/strategies/universal-adapters/extended-adapter.ts +155 -336
  45. package/src/strategies/universal-adapters/index.ts +9 -8
  46. package/src/strategies/universal-adapters/token-transfer-adapter.ts +200 -0
  47. package/src/strategies/universal-adapters/usdc<>usdce-adapter.ts +200 -0
  48. package/src/strategies/universal-adapters/vesu-adapter.ts +110 -75
  49. package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +476 -0
  50. package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +762 -844
  51. package/src/strategies/universal-adapters/vesu-position-common.ts +251 -0
  52. package/src/strategies/universal-adapters/vesu-supply-only-adapter.ts +18 -3
  53. package/src/strategies/universal-lst-muliplier-strategy.tsx +396 -204
  54. package/src/strategies/universal-strategy.tsx +1426 -1178
  55. package/src/strategies/vesu-extended-strategy/services/executionService.ts +2251 -0
  56. package/src/strategies/vesu-extended-strategy/services/extended-vesu-state-manager.ts +2941 -0
  57. package/src/strategies/vesu-extended-strategy/services/operationService.ts +12 -1
  58. package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +52 -0
  59. package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +1 -0
  60. package/src/strategies/vesu-extended-strategy/utils/constants.ts +2 -0
  61. package/src/strategies/vesu-extended-strategy/utils/helper.ts +158 -124
  62. package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +377 -1788
  63. package/src/strategies/vesu-rebalance.tsx +255 -152
  64. package/src/utils/health-factor-math.ts +4 -1
  65. package/src/utils/index.ts +2 -1
  66. package/src/utils/logger.browser.ts +22 -4
  67. package/src/utils/logger.node.ts +259 -24
  68. package/src/utils/starknet-call-parser.ts +1036 -0
  69. package/src/utils/strategy-utils.ts +61 -0
  70. package/src/strategies/universal-adapters/unused-balance-adapter.ts +0 -109
@@ -1,251 +1,263 @@
1
- import { Call, hash, num, shortString } from "starknet";
2
- import { SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
3
- import { ContractAddr, Web3Number } from "@/dataTypes";
4
- import { IConfig, IProtocol, TokenInfo } from "@/interfaces";
5
- import { PricerBase } from "@/modules/pricerBase";
6
- import { LeafData, logger, StandardMerkleTree } from "@/utils";
7
- import { CacheClass } from "@/utils/cacheClass";
8
-
9
- export interface ManageCall {
10
- sanitizer: ContractAddr,
11
- call: {
12
- contractAddress: ContractAddr,
13
- selector: string,
14
- calldata: bigint[]
15
- }
16
- }
17
-
18
-
19
- export interface DepositParams {
20
- amount: Web3Number;
21
- }
22
-
23
- export interface WithdrawParams {
24
- amount: Web3Number;
25
- }
26
-
27
- // export type GenerateCallFn<T> = (params: T) => ManageCall;
28
- // export type AdapterLeafType<T> = {leaf: LeafData, callConstructor: GenerateCallFn<T>}
29
- export type GenerateCallFn<T> = (params: T) => Promise<ManageCall[]>;
30
- export type AdapterLeafType<T> = {leaves: LeafData[], callConstructor: GenerateCallFn<T>}
31
- export type LeafAdapterFn<T> = () => AdapterLeafType<T>;
32
-
33
- export enum APYType {
34
- BASE = "base",
35
- REWARD = "reward",
36
- LST = "lst"
37
- }
38
-
39
- export interface SupportedPosition {
40
- asset: TokenInfo,
41
- isDebt: boolean
42
- }
43
-
44
- export interface BaseAdapterConfig {
45
- baseToken: TokenInfo,
46
- supportedPositions: SupportedPosition[],
47
- networkConfig: IConfig,
48
- pricer: PricerBase,
49
- vaultAllocator: ContractAddr
50
- vaultAddress: ContractAddr
51
- }
52
-
53
- export type PositionAPY = { apy: number, type: APYType };
54
- export type PositionInfo = {
55
- tokenInfo: TokenInfo,
56
- amount: Web3Number,
57
- usdValue: number,
58
- remarks: string,
59
- apy: PositionAPY,
60
- protocol: IProtocol
61
- };
62
-
63
- export type PositionAmount = {
64
- amount: Web3Number,
65
- remarks: string,
66
- }
67
-
68
- export abstract class BaseAdapter<DepositParams, WithdrawParams> extends CacheClass {
69
- readonly name: string;
70
- readonly config: BaseAdapterConfig;
71
- readonly protocol: IProtocol;
72
-
73
- constructor(config: BaseAdapterConfig, name: string, protocol: IProtocol) {
74
- super();
75
- this.config = config;
76
- this.name = name;
77
- this.protocol = protocol;
78
- }
79
-
80
- /**
81
- * Loop through all supported positions and return amount, usd value, remarks and apy for each
82
- */
83
- async getPositions(): Promise<PositionInfo[]> {
84
- const results: PositionInfo[] = [];
85
- for (const supported of this.config.supportedPositions) {
86
- const amount = await this.getPosition(supported);
87
- const usdValue = await this.getUSDValue(supported.asset, amount.amount);
88
- const apy = await this.getAPY(supported);
89
- results.push({ tokenInfo: supported.asset, amount: amount.amount, usdValue, apy, protocol: this.protocol, remarks: amount.remarks });
90
- }
91
- return results;
92
- }
93
-
94
- /**
95
- * Implemented by child adapters to compute APY for a given supported position
96
- */
97
- protected abstract getAPY(supportedPosition: SupportedPosition): Promise<PositionAPY>;
98
-
99
- /**
100
- * Implemented by child adapters to fetch amount for a given supported position
101
- */
102
- protected abstract getPosition(supportedPosition: SupportedPosition): Promise<PositionAmount>;
103
-
104
- /**
105
- * Implemented by child adapters to calculate maximum deposit positions
106
- * @param amount Optional amount in baseToken to deposit
107
- */
108
- abstract maxDeposit(amount?: Web3Number): Promise<PositionInfo>;
109
-
110
- /**
111
- * Implemented by child adapters to calculate maximum withdraw positions
112
- */
113
- abstract maxWithdraw(): Promise<PositionInfo>;
114
-
115
- /**
116
- * Uses pricer to convert an amount of an asset to USD value
117
- */
118
- protected async getUSDValue(asset: TokenInfo, amount: Web3Number): Promise<number> {
119
- const priceInfo = await this.config.pricer.getPrice(asset.symbol);
120
- return amount.toNumber() * priceInfo.price;
121
- }
122
-
123
-
124
- protected constructSimpleLeafData(params: {
125
- id: string,
126
- target: ContractAddr,
127
- method: string,
128
- packedArguments: bigint[],
129
- }, sanitizer: ContractAddr = SIMPLE_SANITIZER): LeafData {
130
- const { id, target, method, packedArguments } = params;
131
- return {
132
- id: BigInt(num.getDecimalString(shortString.encodeShortString(id))),
133
- readableId: id,
134
- data: [
135
- sanitizer.toBigInt(), // sanitizer address
136
- target.toBigInt(), // contract
137
- toBigInt(hash.getSelectorFromName(method)), // method name
138
- BigInt(packedArguments.length),
139
- ...packedArguments
140
- ]
141
- };
142
- }
143
-
144
- /**
145
- * Implementor must provide target/method/packedArguments/sanitizer for deposit leaf construction
146
- */
147
- protected abstract _getDepositLeaf(): {
148
- target: ContractAddr,
149
- method: string,
150
- packedArguments: bigint[],
151
- sanitizer: ContractAddr,
152
- id: string
153
- }[];
154
-
155
- /**
156
- * Implementor must provide target/method/packedArguments/sanitizer for withdraw leaf construction
157
- */
158
- protected abstract _getWithdrawLeaf(): {
159
- target: ContractAddr,
160
- method: string,
161
- packedArguments: bigint[],
162
- sanitizer: ContractAddr,
163
- id: string
164
- }[];
165
-
166
- /**
167
- * Returns deposit leaf adapter using configured proof id
168
- */
169
- getDepositLeaf(): AdapterLeafType<DepositParams> {
170
- const leafConfigs = this._getDepositLeaf();
171
- const leaves = leafConfigs.map(config => {
172
- const { target, method, packedArguments, sanitizer, id } = config;
173
- const leaf = this.constructSimpleLeafData({
174
- id: id,
175
- target,
176
- method,
177
- packedArguments
178
- }, sanitizer);
179
- return leaf;
180
- });
181
- return { leaves, callConstructor: this.getDepositCall.bind(this) as unknown as GenerateCallFn<DepositParams> };
182
- }
183
-
184
- /**
185
- * Returns withdraw leaf adapter using configured proof id
186
- */
187
- getWithdrawLeaf(): AdapterLeafType<WithdrawParams> {
188
- const leafConfigs = this._getWithdrawLeaf();
189
- const leaves = leafConfigs.map(config => {
190
- const { target, method, packedArguments, sanitizer, id } = config;
191
- const leaf = this.constructSimpleLeafData({
192
- id: id,
193
- target,
194
- method,
195
- packedArguments
196
- }, sanitizer ?? SIMPLE_SANITIZER);
197
- return leaf;
198
- });
199
- return { leaves, callConstructor: this.getWithdrawCall.bind(this) as unknown as GenerateCallFn<WithdrawParams> };
200
- }
201
-
202
- /**
203
- * Implementor must provide deposit call
204
- * @param params
205
- */
206
- abstract getDepositCall(params: DepositParams): Promise<ManageCall[]>;
207
-
208
- /**
209
- * Implementor must provide withdraw call
210
- * @param params
211
- */
212
- abstract getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]>;
213
-
214
-
215
- getProofs<T>(isDeposit: boolean, tree: StandardMerkleTree): { proofs: string[][], callConstructor: GenerateCallFn<DepositParams> | GenerateCallFn<WithdrawParams> } {
216
- let proofGroups: string[][] = [];
217
-
218
- const ids = isDeposit ? this.getDepositLeaf().leaves.map(l => l.readableId) : this.getWithdrawLeaf().leaves.map(l => l.readableId);
219
- // console.log(`${this.name}::getProofs ids: ${ids}`);
220
- for (const [i, v] of tree.entries()) {
221
- // console.log(`${this.name}::getProofs v: ${v.readableId}`);
222
- if (ids.includes(v.readableId)) {
223
- // console.log(`${this.name}::getProofs found id: ${v.readableId}`);
224
- proofGroups.push(tree.getProof(i));
225
- }
226
- }
227
- if (proofGroups.length != ids.length) {
228
- throw new Error(`Not all proofs found for IDs: ${ids.join(', ')}`);
229
- }
230
-
231
- // find leaf adapter
232
- return {
233
- proofs: proofGroups,
234
- callConstructor: isDeposit ?
235
- this.getDepositCall.bind(this) :
236
- this.getWithdrawCall.bind(this)
237
- };
238
- }
239
-
240
- async getNetAPY(): Promise<number> {
241
- const positions = await this.getPositions();
242
- logger.verbose(`${this.name}::getNetAPY: positions: ${JSON.stringify(positions)}`);
243
- const netAmount = positions.reduce((acc, curr) => acc + curr.usdValue, 0);
244
- const netAPY = positions.reduce((acc, curr) => acc + curr.apy.apy * curr.usdValue, 0) / netAmount;
245
- logger.verbose(`${this.name}::getNetAPY: netAPY: ${netAPY}`);
246
- return netAPY;
247
- }
248
-
249
- abstract getHealthFactor(): Promise<number>;
250
- }
251
-
1
+ import { Call, hash, num, shortString } from "starknet";
2
+ import { SIMPLE_SANITIZER, toBigInt } from "./adapter-utils";
3
+ import { ContractAddr, Web3Number } from "@/dataTypes";
4
+ import { IConfig, IProtocol, TokenInfo } from "@/interfaces";
5
+ import { PricerBase } from "@/modules/pricerBase";
6
+ import { LeafData, logger, StandardMerkleTree } from "@/utils";
7
+ import { CacheClass } from "@/utils/cacheClass";
8
+
9
+ export interface ManageCall {
10
+ proofReadableId: string,
11
+ sanitizer: ContractAddr,
12
+ call: {
13
+ contractAddress: ContractAddr,
14
+ selector: string,
15
+ calldata: bigint[]
16
+ }
17
+ }
18
+
19
+ export interface SwapPriceInfo {
20
+ source: 'avnu' | 'ekubo';
21
+ fromTokenSymbol: string;
22
+ toTokenSymbol: string;
23
+ fromAmount: number;
24
+ toAmount: number;
25
+ effectivePrice: number;
26
+ }
27
+
28
+
29
+ export interface DepositParams {
30
+ amount: Web3Number;
31
+ }
32
+
33
+ export interface WithdrawParams {
34
+ amount: Web3Number;
35
+ }
36
+
37
+ // export type GenerateCallFn<T> = (params: T) => ManageCall;
38
+ // export type AdapterLeafType<T> = {leaf: LeafData, callConstructor: GenerateCallFn<T>}
39
+ export type GenerateCallFn<T> = (params: T) => Promise<ManageCall[]>;
40
+ export type AdapterLeafType<T> = {leaves: LeafData[], callConstructor: GenerateCallFn<T>}
41
+ export type LeafAdapterFn<T> = () => AdapterLeafType<T>;
42
+
43
+ export enum APYType {
44
+ BASE = "base",
45
+ REWARD = "reward",
46
+ LST = "lst"
47
+ }
48
+
49
+ export interface SupportedPosition {
50
+ asset: TokenInfo,
51
+ isDebt: boolean
52
+ }
53
+
54
+ export interface BaseAdapterConfig {
55
+ baseToken: TokenInfo,
56
+ supportedPositions: SupportedPosition[],
57
+ networkConfig: IConfig,
58
+ pricer: PricerBase,
59
+ vaultAllocator: ContractAddr
60
+ vaultAddress: ContractAddr
61
+ }
62
+
63
+ export type PositionAPY = { apy: number, type: APYType };
64
+ export type PositionInfo = {
65
+ tokenInfo: TokenInfo,
66
+ amount: Web3Number,
67
+ usdValue: number,
68
+ remarks: string,
69
+ apy: PositionAPY,
70
+ protocol: IProtocol
71
+ };
72
+
73
+ export type PositionAmount = {
74
+ amount: Web3Number,
75
+ remarks: string,
76
+ }
77
+
78
+ export abstract class BaseAdapter<DepositParams, WithdrawParams> extends CacheClass {
79
+ readonly name: string;
80
+ readonly config: BaseAdapterConfig;
81
+ readonly protocol: IProtocol;
82
+
83
+ constructor(config: BaseAdapterConfig, name: string, protocol: IProtocol) {
84
+ super();
85
+ this.config = config;
86
+ this.name = name;
87
+ this.protocol = protocol;
88
+ }
89
+
90
+ /**
91
+ * Loop through all supported positions and return amount, usd value, remarks and apy for each
92
+ */
93
+ async getPositions(): Promise<PositionInfo[]> {
94
+ const results: PositionInfo[] = [];
95
+ for (const supported of this.config.supportedPositions) {
96
+ const amount = await this.getPosition(supported);
97
+ if (!amount) {
98
+ continue;
99
+ }
100
+ const usdValue = await this.getUSDValue(supported.asset, amount.amount);
101
+ const apy = await this.getAPY(supported);
102
+ results.push({ tokenInfo: supported.asset, amount: amount.amount, usdValue, apy, protocol: this.protocol, remarks: amount.remarks });
103
+ }
104
+ return results;
105
+ }
106
+
107
+ /**
108
+ * Implemented by child adapters to compute APY for a given supported position
109
+ */
110
+ protected abstract getAPY(supportedPosition: SupportedPosition): Promise<PositionAPY>;
111
+
112
+ /**
113
+ * Implemented by child adapters to fetch amount for a given supported position
114
+ */
115
+ protected abstract getPosition(supportedPosition: SupportedPosition): Promise<PositionAmount | null>;
116
+
117
+ /**
118
+ * Implemented by child adapters to calculate maximum deposit positions
119
+ * @param amount Optional amount in baseToken to deposit
120
+ */
121
+ abstract maxDeposit(amount?: Web3Number): Promise<PositionInfo>;
122
+
123
+ /**
124
+ * Implemented by child adapters to calculate maximum withdraw positions
125
+ */
126
+ abstract maxWithdraw(): Promise<PositionInfo>;
127
+
128
+ /**
129
+ * Uses pricer to convert an amount of an asset to USD value
130
+ */
131
+ protected async getUSDValue(asset: TokenInfo, amount: Web3Number): Promise<number> {
132
+ const priceInfo = await this.config.pricer.getPrice(asset.priceProxySymbol || asset.symbol);
133
+ return amount.toNumber() * priceInfo.price;
134
+ }
135
+
136
+
137
+ protected constructSimpleLeafData(params: {
138
+ id: string,
139
+ target: ContractAddr,
140
+ method: string,
141
+ packedArguments: bigint[],
142
+ }, sanitizer: ContractAddr = SIMPLE_SANITIZER): LeafData {
143
+ const { id, target, method, packedArguments } = params;
144
+ return {
145
+ id: BigInt(num.getDecimalString(shortString.encodeShortString(id))),
146
+ readableId: id,
147
+ data: [
148
+ sanitizer.toBigInt(), // sanitizer address
149
+ target.toBigInt(), // contract
150
+ toBigInt(hash.getSelectorFromName(method)), // method name
151
+ BigInt(packedArguments.length),
152
+ ...packedArguments
153
+ ]
154
+ };
155
+ }
156
+
157
+ /**
158
+ * Implementor must provide target/method/packedArguments/sanitizer for deposit leaf construction
159
+ */
160
+ protected abstract _getDepositLeaf(): {
161
+ target: ContractAddr,
162
+ method: string,
163
+ packedArguments: bigint[],
164
+ sanitizer: ContractAddr,
165
+ id: string
166
+ }[];
167
+
168
+ /**
169
+ * Implementor must provide target/method/packedArguments/sanitizer for withdraw leaf construction
170
+ */
171
+ protected abstract _getWithdrawLeaf(): {
172
+ target: ContractAddr,
173
+ method: string,
174
+ packedArguments: bigint[],
175
+ sanitizer: ContractAddr,
176
+ id: string
177
+ }[];
178
+
179
+ /**
180
+ * Returns deposit leaf adapter using configured proof id
181
+ */
182
+ getDepositLeaf(): AdapterLeafType<DepositParams> {
183
+ const leafConfigs = this._getDepositLeaf();
184
+ const leaves = leafConfigs.map(config => {
185
+ const { target, method, packedArguments, sanitizer, id } = config;
186
+ const leaf = this.constructSimpleLeafData({
187
+ id: id,
188
+ target,
189
+ method,
190
+ packedArguments
191
+ }, sanitizer);
192
+ return leaf;
193
+ });
194
+ return { leaves, callConstructor: this.getDepositCall.bind(this) as unknown as GenerateCallFn<DepositParams> };
195
+ }
196
+
197
+ /**
198
+ * Returns withdraw leaf adapter using configured proof id
199
+ */
200
+ getWithdrawLeaf(): AdapterLeafType<WithdrawParams> {
201
+ const leafConfigs = this._getWithdrawLeaf();
202
+ const leaves = leafConfigs.map(config => {
203
+ const { target, method, packedArguments, sanitizer, id } = config;
204
+ const leaf = this.constructSimpleLeafData({
205
+ id: id,
206
+ target,
207
+ method,
208
+ packedArguments
209
+ }, sanitizer ?? SIMPLE_SANITIZER);
210
+ return leaf;
211
+ });
212
+ return { leaves, callConstructor: this.getWithdrawCall.bind(this) as unknown as GenerateCallFn<WithdrawParams> };
213
+ }
214
+
215
+ /**
216
+ * Implementor must provide deposit call
217
+ * @param params
218
+ */
219
+ abstract getDepositCall(params: DepositParams): Promise<ManageCall[]>;
220
+
221
+ /**
222
+ * Implementor must provide withdraw call
223
+ * @param params
224
+ */
225
+ abstract getWithdrawCall(params: WithdrawParams): Promise<ManageCall[]>;
226
+
227
+
228
+ getProofs<T>(isDeposit: boolean, tree: StandardMerkleTree): { proofs: string[][], callConstructor: GenerateCallFn<DepositParams> | GenerateCallFn<WithdrawParams> } {
229
+ let proofGroups: string[][] = [];
230
+
231
+ const ids = isDeposit ? this.getDepositLeaf().leaves.map(l => l.readableId) : this.getWithdrawLeaf().leaves.map(l => l.readableId);
232
+ // console.log(`${this.name}::getProofs ids: ${ids}`);
233
+ for (const [i, v] of tree.entries()) {
234
+ // console.log(`${this.name}::getProofs v: ${v.readableId}`);
235
+ if (ids.includes(v.readableId)) {
236
+ // console.log(`${this.name}::getProofs found id: ${v.readableId}`);
237
+ proofGroups.push(tree.getProof(i));
238
+ }
239
+ }
240
+ if (proofGroups.length != ids.length) {
241
+ throw new Error(`Not all proofs found for IDs: ${ids.join(', ')}`);
242
+ }
243
+
244
+ // find leaf adapter
245
+ return {
246
+ proofs: proofGroups,
247
+ callConstructor: isDeposit ?
248
+ this.getDepositCall.bind(this) :
249
+ this.getWithdrawCall.bind(this)
250
+ };
251
+ }
252
+
253
+ async getNetAPY(): Promise<number> {
254
+ const positions = (await this.getPositions()).filter(position => position !== null);
255
+ logger.verbose(`${this.name}::getNetAPY: positions: ${JSON.stringify(positions)}`);
256
+ const netAmount = positions.reduce((acc, curr) => acc + curr.usdValue, 0);
257
+ const netAPY = positions.reduce((acc, curr) => acc + curr.apy.apy * curr.usdValue, 0) / netAmount;
258
+ logger.verbose(`${this.name}::getNetAPY: netAPY: ${netAPY}`);
259
+ return netAPY;
260
+ }
261
+
262
+ abstract getHealthFactor(): Promise<number>;
263
+ }