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 7943657d13..f0fe469633 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts @@ -661,6 +661,6 @@ export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = { gasSchedule: DEFAULT_GAS_SCHEDULE, exchangeProxyOverhead: () => ZERO_AMOUNT, allowFallback: true, - shouldGenerateQuoteReport: false, + shouldGenerateQuoteReport: true, tokenAdjacencyGraph: { default: [] }, }; 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 c9a473e6ed..b6edbbfd77 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/index.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/index.ts @@ -62,17 +62,8 @@ export class MarketOperationUtils { comparisonPrice?: BigNumber | undefined, ): QuoteReport { const { side, quotes } = marketSideLiquidity; - const { dexQuotes, twoHopQuotes, nativeOrders } = quotes; const { liquidityDelivered } = optimizerResult; - return generateQuoteReport( - side, - _.flatten(dexQuotes), - twoHopQuotes, - nativeOrders, - liquidityDelivered, - comparisonPrice, - quoteRequestor, - ); + return generateQuoteReport(side, quotes.nativeOrders, liquidityDelivered, comparisonPrice, quoteRequestor); } constructor( diff --git a/packages/asset-swapper/src/utils/quote_report_generator.ts b/packages/asset-swapper/src/utils/quote_report_generator.ts index 44b7532cc4..cd756a922e 100644 --- a/packages/asset-swapper/src/utils/quote_report_generator.ts +++ b/packages/asset-swapper/src/utils/quote_report_generator.ts @@ -1,4 +1,4 @@ -import { FillQuoteTransformerOrderType, Signature } from '@0x/protocol-utils'; +import { FillQuoteTransformerOrderType, RfqOrderFields, Signature } from '@0x/protocol-utils'; import { BigNumber } from '@0x/utils'; import _ = require('lodash'); @@ -44,6 +44,7 @@ export interface NativeRfqOrderQuoteReportEntry extends QuoteReportEntryBase { fillData: NativeFillData; fillableTakerAmount: BigNumber; isRfqt: true; + nativeOrder: RfqOrderFields; makerUri: string; comparisonPrice?: number; } @@ -65,25 +66,15 @@ export interface QuoteReport { */ export function generateQuoteReport( marketOperation: MarketOperation, - dexQuotes: DexSample[], - multiHopQuotes: Array>, nativeOrders: NativeOrderWithFillableAmounts[], liquidityDelivered: ReadonlyArray | DexSample, comparisonPrice?: BigNumber | undefined, quoteRequestor?: QuoteRequestor, ): QuoteReport { - const dexReportSourcesConsidered = dexQuotes.map(quote => _dexSampleToReportSource(quote, marketOperation)); const nativeOrderSourcesConsidered = nativeOrders.map(order => _nativeOrderToReportEntry(order.type, order as any, order.fillableTakerAmount, comparisonPrice, quoteRequestor), ); - const multiHopSourcesConsidered = multiHopQuotes.map(quote => - _multiHopSampleToReportSource(quote, marketOperation), - ); - const sourcesConsidered = [ - ...dexReportSourcesConsidered, - ...nativeOrderSourcesConsidered, - ...multiHopSourcesConsidered, - ]; + const sourcesConsidered = [...nativeOrderSourcesConsidered.filter(order => order.isRfqt)]; let sourcesDelivered; if (Array.isArray(liquidityDelivered)) { @@ -193,7 +184,6 @@ function _nativeOrderToReportEntry( quoteRequestor?: QuoteRequestor, ): NativeRfqOrderQuoteReportEntry | NativeLimitOrderQuoteReportEntry { const nativeOrderBase = { - liquiditySource: ERC20BridgeSource.Native, makerAmount: fillData.order.makerAmount, takerAmount: fillData.order.takerAmount, fillableTakerAmount: fillableAmount, @@ -201,23 +191,28 @@ function _nativeOrderToReportEntry( // if we find this is an rfqt order, label it as such and associate makerUri const isRfqt = type === FillQuoteTransformerOrderType.Rfq; - const rfqtMakerUri = isRfqt ? quoteRequestor!.getMakerUriForSignature(fillData.signature) : undefined; + const rfqtMakerUri = + isRfqt && quoteRequestor ? quoteRequestor.getMakerUriForSignature(fillData.signature) : undefined; if (isRfqt) { + const nativeOrder = fillData.order as RfqOrderFields; // tslint:disable-next-line: no-object-literal-type-assertion return { + liquiditySource: ERC20BridgeSource.Native, ...nativeOrderBase, isRfqt: true, makerUri: rfqtMakerUri || '', ...(comparisonPrice ? { comparisonPrice: comparisonPrice.toNumber() } : {}), + nativeOrder, fillData, - } as NativeRfqOrderQuoteReportEntry; + }; } else { // tslint:disable-next-line: no-object-literal-type-assertion return { + liquiditySource: ERC20BridgeSource.Native, ...nativeOrderBase, isRfqt: false, fillData, - } as NativeLimitOrderQuoteReportEntry; + }; } } diff --git a/packages/asset-swapper/test/market_operation_utils_test.ts b/packages/asset-swapper/test/market_operation_utils_test.ts index 43c9d42315..68c6da073f 100644 --- a/packages/asset-swapper/test/market_operation_utils_test.ts +++ b/packages/asset-swapper/test/market_operation_utils_test.ts @@ -127,6 +127,9 @@ describe('MarketOperationUtils tests', () => { TypeMoq.It.isAny(), ]; const requestor = TypeMoq.Mock.ofType(QuoteRequestor, TypeMoq.MockBehavior.Loose, true); + requestor + .setup(mqr => mqr.getMakerUriForSignature(TypeMoq.It.isValue(SIGNATURE))) + .returns(() => 'https://foo.bar'); if (type === 'firm') { requestor .setup(r => r.requestRfqtFirmQuotesAsync(...args)) @@ -696,6 +699,9 @@ describe('MarketOperationUtils tests', () => { const feeSchedule = { [ERC20BridgeSource.Native]: _.constant(new BigNumber(1)), }; + mockedQuoteRequestor + .setup(mqr => mqr.getMakerUriForSignature(TypeMoq.It.isValue(SIGNATURE))) + .returns(() => 'https://foo.bar'); mockedQuoteRequestor .setup(mqr => mqr.requestRfqtFirmQuotesAsync( @@ -799,6 +805,7 @@ describe('MarketOperationUtils tests', () => { intentOnFilling: true, quoteRequestor: { requestRfqtFirmQuotesAsync: mockedQuoteRequestor.object.requestRfqtFirmQuotesAsync, + getMakerUriForSignature: mockedQuoteRequestor.object.getMakerUriForSignature, } as any, }, }, diff --git a/packages/asset-swapper/test/quote_report_generator_test.ts b/packages/asset-swapper/test/quote_report_generator_test.ts index d0e5e0758f..dcd67dab5f 100644 --- a/packages/asset-swapper/test/quote_report_generator_test.ts +++ b/packages/asset-swapper/test/quote_report_generator_test.ts @@ -58,32 +58,18 @@ describe('generateQuoteReport', async () => { it('should generate report properly for sell', () => { const marketOperation: MarketOperation = MarketOperation.Sell; - const kyberSample1: DexSample = { - source: ERC20BridgeSource.Kyber, - input: new BigNumber(10000), - output: new BigNumber(10001), - fillData: {}, - }; const kyberSample2: DexSample = { source: ERC20BridgeSource.Kyber, input: new BigNumber(10003), output: new BigNumber(10004), fillData: {}, }; - const uniswapSample1: DexSample = { - source: ERC20BridgeSource.UniswapV2, - input: new BigNumber(10003), - output: new BigNumber(10004), - fillData: {}, - }; const uniswapSample2: DexSample = { source: ERC20BridgeSource.UniswapV2, input: new BigNumber(10005), output: new BigNumber(10006), fillData: {}, }; - const dexQuotes: DexSample[] = [kyberSample1, kyberSample2, uniswapSample1, uniswapSample2]; - const orderbookOrder1: NativeOrderWithFillableAmounts = { order: new LimitOrder({ takerAmount: new BigNumber(1000) }), type: FillQuoteTransformerOrderType.Limit, @@ -158,8 +144,6 @@ describe('generateQuoteReport', async () => { const orderReport = generateQuoteReport( marketOperation, - dexQuotes, - [], nativeOrders, pathGenerated, undefined, @@ -173,6 +157,7 @@ describe('generateQuoteReport', async () => { fillableTakerAmount: rfqtOrder1.fillableTakerAmount, isRfqt: true, makerUri: 'https://rfqt1.provider.club', + nativeOrder: rfqtOrder1.order, fillData: { order: rfqtOrder1.order, } as NativeRfqOrderFillData, @@ -184,20 +169,11 @@ describe('generateQuoteReport', async () => { fillableTakerAmount: rfqtOrder2.fillableTakerAmount, isRfqt: true, makerUri: 'https://rfqt2.provider.club', + nativeOrder: rfqtOrder2.order, fillData: { order: rfqtOrder2.order, } as NativeRfqOrderFillData, }; - const orderbookOrder1Source: NativeLimitOrderQuoteReportEntry = { - liquiditySource: ERC20BridgeSource.Native, - makerAmount: orderbookOrder1.order.makerAmount, - takerAmount: orderbookOrder1.order.takerAmount, - fillableTakerAmount: orderbookOrder1.fillableTakerAmount, - isRfqt: false, - fillData: { - order: orderbookOrder1.order, - } as NativeLimitOrderFillData, - }; const orderbookOrder2Source: NativeLimitOrderQuoteReportEntry = { liquiditySource: ERC20BridgeSource.Native, makerAmount: orderbookOrder2.order.makerAmount, @@ -208,24 +184,12 @@ describe('generateQuoteReport', async () => { order: orderbookOrder2.order, } as NativeLimitOrderFillData, }; - const uniswap1Source: BridgeQuoteReportEntry = { - liquiditySource: ERC20BridgeSource.UniswapV2, - makerAmount: uniswapSample1.output, - takerAmount: uniswapSample1.input, - fillData: {}, - }; const uniswap2Source: BridgeQuoteReportEntry = { liquiditySource: ERC20BridgeSource.UniswapV2, makerAmount: uniswapSample2.output, takerAmount: uniswapSample2.input, fillData: {}, }; - const kyber1Source: BridgeQuoteReportEntry = { - liquiditySource: ERC20BridgeSource.Kyber, - makerAmount: kyberSample1.output, - takerAmount: kyberSample1.input, - fillData: {}, - }; const kyber2Source: BridgeQuoteReportEntry = { liquiditySource: ERC20BridgeSource.Kyber, makerAmount: kyberSample2.output, @@ -233,16 +197,7 @@ describe('generateQuoteReport', async () => { fillData: {}, }; - const expectedSourcesConsidered: QuoteReportEntry[] = [ - kyber1Source, - kyber2Source, - uniswap1Source, - uniswap2Source, - orderbookOrder1Source, - rfqtOrder1Source, - rfqtOrder2Source, - orderbookOrder2Source, - ]; + const expectedSourcesConsidered: QuoteReportEntry[] = [rfqtOrder1Source, rfqtOrder2Source]; const expectedSourcesDelivered: QuoteReportEntry[] = [ rfqtOrder2Source, orderbookOrder2Source, @@ -267,7 +222,6 @@ describe('generateQuoteReport', async () => { output: new BigNumber(10004), fillData: {}, }; - const dexQuotes: DexSample[] = [kyberSample1, uniswapSample1]; const orderbookOrder1: NativeOrderWithFillableAmounts = { order: new LimitOrder({ takerAmount: new BigNumber(1101) }), type: FillQuoteTransformerOrderType.Limit, @@ -302,7 +256,7 @@ describe('generateQuoteReport', async () => { }; const pathGenerated: CollapsedFill[] = [orderbookOrder1Fill, uniswap1Fill, kyber1Fill]; - const orderReport = generateQuoteReport(marketOperation, dexQuotes, [], nativeOrders, pathGenerated); + const orderReport = generateQuoteReport(marketOperation, nativeOrders, pathGenerated); const orderbookOrder1Source: NativeLimitOrderQuoteReportEntry = { liquiditySource: ERC20BridgeSource.Native, @@ -314,16 +268,6 @@ describe('generateQuoteReport', async () => { order: orderbookOrder1.order, } as NativeLimitOrderFillData, }; - const orderbookOrder2Source: NativeLimitOrderQuoteReportEntry = { - liquiditySource: ERC20BridgeSource.Native, - makerAmount: orderbookOrder2.order.makerAmount, - takerAmount: orderbookOrder2.order.takerAmount, - fillableTakerAmount: orderbookOrder2.fillableTakerAmount, - isRfqt: false, - fillData: { - order: orderbookOrder2.order, - } as NativeLimitOrderFillData, - }; const uniswap1Source: BridgeQuoteReportEntry = { liquiditySource: ERC20BridgeSource.UniswapV2, makerAmount: uniswapSample1.input, @@ -337,24 +281,14 @@ describe('generateQuoteReport', async () => { fillData: {}, }; - const expectedSourcesConsidered: QuoteReportEntry[] = [ - kyber1Source, - uniswap1Source, - orderbookOrder1Source, - orderbookOrder2Source, - ]; + // No order is considered here because only Native RFQ orders are considered. + const expectedSourcesConsidered: QuoteReportEntry[] = []; const expectedSourcesDelivered: QuoteReportEntry[] = [orderbookOrder1Source, uniswap1Source, kyber1Source]; expectEqualQuoteReportEntries(orderReport.sourcesConsidered, expectedSourcesConsidered, `sourcesConsidered`); expectEqualQuoteReportEntries(orderReport.sourcesDelivered, expectedSourcesDelivered, `sourcesDelivered`); }); it('should correctly generate report for a two-hop quote', () => { const marketOperation: MarketOperation = MarketOperation.Sell; - const kyberSample1: DexSample = { - source: ERC20BridgeSource.Kyber, - input: new BigNumber(10000), - output: new BigNumber(10001), - fillData: {}, - }; const orderbookOrder1: NativeOrderWithFillableAmounts = { order: new LimitOrder({ takerAmount: new BigNumber(1101) }), type: FillQuoteTransformerOrderType.Limit, @@ -387,29 +321,7 @@ describe('generateQuoteReport', async () => { fillData: twoHopFillData, }; - const orderReport = generateQuoteReport( - marketOperation, - [kyberSample1], - [twoHopSample], - [orderbookOrder1], - twoHopSample, - ); - const orderbookOrder1Source: NativeLimitOrderQuoteReportEntry = { - liquiditySource: ERC20BridgeSource.Native, - makerAmount: orderbookOrder1.order.makerAmount, - takerAmount: orderbookOrder1.order.takerAmount, - fillableTakerAmount: orderbookOrder1.fillableTakerAmount, - isRfqt: false, - fillData: { - order: orderbookOrder1.order, - } as NativeLimitOrderFillData, - }; - const kyber1Source: BridgeQuoteReportEntry = { - liquiditySource: ERC20BridgeSource.Kyber, - makerAmount: kyberSample1.output, - takerAmount: kyberSample1.input, - fillData: {}, - }; + const orderReport = generateQuoteReport(marketOperation, [orderbookOrder1], twoHopSample); const twoHopSource: MultiHopQuoteReportEntry = { liquiditySource: ERC20BridgeSource.MultiHop, makerAmount: twoHopSample.output, @@ -418,7 +330,8 @@ describe('generateQuoteReport', async () => { fillData: twoHopFillData, }; - const expectedSourcesConsidered: QuoteReportEntry[] = [kyber1Source, orderbookOrder1Source, twoHopSource]; + // No entry is present in considered because No RFQ orders were reported. + const expectedSourcesConsidered: QuoteReportEntry[] = []; expectEqualQuoteReportEntries(orderReport.sourcesConsidered, expectedSourcesConsidered, `sourcesConsidered`); expect(orderReport.sourcesDelivered.length).to.eql(1); expect(orderReport.sourcesDelivered[0]).to.deep.equal(twoHopSource);