diff options
author | Fabio Berger <me@fabioberger.com> | 2018-02-16 11:09:53 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-02-16 11:09:53 +0800 |
commit | e2b51c5dc46b30b21e0561689de1f9a3d0127554 (patch) | |
tree | c8f93b5700961a46b16e49e52d159c989c11102d /packages/connect | |
parent | b610b7c1923dcc56883c5167393122ceaed26708 (diff) | |
parent | b75fdd6b66a30196d53331827733b863bed770f0 (diff) | |
download | dexon-sol-tools-e2b51c5dc46b30b21e0561689de1f9a3d0127554.tar.gz dexon-sol-tools-e2b51c5dc46b30b21e0561689de1f9a3d0127554.tar.zst dexon-sol-tools-e2b51c5dc46b30b21e0561689de1f9a3d0127554.zip |
Merge branch 'development' of github.com:0xProject/0x.js into development
* 'development' of github.com:0xProject/0x.js: (24 commits)
Rename variables
Update CHANGELOG
Add npm config for contracts list
Run prettier
Fix checks, add contract list to compile script in package.json
Add contracts to compiler options
Add missing public types from connect docs
Change imports order
Change default page params in connect to page 1 and perPage 100
Add docs staging to 0x.js package
Fix a typo
Add an assertion
Add PR numbers
Fix entry points
Add tests for dev-utils package
Move subproviders from dev-utils to subproviders
Add missing CHANGELOG entry
Add support for intersection types in docs
Add stagedocs script to connect package
web3 typings fix - web3.net.peerCount returns number
...
Diffstat (limited to 'packages/connect')
-rw-r--r-- | packages/connect/CHANGELOG.md | 4 | ||||
-rw-r--r-- | packages/connect/scripts/stagedocs.js | 24 | ||||
-rw-r--r-- | packages/connect/src/http_client.ts | 94 | ||||
-rw-r--r-- | packages/connect/src/index.ts | 5 | ||||
-rw-r--r-- | packages/connect/src/schemas/fees_request_schema.ts | 26 | ||||
-rw-r--r-- | packages/connect/src/schemas/orderbook_request_schema.ts (renamed from packages/connect/src/schemas/relayer_fees_request_schema.ts) | 5 | ||||
-rw-r--r-- | packages/connect/src/schemas/orders_request_opts_schema.ts (renamed from packages/connect/src/schemas/relayer_orders_request_schema.ts) | 4 | ||||
-rw-r--r-- | packages/connect/src/schemas/paged_request_opts_schema.ts | 8 | ||||
-rw-r--r-- | packages/connect/src/schemas/relayer_orderbook_request_schema.ts | 8 | ||||
-rw-r--r-- | packages/connect/src/schemas/schemas.ts | 16 | ||||
-rw-r--r-- | packages/connect/src/schemas/token_pairs_request_opts_schema.ts (renamed from packages/connect/src/schemas/relayer_token_pairs_request_schema.ts) | 4 | ||||
-rw-r--r-- | packages/connect/src/types.ts | 15 | ||||
-rw-r--r-- | packages/connect/test/http_client_test.ts | 49 |
13 files changed, 189 insertions, 73 deletions
diff --git a/packages/connect/CHANGELOG.md b/packages/connect/CHANGELOG.md index 91dcc2b2c..18c808e5e 100644 --- a/packages/connect/CHANGELOG.md +++ b/packages/connect/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## v0.6.0 - _TBD, 2018_ + + * Add pagination options to HttpClient methods (#393) + ## v0.5.7 - _February 9, 2018_ * Fix publishing issue where .npmignore was not properly excluding undesired content (#389) diff --git a/packages/connect/scripts/stagedocs.js b/packages/connect/scripts/stagedocs.js new file mode 100644 index 000000000..868112a37 --- /dev/null +++ b/packages/connect/scripts/stagedocs.js @@ -0,0 +1,24 @@ +const execAsync = require('async-child-process').execAsync; +const postpublish_utils = require('../../../scripts/postpublish_utils'); + +const cwd = __dirname + '/..'; +const S3BucketPath = 's3://staging-connect-docs-jsons/'; +const jsonFilePath = __dirname + '/../' + postpublish_utils.generatedDocsDirectoryName + '/index.json'; +const version = process.env.DOCS_VERSION; + +execAsync('JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_DIR=' + __dirname + '/.. yarn docs:json', { + cwd, +}) +.then(function(result) { + if (result.stderr !== '') { + throw new Error(result.stderr); + } + const fileName = 'v' + version + '.json'; + const s3Url = S3BucketPath + fileName; + return execAsync('S3_URL=' + s3Url + ' yarn upload_docs_json', { + cwd, + }); +}) +.catch(function(err) { + console.log(err); +}); diff --git a/packages/connect/src/http_client.ts b/packages/connect/src/http_client.ts index 3df77b0f0..9e5f0f448 100644 --- a/packages/connect/src/http_client.ts +++ b/packages/connect/src/http_client.ts @@ -13,14 +13,26 @@ import { HttpRequestType, OrderbookRequest, OrderbookResponse, - OrdersRequest, + OrdersRequestOpts, + PagedRequestOpts, SignedOrder, TokenPairsItem, - TokenPairsRequest, + TokenPairsRequestOpts, } from './types'; import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers'; const TRAILING_SLASHES_REGEX = /\/+$/; +const DEFAULT_PAGED_REQUEST_OPTS: PagedRequestOpts = { + page: 1, + perPage: 100, +}; +/** + * This mapping defines how an option property name gets converted into an HTTP request query field + */ +const OPTS_TO_QUERY_FIELD_MAP = { + perPage: 'per_page', +}; + /** * This class includes all the functionality related to interacting with a set of HTTP endpoints * that implement the standard relayer API v0 @@ -28,6 +40,22 @@ const TRAILING_SLASHES_REGEX = /\/+$/; export class HttpClient implements Client { private _apiEndpointUrl: string; /** + * Format parameters to be appended to http requests into query string form + */ + private static _buildQueryStringFromHttpParams(params?: object): string { + // if params are undefined or empty, return an empty string + if (_.isUndefined(params) || _.isEmpty(params)) { + return ''; + } + // format params into a form the api expects + const formattedParams = _.mapKeys(params, (value: any, key: string) => { + return _.get(OPTS_TO_QUERY_FIELD_MAP, key, key); + }); + // stringify the formatted object + const stringifiedParams = queryString.stringify(formattedParams); + return `?${stringifiedParams}`; + } + /** * Instantiates a new HttpClient instance * @param url The relayer API base HTTP url you would like to interact with * @return An instance of HttpClient @@ -38,34 +66,35 @@ export class HttpClient implements Client { } /** * Retrieve token pair info from the API - * @param request A TokenPairsRequest instance describing specific token information - * to retrieve + * @param requestOpts Options specifying token information to retrieve and page information, defaults to { page: 1, perPage: 100 } * @return The resulting TokenPairsItems that match the request */ - public async getTokenPairsAsync(request?: TokenPairsRequest): Promise<TokenPairsItem[]> { - if (!_.isUndefined(request)) { - assert.doesConformToSchema('request', request, clientSchemas.relayerTokenPairsRequestSchema); + public async getTokenPairsAsync(requestOpts?: TokenPairsRequestOpts & PagedRequestOpts): Promise<TokenPairsItem[]> { + if (!_.isUndefined(requestOpts)) { + assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.tokenPairsRequestOptsSchema); + assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema); } - const requestOpts = { - params: request, + const httpRequestOpts = { + params: _.defaults({}, requestOpts, DEFAULT_PAGED_REQUEST_OPTS), }; - const responseJson = await this._requestAsync('/token_pairs', HttpRequestType.Get, requestOpts); + const responseJson = await this._requestAsync('/token_pairs', HttpRequestType.Get, httpRequestOpts); const tokenPairs = relayerResponseJsonParsers.parseTokenPairsJson(responseJson); return tokenPairs; } /** * Retrieve orders from the API - * @param request An OrdersRequest instance describing specific orders to retrieve + * @param requestOpts Options specifying orders to retrieve and page information, defaults to { page: 1, perPage: 100 } * @return The resulting SignedOrders that match the request */ - public async getOrdersAsync(request?: OrdersRequest): Promise<SignedOrder[]> { - if (!_.isUndefined(request)) { - assert.doesConformToSchema('request', request, clientSchemas.relayerOrdersRequestSchema); + public async getOrdersAsync(requestOpts?: OrdersRequestOpts & PagedRequestOpts): Promise<SignedOrder[]> { + if (!_.isUndefined(requestOpts)) { + assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.ordersRequestOptsSchema); + assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema); } - const requestOpts = { - params: request, + const httpRequestOpts = { + params: _.defaults({}, requestOpts, DEFAULT_PAGED_REQUEST_OPTS), }; - const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, requestOpts); + const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, httpRequestOpts); const orders = relayerResponseJsonParsers.parseOrdersJson(responseJson); return orders; } @@ -82,15 +111,22 @@ export class HttpClient implements Client { } /** * Retrieve an orderbook from the API - * @param request An OrderbookRequest instance describing the specific orderbook to retrieve + * @param request An OrderbookRequest instance describing the specific orderbook to retrieve + * @param requestOpts Options specifying page information, defaults to { page: 1, perPage: 100 } * @return The resulting OrderbookResponse that matches the request */ - public async getOrderbookAsync(request: OrderbookRequest): Promise<OrderbookResponse> { - assert.doesConformToSchema('request', request, clientSchemas.relayerOrderBookRequestSchema); - const requestOpts = { - params: request, + public async getOrderbookAsync( + request: OrderbookRequest, + requestOpts?: PagedRequestOpts, + ): Promise<OrderbookResponse> { + assert.doesConformToSchema('request', request, clientSchemas.orderBookRequestSchema); + if (!_.isUndefined(requestOpts)) { + assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema); + } + const httpRequestOpts = { + params: _.defaults({}, request, requestOpts, DEFAULT_PAGED_REQUEST_OPTS), }; - const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, requestOpts); + const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, httpRequestOpts); const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(responseJson); return orderbook; } @@ -100,11 +136,11 @@ export class HttpClient implements Client { * @return The resulting FeesResponse that matches the request */ public async getFeesAsync(request: FeesRequest): Promise<FeesResponse> { - assert.doesConformToSchema('request', request, schemas.relayerApiFeesPayloadSchema); - const requestOpts = { + assert.doesConformToSchema('request', request, clientSchemas.feesRequestSchema); + const httpRequestOpts = { payload: request, }; - const responseJson = await this._requestAsync('/fees', HttpRequestType.Post, requestOpts); + const responseJson = await this._requestAsync('/fees', HttpRequestType.Post, httpRequestOpts); const fees = relayerResponseJsonParsers.parseFeesResponseJson(responseJson); return fees; } @@ -126,11 +162,7 @@ export class HttpClient implements Client { ): Promise<any> { const params = _.get(requestOptions, 'params'); const payload = _.get(requestOptions, 'payload'); - let query = ''; - if (!_.isUndefined(params) && !_.isEmpty(params)) { - const stringifiedParams = queryString.stringify(params); - query = `?${stringifiedParams}`; - } + const query = HttpClient._buildQueryStringFromHttpParams(params); const url = `${this._apiEndpointUrl}${path}${query}`; const headers = new Headers({ 'content-type': 'application/json', diff --git a/packages/connect/src/index.ts b/packages/connect/src/index.ts index a492f5ae9..344a32e28 100644 --- a/packages/connect/src/index.ts +++ b/packages/connect/src/index.ts @@ -11,9 +11,10 @@ export { OrderbookChannelSubscriptionOpts, OrderbookRequest, OrderbookResponse, - OrdersRequest, + OrdersRequestOpts, + PagedRequestOpts, SignedOrder, TokenPairsItem, - TokenPairsRequest, + TokenPairsRequestOpts, TokenTradeInfo, } from './types'; diff --git a/packages/connect/src/schemas/fees_request_schema.ts b/packages/connect/src/schemas/fees_request_schema.ts new file mode 100644 index 000000000..ff3d7b9d3 --- /dev/null +++ b/packages/connect/src/schemas/fees_request_schema.ts @@ -0,0 +1,26 @@ +export const feesRequestSchema = { + id: '/FeesRequest', + type: 'object', + properties: { + exchangeContractAddress: { $ref: '/Address' }, + maker: { $ref: '/Address' }, + taker: { $ref: '/Address' }, + makerTokenAddress: { $ref: '/Address' }, + takerTokenAddress: { $ref: '/Address' }, + makerTokenAmount: { $ref: '/Number' }, + takerTokenAmount: { $ref: '/Number' }, + expirationUnixTimestampSec: { $ref: '/Number' }, + salt: { $ref: '/Number' }, + }, + required: [ + 'exchangeContractAddress', + 'maker', + 'taker', + 'makerTokenAddress', + 'takerTokenAddress', + 'makerTokenAmount', + 'takerTokenAmount', + 'expirationUnixTimestampSec', + 'salt', + ], +}; diff --git a/packages/connect/src/schemas/relayer_fees_request_schema.ts b/packages/connect/src/schemas/orderbook_request_schema.ts index f20e077ba..5f3463242 100644 --- a/packages/connect/src/schemas/relayer_fees_request_schema.ts +++ b/packages/connect/src/schemas/orderbook_request_schema.ts @@ -1,8 +1,9 @@ -export const relayerOrderBookRequestSchema = { - id: '/RelayerOrderBookRequest', +export const orderBookRequestSchema = { + id: '/OrderBookRequest', type: 'object', properties: { baseTokenAddress: { $ref: '/Address' }, quoteTokenAddress: { $ref: '/Address' }, }, + required: ['baseTokenAddress', 'quoteTokenAddress'], }; diff --git a/packages/connect/src/schemas/relayer_orders_request_schema.ts b/packages/connect/src/schemas/orders_request_opts_schema.ts index 570238dae..5facbc959 100644 --- a/packages/connect/src/schemas/relayer_orders_request_schema.ts +++ b/packages/connect/src/schemas/orders_request_opts_schema.ts @@ -1,5 +1,5 @@ -export const relayerOrdersRequestSchema = { - id: '/RelayerOrdersRequest', +export const ordersRequestOptsSchema = { + id: '/OrdersRequestOpts', type: 'object', properties: { exchangeContractAddress: { $ref: '/Address' }, diff --git a/packages/connect/src/schemas/paged_request_opts_schema.ts b/packages/connect/src/schemas/paged_request_opts_schema.ts new file mode 100644 index 000000000..eb2e52100 --- /dev/null +++ b/packages/connect/src/schemas/paged_request_opts_schema.ts @@ -0,0 +1,8 @@ +export const pagedRequestOptsSchema = { + id: '/PagedRequestOpts', + type: 'object', + properties: { + page: { type: 'number' }, + perPage: { type: 'number' }, + }, +}; diff --git a/packages/connect/src/schemas/relayer_orderbook_request_schema.ts b/packages/connect/src/schemas/relayer_orderbook_request_schema.ts deleted file mode 100644 index f20e077ba..000000000 --- a/packages/connect/src/schemas/relayer_orderbook_request_schema.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const relayerOrderBookRequestSchema = { - id: '/RelayerOrderBookRequest', - type: 'object', - properties: { - baseTokenAddress: { $ref: '/Address' }, - quoteTokenAddress: { $ref: '/Address' }, - }, -}; diff --git a/packages/connect/src/schemas/schemas.ts b/packages/connect/src/schemas/schemas.ts index 288d6969d..0b8b798a9 100644 --- a/packages/connect/src/schemas/schemas.ts +++ b/packages/connect/src/schemas/schemas.ts @@ -1,9 +1,13 @@ -import { relayerOrderBookRequestSchema } from './relayer_orderbook_request_schema'; -import { relayerOrdersRequestSchema } from './relayer_orders_request_schema'; -import { relayerTokenPairsRequestSchema } from './relayer_token_pairs_request_schema'; +import { feesRequestSchema } from './fees_request_schema'; +import { orderBookRequestSchema } from './orderbook_request_schema'; +import { ordersRequestOptsSchema } from './orders_request_opts_schema'; +import { pagedRequestOptsSchema } from './paged_request_opts_schema'; +import { tokenPairsRequestOptsSchema } from './token_pairs_request_opts_schema'; export const schemas = { - relayerOrderBookRequestSchema, - relayerOrdersRequestSchema, - relayerTokenPairsRequestSchema, + feesRequestSchema, + orderBookRequestSchema, + ordersRequestOptsSchema, + pagedRequestOptsSchema, + tokenPairsRequestOptsSchema, }; diff --git a/packages/connect/src/schemas/relayer_token_pairs_request_schema.ts b/packages/connect/src/schemas/token_pairs_request_opts_schema.ts index 379232204..9b73a917b 100644 --- a/packages/connect/src/schemas/relayer_token_pairs_request_schema.ts +++ b/packages/connect/src/schemas/token_pairs_request_opts_schema.ts @@ -1,5 +1,5 @@ -export const relayerTokenPairsRequestSchema = { - id: '/RelayerTokenPairsRequest', +export const tokenPairsRequestOptsSchema = { + id: '/TokenPairsRequestOpts', type: 'object', properties: { tokenA: { $ref: '/Address' }, diff --git a/packages/connect/src/types.ts b/packages/connect/src/types.ts index edb6c77a6..970eff498 100644 --- a/packages/connect/src/types.ts +++ b/packages/connect/src/types.ts @@ -30,10 +30,10 @@ export interface ECSignature { } export interface Client { - getTokenPairsAsync: (request?: TokenPairsRequest) => Promise<TokenPairsItem[]>; - getOrdersAsync: (request?: OrdersRequest) => Promise<SignedOrder[]>; + getTokenPairsAsync: (requestOpts?: TokenPairsRequestOpts & PagedRequestOpts) => Promise<TokenPairsItem[]>; + getOrdersAsync: (requestOpts?: OrdersRequestOpts & PagedRequestOpts) => Promise<SignedOrder[]>; getOrderAsync: (orderHash: string) => Promise<SignedOrder>; - getOrderbookAsync: (request: OrderbookRequest) => Promise<OrderbookResponse>; + getOrderbookAsync: (request: OrderbookRequest, requestOpts?: PagedRequestOpts) => Promise<OrderbookResponse>; getFeesAsync: (request: FeesRequest) => Promise<FeesResponse>; submitOrderAsync: (signedOrder: SignedOrder) => Promise<void>; } @@ -111,7 +111,7 @@ export enum WebsocketClientEventType { ConnectFailed = 'connectFailed', } -export interface TokenPairsRequest { +export interface TokenPairsRequestOpts { tokenA?: string; tokenB?: string; } @@ -128,7 +128,7 @@ export interface TokenTradeInfo { precision: number; } -export interface OrdersRequest { +export interface OrdersRequestOpts { exchangeContractAddress?: string; tokenAddress?: string; makerTokenAddress?: string; @@ -167,6 +167,11 @@ export interface FeesResponse { takerFee: BigNumber; } +export interface PagedRequestOpts { + page?: number; + perPage?: number; +} + export interface HttpRequestOptions { params?: object; payload?: object; diff --git a/packages/connect/test/http_client_test.ts b/packages/connect/test/http_client_test.ts index 15759d911..311dc96e6 100644 --- a/packages/connect/test/http_client_test.ts +++ b/packages/connect/test/http_client_test.ts @@ -40,19 +40,22 @@ describe('HttpClient', () => { }); describe('#getTokenPairsAsync', () => { const url = `${relayUrl}/token_pairs`; - it('gets token pairs', async () => { - fetchMock.get(url, tokenPairsResponseJSON); + it('gets token pairs with default options when none are provided', async () => { + const urlWithQuery = `${url}?page=1&per_page=100`; + fetchMock.get(urlWithQuery, tokenPairsResponseJSON); const tokenPairs = await relayerClient.getTokenPairsAsync(); expect(tokenPairs).to.be.deep.equal(tokenPairsResponse); }); - it('gets specific token pairs for request', async () => { + it('gets token pairs with specified request options', async () => { const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d'; - const tokenPairsRequest = { + const tokenPairsRequestOpts = { tokenA: tokenAddress, + page: 3, + perPage: 50, }; - const urlWithQuery = `${url}?tokenA=${tokenAddress}`; + const urlWithQuery = `${url}?page=3&per_page=50&tokenA=${tokenAddress}`; fetchMock.get(urlWithQuery, tokenPairsResponseJSON); - const tokenPairs = await relayerClient.getTokenPairsAsync(tokenPairsRequest); + const tokenPairs = await relayerClient.getTokenPairsAsync(tokenPairsRequestOpts); expect(tokenPairs).to.be.deep.equal(tokenPairsResponse); }); it('throws an error for invalid JSON response', async () => { @@ -62,17 +65,20 @@ describe('HttpClient', () => { }); describe('#getOrdersAsync', () => { const url = `${relayUrl}/orders`; - it('gets orders', async () => { - fetchMock.get(url, ordersResponseJSON); + it('gets orders with default options when none are provided', async () => { + const urlWithQuery = `${url}?page=1&per_page=100`; + fetchMock.get(urlWithQuery, ordersResponseJSON); const orders = await relayerClient.getOrdersAsync(); expect(orders).to.be.deep.equal(ordersResponse); }); - it('gets specific orders for request', async () => { + it('gets orders with specified request options', async () => { const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d'; const ordersRequest = { tokenAddress, + page: 3, + perPage: 50, }; - const urlWithQuery = `${url}?tokenAddress=${tokenAddress}`; + const urlWithQuery = `${url}?page=3&per_page=50&tokenAddress=${tokenAddress}`; fetchMock.get(urlWithQuery, ordersResponseJSON); const orders = await relayerClient.getOrdersAsync(ordersRequest); expect(orders).to.be.deep.equal(ordersResponse); @@ -100,14 +106,27 @@ describe('HttpClient', () => { baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', quoteTokenAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32', }; - const url = `${relayUrl}/orderbook?baseTokenAddress=${request.baseTokenAddress}"eTokenAddress=${ - request.quoteTokenAddress - }`; - it('gets order book', async () => { - fetchMock.get(url, orderbookJSON); + const url = `${relayUrl}/orderbook`; + it('gets orderbook with default page options when none are provided', async () => { + const urlWithQuery = `${url}?baseTokenAddress=${ + request.baseTokenAddress + }&page=1&per_page=100"eTokenAddress=${request.quoteTokenAddress}`; + fetchMock.get(urlWithQuery, orderbookJSON); const orderbook = await relayerClient.getOrderbookAsync(request); expect(orderbook).to.be.deep.equal(orderbookResponse); }); + it('gets orderbook with specified page options', async () => { + const urlWithQuery = `${url}?baseTokenAddress=${ + request.baseTokenAddress + }&page=3&per_page=50"eTokenAddress=${request.quoteTokenAddress}`; + fetchMock.get(urlWithQuery, orderbookJSON); + const pagedRequestOptions = { + page: 3, + perPage: 50, + }; + const orderbook = await relayerClient.getOrderbookAsync(request, pagedRequestOptions); + expect(orderbook).to.be.deep.equal(orderbookResponse); + }); it('throws an error for invalid JSON response', async () => { fetchMock.get(url, { test: 'dummy' }); expect(relayerClient.getOrderbookAsync(request)).to.be.rejected(); |