import { assert } from '@0x/assert' ; import { BlockParamLiteral , DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID , ERC20BridgeSource , LiquidityProviderRegistry , OrderPrunerPermittedFeeTypes , RfqMakerAssetOfferings , SamplerOverrides , SOURCE_FLAGS , SwapQuoteRequestOpts , SwapQuoterOpts , SwapQuoterRfqOpts , } from '@0x/asset-swapper' ; import { ChainId } from '@0x/contract-addresses' ; import { nativeWrappedTokenSymbol , TokenMetadatasForChains , valueByChainId } from '@0x/token-metadata' ; import { BigNumber } from '@0x/utils' ; import * as fs from 'fs' ; import * as _ from 'lodash' ; import * as validateUUID from 'uuid-validate' ; import { DEFAULT_ETH_GAS_STATION_API_URL , DEFAULT_EXPECTED_MINED_SEC , DEFAULT_FALLBACK_SLIPPAGE_PERCENTAGE , DEFAULT_LOCAL_POSTGRES_URI , DEFAULT_LOCAL_REDIS_URI , DEFAULT_LOGGER_INCLUDE_TIMESTAMP , DEFAULT_QUOTE_SLIPPAGE_PERCENTAGE , HEALTHCHECK_PATH , METRICS_PATH , NULL_ADDRESS , ONE_MINUTE_MS , ORDERBOOK_PATH , QUOTE_ORDER_EXPIRATION_BUFFER_MS , TX_BASE_GAS , } from './constants' ; import { schemas } from './schemas' ; import { HttpServiceConfig , MetaTransactionRateLimitConfig } from './types' ; import { parseUtils } from './utils/parse_utils' ; import { schemaUtils } from './utils/schema_utils' ; const SHOULD_USE_RUST_ROUTER = process . env . RUST_ROUTER === 'true' ; enum EnvVarType { AddressList , StringList , Integer , Port , KeepAliveTimeout , ChainId , ETHAddressHex , UnitAmount , Url , UrlList , WhitelistAllTokens , Boolean , NonEmptyString , APIKeys , PrivateKeys , RfqMakerAssetOfferings , RateLimitConfig , LiquidityProviderRegistry , JsonStringList } /**
 * A taker-integrator of the 0x API.
 */ export interface Integrator { apiKeys : string [ ] ; integratorId : string ; whitelistIntegratorUrls ? : string [ ] ; label : string ; plp : boolean ; rfqm : boolean ; rfqt : boolean ; } export type IntegratorsAcl = Integrator [ ] ; /**
 * Configuration which represents taker-integrators of the 0x API. The configuration contains the label, id,
 * api keys, and allowed liquidity sources for each integrator.
 */ export const INTEGRATORS_ACL = ( ( ) => { let integrators ; try { integrators = resolveEnvVar < IntegratorsAcl > ( 'INTEGRATORS_ACL' , EnvVarType . JsonStringList , [ ] ) ; schemaUtils . validateSchema ( integrators , schemas . integratorsAclSchema ) ; } catch ( e ) { throw new Error ( `INTEGRATORS_ACL was defined but is not valid JSON per the schema: ${ e }` ) ; } return integrators ; } ) ( ) ; /**
 * Extracts the integrator API keys from the `INTEGRATORS_ACL` environment variable for the provided group type.
 */ export const getApiKeyWhitelistFromIntegratorsAcl = ( groupType ) : string [ ] => { return INTEGRATORS_ACL . filter ( ( i ) => i [ groupType ] ) . flatMap ( ( i ) => i . apiKeys ) . sort ( ) ; } ; /**
 * Gets the integrator ID for the provided label.
 */ export const getIntegratorIdFromLabel = ( label ) : string | undefined => { for ( const integrator of INTEGRATORS_ACL ) { if ( integrator . label === label ) { return integrator . integratorId ; } } } ; export type RfqWorkFlowType = 'rfqt' | 'rfqm' ; export type RfqOrderType = 'rfq' | 'otc' ; export const RFQ_WORKFLOW = 'rfqt' ; export const RFQ_PAIR_REFRESH_INTERVAL_MS = ONE_MINUTE_MS * 1 ; /**
 * The JSON config for each Market Maker, providing information including URIs, type of order supported and authentication.
 */ export interface RfqMakerConfig { makerId : string ; label : string ; rfqmMakerUri : string ; rfqmOrderTypes : RfqOrderType [ ] ; rfqtMakerUri : string ; rfqtOrderTypes : RfqOrderType [ ] ; apiKeyHashes : string [ ] ; } /**
 * A Map type which map the makerId to the config object.
 */ export type MakerIdsToConfigs = Map < string , RfqMakerConfig > ; /**
 * Generate a map from MakerId to MakerConfig that support a given order type for a given workflow
 */ export const getMakerConfigMapForOrderType = ( orderType , workflow ) : MakerIdsToConfigs => { const typesField = workflow === 'rfqt' ? 'rfqtOrderTypes' : 'rfqmOrderTypes' ; return RFQ_MAKER_CONFIGS . reduce ( ( acc , curr ) => { if ( orderType === 'any' || curr [ typesField ] . includes ( orderType ) ) { acc . set ( curr . makerId , curr ) ; } return acc ; } , new Map < string , RfqMakerConfig > ( ) ) ; } ; /**
 * A list of type RfqMakerConfig, read from the RFQ_MAKER_CONFIGS env variable
 */ export const RFQ_MAKER_CONFIGS = ( ( ) => { try { const makerConfigs = resolveEnvVar < RfqMakerConfig [ ] > ( 'RFQ_MAKER_CONFIGS' , EnvVarType . JsonStringList , [ ] ) ; schemaUtils . validateSchema ( makerConfigs , schemas . rfqMakerConfigListSchema ) ; return makerConfigs ; } catch ( e ) { throw new Error ( `RFQ_MAKER_CONFIGS was defined but is not valid JSON per the schema: ${ e }` ) ; } } ) ( ) ; export const LOG_LEVEL = _ . isEmpty ( process . env . LOG_LEVEL ) ? 'info' : assertEnvVarType ( 'LOG_LEVEL' , process . env . LOG_LEVEL , EnvVarType . NonEmptyString ) ; export const HTTP_PORT = _ . isEmpty ( process . env . HTTP_PORT ) ? 3000 : assertEnvVarType ( 'HTTP_PORT' , process . env . HTTP_PORT , EnvVarType . Port ) ; export const HEALTHCHECK_HTTP_PORT = _ . isEmpty ( process . env . HEALTHCHECK_HTTP_PORT ) ? HTTP_PORT : assertEnvVarType ( 'HEALTHCHECK_HTTP_PORT' , process . env . HEALTHCHECK_HTTP_PORT , EnvVarType . Port ) ; export const HTTP_KEEP_ALIVE_TIMEOUT = _ . isEmpty ( process . env . HTTP_KEEP_ALIVE_TIMEOUT ) ? 76 * 1000 : assertEnvVarType ( 'HTTP_KEEP_ALIVE_TIMEOUT' , process . env . HTTP_KEEP_ALIVE_TIMEOUT , EnvVarType . KeepAliveTimeout ) ; export const HTTP_HEADERS_TIMEOUT = _ . isEmpty ( process . env . HTTP_HEADERS_TIMEOUT ) ? 77 * 1000 : assertEnvVarType ( 'HTTP_HEADERS_TIMEOUT' , process . env . HTTP_HEADERS_TIMEOUT , EnvVarType . KeepAliveTimeout ) ; export const CHAIN_ID = _ . isEmpty ( process . env . CHAIN_ID ) ? ChainId . Kovan : assertEnvVarType ( 'CHAIN_ID' , process . env . CHAIN_ID , EnvVarType . ChainId ) ; export const WHITELISTED_TOKENS = _ . isEmpty ( process . env . WHITELIST_ALL_TOKENS ) ? TokenMetadatasForChains . map ( ( tm ) => tm . tokenAddresses [ CHAIN_ID ] ) : assertEnvVarType ( 'WHITELIST_ALL_TOKENS' , process . env . WHITELIST_ALL_TOKENS , EnvVarType . WhitelistAllTokens ) ; export const SWAP_IGNORED_ADDRESSES = _ . isEmpty ( process . env . SWAP_IGNORED_ADDRESSES ) ? [ ] : assertEnvVarType ( 'SWAP_IGNORED_ADDRESSES' , process . env . SWAP_IGNORED_ADDRESSES , EnvVarType . AddressList ) ; export const DB_ORDERS_UPDATE_CHUNK_SIZE = 300 ; export const ETHEREUM_RPC_URL = assertEnvVarType ( 'ETHEREUM_RPC_URL' , process . env . ETHEREUM_RPC_URL , EnvVarType . UrlList ) ; export const RPC_REQUEST_TIMEOUT = _ . isEmpty ( process . env . RPC_REQUEST_TIMEOUT ) ? 5000 : assertEnvVarType ( 'RPC_REQUEST_TIMEOUT' , process . env . RPC_REQUEST_TIMEOUT , EnvVarType . Integer ) ; export const ENABLE_RPC_REQUEST_COMPRESSION = _ . isEmpty ( process . env . ENABLE_RPC_REQUEST_COMPRESSION ) ? false : assertEnvVarType ( 'ENABLE_RPC_REQUEST_COMPRESSION' , process . env . ENABLE_RPC_REQUEST_COMPRESSION , EnvVarType . Boolean ) ; export const ORDER_WATCHER_URL = _ . isEmpty ( process . env . ORDER_WATCHER_URL ) ? 'http://127.0.0.1:8080' : assertEnvVarType ( 'ORDER_WATCHER_URL' , process . env . ORDER_WATCHER_URL , EnvVarType . Url ) ; export const ORDER_WATCHER_KAFKA_TOPIC = _ . isEmpty ( process . env . ORDER_WATCHER_KAFKA_TOPIC ) ? 'order_watcher_events' : assertEnvVarType ( 'ORDER_WATCHER_KAFKA_TOPIC' , process . env . ORDER_WATCHER_KAFKA_TOPIC , EnvVarType . NonEmptyString ) ; export const KAFKA_BROKERS = _ . isEmpty ( process . env . KAFKA_BROKERS ) ? undefined : assertEnvVarType ( 'KAFKA_BROKERS' , process . env . KAFKA_BROKERS , EnvVarType . StringList ) ; export const KAFKA_CONSUMER_GROUP_ID = _ . isEmpty ( process . env . KAFKA_CONSUMER_GROUP_ID ) ? undefined : assertEnvVarType ( 'KAFKA_CONSUMER_GROUP_ID' , process . env . KAFKA_CONSUMER_GROUP_ID , EnvVarType . NonEmptyString ) ; export const WEBSOCKET_ORDER_UPDATES_PATH = _ . isEmpty ( process . env . WEBSOCKET_ORDER_UPDATES_PATH ) ? ORDERBOOK_PATH : assertEnvVarType ( 'WEBSOCKET_ORDER_UPDATES_PATH' , process . env . WEBSOCKET_ORDER_UPDATES_PATH , EnvVarType . NonEmptyString ) ; export const FEE_RECIPIENT_ADDRESS = _ . isEmpty ( process . env . FEE_RECIPIENT_ADDRESS ) ? NULL_ADDRESS : assertEnvVarType ( 'FEE_RECIPIENT_ADDRESS' , process . env . FEE_RECIPIENT_ADDRESS , EnvVarType . ETHAddressHex ) ; export const TAKER_FEE_UNIT_AMOUNT = _ . isEmpty ( process . env . TAKER_FEE_UNIT_AMOUNT ) ? new BigNumber ( 0 ) : assertEnvVarType ( 'TAKER_FEE_UNIT_AMOUNT' , process . env . TAKER_FEE_UNIT_AMOUNT , EnvVarType . UnitAmount ) ; export const MAX_ORDER_EXPIRATION_BUFFER_SECONDS = _ . isEmpty ( process . env . MAX_ORDER_EXPIRATION_BUFFER_SECONDS ) ? 3 * 60 : assertEnvVarType ( 'MAX_ORDER_EXPIRATION_BUFFER_SECONDS' , process . env . MAX_ORDER_EXPIRATION_BUFFER_SECONDS , EnvVarType . KeepAliveTimeout ) ; export const SRA_ORDER_EXPIRATION_BUFFER_SECONDS = _ . isEmpty ( process . env . SRA_ORDER_EXPIRATION_BUFFER_SECONDS ) ? 10 : assertEnvVarType ( 'SRA_ORDER_EXPIRATION_BUFFER_SECONDS' , process . env . SRA_ORDER_EXPIRATION_BUFFER_SECONDS , EnvVarType . KeepAliveTimeout ) ; export const POSTGRES_URI = _ . isEmpty ( process . env . POSTGRES_URI ) ? DEFAULT_LOCAL_POSTGRES_URI : assertEnvVarType ( 'POSTGRES_URI' , process . env . POSTGRES_URI , EnvVarType . Url ) ; export const POSTGRES_READ_REPLICA_URIS = _ . isEmpty ( process . env . POSTGRES_READ_REPLICA_URIS ) ? undefined : assertEnvVarType ( 'POSTGRES_READ_REPLICA_URIS' , process . env . POSTGRES_READ_REPLICA_URIS , EnvVarType . UrlList ) ; export const REDIS_URI = _ . isEmpty ( process . env . REDIS_URI ) ? DEFAULT_LOCAL_REDIS_URI : process . env . REDIS_URI ; export const LOGGER_INCLUDE_TIMESTAMP = _ . isEmpty ( process . env . LOGGER_INCLUDE_TIMESTAMP ) ? DEFAULT_LOGGER_INCLUDE_TIMESTAMP : assertEnvVarType ( 'LOGGER_INCLUDE_TIMESTAMP' , process . env . LOGGER_INCLUDE_TIMESTAMP , EnvVarType . Boolean ) ; export const LIQUIDITY_PROVIDER_REGISTRY = _ . isEmpty ( process . env . LIQUIDITY_PROVIDER_REGISTRY ) ? { } : assertEnvVarType ( 'LIQUIDITY_PROVIDER_REGISTRY' , process . env . LIQUIDITY_PROVIDER_REGISTRY , EnvVarType . LiquidityProviderRegistry ) ; export const RFQT_REGISTRY_PASSWORDS = resolveEnvVar < string [ ] > ( 'RFQT_REGISTRY_PASSWORDS' , EnvVarType . JsonStringList , [ ] ) ; export const RFQT_INTEGRATORS = INTEGRATORS_ACL . filter ( ( i ) => i . rfqt ) ; export const RFQT_INTEGRATOR_IDS = INTEGRATORS_ACL . filter ( ( i ) => i . rfqt ) . map ( ( i ) => i . integratorId ) ; export const RFQT_API_KEY_WHITELIST = getApiKeyWhitelistFromIntegratorsAcl ( 'rfqt' ) ; export const RFQM_API_KEY_WHITELIST = new Set ( getApiKeyWhitelistFromIntegratorsAcl ( 'rfqm' ) ) ; export const PLP_API_KEY_WHITELIST = getApiKeyWhitelistFromIntegratorsAcl ( 'plp' ) ; export const RFQT_MAKER_CONFIG_MAP_FOR_RFQ_ORDER = getMakerConfigMapForOrderType ( 'rfq' , 'rfqt' ) ; export const MATCHA_INTEGRATOR_ID = getIntegratorIdFromLabel ( 'Matcha' ) ; export const RFQT_TX_ORIGIN_BLACKLIST = new Set ( resolveEnvVar < string [ ] > ( 'RFQT_TX_ORIGIN_BLACKLIST' , EnvVarType . JsonStringList , [ ] ) . map ( ( addr ) => addr . toLowerCase ( ) ) ) ; export const ALT_RFQ_MM_ENDPOINT = _ . isEmpty ( process . env . ALT_RFQ_MM_ENDPOINT ) ? undefined : assertEnvVarType ( 'ALT_RFQ_MM_ENDPOINT' , process . env . ALT_RFQ_MM_ENDPOINT , EnvVarType . Url ) ; export const ALT_RFQ_MM_API_KEY = _ . isEmpty ( process . env . ALT_RFQ_MM_API_KEY ) ? undefined : assertEnvVarType ( 'ALT_RFQ_MM_API_KEY' , process . env . ALT_RFQ_MM_API_KEY , EnvVarType . NonEmptyString ) ; export const ALT_RFQ_MM_PROFILE = _ . isEmpty ( process . env . ALT_RFQ_MM_PROFILE ) ? undefined : assertEnvVarType ( 'ALT_RFQ_MM_PROFILE' , process . env . ALT_RFQ_MM_PROFILE , EnvVarType . NonEmptyString ) ; export const RFQT_MAKER_ASSET_OFFERINGS = resolveEnvVar < RfqMakerAssetOfferings > ( 'RFQT_MAKER_ASSET_OFFERINGS' , EnvVarType . RfqMakerAssetOfferings , { } ) ; export const RFQM_MAKER_ASSET_OFFERINGS = resolveEnvVar < RfqMakerAssetOfferings > ( 'RFQM_MAKER_ASSET_OFFERINGS' , EnvVarType . RfqMakerAssetOfferings , { } ) ; export const META_TX_WORKER_REGISTRY = _ . isEmpty ( process . env . META_TX_WORKER_REGISTRY ) ? undefined : assertEnvVarType ( 'META_TX_WORKER_REGISTRY' , process . env . META_TX_WORKER_REGISTRY , EnvVarType . ETHAddressHex ) ; export const META_TX_WORKER_MNEMONIC = _ . isEmpty ( process . env . META_TX_WORKER_MNEMONIC ) ? undefined : assertEnvVarType ( 'META_TX_WORKER_MNEMONIC' , process . env . META_TX_WORKER_MNEMONIC , EnvVarType . NonEmptyString ) ; export const RFQM_WORKER_INDEX = _ . isEmpty ( process . env . RFQM_WORKER_INDEX ) ? undefined : assertEnvVarType ( 'RFQM_WORKER_INDEX' , process . env . RFQM_WORKER_INDEX , EnvVarType . Integer ) ; export const RFQM_META_TX_SQS_URL = _ . isEmpty ( process . env . RFQM_META_TX_SQS_URL ) ? undefined : assertEnvVarType ( 'RFQM_META_TX_SQS_URL' , process . env . RFQM_META_TX_SQS_URL , EnvVarType . Url ) ; export const RFQM_MAINTENANCE_MODE = _ . isEmpty ( process . env . RFQM_MAINTENANCE_MODE ) ? false : assertEnvVarType ( 'RFQM_MAINTENANCE_MODE' , process . env . RFQM_MAINTENANCE_MODE , EnvVarType . Boolean ) ; export const RFQT_REQUEST_MAX_RESPONSE_MS = 600 ; export const SRA_PERSISTENT_ORDER_POSTING_WHITELISTED_API_KEYS = process . env . SRA_PERSISTENT_ORDER_POSTING_WHITELISTED_API_KEYS === undefined ? [ ] : assertEnvVarType ( 'SRA_PERSISTENT_ORDER_POSTING_WHITELISTED_API_KEYS' , process . env . SRA_PERSISTENT_ORDER_POSTING_WHITELISTED_API_KEYS , EnvVarType . APIKeys ) ; export const META_TXN_SUBMIT_WHITELISTED_API_KEYS = process . env . META_TXN_SUBMIT_WHITELISTED_API_KEYS === undefined ? [ ] : assertEnvVarType ( 'META_TXN_SUBMIT_WHITELISTED_API_KEYS' , process . env . META_TXN_SUBMIT_WHITELISTED_API_KEYS , EnvVarType . APIKeys ) ; export const META_TXN_RELAY_PRIVATE_KEYS = _ . isEmpty ( process . env . META_TXN_RELAY_PRIVATE_KEYS ) ? [ ] : assertEnvVarType ( 'META_TXN_RELAY_PRIVATE_KEYS' , process . env . META_TXN_RELAY_PRIVATE_KEYS , EnvVarType . StringList ) ; export const META_TXN_RELAY_EXPECTED_MINED_SEC = _ . isEmpty ( process . env . META_TXN_RELAY_EXPECTED_MINED_SEC ) ? DEFAULT_EXPECTED_MINED_SEC : assertEnvVarType ( 'META_TXN_RELAY_EXPECTED_MINED_SEC' , process . env . META_TXN_RELAY_EXPECTED_MINED_SEC , EnvVarType . Integer ) ; export const META_TXN_SIGNING_ENABLED = _ . isEmpty ( process . env . META_TXN_SIGNING_ENABLED ) ? true : assertEnvVarType ( 'META_TXN_SIGNING_ENABLED' , process . env . META_TXN_SIGNING_ENABLED , EnvVarType . Boolean ) ; export const META_TXN_MAX_GAS_PRICE_GWEI = _ . isEmpty ( process . env . META_TXN_MAX_GAS_PRICE_GWEI ) ? new BigNumber ( 50 ) : assertEnvVarType ( 'META_TXN_MAX_GAS_PRICE_GWEI' , process . env . META_TXN_MAX_GAS_PRICE_GWEI , EnvVarType . UnitAmount ) ; export const META_TXN_RATE_LIMITER_CONFIG = _ . isEmpty ( process . env . META_TXN_RATE_LIMIT_TYPE ) ? undefined : assertEnvVarType ( 'META_TXN_RATE_LIMITER_CONFIG' , process . env . META_TXN_RATE_LIMITER_CONFIG , EnvVarType . RateLimitConfig ) ; export const ENABLE_PROMETHEUS_METRICS = _ . isEmpty ( process . env . ENABLE_PROMETHEUS_METRICS ) ? false : assertEnvVarType ( 'ENABLE_PROMETHEUS_METRICS' , process . env . ENABLE_PROMETHEUS_METRICS , EnvVarType . Boolean ) ; export const PROMETHEUS_PORT = _ . isEmpty ( process . env . PROMETHEUS_PORT ) ? 8080 : assertEnvVarType ( 'PROMETHEUS_PORT' , process . env . PROMETHEUS_PORT , EnvVarType . Port ) ; export const ETH_GAS_STATION_API_URL = _ . isEmpty ( process . env . ETH_GAS_STATION_API_URL ) ? DEFAULT_ETH_GAS_STATION_API_URL : assertEnvVarType ( 'ETH_GAS_STATION_API_URL' , process . env . ETH_GAS_STATION_API_URL , EnvVarType . Url ) ; export const RFQ_PROXY_ADDRESS = _ . isEmpty ( process . env . RFQ_PROXY_ADDRESS ) ? undefined : assertEnvVarType ( 'RFQ_PROXY_ADDRESS' , process . env . RFQ_PROXY_ADDRESS , EnvVarType . NonEmptyString ) ; export const RFQ_PROXY_PORT = _ . isEmpty ( process . env . RFQ_PROXY_PORT ) ? undefined : assertEnvVarType ( 'RFQ_PROXY_PORT' , process . env . RFQ_PROXY_PORT , EnvVarType . Port ) ; export const KAFKA_TOPIC_QUOTE_REPORT = _ . isEmpty ( process . env . KAFKA_TOPIC_QUOTE_REPORT ) ? undefined : assertEnvVarType ( 'KAFKA_TOPIC_QUOTE_REPORT' , process . env . KAFKA_TOPIC_QUOTE_REPORT , EnvVarType . NonEmptyString ) ; export const MAX_PER_PAGE = 1000 ; export const DEFAULT_ERC20_TOKEN_PRECISION = 18 ; export const PROTOCOL_FEE_MULTIPLIER = new BigNumber ( 0 ) ; export const RFQT_PROTOCOL_FEE_GAS_PRICE_MAX_PADDING_MULTIPLIER = 1.2 ; const UNWRAP_GAS_BY_CHAIN_ID = valueByChainId < BigNumber > ( { [ ChainId . Fantom ] : new BigNumber ( 37000 ) , } , new BigNumber ( 25000 ) ) ; export const UNWRAP_WETH_GAS = UNWRAP_GAS_BY_CHAIN_ID [ CHAIN_ID ] ; export const WRAP_ETH_GAS = UNWRAP_WETH_GAS ; export const UNWRAP_QUOTE_GAS = TX_BASE_GAS . plus ( UNWRAP_WETH_GAS ) ; export const WRAP_QUOTE_GAS = UNWRAP_QUOTE_GAS ; const EXCLUDED_SOURCES = ( ( ) => { const allERC20BridgeSources = Object . values ( ERC20BridgeSource ) ; switch ( CHAIN_ID ) { case ChainId . Mainnet : return [ ERC20BridgeSource . MultiBridge ] ; case ChainId . Kovan : return allERC20BridgeSources . filter ( ( s ) => s !== ERC20BridgeSource . Native && s !== ERC20BridgeSource . UniswapV2 ) ; case ChainId . Ropsten : const supportedRopstenSources = new Set ( [ ERC20BridgeSource . Kyber , ERC20BridgeSource . Native , ERC20BridgeSource . SushiSwap , ERC20BridgeSource . Uniswap , ERC20BridgeSource . UniswapV2 , ERC20BridgeSource . UniswapV3 , ERC20BridgeSource . Curve , ERC20BridgeSource . Mooniswap , ] ) ; return allERC20BridgeSources . filter ( ( s ) => ! supportedRopstenSources . has ( s ) ) ; case ChainId . BSC : return [ ERC20BridgeSource . MultiBridge , ERC20BridgeSource . Native ] ; case ChainId . Polygon : return [ ERC20BridgeSource . MultiBridge , ERC20BridgeSource . Native ] ; case ChainId . Avalanche : return [ ERC20BridgeSource . MultiBridge , ERC20BridgeSource . Native ] ; case ChainId . Celo : return [ ERC20BridgeSource . MultiBridge , ERC20BridgeSource . Native ] ; case ChainId . Fantom : return [ ERC20BridgeSource . MultiBridge , ERC20BridgeSource . Native ] ; case ChainId . Optimism : return [ ERC20BridgeSource . MultiBridge , ERC20BridgeSource . Native ] ; default : return allERC20BridgeSources . filter ( ( s ) => s !== ERC20BridgeSource . Native ) ; } } ) ( ) ; const EXCLUDED_FEE_SOURCES = ( ( ) => { switch ( CHAIN_ID ) { case ChainId . Mainnet : return [ ] ; case ChainId . Kovan : return [ ERC20BridgeSource . Uniswap ] ; case ChainId . Ropsten : return [ ] ; case ChainId . BSC : return [ ERC20BridgeSource . Uniswap ] ; case ChainId . Polygon : return [ ] ; case ChainId . Celo : return [ ] ; default : return [ ERC20BridgeSource . Uniswap , ERC20BridgeSource . UniswapV2 ] ; } } ) ( ) ; const FILL_QUOTE_TRANSFORMER_GAS_OVERHEAD = new BigNumber ( 150e3 ) ; const EXCHANGE_PROXY_OVERHEAD_NO_VIP = ( ) => FILL_QUOTE_TRANSFORMER_GAS_OVERHEAD ; const MULTIPLEX_BATCH_FILL_SOURCE_FLAGS = SOURCE_FLAGS . Uniswap_V2 | SOURCE_FLAGS . SushiSwap | SOURCE_FLAGS . LiquidityProvider | SOURCE_FLAGS . RfqOrder | SOURCE_FLAGS . Uniswap_V3 ; const MULTIPLEX_MULTIHOP_FILL_SOURCE_FLAGS = SOURCE_FLAGS . Uniswap_V2 | SOURCE_FLAGS . SushiSwap | SOURCE_FLAGS . LiquidityProvider | SOURCE_FLAGS . Uniswap_V3 ; const EXCHANGE_PROXY_OVERHEAD_FULLY_FEATURED = ( sourceFlags ) => { if ( [ SOURCE_FLAGS . Uniswap_V2 , SOURCE_FLAGS . SushiSwap ] . includes ( sourceFlags ) ) { return TX_BASE_GAS ; } else if ( [ SOURCE_FLAGS . SushiSwap , SOURCE_FLAGS . PancakeSwap , SOURCE_FLAGS . PancakeSwap_V2 , SOURCE_FLAGS . BakerySwap , SOURCE_FLAGS . ApeSwap , SOURCE_FLAGS . CafeSwap , SOURCE_FLAGS . CheeseSwap , SOURCE_FLAGS . JulSwap , ] . includes ( sourceFlags ) && CHAIN_ID === ChainId . BSC ) { return TX_BASE_GAS ; } else if ( SOURCE_FLAGS . Uniswap_V3 === sourceFlags ) { return TX_BASE_GAS . plus ( 5e3 ) ; } else if ( SOURCE_FLAGS . Curve === sourceFlags ) { return TX_BASE_GAS . plus ( 40e3 ) ; } else if ( SOURCE_FLAGS . LiquidityProvider === sourceFlags ) { return TX_BASE_GAS . plus ( 10e3 ) ; } else if ( ( MULTIPLEX_BATCH_FILL_SOURCE_FLAGS | sourceFlags ) === MULTIPLEX_BATCH_FILL_SOURCE_FLAGS ) { return TX_BASE_GAS . plus ( 15e3 ) ; } else if ( ( MULTIPLEX_MULTIHOP_FILL_SOURCE_FLAGS | sourceFlags ) === ( MULTIPLEX_MULTIHOP_FILL_SOURCE_FLAGS | SOURCE_FLAGS . MultiHop ) ) { return TX_BASE_GAS . plus ( 25e3 ) ; } else { return FILL_QUOTE_TRANSFORMER_GAS_OVERHEAD ; } } ; export const NATIVE_WRAPPED_TOKEN_SYMBOL = nativeWrappedTokenSymbol ( CHAIN_ID ) ; const NEON_ROUTER_NUM_SAMPLES = 14 ; const SAMPLE_DISTRIBUTION_BASE = SHOULD_USE_RUST_ROUTER ? 1 : 1.05 ; export const ASSET_SWAPPER_MARKET_ORDERS_OPTS = { excludedSources : EXCLUDED_SOURCES , excludedFeeSources : EXCLUDED_FEE_SOURCES , bridgeSlippage : DEFAULT_QUOTE_SLIPPAGE_PERCENTAGE , maxFallbackSlippage : DEFAULT_FALLBACK_SLIPPAGE_PERCENTAGE , numSamples : 13 , sampleDistributionBase : SAMPLE_DISTRIBUTION_BASE , neonRouterNumSamples : NEON_ROUTER_NUM_SAMPLES , exchangeProxyOverhead : EXCHANGE_PROXY_OVERHEAD_FULLY_FEATURED , runLimit : 2 ** 8 , shouldGenerateQuoteReport : true , } ; export const ASSET_SWAPPER_MARKET_ORDERS_OPTS_NO_VIP = { ... ASSET_SWAPPER_MARKET_ORDERS_OPTS , exchangeProxyOverhead : EXCHANGE_PROXY_OVERHEAD_NO_VIP , } ; export const SAMPLER_OVERRIDES = ( ( ) => { switch ( CHAIN_ID ) { case ChainId . Ganache : case ChainId . Kovan : return { overrides : { } , block : BlockParamLiteral . Latest } ; default : return undefined ; } } ) ( ) ; let SWAP_QUOTER_RFQT_OPTS = { integratorsWhitelist : RFQT_INTEGRATORS , makerAssetOfferings : RFQT_MAKER_ASSET_OFFERINGS , txOriginBlacklist : RFQT_TX_ORIGIN_BLACKLIST , } ; if ( ALT_RFQ_MM_API_KEY && ALT_RFQ_MM_PROFILE ) { SWAP_QUOTER_RFQT_OPTS = { ... SWAP_QUOTER_RFQT_OPTS , altRfqCreds : { altRfqApiKey : ALT_RFQ_MM_API_KEY , altRfqProfile : ALT_RFQ_MM_PROFILE , } , } ; } export const SWAP_QUOTER_OPTS = { chainId : CHAIN_ID , expiryBufferMs : QUOTE_ORDER_EXPIRATION_BUFFER_MS , rfqt : SWAP_QUOTER_RFQT_OPTS , ethGasStationUrl : ETH_GAS_STATION_API_URL , permittedOrderFeeTypes : new Set ( [ OrderPrunerPermittedFeeTypes . NoFees ] ) , samplerOverrides : SAMPLER_OVERRIDES , tokenAdjacencyGraph : DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID [ CHAIN_ID ] , liquidityProviderRegistry : LIQUIDITY_PROVIDER_REGISTRY , } ; export const defaultHttpServiceConfig = { httpPort : HTTP_PORT , healthcheckHttpPort : HEALTHCHECK_HTTP_PORT , healthcheckPath : HEALTHCHECK_PATH , ethereumRpcUrl : ETHEREUM_RPC_URL , httpKeepAliveTimeout : HTTP_KEEP_ALIVE_TIMEOUT , httpHeadersTimeout : HTTP_HEADERS_TIMEOUT , enablePrometheusMetrics : ENABLE_PROMETHEUS_METRICS , prometheusPort : PROMETHEUS_PORT , prometheusPath : METRICS_PATH , kafkaBrokers : KAFKA_BROKERS , kafkaConsumerGroupId : KAFKA_CONSUMER_GROUP_ID , rpcRequestTimeout : RPC_REQUEST_TIMEOUT , shouldCompressRequest : ENABLE_RPC_REQUEST_COMPRESSION , } ; export const defaultHttpServiceWithRateLimiterConfig = { ... defaultHttpServiceConfig , metaTxnRateLimiters : META_TXN_RATE_LIMITER_CONFIG , } ; export const getIntegratorByIdOrThrow = ( ( integratorsMap ) => ( integratorId ) : Integrator => { const integrator = integratorsMap . get ( integratorId ) ; if ( ! integrator ) { throw new Error ( `Integrator ${ integratorId } does not exist.` ) ; } return integrator ; } ) ( transformIntegratorsAcl ( INTEGRATORS_ACL , 'integratorId' ) ) ; /**
 * Gets the integrator ID for a given API key. If the API key is not in the configuration, returns `undefined`.
 */ export const getIntegratorIdForApiKey = ( ( integratorsMap ) => ( apiKey ) : string | undefined => { const integrator = integratorsMap . get ( apiKey ) ; return integrator ?. integratorId ; } ) ( transformIntegratorsAcl ( INTEGRATORS_ACL , 'apiKeys' ) ) ; param integrators param keyBy function transformIntegratorsAcl ( integrators , keyBy ) { const result = new Map < string , Integrator > ( ) ; integrators . forEach ( ( integrator ) => { let mapKeys ; switch ( keyBy ) { case 'apiKeys' : mapKeys = integrator . apiKeys ; break ; case 'integratorId' : mapKeys = [ integrator . integratorId ] ; break ; default : throw new Error ( `Parameter "${ keyBy }" is misconfigured` ) ; } mapKeys . forEach ( ( apiKey ) => { result . set ( apiKey , integrator ) ; } ) ; } ) ; return result ; } param envVar param envVarType param fallback returns function resolveEnvVar < T > ( envVar , envVarType , fallback ) { const rawEnvVar = process . env [ envVar ] ; if ( rawEnvVar === undefined || _ . isEmpty ( rawEnvVar ) ) { return fallback ; } if ( fs . existsSync ( rawEnvVar ) ) { return JSON . parse ( fs . readFileSync ( rawEnvVar , 'utf8' ) ) ; } return assertEnvVarType ( envVar , process . env [ envVar ] , envVarType ) ; } function assertEnvVarType ( name , value , expectedType ) { let returnValue ; switch ( expectedType ) { case EnvVarType . Port : returnValue = parseInt ( value , 10 ) ; const isWithinRange = returnValue >= 0 && returnValue <= 65535 ; if ( isNaN ( returnValue ) || ! isWithinRange ) { throw new Error ( `${ name } must be between 0 to 65535, found ${ value }.` ) ; } return returnValue ; case EnvVarType . ChainId : case EnvVarType . KeepAliveTimeout : case EnvVarType . Integer : returnValue = parseInt ( value , 10 ) ; if ( isNaN ( returnValue ) ) { throw new Error ( `${ name } must be a valid integer, found ${ value }.` ) ; } return returnValue ; case EnvVarType . ETHAddressHex : assert . isETHAddressHex ( name , value ) ; return value ; case EnvVarType . Url : assert . isUri ( name , value ) ; return value ; case EnvVarType . UrlList : assert . isString ( name , value ) ; const urlList = ( value as string ) . split ( ',' ) ; urlList . forEach ( ( url , i ) => assert . isUri ( `${ name }[${ i }]` , url ) ) ; return urlList ; case EnvVarType . Boolean : return value === 'true' ; case EnvVarType . UnitAmount : returnValue = new BigNumber ( parseFloat ( value ) ) ; if ( returnValue . isNaN ( ) || returnValue . isNegative ( ) ) { throw new Error ( `${ name } must be valid number greater than 0.` ) ; } return returnValue ; case EnvVarType . AddressList : assert . isString ( name , value ) ; const addressList = ( value as string ) . split ( ',' ) . map ( ( a ) => a . toLowerCase ( ) ) ; addressList . forEach ( ( a , i ) => assert . isETHAddressHex ( `${ name }[${ i }]` , a ) ) ; return addressList ; case EnvVarType . StringList : assert . isString ( name , value ) ; const stringList = ( value as string ) . split ( ',' ) ; return stringList ; case EnvVarType . WhitelistAllTokens : return '*' ; case EnvVarType . NonEmptyString : assert . isString ( name , value ) ; if ( value === '' ) { throw new Error ( `${ name } must be supplied` ) ; } return value ; case EnvVarType . RateLimitConfig : assert . isString ( name , value ) ; return parseUtils . parseJsonStringForMetaTransactionRateLimitConfigOrThrow ( value ) ; case EnvVarType . APIKeys : assert . isString ( name , value ) ; const apiKeys = ( value as string ) . split ( ',' ) ; apiKeys . forEach ( ( apiKey ) => { const isValidUUID = validateUUID ( apiKey ) ; if ( ! isValidUUID ) { throw new Error ( `API Key ${ apiKey } isn't UUID compliant` ) ; } } ) ; return apiKeys ; case EnvVarType . JsonStringList : assert . isString ( name , value ) ; return JSON . parse ( value ) ; case EnvVarType . RfqMakerAssetOfferings : const offerings = JSON . parse ( value ) ; for ( const makerEndpoint in offerings ) { assert . isWebUri ( 'market maker endpoint' , makerEndpoint ) ; const assetOffering = offerings [ makerEndpoint ] ; assert . isArray ( `value in maker endpoint mapping, for index ${ makerEndpoint },` , assetOffering ) ; assetOffering . forEach ( ( assetPair , i ) => { assert . isArray ( `asset pair array ${ i } for maker endpoint ${ makerEndpoint }` , assetPair ) ; assert . assert ( assetPair . length === 2 , `asset pair array ${ i } for maker endpoint ${ makerEndpoint } does not consist of exactly two elements.` ) ; assert . isETHAddressHex ( `first token address for asset pair ${ i } for maker endpoint ${ makerEndpoint }` , assetPair [ 0 ] ) ; assert . isETHAddressHex ( `second token address for asset pair ${ i } for maker endpoint ${ makerEndpoint }` , assetPair [ 1 ] ) ; assert . assert ( assetPair [ 0 ] !== assetPair [ 1 ] , `asset pair array ${ i } for maker endpoint ${ makerEndpoint } has identical assets` ) ; } ) ; } return offerings ; case EnvVarType . LiquidityProviderRegistry : const registry = JSON . parse ( value ) ; for ( const liquidityProvider in registry ) { assert . isETHAddressHex ( 'liquidity provider address' , liquidityProvider ) ; const { tokens } = registry [ liquidityProvider ] ; assert . isArray ( `token list for liquidity provider ${ liquidityProvider }` , tokens ) ; tokens . forEach ( ( token , i ) => { assert . isETHAddressHex ( `address of token ${ i } for liquidity provider ${ liquidityProvider }` , token ) ; } ) ; } return registry ; default : throw new Error ( `Unrecognised EnvVarType: ${ expectedType } encountered for variable ${ name }.` ) ; } }