@gearbox-protocol/sdk 0.0.55 → 0.0.56

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 (42) hide show
  1. package/lib/core/pathfinder.d.ts +35 -5
  2. package/lib/core/pathfinder.js +547 -67
  3. package/lib/core/token.d.ts +5 -0
  4. package/lib/core/token.js +8 -1
  5. package/lib/core/tradeTypes.d.ts +2 -0
  6. package/lib/pathfinder/connectorPathAsset.d.ts +7 -0
  7. package/lib/pathfinder/connectorPathAsset.js +144 -0
  8. package/lib/pathfinder/convexLPTokenPathAsset.d.ts +5 -0
  9. package/lib/pathfinder/convexLPTokenPathAsset.js +77 -0
  10. package/lib/pathfinder/curveLPPathAsset.d.ts +5 -0
  11. package/lib/pathfinder/curveLPPathAsset.js +72 -0
  12. package/lib/pathfinder/metaCurveLPPathAsset.d.ts +5 -0
  13. package/lib/pathfinder/metaCurveLPPathAsset.js +72 -0
  14. package/lib/pathfinder/normalTokenPathAsset.d.ts +5 -0
  15. package/lib/pathfinder/normalTokenPathAsset.js +136 -0
  16. package/lib/pathfinder/path.d.ts +41 -0
  17. package/lib/pathfinder/path.js +302 -0
  18. package/lib/pathfinder/pathfinder.d.ts +28 -0
  19. package/lib/pathfinder/pathfinder.js +519 -0
  20. package/lib/pathfinder/yearnVaultOfCurveLPPathAsset.d.ts +5 -0
  21. package/lib/pathfinder/yearnVaultOfCurveLPPathAsset.js +87 -0
  22. package/lib/pathfinder/yearnVaultOfMetaCurveLPPathAsset.d.ts +5 -0
  23. package/lib/pathfinder/yearnVaultOfMetaCurveLPPathAsset.js +87 -0
  24. package/lib/pathfinder/yearnVaultPathAsset.d.ts +5 -0
  25. package/lib/pathfinder/yearnVaultPathAsset.js +87 -0
  26. package/lib/utils/types.d.ts +3 -0
  27. package/lib/utils/types.js +2 -0
  28. package/package.json +1 -1
  29. package/src/core/contracts.ts +11 -1
  30. package/src/core/token.ts +12 -0
  31. package/src/core/tradeTypes.ts +2 -0
  32. package/src/pathfinder/connectorPathAsset.ts +69 -0
  33. package/src/pathfinder/convexLPTokenPathAsset.ts +33 -0
  34. package/src/pathfinder/curveLPPathAsset.ts +10 -0
  35. package/src/pathfinder/metaCurveLPPathAsset.ts +12 -0
  36. package/src/pathfinder/normalTokenPathAsset.ts +68 -0
  37. package/src/pathfinder/path.ts +259 -0
  38. package/src/pathfinder/yearnVaultOfCurveLPPathAsset.ts +22 -0
  39. package/src/pathfinder/yearnVaultOfMetaCurveLPPathAsset.ts +22 -0
  40. package/src/pathfinder/yearnVaultPathAsset.ts +27 -0
  41. package/src/utils/types.ts +3 -0
  42. package/src/core/pathfinder.ts +0 -115
@@ -0,0 +1,259 @@
1
+ import {BigNumber, ethers} from "ethers";
2
+ import {CreditManagerData} from "../core/creditManager";
3
+ import {MultiCall} from "../core/multicall";
4
+ import {
5
+ Curve3CrvUnderlyingTokenIndex, NormalToken,
6
+ priority,
7
+ SupportedToken,
8
+ supportedTokens,
9
+ TokenType
10
+ } from "../core/token";
11
+ import {NetworkType} from "../core/constants";
12
+ import {CreditAccountData} from "../core/creditAccount";
13
+ import {ConnectorPathAsset} from "./connectorPathAsset";
14
+ import {YearnVaultPathAsset} from "./yearnVaultPathAsset";
15
+ import {ConvexLPTokenPathAsset} from "./convexLPTokenPathAsset";
16
+ import {CurveLPPathAsset} from "./curveLPPathAsset";
17
+ import {MetaCurveLPPathAsset} from "./metaCurveLPPathAsset";
18
+ import {NormalTokenPathAsset} from "./normalTokenPathAsset";
19
+ import {YearnVaultOfCurveLPPathAsset} from "./yearnVaultOfCurveLPPathAsset";
20
+ import {YearnVaultOfMetaCurveLPPathAsset} from "./yearnVaultOfMetaCurveLPPathAsset";
21
+ import {
22
+ CurveV1Adapter__factory,
23
+ IQuoter__factory,
24
+ UniswapV2Adapter__factory,
25
+ UniswapV3Adapter__factory, YearnAdapter__factory
26
+ } from "../types";
27
+ import {contractsByNetwork, SupportedContract, UNISWAP_V3_QUOTER} from "../core/contracts";
28
+ import {TradeAction, TradeType} from "../core/tradeTypes";
29
+
30
+
31
+ export class Path {
32
+ public readonly calls: Array<MultiCall> = [];
33
+ public readonly balances: Record<SupportedToken, BigNumber>;
34
+ public readonly pool: SupportedToken;
35
+ public readonly creditManager: CreditManagerData;
36
+ public readonly creditAccount: CreditAccountData;
37
+ public readonly networkType: NetworkType;
38
+ public readonly provider: ethers.providers.Provider;
39
+ public readonly totalGasLimit: BigNumber;
40
+
41
+
42
+ // Path is for selling all assets in the credit account, it will return the calls data to sell all the assets, the amount of pool token will got after selling and the total gas limit for all the calls.
43
+ // This is an example to describe how to use Path:
44
+ // const path = new Path({gasUsed:0, balances: creditAccount.balances, })
45
+ // const closurePath = await path.getBestPath();
46
+ // closurePath.calls -> multicalls (!)
47
+ // closurePath.balances[path.pool] = (X)
48
+ // closurePath.balances[!path.pool] = 0 / 1;
49
+ //
50
+ // balances: the balance of each asset in the credit account
51
+ // pool: the pool token
52
+ // creditManager: credit manager data
53
+ // creditAccount: credit account data
54
+ // networkType: network type (Mainnet, Kovan)
55
+ // provider: ehters rpc provider
56
+ // totalGasLimit: the base gas limit, you can pass zero for not adding any base gas limit
57
+
58
+ constructor(opts: {
59
+ balances: Record<SupportedToken, BigNumber>;
60
+ pool: SupportedToken;
61
+ creditManager: CreditManagerData;
62
+ creditAccount: CreditAccountData;
63
+ networkType: NetworkType;
64
+ provider: ethers.providers.Provider;
65
+ totalGasLimit: BigNumber;
66
+ }) {
67
+ this.balances = opts.balances;
68
+ this.pool = opts.pool;
69
+ this.creditManager = opts.creditManager;
70
+ this.creditAccount = opts.creditAccount;
71
+ this.networkType = opts.networkType;
72
+ this.provider = opts.provider;
73
+ this.totalGasLimit = opts.totalGasLimit;
74
+ }
75
+
76
+ private comparedByPriority([tokenA, _balanceA]: [string, BigNumber], [tokenB, _balanceB]: [string, BigNumber]): number {
77
+ const priorityTokenA = priority[supportedTokens[tokenA as SupportedToken].type];
78
+ const priorityTokenB = priority[supportedTokens[tokenB as SupportedToken].type];
79
+
80
+ if (priorityTokenA > priorityTokenB) {
81
+ return -1;
82
+ } else if (priorityTokenA < priorityTokenB) {
83
+ return 1;
84
+ }
85
+ return 0;
86
+ }
87
+
88
+ async getBestPath(): Promise<Path> {
89
+ const existingTokens = Object.entries(this.balances).filter(([_token, balance]) => balance.gt(1)).sort(this.comparedByPriority);
90
+
91
+ if (existingTokens.length == 1) {
92
+ return this;
93
+ }
94
+
95
+ const nextToken = existingTokens.at(0)![0] as SupportedToken;
96
+ let pathAsset: PathAsset;
97
+ // Get balances and keep non-zero only
98
+ // Find token with highest priority
99
+ // Get token type of this token
100
+ switch (supportedTokens[nextToken].type) {
101
+ case TokenType.CONNECTOR:
102
+ pathAsset = new ConnectorPathAsset();
103
+ break;
104
+
105
+ case TokenType.YEARN_VAULT:
106
+ pathAsset = new YearnVaultPathAsset();
107
+ break;
108
+
109
+ case TokenType.CONVEX_LP_TOKEN:
110
+ pathAsset = new ConvexLPTokenPathAsset();
111
+ break;
112
+
113
+ case TokenType.CURVE_LP:
114
+ pathAsset = new CurveLPPathAsset();
115
+ break;
116
+
117
+ case TokenType.META_CURVE_LP:
118
+ pathAsset = new MetaCurveLPPathAsset();
119
+ break;
120
+
121
+ case TokenType.NORMAL_TOKEN:
122
+ pathAsset = new NormalTokenPathAsset();
123
+ break;
124
+
125
+ case TokenType.YEARN_VAULT_OF_CURVE_LP:
126
+ pathAsset = new YearnVaultOfCurveLPPathAsset();
127
+ break;
128
+
129
+ case TokenType.YEARN_VAULT_OF_META_CURVE_LP:
130
+ pathAsset = new YearnVaultOfMetaCurveLPPathAsset();
131
+ break;
132
+
133
+ default:
134
+ throw new Error("Token type not supported yet");
135
+ }
136
+
137
+ return await pathAsset.getBestPath(nextToken, this);
138
+ }
139
+ }
140
+
141
+ export interface ActionData {
142
+ callData: MultiCall;
143
+ amountOut: BigNumber;
144
+ gasLimit: BigNumber;
145
+ };
146
+
147
+ export abstract class PathAsset {
148
+ abstract getBestPath(currentToken: SupportedToken, p: Path): Promise<Path>;
149
+
150
+
151
+ async getUniswapV2SwapData(adapterAddress: string, currentTokenAddress: string, currentBalance: BigNumber, nextTokenAddress: string, p: Path): Promise<ActionData> {
152
+
153
+ const deadline = Math.floor(Date.now() / 1000) + 1200;
154
+ const uniswapV2Adapter = UniswapV2Adapter__factory.connect(adapterAddress, p.provider);
155
+ const path: Array<string> = [currentTokenAddress, nextTokenAddress];
156
+ const amountsOut: Array<BigNumber> = await uniswapV2Adapter.getAmountsOut(currentBalance, path);
157
+
158
+ const amountOut: BigNumber = amountsOut[amountsOut.length - 1];
159
+ const gasLimit: BigNumber = await uniswapV2Adapter.estimateGas.swapExactTokensForTokens(currentBalance, amountOut, path, p.creditAccount.addr, deadline);
160
+ const call: MultiCall = {
161
+ targetContract: adapterAddress,
162
+ callData: UniswapV2Adapter__factory.createInterface().encodeFunctionData("swapExactTokensForTokens", [currentBalance, amountOut, path, p.creditAccount.addr, deadline])
163
+ }
164
+
165
+ return { callData: call, amountOut: amountOut, gasLimit: gasLimit };
166
+ }
167
+
168
+ async getUniswapV3SwapData(adapterAddress: string, currentTokenAddress: string, currentBalance: BigNumber, nextTokenAddress: string, p: Path): Promise<ActionData> {
169
+ const uniswapV3Adapter = UniswapV3Adapter__factory.connect(adapterAddress, p.provider);
170
+ const iQuoter = IQuoter__factory.connect(UNISWAP_V3_QUOTER, p.provider);
171
+ const amountOut: BigNumber = await iQuoter.callStatic.quoteExactInputSingle(currentTokenAddress, nextTokenAddress, 3000, currentBalance, 0);
172
+ const deadline = Math.floor(Date.now() / 1000) + 1200;
173
+ const exactInputSingleOrder = {
174
+ "tokenIn": currentTokenAddress,
175
+ "tokenOut": nextTokenAddress,
176
+ "fee": 3000,
177
+ "recipient": p.creditAccount.addr,
178
+ "amountIn": currentBalance,
179
+ "amountOutMinimum": amountOut,
180
+ "deadline": deadline,
181
+ "sqrtPriceLimitX96": 0
182
+ };
183
+ const call: MultiCall = {
184
+ targetContract: adapterAddress,
185
+ callData: UniswapV3Adapter__factory.createInterface().encodeFunctionData("exactInputSingle", [exactInputSingleOrder])
186
+ }
187
+ const gasLimit: BigNumber = await uniswapV3Adapter.estimateGas.exactInputSingle(exactInputSingleOrder);
188
+
189
+ return { callData: call, amountOut: amountOut, gasLimit: gasLimit };
190
+ }
191
+
192
+ async getCurveActionData(adapterAddress: string, currentToken: SupportedToken, currentBalance: BigNumber, nextToken: SupportedToken, p: Path): Promise<ActionData> {
193
+ const curve3CrvPool = CurveV1Adapter__factory.connect(adapterAddress, p.provider);
194
+ const currentIndex: BigNumber = Curve3CrvUnderlyingTokenIndex[currentToken]!;
195
+ const outputIndex: BigNumber = Curve3CrvUnderlyingTokenIndex[nextToken]!;
196
+
197
+ const amountOut: BigNumber = await curve3CrvPool.get_dy_underlying(currentIndex, outputIndex, currentBalance);
198
+ const gasLimit: BigNumber = await curve3CrvPool.estimateGas.exchange_underlying(currentIndex, outputIndex, currentBalance, amountOut);
199
+ const call: MultiCall = {
200
+ targetContract: adapterAddress,
201
+ callData: CurveV1Adapter__factory.createInterface().encodeFunctionData("exchange_underlying", [currentIndex, outputIndex, currentBalance, amountOut])
202
+ };
203
+
204
+ return { callData: call, amountOut: amountOut, gasLimit: gasLimit };
205
+ }
206
+
207
+ async getActionData(swapAction: TradeAction, currentTokenAddress: string, currentToken: SupportedToken, currentBalance: BigNumber, nextTokenAddress: string, nextToken: SupportedToken, p: Path): Promise<ActionData> {
208
+ const actionType: TradeType = swapAction.type;
209
+ const actionContract: SupportedContract = swapAction.contract;
210
+ const actionContractAddress: string = contractsByNetwork[p.networkType][actionContract];
211
+ const adapterAddress: string = p.creditManager.adapters[actionContractAddress];
212
+
213
+ switch (actionType) {
214
+ case TradeType.UniswapV2Swap:
215
+ return await this.getUniswapV2SwapData(adapterAddress, currentTokenAddress, currentBalance, nextTokenAddress, p);
216
+
217
+ case TradeType.UniswapV3Swap:
218
+ return await this.getUniswapV3SwapData(adapterAddress, currentTokenAddress, currentBalance, nextTokenAddress, p);
219
+
220
+ case TradeType.CurveExchange:
221
+ if (swapAction.tokenOut!.includes(p.pool as NormalToken)) {
222
+ return await this.getCurveActionData(adapterAddress, currentToken, currentBalance, nextToken, p);
223
+ } else {
224
+ return {
225
+ callData: {
226
+ targetContract: "",
227
+ callData: ""
228
+ },
229
+ amountOut: BigNumber.from(0),
230
+ gasLimit: BigNumber.from(0)
231
+ };
232
+ }
233
+
234
+ default:
235
+ throw Error(`TradeType not supported. ${actionType}`);
236
+ }
237
+ }
238
+
239
+ async getYearnActionData(lpAction: TradeAction, currentBalance: BigNumber, p: Path): Promise<ActionData> {
240
+ // Yearn Vault only has one lp action
241
+ const actionContract: SupportedContract = lpAction.contract;
242
+ const allowedContract: string = contractsByNetwork[p.networkType][actionContract];
243
+ // For Yearn Vault the token address is the contract to withdraw
244
+ const adapterAddress = p.creditManager.adapters[allowedContract];
245
+ const call: MultiCall = {
246
+ targetContract: adapterAddress,
247
+ callData: YearnAdapter__factory.createInterface().encodeFunctionData('withdraw', [currentBalance, p.creditAccount.addr])
248
+ };
249
+
250
+ const IYVault = YearnAdapter__factory.connect(allowedContract, p.provider);
251
+ const price: BigNumber = await IYVault.pricePerShare(); // get price
252
+ const gasLimit: BigNumber = await IYVault.estimateGas["withdraw(uint256,address)"](currentBalance, p.creditAccount.addr);
253
+ return {
254
+ callData: call,
255
+ amountOut: currentBalance.mul(price),
256
+ gasLimit: gasLimit
257
+ }
258
+ }
259
+ }
@@ -0,0 +1,22 @@
1
+ import {SupportedToken, supportedTokens, TokenDataI, TokenType} from "../core/token";
2
+ import {ActionData, Path, PathAsset} from "./path";
3
+ import {BigNumber} from "ethers";
4
+
5
+ export class YearnVaultOfCurveLPPathAsset extends PathAsset {
6
+ async getBestPath(currentToken: SupportedToken, p: Path): Promise<Path> {
7
+ const currentBalance: BigNumber = p.balances[currentToken].sub(1);
8
+ type YearnVaultOfMetaCurveDataI = Extract<TokenDataI, { type: TokenType.YEARN_VAULT_OF_CURVE_LP }>;
9
+ const currentTokenData = supportedTokens[currentToken] as YearnVaultOfMetaCurveDataI;
10
+
11
+ // Yearn Vault only has one lp action
12
+ const outputToken: SupportedToken = currentTokenData.lpActions[0].tokenOut as SupportedToken;
13
+ const yearnActionData: ActionData = await this.getYearnActionData(currentTokenData.lpActions[0], currentBalance, p);
14
+
15
+ p.balances[outputToken].add(yearnActionData.amountOut);
16
+ p.balances[currentToken] = BigNumber.from(1);
17
+ p.totalGasLimit.add(yearnActionData.gasLimit);
18
+ p.calls.push(yearnActionData.callData);
19
+
20
+ return await p.getBestPath();
21
+ }
22
+ }
@@ -0,0 +1,22 @@
1
+ import {SupportedToken, supportedTokens, TokenDataI, TokenType} from "../core/token";
2
+ import {ActionData, Path, PathAsset} from "./path";
3
+ import {BigNumber} from "ethers";
4
+
5
+ export class YearnVaultOfMetaCurveLPPathAsset extends PathAsset {
6
+ async getBestPath(currentToken: SupportedToken, p: Path): Promise<Path> {
7
+ const currentBalance: BigNumber = p.balances[currentToken].sub(1);
8
+ type YearnVaultOfMetaCurveDataI = Extract<TokenDataI, { type: TokenType.YEARN_VAULT_OF_META_CURVE_LP }>;
9
+ const currentTokenData = supportedTokens[currentToken] as YearnVaultOfMetaCurveDataI;
10
+
11
+ // Yearn Vault only has one lp action
12
+ const outputToken: SupportedToken = currentTokenData.lpActions[0].tokenOut as SupportedToken;
13
+ const yearnActionData: ActionData = await this.getYearnActionData(currentTokenData.lpActions[0], currentBalance, p);
14
+
15
+ p.balances[outputToken].add(yearnActionData.amountOut);
16
+ p.balances[currentToken] = BigNumber.from(1);
17
+ p.totalGasLimit.add(yearnActionData.gasLimit);
18
+ p.calls.push(yearnActionData.callData);
19
+
20
+ return await p.getBestPath();
21
+ }
22
+ }
@@ -0,0 +1,27 @@
1
+ import {BigNumber} from "ethers";
2
+ import {
3
+ SupportedToken,
4
+ supportedTokens,
5
+ TokenDataI,
6
+ TokenType
7
+ } from "../core/token";
8
+ import {ActionData, Path, PathAsset} from "./path";
9
+
10
+ export class YearnVaultPathAsset extends PathAsset {
11
+ async getBestPath(currentToken: SupportedToken, p: Path): Promise<Path> {
12
+ const currentBalance: BigNumber = p.balances[currentToken].sub(1);
13
+ type YearnVaultDataI = Extract<TokenDataI, { type: TokenType.YEARN_VAULT }>;
14
+ const currentTokenData = supportedTokens[currentToken] as YearnVaultDataI;
15
+
16
+ // Yearn Vault only has one lp action
17
+ const outputToken: SupportedToken = currentTokenData.lpActions[0].tokenOut as SupportedToken;
18
+ const yearnActionData: ActionData = await this.getYearnActionData(currentTokenData.lpActions[0], currentBalance, p);
19
+
20
+ p.balances[outputToken].add(yearnActionData.amountOut);
21
+ p.balances[currentToken] = BigNumber.from(1);
22
+ p.totalGasLimit.add(yearnActionData.gasLimit);
23
+ p.calls.push(yearnActionData.callData);
24
+
25
+ return await p.getBestPath();
26
+ }
27
+ }
@@ -0,0 +1,3 @@
1
+ export type PartialRecord<K extends keyof any, T> = {
2
+ [P in K]?: T;
3
+ };
@@ -1,115 +0,0 @@
1
- import { BigNumber } from "ethers";
2
- import { CreditManagerData } from "./creditManager";
3
- import { MultiCall } from "./multicall";
4
- import { SupportedToken } from "./token";
5
-
6
- // const path = new Path({gasUsed:0, balances: creditAccount.balances, })
7
- // const closurePath = await path.getBestPath();
8
- // closurePath.calls -> multicalls (!)
9
- // closurePath.balances[path.pool] = (X)
10
- // closurePath.balances[!path.pool] = 0 / 1;
11
-
12
- //
13
- // [0,0,0, 100]
14
- // [ 12, 12, 12, 0]
15
-
16
- export class Path {
17
- public readonly calls: Array<MultiCall> = [];
18
- public readonly balances: Record<SupportedToken, BigNumber>;
19
- // usedTokens: Array<SupportedTokens>;
20
- protected _gasUsed: number;
21
- public readonly pool: SupportedToken;
22
- public readonly creditManager: CreditManagerData;
23
-
24
- constructor(opts: {
25
- gasUsed: number;
26
- balances: Record<SupportedToken, BigNumber>;
27
- pool: SupportedToken;
28
- creditManager: CreditManagerData;
29
- }) {
30
- this._gasUsed = opts.gasUsed;
31
- this.balances = opts.balances;
32
- this.pool = opts.pool;
33
- this.creditManager = opts.creditManager;
34
- }
35
-
36
- async getBestPath(): Promise<Path> {
37
- // const nextToken = Object.entries(this.balances).filter(([token, balance]) => balance.gt(1) ) //.sort((a,b) => {})
38
- // if (nextToken.length ===1 ) {
39
-
40
- // }
41
-
42
- // Get balances and keep non-zero only
43
- // Find token with highest priority
44
- // Get token type of this token
45
- // switch (type) {
46
- // case TokenType.YearnValut:
47
- // const assetPathClass = new YearnPathAsset();
48
- // return assetPathClass.getBestPath(this);
49
- // ...
50
-
51
- //}
52
- throw new Error("Not implmented");
53
- }
54
- }
55
-
56
- export interface PathAsset {
57
- getBestPath(p: Path): Promise<Path>;
58
- }
59
-
60
- export class ConnectorPathAsset implements PathAsset {
61
- getBestPath(p: Path): Promise<Path> {
62
- console.log(p);
63
- // How to unwrap
64
- // set balance of current token to 0
65
- // add balnace what we get
66
- // add call
67
- // create new Paths
68
-
69
- // 3CRV:
70
- // coinst balance3crv = p.balance["3rcv"];
71
- // const p.balance["3rcv"] = 0;
72
- // DAI
73
- // const daiPath = {...p};
74
- // const daiPath["Dai"] = await curve.getAmount(t balance3crv);
75
-
76
- // const pathDai = new Path(daiPath)
77
- // ...
78
- // const bestPath = pathDai.balance[0] > pathUSDC.balance(0) ? pathDai : pathUsdc;
79
-
80
- // --- DAI
81
- // --|
82
- // --- USDC
83
- //
84
- // NORMAL TOKEN
85
- // ============
86
- //
87
- // - NORMAL -> POOL (1 pair) => #1
88
- // for(let conn of connectors) {
89
- // const result = getAmount([NORMAL, conn, pool])
90
- // }
91
- // => best Path to get max Pool tokens
92
- // const resultInConnector = getAmount([NORMAL, conn]);
93
- // calls.push("Uniswap.swap(NORMAL, conn)");
94
-
95
- // CRV => CRV -> USDC -> DAI
96
- // LINK => LINK -> USDC -> DAI
97
- //
98
- // [UniV2.swap("CRV", "USDC"),
99
- // UniV3.swap("LINK", "USDC"),
100
- // Curve.exchange("USDC", "DAI")]
101
- //
102
- // Below is not optimal:
103
- // [ UniV2.swap("CRV -> USDC -> DAI"),
104
- // UniV2.swap("LINK -> USDC -> DAI")]
105
- //
106
- //
107
- // [ UniV2.swap("CRV -> USDC")
108
- // UniV2.swap("USDC -> DAI"),
109
- // UniV2.swap("LINK -> USDC"),
110
- // UniV2.swap("USDC -> DAI") ]
111
-
112
- // return maxValuable(new Paths.getBestPath())
113
- throw new Error("Method not implemented.");
114
- }
115
- }