@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,202 +0,0 @@
1
- import { ContractAddr, Web3Number } from '../dataTypes';
2
- import { TokenInfo, IConfig } from '../interfaces';
3
- import { PricerBase } from './pricerBase';
4
- import { LSTAPRService } from './lst-apr';
5
- import { Midas } from './midas';
6
- import { SingleTokenInfo } from '../strategies/base-strategy';
7
- import { logger } from '../utils/logger';
8
- import { Contract } from 'starknet';
9
- import { uint256 } from 'starknet';
10
- import ERC4626Abi from '../data/erc4626.abi.json';
11
-
12
- /**
13
- * TokenMarketData class that combines LST APR and Midas modules
14
- * to provide unified APY, price, and TVL functions for tokens
15
- */
16
- export class TokenMarketData {
17
- private pricer: PricerBase;
18
- private config: IConfig;
19
-
20
- constructor(pricer: PricerBase, config: IConfig) {
21
- this.pricer = pricer;
22
- this.config = config;
23
- }
24
-
25
- /**
26
- * Get APY for a token
27
- * - If it's an LST token, returns LST APY
28
- * - If it's a Midas token, returns Midas APY
29
- * - Otherwise returns 0
30
- * @param tokenInfo The token to get APY for
31
- * @returns APY in absolute terms (not percentage)
32
- */
33
- async getAPY(tokenInfo: TokenInfo): Promise<number> {
34
- try {
35
- // Check if it's an LST token
36
- if (LSTAPRService.isLST(tokenInfo.address)) {
37
- const underlying = LSTAPRService.getUnderlyingFromLST(tokenInfo.address);
38
- const lstApr = await LSTAPRService.getLSTAPR(underlying.address);
39
- logger.verbose(`TokenMarketData: LST APY for ${tokenInfo.symbol}: ${lstApr}`);
40
- return lstApr;
41
- }
42
-
43
- // Check if it's a Midas token by trying to get symbol
44
- if (Midas.isSupported(tokenInfo.address)) {
45
- const midasApy = await Midas.getAPY(tokenInfo.address);
46
- logger.verbose(`TokenMarketData: Midas APY for ${tokenInfo.symbol}: ${midasApy}`);
47
- return midasApy;
48
- }
49
-
50
- // Default to 0 for unsupported tokens
51
- logger.verbose(`TokenMarketData: No APY data available for ${tokenInfo.symbol}, returning 0`);
52
- return 0;
53
- } catch (error) {
54
- logger.error(`TokenMarketData: Error getting APY for ${tokenInfo.symbol}:`, error);
55
- return 0;
56
- }
57
- }
58
-
59
- /**
60
- * Get price for a token using the pricer module
61
- * @param tokenInfo The token to get price for
62
- * @returns Price as a number
63
- * @throws Error if price is 0 or unavailable
64
- */
65
- async getPrice(tokenInfo: TokenInfo): Promise<number> {
66
- try {
67
- const priceInfo = await this.pricer.getPrice(tokenInfo.symbol);
68
-
69
- if (priceInfo.price === 0) {
70
- throw new Error(`Price is 0 for token ${tokenInfo.symbol}`);
71
- }
72
-
73
- logger.verbose(`TokenMarketData: Price for ${tokenInfo.symbol}: ${priceInfo.price}`);
74
- return priceInfo.price;
75
- } catch (error) {
76
- logger.error(`TokenMarketData: Error getting price for ${tokenInfo.symbol}:`, error);
77
- throw new Error(`Failed to get price for ${tokenInfo.symbol}: ${error instanceof Error ? error.message : 'Unknown error'}`);
78
- }
79
- }
80
-
81
- /**
82
- * Get true price for a token
83
- * - For LST tokens: Uses convert_to_assets to get true exchange rate
84
- * - For Midas tokens: Uses Midas price API
85
- * - For other tokens: Falls back to regular pricer
86
- * @param tokenInfo The token to get true price for
87
- * @returns True price as a number
88
- * @throws Error if price is 0 or unavailable
89
- */
90
- async getTruePrice(tokenInfo: TokenInfo): Promise<number> {
91
- try {
92
- // For LST tokens, use convert_to_assets
93
- if (LSTAPRService.isLST(tokenInfo.address)) {
94
- const lstABI = new Contract({
95
- abi: ERC4626Abi,
96
- address: tokenInfo.address.address,
97
- providerOrAccount: this.config.provider
98
- });
99
-
100
- const price: any = await lstABI.call('convert_to_assets', [
101
- uint256.bnToUint256((new Web3Number(1, tokenInfo.decimals)).toWei())
102
- ]);
103
- const exchangeRate = Number(uint256.uint256ToBN(price).toString()) / Math.pow(10, tokenInfo.decimals);
104
-
105
- if (exchangeRate === 0) {
106
- throw new Error(`True price is 0 for LST token ${tokenInfo.symbol}`);
107
- }
108
-
109
- logger.verbose(`TokenMarketData: LST true price for ${tokenInfo.symbol}: ${exchangeRate}`);
110
- return exchangeRate;
111
- }
112
-
113
- // For Midas tokens, use Midas price API
114
- if (Midas.isSupported(tokenInfo.address)) {
115
- const midasPrice = await Midas.getPrice(tokenInfo.address);
116
-
117
- if (midasPrice === 0) {
118
- throw new Error(`True price is 0 for Midas token ${tokenInfo.symbol}`);
119
- }
120
-
121
- logger.verbose(`TokenMarketData: Midas true price for ${tokenInfo.symbol}: ${midasPrice}`);
122
- return midasPrice;
123
- }
124
-
125
- // For other tokens, fall back to regular pricer
126
- const price = await this.getPrice(tokenInfo);
127
-
128
- if (price === 0) {
129
- throw new Error(`True price is 0 for token ${tokenInfo.symbol}`);
130
- }
131
-
132
- logger.verbose(`TokenMarketData: Regular price for ${tokenInfo.symbol}: ${price}`);
133
- return price;
134
- } catch (error) {
135
- logger.error(`TokenMarketData: Error getting true price for ${tokenInfo.symbol}:`, error);
136
- throw new Error(`Failed to get true price for ${tokenInfo.symbol}: ${error instanceof Error ? error.message : 'Unknown error'}`);
137
- }
138
- }
139
-
140
- /**
141
- * Get TVL for a token
142
- * - If it's a Midas token, returns Midas TVL data
143
- * - Otherwise returns 0
144
- * @param tokenInfo The token to get TVL for
145
- * @returns TVL as SingleTokenInfo or 0
146
- */
147
- async getTVL(tokenInfo: TokenInfo): Promise<SingleTokenInfo> {
148
- // Check if it's a Midas token by trying to get TVL
149
- if (Midas.isSupported(tokenInfo.address)) {
150
- const midasTvl = await Midas.getTVL(tokenInfo.address);
151
-
152
- // Handle different TVL response formats
153
- let usdValue: number;
154
- let nativeAmount: number;
155
-
156
- if (typeof midasTvl === 'number') {
157
- // Simple number format (e.g., mre7: 18193466)
158
- usdValue = midasTvl;
159
- nativeAmount = 0; // We don't have native amount in this format
160
- } else if (typeof midasTvl === 'object' && 'usd' in midasTvl && 'native' in midasTvl) {
161
- // Object format with usd and native (e.g., mre7btc: {usd: 998826, native: 9.3228})
162
- usdValue = midasTvl.usd;
163
- nativeAmount = midasTvl.native;
164
- } else {
165
- throw new Error(`Unexpected TVL format for ${tokenInfo.symbol}`);
166
- }
167
-
168
- const tvlInfo: SingleTokenInfo = {
169
- tokenInfo,
170
- amount: Web3Number.fromWei(nativeAmount, tokenInfo.decimals),
171
- usdValue
172
- };
173
-
174
- logger.verbose(`TokenMarketData: Midas TVL for ${tokenInfo.symbol}: USD=${usdValue}, Native=${nativeAmount}`);
175
- return tvlInfo;
176
- }
177
-
178
- return {
179
- tokenInfo,
180
- amount: Web3Number.fromWei('0', tokenInfo.decimals),
181
- usdValue: 0
182
- }
183
- }
184
-
185
- /**
186
- * Check if a token is supported for APY data
187
- * @param tokenInfo The token to check
188
- * @returns True if the token has APY data available
189
- */
190
- isAPYSupported(tokenInfo: TokenInfo): boolean {
191
- return LSTAPRService.isLST(tokenInfo.address) || Midas.isSupported(tokenInfo.address);
192
- }
193
-
194
- /**
195
- * Check if a token is supported for TVL data
196
- * @param tokenInfo The token to check
197
- * @returns True if the token has TVL data available
198
- */
199
- isTVLSupported(tokenInfo: TokenInfo): boolean {
200
- return Midas.isSupported(tokenInfo.address);
201
- }
202
- }
@@ -1,247 +0,0 @@
1
- import { ContractAddr, Web3Number } from "@/dataTypes";
2
- import { IConfig, IStrategyMetadata, TokenInfo, VaultPosition } from "@/interfaces";
3
- import { PricerBase } from "@/modules/pricerBase";
4
- import { ERC20 } from "@/modules";
5
- import { BaseStrategy, SingleActionAmount, SingleTokenInfo } from "./base-strategy";
6
- import { Call, Contract, num } from "starknet";
7
- import { assert, LeafData, logger, StandardMerkleTree } from "@/utils";
8
- import { UniversalStrategySettings } from "./universal-strategy";
9
- import { UNIVERSAL_MANAGE_IDS } from "./universal-strategy";
10
- import UniversalVaultAbi from '../data/universal-vault.abi.json';
11
- import ManagerAbi from '../data/vault-manager.abi.json';
12
- import { ManageCall, PositionInfo } from "./universal-adapters";
13
-
14
- /**
15
- * Base class for all SVK (Starknet Vault Kit) strategies.
16
- * Contains common functions that are shared across all SVK strategies.
17
- */
18
- export abstract class SVKStrategy<S extends UniversalStrategySettings>
19
- extends BaseStrategy<SingleTokenInfo, SingleActionAmount> {
20
-
21
- /** Contract address of the strategy */
22
- readonly address: ContractAddr;
23
- /** Pricer instance for token price calculations */
24
- readonly pricer: PricerBase;
25
- /** Metadata containing strategy information */
26
- readonly metadata: IStrategyMetadata<S>;
27
- /** Contract instance for interacting with the strategy */
28
- readonly contract: Contract;
29
- /** Manager contract instance for merkle verification */
30
- readonly managerContract: Contract;
31
- /** Cached merkle tree instance */
32
- merkleTree: StandardMerkleTree | undefined;
33
-
34
- constructor(config: IConfig, pricer: PricerBase, metadata: IStrategyMetadata<S>) {
35
- super(config);
36
- this.pricer = pricer;
37
- this.metadata = metadata;
38
- this.address = metadata.address;
39
-
40
- this.contract = new Contract({
41
- abi: UniversalVaultAbi,
42
- address: this.address.address,
43
- providerOrAccount: this.config.provider
44
- });
45
-
46
- this.managerContract = new Contract({
47
- abi: ManagerAbi,
48
- address: this.metadata.additionalInfo.manager.address,
49
- providerOrAccount: this.config.provider
50
- });
51
- }
52
-
53
- /**
54
- * Returns the asset token for this strategy
55
- */
56
- asset(): TokenInfo {
57
- return this.metadata.depositTokens[0];
58
- }
59
-
60
- /**
61
- * Returns the unused balance in the vault allocator.
62
- * Note: This function is common for any SVK strategy.
63
- */
64
- async getUnusedBalance(): Promise<SingleTokenInfo> {
65
- const balance = await (new ERC20(this.config)).balanceOf(
66
- this.asset().address,
67
- this.metadata.additionalInfo.vaultAllocator,
68
- this.asset().decimals
69
- );
70
- const price = await this.pricer.getPrice(this.metadata.depositTokens[0].symbol);
71
- const usdValue = Number(balance.toFixed(6)) * price.price;
72
- return {
73
- tokenInfo: this.asset(),
74
- amount: balance,
75
- usdValue
76
- };
77
- }
78
-
79
- /**
80
- * Bridges liquidity from the vault allocator back to the vault.
81
- * Note: This function is common for any SVK strategy.
82
- */
83
- async getBringLiquidityCall(params: { amount: Web3Number }): Promise<Call> {
84
- // Find approve leaf adapter
85
- const approveAdapter = this.metadata.additionalInfo.leafAdapters.find(
86
- adapter => adapter().leaves.find(leaf => leaf.readableId === UNIVERSAL_MANAGE_IDS.APPROVE_BRING_LIQUIDITY)
87
- );
88
-
89
- if (!approveAdapter) {
90
- throw new Error(`${this.getTag()}::getBringLiquidityCall: approve adapter not found`);
91
- }
92
-
93
- // Find bring liquidity leaf adapter
94
- const bringLiquidityAdapter = this.metadata.additionalInfo.leafAdapters.find(
95
- adapter => adapter().leaves.find(leaf => leaf.readableId === UNIVERSAL_MANAGE_IDS.BRING_LIQUIDITY)
96
- );
97
-
98
- if (!bringLiquidityAdapter) {
99
- throw new Error(`${this.getTag()}::getBringLiquidityCall: bring liquidity adapter not found`);
100
- }
101
-
102
- // Get proofs
103
- const tree = this.getMerkleTree();
104
- const proofGroups: string[][] = [];
105
- for (const [i, v] of tree.entries()) {
106
- if (v.readableId === UNIVERSAL_MANAGE_IDS.APPROVE_BRING_LIQUIDITY ||
107
- v.readableId === UNIVERSAL_MANAGE_IDS.BRING_LIQUIDITY) {
108
- proofGroups.push(tree.getProof(i));
109
- }
110
- }
111
-
112
- // Construct calls
113
- logger.verbose("approve adapter amount", params.amount);
114
- const approveCalls = await approveAdapter().callConstructor({ amount: params.amount });
115
- const bringLiquidityCalls = await bringLiquidityAdapter().callConstructor({ amount: params.amount });
116
-
117
- // Combine into final call
118
- return this.getManageCall(proofGroups, [...approveCalls, ...bringLiquidityCalls]);
119
- }
120
-
121
- /**
122
- * Gets all leaves from all leaf adapters.
123
- * Note: This function is common for any SVK strategy.
124
- */
125
- getAllLeaves(): LeafData[] {
126
- const leaves = this.metadata.additionalInfo.leafAdapters.map(adapter => adapter());
127
- const _leaves: LeafData[] = [];
128
- leaves.forEach((_l) => {
129
- _leaves.push(..._l.leaves);
130
- });
131
- return _leaves;
132
- }
133
-
134
- /**
135
- * Builds and caches the merkle tree from all leaf adapters.
136
- * Note: This function is common for any SVK strategy.
137
- */
138
- getMerkleTree(): StandardMerkleTree {
139
- if (this.merkleTree) return this.merkleTree;
140
- const _leaves = this.getAllLeaves();
141
- const standardTree = StandardMerkleTree.of(_leaves);
142
- this.merkleTree = standardTree;
143
- return standardTree;
144
- }
145
-
146
- /**
147
- * Gets the merkle root of the tree.
148
- * Note: This function is common for any SVK strategy.
149
- */
150
- getMerkleRoot(): string {
151
- return this.getMerkleTree().root;
152
- }
153
-
154
- /**
155
- * Combines proofs and manage calls into a single Starknet call.
156
- * Note: This function is common for any SVK strategy.
157
- */
158
- getManageCall(proofGroups: string[][], manageCalls: ManageCall[]): Call {
159
- assert(
160
- proofGroups.length == manageCalls.length,
161
- `Proof IDs and Manage Calls length mismatch: ${proofGroups.length} != ${manageCalls.length}`
162
- );
163
-
164
- return this.managerContract.populate('manage_vault_with_merkle_verification', {
165
- proofs: proofGroups.map(group => group),
166
- decoder_and_sanitizers: manageCalls.map(call => call.sanitizer.address),
167
- targets: manageCalls.map(call => call.call.contractAddress.address),
168
- selectors: manageCalls.map(call => call.call.selector),
169
- calldatas: manageCalls.map(call => call.call.calldata),
170
- });
171
- }
172
-
173
- /**
174
- * Creates a call to set the merkle root on the manager contract.
175
- * Note: This function is common for any SVK strategy.
176
- */
177
- getSetManagerCall(strategist: ContractAddr, root = this.getMerkleRoot()): Call {
178
- return this.managerContract.populate('set_manage_root', [
179
- strategist.address,
180
- num.getHexString(root)
181
- ]);
182
- }
183
-
184
- /**
185
- * Returns a tag for logging purposes.
186
- * Should be overridden by subclasses to provide strategy-specific tags.
187
- */
188
- abstract getTag(): string;
189
-
190
-
191
- /**
192
- * Returns the positions in the vault.
193
- * @returns An array of VaultPosition objects representing the positions in the vault.
194
- */
195
- async getVaultPositions(): Promise<VaultPosition[]> {
196
- const positions = await Promise.all(
197
- this.metadata.additionalInfo.adapters.map(adapter => adapter.adapter.getPositions())
198
- )
199
- return positions.flat().map((position) => ({
200
- amount: position.amount,
201
- usdValue: position.usdValue,
202
- remarks: position.remarks ?? '',
203
- token: position.tokenInfo,
204
- protocol: position.protocol
205
- }))
206
- }
207
-
208
- async getHealthFactors(): Promise<number[]> {
209
- return Promise.all(this.metadata.additionalInfo.adapters.map(adapter => adapter.adapter.getHealthFactor()));
210
- }
211
-
212
- // todo undo this
213
- async netAPY(): Promise<{ net: number; splits: { apy: number; id: string; }[]; }> {
214
- const allPositions: PositionInfo[] = [];
215
- for (let adapter of this.metadata.additionalInfo.adapters) {
216
- const positions = await adapter.adapter.getPositions();
217
- allPositions.push(...positions);
218
- }
219
-
220
- const totalHoldingsUSDValue = allPositions.reduce((acc, curr) => acc + curr.usdValue, 0);
221
- let weightedAPYs = allPositions.reduce((acc, curr) => acc + curr.apy.apy * curr.usdValue, 0);
222
- const netAPY = weightedAPYs / totalHoldingsUSDValue;
223
- return {
224
- net: netAPY,
225
- splits: allPositions.map(p => ({apy: p.apy.apy, id: p.remarks ?? ''}))
226
- };
227
- }
228
-
229
- async getPrevAUM() {
230
- const currentAUM: bigint = await this.contract.call('aum', []) as bigint;
231
- const prevAum = Web3Number.fromWei(currentAUM.toString(), this.asset().decimals);
232
- logger.verbose(`${this.getTag()} Prev AUM: ${prevAum}`);
233
- return prevAum;
234
- }
235
-
236
- async maxDepositables() {
237
- const maxDepositables = await Promise.all(this.metadata.additionalInfo.adapters.map(adapter => adapter.adapter.maxDeposit()));
238
- return maxDepositables;
239
- }
240
-
241
- async maxWithdrawables() {
242
- const maxWithdrawables = await Promise.all(this.metadata.additionalInfo.adapters.map(adapter => adapter.adapter.maxWithdraw()));
243
- return maxWithdrawables;
244
- }
245
-
246
- }
247
-
@@ -1,65 +0,0 @@
1
- import { logger } from "@/utils";
2
- import { BaseAdapter, DepositParams, WithdrawParams } from "./baseAdapter";
3
- import { Web3Number } from "@/dataTypes";
4
-
5
- export class AdapterOptimizer {
6
-
7
- // write a export function to compute the adapter to use
8
- // for a given withdraw/deposit action. It can be one or more adapters.
9
- // Key decision factors:
10
- // 1. The netAPY of the adapter is low compared to others (exhaust this first before using others)
11
- // 2. Prefer one adapter over multiple adapters
12
- static async getAdapterToUse(adapters: BaseAdapter<DepositParams, WithdrawParams>[], isDeposit: boolean, amount: Web3Number): Promise<BaseAdapter<DepositParams, WithdrawParams>[]> {
13
- logger.verbose(`${this.name}::getAdapterToUse: adapters: ${JSON.stringify(adapters)}, isDeposit: ${isDeposit}, amount: ${amount.toFixed(9)}`);
14
- const netAPYs = await Promise.all(adapters.map(a => a.getNetAPY()));
15
- const indexAndNetAPYsArr = netAPYs.map((apy, index) => [index, apy]);
16
- logger.verbose(`${this.name}::getAdapterToUse: netAPYs: ${JSON.stringify(netAPYs)}`);
17
- // if is deposit
18
- if (isDeposit) {
19
- // sort apys by descending
20
- const sortedNetAPYs = indexAndNetAPYsArr.sort((a, b) => (b[1] || 0) - (a[1] || 0));
21
- logger.verbose(`${this.name}::getAdapterToUse: sortedNetAPYs: ${JSON.stringify(sortedNetAPYs)}`);
22
-
23
- // get max depositables
24
- const adaptersToUse: BaseAdapter<DepositParams, WithdrawParams>[] = [];
25
- let remainingAmount = amount;
26
- for (const [index, _] of sortedNetAPYs) {
27
- const adapter = adapters[index];
28
- const maxDepositable = await adapter.maxDeposit(amount);
29
- if (maxDepositable.amount.gt(0)) {
30
- adaptersToUse.push(adapter);
31
- remainingAmount = remainingAmount.minus(maxDepositable.amount).minimum(0);
32
- }
33
-
34
- if (remainingAmount.lte(0)) {
35
- break;
36
- }
37
- }
38
-
39
- return adaptersToUse;
40
- } else {
41
- // sort apys by ascending
42
- const sortedNetAPYs = indexAndNetAPYsArr.sort((a, b) => (a[1] || 0) - (b[1] || 0));
43
- logger.verbose(`${this.name}::getAdapterToUse: sortedNetAPYs: ${JSON.stringify(sortedNetAPYs)}`);
44
-
45
- // get max withdrawables
46
- const adaptersToUse: BaseAdapter<DepositParams, WithdrawParams>[] = [];
47
- let remainingAmount = amount.abs();
48
- for (const [index, _] of sortedNetAPYs) {
49
- const adapter = adapters[index];
50
- const maxWithdrawable = await adapter.maxWithdraw();
51
- logger.verbose(`${this.name}::getAdapterToUse: maxWithdrawable: ${JSON.stringify(maxWithdrawable)}, adapter: ${adapter.name}, remainingAmount: ${remainingAmount}`);
52
- if (maxWithdrawable.amount.gt(0)) {
53
- adaptersToUse.push(adapter);
54
- remainingAmount = remainingAmount.minus(maxWithdrawable.amount).minimum(0);
55
- }
56
-
57
- if (remainingAmount.lte(0)) {
58
- break;
59
- }
60
- }
61
-
62
- return adaptersToUse;
63
- }
64
- }
65
- }