From e10a81023a69564cd5474f0b1e733019080e6fc2 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Tue, 3 Nov 2020 07:48:37 +1000 Subject: [PATCH] feat: [asset-swapper] more hops via token adjacency (#24) * feat: [asset-swapper] more hops via token adjacency * fix lint * CHANGELOG --- packages/asset-swapper/CHANGELOG.json | 6 +- packages/asset-swapper/src/constants.ts | 4 +- packages/asset-swapper/src/swap_quoter.ts | 2 - packages/asset-swapper/src/types.ts | 8 +- .../utils/market_operation_utils/constants.ts | 1 + .../src/utils/market_operation_utils/index.ts | 13 ++-- .../market_operation_utils/multihop_utils.ts | 2 +- .../sampler_operations.ts | 62 ++++++++------- .../src/utils/market_operation_utils/types.ts | 5 ++ .../asset-swapper/test/dex_sampler_test.ts | 11 ++- .../test/market_operation_utils_test.ts | 77 +++++++++++++++++-- 11 files changed, 135 insertions(+), 56 deletions(-) diff --git a/packages/asset-swapper/CHANGELOG.json b/packages/asset-swapper/CHANGELOG.json index a72cc8951b..c107dae0b8 100644 --- a/packages/asset-swapper/CHANGELOG.json +++ b/packages/asset-swapper/CHANGELOG.json @@ -1,10 +1,14 @@ [ { - "version": "4.9.0", + "version": "5.0.0", "changes": [ { "note": "Support multiple `Shells` by supplying the `pool` address", "pr": 17 + }, + { + "note": "Make use of Token Adjacency in more places. Moved as a parameter for the quote", + "pr": 24 } ] }, diff --git a/packages/asset-swapper/src/constants.ts b/packages/asset-swapper/src/constants.ts index b2c7fbd98e..73775b08a5 100644 --- a/packages/asset-swapper/src/constants.ts +++ b/packages/asset-swapper/src/constants.ts @@ -14,7 +14,7 @@ import { SwapQuoteRequestOpts, SwapQuoterOpts, } from './types'; -import { DEFAULT_GET_MARKET_ORDERS_OPTS } from './utils/market_operation_utils/constants'; +import { DEFAULT_GET_MARKET_ORDERS_OPTS, TOKENS } from './utils/market_operation_utils/constants'; const ETH_GAS_STATION_API_URL = 'https://ethgasstation.info/api/ethgasAPI.json'; const NULL_BYTES = '0x'; @@ -42,6 +42,7 @@ const PROTOCOL_FEE_MULTIPLIER = new BigNumber(70000); // default 50% buffer for selecting native orders to be aggregated with other sources const MARKET_UTILS_AMOUNT_BUFFER_PERCENTAGE = 0.5; +const DEFAULT_INTERMEDIATE_TOKENS = [TOKENS.WETH, TOKENS.USDT, TOKENS.DAI, TOKENS.USDC]; const DEFAULT_SWAP_QUOTER_OPTS: SwapQuoterOpts = { chainId: ChainId.Mainnet, orderRefreshIntervalMs: 10000, // 10 seconds @@ -125,6 +126,7 @@ export const constants = { ONE_SECOND_MS, ONE_MINUTE_MS, DEFAULT_SWAP_QUOTER_OPTS, + DEFAULT_INTERMEDIATE_TOKENS, DEFAULT_FORWARDER_SWAP_QUOTE_GET_OPTS, DEFAULT_FORWARDER_SWAP_QUOTE_EXECUTE_OPTS, DEFAULT_SWAP_QUOTE_REQUEST_OPTS, diff --git a/packages/asset-swapper/src/swap_quoter.ts b/packages/asset-swapper/src/swap_quoter.ts index 21420ada9f..909a39908c 100644 --- a/packages/asset-swapper/src/swap_quoter.ts +++ b/packages/asset-swapper/src/swap_quoter.ts @@ -166,7 +166,6 @@ export class SwapQuoter { samplerGasLimit, liquidityProviderRegistryAddress, rfqt, - tokenAdjacencyGraph, } = _.merge({}, constants.DEFAULT_SWAP_QUOTER_OPTS, options); const provider = providerUtils.standardizeOrThrow(supportedProvider); assert.isValidOrderbook('orderbook', orderbook); @@ -215,7 +214,6 @@ export class SwapQuoter { exchangeAddress: this._contractAddresses.exchange, }, liquidityProviderRegistryAddress, - tokenAdjacencyGraph, ); this._swapQuoteCalculator = new SwapQuoteCalculator(this._marketOperationUtils); } diff --git a/packages/asset-swapper/src/types.ts b/packages/asset-swapper/src/types.ts index 0ba490a9a7..283051be01 100644 --- a/packages/asset-swapper/src/types.ts +++ b/packages/asset-swapper/src/types.ts @@ -4,12 +4,7 @@ import { TakerRequestQueryParams } from '@0x/quote-server'; import { SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; -import { - ERC20BridgeSource, - GetMarketOrdersOpts, - OptimizedMarketOrder, - TokenAdjacencyGraph, -} from './utils/market_operation_utils/types'; +import { ERC20BridgeSource, GetMarketOrdersOpts, OptimizedMarketOrder } from './utils/market_operation_utils/types'; import { QuoteReport } from './utils/quote_report_generator'; /** @@ -315,7 +310,6 @@ export interface SwapQuoterOpts extends OrderPrunerOpts { ethGasStationUrl?: string; rfqt?: SwapQuoterRfqtOpts; samplerOverrides?: SamplerOverrides; - tokenAdjacencyGraph?: TokenAdjacencyGraph; } /** diff --git a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts index 80f108b739..c614f28171 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts @@ -459,4 +459,5 @@ export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = { exchangeProxyOverhead: () => ZERO_AMOUNT, allowFallback: true, shouldGenerateQuoteReport: false, + tokenAdjacencyGraph: {}, }; diff --git a/packages/asset-swapper/src/utils/market_operation_utils/index.ts b/packages/asset-swapper/src/utils/market_operation_utils/index.ts index 750b28e757..d151c9f486 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/index.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/index.ts @@ -41,7 +41,6 @@ import { OptimizerResult, OptimizerResultWithReport, OrderDomain, - TokenAdjacencyGraph, } from './types'; // tslint:disable:boolean-naming @@ -109,7 +108,6 @@ export class MarketOperationUtils { private readonly contractAddresses: AssetSwapperContractAddresses, private readonly _orderDomain: OrderDomain, private readonly _liquidityProviderRegistry: string = NULL_ADDRESS, - private readonly _tokenAdjacencyGraph: TokenAdjacencyGraph = {}, ) { this._wethAddress = contractAddresses.etherToken.toLowerCase(); this._multiBridge = contractAddresses.multiBridge.toLowerCase(); @@ -182,7 +180,6 @@ export class MarketOperationUtils { makerToken, this._wethAddress, ONE_ETHER, - this._wethAddress, this._liquidityProviderRegistry, this._multiBridge, ), @@ -192,7 +189,6 @@ export class MarketOperationUtils { takerToken, this._wethAddress, ONE_ETHER, - this._wethAddress, this._liquidityProviderRegistry, this._multiBridge, ), @@ -203,6 +199,7 @@ export class MarketOperationUtils { takerToken, sampleAmounts, this._wethAddress, + _opts.tokenAdjacencyGraph, this._liquidityProviderRegistry, this._multiBridge, ), @@ -211,8 +208,8 @@ export class MarketOperationUtils { makerToken, takerToken, takerAmount, - this._tokenAdjacencyGraph, this._wethAddress, + _opts.tokenAdjacencyGraph, this._liquidityProviderRegistry, ), ); @@ -333,7 +330,6 @@ export class MarketOperationUtils { makerToken, this._wethAddress, ONE_ETHER, - this._wethAddress, this._liquidityProviderRegistry, this._multiBridge, ), @@ -343,7 +339,6 @@ export class MarketOperationUtils { takerToken, this._wethAddress, ONE_ETHER, - this._wethAddress, this._liquidityProviderRegistry, this._multiBridge, ), @@ -354,6 +349,7 @@ export class MarketOperationUtils { takerToken, sampleAmounts, this._wethAddress, + _opts.tokenAdjacencyGraph, this._liquidityProviderRegistry, ), this._sampler.getTwoHopBuyQuotes( @@ -361,8 +357,8 @@ export class MarketOperationUtils { makerToken, takerToken, makerAmount, - this._tokenAdjacencyGraph, this._wethAddress, + _opts.tokenAdjacencyGraph, this._liquidityProviderRegistry, ), ); @@ -493,6 +489,7 @@ export class MarketOperationUtils { getNativeOrderTokens(orders[0])[1], [makerAmounts[i]], this._wethAddress, + _opts.tokenAdjacencyGraph, ), ), ]; diff --git a/packages/asset-swapper/src/utils/market_operation_utils/multihop_utils.ts b/packages/asset-swapper/src/utils/market_operation_utils/multihop_utils.ts index 961590b37e..f0a4d2215e 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/multihop_utils.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/multihop_utils.ts @@ -34,7 +34,7 @@ export function getIntermediateTokens( [wethAddress], ); } - return intermediateTokens.filter( + return _.uniqBy(intermediateTokens, a => a.toLowerCase()).filter( token => token.toLowerCase() !== makerToken.toLowerCase() && token.toLowerCase() !== takerToken.toLowerCase(), ); } diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index 688dd43ffd..33b7782893 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -669,8 +669,8 @@ export class SamplerOperations { makerToken: string, takerToken: string, sellAmount: BigNumber, - tokenAdjacencyGraph: TokenAdjacencyGraph, wethAddress: string, + tokenAdjacencyGraph: TokenAdjacencyGraph, liquidityProviderRegistryAddress?: string, ): BatchedOperation>> { const _sources = TWO_HOP_SOURCE_FILTERS.getAllowed(sources); @@ -685,6 +685,7 @@ export class SamplerOperations { takerToken, [ZERO_AMOUNT], wethAddress, + tokenAdjacencyGraph, liquidityProviderRegistryAddress, ); const secondHopOps = this._getSellQuoteOperations( @@ -693,6 +694,7 @@ export class SamplerOperations { intermediateToken, [ZERO_AMOUNT], wethAddress, + tokenAdjacencyGraph, liquidityProviderRegistryAddress, ); return new SamplerContractOperation({ @@ -745,8 +747,8 @@ export class SamplerOperations { makerToken: string, takerToken: string, buyAmount: BigNumber, - tokenAdjacencyGraph: TokenAdjacencyGraph, wethAddress: string, + tokenAdjacencyGraph: TokenAdjacencyGraph, liquidityProviderRegistryAddress?: string, ): BatchedOperation>> { const _sources = TWO_HOP_SOURCE_FILTERS.getAllowed(sources); @@ -761,6 +763,7 @@ export class SamplerOperations { takerToken, [new BigNumber(0)], wethAddress, + tokenAdjacencyGraph, // TODO is this a bad idea? liquidityProviderRegistryAddress, ); const secondHopOps = this._getBuyQuoteOperations( @@ -769,6 +772,7 @@ export class SamplerOperations { intermediateToken, [new BigNumber(0)], wethAddress, + tokenAdjacencyGraph, liquidityProviderRegistryAddress, ); return new SamplerContractOperation({ @@ -932,7 +936,6 @@ export class SamplerOperations { makerToken: string, takerToken: string, takerFillAmount: BigNumber, - wethAddress: string, liquidityProviderRegistryAddress?: string, multiBridgeAddress?: string, ): BatchedOperation { @@ -944,7 +947,8 @@ export class SamplerOperations { makerToken, takerToken, [takerFillAmount], - wethAddress, + NULL_ADDRESS, // weth address + {}, // token adjacency liquidityProviderRegistryAddress, multiBridgeAddress, ); @@ -988,6 +992,7 @@ export class SamplerOperations { takerToken: string, takerFillAmounts: BigNumber[], wethAddress: string, + tokenAdjacencyGraph: TokenAdjacencyGraph, liquidityProviderRegistryAddress?: string, multiBridgeAddress?: string, ): BatchedOperation { @@ -997,6 +1002,7 @@ export class SamplerOperations { takerToken, takerFillAmounts, wethAddress, + tokenAdjacencyGraph, liquidityProviderRegistryAddress, multiBridgeAddress, ); @@ -1029,6 +1035,7 @@ export class SamplerOperations { takerToken: string, makerFillAmounts: BigNumber[], wethAddress: string, + tokenAdjacencyGraph: TokenAdjacencyGraph, liquidityProviderRegistryAddress?: string, ): BatchedOperation { const subOps = this._getBuyQuoteOperations( @@ -1037,6 +1044,7 @@ export class SamplerOperations { takerToken, makerFillAmounts, wethAddress, + tokenAdjacencyGraph, liquidityProviderRegistryAddress, ); return { @@ -1068,6 +1076,7 @@ export class SamplerOperations { takerToken: string, takerFillAmounts: BigNumber[], wethAddress: string, + tokenAdjacencyGraph: TokenAdjacencyGraph, liquidityProviderRegistryAddress?: string, multiBridgeAddress?: string, ): SourceQuoteOperation[] { @@ -1076,6 +1085,11 @@ export class SamplerOperations { ) .exclude(multiBridgeAddress || multiBridgeAddress === NULL_ADDRESS ? [] : [ERC20BridgeSource.MultiBridge]) .getAllowed(sources); + + // Find the adjacent tokens in the provided tooken adjacency graph, + // e.g if this is DAI->USDC we may check for DAI->WETH->USDC + const intermediateTokens = getIntermediateTokens(makerToken, takerToken, tokenAdjacencyGraph, wethAddress); + return _.flatten( _sources.map( (source): SourceQuoteOperation | SourceQuoteOperation[] => { @@ -1086,25 +1100,17 @@ export class SamplerOperations { return this.getUniswapSellQuotes(makerToken, takerToken, takerFillAmounts); case ERC20BridgeSource.UniswapV2: const ops = [this.getUniswapV2SellQuotes([takerToken, makerToken], takerFillAmounts)]; - if (takerToken !== wethAddress && makerToken !== wethAddress) { - ops.push( - this.getUniswapV2SellQuotes( - [takerToken, wethAddress, makerToken], - takerFillAmounts, - ), - ); - } + intermediateTokens.forEach(t => { + ops.push(this.getUniswapV2SellQuotes([takerToken, t, makerToken], takerFillAmounts)); + }); return ops; case ERC20BridgeSource.SushiSwap: const sushiOps = [this.getSushiSwapSellQuotes([takerToken, makerToken], takerFillAmounts)]; - if (takerToken !== wethAddress && makerToken !== wethAddress) { + intermediateTokens.forEach(t => { sushiOps.push( - this.getSushiSwapSellQuotes( - [takerToken, wethAddress, makerToken], - takerFillAmounts, - ), + this.getSushiSwapSellQuotes([takerToken, t, makerToken], takerFillAmounts), ); - } + }); return sushiOps; case ERC20BridgeSource.Kyber: return getKyberReserveIdsForPair(takerToken, makerToken).map(reserveId => @@ -1211,11 +1217,17 @@ export class SamplerOperations { takerToken: string, makerFillAmounts: BigNumber[], wethAddress: string, + tokenAdjacencyGraph: TokenAdjacencyGraph, liquidityProviderRegistryAddress?: string, ): SourceQuoteOperation[] { const _sources = BATCH_SOURCE_FILTERS.exclude( liquidityProviderRegistryAddress ? [] : [ERC20BridgeSource.LiquidityProvider], ).getAllowed(sources); + + // Find the adjacent tokens in the provided tooken adjacency graph, + // e.g if this is DAI->USDC we may check for DAI->WETH->USDC + const intermediateTokens = getIntermediateTokens(makerToken, takerToken, tokenAdjacencyGraph, wethAddress); + return _.flatten( _sources.map( (source): SourceQuoteOperation | SourceQuoteOperation[] => { @@ -1226,19 +1238,17 @@ export class SamplerOperations { return this.getUniswapBuyQuotes(makerToken, takerToken, makerFillAmounts); case ERC20BridgeSource.UniswapV2: const ops = [this.getUniswapV2BuyQuotes([takerToken, makerToken], makerFillAmounts)]; - if (takerToken !== wethAddress && makerToken !== wethAddress) { - ops.push( - this.getUniswapV2BuyQuotes([takerToken, wethAddress, makerToken], makerFillAmounts), - ); - } + intermediateTokens.forEach(t => { + ops.push(this.getUniswapV2BuyQuotes([takerToken, t, makerToken], makerFillAmounts)); + }); return ops; case ERC20BridgeSource.SushiSwap: const sushiOps = [this.getSushiSwapBuyQuotes([takerToken, makerToken], makerFillAmounts)]; - if (takerToken !== wethAddress && makerToken !== wethAddress) { + intermediateTokens.forEach(t => { sushiOps.push( - this.getSushiSwapBuyQuotes([takerToken, wethAddress, makerToken], makerFillAmounts), + this.getSushiSwapBuyQuotes([takerToken, t, makerToken], makerFillAmounts), ); - } + }); return sushiOps; case ERC20BridgeSource.Kyber: return getKyberReserveIdsForPair(takerToken, makerToken).map(reserveId => diff --git a/packages/asset-swapper/src/utils/market_operation_utils/types.ts b/packages/asset-swapper/src/utils/market_operation_utils/types.ts index e0364bdd2b..399db51c02 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/types.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/types.ts @@ -317,6 +317,11 @@ export interface GetMarketOrdersOpts { * Whether to generate a quote report */ shouldGenerateQuoteReport: boolean; + /** + * Token addresses with a list of adjacent intermediary tokens to consider + * hopping to. E.g DAI->USDC via an adjacent token WETH + */ + tokenAdjacencyGraph: TokenAdjacencyGraph; } /** diff --git a/packages/asset-swapper/test/dex_sampler_test.ts b/packages/asset-swapper/test/dex_sampler_test.ts index 8d2706b0e3..b79bc75475 100644 --- a/packages/asset-swapper/test/dex_sampler_test.ts +++ b/packages/asset-swapper/test/dex_sampler_test.ts @@ -18,7 +18,7 @@ import { computeBalancerSellQuote, } from '../src/utils/market_operation_utils/balancer_utils'; import { DexOrderSampler, getSampleAmounts } from '../src/utils/market_operation_utils/sampler'; -import { ERC20BridgeSource } from '../src/utils/market_operation_utils/types'; +import { ERC20BridgeSource, TokenAdjacencyGraph } from '../src/utils/market_operation_utils/types'; import { MockBalancerPoolsCache } from './utils/mock_balancer_pools_cache'; import { MockBancorService } from './utils/mock_bancor_service'; @@ -36,6 +36,8 @@ describe('DexSampler tests', () => { const wethAddress = getContractAddressesForChainOrThrow(CHAIN_ID).etherToken; const exchangeAddress = getContractAddressesForChainOrThrow(CHAIN_ID).exchange; + const tokenAdjacencyGraph: TokenAdjacencyGraph = {}; + describe('getSampleAmounts()', () => { const FILL_AMOUNT = getRandomInteger(1, 1e18); const NUM_SAMPLES = 16; @@ -175,6 +177,7 @@ describe('DexSampler tests', () => { expectedTakerToken, [toBaseUnitAmount(1000)], wethAddress, + tokenAdjacencyGraph, registry, ), ); @@ -211,6 +214,7 @@ describe('DexSampler tests', () => { expectedTakerToken, [toBaseUnitAmount(1000)], wethAddress, + tokenAdjacencyGraph, registry, ), ); @@ -252,7 +256,8 @@ describe('DexSampler tests', () => { expectedMakerToken, expectedTakerToken, [toBaseUnitAmount(1000)], - randomAddress(), + wethAddress, + tokenAdjacencyGraph, randomAddress(), multiBridge, ), @@ -419,6 +424,7 @@ describe('DexSampler tests', () => { expectedTakerToken, expectedTakerFillAmounts, wethAddress, + tokenAdjacencyGraph, ), ); const expectedQuotes = sources.map(s => @@ -563,6 +569,7 @@ describe('DexSampler tests', () => { expectedTakerToken, expectedMakerFillAmounts, wethAddress, + tokenAdjacencyGraph, ), ); const expectedQuotes = sources.map(s => diff --git a/packages/asset-swapper/test/market_operation_utils_test.ts b/packages/asset-swapper/test/market_operation_utils_test.ts index 682fd389a4..64afc8321b 100644 --- a/packages/asset-swapper/test/market_operation_utils_test.ts +++ b/packages/asset-swapper/test/market_operation_utils_test.ts @@ -41,6 +41,7 @@ import { GetMarketOrdersOpts, MarketSideLiquidity, NativeFillData, + TokenAdjacencyGraph, } from '../src/utils/market_operation_utils/types'; const MAKER_TOKEN = randomAddress(); @@ -64,6 +65,7 @@ const DEFAULT_EXCLUDED = [ ]; const BUY_SOURCES = BUY_SOURCE_FILTER.sources; const SELL_SOURCES = SELL_SOURCE_FILTER.sources; +const TOKEN_ADJACENCY_GRAPH: TokenAdjacencyGraph = {}; // tslint:disable: custom-no-magic-numbers promise-function-async describe('MarketOperationUtils tests', () => { @@ -219,6 +221,7 @@ describe('MarketOperationUtils tests', () => { takerToken: string, fillAmounts: BigNumber[], wethAddress: string, + tokenAdjacencyGraph: TokenAdjacencyGraph, liquidityProviderAddress?: string, ) => DexSample[][]; @@ -248,6 +251,7 @@ describe('MarketOperationUtils tests', () => { takerToken: string, fillAmounts: BigNumber[], wethAddress: string, + tokenAdjacencyGraph: TokenAdjacencyGraph = TOKEN_ADJACENCY_GRAPH, liquidityProviderAddress?: string, ) => { liquidityPoolParams.liquidityProviderAddress = liquidityProviderAddress; @@ -258,6 +262,7 @@ describe('MarketOperationUtils tests', () => { takerToken, fillAmounts, wethAddress, + TOKEN_ADJACENCY_GRAPH, liquidityProviderAddress, ); }; @@ -548,7 +553,14 @@ describe('MarketOperationUtils tests', () => { replaceSamplerOps({ getSellQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => { actualNumSamples = amounts.length; - return DEFAULT_OPS.getSellQuotes(sources, makerToken, takerToken, amounts, wethAddress); + return DEFAULT_OPS.getSellQuotes( + sources, + makerToken, + takerToken, + amounts, + wethAddress, + TOKEN_ADJACENCY_GRAPH, + ); }, }); await marketOperationUtils.getMarketSellOrdersAsync(ORDERS, FILL_AMOUNT, { @@ -563,7 +575,14 @@ describe('MarketOperationUtils tests', () => { replaceSamplerOps({ getSellQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => { sourcesPolled = sourcesPolled.concat(sources.slice()); - return DEFAULT_OPS.getSellQuotes(sources, makerToken, takerToken, amounts, wethAddress); + return DEFAULT_OPS.getSellQuotes( + sources, + makerToken, + takerToken, + amounts, + wethAddress, + TOKEN_ADJACENCY_GRAPH, + ); }, getTwoHopSellQuotes: (...args: any[]) => { sourcesPolled.push(ERC20BridgeSource.MultiHop); @@ -647,7 +666,14 @@ describe('MarketOperationUtils tests', () => { replaceSamplerOps({ getSellQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => { sourcesPolled = sourcesPolled.concat(sources.slice()); - return DEFAULT_OPS.getSellQuotes(sources, makerToken, takerToken, amounts, wethAddress); + return DEFAULT_OPS.getSellQuotes( + sources, + makerToken, + takerToken, + amounts, + wethAddress, + TOKEN_ADJACENCY_GRAPH, + ); }, getTwoHopSellQuotes: (sources: ERC20BridgeSource[], ...args: any[]) => { if (sources.length !== 0) { @@ -686,7 +712,14 @@ describe('MarketOperationUtils tests', () => { replaceSamplerOps({ getSellQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => { sourcesPolled = sourcesPolled.concat(sources.slice()); - return DEFAULT_OPS.getSellQuotes(sources, makerToken, takerToken, amounts, wethAddress); + return DEFAULT_OPS.getSellQuotes( + sources, + makerToken, + takerToken, + amounts, + wethAddress, + TOKEN_ADJACENCY_GRAPH, + ); }, getTwoHopSellQuotes: (sources: ERC20BridgeSource[], ...args: any[]) => { if (sources.length !== 0) { @@ -1429,7 +1462,14 @@ describe('MarketOperationUtils tests', () => { replaceSamplerOps({ getBuyQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => { actualNumSamples = amounts.length; - return DEFAULT_OPS.getBuyQuotes(sources, makerToken, takerToken, amounts, wethAddress); + return DEFAULT_OPS.getBuyQuotes( + sources, + makerToken, + takerToken, + amounts, + wethAddress, + TOKEN_ADJACENCY_GRAPH, + ); }, }); await marketOperationUtils.getMarketBuyOrdersAsync(ORDERS, FILL_AMOUNT, { @@ -1444,7 +1484,14 @@ describe('MarketOperationUtils tests', () => { replaceSamplerOps({ getBuyQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => { sourcesPolled = sourcesPolled.concat(sources.slice()); - return DEFAULT_OPS.getBuyQuotes(sources, makerToken, takerToken, amounts, wethAddress); + return DEFAULT_OPS.getBuyQuotes( + sources, + makerToken, + takerToken, + amounts, + wethAddress, + TOKEN_ADJACENCY_GRAPH, + ); }, getTwoHopBuyQuotes: (sources: ERC20BridgeSource[], ..._args: any[]) => { if (sources.length !== 0) { @@ -1531,7 +1578,14 @@ describe('MarketOperationUtils tests', () => { replaceSamplerOps({ getBuyQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => { sourcesPolled = sourcesPolled.concat(sources.slice()); - return DEFAULT_OPS.getBuyQuotes(sources, makerToken, takerToken, amounts, wethAddress); + return DEFAULT_OPS.getBuyQuotes( + sources, + makerToken, + takerToken, + amounts, + wethAddress, + TOKEN_ADJACENCY_GRAPH, + ); }, getTwoHopBuyQuotes: (sources: ERC20BridgeSource[], ..._args: any[]) => { if (sources.length !== 0) { @@ -1570,7 +1624,14 @@ describe('MarketOperationUtils tests', () => { replaceSamplerOps({ getBuyQuotes: (sources, makerToken, takerToken, amounts, wethAddress) => { sourcesPolled = sourcesPolled.concat(sources.slice()); - return DEFAULT_OPS.getBuyQuotes(sources, makerToken, takerToken, amounts, wethAddress); + return DEFAULT_OPS.getBuyQuotes( + sources, + makerToken, + takerToken, + amounts, + wethAddress, + TOKEN_ADJACENCY_GRAPH, + ); }, getTwoHopBuyQuotes: (sources: ERC20BridgeSource[], ..._args: any[]) => { if (sources.length !== 0) {