diff --git a/packages/asset-swapper/src/constants.ts b/packages/asset-swapper/src/constants.ts index f54b81470d..e68c605930 100644 --- a/packages/asset-swapper/src/constants.ts +++ b/packages/asset-swapper/src/constants.ts @@ -1,9 +1,10 @@ -import { BigNumber } from '@0x/utils'; +import { BigNumber, logUtils } from '@0x/utils'; import { ExchangeProxyContractOpts, ExtensionContractType, ForwarderExtensionContractOpts, + LogFunction, OrderPrunerOpts, OrderPrunerPermittedFeeTypes, RfqtRequestOpts, @@ -89,6 +90,11 @@ const DEFAULT_RFQT_REQUEST_OPTS: Partial = { makerEndpointMaxResponseTimeMs: 1000, }; +export const DEFAULT_INFO_LOGGER: LogFunction = (obj, msg) => + logUtils.log(`${msg ? `${msg}: ` : ''}${JSON.stringify(obj)}`); +export const DEFAULT_WARNING_LOGGER: LogFunction = (obj, msg) => + logUtils.warn(`${msg ? `${msg}: ` : ''}${JSON.stringify(obj)}`); + export const constants = { ETH_GAS_STATION_API_URL, PROTOCOL_FEE_MULTIPLIER, @@ -113,4 +119,6 @@ export const constants = { PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS, MARKET_UTILS_AMOUNT_BUFFER_PERCENTAGE, BRIDGE_ASSET_DATA_PREFIX: '0xdc1600f3', + DEFAULT_INFO_LOGGER, + DEFAULT_WARNING_LOGGER, }; diff --git a/packages/asset-swapper/src/types.ts b/packages/asset-swapper/src/types.ts index 6ec4357215..3cb701481f 100644 --- a/packages/asset-swapper/src/types.ts +++ b/packages/asset-swapper/src/types.ts @@ -9,7 +9,6 @@ import { TokenAdjacencyGraph, } from './utils/market_operation_utils/types'; import { QuoteReport } from './utils/quote_report_generator'; -import { LogFunction } from './utils/quote_requestor'; /** * expiryBufferMs: The number of seconds to add when calculating whether an order is expired or not. Defaults to 300s (5m). @@ -273,7 +272,7 @@ export interface RfqtMakerAssetOfferings { [endpoint: string]: Array<[string, string]>; } -export { LogFunction } from './utils/quote_requestor'; +export type LogFunction = (obj: object, msg?: string, ...args: any[]) => void; export interface SwapQuoterRfqtOpts { takerApiKeyWhitelist: string[]; diff --git a/packages/asset-swapper/src/utils/quote_requestor.ts b/packages/asset-swapper/src/utils/quote_requestor.ts index cd34d0d07a..ea889e5ebd 100644 --- a/packages/asset-swapper/src/utils/quote_requestor.ts +++ b/packages/asset-swapper/src/utils/quote_requestor.ts @@ -2,13 +2,13 @@ import { schemas, SchemaValidator } from '@0x/json-schemas'; import { assetDataUtils, orderCalculationUtils, SignedOrder } from '@0x/order-utils'; import { RFQTFirmQuote, RFQTIndicativeQuote, TakerRequest } from '@0x/quote-server'; import { ERC20AssetData } from '@0x/types'; -import { BigNumber, logUtils } from '@0x/utils'; +import { BigNumber } from '@0x/utils'; import Axios, { AxiosInstance } from 'axios'; import { Agent as HttpAgent } from 'http'; import { Agent as HttpsAgent } from 'https'; import { constants } from '../constants'; -import { MarketOperation, RfqtMakerAssetOfferings, RfqtRequestOpts } from '../types'; +import { LogFunction, MarketOperation, RfqtMakerAssetOfferings, RfqtRequestOpts } from '../types'; import { ONE_SECOND_MS } from './market_operation_utils/constants'; import { RfqMakerBlacklist } from './rfq_maker_blacklist'; @@ -107,20 +107,18 @@ function convertIfAxiosError(error: any): Error | object /* axios' .d.ts has Axi } } -export type LogFunction = (obj: object, msg?: string, ...args: any[]) => void; - export class QuoteRequestor { private readonly _schemaValidator: SchemaValidator = new SchemaValidator(); private readonly _orderSignatureToMakerUri: { [orderSignature: string]: string } = {}; constructor( private readonly _rfqtAssetOfferings: RfqtMakerAssetOfferings, - private readonly _warningLogger: LogFunction = (obj, msg) => - logUtils.warn(`${msg ? `${msg}: ` : ''}${JSON.stringify(obj)}`), - private readonly _infoLogger: LogFunction = (obj, msg) => - logUtils.log(`${msg ? `${msg}: ` : ''}${JSON.stringify(obj)}`), + private readonly _warningLogger: LogFunction = constants.DEFAULT_WARNING_LOGGER, + private readonly _infoLogger: LogFunction = constants.DEFAULT_INFO_LOGGER, private readonly _expiryBufferMs: number = constants.DEFAULT_SWAP_QUOTER_OPTS.expiryBufferMs, - ) {} + ) { + rfqMakerBlacklist.infoLogger = this._infoLogger; + } public async requestRfqtFirmQuotesAsync( makerAssetData: string, @@ -395,7 +393,7 @@ export class QuoteRequestor { }, }, }); - rfqMakerBlacklist.logTimeoutOrLackThereof(url, latencyMs > maxResponseTimeMs); + rfqMakerBlacklist.logTimeoutOrLackThereof(url, latencyMs >= maxResponseTimeMs); result.push({ response: response.data, makerUri: url }); } catch (err) { const latencyMs = Date.now() - timeBeforeAwait; @@ -411,7 +409,7 @@ export class QuoteRequestor { }, }, }); - rfqMakerBlacklist.logTimeoutOrLackThereof(url, latencyMs > maxResponseTimeMs); + rfqMakerBlacklist.logTimeoutOrLackThereof(url, latencyMs >= maxResponseTimeMs); this._warningLogger( convertIfAxiosError(err), `Failed to get RFQ-T ${quoteType} quote from market maker endpoint ${url} for API key ${ diff --git a/packages/asset-swapper/src/utils/rfq_maker_blacklist.ts b/packages/asset-swapper/src/utils/rfq_maker_blacklist.ts index b261b116e0..8cfdf4c2b6 100644 --- a/packages/asset-swapper/src/utils/rfq_maker_blacklist.ts +++ b/packages/asset-swapper/src/utils/rfq_maker_blacklist.ts @@ -4,11 +4,16 @@ */ import { constants } from '../constants'; +import { LogFunction } from '../types'; export class RfqMakerBlacklist { private readonly _makerTimeoutStreakLength: { [makerUrl: string]: number } = {}; private readonly _makerBlacklistedUntilDate: { [makerUrl: string]: number } = {}; - constructor(private readonly _blacklistDurationMinutes: number, private readonly _timeoutStreakThreshold: number) {} + constructor( + private readonly _blacklistDurationMinutes: number, + private readonly _timeoutStreakThreshold: number, + public infoLogger: LogFunction = constants.DEFAULT_INFO_LOGGER, + ) {} public logTimeoutOrLackThereof(makerUrl: string, didTimeout: boolean): void { if (!this._makerTimeoutStreakLength.hasOwnProperty(makerUrl)) { this._makerTimeoutStreakLength[makerUrl] = 0; @@ -16,8 +21,12 @@ export class RfqMakerBlacklist { if (didTimeout) { this._makerTimeoutStreakLength[makerUrl] += 1; if (this._makerTimeoutStreakLength[makerUrl] === this._timeoutStreakThreshold) { - this._makerBlacklistedUntilDate[makerUrl] = - Date.now() + this._blacklistDurationMinutes * constants.ONE_MINUTE_MS; + const blacklistEnd = Date.now() + this._blacklistDurationMinutes * constants.ONE_MINUTE_MS; + this._makerBlacklistedUntilDate[makerUrl] = blacklistEnd; + this.infoLogger( + { makerUrl, blacklistedUntil: new Date(blacklistEnd).toISOString() }, + 'maker blacklisted', + ); } } else { this._makerTimeoutStreakLength[makerUrl] = 0; @@ -27,6 +36,7 @@ export class RfqMakerBlacklist { const now = Date.now(); if (now > this._makerBlacklistedUntilDate[makerUrl]) { delete this._makerBlacklistedUntilDate[makerUrl]; + this.infoLogger({ makerUrl }, 'maker unblacklisted'); } return this._makerBlacklistedUntilDate[makerUrl] > now; }