* baseline adapter code [WIP] * fixed adapter logic, quote_requester instantiation * modified quote-requestor test to include alt implementation * type changes, fixes to quote requestor test * small fixes * working tests, made alt utils more readable * lint errors * added alt indicative quote tests, minor fixes * export alt MM market offering types * altered alt market offering to have id instead of symbols * addressed minor comments * updated changelog * got rid of unnecessary, large if-block, fixed the buy-sell assignment to be from the MM's perspective * extra logging for debugging * fixed existingOrder size * get rid of only flag on test, get rid of extra logging * prettier
651 lines
27 KiB
TypeScript
651 lines
27 KiB
TypeScript
import { tokenUtils } from '@0x/dev-utils';
|
|
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 * as chai from 'chai';
|
|
import _ = require('lodash');
|
|
import 'mocha';
|
|
|
|
import { constants } from '../src/constants';
|
|
import {
|
|
AltMockedRfqtQuoteResponse,
|
|
AltQuoteModel,
|
|
AltQuoteRequestData,
|
|
AltQuoteSide,
|
|
AltRfqtMakerAssetOfferings,
|
|
MarketOperation,
|
|
MockedRfqtQuoteResponse,
|
|
} from '../src/types';
|
|
import { NULL_ADDRESS } from '../src/utils/market_operation_utils/constants';
|
|
import { QuoteRequestor, quoteRequestorHttpClient } from '../src/utils/quote_requestor';
|
|
|
|
import { chaiSetup } from './utils/chai_setup';
|
|
import { RfqtQuoteEndpoint, testHelpers } from './utils/test_helpers';
|
|
|
|
chaiSetup.configure();
|
|
const expect = chai.expect;
|
|
const ALT_MM_API_KEY = 'averysecurekey';
|
|
const ALT_PROFILE = 'acoolprofile';
|
|
const ALT_RFQ_CREDS = {
|
|
altRfqApiKey: ALT_MM_API_KEY,
|
|
altRfqProfile: ALT_PROFILE,
|
|
};
|
|
|
|
function makeThreeMinuteExpiry(): BigNumber {
|
|
const expiry = new Date(Date.now());
|
|
expiry.setMinutes(expiry.getMinutes() + 3);
|
|
return new BigNumber(Math.round(expiry.valueOf() / constants.ONE_SECOND_MS));
|
|
}
|
|
|
|
describe('QuoteRequestor', async () => {
|
|
const [makerToken, takerToken, otherToken1] = tokenUtils.getDummyERC20TokenAddresses();
|
|
const validSignature = { v: 28, r: '0x', s: '0x', signatureType: SignatureType.EthSign };
|
|
|
|
const altRfqtAssetOfferings: AltRfqtMakerAssetOfferings = {
|
|
'https://132.0.0.1': [
|
|
{
|
|
id: 'XYZ-123',
|
|
baseAsset: makerToken,
|
|
quoteAsset: takerToken,
|
|
baseAssetDecimals: 2,
|
|
quoteAssetDecimals: 3,
|
|
},
|
|
],
|
|
};
|
|
|
|
describe('requestRfqtFirmQuotesAsync for firm quotes', async () => {
|
|
it('should return successful RFQT requests', async () => {
|
|
const takerAddress = '0xd209925defc99488e3afff1174e48b4fa628302a';
|
|
const txOrigin = takerAddress;
|
|
const apiKey = 'my-ko0l-api-key';
|
|
|
|
// Set up RFQT responses
|
|
// tslint:disable-next-line:array-type
|
|
const mockedRequests: MockedRfqtQuoteResponse[] = [];
|
|
const altMockedRequests: AltMockedRfqtQuoteResponse[] = [];
|
|
|
|
const expectedParams: TakerRequestQueryParams = {
|
|
sellTokenAddress: takerToken,
|
|
buyTokenAddress: makerToken,
|
|
sellAmountBaseUnits: '10000',
|
|
comparisonPrice: undefined,
|
|
takerAddress,
|
|
txOrigin,
|
|
protocolVersion: '4',
|
|
};
|
|
const mockedDefaults = {
|
|
requestApiKey: apiKey,
|
|
requestParams: expectedParams,
|
|
responseCode: StatusCodes.Success,
|
|
};
|
|
const validSignedOrder = {
|
|
makerToken,
|
|
takerToken,
|
|
makerAmount: new BigNumber('1000'),
|
|
takerAmount: new BigNumber('1000'),
|
|
maker: takerAddress,
|
|
taker: takerAddress,
|
|
pool: '0x',
|
|
salt: '0',
|
|
chainId: 1,
|
|
verifyingContract: takerAddress,
|
|
txOrigin,
|
|
expiry: makeThreeMinuteExpiry(),
|
|
signature: validSignature,
|
|
};
|
|
// request is to sell 10000 units of the base token
|
|
// 10 units at 3 decimals
|
|
const altFirmRequestData = {
|
|
market: 'XYZ-123',
|
|
model: AltQuoteModel.Firm,
|
|
profile: ALT_PROFILE,
|
|
side: AltQuoteSide.Sell,
|
|
meta: {
|
|
txOrigin,
|
|
taker: takerAddress,
|
|
client: apiKey,
|
|
},
|
|
value: '10',
|
|
};
|
|
const altFirmResponse = {
|
|
...altFirmRequestData,
|
|
id: 'random_id',
|
|
// tslint:disable-next-line:custom-no-magic-numbers
|
|
price: new BigNumber(10 / 100).toString(),
|
|
status: 'active',
|
|
data: {
|
|
'0xv4order': validSignedOrder,
|
|
},
|
|
};
|
|
|
|
// Successful response
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://1337.0.0.1',
|
|
responseData: {
|
|
signedOrder: validSignedOrder,
|
|
},
|
|
});
|
|
// Another Successful response
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://37.0.0.1',
|
|
responseData: { signedOrder: validSignedOrder },
|
|
});
|
|
// Test out a bad response code, ensure it doesnt cause throw
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://420.0.0.1',
|
|
responseData: { error: 'bad request' },
|
|
responseCode: StatusCodes.InternalError,
|
|
});
|
|
// Test out a successful response code but a partial order
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://421.0.0.1',
|
|
responseData: { signedOrder: { makerToken: '123' } },
|
|
});
|
|
// A successful response code and invalid response data (encoding)
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://421.1.0.1',
|
|
responseData: 'this is not JSON!',
|
|
});
|
|
// A successful response code and valid order, but for wrong maker asset data
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://422.0.0.1',
|
|
responseData: { signedOrder: { ...validSignedOrder, makerToken: '0x1234' } },
|
|
});
|
|
// A successful response code and valid order, but for wrong taker asset data
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://423.0.0.1',
|
|
responseData: { signedOrder: { ...validSignedOrder, takerToken: '0x1234' } },
|
|
});
|
|
// A successful response code and good order but its unsigned
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://424.0.0.1',
|
|
responseData: { signedOrder: _.omit(validSignedOrder, ['signature']) },
|
|
});
|
|
// A successful response code and good order but for the wrong txOrigin
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://425.0.0.1',
|
|
responseData: { signedOrder: { ...validSignedOrder, txOrigin: NULL_ADDRESS } },
|
|
});
|
|
// A successful response code and order from an alt RFQ implementation
|
|
altMockedRequests.push({
|
|
endpoint: 'https://132.0.0.1',
|
|
mmApiKey: ALT_MM_API_KEY,
|
|
responseCode: StatusCodes.Success,
|
|
requestData: altFirmRequestData,
|
|
responseData: altFirmResponse,
|
|
});
|
|
|
|
const normalizedSuccessfulOrder = {
|
|
order: {
|
|
..._.omit(validSignedOrder, ['signature']),
|
|
makerAmount: new BigNumber(validSignedOrder.makerAmount),
|
|
takerAmount: new BigNumber(validSignedOrder.takerAmount),
|
|
expiry: new BigNumber(validSignedOrder.expiry),
|
|
salt: new BigNumber(validSignedOrder.salt),
|
|
},
|
|
signature: validSignedOrder.signature,
|
|
type: FillQuoteTransformerOrderType.Rfq,
|
|
};
|
|
|
|
return testHelpers.withMockedRfqtQuotes(
|
|
mockedRequests,
|
|
altMockedRequests,
|
|
RfqtQuoteEndpoint.Firm,
|
|
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://421.1.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://425.0.0.1': [[makerToken, takerToken]],
|
|
'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]],
|
|
},
|
|
ALT_RFQ_CREDS,
|
|
);
|
|
const resp = await qr.requestRfqtFirmQuotesAsync(
|
|
makerToken,
|
|
takerToken,
|
|
new BigNumber(10000),
|
|
MarketOperation.Sell,
|
|
undefined,
|
|
{
|
|
apiKey,
|
|
takerAddress,
|
|
txOrigin: takerAddress,
|
|
intentOnFilling: true,
|
|
altRfqtAssetOfferings,
|
|
},
|
|
);
|
|
expect(resp).to.deep.eq([
|
|
normalizedSuccessfulOrder,
|
|
normalizedSuccessfulOrder,
|
|
normalizedSuccessfulOrder,
|
|
]);
|
|
},
|
|
quoteRequestorHttpClient,
|
|
);
|
|
});
|
|
});
|
|
describe('requestRfqtIndicativeQuotesAsync for Indicative quotes', async () => {
|
|
it('should optionally accept a "comparisonPrice" parameter', async () => {
|
|
const response = QuoteRequestor.makeQueryParameters(
|
|
otherToken1, // tx origin
|
|
otherToken1, // taker
|
|
MarketOperation.Sell,
|
|
makerToken,
|
|
takerToken,
|
|
new BigNumber(1000),
|
|
new BigNumber(300.2),
|
|
);
|
|
expect(response.comparisonPrice).to.eql('300.2');
|
|
});
|
|
it('should return successful RFQT requests', async () => {
|
|
const takerAddress = '0xd209925defc99488e3afff1174e48b4fa628302a';
|
|
const apiKey = 'my-ko0l-api-key';
|
|
|
|
// Set up RFQT responses
|
|
// tslint:disable-next-line:array-type
|
|
const mockedRequests: MockedRfqtQuoteResponse[] = [];
|
|
const expectedParams: TakerRequestQueryParams = {
|
|
sellTokenAddress: takerToken,
|
|
buyTokenAddress: makerToken,
|
|
sellAmountBaseUnits: '10000',
|
|
comparisonPrice: undefined,
|
|
takerAddress,
|
|
txOrigin: takerAddress,
|
|
protocolVersion: '4',
|
|
};
|
|
const mockedDefaults = {
|
|
requestApiKey: apiKey,
|
|
requestParams: expectedParams,
|
|
responseCode: StatusCodes.Success,
|
|
};
|
|
|
|
// Successful response
|
|
const successfulQuote1 = {
|
|
makerToken,
|
|
takerToken,
|
|
makerAmount: new BigNumber(expectedParams.sellAmountBaseUnits),
|
|
takerAmount: new BigNumber(expectedParams.sellAmountBaseUnits),
|
|
expiry: makeThreeMinuteExpiry(),
|
|
};
|
|
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://1337.0.0.1',
|
|
responseData: successfulQuote1,
|
|
});
|
|
// Test out a bad response code, ensure it doesnt cause throw
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://420.0.0.1',
|
|
responseData: { error: 'bad request' },
|
|
responseCode: StatusCodes.InternalError,
|
|
});
|
|
// Test out a successful response code but an invalid order
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://421.0.0.1',
|
|
responseData: { makerToken: '123' },
|
|
});
|
|
// A successful response code and valid response data, but for wrong maker asset data
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://422.0.0.1',
|
|
responseData: { ...successfulQuote1, makerToken: otherToken1 },
|
|
});
|
|
// A successful response code and valid response data, but for wrong taker asset data
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://423.0.0.1',
|
|
responseData: { ...successfulQuote1, takerToken: otherToken1 },
|
|
});
|
|
// Another Successful response
|
|
mockedRequests.push({
|
|
...mockedDefaults,
|
|
endpoint: 'https://37.0.0.1',
|
|
responseData: successfulQuote1,
|
|
});
|
|
|
|
return testHelpers.withMockedRfqtQuotes(
|
|
mockedRequests,
|
|
[],
|
|
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 resp = await qr.requestRfqtIndicativeQuotesAsync(
|
|
makerToken,
|
|
takerToken,
|
|
new BigNumber(10000),
|
|
MarketOperation.Sell,
|
|
undefined,
|
|
{
|
|
apiKey,
|
|
takerAddress,
|
|
txOrigin: takerAddress,
|
|
intentOnFilling: true,
|
|
},
|
|
);
|
|
expect(resp.sort()).to.eql([successfulQuote1, successfulQuote1].sort());
|
|
},
|
|
quoteRequestorHttpClient,
|
|
);
|
|
});
|
|
it('should return successful RFQT indicative quote requests (Buy)', async () => {
|
|
const takerAddress = '0xd209925defc99488e3afff1174e48b4fa628302a';
|
|
const apiKey = 'my-ko0l-api-key';
|
|
|
|
// Set up RFQT responses
|
|
// tslint:disable-next-line:array-type
|
|
const mockedRequests: MockedRfqtQuoteResponse[] = [];
|
|
const expectedParams: TakerRequestQueryParams = {
|
|
sellTokenAddress: takerToken,
|
|
buyTokenAddress: makerToken,
|
|
buyAmountBaseUnits: '10000',
|
|
comparisonPrice: undefined,
|
|
takerAddress,
|
|
txOrigin: takerAddress,
|
|
protocolVersion: '4',
|
|
};
|
|
// Successful response
|
|
const successfulQuote1 = {
|
|
makerToken,
|
|
takerToken,
|
|
makerAmount: new BigNumber(expectedParams.buyAmountBaseUnits),
|
|
takerAmount: new BigNumber(expectedParams.buyAmountBaseUnits),
|
|
expiry: makeThreeMinuteExpiry(),
|
|
};
|
|
mockedRequests.push({
|
|
endpoint: 'https://1337.0.0.1',
|
|
requestApiKey: apiKey,
|
|
requestParams: expectedParams,
|
|
responseData: successfulQuote1,
|
|
responseCode: StatusCodes.Success,
|
|
});
|
|
|
|
return testHelpers.withMockedRfqtQuotes(
|
|
mockedRequests,
|
|
[],
|
|
RfqtQuoteEndpoint.Indicative,
|
|
async () => {
|
|
const qr = new QuoteRequestor({ 'https://1337.0.0.1': [[makerToken, takerToken]] });
|
|
const resp = await qr.requestRfqtIndicativeQuotesAsync(
|
|
makerToken,
|
|
takerToken,
|
|
new BigNumber(10000),
|
|
MarketOperation.Buy,
|
|
undefined,
|
|
{
|
|
apiKey,
|
|
takerAddress,
|
|
txOrigin: takerAddress,
|
|
intentOnFilling: true,
|
|
},
|
|
);
|
|
expect(resp.sort()).to.eql([successfulQuote1].sort());
|
|
},
|
|
quoteRequestorHttpClient,
|
|
);
|
|
});
|
|
it('should return successful alt indicative quotes', async () => {
|
|
const takerAddress = '0xd209925defc99488e3afff1174e48b4fa628302a';
|
|
const txOrigin = '0xf209925defc99488e3afff1174e48b4fa628302a';
|
|
const apiKey = 'my-ko0l-api-key';
|
|
|
|
// base token has 2 decimals
|
|
// quote token has 3 decimals
|
|
const baseToken = makerToken;
|
|
const quoteToken = takerToken;
|
|
|
|
// Set up RFQT responses
|
|
const altMockedRequests: AltMockedRfqtQuoteResponse[] = [];
|
|
const altScenarios: Array<{
|
|
successfulQuote: V4RFQIndicativeQuote;
|
|
requestedMakerToken: string;
|
|
requestedTakerToken: string;
|
|
requestedAmount: BigNumber;
|
|
requestedOperation: MarketOperation;
|
|
}> = [];
|
|
|
|
// SCENARIO 1
|
|
// buy, base asset specified
|
|
// requesting to buy 100 units (10000 base units) of the base token
|
|
// returning a price of 0.01, which should mean 10000 maker, 1000 taker amount
|
|
const buyAmountAltRequest: AltQuoteRequestData = {
|
|
market: 'XYZ-123',
|
|
model: AltQuoteModel.Indicative,
|
|
profile: ALT_PROFILE,
|
|
side: AltQuoteSide.Sell,
|
|
meta: {
|
|
txOrigin,
|
|
taker: takerAddress,
|
|
client: apiKey,
|
|
},
|
|
amount: '100',
|
|
};
|
|
// Successful response
|
|
const buyAmountAltResponse = {
|
|
...buyAmountAltRequest,
|
|
id: 'random_id',
|
|
// tslint:disable-next-line:custom-no-magic-numbers
|
|
price: new BigNumber(0.01).toString(),
|
|
status: 'live',
|
|
};
|
|
const successfulBuyAmountQuote: V4RFQIndicativeQuote = {
|
|
makerToken: baseToken,
|
|
takerToken: quoteToken,
|
|
makerAmount: new BigNumber(10000),
|
|
takerAmount: new BigNumber(1000),
|
|
expiry: new BigNumber(0),
|
|
};
|
|
altMockedRequests.push({
|
|
endpoint: 'https://132.0.0.1',
|
|
mmApiKey: ALT_MM_API_KEY,
|
|
responseCode: StatusCodes.Success,
|
|
requestData: buyAmountAltRequest,
|
|
responseData: buyAmountAltResponse,
|
|
});
|
|
altScenarios.push({
|
|
successfulQuote: successfulBuyAmountQuote,
|
|
requestedMakerToken: baseToken,
|
|
requestedTakerToken: quoteToken,
|
|
requestedAmount: new BigNumber(10000),
|
|
requestedOperation: MarketOperation.Buy,
|
|
});
|
|
|
|
// SCENARIO 2
|
|
// alt buy, quote asset specified
|
|
// user is requesting to sell 1 unit of the quote token, or 1000 base units
|
|
// returning a price of 0.01, which should mean 10000 maker amount, 1000 taker amount
|
|
const buyValueAltRequest: AltQuoteRequestData = {
|
|
market: 'XYZ-123',
|
|
model: AltQuoteModel.Indicative,
|
|
profile: ALT_PROFILE,
|
|
side: AltQuoteSide.Sell,
|
|
meta: {
|
|
txOrigin,
|
|
taker: takerAddress,
|
|
client: apiKey,
|
|
},
|
|
value: '1',
|
|
};
|
|
// Successful response
|
|
const buyValueAltResponse = {
|
|
...buyValueAltRequest,
|
|
id: 'random_id',
|
|
// tslint:disable-next-line:custom-no-magic-numbers
|
|
price: new BigNumber(0.01).toString(),
|
|
status: 'live',
|
|
};
|
|
const successfulBuyValueQuote: V4RFQIndicativeQuote = {
|
|
makerToken: baseToken,
|
|
takerToken: quoteToken,
|
|
makerAmount: new BigNumber(10000),
|
|
takerAmount: new BigNumber(1000),
|
|
expiry: new BigNumber(0),
|
|
};
|
|
altMockedRequests.push({
|
|
endpoint: 'https://132.0.0.1',
|
|
mmApiKey: ALT_MM_API_KEY,
|
|
responseCode: StatusCodes.Success,
|
|
requestData: buyValueAltRequest,
|
|
responseData: buyValueAltResponse,
|
|
});
|
|
altScenarios.push({
|
|
successfulQuote: successfulBuyValueQuote,
|
|
requestedMakerToken: baseToken,
|
|
requestedTakerToken: quoteToken,
|
|
requestedAmount: new BigNumber(1000),
|
|
requestedOperation: MarketOperation.Sell,
|
|
});
|
|
|
|
// SCENARIO 3
|
|
// alt sell, base asset specified
|
|
// user is requesting to sell 100 units (10000 base units) of the base token
|
|
// returning a price of 0.01, which should mean 10000 taker amount, 1000 maker amount
|
|
const sellAmountAltRequest: AltQuoteRequestData = {
|
|
market: 'XYZ-123',
|
|
model: AltQuoteModel.Indicative,
|
|
profile: ALT_PROFILE,
|
|
side: AltQuoteSide.Buy,
|
|
meta: {
|
|
txOrigin,
|
|
taker: takerAddress,
|
|
client: apiKey,
|
|
},
|
|
amount: '100',
|
|
};
|
|
// Successful response
|
|
const sellAmountAltResponse = {
|
|
...sellAmountAltRequest,
|
|
id: 'random_id',
|
|
// tslint:disable-next-line:custom-no-magic-numbers
|
|
price: new BigNumber(0.01).toString(),
|
|
status: 'live',
|
|
};
|
|
const successfulSellAmountQuote: V4RFQIndicativeQuote = {
|
|
makerToken: quoteToken,
|
|
takerToken: baseToken,
|
|
makerAmount: new BigNumber(1000),
|
|
takerAmount: new BigNumber(10000),
|
|
expiry: new BigNumber(0),
|
|
};
|
|
altMockedRequests.push({
|
|
endpoint: 'https://132.0.0.1',
|
|
mmApiKey: ALT_MM_API_KEY,
|
|
responseCode: StatusCodes.Success,
|
|
requestData: sellAmountAltRequest,
|
|
responseData: sellAmountAltResponse,
|
|
});
|
|
altScenarios.push({
|
|
successfulQuote: successfulSellAmountQuote,
|
|
requestedMakerToken: quoteToken,
|
|
requestedTakerToken: baseToken,
|
|
requestedAmount: new BigNumber(10000),
|
|
requestedOperation: MarketOperation.Sell,
|
|
});
|
|
|
|
// SCENARIO 4
|
|
// alt sell, quote asset specified
|
|
// user is requesting to buy 1 unit (1000 base units) of the quote token
|
|
// returning a price of 0.01, which should mean 10000 taker amount, 1000 maker amount
|
|
const sellValueAltRequest: AltQuoteRequestData = {
|
|
market: 'XYZ-123',
|
|
model: AltQuoteModel.Indicative,
|
|
profile: ALT_PROFILE,
|
|
side: AltQuoteSide.Buy,
|
|
meta: {
|
|
txOrigin,
|
|
taker: takerAddress,
|
|
client: apiKey,
|
|
},
|
|
value: '1',
|
|
};
|
|
// Successful response
|
|
const sellValueAltResponse = {
|
|
...sellValueAltRequest,
|
|
id: 'random_id',
|
|
// tslint:disable-next-line:custom-no-magic-numbers
|
|
price: new BigNumber(0.01).toString(),
|
|
status: 'live',
|
|
};
|
|
const successfulSellValueQuote: V4RFQIndicativeQuote = {
|
|
makerToken: quoteToken,
|
|
takerToken: baseToken,
|
|
makerAmount: new BigNumber(1000),
|
|
takerAmount: new BigNumber(10000),
|
|
expiry: new BigNumber(0),
|
|
};
|
|
altMockedRequests.push({
|
|
endpoint: 'https://132.0.0.1',
|
|
mmApiKey: ALT_MM_API_KEY,
|
|
responseCode: StatusCodes.Success,
|
|
requestData: sellValueAltRequest,
|
|
responseData: sellValueAltResponse,
|
|
});
|
|
altScenarios.push({
|
|
successfulQuote: successfulSellValueQuote,
|
|
requestedMakerToken: quoteToken,
|
|
requestedTakerToken: baseToken,
|
|
requestedAmount: new BigNumber(1000),
|
|
requestedOperation: MarketOperation.Buy,
|
|
});
|
|
|
|
let scenarioCounter = 1;
|
|
for (const altScenario of altScenarios) {
|
|
logUtils.log(`Alt MM indicative scenario ${scenarioCounter}`);
|
|
scenarioCounter += 1;
|
|
await testHelpers.withMockedRfqtQuotes(
|
|
[],
|
|
altMockedRequests,
|
|
RfqtQuoteEndpoint.Indicative,
|
|
async () => {
|
|
const qr = new QuoteRequestor({}, ALT_RFQ_CREDS);
|
|
const resp = await qr.requestRfqtIndicativeQuotesAsync(
|
|
altScenario.requestedMakerToken,
|
|
altScenario.requestedTakerToken,
|
|
altScenario.requestedAmount,
|
|
altScenario.requestedOperation,
|
|
undefined,
|
|
{
|
|
apiKey,
|
|
takerAddress,
|
|
txOrigin,
|
|
intentOnFilling: true,
|
|
altRfqtAssetOfferings,
|
|
},
|
|
);
|
|
// hack to get the expiry right, since it's dependent on the current timestamp
|
|
const expected = { ...altScenario.successfulQuote, expiry: resp[0].expiry };
|
|
expect(resp.sort()).to.eql([expected].sort());
|
|
},
|
|
quoteRequestorHttpClient,
|
|
);
|
|
}
|
|
});
|
|
});
|
|
});
|