Skip to content
This repository was archived by the owner on Oct 15, 2024. It is now read-only.

Commit 11cb5a8

Browse files
author
Steve Klebanoff
authored
RFQT: More tests (#170)
* generate source maps * abstract tests out into nested contexts * test for skipping validation * dont include order for maker who does not have allowances set * bad api key test * fix test names and explicitly deposit so taker can fill
1 parent e1693bb commit 11cb5a8

File tree

2 files changed

+232
-53
lines changed

2 files changed

+232
-53
lines changed

test/app_test.ts

+231-52
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ let provider: Web3ProviderEngine;
2323
let accounts: string[];
2424
let blockchainLifecycle: BlockchainLifecycle;
2525

26+
// tslint:disable-next-line:custom-no-magic-numbers
27+
const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
28+
2629
describe('app test', () => {
2730
before(async () => {
2831
// start ganache and run contract migrations
@@ -74,59 +77,235 @@ describe('app test', () => {
7477
});
7578
});
7679
});
77-
describe('should hit RFQ-T when apropriate', () => {
78-
it('should get a quote from an RFQ-T provider', async () => {
79-
const [makerAddress, takerAddress] = accounts;
80-
const sellAmount = new BigNumber(100000000000000000);
81-
82-
const contractAddresses: ContractAddresses = getContractAddressesForChainOrThrow(
83-
parseInt(process.env.CHAIN_ID || '1337', 10),
84-
);
85-
86-
const wethContract = new WETH9Contract(contractAddresses.etherToken, provider);
87-
await wethContract.deposit().sendTransactionAsync({ value: sellAmount, from: takerAddress });
88-
await wethContract
89-
.approve(contractAddresses.erc20Proxy, sellAmount)
90-
.sendTransactionAsync({ from: takerAddress });
91-
92-
const zrxToken = new ERC20TokenContract(contractAddresses.zrxToken, provider);
93-
await zrxToken.approve(contractAddresses.erc20Proxy, sellAmount).sendTransactionAsync(
94-
// using buyAmount based on assumption that the RFQ-T provider will be using a "one-to-one" strategy.
95-
{ from: makerAddress },
96-
);
97-
// done setting balances and allowances
98-
99-
const mockedApiParams = {
100-
sellToken: contractAddresses.etherToken,
101-
buyToken: contractAddresses.zrxToken,
102-
sellAmount: sellAmount.toString(),
103-
buyAmount: undefined,
104-
takerAddress,
105-
};
106-
return rfqtMocker.withMockedRfqtFirmQuotes(
107-
[
108-
{
109-
endpoint: 'https://mock-rfqt1.club',
110-
responseData: ganacheZrxWethOrder1,
111-
responseCode: 200,
112-
requestApiKey: 'koolApiKey1',
113-
requestParams: mockedApiParams,
80+
describe('should hit RFQ-T when apropriate', async () => {
81+
let contractAddresses: ContractAddresses;
82+
let makerAddress: string;
83+
let takerAddress: string;
84+
85+
beforeEach(() => {
86+
contractAddresses = getContractAddressesForChainOrThrow(parseInt(process.env.CHAIN_ID || '1337', 10));
87+
[makerAddress, takerAddress] = accounts;
88+
});
89+
90+
context('with maker allowances set', async () => {
91+
beforeEach(async () => {
92+
const zrxToken = new ERC20TokenContract(contractAddresses.zrxToken, provider);
93+
await zrxToken
94+
.approve(contractAddresses.erc20Proxy, MAX_UINT256)
95+
.sendTransactionAsync({ from: makerAddress });
96+
});
97+
98+
context('getting a quote from an RFQ-T provider', async () => {
99+
it('should succeed when taker has balances and amounts', async () => {
100+
const sellAmount = new BigNumber(100000000000000000);
101+
102+
const wethContract = new WETH9Contract(contractAddresses.etherToken, provider);
103+
await wethContract.deposit().sendTransactionAsync({ value: sellAmount, from: takerAddress });
104+
await wethContract
105+
.approve(contractAddresses.erc20Proxy, sellAmount)
106+
.sendTransactionAsync({ from: takerAddress });
107+
108+
const mockedApiParams = {
109+
sellToken: contractAddresses.etherToken,
110+
buyToken: contractAddresses.zrxToken,
111+
sellAmount: sellAmount.toString(),
112+
buyAmount: undefined,
113+
takerAddress,
114+
};
115+
return rfqtMocker.withMockedRfqtFirmQuotes(
116+
[
117+
{
118+
endpoint: 'https://mock-rfqt1.club',
119+
responseData: ganacheZrxWethOrder1,
120+
responseCode: 200,
121+
requestApiKey: 'koolApiKey1',
122+
requestParams: mockedApiParams,
123+
},
124+
],
125+
async () => {
126+
const appResponse = await request(app)
127+
.get(
128+
`${SWAP_PATH}/quote?buyToken=ZRX&sellToken=WETH&sellAmount=${sellAmount.toString()}&takerAddress=${takerAddress}&intentOnFilling=true&excludedSources=Uniswap,Eth2Dai,Kyber,LiquidityProvider`,
129+
)
130+
.set('0x-api-key', 'koolApiKey1')
131+
.expect(HttpStatus.OK)
132+
.expect('Content-Type', /json/);
133+
134+
const responseJson = JSON.parse(appResponse.text);
135+
expect(responseJson.orders.length).to.equal(1);
136+
expect(responseJson.orders[0]).to.eql(ganacheZrxWethOrder1);
137+
},
138+
);
139+
});
140+
it('should succeed when taker can not actually fill but we skip validation', async () => {
141+
const sellAmount = new BigNumber(100000000000000000);
142+
143+
const wethContract = new WETH9Contract(contractAddresses.etherToken, provider);
144+
await wethContract
145+
.approve(contractAddresses.erc20Proxy, new BigNumber(0))
146+
.sendTransactionAsync({ from: takerAddress });
147+
148+
const mockedApiParams = {
149+
sellToken: contractAddresses.etherToken,
150+
buyToken: contractAddresses.zrxToken,
151+
sellAmount: sellAmount.toString(),
152+
buyAmount: undefined,
153+
takerAddress,
154+
};
155+
return rfqtMocker.withMockedRfqtFirmQuotes(
156+
[
157+
{
158+
endpoint: 'https://mock-rfqt1.club',
159+
responseData: ganacheZrxWethOrder1,
160+
responseCode: 200,
161+
requestApiKey: 'koolApiKey1',
162+
requestParams: mockedApiParams,
163+
},
164+
],
165+
async () => {
166+
const appResponse = await request(app)
167+
.get(
168+
`${SWAP_PATH}/quote?buyToken=ZRX&sellToken=WETH&sellAmount=${sellAmount.toString()}&takerAddress=${takerAddress}&intentOnFilling=true&excludedSources=Uniswap,Eth2Dai,Kyber,LiquidityProvider&skipValidation=true`,
169+
)
170+
.set('0x-api-key', 'koolApiKey1')
171+
.expect(HttpStatus.OK)
172+
.expect('Content-Type', /json/);
173+
const responseJson = JSON.parse(appResponse.text);
174+
expect(responseJson.orders.length).to.equal(1);
175+
expect(responseJson.orders[0]).to.eql(ganacheZrxWethOrder1);
176+
},
177+
);
178+
});
179+
it('should fail when bad api key used', async () => {
180+
const sellAmount = new BigNumber(100000000000000000);
181+
182+
const wethContract = new WETH9Contract(contractAddresses.etherToken, provider);
183+
await wethContract.deposit().sendTransactionAsync({ value: sellAmount, from: takerAddress });
184+
await wethContract
185+
.approve(contractAddresses.erc20Proxy, new BigNumber(0))
186+
.sendTransactionAsync({ from: takerAddress });
187+
188+
// this RFQ-T mock should never actually get hit b/c of the bad api key
189+
// but in the case in which the bad api key was _not_ blocked
190+
// this would cause the API to respond with RFQ-T liquidity
191+
const mockedApiParams = {
192+
sellToken: contractAddresses.etherToken,
193+
buyToken: contractAddresses.zrxToken,
194+
sellAmount: sellAmount.toString(),
195+
buyAmount: undefined,
196+
takerAddress,
197+
};
198+
return rfqtMocker.withMockedRfqtFirmQuotes(
199+
[
200+
{
201+
endpoint: 'https://mock-rfqt1.club',
202+
responseData: ganacheZrxWethOrder1,
203+
responseCode: 200,
204+
requestApiKey: 'badApiKey',
205+
requestParams: mockedApiParams,
206+
},
207+
],
208+
async () => {
209+
const appResponse = await request(app)
210+
.get(
211+
`${SWAP_PATH}/quote?buyToken=ZRX&sellToken=WETH&sellAmount=${sellAmount.toString()}&takerAddress=${takerAddress}&intentOnFilling=true&excludedSources=Uniswap,Eth2Dai,Kyber,LiquidityProvider&skipValidation=true`,
212+
)
213+
.set('0x-api-key', 'badApiKey')
214+
.expect(HttpStatus.BAD_REQUEST)
215+
.expect('Content-Type', /json/);
216+
const validationErrors = appResponse.body.validationErrors;
217+
expect(validationErrors.length).to.eql(1);
218+
expect(validationErrors[0].reason).to.eql('INSUFFICIENT_ASSET_LIQUIDITY');
219+
},
220+
);
221+
});
222+
it('should fail validation when taker can not actually fill', async () => {
223+
const sellAmount = new BigNumber(100000000000000000);
224+
225+
const wethContract = new WETH9Contract(contractAddresses.etherToken, provider);
226+
await wethContract
227+
.approve(contractAddresses.erc20Proxy, new BigNumber(0))
228+
.sendTransactionAsync({ from: takerAddress });
229+
230+
const mockedApiParams = {
231+
sellToken: contractAddresses.etherToken,
232+
buyToken: contractAddresses.zrxToken,
233+
sellAmount: sellAmount.toString(),
234+
buyAmount: undefined,
235+
takerAddress,
236+
};
237+
return rfqtMocker.withMockedRfqtFirmQuotes(
238+
[
239+
{
240+
endpoint: 'https://mock-rfqt1.club',
241+
responseData: ganacheZrxWethOrder1,
242+
responseCode: 200,
243+
requestApiKey: 'koolApiKey1',
244+
requestParams: mockedApiParams,
245+
},
246+
],
247+
async () => {
248+
await request(app)
249+
.get(
250+
`${SWAP_PATH}/quote?buyToken=ZRX&sellToken=WETH&sellAmount=${sellAmount.toString()}&takerAddress=${takerAddress}&intentOnFilling=true&excludedSources=Uniswap,Eth2Dai,Kyber,LiquidityProvider`,
251+
)
252+
.set('0x-api-key', 'koolApiKey1')
253+
.expect(HttpStatus.BAD_REQUEST)
254+
.expect('Content-Type', /json/);
255+
},
256+
);
257+
});
258+
});
259+
});
260+
261+
context('without maker allowances set', async () => {
262+
beforeEach(async () => {
263+
const zrxToken = new ERC20TokenContract(contractAddresses.zrxToken, provider);
264+
await zrxToken
265+
.approve(contractAddresses.erc20Proxy, new BigNumber(0))
266+
.sendTransactionAsync({ from: makerAddress });
267+
});
268+
269+
it('should not return order if maker allowances are not set', async () => {
270+
const sellAmount = new BigNumber(100000000000000000);
271+
272+
const wethContract = new WETH9Contract(contractAddresses.etherToken, provider);
273+
await wethContract
274+
.approve(contractAddresses.erc20Proxy, new BigNumber(0))
275+
.sendTransactionAsync({ from: takerAddress });
276+
277+
const mockedApiParams = {
278+
sellToken: contractAddresses.etherToken,
279+
buyToken: contractAddresses.zrxToken,
280+
sellAmount: sellAmount.toString(),
281+
buyAmount: undefined,
282+
takerAddress,
283+
};
284+
return rfqtMocker.withMockedRfqtFirmQuotes(
285+
[
286+
{
287+
endpoint: 'https://mock-rfqt1.club',
288+
responseData: ganacheZrxWethOrder1,
289+
responseCode: 200,
290+
requestApiKey: 'koolApiKey1',
291+
requestParams: mockedApiParams,
292+
},
293+
],
294+
async () => {
295+
const appResponse = await request(app)
296+
.get(
297+
`${SWAP_PATH}/quote?buyToken=ZRX&sellToken=WETH&sellAmount=${sellAmount.toString()}&takerAddress=${takerAddress}&intentOnFilling=true&excludedSources=Uniswap,Eth2Dai,Kyber,LiquidityProvider&skipValidation=true`,
298+
)
299+
.set('0x-api-key', 'koolApiKey1')
300+
.expect(HttpStatus.BAD_REQUEST)
301+
.expect('Content-Type', /json/);
302+
303+
const validationErrors = appResponse.body.validationErrors;
304+
expect(validationErrors.length).to.eql(1);
305+
expect(validationErrors[0].reason).to.eql('INSUFFICIENT_ASSET_LIQUIDITY');
114306
},
115-
],
116-
async () => {
117-
const appResponse = await request(app)
118-
.get(
119-
`${SWAP_PATH}/quote?buyToken=ZRX&sellToken=WETH&sellAmount=${sellAmount.toString()}&takerAddress=${takerAddress}&intentOnFilling=true&excludedSources=Uniswap,Eth2Dai,Kyber,LiquidityProvider`,
120-
)
121-
.set('0x-api-key', 'koolApiKey1')
122-
.expect(HttpStatus.OK)
123-
.expect('Content-Type', /json/);
124-
125-
const responseJson = JSON.parse(appResponse.text);
126-
expect(responseJson.orders.length).to.equal(1);
127-
expect(responseJson.orders[0]).to.eql(ganacheZrxWethOrder1);
128-
},
129-
);
307+
);
308+
});
130309
});
131310
});
132311
});

tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"noUnusedLocals": true,
1010
"emitDecoratorMetadata": true,
1111
"experimentalDecorators": true,
12-
"sourceMap": false,
12+
"sourceMap": true,
1313
"typeRoots": ["./node_modules/@0x/typescript-typings/types", "./node_modules/@types"],
1414
"noUnusedParameters": true,
1515
"resolveJsonModule": true

0 commit comments

Comments
 (0)