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

RFQ-T Firm Quotes #162

Merged
merged 37 commits into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d3cfe8e
test: Stop running contract migrations
feuGeneA Apr 6, 2020
05ca1b6
Add test of /swap/v0/quote endpoint
feuGeneA Mar 11, 2020
e026de2
Add and use RFQ-T configuration types
feuGeneA Mar 13, 2020
0a0de81
yarn clean: separate docker from ts
feuGeneA Mar 31, 2020
89ff735
Only run prettier on ./src
feuGeneA Apr 7, 2020
61cbd5c
Include prettier in lint
feuGeneA Apr 7, 2020
268bff8
yarn add --dev make-promises-safe
feuGeneA Apr 7, 2020
2578a79
Adapt to new RFQ-T namespace in SwapQuoterOpts
feuGeneA Apr 9, 2020
6b21a39
Adapt to new RFQ-T namespace in SwapQuoterReqOpts
feuGeneA Apr 9, 2020
d11b850
Revert addition of env var defs to `yarn dev`
feuGeneA Apr 9, 2020
b126316
Don't enforce presence of taker address
feuGeneA Apr 9, 2020
cbecfc4
Enforce a specific value for intentOnFilling
feuGeneA Apr 9, 2020
902b15d
Remove unused apiKey parameter
feuGeneA Apr 9, 2020
bdc7bae
Add `rfqt:` namespace for RFQ-T specific options
feuGeneA Apr 9, 2020
47227ad
Parse RFQT environment variables as CSV, not JSON
feuGeneA Apr 10, 2020
0255b25
Set RFQT taker address to Forwarder for ETH sales
feuGeneA Apr 10, 2020
29d6215
Restore accidentally deleted line in recent commit.
feuGeneA Apr 10, 2020
b0488ef
Add metadata for dummy kovan tokens
feuGeneA Apr 10, 2020
e50fc98
introduce new test using rfqtMocker
Apr 10, 2020
e150eec
HACK: fix ganache-core bug
feuGeneA Apr 7, 2020
7c448d3
TEMPORARY: use gene's ganache snapshot for tests
feuGeneA Apr 6, 2020
08f4d31
TEMPORARY: Update gitpkg monorepo references
feuGeneA Apr 6, 2020
f325f42
Enable prettier for {.,test}/**/*.{ts,tsx,json,md}
feuGeneA Apr 15, 2020
ea8c8e9
Add SwapQuoteRequestParam `skipValidation`
feuGeneA Apr 15, 2020
0633aca
Add API Key and `intentOnFilling` to API schema
feuGeneA Apr 15, 2020
556a45b
Parse present but empty intentOnFilling as true
feuGeneA Apr 15, 2020
e1693bb
Fix bug: env var csv split was wrongly applied
feuGeneA Apr 15, 2020
11cb5a8
RFQT: More tests (#170)
Apr 16, 2020
bb2814a
Validate bool query params as enum, not presence
feuGeneA Apr 16, 2020
74d3ea7
Add comments around using Forwarder as Taker
feuGeneA Apr 16, 2020
6a0aed8
Test no quote provided when taker address absent
feuGeneA Apr 16, 2020
fb176a5
Revert "TEMPORARY: Update gitpkg monorepo references"
feuGeneA Apr 16, 2020
2e7c7bb
Revert "TEMPORARY: use gene's ganache snapshot for tests"
feuGeneA Apr 16, 2020
3ed896f
Pin updated monorepo deps to development revision
feuGeneA Apr 16, 2020
c772d43
Pin tests' ganache snapshot to monorepo commit
feuGeneA Apr 16, 2020
735fe3e
Simplify expressions parsing boolean query params
feuGeneA Apr 16, 2020
bf835d0
Merge branch 'master' into rfqt
feuGeneA Apr 16, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ jobs:
- image: circleci/node:8.12.0-browsers
- image: circleci/postgres:9.6.5-alpine-ram
- image: 0xorg/ganache-cli:6.0.0
environment:
SNAPSHOT_NAME: 0x_ganache_snapshot_gene
feuGeneA marked this conversation as resolved.
Show resolved Hide resolved
VERSION: 6.2.4
- image: 0xorg/mesh:9.0.1
environment:
ETHEREUM_RPC_URL: http://0.0.0.0:8545
Expand Down
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ services:
image: "0xorg/ganache-cli:6.0.0"
ports:
- "8545:8545"
environment:
SNAPSHOT_NAME: 0x_ganache_snapshot_gene
VERSION: 6.2.4
postgres:
image: postgres:9.6
environment:
Expand Down
24 changes: 15 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,38 @@
"author": "Francesco Agosti <[email protected]>",
"license": "Apache-2.0",
"scripts": {
"clean": "shx rm -rf lib 0x_mesh/db",
"install": "sed -ie 's!import { Provider as Web3Provider } from \"web3/providers\";!import { Web3EthereumProvider as Web3Provider } from \"web3-providers\";!' node_modules/ganache-core/typings/index.d.ts # see https://github.com/trufflesuite/ganache-core/issues/465#issuecomment-610005598",
feuGeneA marked this conversation as resolved.
Show resolved Hide resolved
"clean": "yarn clean:ts && yarn clean:docker",
"clean:ts": "shx rm -rf lib",
"clean:docker": "shx rm -rf 0x_mesh/db",
"build": "tsc -p tsconfig.json",
"test": "ETHEREUM_RPC_URL=http://localhost:8545 mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --timeout 100000 --exit",
"test": "ETHEREUM_RPC_URL=http://localhost:8545 CHAIN_ID=1337 RFQT_API_KEY_WHITELIST='koolApiKey1,koolApikey2' RFQT_MAKER_ENDPOINTS='https://mock-rfqt1.club' mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --timeout 100000 --exit",
"dev": "nodemon -r dotenv/config src/index.ts | pino-pretty",
"dev:service:http": "nodemon -r dotenv/config src/runners/http_service_runner.ts | pino-pretty",
"dev:service:sra_http": "nodemon -r dotenv/config src/runners/http_sra_service_runner.ts | pino-pretty",
"dev:service:staking_http": "nodemon -r dotenv/config src/runners/http_staking_service_runner.ts | pino-pretty",
"dev:service:swap_http": "nodemon -r dotenv/config src/runners/http_swap_service_runner.ts | pino-pretty",
"dev:service:order_watcher": "nodemon -r dotenv/config src/runners/order_watcher_service_runner.ts | pino-pretty",
"watch": "tsc -w",
"prettier": "prettier --write '**/*.{ts,tsx,json,md}' --config .prettierrc",
"prettier:ci": "prettier --list-different '**/*.{ts,tsx,json,md}' --config .prettierrc",
"prettier": "prettier --write ${npm_package_config_prettier_target} --config .prettierrc",
"prettier:ci": "prettier --list-different ${npm_package_config_prettier_target} --config .prettierrc",
"start": "node -r dotenv/config lib/src/index.js",
"start:service:http": "node -r dotenv/config lib/src/runners/http_service_runner.js",
"start:service:sra_http": "node -r dotenv/config lib/src/runners/http_sra_service_runner.js",
"start:service:staking_http": "node -r dotenv/config lib/src/runners/http_staking_service_runner.js",
"start:service:swap_http": "node -r dotenv/config lib/src/runners/http_swap_service_runner.js",
"start:service:order_watcher": "node -r dotenv/config lib/src/runners/order_watcher_service_runner.js",
"lint": "tslint --project . --format stylish"
"lint": "tslint --project . --format stylish && yarn prettier:ci"
},
"config": {
"prettier_target": "{.,test/**,src/**}/*.{ts,tsx,json,md}"
},
"resolutions": {
"@0x/contract-addresses": "0xProject/gitpkg-registry#0x-contract-addresses-v4.9.0-58b6c25d5",
"@0x/contract-addresses": "0xProject/gitpkg-registry#0x-contract-addresses-v4.9.0-264407b70",
"@0x/contract-wrappers": "0xProject/gitpkg-registry#0x-contract-wrappers-v13.6.3-e3f3bb670"
},
"devDependencies": {
"@0x/dev-utils": "^3.1.1",
"@0x/migrations": "^5.0.2",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.1",
"@0x/typescript-typings": "^5.0.1",
Expand All @@ -48,6 +53,7 @@
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^5.1.0",
"mocha": "^6.2.2",
"nodemon": "^1.19.4",
"pino-pretty": "^3.2.2",
Expand All @@ -60,9 +66,9 @@
},
"dependencies": {
"@0x/assert": "^3.0.4",
"@0x/asset-swapper": "0xProject/gitpkg-registry#0x-asset-swapper-v4.4.0-aaa62beca",
"@0x/asset-swapper": "0xProject/gitpkg-registry#0x-asset-swapper-v4.4.0-513ddb4cc",
"@0x/connect": "^6.0.4",
"@0x/contract-addresses": "0xProject/gitpkg-registry#0x-contract-addresses-v4.9.0-58b6c25d5",
"@0x/contract-addresses": "0xProject/gitpkg-registry#0x-contract-addresses-v4.9.0-264407b70",
"@0x/contract-wrappers": "0xProject/gitpkg-registry#0x-contract-wrappers-v13.6.3-e3f3bb670",
"@0x/json-schemas": "^5.0.4",
"@0x/mesh-rpc-client": "^9.0.1",
Expand Down
6 changes: 6 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ export const LIQUIDITY_POOL_REGISTRY_ADDRESS: string | undefined = _.isEmpty(
EnvVarType.ETHAddressHex,
);

export const RFQT_API_KEY_WHITELIST: string[] =
process.env.RFQT_API_KEY_WHITELIST === undefined ? [] : process.env.RFQT_API_KEY_WHITELIST.split(',');

export const RFQT_MAKER_ENDPOINTS: string[] =
process.env.RFQT_MAKER_ENDPOINTS === undefined ? [] : process.env.RFQT_MAKER_ENDPOINTS.split(',');

// Max number of entities per page
export const MAX_PER_PAGE = 1000;
// Default ERC20 token precision
Expand Down
22 changes: 22 additions & 0 deletions src/handlers/swap_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export class SwapHandlers {
gasPrice,
excludedSources,
affiliateAddress,
rfqt,
// tslint:disable-next-line:boolean-naming
skipValidation,
} = parseGetSwapQuoteRequestParams(req);
const isETHSell = isETHSymbol(sellToken);
const sellTokenAddress = findTokenAddressOrThrowApiError(sellToken, 'sellToken', CHAIN_ID);
Expand Down Expand Up @@ -63,6 +66,14 @@ export class SwapHandlers {
gasPrice,
excludedSources,
affiliateAddress,
apiKey: req.header('0x-api-key'),
rfqt:
rfqt === undefined
? undefined
: {
intentOnFilling: rfqt.intentOnFilling,
},
skipValidation,
});
res.status(HttpStatus.OK).send(swapQuote);
} catch (e) {
Expand Down Expand Up @@ -166,6 +177,15 @@ const parseGetSwapQuoteRequestParams = (req: express.Request): GetSwapQuoteReque
? undefined
: parseStringArrForERC20BridgeSources(req.query.excludedSources.split(','));
const affiliateAddress = req.query.affiliateAddress;
const rfqt =
req.query.intentOnFilling === undefined
? undefined
: {
intentOnFilling: ['true', ''].includes(req.query.intentOnFilling) ? true : false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just do something like the following?

const rfqt = req.query.intentOnFilling === 'true'  ? { intentOnFilling: true } : undefined;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some digging when I updated the schemas here. I had initially wanted to make them type: "boolean" (whatever exactly that would mean!) but the jsonschema package didn't handle that nicely. Later discovered this question which is a good analog to what we're doing here: OAI/OpenAPI-Specification#1782

I changed this here because I liked the idea of the mere presence of this flag indicating it should be true, eg /quote?intentOnFilling&....

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How we resolve #162 (comment) will impact this

};
// tslint:disable-next-line:boolean-naming
const skipValidation =
req.query.skipValidation === undefined ? false : ['true', ''].includes(req.query.skipValidation) ? true : false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want to consider req.query.skipValidation === '' as true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same logic behind my recent change to intentOnFilling. I think it makes logical sense to be able to say just /quote?skipValidation&..., and when that's the query string, req.query here contains "skipValidation": "".

return {
takerAddress,
sellToken,
Expand All @@ -176,5 +196,7 @@ const parseGetSwapQuoteRequestParams = (req: express.Request): GetSwapQuoteReque
gasPrice,
excludedSources,
affiliateAddress,
rfqt,
skipValidation,
};
};
11 changes: 11 additions & 0 deletions src/schemas/swap_quote_request_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@
},
"excludedSources": {
"type": "string"
},
"apiKey": {
"type": "string"
},
"intentOnFilling": {
"type": "string",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to. I tried. jsonschema choked on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At test runtime i get this json schema error

{\"field\":\"instance.intentOnFilling\",\"code\":1001,\"reason\":\"is not of a type(s) boolean\"}

This happened no matter whether my client said quote?intentOnFilling or quote?intenOnFilling=true.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.

I think this schema could be cleaner if we:

This would allow ?skipValidation=truue to raise a schema error instead of silently being set to false on our backend.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How's this: bb2814a

"allowEmptyValue": true
},
"skipValidation": {
"type": "string",
"allowEmptyValue": true
}
},
"required": ["sellToken", "buyToken"],
Expand Down
22 changes: 21 additions & 1 deletion src/services/swap_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
SwapQuoter,
SwapQuoterOpts,
steveklebanoff marked this conversation as resolved.
Show resolved Hide resolved
} from '@0x/asset-swapper';
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { assetDataUtils, SupportedProvider } from '@0x/order-utils';
import { AbiEncoder, BigNumber, decodeThrownErrorAsRevertError, RevertError } from '@0x/utils';
import { TxData, Web3Wrapper } from '@0x/web3-wrapper';
Expand All @@ -20,10 +21,13 @@ import {
CHAIN_ID,
FEE_RECIPIENT_ADDRESS,
LIQUIDITY_POOL_REGISTRY_ADDRESS,
RFQT_API_KEY_WHITELIST,
RFQT_MAKER_ENDPOINTS,
} from '../config';
import {
DEFAULT_TOKEN_DECIMALS,
GAS_LIMIT_BUFFER_PERCENTAGE,
NULL_ADDRESS,
ONE_SECOND_MS,
PERCENTAGE_SIG_DIGITS,
QUOTE_ORDER_EXPIRATION_BUFFER_MS,
Expand Down Expand Up @@ -51,6 +55,10 @@ export class SwapService {
chainId: CHAIN_ID,
expiryBufferMs: QUOTE_ORDER_EXPIRATION_BUFFER_MS,
liquidityProviderRegistryAddress: LIQUIDITY_POOL_REGISTRY_ADDRESS,
feuGeneA marked this conversation as resolved.
Show resolved Hide resolved
rfqt: {
takerApiKeyWhitelist: RFQT_API_KEY_WHITELIST,
makerEndpoints: RFQT_MAKER_ENDPOINTS,
},
};
this._swapQuoter = new SwapQuoter(this._provider, orderbook, swapQuoterOpts);
this._swapQuoteConsumer = new SwapQuoteConsumer(this._provider, swapQuoterOpts);
Expand All @@ -69,13 +77,25 @@ export class SwapService {
from,
excludedSources,
affiliateAddress,
apiKey,
rfqt,
// tslint:disable-next-line:boolean-naming
skipValidation,
} = params;
const assetSwapperOpts = {
...ASSET_SWAPPER_MARKET_ORDERS_OPTS,
slippagePercentage,
bridgeSlippage: slippagePercentage,
gasPrice: providedGasPrice,
excludedSources, // TODO(dave4506): overrides the excluded sources selected by chainId
apiKey,
rfqt:
rfqt === undefined || from === undefined || from === NULL_ADDRESS
? undefined
: {
...rfqt,
takerAddress: isETHSell ? getContractAddressesForChainOrThrow(CHAIN_ID).forwarder : from,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to add a comment describing what's happening here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 03f7673

},
};
if (sellAmount !== undefined) {
swapQuote = await this._swapQuoter.getMarketSellSwapQuoteAsync(
Expand Down Expand Up @@ -120,7 +140,7 @@ export class SwapService {
const affiliatedData = this._attributeCallData(data, affiliateAddress);

let suggestedGasEstimate = new BigNumber(gas);
if (from) {
if (!skipValidation && from) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// Force a revert error if the takerAddress does not have enough ETH.
const txDataValue =
extensionContractType === ExtensionContractType.Forwarder
Expand Down
20 changes: 20 additions & 0 deletions src/token_metadatas_for_networks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,4 +637,24 @@ export const TokenMetadatasForChains: TokenMetadataAndChainAddresses[] = [
[ChainId.Ganache]: NULL_ADDRESS,
},
},
{
symbol: 'ZWETH',
name: 'Custom Kovan Wrapped Ether',
decimals: 18,
tokenAddresses: {
[ChainId.Mainnet]: NULL_ADDRESS,
[ChainId.Kovan]: '0x1FcAf05ABa8c7062D6F08E25c77Bf3746fCe5433',
[ChainId.Ganache]: NULL_ADDRESS,
},
},
{
symbol: 'ZUSDC',
name: 'Custom Kovan USD Coin',
decimals: 6,
tokenAddresses: {
[ChainId.Mainnet]: NULL_ADDRESS,
[ChainId.Kovan]: '0x5a719Cf3E02c17c876F6d294aDb5CB7C6eB47e2F',
[ChainId.Ganache]: NULL_ADDRESS,
},
},
];
9 changes: 9 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ export interface GetSwapQuoteRequestParams {
gasPrice?: BigNumber;
excludedSources?: ERC20BridgeSource[];
affiliateAddress?: string;
rfqt?: {
intentOnFilling: boolean;
};
skipValidation: boolean;
}

export interface CalculateSwapQuoteParams {
Expand All @@ -355,6 +359,11 @@ export interface CalculateSwapQuoteParams {
gasPrice?: BigNumber;
excludedSources?: ERC20BridgeSource[];
affiliateAddress?: string;
apiKey?: string;
rfqt?: {
intentOnFilling: boolean;
};
skipValidation: boolean;
}

export interface GetSwapQuoteResponseLiquiditySource {
Expand Down
83 changes: 79 additions & 4 deletions test/app_test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { rfqtMocker } from '@0x/asset-swapper';
import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { ERC20TokenContract, WETH9Contract } from '@0x/contract-wrappers';
import { BlockchainLifecycle, web3Factory } from '@0x/dev-utils';
import { runMigrationsOnceAsync } from '@0x/migrations';
import { Web3ProviderEngine } from '@0x/subproviders';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as HttpStatus from 'http-status-codes';
import 'mocha';
import * as request from 'supertest';

import { getAppAsync, getDefaultAppDependenciesAsync } from '../src/app';
import * as config from '../src/config';
import { DEFAULT_PAGE, DEFAULT_PER_PAGE, SRA_PATH } from '../src/constants';
import { DEFAULT_PAGE, DEFAULT_PER_PAGE, SRA_PATH, SWAP_PATH } from '../src/constants';

import { expect } from './utils/expect';
import { ganacheZrxWethOrder1 } from './utils/mocks';

let app: Express.Application;

Expand All @@ -32,10 +36,9 @@ describe('app test', () => {
blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
await blockchainLifecycle.startAsync();
accounts = await web3Wrapper.getAvailableAddressesAsync();
const owner = accounts[0];
await runMigrationsOnceAsync(provider, { from: owner });

const dependencies = await getDefaultAppDependenciesAsync(provider, config);

// start the 0x-api app
app = await getAppAsync({ ...dependencies }, config);
});
Expand All @@ -54,4 +57,76 @@ describe('app test', () => {
expect(response.body.records).to.deep.equal([]);
});
});
describe('should respond to GET /swap/quote', () => {
it("with INSUFFICIENT_ASSET_LIQUIDITY when there's no liquidity (empty orderbook, sampling excluded, no RFQ)", async () => {
await request(app)
.get(
`${SWAP_PATH}/quote?buyToken=DAI&sellToken=WETH&buyAmount=100000000000000000&excludedSources=Uniswap,Eth2Dai,Kyber,LiquidityProvider`,
)
.expect(HttpStatus.BAD_REQUEST)
.expect('Content-Type', /json/)
.then(response => {
const responseJson = JSON.parse(response.text);
expect(responseJson.reason).to.equal('Validation Failed');
expect(responseJson.validationErrors.length).to.equal(1);
expect(responseJson.validationErrors[0].field).to.equal('buyAmount');
expect(responseJson.validationErrors[0].reason).to.equal('INSUFFICIENT_ASSET_LIQUIDITY');
});
});
});
describe('should hit RFQ-T when apropriate', () => {
it('should get a quote from an RFQ-T provider', async () => {
const [makerAddress, takerAddress] = accounts;
const sellAmount = new BigNumber(100000000000000000);

const contractAddresses: ContractAddresses = getContractAddressesForChainOrThrow(
parseInt(process.env.CHAIN_ID || '1337', 10),
);

const wethContract = new WETH9Contract(contractAddresses.etherToken, provider);
await wethContract.deposit().sendTransactionAsync({ value: sellAmount, from: takerAddress });
await wethContract
.approve(contractAddresses.erc20Proxy, sellAmount)
.sendTransactionAsync({ from: takerAddress });

const zrxToken = new ERC20TokenContract(contractAddresses.zrxToken, provider);
await zrxToken.approve(contractAddresses.erc20Proxy, sellAmount).sendTransactionAsync(
// using buyAmount based on assumption that the RFQ-T provider will be using a "one-to-one" strategy.
{ from: makerAddress },
);
// done setting balances and allowances

const mockedApiParams = {
sellToken: contractAddresses.etherToken,
buyToken: contractAddresses.zrxToken,
sellAmount: sellAmount.toString(),
buyAmount: undefined,
takerAddress,
};
return rfqtMocker.withMockedRfqtFirmQuotes(
[
{
endpoint: 'https://mock-rfqt1.club',
responseData: ganacheZrxWethOrder1,
responseCode: 200,
requestApiKey: 'koolApiKey1',
requestParams: mockedApiParams,
},
],
async () => {
const appResponse = await request(app)
.get(
`${SWAP_PATH}/quote?buyToken=ZRX&sellToken=WETH&sellAmount=${sellAmount.toString()}&takerAddress=${takerAddress}&intentOnFilling=true&excludedSources=Uniswap,Eth2Dai,Kyber,LiquidityProvider`,
)
.set('0x-api-key', 'koolApiKey1')
.expect(HttpStatus.OK)
.expect('Content-Type', /json/);

const responseJson = JSON.parse(appResponse.text);
expect(responseJson.orders.length).to.equal(1);
expect(responseJson.orders[0]).to.eql(ganacheZrxWethOrder1);
},
);
});
});
});
Loading