From df055e1958af4f462209a0e1760b3364747efbff Mon Sep 17 00:00:00 2001 From: Daniel Pyrathon Date: Tue, 11 May 2021 12:57:51 -0400 Subject: [PATCH] fix: Added fee parameter to Quote Requestor (#235) * Added changes * Fixes * Applied PR feedback * lint fix --- packages/asset-swapper/package.json | 2 +- packages/asset-swapper/src/index.ts | 7 +++- packages/asset-swapper/src/types.ts | 12 +++++-- .../src/utils/alt_mm_implementation_utils.ts | 4 +-- .../src/utils/quote_requestor.ts | 30 ++++++++++++---- .../test/quote_requestor_test.ts | 34 ++++++++++++++----- yarn.lock | 13 +++---- 7 files changed, 75 insertions(+), 27 deletions(-) diff --git a/packages/asset-swapper/package.json b/packages/asset-swapper/package.json index 4e9c1ff55b..9b280513e5 100644 --- a/packages/asset-swapper/package.json +++ b/packages/asset-swapper/package.json @@ -67,7 +67,7 @@ "@0x/dev-utils": "^4.2.7", "@0x/json-schemas": "^6.1.3", "@0x/protocol-utils": "^1.6.0", - "@0x/quote-server": "^5.0.0", + "@0x/quote-server": "^6.0.2", "@0x/types": "^3.3.3", "@0x/typescript-typings": "^5.2.0", "@0x/utils": "^6.4.3", diff --git a/packages/asset-swapper/src/index.ts b/packages/asset-swapper/src/index.ts index 1c137ab622..b1dd502edb 100644 --- a/packages/asset-swapper/src/index.ts +++ b/packages/asset-swapper/src/index.ts @@ -5,7 +5,12 @@ export { SendTransactionOpts, } from '@0x/base-contract'; export { ContractAddresses } from '@0x/contract-addresses'; -export { V4RFQFirmQuote, V4RFQIndicativeQuote, V4SignedRfqOrder, TakerRequestQueryParams } from '@0x/quote-server'; +export { + V4RFQFirmQuote, + V4RFQIndicativeQuote, + V4SignedRfqOrder, + TakerRequestQueryParamsUnnested as TakerRequestQueryParams, +} from '@0x/quote-server'; export { Asset, AssetPairsItem, DecodedLogEvent, EventCallback, IndexedFilterValues } from '@0x/types'; export { BigNumber } from '@0x/utils'; export { diff --git a/packages/asset-swapper/src/types.ts b/packages/asset-swapper/src/types.ts index 6563d9ee38..4221c03028 100644 --- a/packages/asset-swapper/src/types.ts +++ b/packages/asset-swapper/src/types.ts @@ -7,7 +7,8 @@ import { RfqOrderFields, Signature, } from '@0x/protocol-utils'; -import { TakerRequestQueryParams, V4SignedRfqOrder } from '@0x/quote-server'; +import { TakerRequestQueryParamsUnnested, V4SignedRfqOrder } from '@0x/quote-server'; +import { Fee } from '@0x/quote-server/lib/src/types'; import { BigNumber } from '@0x/utils'; import { AxiosRequestConfig } from 'axios'; @@ -232,6 +233,12 @@ export type SwapQuoteOrdersBreakdown = Partial< * If set to `true` and `ERC20BridgeSource.Native` is part of the `excludedSources` * array in `SwapQuoteRequestOpts`, an Error will be raised. */ + +export interface RfqmRequestOptions extends RfqRequestOpts { + isLastLook: true; + fee: Fee; +} + export interface RfqRequestOpts { takerAddress: string; txOrigin: string; @@ -242,6 +249,7 @@ export interface RfqRequestOpts { nativeExclusivelyRFQ?: boolean; altRfqAssetOfferings?: AltRfqMakerAssetOfferings; isLastLook?: boolean; + fee?: Fee; } /** @@ -366,7 +374,7 @@ export enum OrderPrunerPermittedFeeTypes { export interface MockedRfqQuoteResponse { endpoint: string; requestApiKey: string; - requestParams: TakerRequestQueryParams; + requestParams: TakerRequestQueryParamsUnnested; responseData: any; responseCode: number; callback?: (config: any) => Promise; diff --git a/packages/asset-swapper/src/utils/alt_mm_implementation_utils.ts b/packages/asset-swapper/src/utils/alt_mm_implementation_utils.ts index b5806cf659..0a8fc5c4f9 100644 --- a/packages/asset-swapper/src/utils/alt_mm_implementation_utils.ts +++ b/packages/asset-swapper/src/utils/alt_mm_implementation_utils.ts @@ -1,5 +1,5 @@ import { Web3Wrapper } from '@0x/dev-utils'; -import { TakerRequestQueryParams, V4RFQFirmQuote, V4RFQIndicativeQuote } from '@0x/quote-server'; +import { TakerRequestQueryParamsUnnested, V4RFQFirmQuote, V4RFQIndicativeQuote } from '@0x/quote-server'; import { BigNumber } from '@0x/utils'; import { AxiosInstance, CancelToken } from 'axios'; @@ -123,7 +123,7 @@ export async function returnQuoteFromAltMMAsync( takerToken: string, maxResponseTimeMs: number, altRfqAssetOfferings: AltRfqMakerAssetOfferings, - takerRequestQueryParams: TakerRequestQueryParams, + takerRequestQueryParams: TakerRequestQueryParamsUnnested, axiosInstance: AxiosInstance, warningLogger: LogFunction, cancelToken: CancelToken, diff --git a/packages/asset-swapper/src/utils/quote_requestor.ts b/packages/asset-swapper/src/utils/quote_requestor.ts index 6a6b0fd4eb..bbdb773431 100644 --- a/packages/asset-swapper/src/utils/quote_requestor.ts +++ b/packages/asset-swapper/src/utils/quote_requestor.ts @@ -1,6 +1,12 @@ import { schemas, SchemaValidator } from '@0x/json-schemas'; import { FillQuoteTransformerOrderType, Signature } from '@0x/protocol-utils'; -import { TakerRequestQueryParams, V4RFQFirmQuote, V4RFQIndicativeQuote, V4SignedRfqOrder } from '@0x/quote-server'; +import { + TakerRequestQueryParamsUnnested, + V4RFQFirmQuote, + V4RFQIndicativeQuote, + V4SignedRfqOrder, +} from '@0x/quote-server'; +import { Fee } from '@0x/quote-server/lib/src/types'; import { BigNumber, NULL_ADDRESS } from '@0x/utils'; import axios, { AxiosInstance } from 'axios'; @@ -11,6 +17,7 @@ import { LogFunction, MarketOperation, RfqMakerAssetOfferings, + RfqmRequestOptions, RfqPairType, RfqRequestOpts, SignedNativeOrder, @@ -84,7 +91,8 @@ export class QuoteRequestor { assetFillAmount: BigNumber, comparisonPrice?: BigNumber, isLastLook?: boolean | undefined, - ): TakerRequestQueryParams { + fee?: Fee | undefined, + ): TakerRequestQueryParamsUnnested { const { buyAmountBaseUnits, sellAmountBaseUnits } = marketOperation === MarketOperation.Buy ? { @@ -97,7 +105,7 @@ export class QuoteRequestor { }; const requestParamsWithBigNumbers: Pick< - TakerRequestQueryParams, + TakerRequestQueryParamsUnnested, | 'txOrigin' | 'takerAddress' | 'buyTokenAddress' @@ -105,6 +113,9 @@ export class QuoteRequestor { | 'comparisonPrice' | 'isLastLook' | 'protocolVersion' + | 'feeAmount' + | 'feeToken' + | 'feeType' > = { txOrigin, takerAddress, @@ -114,7 +125,13 @@ export class QuoteRequestor { protocolVersion: '4', }; if (isLastLook) { + if (fee === undefined) { + throw new Error(`isLastLook cannot be passed without a fee parameter`); + } requestParamsWithBigNumbers.isLastLook = isLastLook.toString(); + requestParamsWithBigNumbers.feeAmount = fee.amount.toString(); + requestParamsWithBigNumbers.feeToken = fee.token; + requestParamsWithBigNumbers.feeType = fee.type; } // convert BigNumbers to strings @@ -181,12 +198,11 @@ export class QuoteRequestor { assetFillAmount: BigNumber, marketOperation: MarketOperation, comparisonPrice: BigNumber | undefined, - options: RfqRequestOpts, + options: RfqmRequestOptions, ): Promise { const _opts: RfqRequestOpts = { ...constants.DEFAULT_RFQT_REQUEST_OPTS, ...options, - isLastLook: true, }; return this._fetchAndValidateFirmQuotesAsync( @@ -230,12 +246,11 @@ export class QuoteRequestor { assetFillAmount: BigNumber, marketOperation: MarketOperation, comparisonPrice: BigNumber | undefined, - options: RfqRequestOpts, + options: RfqmRequestOptions, ): Promise { const _opts: RfqRequestOpts = { ...constants.DEFAULT_RFQT_REQUEST_OPTS, ...options, - isLastLook: true, }; return this._fetchAndValidateIndicativeQuotesAsync( @@ -344,6 +359,7 @@ export class QuoteRequestor { assetFillAmount, comparisonPrice, options.isLastLook, + options.fee, ); const quotePath = (() => { diff --git a/packages/asset-swapper/test/quote_requestor_test.ts b/packages/asset-swapper/test/quote_requestor_test.ts index 46a8677d9b..f473eb42d8 100644 --- a/packages/asset-swapper/test/quote_requestor_test.ts +++ b/packages/asset-swapper/test/quote_requestor_test.ts @@ -1,6 +1,6 @@ import { tokenUtils } from '@0x/dev-utils'; -import { FillQuoteTransformerOrderType, SignatureType } from '@0x/protocol-utils'; -import { TakerRequestQueryParams, V4RFQIndicativeQuote } from '@0x/quote-server'; +import { ETH_TOKEN_ADDRESS, FillQuoteTransformerOrderType, SignatureType } from '@0x/protocol-utils'; +import { TakerRequestQueryParamsUnnested, V4RFQIndicativeQuote } from '@0x/quote-server'; import { StatusCodes } from '@0x/types'; import { BigNumber, logUtils } from '@0x/utils'; import Axios from 'axios'; @@ -75,7 +75,7 @@ describe('QuoteRequestor', async () => { const mockedRequests: MockedRfqQuoteResponse[] = []; const altMockedRequests: AltMockedRfqQuoteResponse[] = []; - const expectedParams: TakerRequestQueryParams = { + const expectedParams: TakerRequestQueryParamsUnnested = { sellTokenAddress: takerToken, buyTokenAddress: makerToken, sellAmountBaseUnits: '10000', @@ -84,6 +84,9 @@ describe('QuoteRequestor', async () => { txOrigin, isLastLook: 'true', // the major difference between RFQ-T and RFQ-M protocolVersion: '4', + feeAmount: '1000000000', + feeToken: ETH_TOKEN_ADDRESS, + feeType: 'fixed', }; const mockedDefaults = { requestApiKey: apiKey, @@ -242,6 +245,12 @@ describe('QuoteRequestor', async () => { txOrigin: takerAddress, intentOnFilling: true, altRfqAssetOfferings, + isLastLook: true, + fee: { + amount: new BigNumber('1000000000'), + token: ETH_TOKEN_ADDRESS, + type: 'fixed', + }, }, ); expect(resp).to.deep.eq([ @@ -265,7 +274,7 @@ describe('QuoteRequestor', async () => { const mockedRequests: MockedRfqQuoteResponse[] = []; const altMockedRequests: AltMockedRfqQuoteResponse[] = []; - const expectedParams: TakerRequestQueryParams = { + const expectedParams: TakerRequestQueryParamsUnnested = { sellTokenAddress: takerToken, buyTokenAddress: makerToken, sellAmountBaseUnits: '10000', @@ -451,7 +460,7 @@ describe('QuoteRequestor', async () => { // Set up RFQ responses // tslint:disable-next-line:array-type const mockedRequests: MockedRfqQuoteResponse[] = []; - const expectedParams: TakerRequestQueryParams = { + const expectedParams: TakerRequestQueryParamsUnnested = { sellTokenAddress: takerToken, buyTokenAddress: makerToken, sellAmountBaseUnits: '10000', @@ -460,6 +469,9 @@ describe('QuoteRequestor', async () => { txOrigin: takerAddress, isLastLook: 'true', // the major difference between RFQ-T and RFQ-M protocolVersion: '4', + feeAmount: '1000000000', + feeToken: ETH_TOKEN_ADDRESS, + feeType: 'fixed', }; const mockedDefaults = { requestApiKey: apiKey, @@ -543,6 +555,12 @@ describe('QuoteRequestor', async () => { takerAddress, txOrigin: takerAddress, intentOnFilling: true, + isLastLook: true, + fee: { + type: 'fixed', + token: ETH_TOKEN_ADDRESS, + amount: new BigNumber('1000000000'), + }, }, ); expect(resp.sort()).to.eql([successfulQuote1, successfulQuote1].sort()); @@ -571,7 +589,7 @@ describe('QuoteRequestor', async () => { // Set up RFQT responses // tslint:disable-next-line:array-type const mockedRequests: MockedRfqQuoteResponse[] = []; - const expectedParams: TakerRequestQueryParams = { + const expectedParams: TakerRequestQueryParamsUnnested = { sellTokenAddress: takerToken, buyTokenAddress: makerToken, sellAmountBaseUnits: '10000', @@ -678,7 +696,7 @@ describe('QuoteRequestor', async () => { // Set up RFQT responses // tslint:disable-next-line:array-type const mockedRequests: MockedRfqQuoteResponse[] = []; - const expectedParams: TakerRequestQueryParams = { + const expectedParams: TakerRequestQueryParamsUnnested = { sellTokenAddress: takerToken, buyTokenAddress: makerToken, sellAmountBaseUnits: '10000', @@ -763,7 +781,7 @@ describe('QuoteRequestor', async () => { // Set up RFQT responses // tslint:disable-next-line:array-type const mockedRequests: MockedRfqQuoteResponse[] = []; - const expectedParams: TakerRequestQueryParams = { + const expectedParams: TakerRequestQueryParamsUnnested = { sellTokenAddress: takerToken, buyTokenAddress: makerToken, buyAmountBaseUnits: '10000', diff --git a/yarn.lock b/yarn.lock index de4fc972d3..c24ebdd949 100644 --- a/yarn.lock +++ b/yarn.lock @@ -783,7 +783,7 @@ lodash "^4.17.11" web3-provider-engine "14.0.6" -"@0x/json-schemas@^5.0.1", "@0x/json-schemas@^5.0.7", "@0x/json-schemas@^5.3.3": +"@0x/json-schemas@^5.0.1", "@0x/json-schemas@^5.3.3": version "5.3.3" resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-5.3.3.tgz#4b9de100385ca23b0cd58a454165df2e9758e453" dependencies: @@ -801,7 +801,7 @@ jsonschema "^1.2.0" lodash.values "^4.3.0" -"@0x/json-schemas@^6.1.3": +"@0x/json-schemas@^6.0.1", "@0x/json-schemas@^6.1.3": version "6.1.3" resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-6.1.3.tgz#da71ed2e50ae6813a6d4d0fe5f8ad69b8e6a7435" dependencies: @@ -850,11 +850,12 @@ typedoc "~0.16.11" yargs "^10.0.3" -"@0x/quote-server@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@0x/quote-server/-/quote-server-5.0.0.tgz#15554099bdfdf71e2910430860257d622f24f703" +"@0x/quote-server@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@0x/quote-server/-/quote-server-6.0.2.tgz#cb99e00c737e0f97a2a32bc7e7be6db65243c3af" + integrity sha512-SS5LfAgKSRjEszWVZl5UtRDBkrsqAvYn/lPB4hxtKky8XitClUYFQ2pSnrFuyQSVft3tFxH4p7eC65YQN5wkcA== dependencies: - "@0x/json-schemas" "^5.0.7" + "@0x/json-schemas" "^6.0.1" "@0x/order-utils" "^10.2.4" "@0x/protocol-utils" "^1.0.1" "@0x/utils" "^5.4.1"