Skip to content
This repository was 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 all 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
2 changes: 2 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ jobs:
- image: circleci/node:11.14-browsers
- image: circleci/postgres:9.6.5-alpine-ram
- image: 0xorg/ganache-cli:6.0.0
environment:
VERSION: 6.2.4-110e1afa8
- image: 0xorg/mesh:9.2.1
environment:
ETHEREUM_RPC_URL: http://0.0.0.0:8545
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ services:
image: "0xorg/ganache-cli:6.0.0"
ports:
- "8545:8545"
environment:
VERSION: 6.2.4-110e1afa8
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",
"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-0e196a59d",
"@0x/contract-addresses": "0xProject/gitpkg-registry#0x-contract-addresses-v4.9.0-110e1afa8",
"@0x/contract-wrappers": "0xProject/gitpkg-registry#0x-contract-wrappers-v13.6.3-0e196a59d"
},
"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-0e196a59d",
"@0x/asset-swapper": "0xProject/gitpkg-registry#0x-asset-swapper-v4.4.0-110e1afa8",
"@0x/connect": "^6.0.4",
"@0x/contract-addresses": "0xProject/gitpkg-registry#0x-contract-addresses-v4.9.0-0e196a59d",
"@0x/contract-addresses": "0xProject/gitpkg-registry#0x-contract-addresses-v4.9.0-110e1afa8",
"@0x/contract-wrappers": "0xProject/gitpkg-registry#0x-contract-wrappers-v13.6.3-0e196a59d",
"@0x/json-schemas": "^5.0.4",
"@0x/mesh-rpc-client": "^9.2.1",
Expand Down
6 changes: 6 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,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
17 changes: 17 additions & 0 deletions src/handlers/swap_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export class SwapHandlers {
gasPrice,
excludedSources,
affiliateAddress,
rfqt,
// tslint:disable-next-line:boolean-naming
skipValidation,
} = parseGetSwapQuoteRequestParams(req);

const isETHSell = isETHSymbol(sellToken);
Expand Down Expand Up @@ -83,6 +86,14 @@ export class SwapHandlers {
gasPrice,
excludedSources,
affiliateAddress,
apiKey: req.header('0x-api-key'),
rfqt:
rfqt === undefined
? undefined
: {
intentOnFilling: rfqt.intentOnFilling,
},
skipValidation,
};

try {
Expand Down Expand Up @@ -200,6 +211,10 @@ 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: req.query.intentOnFilling === 'true' };
// tslint:disable-next-line:boolean-naming
const skipValidation = req.query.skipValidation === undefined ? false : req.query.skipValidation === 'true';
return {
takerAddress,
sellToken,
Expand All @@ -210,5 +225,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

"enum": ["true", "false"]
},
"skipValidation": {
"type": "string",
"enum": ["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.

❤️

}
},
"required": ["sellToken", "buyToken"],
Expand Down
24 changes: 23 additions & 1 deletion src/services/swap_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,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,
ONE_SECOND_MS,
PERCENTAGE_SIG_DIGITS,
Expand Down Expand Up @@ -62,6 +65,10 @@ export class SwapService {
chainId: CHAIN_ID,
expiryBufferMs: QUOTE_ORDER_EXPIRATION_BUFFER_MS,
liquidityProviderRegistryAddress: LIQUIDITY_POOL_REGISTRY_ADDRESS,
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 @@ -85,13 +92,28 @@ 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,
// If this is a forwarder transaction, then we want to request quotes with the taker as the
// forwarder contract. If it's not, then we want to request quotes with the taker set to the
// API's takerAddress query parameter, which in this context is known as `from`.
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 @@ -136,7 +158,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 @@ -359,6 +359,10 @@ export interface GetSwapQuoteRequestParams {
gasPrice?: BigNumber;
excludedSources?: ERC20BridgeSource[];
affiliateAddress?: string;
rfqt?: {
intentOnFilling: boolean;
};
skipValidation: boolean;
}

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

export interface GetSwapQuoteResponseLiquiditySource {
Expand Down
Loading