bestTradeExactIn static method
Given a list of pairs, and a fixed amount in, returns the top maxNumResults trades that go from an input token
amount to an output token, making at most maxHops hops.
Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting
the amount in among multiple routes.
@param pairs the pairs to consider in finding the best trade
@param currencyAmountIn exact amount of input currency to spend
@param currencyOut the desired currency out
@param maxNumResults maximum number of results to return
@param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pair
@param currentPairs used in recursion; the current list of pairs
@param originalAmountIn used in recursion; the original value of the currencyAmountIn parameter
@param bestTrades used in recursion; the current list of best trades
Implementation
static List<Trade> bestTradeExactIn(
List<Pair> pairs,
CurrencyAmount currencyAmountIn,
Currency currencyOut, {
int maxNumResults = 3,
int maxHops = 3,
// used in recursion.
List<Pair>? currentPairs,
CurrencyAmount? originalAmountIn,
List<Trade>? bestTrades,
}) {
currentPairs = currentPairs ?? [];
originalAmountIn = originalAmountIn ?? currencyAmountIn;
bestTrades = bestTrades ?? [];
invariant(pairs.isNotEmpty, 'PAIRS');
invariant(maxHops > 0, 'MAX_HOPS');
invariant(originalAmountIn == currencyAmountIn || currentPairs.isNotEmpty,
'INVALID_RECURSION');
final chainId = currencyAmountIn is TokenAmount
? currencyAmountIn.token.chainId
: currencyOut is Token
? currencyOut.chainId
: null;
invariant(chainId != null, 'CHAIN_ID');
final amountIn =
wrappedAmount(currencyAmountIn, int.parse(chainId.toString()).chain);
final tokenOut =
wrappedCurrency(currencyOut, int.parse(chainId.toString()));
for (int i = 0; i < pairs.length; i++) {
final pair = pairs[i];
// pair irrelevant
if (pair.token0 != amountIn.token && pair.token1 != amountIn.token) {
continue;
}
if (pair.reserve0.raw == ZERO || pair.reserve1.raw == ZERO) continue;
TokenAmount amountOut;
try {
amountOut = pair.getOutputAmount(amountIn)[0];
} on InsufficientReservesError catch (_) {
continue;
} catch (error) {
continue;
}
// we have arrived at the output token, so this is the final trade of one of the paths
if (amountOut.token == tokenOut) {
sortedInsertTrade(
bestTrades,
Trade(
Route([...currentPairs, pair], originalAmountIn.currency,
output: currencyOut),
originalAmountIn,
TradeType.EXACT_INPUT),
maxNumResults,
);
} else if (maxHops > 1 && pairs.length > 1) {
final dataLastPair = pairs.sublist(i + 1, pairs.length);
final pairsExcludingThisPair = pairs.sublist(0, i) + dataLastPair;
// otherwise, consider all the other paths that lead from this token as long as we have not exceeded maxHops
Trade.bestTradeExactIn(pairsExcludingThisPair, amountOut, currencyOut,
maxNumResults: maxNumResults,
maxHops: (maxHops - 1),
currentPairs: [...currentPairs, pair],
originalAmountIn: originalAmountIn,
bestTrades: bestTrades);
}
}
return bestTrades;
}