@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.
- package/lib/core/pathfinder.d.ts +35 -5
- package/lib/core/pathfinder.js +547 -67
- package/lib/core/token.d.ts +5 -0
- package/lib/core/token.js +8 -1
- package/lib/core/tradeTypes.d.ts +2 -0
- package/lib/pathfinder/connectorPathAsset.d.ts +7 -0
- package/lib/pathfinder/connectorPathAsset.js +144 -0
- package/lib/pathfinder/convexLPTokenPathAsset.d.ts +5 -0
- package/lib/pathfinder/convexLPTokenPathAsset.js +77 -0
- package/lib/pathfinder/curveLPPathAsset.d.ts +5 -0
- package/lib/pathfinder/curveLPPathAsset.js +72 -0
- package/lib/pathfinder/metaCurveLPPathAsset.d.ts +5 -0
- package/lib/pathfinder/metaCurveLPPathAsset.js +72 -0
- package/lib/pathfinder/normalTokenPathAsset.d.ts +5 -0
- package/lib/pathfinder/normalTokenPathAsset.js +136 -0
- package/lib/pathfinder/path.d.ts +41 -0
- package/lib/pathfinder/path.js +302 -0
- package/lib/pathfinder/pathfinder.d.ts +28 -0
- package/lib/pathfinder/pathfinder.js +519 -0
- package/lib/pathfinder/yearnVaultOfCurveLPPathAsset.d.ts +5 -0
- package/lib/pathfinder/yearnVaultOfCurveLPPathAsset.js +87 -0
- package/lib/pathfinder/yearnVaultOfMetaCurveLPPathAsset.d.ts +5 -0
- package/lib/pathfinder/yearnVaultOfMetaCurveLPPathAsset.js +87 -0
- package/lib/pathfinder/yearnVaultPathAsset.d.ts +5 -0
- package/lib/pathfinder/yearnVaultPathAsset.js +87 -0
- package/lib/utils/types.d.ts +3 -0
- package/lib/utils/types.js +2 -0
- package/package.json +1 -1
- package/src/core/contracts.ts +11 -1
- package/src/core/token.ts +12 -0
- package/src/core/tradeTypes.ts +2 -0
- package/src/pathfinder/connectorPathAsset.ts +69 -0
- package/src/pathfinder/convexLPTokenPathAsset.ts +33 -0
- package/src/pathfinder/curveLPPathAsset.ts +10 -0
- package/src/pathfinder/metaCurveLPPathAsset.ts +12 -0
- package/src/pathfinder/normalTokenPathAsset.ts +68 -0
- package/src/pathfinder/path.ts +259 -0
- package/src/pathfinder/yearnVaultOfCurveLPPathAsset.ts +22 -0
- package/src/pathfinder/yearnVaultOfMetaCurveLPPathAsset.ts +22 -0
- package/src/pathfinder/yearnVaultPathAsset.ts +27 -0
- package/src/utils/types.ts +3 -0
- 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
|
+
}
|
package/src/core/pathfinder.ts
DELETED
|
@@ -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
|
-
}
|