feat: add proxy configuration to axios instance in RFQT asset-swapper (#159)

* add proxy configuration to axios instance

* add support for additional axios instance opts

* move quoteRequestorHttpClient parameter

* fix tests, build errors

* prettier

* bump axios

* bumped mock-axios-adapter version

* downgrade axios again

* re-upgrade axios 🤦

* updated yarn.lock

* updated changelog

Co-authored-by: Alex Kroeger <alexrkroeger@gmail.com>
This commit is contained in:
Oskar Paolini 2021-03-03 20:38:54 +01:00 committed by GitHub
parent db3e076d03
commit f3ca4293bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 69 additions and 43 deletions

View File

@ -5,6 +5,10 @@
{
"note": "Add MooniswapLiquidityProvider \"direct\" route to EP consumer.",
"pr": 143
},
{
"note": "Enable the ability to send RFQT requests thru a proxy",
"pr": 159
}
]
},

View File

@ -75,8 +75,8 @@
"@ethersproject/address": "^5.0.1",
"@ethersproject/contracts": "^5.0.1",
"@ethersproject/providers": "^5.0.4",
"axios": "^0.19.2",
"axios-mock-adapter": "^1.18.1",
"axios": "^0.21.1",
"axios-mock-adapter": "^1.19.0",
"cream-sor": "^0.3.3",
"decimal.js": "^10.2.0",
"ethereum-types": "^3.4.0",

View File

@ -94,6 +94,9 @@ export { DEFAULT_FEE_SCHEDULE, DEFAULT_GAS_SCHEDULE } from './utils/market_opera
export const POSITIVE_SLIPPAGE_FEE_TRANSFORMER_GAS = new BigNumber(30000);
// tslint:disable-next-line: custom-no-magic-numbers
export const KEEP_ALIVE_TTL = 5 * 60 * ONE_SECOND_MS;
export const constants = {
ETH_GAS_STATION_API_URL,
PROTOCOL_FEE_MULTIPLIER,

View File

@ -1,11 +1,14 @@
import { ChainId, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { FillQuoteTransformerOrderType, LimitOrder } from '@0x/protocol-utils';
import { BigNumber, providerUtils } from '@0x/utils';
import Axios, { AxiosInstance } from 'axios';
import { BlockParamLiteral, SupportedProvider, ZeroExProvider } from 'ethereum-types';
import { Agent as HttpAgent } from 'http';
import { Agent as HttpsAgent } from 'https';
import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { constants, INVALID_SIGNATURE } from './constants';
import { constants, INVALID_SIGNATURE, KEEP_ALIVE_TTL } from './constants';
import {
AssetSwapperContractAddresses,
MarketBuySwapQuote,
@ -70,6 +73,7 @@ export class SwapQuoter {
private readonly _protocolFeeUtils: ProtocolFeeUtils;
private readonly _marketOperationUtils: MarketOperationUtils;
private readonly _rfqtOptions?: SwapQuoterRfqtOpts;
private readonly _quoteRequestorHttpClient: AxiosInstance;
/**
* Instantiates a new SwapQuoter instance
@ -144,6 +148,12 @@ export class SwapQuoter {
exchangeAddress: this._contractAddresses.exchange,
},
);
this._quoteRequestorHttpClient = Axios.create({
httpAgent: new HttpAgent({ keepAlive: true, timeout: KEEP_ALIVE_TTL }),
httpsAgent: new HttpsAgent({ keepAlive: true, timeout: KEEP_ALIVE_TTL }),
...(rfqt ? rfqt.axiosInstanceOpts : {}),
});
}
public async getBatchMarketBuySwapQuoteAsync(
@ -348,6 +358,7 @@ export class SwapQuoter {
if (calcOpts.rfqt !== undefined) {
calcOpts.rfqt.quoteRequestor = new QuoteRequestor(
rfqtOptions ? rfqtOptions.makerAssetOfferings || {} : {},
this._quoteRequestorHttpClient,
rfqtOptions ? rfqtOptions.altRfqCreds : undefined,
rfqtOptions ? rfqtOptions.warningLogger : undefined,
rfqtOptions ? rfqtOptions.infoLogger : undefined,

View File

@ -9,6 +9,7 @@ import {
} from '@0x/protocol-utils';
import { TakerRequestQueryParams, V4SignedRfqOrder } from '@0x/quote-server';
import { BigNumber } from '@0x/utils';
import { AxiosRequestConfig } from 'axios';
import {
ERC20BridgeSource,
@ -291,6 +292,7 @@ export interface SwapQuoterRfqtOpts {
};
warningLogger?: LogFunction;
infoLogger?: LogFunction;
axiosInstanceOpts?: AxiosRequestConfig;
}
export type AssetSwapperContractAddresses = ContractAddresses;

View File

@ -2,9 +2,7 @@ import { schemas, SchemaValidator } from '@0x/json-schemas';
import { FillQuoteTransformerOrderType, Signature } from '@0x/protocol-utils';
import { TakerRequestQueryParams, V4RFQFirmQuote, V4RFQIndicativeQuote, V4SignedRfqOrder } from '@0x/quote-server';
import { BigNumber, NULL_ADDRESS } from '@0x/utils';
import Axios, { AxiosInstance } from 'axios';
import { Agent as HttpAgent } from 'http';
import { Agent as HttpsAgent } from 'https';
import { AxiosInstance } from 'axios';
import { constants } from '../constants';
import {
@ -20,17 +18,8 @@ import {
} from '../types';
import { returnQuoteFromAltMMAsync } from './alt_mm_implementation_utils';
import { ONE_SECOND_MS } from './market_operation_utils/constants';
import { RfqMakerBlacklist } from './rfq_maker_blacklist';
// tslint:disable-next-line: custom-no-magic-numbers
const KEEP_ALIVE_TTL = 5 * 60 * ONE_SECOND_MS;
export const quoteRequestorHttpClient: AxiosInstance = Axios.create({
httpAgent: new HttpAgent({ keepAlive: true, timeout: KEEP_ALIVE_TTL }),
httpsAgent: new HttpsAgent({ keepAlive: true, timeout: KEEP_ALIVE_TTL }),
});
const MAKER_TIMEOUT_STREAK_LENGTH = 10;
const MAKER_TIMEOUT_BLACKLIST_DURATION_MINUTES = 10;
const rfqMakerBlacklist = new RfqMakerBlacklist(MAKER_TIMEOUT_STREAK_LENGTH, MAKER_TIMEOUT_BLACKLIST_DURATION_MINUTES);
@ -137,6 +126,7 @@ export class QuoteRequestor {
constructor(
private readonly _rfqtAssetOfferings: RfqtMakerAssetOfferings,
private readonly _quoteRequestorHttpClient: AxiosInstance,
private readonly _altRfqCreds?: { altRfqApiKey: string; altRfqProfile: string },
private readonly _warningLogger: LogFunction = constants.DEFAULT_WARNING_LOGGER,
private readonly _infoLogger: LogFunction = constants.DEFAULT_INFO_LOGGER,
@ -420,7 +410,7 @@ export class QuoteRequestor {
: options.makerEndpointMaxResponseTimeMs;
try {
if (typedMakerUrl.pairType === RfqPairType.Standard) {
const response = await quoteRequestorHttpClient.get(`${typedMakerUrl.url}/${quotePath}`, {
const response = await this._quoteRequestorHttpClient.get(`${typedMakerUrl.url}/${quotePath}`, {
headers: { '0x-api-key': options.apiKey },
params: requestParams,
timeout: maxResponseTimeMs,
@ -456,7 +446,7 @@ export class QuoteRequestor {
maxResponseTimeMs,
options.altRfqtAssetOfferings || {},
requestParams,
quoteRequestorHttpClient,
this._quoteRequestorHttpClient,
);
const latencyMs = Date.now() - timeBeforeAwait;

View File

@ -3,11 +3,14 @@ import { FillQuoteTransformerOrderType, SignatureType } from '@0x/protocol-utils
import { TakerRequestQueryParams, V4RFQIndicativeQuote } from '@0x/quote-server';
import { StatusCodes } from '@0x/types';
import { BigNumber, logUtils } from '@0x/utils';
import Axios, { AxiosInstance } from 'axios';
import * as chai from 'chai';
import { Agent as HttpAgent } from 'http';
import { Agent as HttpsAgent } from 'https';
import _ = require('lodash');
import 'mocha';
import { constants } from '../src/constants';
import { constants, KEEP_ALIVE_TTL } from '../src/constants';
import {
AltMockedRfqtQuoteResponse,
AltQuoteModel,
@ -18,11 +21,16 @@ import {
MockedRfqtQuoteResponse,
} from '../src/types';
import { NULL_ADDRESS } from '../src/utils/market_operation_utils/constants';
import { QuoteRequestor, quoteRequestorHttpClient } from '../src/utils/quote_requestor';
import { QuoteRequestor } from '../src/utils/quote_requestor';
import { chaiSetup } from './utils/chai_setup';
import { RfqtQuoteEndpoint, testHelpers } from './utils/test_helpers';
const quoteRequestorHttpClient = Axios.create({
httpAgent: new HttpAgent({ keepAlive: true, timeout: KEEP_ALIVE_TTL }),
httpsAgent: new HttpsAgent({ keepAlive: true, timeout: KEEP_ALIVE_TTL }),
});
chaiSetup.configure();
const expect = chai.expect;
const ALT_MM_API_KEY = 'averysecurekey';
@ -215,6 +223,7 @@ describe('QuoteRequestor', async () => {
'https://426.0.0.1': [] /* Shouldn't ping an RFQ-T provider when they don't support the requested asset pair. */,
'https://37.0.0.1': [[makerToken, takerToken]],
},
quoteRequestorHttpClient,
ALT_RFQ_CREDS,
);
const resp = await qr.requestRfqtFirmQuotesAsync(
@ -327,15 +336,18 @@ describe('QuoteRequestor', async () => {
[],
RfqtQuoteEndpoint.Indicative,
async () => {
const qr = new QuoteRequestor({
'https://1337.0.0.1': [[makerToken, takerToken]],
'https://420.0.0.1': [[makerToken, takerToken]],
'https://421.0.0.1': [[makerToken, takerToken]],
'https://422.0.0.1': [[makerToken, takerToken]],
'https://423.0.0.1': [[makerToken, takerToken]],
'https://424.0.0.1': [[makerToken, takerToken]],
'https://37.0.0.1': [[makerToken, takerToken]],
});
const qr = new QuoteRequestor(
{
'https://1337.0.0.1': [[makerToken, takerToken]],
'https://420.0.0.1': [[makerToken, takerToken]],
'https://421.0.0.1': [[makerToken, takerToken]],
'https://422.0.0.1': [[makerToken, takerToken]],
'https://423.0.0.1': [[makerToken, takerToken]],
'https://424.0.0.1': [[makerToken, takerToken]],
'https://37.0.0.1': [[makerToken, takerToken]],
},
quoteRequestorHttpClient,
);
const resp = await qr.requestRfqtIndicativeQuotesAsync(
makerToken,
takerToken,
@ -391,7 +403,10 @@ describe('QuoteRequestor', async () => {
[],
RfqtQuoteEndpoint.Indicative,
async () => {
const qr = new QuoteRequestor({ 'https://1337.0.0.1': [[makerToken, takerToken]] });
const qr = new QuoteRequestor(
{ 'https://1337.0.0.1': [[makerToken, takerToken]] },
quoteRequestorHttpClient,
);
const resp = await qr.requestRfqtIndicativeQuotesAsync(
makerToken,
takerToken,
@ -623,7 +638,7 @@ describe('QuoteRequestor', async () => {
altMockedRequests,
RfqtQuoteEndpoint.Indicative,
async () => {
const qr = new QuoteRequestor({}, ALT_RFQ_CREDS);
const qr = new QuoteRequestor({}, quoteRequestorHttpClient, ALT_RFQ_CREDS);
const resp = await qr.requestRfqtIndicativeQuotesAsync(
altScenario.requestedMakerToken,
altScenario.requestedTakerToken,

View File

@ -2991,18 +2991,20 @@ aws4@^1.8.0:
version "1.10.1"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428"
axios-mock-adapter@^1.18.1:
axios-mock-adapter@^1.19.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/axios-mock-adapter/-/axios-mock-adapter-1.19.0.tgz#9d72e321a6c5418e1eff067aa99761a86c5188a4"
integrity sha512-D+0U4LNPr7WroiBDvWilzTMYPYTuZlbo6BI8YHZtj7wYQS8NkARlP9KBt8IWWHTQJ0q/8oZ0ClPBtKCCkx8cQg==
dependencies:
fast-deep-equal "^3.1.3"
is-buffer "^2.0.3"
axios@^0.19.2:
version "0.19.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
axios@^0.21.1:
version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
dependencies:
follow-redirects "1.5.10"
follow-redirects "^1.10.0"
babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
version "6.26.0"
@ -4757,7 +4759,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
dependencies:
ms "2.0.0"
debug@3.1.0, debug@=3.1.0:
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
@ -6353,11 +6355,10 @@ flush-write-stream@^1.0.0, flush-write-stream@^1.0.2:
inherits "^2.0.3"
readable-stream "^2.3.6"
follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
dependencies:
debug "=3.1.0"
follow-redirects@^1.10.0:
version "1.13.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267"
integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==
for-each@~0.3.3:
version "0.3.3"
@ -10315,9 +10316,9 @@ public-encrypt@^4.0.0:
randombytes "^2.0.1"
safe-buffer "^5.1.2"
"publish-release@git+https://github.com/0xProject/publish-release.git#3f8be1105a356527f4b362ff456d94bf9a82f2ed":
"publish-release@https://github.com/0xProject/publish-release.git#3f8be1105a356527f4b362ff456d94bf9a82f2ed":
version "1.3.3"
resolved "git+https://github.com/0xProject/publish-release.git#3f8be1105a356527f4b362ff456d94bf9a82f2ed"
resolved "https://github.com/0xProject/publish-release.git#3f8be1105a356527f4b362ff456d94bf9a82f2ed"
dependencies:
async "^0.9.0"
ghauth "^2.0.0"