Merge pull request #2713 from 0xProject/refactor_reporter

[Price-aware RFQ requests] Decouple QuoteReporter from _generateOptimizedOrdersAsync
This commit is contained in:
Daniel Pyrathon 2020-09-30 14:11:43 -07:00 committed by GitHub
commit 39bd0c5459
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 38 deletions

View File

@ -17,7 +17,7 @@
"compile": "sol-compiler", "compile": "sol-compiler",
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"lint-contracts": "#solhint -c .solhint.json contracts/**/**/**/**/*.sol", "lint-contracts": "#solhint -c .solhint.json contracts/**/**/**/**/*.sol",
"prettier": "prettier '**/*.{ts,tsx,json,md}' --config ../../.prettierrc --ignore-path ../../.prettierignore", "prettier": "prettier --write '**/*.{ts,tsx,json,md}' --config ../../.prettierrc --ignore-path ../../.prettierignore",
"fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-wrappers/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-wrappers/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild_and_test": "run-s clean build test", "rebuild_and_test": "run-s clean build test",

View File

@ -7,7 +7,7 @@ import * as _ from 'lodash';
import { MarketOperation } from '../../types'; import { MarketOperation } from '../../types';
import { QuoteRequestor } from '../quote_requestor'; import { QuoteRequestor } from '../quote_requestor';
import { generateQuoteReport } from './../quote_report_generator'; import { generateQuoteReport, QuoteReport } from './../quote_report_generator';
import { import {
BUY_SOURCE_FILTER, BUY_SOURCE_FILTER,
DEFAULT_GET_MARKET_ORDERS_OPTS, DEFAULT_GET_MARKET_ORDERS_OPTS,
@ -37,6 +37,7 @@ import {
MarketSideLiquidity, MarketSideLiquidity,
OptimizedMarketOrder, OptimizedMarketOrder,
OptimizerResult, OptimizerResult,
OptimizerResultWithReport,
OrderDomain, OrderDomain,
TokenAdjacencyGraph, TokenAdjacencyGraph,
} from './types'; } from './types';
@ -78,6 +79,25 @@ export class MarketOperationUtils {
private readonly _buySources: SourceFilters; private readonly _buySources: SourceFilters;
private readonly _feeSources = new SourceFilters(FEE_QUOTE_SOURCES); private readonly _feeSources = new SourceFilters(FEE_QUOTE_SOURCES);
private static _computeQuoteReport(
nativeOrders: SignedOrder[],
quoteRequestor: QuoteRequestor | undefined,
marketSideLiquidity: MarketSideLiquidity,
optimizerResult: OptimizerResult,
): QuoteReport {
const { side, dexQuotes, twoHopQuotes, orderFillableAmounts } = marketSideLiquidity;
const { liquidityDelivered } = optimizerResult;
return generateQuoteReport(
side,
_.flatten(dexQuotes),
twoHopQuotes,
nativeOrders,
orderFillableAmounts,
liquidityDelivered,
quoteRequestor,
);
}
constructor( constructor(
private readonly _sampler: DexOrderSampler, private readonly _sampler: DexOrderSampler,
private readonly contractAddresses: ContractAddresses, private readonly contractAddresses: ContractAddresses,
@ -339,19 +359,29 @@ export class MarketOperationUtils {
nativeOrders: SignedOrder[], nativeOrders: SignedOrder[],
takerAmount: BigNumber, takerAmount: BigNumber,
opts?: Partial<GetMarketOrdersOpts>, opts?: Partial<GetMarketOrdersOpts>,
): Promise<OptimizerResult> { ): Promise<OptimizerResultWithReport> {
const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts }; const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts };
const marketSideLiquidity = await this.getMarketSellLiquidityAsync(nativeOrders, takerAmount, _opts); const marketSideLiquidity = await this.getMarketSellLiquidityAsync(nativeOrders, takerAmount, _opts);
return this._generateOptimizedOrdersAsync(marketSideLiquidity, { const optimizerResult = await this._generateOptimizedOrdersAsync(marketSideLiquidity, {
bridgeSlippage: _opts.bridgeSlippage, bridgeSlippage: _opts.bridgeSlippage,
maxFallbackSlippage: _opts.maxFallbackSlippage, maxFallbackSlippage: _opts.maxFallbackSlippage,
excludedSources: _opts.excludedSources, excludedSources: _opts.excludedSources,
feeSchedule: _opts.feeSchedule, feeSchedule: _opts.feeSchedule,
allowFallback: _opts.allowFallback, allowFallback: _opts.allowFallback,
shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders, shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders,
quoteRequestor: _opts.rfqt ? _opts.rfqt.quoteRequestor : undefined,
shouldGenerateQuoteReport: _opts.shouldGenerateQuoteReport,
}); });
// Compute Quote Report and return the results.
let quoteReport: QuoteReport | undefined;
if (_opts.shouldGenerateQuoteReport) {
quoteReport = MarketOperationUtils._computeQuoteReport(
nativeOrders,
_opts.rfqt ? _opts.rfqt.quoteRequestor : undefined,
marketSideLiquidity,
optimizerResult,
);
}
return { ...optimizerResult, quoteReport };
} }
/** /**
@ -366,19 +396,27 @@ export class MarketOperationUtils {
nativeOrders: SignedOrder[], nativeOrders: SignedOrder[],
makerAmount: BigNumber, makerAmount: BigNumber,
opts?: Partial<GetMarketOrdersOpts>, opts?: Partial<GetMarketOrdersOpts>,
): Promise<OptimizerResult> { ): Promise<OptimizerResultWithReport> {
const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts }; const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts };
const marketSideLiquidity = await this.getMarketBuyLiquidityAsync(nativeOrders, makerAmount, _opts); const marketSideLiquidity = await this.getMarketBuyLiquidityAsync(nativeOrders, makerAmount, _opts);
return this._generateOptimizedOrdersAsync(marketSideLiquidity, { const optimizerResult = await this._generateOptimizedOrdersAsync(marketSideLiquidity, {
bridgeSlippage: _opts.bridgeSlippage, bridgeSlippage: _opts.bridgeSlippage,
maxFallbackSlippage: _opts.maxFallbackSlippage, maxFallbackSlippage: _opts.maxFallbackSlippage,
excludedSources: _opts.excludedSources, excludedSources: _opts.excludedSources,
feeSchedule: _opts.feeSchedule, feeSchedule: _opts.feeSchedule,
allowFallback: _opts.allowFallback, allowFallback: _opts.allowFallback,
shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders, shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders,
quoteRequestor: _opts.rfqt ? _opts.rfqt.quoteRequestor : undefined,
shouldGenerateQuoteReport: _opts.shouldGenerateQuoteReport,
}); });
let quoteReport: QuoteReport | undefined;
if (_opts.shouldGenerateQuoteReport && _opts.rfqt && _opts.rfqt.quoteRequestor) {
quoteReport = MarketOperationUtils._computeQuoteReport(
nativeOrders,
_opts.rfqt.quoteRequestor,
marketSideLiquidity,
optimizerResult,
);
}
return { ...optimizerResult, quoteReport };
} }
/** /**
@ -468,7 +506,6 @@ export class MarketOperationUtils {
feeSchedule: _opts.feeSchedule, feeSchedule: _opts.feeSchedule,
allowFallback: _opts.allowFallback, allowFallback: _opts.allowFallback,
shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders, shouldBatchBridgeOrders: _opts.shouldBatchBridgeOrders,
shouldGenerateQuoteReport: false,
}, },
); );
return optimizedOrders; return optimizedOrders;
@ -491,8 +528,6 @@ export class MarketOperationUtils {
feeSchedule?: FeeSchedule; feeSchedule?: FeeSchedule;
allowFallback?: boolean; allowFallback?: boolean;
shouldBatchBridgeOrders?: boolean; shouldBatchBridgeOrders?: boolean;
quoteRequestor?: QuoteRequestor;
shouldGenerateQuoteReport?: boolean;
}, },
): Promise<OptimizerResult> { ): Promise<OptimizerResult> {
const { const {
@ -506,7 +541,6 @@ export class MarketOperationUtils {
dexQuotes, dexQuotes,
ethToOutputRate, ethToOutputRate,
ethToInputRate, ethToInputRate,
twoHopQuotes,
} = marketSideLiquidity; } = marketSideLiquidity;
const maxFallbackSlippage = opts.maxFallbackSlippage || 0; const maxFallbackSlippage = opts.maxFallbackSlippage || 0;
@ -549,18 +583,7 @@ export class MarketOperationUtils {
); );
if (bestTwoHopQuote && bestTwoHopRate.isGreaterThan(optimalPathRate)) { if (bestTwoHopQuote && bestTwoHopRate.isGreaterThan(optimalPathRate)) {
const twoHopOrders = createOrdersFromTwoHopSample(bestTwoHopQuote, orderOpts); const twoHopOrders = createOrdersFromTwoHopSample(bestTwoHopQuote, orderOpts);
const twoHopQuoteReport = opts.shouldGenerateQuoteReport return { optimizedOrders: twoHopOrders, liquidityDelivered: bestTwoHopQuote, isTwoHop: true };
? generateQuoteReport(
side,
_.flatten(dexQuotes),
twoHopQuotes,
nativeOrders,
orderFillableAmounts,
bestTwoHopQuote,
opts.quoteRequestor,
)
: undefined;
return { optimizedOrders: twoHopOrders, quoteReport: twoHopQuoteReport, isTwoHop: true };
} }
// Generate a fallback path if native orders are in the optimal path. // Generate a fallback path if native orders are in the optimal path.
@ -591,18 +614,8 @@ export class MarketOperationUtils {
} }
} }
const optimizedOrders = createOrdersFromPath(optimalPath, orderOpts); const optimizedOrders = createOrdersFromPath(optimalPath, orderOpts);
const quoteReport = opts.shouldGenerateQuoteReport const liquidityDelivered = _.flatten(optimizedOrders.map(order => order.fills));
? generateQuoteReport( return { optimizedOrders, liquidityDelivered, isTwoHop: false };
side,
_.flatten(dexQuotes),
twoHopQuotes,
nativeOrders,
orderFillableAmounts,
_.flatten(optimizedOrders.map(order => order.fills)),
opts.quoteRequestor,
)
: undefined;
return { optimizedOrders, quoteReport, isTwoHop: false };
} }
} }

View File

@ -322,6 +322,10 @@ export interface SourceQuoteOperation<TFillData extends FillData = FillData>
export interface OptimizerResult { export interface OptimizerResult {
optimizedOrders: OptimizedMarketOrder[]; optimizedOrders: OptimizedMarketOrder[];
isTwoHop: boolean; isTwoHop: boolean;
liquidityDelivered: CollapsedFill[] | DexSample<MultiHopFillData>;
}
export interface OptimizerResultWithReport extends OptimizerResult {
quoteReport?: QuoteReport; quoteReport?: QuoteReport;
} }