fix: add separate priceComparisonsReport to fix missing quoteReport data [TKR-91] (#219)
* fix: add separate priceComparisonsReport to fix missing quoteReport data * chore: remove notice about unconfirmed Uniswap V3 addresses * refactor: move price comparisons computation logic into separate method * chore: add AS changelog entry
This commit is contained in:
parent
7d15baad0f
commit
7d34e09a12
@ -2,9 +2,13 @@
|
||||
{
|
||||
"version": "6.11.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add price comparisons data separate from the quote report",
|
||||
"pr": 219
|
||||
},
|
||||
{
|
||||
"note": "Add caching for top Balancer V2 pools on startup and during regular intervals",
|
||||
"pr": "228"
|
||||
"pr": 228
|
||||
},
|
||||
{
|
||||
"note": "Tweak compiler settings for smaller sampler bytecode",
|
||||
|
@ -161,6 +161,7 @@ export {
|
||||
NativeRfqOrderQuoteReportEntry,
|
||||
QuoteReport,
|
||||
QuoteReportEntry,
|
||||
PriceComparisonsReport,
|
||||
} from './utils/quote_report_generator';
|
||||
export { QuoteRequestor } from './utils/quote_requestor';
|
||||
export { ERC20BridgeSamplerContract, BalanceCheckerContract, FakeTakerContract } from './wrappers';
|
||||
|
@ -495,7 +495,14 @@ function createSwapQuote(
|
||||
gasSchedule: FeeSchedule,
|
||||
slippage: number,
|
||||
): SwapQuote {
|
||||
const { optimizedOrders, quoteReport, sourceFlags, takerAmountPerEth, makerAmountPerEth } = optimizerResult;
|
||||
const {
|
||||
optimizedOrders,
|
||||
quoteReport,
|
||||
sourceFlags,
|
||||
takerAmountPerEth,
|
||||
makerAmountPerEth,
|
||||
priceComparisonsReport,
|
||||
} = optimizerResult;
|
||||
const isTwoHop = sourceFlags === SOURCE_FLAGS[ERC20BridgeSource.MultiHop];
|
||||
|
||||
// Calculate quote info
|
||||
@ -519,6 +526,7 @@ function createSwapQuote(
|
||||
makerAmountPerEth,
|
||||
quoteReport,
|
||||
isTwoHop,
|
||||
priceComparisonsReport,
|
||||
};
|
||||
|
||||
if (operation === MarketOperation.Buy) {
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
OptimizedMarketOrder,
|
||||
TokenAdjacencyGraph,
|
||||
} from './utils/market_operation_utils/types';
|
||||
import { QuoteReport } from './utils/quote_report_generator';
|
||||
import { PriceComparisonsReport, QuoteReport } from './utils/quote_report_generator';
|
||||
|
||||
/**
|
||||
* expiryBufferMs: The number of seconds to add when calculating whether an order is expired or not. Defaults to 300s (5m).
|
||||
@ -169,6 +169,7 @@ export interface SwapQuoteBase {
|
||||
worstCaseQuoteInfo: SwapQuoteInfo;
|
||||
sourceBreakdown: SwapQuoteOrdersBreakdown;
|
||||
quoteReport?: QuoteReport;
|
||||
priceComparisonsReport?: PriceComparisonsReport;
|
||||
isTwoHop: boolean;
|
||||
makerTokenDecimals: number;
|
||||
takerTokenDecimals: number;
|
||||
|
@ -1059,7 +1059,6 @@ export const BALANCER_V2_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name
|
||||
|
||||
export const UNISWAPV3_CONFIG_BY_CHAIN_ID = valueByChainId(
|
||||
{
|
||||
// Unconfirmed Mainnet contracts, please confirm
|
||||
[ChainId.Mainnet]: {
|
||||
quoter: '0xb27308f9f90d607463bb33ea1bebb41c27ce5ab6',
|
||||
router: '0xe592427a0aece92de3edee1f18e0157c05861564',
|
||||
@ -1335,5 +1334,6 @@ export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = {
|
||||
exchangeProxyOverhead: () => ZERO_AMOUNT,
|
||||
allowFallback: true,
|
||||
shouldGenerateQuoteReport: true,
|
||||
shouldIncludePriceComparisonsReport: false,
|
||||
tokenAdjacencyGraph: { default: [] },
|
||||
};
|
||||
|
@ -16,7 +16,14 @@ import {
|
||||
getNativeAdjustedMakerFillAmount,
|
||||
} from '../utils';
|
||||
|
||||
import { generateQuoteReport, QuoteReport } from './../quote_report_generator';
|
||||
import {
|
||||
dexSampleToReportSource,
|
||||
generateQuoteReport,
|
||||
multiHopSampleToReportSource,
|
||||
nativeOrderToReportEntry,
|
||||
PriceComparisonsReport,
|
||||
QuoteReport,
|
||||
} from './../quote_report_generator';
|
||||
import { getComparisonPrices } from './comparison_price';
|
||||
import {
|
||||
BUY_SOURCE_FILTER_BY_CHAIN_ID,
|
||||
@ -68,6 +75,27 @@ export class MarketOperationUtils {
|
||||
return generateQuoteReport(side, quotes.nativeOrders, liquidityDelivered, comparisonPrice, quoteRequestor);
|
||||
}
|
||||
|
||||
private static _computePriceComparisonsReport(
|
||||
quoteRequestor: QuoteRequestor | undefined,
|
||||
marketSideLiquidity: MarketSideLiquidity,
|
||||
comparisonPrice?: BigNumber | undefined,
|
||||
): PriceComparisonsReport {
|
||||
const { side, quotes } = marketSideLiquidity;
|
||||
const dexSources = _.flatten(quotes.dexQuotes).map(quote => dexSampleToReportSource(quote, side));
|
||||
const multiHopSources = quotes.twoHopQuotes.map(quote => multiHopSampleToReportSource(quote, side));
|
||||
const nativeSources = quotes.nativeOrders.map(order =>
|
||||
nativeOrderToReportEntry(
|
||||
order.type,
|
||||
order as any,
|
||||
order.fillableTakerAmount,
|
||||
comparisonPrice,
|
||||
quoteRequestor,
|
||||
),
|
||||
);
|
||||
|
||||
return { dexSources, multiHopSources, nativeSources };
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly _sampler: DexOrderSampler,
|
||||
private readonly contractAddresses: AssetSwapperContractAddresses,
|
||||
@ -677,7 +705,16 @@ export class MarketOperationUtils {
|
||||
wholeOrderPrice,
|
||||
);
|
||||
}
|
||||
return { ...optimizerResult, quoteReport };
|
||||
|
||||
let priceComparisonsReport: PriceComparisonsReport | undefined;
|
||||
if (_opts.shouldIncludePriceComparisonsReport) {
|
||||
priceComparisonsReport = MarketOperationUtils._computePriceComparisonsReport(
|
||||
_opts.rfqt ? _opts.rfqt.quoteRequestor : undefined,
|
||||
marketSideLiquidity,
|
||||
wholeOrderPrice,
|
||||
);
|
||||
}
|
||||
return { ...optimizerResult, quoteReport, priceComparisonsReport };
|
||||
}
|
||||
|
||||
private async _refreshPoolCacheIfRequiredAsync(takerToken: string, makerToken: string): Promise<void> {
|
||||
|
@ -9,7 +9,7 @@ import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { NativeOrderWithFillableAmounts, RfqFirmQuoteValidator, RfqRequestOpts } from '../../types';
|
||||
import { QuoteRequestor } from '../../utils/quote_requestor';
|
||||
import { QuoteReport } from '../quote_report_generator';
|
||||
import { PriceComparisonsReport, QuoteReport } from '../quote_report_generator';
|
||||
|
||||
import { CollapsedPath } from './path';
|
||||
import { SourceFilters } from './source_filters';
|
||||
@ -401,6 +401,11 @@ export interface GetMarketOrdersOpts {
|
||||
* Whether to generate a quote report
|
||||
*/
|
||||
shouldGenerateQuoteReport: boolean;
|
||||
|
||||
/**
|
||||
* Whether to include price comparison data in the quote
|
||||
*/
|
||||
shouldIncludePriceComparisonsReport: boolean;
|
||||
/**
|
||||
* Token addresses with a list of adjacent intermediary tokens to consider
|
||||
* hopping to. E.g DAI->USDC via an adjacent token WETH
|
||||
@ -435,6 +440,7 @@ export interface OptimizerResult {
|
||||
|
||||
export interface OptimizerResultWithReport extends OptimizerResult {
|
||||
quoteReport?: QuoteReport;
|
||||
priceComparisonsReport?: PriceComparisonsReport;
|
||||
}
|
||||
|
||||
export type MarketDepthSide = Array<Array<DexSample<FillData>>>;
|
||||
|
@ -60,6 +60,12 @@ export interface QuoteReport {
|
||||
sourcesDelivered: QuoteReportEntry[];
|
||||
}
|
||||
|
||||
export interface PriceComparisonsReport {
|
||||
dexSources: BridgeQuoteReportEntry[];
|
||||
multiHopSources: MultiHopQuoteReportEntry[];
|
||||
nativeSources: Array<NativeLimitOrderQuoteReportEntry | NativeRfqOrderQuoteReportEntry>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a report of sources considered while computing the optimized
|
||||
* swap quote, and the sources ultimately included in the computed quote.
|
||||
@ -72,7 +78,7 @@ export function generateQuoteReport(
|
||||
quoteRequestor?: QuoteRequestor,
|
||||
): QuoteReport {
|
||||
const nativeOrderSourcesConsidered = nativeOrders.map(order =>
|
||||
_nativeOrderToReportEntry(order.type, order as any, order.fillableTakerAmount, comparisonPrice, quoteRequestor),
|
||||
nativeOrderToReportEntry(order.type, order as any, order.fillableTakerAmount, comparisonPrice, quoteRequestor),
|
||||
);
|
||||
const sourcesConsidered = [...nativeOrderSourcesConsidered.filter(order => order.isRfqt)];
|
||||
|
||||
@ -87,7 +93,7 @@ export function generateQuoteReport(
|
||||
// map sources delivered
|
||||
sourcesDelivered = liquidityDelivered.map(collapsedFill => {
|
||||
if (_isNativeOrderFromCollapsedFill(collapsedFill)) {
|
||||
return _nativeOrderToReportEntry(
|
||||
return nativeOrderToReportEntry(
|
||||
collapsedFill.type,
|
||||
collapsedFill.fillData,
|
||||
nativeOrderSignaturesToFillableAmounts[_nativeDataToId(collapsedFill.fillData)],
|
||||
@ -95,13 +101,13 @@ export function generateQuoteReport(
|
||||
quoteRequestor,
|
||||
);
|
||||
} else {
|
||||
return _dexSampleToReportSource(collapsedFill, marketOperation);
|
||||
return dexSampleToReportSource(collapsedFill, marketOperation);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
sourcesDelivered = [
|
||||
// tslint:disable-next-line: no-unnecessary-type-assertion
|
||||
_multiHopSampleToReportSource(liquidityDelivered as DexSample<MultiHopFillData>, marketOperation),
|
||||
multiHopSampleToReportSource(liquidityDelivered as DexSample<MultiHopFillData>, marketOperation),
|
||||
];
|
||||
}
|
||||
return {
|
||||
@ -115,7 +121,11 @@ function _nativeDataToId(data: { signature: Signature }): string {
|
||||
return `${v}${r}${s}`;
|
||||
}
|
||||
|
||||
function _dexSampleToReportSource(ds: DexSample, marketOperation: MarketOperation): BridgeQuoteReportEntry {
|
||||
/**
|
||||
* Generates a report sample for a DEX source
|
||||
* NOTE: this is used for the QuoteReport and quote price comparison data
|
||||
*/
|
||||
export function dexSampleToReportSource(ds: DexSample, marketOperation: MarketOperation): BridgeQuoteReportEntry {
|
||||
const liquiditySource = ds.source;
|
||||
|
||||
if (liquiditySource === ERC20BridgeSource.Native) {
|
||||
@ -143,7 +153,11 @@ function _dexSampleToReportSource(ds: DexSample, marketOperation: MarketOperatio
|
||||
}
|
||||
}
|
||||
|
||||
function _multiHopSampleToReportSource(
|
||||
/**
|
||||
* Generates a report sample for a MultiHop source
|
||||
* NOTE: this is used for the QuoteReport and quote price comparison data
|
||||
*/
|
||||
export function multiHopSampleToReportSource(
|
||||
ds: DexSample<MultiHopFillData>,
|
||||
marketOperation: MarketOperation,
|
||||
): MultiHopQuoteReportEntry {
|
||||
@ -176,7 +190,11 @@ function _isNativeOrderFromCollapsedFill(cf: CollapsedFill): cf is NativeCollaps
|
||||
return type === FillQuoteTransformerOrderType.Limit || type === FillQuoteTransformerOrderType.Rfq;
|
||||
}
|
||||
|
||||
function _nativeOrderToReportEntry(
|
||||
/**
|
||||
* Generates a report entry for a native order
|
||||
* NOTE: this is used for the QuoteReport and quote price comparison data
|
||||
*/
|
||||
export function nativeOrderToReportEntry(
|
||||
type: FillQuoteTransformerOrderType,
|
||||
fillData: NativeLimitOrderFillData | NativeRfqOrderFillData,
|
||||
fillableAmount: BigNumber,
|
||||
|
Loading…
x
Reference in New Issue
Block a user