From 713c922e351b284a4a17cde4899b133bfe939c4d Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Tue, 13 Feb 2018 11:34:54 -0800 Subject: Add page options to relevant HttpClient methods --- packages/connect/CHANGELOG.md | 4 ++ packages/connect/src/http_client.ts | 68 +++++++++++++--------- packages/connect/src/index.ts | 5 +- .../connect/src/schemas/fees_request_schema.ts | 26 +++++++++ .../src/schemas/orderbook_request_schema.ts | 9 +++ .../src/schemas/orders_request_opts_schema.ts | 16 +++++ .../src/schemas/paged_request_opts_schema.ts | 8 +++ .../src/schemas/relayer_fees_request_schema.ts | 8 --- .../schemas/relayer_orderbook_request_schema.ts | 8 --- .../src/schemas/relayer_orders_request_schema.ts | 16 ----- .../schemas/relayer_token_pairs_request_schema.ts | 8 --- packages/connect/src/schemas/schemas.ts | 16 +++-- .../src/schemas/token_pairs_request_opts_schema.ts | 8 +++ packages/connect/src/types.ts | 15 +++-- packages/connect/test/http_client_test.ts | 49 +++++++++++----- .../ts/containers/connect_documentation.tsx | 5 +- 16 files changed, 173 insertions(+), 96 deletions(-) create mode 100644 packages/connect/src/schemas/fees_request_schema.ts create mode 100644 packages/connect/src/schemas/orderbook_request_schema.ts create mode 100644 packages/connect/src/schemas/orders_request_opts_schema.ts create mode 100644 packages/connect/src/schemas/paged_request_opts_schema.ts delete mode 100644 packages/connect/src/schemas/relayer_fees_request_schema.ts delete mode 100644 packages/connect/src/schemas/relayer_orderbook_request_schema.ts delete mode 100644 packages/connect/src/schemas/relayer_orders_request_schema.ts delete mode 100644 packages/connect/src/schemas/relayer_token_pairs_request_schema.ts create mode 100644 packages/connect/src/schemas/token_pairs_request_opts_schema.ts 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/src/http_client.ts b/packages/connect/src/http_client.ts index 3df77b0f0..2cabaae76 100644 --- a/packages/connect/src/http_client.ts +++ b/packages/connect/src/http_client.ts @@ -13,14 +13,20 @@ 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: 0, + per_page: 100, +}; + /** * This class includes all the functionality related to interacting with a set of HTTP endpoints * that implement the standard relayer API v0 @@ -38,34 +44,37 @@ 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 An optional (TokenPairsRequestOpts & PagedRequestOpts) instance describing token information + * to retrieve with page information, defaults to { page: 0, per_page: 100 } * @return The resulting TokenPairsItems that match the request */ - public async getTokenPairsAsync(request?: TokenPairsRequest): Promise { - if (!_.isUndefined(request)) { - assert.doesConformToSchema('request', request, clientSchemas.relayerTokenPairsRequestSchema); + public async getTokenPairsAsync(requestOpts?: TokenPairsRequestOpts & PagedRequestOpts): Promise { + 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 An optional (OrdersRequestOpts & PagedRequestOpts) instance describing specific orders to retrieve + * with page information, defaults to { page: 0, per_page: 100 } * @return The resulting SignedOrders that match the request */ - public async getOrdersAsync(request?: OrdersRequest): Promise { - if (!_.isUndefined(request)) { - assert.doesConformToSchema('request', request, clientSchemas.relayerOrdersRequestSchema); + public async getOrdersAsync(requestOpts?: OrdersRequestOpts & PagedRequestOpts): Promise { + 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 +91,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 An optional PagedRequestOpts instance describing page information, defaults to { page: 0, per_page: 100 } * @return The resulting OrderbookResponse that matches the request */ - public async getOrderbookAsync(request: OrderbookRequest): Promise { - assert.doesConformToSchema('request', request, clientSchemas.relayerOrderBookRequestSchema); - const requestOpts = { - params: request, + public async getOrderbookAsync( + request: OrderbookRequest, + requestOpts?: PagedRequestOpts, + ): Promise { + 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 +116,11 @@ export class HttpClient implements Client { * @return The resulting FeesResponse that matches the request */ public async getFeesAsync(request: FeesRequest): Promise { - 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; } 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/orderbook_request_schema.ts b/packages/connect/src/schemas/orderbook_request_schema.ts new file mode 100644 index 000000000..5f3463242 --- /dev/null +++ b/packages/connect/src/schemas/orderbook_request_schema.ts @@ -0,0 +1,9 @@ +export const orderBookRequestSchema = { + id: '/OrderBookRequest', + type: 'object', + properties: { + baseTokenAddress: { $ref: '/Address' }, + quoteTokenAddress: { $ref: '/Address' }, + }, + required: ['baseTokenAddress', 'quoteTokenAddress'], +}; diff --git a/packages/connect/src/schemas/orders_request_opts_schema.ts b/packages/connect/src/schemas/orders_request_opts_schema.ts new file mode 100644 index 000000000..5facbc959 --- /dev/null +++ b/packages/connect/src/schemas/orders_request_opts_schema.ts @@ -0,0 +1,16 @@ +export const ordersRequestOptsSchema = { + id: '/OrdersRequestOpts', + type: 'object', + properties: { + exchangeContractAddress: { $ref: '/Address' }, + tokenAddress: { $ref: '/Address' }, + makerTokenAddress: { $ref: '/Address' }, + takerTokenAddress: { $ref: '/Address' }, + tokenA: { $ref: '/Address' }, + tokenB: { $ref: '/Address' }, + maker: { $ref: '/Address' }, + taker: { $ref: '/Address' }, + trader: { $ref: '/Address' }, + feeRecipient: { $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..f41a637b1 --- /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' }, + per_page: { type: 'number' }, + }, +}; diff --git a/packages/connect/src/schemas/relayer_fees_request_schema.ts b/packages/connect/src/schemas/relayer_fees_request_schema.ts deleted file mode 100644 index f20e077ba..000000000 --- a/packages/connect/src/schemas/relayer_fees_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/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/relayer_orders_request_schema.ts b/packages/connect/src/schemas/relayer_orders_request_schema.ts deleted file mode 100644 index 570238dae..000000000 --- a/packages/connect/src/schemas/relayer_orders_request_schema.ts +++ /dev/null @@ -1,16 +0,0 @@ -export const relayerOrdersRequestSchema = { - id: '/RelayerOrdersRequest', - type: 'object', - properties: { - exchangeContractAddress: { $ref: '/Address' }, - tokenAddress: { $ref: '/Address' }, - makerTokenAddress: { $ref: '/Address' }, - takerTokenAddress: { $ref: '/Address' }, - tokenA: { $ref: '/Address' }, - tokenB: { $ref: '/Address' }, - maker: { $ref: '/Address' }, - taker: { $ref: '/Address' }, - trader: { $ref: '/Address' }, - feeRecipient: { $ref: '/Address' }, - }, -}; diff --git a/packages/connect/src/schemas/relayer_token_pairs_request_schema.ts b/packages/connect/src/schemas/relayer_token_pairs_request_schema.ts deleted file mode 100644 index 379232204..000000000 --- a/packages/connect/src/schemas/relayer_token_pairs_request_schema.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const relayerTokenPairsRequestSchema = { - id: '/RelayerTokenPairsRequest', - type: 'object', - properties: { - tokenA: { $ref: '/Address' }, - tokenB: { $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/token_pairs_request_opts_schema.ts b/packages/connect/src/schemas/token_pairs_request_opts_schema.ts new file mode 100644 index 000000000..9b73a917b --- /dev/null +++ b/packages/connect/src/schemas/token_pairs_request_opts_schema.ts @@ -0,0 +1,8 @@ +export const tokenPairsRequestOptsSchema = { + id: '/TokenPairsRequestOpts', + type: 'object', + properties: { + tokenA: { $ref: '/Address' }, + tokenB: { $ref: '/Address' }, + }, +}; diff --git a/packages/connect/src/types.ts b/packages/connect/src/types.ts index edb6c77a6..38f213dca 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; - getOrdersAsync: (request?: OrdersRequest) => Promise; + getTokenPairsAsync: (requestOpts?: TokenPairsRequestOpts & PagedRequestOpts) => Promise; + getOrdersAsync: (requestOpts?: OrdersRequestOpts & PagedRequestOpts) => Promise; getOrderAsync: (orderHash: string) => Promise; - getOrderbookAsync: (request: OrderbookRequest) => Promise; + getOrderbookAsync: (request: OrderbookRequest, requestOpts?: PagedRequestOpts) => Promise; getFeesAsync: (request: FeesRequest) => Promise; submitOrderAsync: (signedOrder: SignedOrder) => Promise; } @@ -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; + per_page?: 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..62a159628 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=0&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, + per_page: 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=0&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, + per_page: 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=0&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, + per_page: 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(); diff --git a/packages/website/ts/containers/connect_documentation.tsx b/packages/website/ts/containers/connect_documentation.tsx index 3e02a7d05..22ba4a7a1 100644 --- a/packages/website/ts/containers/connect_documentation.tsx +++ b/packages/website/ts/containers/connect_documentation.tsx @@ -51,9 +51,10 @@ const docsInfoConfig: DocsInfoConfig = { 'OrderbookChannelSubscriptionOpts', 'OrderbookRequest', 'OrderbookResponse', - 'OrdersRequest', + 'OrdersRequestOpts', + 'PagedRequestOpts', 'TokenPairsItem', - 'TokenPairsRequest', + 'TokenPairsRequestOpts', 'TokenTradeInfo', 'Order', 'SignedOrder', -- cgit