fix: Exclusive API keys for select integrations (#317)
* Initial commit of changes * Added unit tests for filtering process * linting * Update packages/asset-swapper/src/utils/quote_requestor.ts Co-authored-by: phil-ociraptor <philipliao@gmail.com> * lint and refactor based on feedback Co-authored-by: phil-ociraptor <philipliao@gmail.com>
This commit is contained in:
parent
7439871aa0
commit
e838a6801b
@ -244,6 +244,7 @@ export interface RfqRequestOpts {
|
||||
takerAddress: string;
|
||||
txOrigin: string;
|
||||
apiKey: string;
|
||||
apiKeyWhitelist?: string[];
|
||||
intentOnFilling: boolean;
|
||||
isIndicative?: boolean;
|
||||
makerEndpointMaxResponseTimeMs?: number;
|
||||
|
@ -178,6 +178,42 @@ export class QuoteRequestor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets both standard RFQ makers and "alternative" RFQ makers and combines them together
|
||||
* in a single configuration map. If an integration key whitelist is present, it will be used
|
||||
* to filter a specific makers.
|
||||
*
|
||||
* @param options the RfqmRequestOptions passed in
|
||||
* @param assetOfferings the RFQM or RFQT maker offerings
|
||||
* @returns a list of TypedMakerUrl instances
|
||||
*/
|
||||
public static getTypedMakerUrlsAndWhitelist(
|
||||
options: Pick<RfqmRequestOptions, 'apiKeyWhitelist' | 'altRfqAssetOfferings'>,
|
||||
assetOfferings: RfqMakerAssetOfferings,
|
||||
): TypedMakerUrl[] {
|
||||
const standardUrls = Object.keys(assetOfferings).map(
|
||||
(mm: string): TypedMakerUrl => {
|
||||
return { pairType: RfqPairType.Standard, url: mm };
|
||||
},
|
||||
);
|
||||
const altUrls = options.altRfqAssetOfferings
|
||||
? Object.keys(options.altRfqAssetOfferings).map(
|
||||
(mm: string): TypedMakerUrl => {
|
||||
return { pairType: RfqPairType.Alt, url: mm };
|
||||
},
|
||||
)
|
||||
: [];
|
||||
|
||||
let typedMakerUrls = standardUrls.concat(altUrls);
|
||||
|
||||
// If there is a whitelist, only allow approved maker URLs
|
||||
if (options.apiKeyWhitelist !== undefined) {
|
||||
const whitelist = new Set(options.apiKeyWhitelist.map(key => key.toLowerCase()));
|
||||
typedMakerUrls = typedMakerUrls.filter(makerUrl => whitelist.has(makerUrl.url.toLowerCase()));
|
||||
}
|
||||
return typedMakerUrls;
|
||||
}
|
||||
|
||||
public static getDurationUntilExpirationMs(expirationTimeSeconds: BigNumber): BigNumber {
|
||||
const expirationTimeMs = expirationTimeSeconds.times(constants.ONE_SECOND_MS);
|
||||
const currentTimeMs = new BigNumber(Date.now());
|
||||
@ -401,21 +437,6 @@ export class QuoteRequestor {
|
||||
}
|
||||
})();
|
||||
|
||||
const standardUrls = Object.keys(assetOfferings).map(
|
||||
(mm: string): TypedMakerUrl => {
|
||||
return { pairType: RfqPairType.Standard, url: mm };
|
||||
},
|
||||
);
|
||||
const altUrls = options.altRfqAssetOfferings
|
||||
? Object.keys(options.altRfqAssetOfferings).map(
|
||||
(mm: string): TypedMakerUrl => {
|
||||
return { pairType: RfqPairType.Alt, url: mm };
|
||||
},
|
||||
)
|
||||
: [];
|
||||
|
||||
const typedMakerUrls = standardUrls.concat(altUrls);
|
||||
|
||||
const timeoutMs =
|
||||
options.makerEndpointMaxResponseTimeMs ||
|
||||
constants.DEFAULT_RFQT_REQUEST_OPTS.makerEndpointMaxResponseTimeMs!;
|
||||
@ -427,6 +448,7 @@ export class QuoteRequestor {
|
||||
cancelTokenSource.cancel('timeout via cancel token');
|
||||
}, timeoutMs + bufferMs);
|
||||
|
||||
const typedMakerUrls = QuoteRequestor.getTypedMakerUrlsAndWhitelist(options, assetOfferings);
|
||||
const quotePromises = typedMakerUrls.map(async typedMakerUrl => {
|
||||
// filter out requests to skip
|
||||
const isBlacklisted = rfqMakerBlacklist.isMakerBlacklisted(typedMakerUrl.url);
|
||||
|
@ -834,6 +834,39 @@ describe('QuoteRequestor', async () => {
|
||||
quoteRequestorHttpClient,
|
||||
);
|
||||
});
|
||||
it('should be able to handle and filter RFQ offerings', () => {
|
||||
const tests: Array<[string[] | undefined, string[]]> = [
|
||||
[['https://top.maker'], []],
|
||||
[undefined, ['https://foo.bar/', 'https://lorem.ipsum/']],
|
||||
[['https://lorem.ipsum/'], ['https://lorem.ipsum/']],
|
||||
];
|
||||
for (const test of tests) {
|
||||
const [apiKeyWhitelist, results] = test;
|
||||
const response = QuoteRequestor.getTypedMakerUrlsAndWhitelist(
|
||||
{
|
||||
apiKeyWhitelist,
|
||||
altRfqAssetOfferings: {},
|
||||
},
|
||||
{
|
||||
'https://foo.bar/': [
|
||||
[
|
||||
'0xA6cD4cb8c62aCDe44739E3Ed0F1d13E0e31f2d94',
|
||||
'0xF45107c0200a04A8aB9C600cc52A3C89AE5D0489',
|
||||
],
|
||||
],
|
||||
'https://lorem.ipsum/': [
|
||||
[
|
||||
'0xA6cD4cb8c62aCDe44739E3Ed0F1d13E0e31f2d94',
|
||||
'0xF45107c0200a04A8aB9C600cc52A3C89AE5D0489',
|
||||
],
|
||||
],
|
||||
},
|
||||
);
|
||||
const typedUrls = response.map(typed => typed.url);
|
||||
expect(typedUrls).to.eql(results);
|
||||
}
|
||||
});
|
||||
|
||||
it('should return successful alt indicative quotes', async () => {
|
||||
const takerAddress = '0xd209925defc99488e3afff1174e48b4fa628302a';
|
||||
const txOrigin = '0xf209925defc99488e3afff1174e48b4fa628302a';
|
||||
|
Loading…
x
Reference in New Issue
Block a user