Add networkId request param option

This commit is contained in:
fragosti 2018-08-17 10:43:44 -07:00
parent 64a85dfb9c
commit 48ec78d3aa
7 changed files with 64 additions and 39 deletions

View File

@ -21,6 +21,7 @@ import {
OrdersRequestOpts, OrdersRequestOpts,
OrdersResponse, OrdersResponse,
PagedRequestOpts, PagedRequestOpts,
RequestOpts,
} from './types'; } from './types';
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers'; import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
@ -29,6 +30,9 @@ const DEFAULT_PAGED_REQUEST_OPTS: PagedRequestOpts = {
page: 1, page: 1,
perPage: 100, perPage: 100,
}; };
const DEFAULT_REQUEST_OPTS: RequestOpts = {
networkId: 1,
};
/** /**
* This class includes all the functionality related to interacting with a set of HTTP endpoints * This class includes all the functionality related to interacting with a set of HTTP endpoints
@ -62,13 +66,14 @@ export class HttpClient implements Client {
* @param requestOpts Options specifying assetData information to retrieve and page information, defaults to { page: 1, perPage: 100 } * @param requestOpts Options specifying assetData information to retrieve and page information, defaults to { page: 1, perPage: 100 }
* @return The resulting AssetPairsItems that match the request * @return The resulting AssetPairsItems that match the request
*/ */
public async getAssetPairsAsync(requestOpts?: AssetPairsRequestOpts & PagedRequestOpts): Promise<AssetPairsResponse> { public async getAssetPairsAsync(requestOpts?: RequestOpts & AssetPairsRequestOpts & PagedRequestOpts): Promise<AssetPairsResponse> {
if (!_.isUndefined(requestOpts)) { if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.assetPairsRequestOptsSchema); assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.assetPairsRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema); assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
} }
const httpRequestOpts = { const httpRequestOpts = {
params: _.defaults({}, requestOpts, DEFAULT_PAGED_REQUEST_OPTS), params: _.defaults({}, requestOpts, DEFAULT_REQUEST_OPTS, DEFAULT_PAGED_REQUEST_OPTS),
}; };
const responseJson = await this._requestAsync('/asset_pairs', HttpRequestType.Get, httpRequestOpts); const responseJson = await this._requestAsync('/asset_pairs', HttpRequestType.Get, httpRequestOpts);
const assetDataPairs = relayerResponseJsonParsers.parseAssetDataPairsJson(responseJson); const assetDataPairs = relayerResponseJsonParsers.parseAssetDataPairsJson(responseJson);
@ -79,13 +84,14 @@ export class HttpClient implements Client {
* @param requestOpts Options specifying orders to retrieve and page information, defaults to { page: 1, perPage: 100 } * @param requestOpts Options specifying orders to retrieve and page information, defaults to { page: 1, perPage: 100 }
* @return The resulting SignedOrders that match the request * @return The resulting SignedOrders that match the request
*/ */
public async getOrdersAsync(requestOpts?: OrdersRequestOpts & PagedRequestOpts): Promise<OrdersResponse> { public async getOrdersAsync(requestOpts?: RequestOpts & OrdersRequestOpts & PagedRequestOpts): Promise<OrdersResponse> {
if (!_.isUndefined(requestOpts)) { if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.ordersRequestOptsSchema); assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.ordersRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema); assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
} }
const httpRequestOpts = { const httpRequestOpts = {
params: _.defaults({}, requestOpts, DEFAULT_PAGED_REQUEST_OPTS), params: _.defaults({}, requestOpts, DEFAULT_REQUEST_OPTS, DEFAULT_PAGED_REQUEST_OPTS),
}; };
const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, httpRequestOpts); const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, httpRequestOpts);
const orders = relayerResponseJsonParsers.parseOrdersJson(responseJson); const orders = relayerResponseJsonParsers.parseOrdersJson(responseJson);
@ -96,9 +102,15 @@ export class HttpClient implements Client {
* @param orderHash An orderHash generated from the desired order * @param orderHash An orderHash generated from the desired order
* @return The SignedOrder that matches the supplied orderHash * @return The SignedOrder that matches the supplied orderHash
*/ */
public async getOrderAsync(orderHash: string): Promise<APIOrder> { public async getOrderAsync(orderHash: string, requestOpts?: RequestOpts): Promise<APIOrder> {
if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
}
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
const responseJson = await this._requestAsync(`/order/${orderHash}`, HttpRequestType.Get); const httpRequestOpts = {
params: _.defaults({}, requestOpts, DEFAULT_REQUEST_OPTS),
};
const responseJson = await this._requestAsync(`/order/${orderHash}`, HttpRequestType.Get, httpRequestOpts);
const order = relayerResponseJsonParsers.parseAPIOrderJson(responseJson); const order = relayerResponseJsonParsers.parseAPIOrderJson(responseJson);
return order; return order;
} }
@ -110,14 +122,15 @@ export class HttpClient implements Client {
*/ */
public async getOrderbookAsync( public async getOrderbookAsync(
request: OrderbookRequest, request: OrderbookRequest,
requestOpts?: PagedRequestOpts, requestOpts?: RequestOpts & PagedRequestOpts,
): Promise<OrderbookResponse> { ): Promise<OrderbookResponse> {
assert.doesConformToSchema('request', request, clientSchemas.orderBookRequestSchema); assert.doesConformToSchema('request', request, clientSchemas.orderBookRequestSchema);
if (!_.isUndefined(requestOpts)) { if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema); assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
} }
const httpRequestOpts = { const httpRequestOpts = {
params: _.defaults({}, request, requestOpts, DEFAULT_PAGED_REQUEST_OPTS), params: _.defaults({}, request, requestOpts, DEFAULT_REQUEST_OPTS, DEFAULT_PAGED_REQUEST_OPTS),
}; };
const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, httpRequestOpts); const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, httpRequestOpts);
const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(responseJson); const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(responseJson);
@ -128,9 +141,13 @@ export class HttpClient implements Client {
* @param request A OrderConfigRequest instance describing the specific fees to retrieve * @param request A OrderConfigRequest instance describing the specific fees to retrieve
* @return The resulting OrderConfigResponse that matches the request * @return The resulting OrderConfigResponse that matches the request
*/ */
public async getOrderConfigAsync(request: OrderConfigRequest): Promise<OrderConfigResponse> { public async getOrderConfigAsync(request: OrderConfigRequest, requestOpts?: RequestOpts): Promise<OrderConfigResponse> {
if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
}
assert.doesConformToSchema('request', request, clientSchemas.orderConfigRequestSchema); assert.doesConformToSchema('request', request, clientSchemas.orderConfigRequestSchema);
const httpRequestOpts = { const httpRequestOpts = {
params: _.defaults({}, requestOpts, DEFAULT_REQUEST_OPTS),
payload: request, payload: request,
}; };
const responseJson = await this._requestAsync('/order_config', HttpRequestType.Post, httpRequestOpts); const responseJson = await this._requestAsync('/order_config', HttpRequestType.Post, httpRequestOpts);
@ -140,11 +157,15 @@ export class HttpClient implements Client {
/** /**
* Retrieve the list of fee recipient addresses used by * Retrieve the list of fee recipient addresses used by
*/ */
public async getFeeRecipientsAsync(requestOpts?: PagedRequestOpts): Promise<FeeRecipientsResponse> { public async getFeeRecipientsAsync(requestOpts?: RequestOpts & PagedRequestOpts): Promise<FeeRecipientsResponse> {
if (!_.isUndefined(requestOpts)) { if (!_.isUndefined(requestOpts)) {
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema); assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
} }
const feeRecipients = await this._requestAsync('/fee_recipients', HttpRequestType.Get); const httpRequestOpts = {
params: _.defaults({}, requestOpts, DEFAULT_REQUEST_OPTS, DEFAULT_PAGED_REQUEST_OPTS),
};
const feeRecipients = await this._requestAsync('/fee_recipients', HttpRequestType.Get, httpRequestOpts);
assert.doesConformToSchema('feeRecipients', feeRecipients, schemas.relayerApiFeeRecipientsResponseSchema); assert.doesConformToSchema('feeRecipients', feeRecipients, schemas.relayerApiFeeRecipientsResponseSchema);
return feeRecipients; return feeRecipients;
} }
@ -152,12 +173,13 @@ export class HttpClient implements Client {
* Submit a signed order to the API * Submit a signed order to the API
* @param signedOrder A SignedOrder instance to submit * @param signedOrder A SignedOrder instance to submit
*/ */
public async submitOrderAsync(signedOrder: SignedOrder): Promise<void> { public async submitOrderAsync(signedOrder: SignedOrder, requestOpts?: RequestOpts): Promise<void> {
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
const requestOpts = { const httpRequestOpts = {
params: _.defaults({}, requestOpts, DEFAULT_REQUEST_OPTS),
payload: signedOrder, payload: signedOrder,
}; };
await this._requestAsync('/order', HttpRequestType.Post, requestOpts); await this._requestAsync('/order', HttpRequestType.Post, httpRequestOpts);
} }
private async _requestAsync( private async _requestAsync(
path: string, path: string,

View File

@ -1,12 +1,12 @@
export { HttpClient } from './http_client'; export { HttpClient } from './http_client';
export { orderbookChannelFactory } from './orderbook_channel_factory'; export { ordersChannelFactory } from './orders_channel_factory';
export { export {
Client, Client,
OrderConfigRequest, OrderConfigRequest,
OrderConfigResponse, OrderConfigResponse,
OrderbookChannel, OrdersChannel,
OrderbookChannelHandler, OrdersChannelHandler,
OrderbookChannelSubscriptionOpts, OrdersChannelSubscriptionOpts,
OrderbookRequest, OrderbookRequest,
OrderbookResponse, OrderbookResponse,
OrdersRequestOpts, OrdersRequestOpts,

View File

@ -10,14 +10,14 @@ export const ordersChannelFactory = {
* @param url The relayer API base WS url you would like to interact with * @param url The relayer API base WS url you would like to interact with
* @param handler An OrderbookChannelHandler instance that responds to various * @param handler An OrderbookChannelHandler instance that responds to various
* channel updates * channel updates
* @return An OrderbookChannel Promise * @return An OrdersChannel Promise
*/ */
async createWebSocketOrdersChannelAsync( async createWebSocketOrdersChannelAsync(
url: string, url: string,
handler: OrdersChannelHandler, handler: OrdersChannelHandler,
): Promise<OrdersChannel> { ): Promise<OrdersChannel> {
assert.isUri('url', url); assert.isUri('url', url);
assert.isOrderbookChannelHandler('handler', handler); assert.isOrdersChannelHandler('handler', handler);
return new Promise<OrdersChannel>((resolve, reject) => { return new Promise<OrdersChannel>((resolve, reject) => {
const client = new WebSocket.w3cwebsocket(url); const client = new WebSocket.w3cwebsocket(url);
client.onopen = () => { client.onopen = () => {

View File

@ -3,11 +3,13 @@ import { orderConfigRequestSchema } from './order_config_request_schema';
import { orderBookRequestSchema } from './orderbook_request_schema'; import { orderBookRequestSchema } from './orderbook_request_schema';
import { ordersRequestOptsSchema } from './orders_request_opts_schema'; import { ordersRequestOptsSchema } from './orders_request_opts_schema';
import { pagedRequestOptsSchema } from './paged_request_opts_schema'; import { pagedRequestOptsSchema } from './paged_request_opts_schema';
import { requestOptsSchema } from './request_opts_schema';
export const schemas = { export const schemas = {
orderConfigRequestSchema, orderConfigRequestSchema,
orderBookRequestSchema, orderBookRequestSchema,
ordersRequestOptsSchema, ordersRequestOptsSchema,
pagedRequestOptsSchema, pagedRequestOptsSchema,
requestOptsSchema,
assetPairsRequestOptsSchema, assetPairsRequestOptsSchema,
}; };

View File

@ -147,6 +147,10 @@ export interface OrderConfigResponse {
export type FeeRecipientsResponse = PaginatedCollection<string>; export type FeeRecipientsResponse = PaginatedCollection<string>;
export interface RequestOpts {
networkId?: number;
}
export interface PagedRequestOpts { export interface PagedRequestOpts {
page?: number; page?: number;
perPage?: number; perPage?: number;

View File

@ -3,15 +3,12 @@ import * as dirtyChai from 'dirty-chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
import 'mocha'; import 'mocha';
import { orderbookChannelFactory } from '../src/orderbook_channel_factory'; import { ordersChannelFactory } from '../src/orders_channel_factory';
chai.config.includeStack = true; chai.config.includeStack = true;
chai.use(dirtyChai); chai.use(dirtyChai);
const expect = chai.expect; const expect = chai.expect;
const emptyOrderbookChannelHandler = { const emptyOrdersChannelHandler = {
onSnapshot: () => {
_.noop();
},
onUpdate: () => { onUpdate: () => {
_.noop(); _.noop();
}, },
@ -23,22 +20,22 @@ const emptyOrderbookChannelHandler = {
}, },
}; };
describe('orderbookChannelFactory', () => { describe('ordersChannelFactory', () => {
const websocketUrl = 'ws://localhost:8080'; const websocketUrl = 'ws://localhost:8080';
describe('#createWebSocketOrderbookChannelAsync', () => { describe('#createWebSocketOrdersChannelAsync', () => {
it('throws when input is not a url', () => { it('throws when input is not a url', () => {
const badUrlInput = 54; const badUrlInput = 54;
expect( expect(
orderbookChannelFactory.createWebSocketOrderbookChannelAsync( ordersChannelFactory.createWebSocketOrdersChannelAsync(
badUrlInput as any, badUrlInput as any,
emptyOrderbookChannelHandler, emptyOrdersChannelHandler,
), ),
).to.be.rejected(); ).to.be.rejected();
}); });
it('throws when handler has the incorrect members', () => { it('throws when handler has the incorrect members', () => {
const badHandlerInput = {}; const badHandlerInput = {};
expect( expect(
orderbookChannelFactory.createWebSocketOrderbookChannelAsync(websocketUrl, badHandlerInput as any), ordersChannelFactory.createWebSocketOrdersChannelAsync(websocketUrl, badHandlerInput as any),
).to.be.rejected(); ).to.be.rejected();
}); });
}); });

View File

@ -5,12 +5,12 @@ import 'mocha';
import * as Sinon from 'sinon'; import * as Sinon from 'sinon';
import * as WebSocket from 'websocket'; import * as WebSocket from 'websocket';
import { WebSocketOrderbookChannel } from '../src/ws_orderbook_channel'; import { WebSocketOrdersChannel } from '../src/ws_orders_channel';
chai.config.includeStack = true; chai.config.includeStack = true;
chai.use(dirtyChai); chai.use(dirtyChai);
const expect = chai.expect; const expect = chai.expect;
const emptyOrderbookChannelHandler = { const emptyOrdersChannelHandler = {
onSnapshot: () => { onSnapshot: () => {
_.noop(); _.noop();
}, },
@ -25,12 +25,12 @@ const emptyOrderbookChannelHandler = {
}, },
}; };
describe('WebSocketOrderbookChannel', () => { describe('WebSocketOrdersChannel', () => {
const websocketUrl = 'ws://localhost:8080'; const websocketUrl = 'ws://localhost:8080';
const openClient = new WebSocket.w3cwebsocket(websocketUrl); const openClient = new WebSocket.w3cwebsocket(websocketUrl);
Sinon.stub(openClient, 'readyState').get(() => WebSocket.w3cwebsocket.OPEN); Sinon.stub(openClient, 'readyState').get(() => WebSocket.w3cwebsocket.OPEN);
Sinon.stub(openClient, 'send').callsFake(_.noop.bind(_)); Sinon.stub(openClient, 'send').callsFake(_.noop.bind(_));
const openOrderbookChannel = new WebSocketOrderbookChannel(openClient, emptyOrderbookChannelHandler); const openOrdersChannel = new WebSocketOrdersChannel(openClient, emptyOrdersChannelHandler);
const subscriptionOpts = { const subscriptionOpts = {
baseAssetData: '0x323b5d4c32345ced77393b3530b1eed0f346429d', baseAssetData: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
quoteAssetData: '0xef7fff64389b814a946f3e92105513705ca6b990', quoteAssetData: '0xef7fff64389b814a946f3e92105513705ca6b990',
@ -39,20 +39,20 @@ describe('WebSocketOrderbookChannel', () => {
}; };
describe('#subscribe', () => { describe('#subscribe', () => {
it('throws when subscriptionOpts does not conform to schema', () => { it('throws when subscriptionOpts does not conform to schema', () => {
const badSubscribeCall = openOrderbookChannel.subscribe.bind(openOrderbookChannel, {}); const badSubscribeCall = openOrdersChannel.subscribe.bind(openOrdersChannel, {});
expect(badSubscribeCall).throws( expect(badSubscribeCall).throws(
'Expected subscriptionOpts to conform to schema /RelayerApiOrderbookChannelSubscribePayload\nEncountered: {}\nValidation errors: instance requires property "baseAssetData", instance requires property "quoteAssetData"', 'Expected subscriptionOpts to conform to schema /RelayerApiOrdersChannelSubscribePayload\nEncountered: {}\nValidation errors: instance requires property "baseAssetData", instance requires property "quoteAssetData"',
); );
}); });
it('does not throw when inputs are of correct types', () => { it('does not throw when inputs are of correct types', () => {
const goodSubscribeCall = openOrderbookChannel.subscribe.bind(openOrderbookChannel, subscriptionOpts); const goodSubscribeCall = openOrdersChannel.subscribe.bind(openOrdersChannel, subscriptionOpts);
expect(goodSubscribeCall).to.not.throw(); expect(goodSubscribeCall).to.not.throw();
}); });
it('throws when client is closed', () => { it('throws when client is closed', () => {
const closedClient = new WebSocket.w3cwebsocket(websocketUrl); const closedClient = new WebSocket.w3cwebsocket(websocketUrl);
Sinon.stub(closedClient, 'readyState').get(() => WebSocket.w3cwebsocket.CLOSED); Sinon.stub(closedClient, 'readyState').get(() => WebSocket.w3cwebsocket.CLOSED);
const closedOrderbookChannel = new WebSocketOrderbookChannel(closedClient, emptyOrderbookChannelHandler); const closedOrdersChannel = new WebSocketOrdersChannel(closedClient, emptyOrdersChannelHandler);
const badSubscribeCall = closedOrderbookChannel.subscribe.bind(closedOrderbookChannel, subscriptionOpts); const badSubscribeCall = closedOrdersChannel.subscribe.bind(closedOrdersChannel, subscriptionOpts);
expect(badSubscribeCall).throws('WebSocket connection is closed'); expect(badSubscribeCall).throws('WebSocket connection is closed');
}); });
}); });