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",
|
"version": "6.11.0",
|
||||||
"changes": [
|
"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",
|
"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",
|
"note": "Tweak compiler settings for smaller sampler bytecode",
|
||||||
|
@ -161,6 +161,7 @@ export {
|
|||||||
NativeRfqOrderQuoteReportEntry,
|
NativeRfqOrderQuoteReportEntry,
|
||||||
QuoteReport,
|
QuoteReport,
|
||||||
QuoteReportEntry,
|
QuoteReportEntry,
|
||||||
|
PriceComparisonsReport,
|
||||||
} from './utils/quote_report_generator';
|
} from './utils/quote_report_generator';
|
||||||
export { QuoteRequestor } from './utils/quote_requestor';
|
export { QuoteRequestor } from './utils/quote_requestor';
|
||||||
export { ERC20BridgeSamplerContract, BalanceCheckerContract, FakeTakerContract } from './wrappers';
|
export { ERC20BridgeSamplerContract, BalanceCheckerContract, FakeTakerContract } from './wrappers';
|
||||||
|
@ -495,7 +495,14 @@ function createSwapQuote(
|
|||||||
gasSchedule: FeeSchedule,
|
gasSchedule: FeeSchedule,
|
||||||
slippage: number,
|
slippage: number,
|
||||||
): SwapQuote {
|
): SwapQuote {
|
||||||
const { optimizedOrders, quoteReport, sourceFlags, takerAmountPerEth, makerAmountPerEth } = optimizerResult;
|
const {
|
||||||
|
optimizedOrders,
|
||||||
|
quoteReport,
|
||||||
|
sourceFlags,
|
||||||
|
takerAmountPerEth,
|
||||||
|
makerAmountPerEth,
|
||||||
|
priceComparisonsReport,
|
||||||
|
} = optimizerResult;
|
||||||
const isTwoHop = sourceFlags === SOURCE_FLAGS[ERC20BridgeSource.MultiHop];
|
const isTwoHop = sourceFlags === SOURCE_FLAGS[ERC20BridgeSource.MultiHop];
|
||||||
|
|
||||||
// Calculate quote info
|
// Calculate quote info
|
||||||
@ -519,6 +526,7 @@ function createSwapQuote(
|
|||||||
makerAmountPerEth,
|
makerAmountPerEth,
|
||||||
quoteReport,
|
quoteReport,
|
||||||
isTwoHop,
|
isTwoHop,
|
||||||
|
priceComparisonsReport,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (operation === MarketOperation.Buy) {
|
if (operation === MarketOperation.Buy) {
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
OptimizedMarketOrder,
|
OptimizedMarketOrder,
|
||||||
TokenAdjacencyGraph,
|
TokenAdjacencyGraph,
|
||||||
} from './utils/market_operation_utils/types';
|
} 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).
|
* 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;
|
worstCaseQuoteInfo: SwapQuoteInfo;
|
||||||
sourceBreakdown: SwapQuoteOrdersBreakdown;
|
sourceBreakdown: SwapQuoteOrdersBreakdown;
|
||||||
quoteReport?: QuoteReport;
|
quoteReport?: QuoteReport;
|
||||||
|
priceComparisonsReport?: PriceComparisonsReport;
|
||||||
isTwoHop: boolean;
|
isTwoHop: boolean;
|
||||||
makerTokenDecimals: number;
|
makerTokenDecimals: number;
|
||||||
takerTokenDecimals: 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(
|
export const UNISWAPV3_CONFIG_BY_CHAIN_ID = valueByChainId(
|
||||||
{
|
{
|
||||||
// Unconfirmed Mainnet contracts, please confirm
|
|
||||||
[ChainId.Mainnet]: {
|
[ChainId.Mainnet]: {
|
||||||
quoter: '0xb27308f9f90d607463bb33ea1bebb41c27ce5ab6',
|
quoter: '0xb27308f9f90d607463bb33ea1bebb41c27ce5ab6',
|
||||||
router: '0xe592427a0aece92de3edee1f18e0157c05861564',
|
router: '0xe592427a0aece92de3edee1f18e0157c05861564',
|
||||||
@ -1335,5 +1334,6 @@ export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = {
|
|||||||
exchangeProxyOverhead: () => ZERO_AMOUNT,
|
exchangeProxyOverhead: () => ZERO_AMOUNT,
|
||||||
allowFallback: true,
|
allowFallback: true,
|
||||||
shouldGenerateQuoteReport: true,
|
shouldGenerateQuoteReport: true,
|
||||||
|
shouldIncludePriceComparisonsReport: false,
|
||||||
tokenAdjacencyGraph: { default: [] },
|
tokenAdjacencyGraph: { default: [] },
|
||||||
};
|
};
|
||||||
|
@ -16,7 +16,14 @@ import {
|
|||||||
getNativeAdjustedMakerFillAmount,
|
getNativeAdjustedMakerFillAmount,
|
||||||
} from '../utils';
|
} 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 { getComparisonPrices } from './comparison_price';
|
||||||
import {
|
import {
|
||||||
BUY_SOURCE_FILTER_BY_CHAIN_ID,
|
BUY_SOURCE_FILTER_BY_CHAIN_ID,
|
||||||
@ -68,6 +75,27 @@ export class MarketOperationUtils {
|
|||||||
return generateQuoteReport(side, quotes.nativeOrders, liquidityDelivered, comparisonPrice, quoteRequestor);
|
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(
|
constructor(
|
||||||
private readonly _sampler: DexOrderSampler,
|
private readonly _sampler: DexOrderSampler,
|
||||||
private readonly contractAddresses: AssetSwapperContractAddresses,
|
private readonly contractAddresses: AssetSwapperContractAddresses,
|
||||||
@ -677,7 +705,16 @@ export class MarketOperationUtils {
|
|||||||
wholeOrderPrice,
|
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> {
|
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 { NativeOrderWithFillableAmounts, RfqFirmQuoteValidator, RfqRequestOpts } from '../../types';
|
||||||
import { QuoteRequestor } from '../../utils/quote_requestor';
|
import { QuoteRequestor } from '../../utils/quote_requestor';
|
||||||
import { QuoteReport } from '../quote_report_generator';
|
import { PriceComparisonsReport, QuoteReport } from '../quote_report_generator';
|
||||||
|
|
||||||
import { CollapsedPath } from './path';
|
import { CollapsedPath } from './path';
|
||||||
import { SourceFilters } from './source_filters';
|
import { SourceFilters } from './source_filters';
|
||||||
@ -401,6 +401,11 @@ export interface GetMarketOrdersOpts {
|
|||||||
* Whether to generate a quote report
|
* Whether to generate a quote report
|
||||||
*/
|
*/
|
||||||
shouldGenerateQuoteReport: boolean;
|
shouldGenerateQuoteReport: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to include price comparison data in the quote
|
||||||
|
*/
|
||||||
|
shouldIncludePriceComparisonsReport: boolean;
|
||||||
/**
|
/**
|
||||||
* Token addresses with a list of adjacent intermediary tokens to consider
|
* Token addresses with a list of adjacent intermediary tokens to consider
|
||||||
* hopping to. E.g DAI->USDC via an adjacent token WETH
|
* hopping to. E.g DAI->USDC via an adjacent token WETH
|
||||||
@ -435,6 +440,7 @@ export interface OptimizerResult {
|
|||||||
|
|
||||||
export interface OptimizerResultWithReport extends OptimizerResult {
|
export interface OptimizerResultWithReport extends OptimizerResult {
|
||||||
quoteReport?: QuoteReport;
|
quoteReport?: QuoteReport;
|
||||||
|
priceComparisonsReport?: PriceComparisonsReport;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MarketDepthSide = Array<Array<DexSample<FillData>>>;
|
export type MarketDepthSide = Array<Array<DexSample<FillData>>>;
|
||||||
|
@ -60,6 +60,12 @@ export interface QuoteReport {
|
|||||||
sourcesDelivered: QuoteReportEntry[];
|
sourcesDelivered: QuoteReportEntry[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PriceComparisonsReport {
|
||||||
|
dexSources: BridgeQuoteReportEntry[];
|
||||||
|
multiHopSources: MultiHopQuoteReportEntry[];
|
||||||
|
nativeSources: Array<NativeLimitOrderQuoteReportEntry | NativeRfqOrderQuoteReportEntry>;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a report of sources considered while computing the optimized
|
* Generates a report of sources considered while computing the optimized
|
||||||
* swap quote, and the sources ultimately included in the computed quote.
|
* swap quote, and the sources ultimately included in the computed quote.
|
||||||
@ -72,7 +78,7 @@ export function generateQuoteReport(
|
|||||||
quoteRequestor?: QuoteRequestor,
|
quoteRequestor?: QuoteRequestor,
|
||||||
): QuoteReport {
|
): QuoteReport {
|
||||||
const nativeOrderSourcesConsidered = nativeOrders.map(order =>
|
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)];
|
const sourcesConsidered = [...nativeOrderSourcesConsidered.filter(order => order.isRfqt)];
|
||||||
|
|
||||||
@ -87,7 +93,7 @@ export function generateQuoteReport(
|
|||||||
// map sources delivered
|
// map sources delivered
|
||||||
sourcesDelivered = liquidityDelivered.map(collapsedFill => {
|
sourcesDelivered = liquidityDelivered.map(collapsedFill => {
|
||||||
if (_isNativeOrderFromCollapsedFill(collapsedFill)) {
|
if (_isNativeOrderFromCollapsedFill(collapsedFill)) {
|
||||||
return _nativeOrderToReportEntry(
|
return nativeOrderToReportEntry(
|
||||||
collapsedFill.type,
|
collapsedFill.type,
|
||||||
collapsedFill.fillData,
|
collapsedFill.fillData,
|
||||||
nativeOrderSignaturesToFillableAmounts[_nativeDataToId(collapsedFill.fillData)],
|
nativeOrderSignaturesToFillableAmounts[_nativeDataToId(collapsedFill.fillData)],
|
||||||
@ -95,13 +101,13 @@ export function generateQuoteReport(
|
|||||||
quoteRequestor,
|
quoteRequestor,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return _dexSampleToReportSource(collapsedFill, marketOperation);
|
return dexSampleToReportSource(collapsedFill, marketOperation);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
sourcesDelivered = [
|
sourcesDelivered = [
|
||||||
// tslint:disable-next-line: no-unnecessary-type-assertion
|
// tslint:disable-next-line: no-unnecessary-type-assertion
|
||||||
_multiHopSampleToReportSource(liquidityDelivered as DexSample<MultiHopFillData>, marketOperation),
|
multiHopSampleToReportSource(liquidityDelivered as DexSample<MultiHopFillData>, marketOperation),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@ -115,7 +121,11 @@ function _nativeDataToId(data: { signature: Signature }): string {
|
|||||||
return `${v}${r}${s}`;
|
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;
|
const liquiditySource = ds.source;
|
||||||
|
|
||||||
if (liquiditySource === ERC20BridgeSource.Native) {
|
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>,
|
ds: DexSample<MultiHopFillData>,
|
||||||
marketOperation: MarketOperation,
|
marketOperation: MarketOperation,
|
||||||
): MultiHopQuoteReportEntry {
|
): MultiHopQuoteReportEntry {
|
||||||
@ -176,7 +190,11 @@ function _isNativeOrderFromCollapsedFill(cf: CollapsedFill): cf is NativeCollaps
|
|||||||
return type === FillQuoteTransformerOrderType.Limit || type === FillQuoteTransformerOrderType.Rfq;
|
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,
|
type: FillQuoteTransformerOrderType,
|
||||||
fillData: NativeLimitOrderFillData | NativeRfqOrderFillData,
|
fillData: NativeLimitOrderFillData | NativeRfqOrderFillData,
|
||||||
fillableAmount: BigNumber,
|
fillableAmount: BigNumber,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user