diff options
Diffstat (limited to 'packages/sra-report/src')
8 files changed, 259 insertions, 0 deletions
diff --git a/packages/sra-report/src/contract_addresses/kovan_addresses.ts b/packages/sra-report/src/contract_addresses/kovan_addresses.ts new file mode 100644 index 000000000..e06568f52 --- /dev/null +++ b/packages/sra-report/src/contract_addresses/kovan_addresses.ts @@ -0,0 +1,5 @@ +export const addresses = { + WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c', + ZRX: '0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570', + EXCHANGE: '0x90fe2af704b34e0224bf2299c838e04d4dcf1364', +}; diff --git a/packages/sra-report/src/contract_addresses/mainnet_addresses.ts b/packages/sra-report/src/contract_addresses/mainnet_addresses.ts new file mode 100644 index 000000000..e9aa0f167 --- /dev/null +++ b/packages/sra-report/src/contract_addresses/mainnet_addresses.ts @@ -0,0 +1,5 @@ +export const addresses = { + WETH: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + ZRX: '0xe41d2489571d322189246dafa5ebde1f4699f498', + EXCHANGE: '0x12459c951127e0c374ff9105dda097662a027093', +}; diff --git a/packages/sra-report/src/contract_addresses/rinkeby_addresses.ts b/packages/sra-report/src/contract_addresses/rinkeby_addresses.ts new file mode 100644 index 000000000..b1e0848d0 --- /dev/null +++ b/packages/sra-report/src/contract_addresses/rinkeby_addresses.ts @@ -0,0 +1,5 @@ +export const addresses = { + WETH: '0xc778417e063141139fce010982780140aa0cd5ab', + ZRX: '0x00f58d6d585f84b2d7267940cede30ce2fe6eae8', + EXCHANGE: '0x1d16ef40fac01cec8adac2ac49427b9384192c05', +}; diff --git a/packages/sra-report/src/contract_addresses/ropsten_addresses.ts b/packages/sra-report/src/contract_addresses/ropsten_addresses.ts new file mode 100644 index 000000000..80e6e5e7e --- /dev/null +++ b/packages/sra-report/src/contract_addresses/ropsten_addresses.ts @@ -0,0 +1,5 @@ +export const addresses = { + WETH: '0xc778417e063141139fce010982780140aa0cd5ab', + ZRX: '0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d', + EXCHANGE: '0x479cc461fecd078f766ecc58533d6f69580cf3ac', +}; diff --git a/packages/sra-report/src/globals.d.ts b/packages/sra-report/src/globals.d.ts new file mode 100644 index 000000000..0d3beb446 --- /dev/null +++ b/packages/sra-report/src/globals.d.ts @@ -0,0 +1,9 @@ +declare module 'newman' { + // tslint:disable-next-line:completed-docs + export function run(options: any, callback?: () => void): void; +} + +declare module '*.json' { + const value: any; + export default value; +} diff --git a/packages/sra-report/src/index.ts b/packages/sra-report/src/index.ts new file mode 100644 index 000000000..d23549916 --- /dev/null +++ b/packages/sra-report/src/index.ts @@ -0,0 +1,102 @@ +#!/usr/bin/env node +import { assert } from '@0xproject/assert'; +import { Schema, schemas } from '@0xproject/json-schemas'; +import { promisify } from '@0xproject/utils'; +import chalk from 'chalk'; +import * as _ from 'lodash'; +import * as newman from 'newman'; +import * as yargs from 'yargs'; + +import * as sraReportCollectionJSON from '../postman_configs/collections/sra_report.postman_collection.json'; + +import { postmanEnvironmentFactory } from './postman_environment_factory'; +import { utils } from './utils'; + +const newmanRunAsync = promisify<void>(newman.run); +const DEFAULT_NETWORK_ID = 1; +const SUPPORTED_NETWORK_IDS = [1, 3, 4, 42]; + +// extract command line arguments +const args = yargs + .option('endpoint-url', { + alias: ['e'], + describe: 'API endpoint url to test for standard relayer API compliance', + type: 'string', + demandOption: true, + }) + .option('output', { + alias: ['o', 'out'], + describe: 'The relative path to write the report generated by the collection run, prints to console by default', + type: 'string', + normalize: true, + demandOption: false, + }) + .option('network-id', { + alias: ['n'], + describe: 'ID of the network that the API is serving orders from', + type: 'number', + default: DEFAULT_NETWORK_ID, + }) + .option('environment', { + alias: ['env'], + describe: 'The relative path to a postman environment file for the collection run', + type: 'string', + normalize: true, + demandOption: false, + }) + .option('export-collection', { + alias: ['ec'], + describe: 'The relative path to write the postman collection file used by the collection run', + type: 'string', + normalize: true, + demandOption: false, + }) + .option('export-environment', { + alias: ['ee'], + describe: 'The relative path to write the postman environment file used by the collection run', + type: 'string', + normalize: true, + demandOption: false, + }) + .example( + "$0 --endpoint-url 'http://api.example.com' --out 'path/to/report.json' --network-id 42 --environment 'path/to/custom/environment.json' --export-collection 'path/to/collection.json' --export-environment 'path/to/environment.json'", + 'Full usage example', + ).argv; +// perform extra validation on command line arguments +try { + assert.isWebUri('args', args.endpointUrl); +} catch (err) { + utils.log(`${chalk.red(`Invalid url format:`)} ${args.endpointUrl}`); + process.exit(1); +} +if (!_.includes(SUPPORTED_NETWORK_IDS, args.networkId)) { + utils.log(`${chalk.red(`Unsupported network id:`)} ${args.networkId}`); + utils.log(`${chalk.bold(`Supported network ids:`)} ${SUPPORTED_NETWORK_IDS}`); + process.exit(1); +} +const mainAsync = async () => { + const newmanReporterOptions = !_.isUndefined(args.output) + ? { + reporters: 'json', + reporter: { + json: { + export: args.output, + }, + }, + } + : { + reporters: 'cli', + }; + const environment = !_.isUndefined(args.environment) + ? args.environment + : await postmanEnvironmentFactory.createPostmanEnvironmentAsync(args.endpointUrl, args.networkId); + const newmanRunOptions = { + collection: sraReportCollectionJSON, + environment, + exportCollection: args.exportCollection, + exportEnvironment: args.exportEnvironment, + ...newmanReporterOptions, + }; + await newmanRunAsync(newmanRunOptions); +}; +mainAsync().catch(utils.log); diff --git a/packages/sra-report/src/postman_environment_factory.ts b/packages/sra-report/src/postman_environment_factory.ts new file mode 100644 index 000000000..ffac7ac2e --- /dev/null +++ b/packages/sra-report/src/postman_environment_factory.ts @@ -0,0 +1,123 @@ +import { SignedOrder, ZeroEx } from '0x.js'; +import { HttpClient } from '@0xproject/connect'; +import { Schema, schemas as schemasByName } from '@0xproject/json-schemas'; +import chalk from 'chalk'; +import * as _ from 'lodash'; + +import { addresses as kovanAddresses } from './contract_addresses/kovan_addresses'; +import { addresses as mainnetAddresses } from './contract_addresses/mainnet_addresses'; +import { addresses as rinkebyAddresses } from './contract_addresses/rinkeby_addresses'; +import { addresses as ropstenAddresses } from './contract_addresses/ropsten_addresses'; +import { utils } from './utils'; + +const ENVIRONMENT_NAME = 'SRA Report'; + +interface EnvironmentValue { + key: string; +} + +export const postmanEnvironmentFactory = { + /** + * Dynamically generates a postman environment (https://www.getpostman.com/docs/v6/postman/environments_and_globals/manage_environments) + * When running the postman collection via newman, we provide it a set of environment variables + * These variables include: + * - 0x JSON schemas for response body validation + * - Contract addresses based on the network id for making specific queries (ex. baseTokenAddress=ZRX_address) + * - Order properties for making specific queries (ex. maker=orderMaker) + */ + async createPostmanEnvironmentAsync(url: string, networkId: number) { + const orderEnvironmentValues = await createOrderEnvironmentValuesAsync(url); + const allEnvironmentValues = _.concat( + createSchemaEnvironmentValues(), + createContractAddressEnvironmentValues(networkId), + orderEnvironmentValues, + createEnvironmentValue('url', url), + ); + const environment = { + name: ENVIRONMENT_NAME, + values: allEnvironmentValues, + }; + return environment; + }, +}; +function createSchemaEnvironmentValues() { + const schemas: Schema[] = _.values(schemasByName); + const schemaEnvironmentValues = _.compact( + _.map(schemas, (schema: Schema) => { + if (_.isUndefined(schema.id)) { + return undefined; + } else { + const schemaKey = convertSchemaIdToKey(schema.id); + const stringifiedSchema = JSON.stringify(schema); + const schemaEnvironmentValue = createEnvironmentValue(schemaKey, stringifiedSchema); + return schemaEnvironmentValue; + } + }), + ); + const schemaKeys = _.map(schemaEnvironmentValues, (environmentValue: EnvironmentValue) => { + return environmentValue.key; + }); + const result = _.concat(schemaEnvironmentValues, createEnvironmentValue('schemaKeys', JSON.stringify(schemaKeys))); + return result; +} +function createContractAddressEnvironmentValues(networkId: number) { + const contractAddresses = getContractAddresses(networkId); + return [ + createEnvironmentValue('tokenContractAddress1', contractAddresses.WETH), + createEnvironmentValue('tokenContractAddress2', contractAddresses.ZRX), + createEnvironmentValue('exchangeContractAddress', contractAddresses.EXCHANGE), + ]; +} +async function createOrderEnvironmentValuesAsync(url: string) { + const httpClient = new HttpClient(url); + const orders = await httpClient.getOrdersAsync(); + const orderIfExists = _.head(orders); + if (!_.isUndefined(orderIfExists)) { + return [ + createEnvironmentValue('order', JSON.stringify(orderIfExists)), + createEnvironmentValue('orderMaker', orderIfExists.maker), + createEnvironmentValue('orderTaker', orderIfExists.taker), + createEnvironmentValue('orderFeeRecipient', orderIfExists.feeRecipient), + createEnvironmentValue('orderHash', ZeroEx.getOrderHashHex(orderIfExists)), + ]; + } else { + utils.log(`${chalk.red(`No orders from /orders found`)}`); + return [ + createEnvironmentValue('order', ''), + createEnvironmentValue('orderMaker', ''), + createEnvironmentValue('orderTaker', ''), + createEnvironmentValue('orderFeeRecipient', ''), + createEnvironmentValue('orderHash', ''), + ]; + } +} +function getContractAddresses(networkId: number) { + switch (networkId) { + case 1: + return mainnetAddresses; + case 3: + return ropstenAddresses; + case 4: + return rinkebyAddresses; + case 42: + return kovanAddresses; + default: + throw new Error('Unsupported network id'); + } +} +function convertSchemaIdToKey(schemaId: string) { + let result = schemaId; + if (_.startsWith(result, '/')) { + result = result.substr(1); + } + result = `${result}Schema`; + return result; +} +function createEnvironmentValue(key: string, value: string) { + return { + key, + value, + enabled: true, + type: 'text', + }; +} diff --git a/packages/sra-report/src/utils.ts b/packages/sra-report/src/utils.ts new file mode 100644 index 000000000..5423cabd9 --- /dev/null +++ b/packages/sra-report/src/utils.ts @@ -0,0 +1,5 @@ +export const utils = { + log(...args: any[]): void { + console.log(...args); // tslint:disable-line:no-console + }, +}; |