diff options
Diffstat (limited to 'packages/connect/src')
-rw-r--r-- | packages/connect/src/globals.d.ts | 4 | ||||
-rw-r--r-- | packages/connect/src/http_client.ts | 268 | ||||
-rw-r--r-- | packages/connect/src/index.ts | 30 | ||||
-rw-r--r-- | packages/connect/src/schemas/relayer_fees_request_schema.ts | 12 | ||||
-rw-r--r-- | packages/connect/src/schemas/relayer_orderbook_request_schema.ts | 12 | ||||
-rw-r--r-- | packages/connect/src/schemas/relayer_orders_request_schema.ts | 28 | ||||
-rw-r--r-- | packages/connect/src/schemas/relayer_token_pairs_request_schema.ts | 12 | ||||
-rw-r--r-- | packages/connect/src/schemas/schemas.ts | 6 | ||||
-rw-r--r-- | packages/connect/src/types.ts | 192 | ||||
-rw-r--r-- | packages/connect/src/utils/orderbook_channel_message_parser.ts | 54 | ||||
-rw-r--r-- | packages/connect/src/utils/relayer_response_json_parsers.ts | 54 | ||||
-rw-r--r-- | packages/connect/src/utils/type_converters.ts | 50 | ||||
-rw-r--r-- | packages/connect/src/ws_orderbook_channel.ts | 238 |
13 files changed, 480 insertions, 480 deletions
diff --git a/packages/connect/src/globals.d.ts b/packages/connect/src/globals.d.ts index 078e189cd..d2011026b 100644 --- a/packages/connect/src/globals.d.ts +++ b/packages/connect/src/globals.d.ts @@ -1,6 +1,6 @@ declare module 'dirty-chai'; declare module '*.json' { - const value: any; - export default value; + const value: any; + export default value; } diff --git a/packages/connect/src/http_client.ts b/packages/connect/src/http_client.ts index 3df77b0f0..03c0b9702 100644 --- a/packages/connect/src/http_client.ts +++ b/packages/connect/src/http_client.ts @@ -6,17 +6,17 @@ import * as queryString from 'query-string'; import { schemas as clientSchemas } from './schemas/schemas'; import { - Client, - FeesRequest, - FeesResponse, - HttpRequestOptions, - HttpRequestType, - OrderbookRequest, - OrderbookResponse, - OrdersRequest, - SignedOrder, - TokenPairsItem, - TokenPairsRequest, + Client, + FeesRequest, + FeesResponse, + HttpRequestOptions, + HttpRequestType, + OrderbookRequest, + OrderbookResponse, + OrdersRequest, + SignedOrder, + TokenPairsItem, + TokenPairsRequest, } from './types'; import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers'; @@ -26,127 +26,127 @@ const TRAILING_SLASHES_REGEX = /\/+$/; * that implement the standard relayer API v0 */ export class HttpClient implements Client { - private _apiEndpointUrl: string; - /** - * Instantiates a new HttpClient instance - * @param url The relayer API base HTTP url you would like to interact with - * @return An instance of HttpClient - */ - constructor(url: string) { - assert.isHttpUrl('url', url); - this._apiEndpointUrl = url.replace(TRAILING_SLASHES_REGEX, ''); // remove trailing slashes - } - /** - * Retrieve token pair info from the API - * @param request A TokenPairsRequest instance describing specific token information - * to retrieve - * @return The resulting TokenPairsItems that match the request - */ - public async getTokenPairsAsync(request?: TokenPairsRequest): Promise<TokenPairsItem[]> { - if (!_.isUndefined(request)) { - assert.doesConformToSchema('request', request, clientSchemas.relayerTokenPairsRequestSchema); - } - const requestOpts = { - params: request, - }; - const responseJson = await this._requestAsync('/token_pairs', HttpRequestType.Get, requestOpts); - const tokenPairs = relayerResponseJsonParsers.parseTokenPairsJson(responseJson); - return tokenPairs; - } - /** - * Retrieve orders from the API - * @param request An OrdersRequest instance describing specific orders to retrieve - * @return The resulting SignedOrders that match the request - */ - public async getOrdersAsync(request?: OrdersRequest): Promise<SignedOrder[]> { - if (!_.isUndefined(request)) { - assert.doesConformToSchema('request', request, clientSchemas.relayerOrdersRequestSchema); - } - const requestOpts = { - params: request, - }; - const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, requestOpts); - const orders = relayerResponseJsonParsers.parseOrdersJson(responseJson); - return orders; - } - /** - * Retrieve a specific order from the API - * @param orderHash An orderHash generated from the desired order - * @return The SignedOrder that matches the supplied orderHash - */ - public async getOrderAsync(orderHash: string): Promise<SignedOrder> { - assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); - const responseJson = await this._requestAsync(`/order/${orderHash}`, HttpRequestType.Get); - const order = relayerResponseJsonParsers.parseOrderJson(responseJson); - return order; - } - /** - * Retrieve an orderbook from the API - * @param request An OrderbookRequest instance describing the specific orderbook to retrieve - * @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, - }; - const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, requestOpts); - const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(responseJson); - return orderbook; - } - /** - * Retrieve fee information from the API - * @param request A FeesRequest instance describing the specific fees to retrieve - * @return The resulting FeesResponse that matches the request - */ - public async getFeesAsync(request: FeesRequest): Promise<FeesResponse> { - assert.doesConformToSchema('request', request, schemas.relayerApiFeesPayloadSchema); - const requestOpts = { - payload: request, - }; - const responseJson = await this._requestAsync('/fees', HttpRequestType.Post, requestOpts); - const fees = relayerResponseJsonParsers.parseFeesResponseJson(responseJson); - return fees; - } - /** - * Submit a signed order to the API - * @param signedOrder A SignedOrder instance to submit - */ - public async submitOrderAsync(signedOrder: SignedOrder): Promise<void> { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - const requestOpts = { - payload: signedOrder, - }; - await this._requestAsync('/order', HttpRequestType.Post, requestOpts); - } - private async _requestAsync( - path: string, - requestType: HttpRequestType, - requestOptions?: HttpRequestOptions, - ): 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 url = `${this._apiEndpointUrl}${path}${query}`; - const headers = new Headers({ - 'content-type': 'application/json', - }); - const response = await fetch(url, { - method: requestType, - body: JSON.stringify(payload), - headers, - }); - const json = await response.json(); - if (!response.ok) { - const errorString = `${response.status} - ${response.statusText}\n${requestType} ${url}\n${JSON.stringify( - json, - )}`; - throw Error(errorString); - } - return json; - } + private _apiEndpointUrl: string; + /** + * Instantiates a new HttpClient instance + * @param url The relayer API base HTTP url you would like to interact with + * @return An instance of HttpClient + */ + constructor(url: string) { + assert.isHttpUrl('url', url); + this._apiEndpointUrl = url.replace(TRAILING_SLASHES_REGEX, ''); // remove trailing slashes + } + /** + * Retrieve token pair info from the API + * @param request A TokenPairsRequest instance describing specific token information + * to retrieve + * @return The resulting TokenPairsItems that match the request + */ + public async getTokenPairsAsync(request?: TokenPairsRequest): Promise<TokenPairsItem[]> { + if (!_.isUndefined(request)) { + assert.doesConformToSchema('request', request, clientSchemas.relayerTokenPairsRequestSchema); + } + const requestOpts = { + params: request, + }; + const responseJson = await this._requestAsync('/token_pairs', HttpRequestType.Get, requestOpts); + const tokenPairs = relayerResponseJsonParsers.parseTokenPairsJson(responseJson); + return tokenPairs; + } + /** + * Retrieve orders from the API + * @param request An OrdersRequest instance describing specific orders to retrieve + * @return The resulting SignedOrders that match the request + */ + public async getOrdersAsync(request?: OrdersRequest): Promise<SignedOrder[]> { + if (!_.isUndefined(request)) { + assert.doesConformToSchema('request', request, clientSchemas.relayerOrdersRequestSchema); + } + const requestOpts = { + params: request, + }; + const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, requestOpts); + const orders = relayerResponseJsonParsers.parseOrdersJson(responseJson); + return orders; + } + /** + * Retrieve a specific order from the API + * @param orderHash An orderHash generated from the desired order + * @return The SignedOrder that matches the supplied orderHash + */ + public async getOrderAsync(orderHash: string): Promise<SignedOrder> { + assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); + const responseJson = await this._requestAsync(`/order/${orderHash}`, HttpRequestType.Get); + const order = relayerResponseJsonParsers.parseOrderJson(responseJson); + return order; + } + /** + * Retrieve an orderbook from the API + * @param request An OrderbookRequest instance describing the specific orderbook to retrieve + * @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, + }; + const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, requestOpts); + const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(responseJson); + return orderbook; + } + /** + * Retrieve fee information from the API + * @param request A FeesRequest instance describing the specific fees to retrieve + * @return The resulting FeesResponse that matches the request + */ + public async getFeesAsync(request: FeesRequest): Promise<FeesResponse> { + assert.doesConformToSchema('request', request, schemas.relayerApiFeesPayloadSchema); + const requestOpts = { + payload: request, + }; + const responseJson = await this._requestAsync('/fees', HttpRequestType.Post, requestOpts); + const fees = relayerResponseJsonParsers.parseFeesResponseJson(responseJson); + return fees; + } + /** + * Submit a signed order to the API + * @param signedOrder A SignedOrder instance to submit + */ + public async submitOrderAsync(signedOrder: SignedOrder): Promise<void> { + assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); + const requestOpts = { + payload: signedOrder, + }; + await this._requestAsync('/order', HttpRequestType.Post, requestOpts); + } + private async _requestAsync( + path: string, + requestType: HttpRequestType, + requestOptions?: HttpRequestOptions, + ): 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 url = `${this._apiEndpointUrl}${path}${query}`; + const headers = new Headers({ + 'content-type': 'application/json', + }); + const response = await fetch(url, { + method: requestType, + body: JSON.stringify(payload), + headers, + }); + const json = await response.json(); + if (!response.ok) { + const errorString = `${response.status} - ${response.statusText}\n${requestType} ${url}\n${JSON.stringify( + json, + )}`; + throw Error(errorString); + } + return json; + } } diff --git a/packages/connect/src/index.ts b/packages/connect/src/index.ts index a492f5ae9..d0cce9935 100644 --- a/packages/connect/src/index.ts +++ b/packages/connect/src/index.ts @@ -1,19 +1,19 @@ export { HttpClient } from './http_client'; export { WebSocketOrderbookChannel } from './ws_orderbook_channel'; export { - Client, - ECSignature, - FeesRequest, - FeesResponse, - Order, - OrderbookChannel, - OrderbookChannelHandler, - OrderbookChannelSubscriptionOpts, - OrderbookRequest, - OrderbookResponse, - OrdersRequest, - SignedOrder, - TokenPairsItem, - TokenPairsRequest, - TokenTradeInfo, + Client, + ECSignature, + FeesRequest, + FeesResponse, + Order, + OrderbookChannel, + OrderbookChannelHandler, + OrderbookChannelSubscriptionOpts, + OrderbookRequest, + OrderbookResponse, + OrdersRequest, + SignedOrder, + TokenPairsItem, + TokenPairsRequest, + TokenTradeInfo, } from './types'; diff --git a/packages/connect/src/schemas/relayer_fees_request_schema.ts b/packages/connect/src/schemas/relayer_fees_request_schema.ts index f20e077ba..bd0b91fa3 100644 --- a/packages/connect/src/schemas/relayer_fees_request_schema.ts +++ b/packages/connect/src/schemas/relayer_fees_request_schema.ts @@ -1,8 +1,8 @@ export const relayerOrderBookRequestSchema = { - id: '/RelayerOrderBookRequest', - type: 'object', - properties: { - baseTokenAddress: { $ref: '/Address' }, - quoteTokenAddress: { $ref: '/Address' }, - }, + 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 index f20e077ba..bd0b91fa3 100644 --- a/packages/connect/src/schemas/relayer_orderbook_request_schema.ts +++ b/packages/connect/src/schemas/relayer_orderbook_request_schema.ts @@ -1,8 +1,8 @@ export const relayerOrderBookRequestSchema = { - id: '/RelayerOrderBookRequest', - type: 'object', - properties: { - baseTokenAddress: { $ref: '/Address' }, - quoteTokenAddress: { $ref: '/Address' }, - }, + 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 index 570238dae..0471cb104 100644 --- a/packages/connect/src/schemas/relayer_orders_request_schema.ts +++ b/packages/connect/src/schemas/relayer_orders_request_schema.ts @@ -1,16 +1,16 @@ 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' }, - }, + 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 index 379232204..cb79efdb3 100644 --- a/packages/connect/src/schemas/relayer_token_pairs_request_schema.ts +++ b/packages/connect/src/schemas/relayer_token_pairs_request_schema.ts @@ -1,8 +1,8 @@ export const relayerTokenPairsRequestSchema = { - id: '/RelayerTokenPairsRequest', - type: 'object', - properties: { - tokenA: { $ref: '/Address' }, - tokenB: { $ref: '/Address' }, - }, + 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..2982d81ab 100644 --- a/packages/connect/src/schemas/schemas.ts +++ b/packages/connect/src/schemas/schemas.ts @@ -3,7 +3,7 @@ import { relayerOrdersRequestSchema } from './relayer_orders_request_schema'; import { relayerTokenPairsRequestSchema } from './relayer_token_pairs_request_schema'; export const schemas = { - relayerOrderBookRequestSchema, - relayerOrdersRequestSchema, - relayerTokenPairsRequestSchema, + relayerOrderBookRequestSchema, + relayerOrdersRequestSchema, + relayerTokenPairsRequestSchema, }; diff --git a/packages/connect/src/types.ts b/packages/connect/src/types.ts index edb6c77a6..5f72f6e85 100644 --- a/packages/connect/src/types.ts +++ b/packages/connect/src/types.ts @@ -2,45 +2,45 @@ import { BigNumber } from '@0xproject/utils'; // TODO: Consolidate Order, SignedOrder and ECSignature into a shared package instead of duplicating them from 0x.js export interface Order { - maker: string; - taker: string; - makerFee: BigNumber; - takerFee: BigNumber; - makerTokenAmount: BigNumber; - takerTokenAmount: BigNumber; - makerTokenAddress: string; - takerTokenAddress: string; - salt: BigNumber; - exchangeContractAddress: string; - feeRecipient: string; - expirationUnixTimestampSec: BigNumber; + maker: string; + taker: string; + makerFee: BigNumber; + takerFee: BigNumber; + makerTokenAmount: BigNumber; + takerTokenAmount: BigNumber; + makerTokenAddress: string; + takerTokenAddress: string; + salt: BigNumber; + exchangeContractAddress: string; + feeRecipient: string; + expirationUnixTimestampSec: BigNumber; } export interface SignedOrder extends Order { - ecSignature: ECSignature; + ecSignature: ECSignature; } /** * Elliptic Curve signature */ export interface ECSignature { - v: number; - r: string; - s: string; + v: number; + r: string; + s: string; } export interface Client { - getTokenPairsAsync: (request?: TokenPairsRequest) => Promise<TokenPairsItem[]>; - getOrdersAsync: (request?: OrdersRequest) => Promise<SignedOrder[]>; - getOrderAsync: (orderHash: string) => Promise<SignedOrder>; - getOrderbookAsync: (request: OrderbookRequest) => Promise<OrderbookResponse>; - getFeesAsync: (request: FeesRequest) => Promise<FeesResponse>; - submitOrderAsync: (signedOrder: SignedOrder) => Promise<void>; + getTokenPairsAsync: (request?: TokenPairsRequest) => Promise<TokenPairsItem[]>; + getOrdersAsync: (request?: OrdersRequest) => Promise<SignedOrder[]>; + getOrderAsync: (orderHash: string) => Promise<SignedOrder>; + getOrderbookAsync: (request: OrderbookRequest) => Promise<OrderbookResponse>; + getFeesAsync: (request: FeesRequest) => Promise<FeesResponse>; + submitOrderAsync: (signedOrder: SignedOrder) => Promise<void>; } export interface OrderbookChannel { - subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler) => void; - close: () => void; + subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler) => void; + close: () => void; } /* @@ -50,129 +50,129 @@ export interface OrderbookChannel { * limit: Maximum number of bids and asks in orderbook snapshot */ export interface OrderbookChannelSubscriptionOpts { - baseTokenAddress: string; - quoteTokenAddress: string; - snapshot: boolean; - limit: number; + baseTokenAddress: string; + quoteTokenAddress: string; + snapshot: boolean; + limit: number; } export interface OrderbookChannelHandler { - onSnapshot: ( - channel: OrderbookChannel, - subscriptionOpts: OrderbookChannelSubscriptionOpts, - snapshot: OrderbookResponse, - ) => void; - onUpdate: ( - channel: OrderbookChannel, - subscriptionOpts: OrderbookChannelSubscriptionOpts, - order: SignedOrder, - ) => void; - onError: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts, err: Error) => void; - onClose: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts) => void; + onSnapshot: ( + channel: OrderbookChannel, + subscriptionOpts: OrderbookChannelSubscriptionOpts, + snapshot: OrderbookResponse, + ) => void; + onUpdate: ( + channel: OrderbookChannel, + subscriptionOpts: OrderbookChannelSubscriptionOpts, + order: SignedOrder, + ) => void; + onError: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts, err: Error) => void; + onClose: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts) => void; } export type OrderbookChannelMessage = - | SnapshotOrderbookChannelMessage - | UpdateOrderbookChannelMessage - | UnknownOrderbookChannelMessage; + | SnapshotOrderbookChannelMessage + | UpdateOrderbookChannelMessage + | UnknownOrderbookChannelMessage; export enum OrderbookChannelMessageTypes { - Snapshot = 'snapshot', - Update = 'update', - Unknown = 'unknown', + Snapshot = 'snapshot', + Update = 'update', + Unknown = 'unknown', } export interface SnapshotOrderbookChannelMessage { - type: OrderbookChannelMessageTypes.Snapshot; - requestId: number; - payload: OrderbookResponse; + type: OrderbookChannelMessageTypes.Snapshot; + requestId: number; + payload: OrderbookResponse; } export interface UpdateOrderbookChannelMessage { - type: OrderbookChannelMessageTypes.Update; - requestId: number; - payload: SignedOrder; + type: OrderbookChannelMessageTypes.Update; + requestId: number; + payload: SignedOrder; } export interface UnknownOrderbookChannelMessage { - type: OrderbookChannelMessageTypes.Unknown; - requestId: number; - payload: undefined; + type: OrderbookChannelMessageTypes.Unknown; + requestId: number; + payload: undefined; } export enum WebsocketConnectionEventType { - Close = 'close', - Error = 'error', - Message = 'message', + Close = 'close', + Error = 'error', + Message = 'message', } export enum WebsocketClientEventType { - Connect = 'connect', - ConnectFailed = 'connectFailed', + Connect = 'connect', + ConnectFailed = 'connectFailed', } export interface TokenPairsRequest { - tokenA?: string; - tokenB?: string; + tokenA?: string; + tokenB?: string; } export interface TokenPairsItem { - tokenA: TokenTradeInfo; - tokenB: TokenTradeInfo; + tokenA: TokenTradeInfo; + tokenB: TokenTradeInfo; } export interface TokenTradeInfo { - address: string; - minAmount: BigNumber; - maxAmount: BigNumber; - precision: number; + address: string; + minAmount: BigNumber; + maxAmount: BigNumber; + precision: number; } export interface OrdersRequest { - exchangeContractAddress?: string; - tokenAddress?: string; - makerTokenAddress?: string; - takerTokenAddress?: string; - maker?: string; - taker?: string; - trader?: string; - feeRecipient?: string; + exchangeContractAddress?: string; + tokenAddress?: string; + makerTokenAddress?: string; + takerTokenAddress?: string; + maker?: string; + taker?: string; + trader?: string; + feeRecipient?: string; } export interface OrderbookRequest { - baseTokenAddress: string; - quoteTokenAddress: string; + baseTokenAddress: string; + quoteTokenAddress: string; } export interface OrderbookResponse { - bids: SignedOrder[]; - asks: SignedOrder[]; + bids: SignedOrder[]; + asks: SignedOrder[]; } export interface FeesRequest { - exchangeContractAddress: string; - maker: string; - taker: string; - makerTokenAddress: string; - takerTokenAddress: string; - makerTokenAmount: BigNumber; - takerTokenAmount: BigNumber; - expirationUnixTimestampSec: BigNumber; - salt: BigNumber; + exchangeContractAddress: string; + maker: string; + taker: string; + makerTokenAddress: string; + takerTokenAddress: string; + makerTokenAmount: BigNumber; + takerTokenAmount: BigNumber; + expirationUnixTimestampSec: BigNumber; + salt: BigNumber; } export interface FeesResponse { - feeRecipient: string; - makerFee: BigNumber; - takerFee: BigNumber; + feeRecipient: string; + makerFee: BigNumber; + takerFee: BigNumber; } export interface HttpRequestOptions { - params?: object; - payload?: object; + params?: object; + payload?: object; } export enum HttpRequestType { - Get = 'GET', - Post = 'POST', + Get = 'GET', + Post = 'POST', } diff --git a/packages/connect/src/utils/orderbook_channel_message_parser.ts b/packages/connect/src/utils/orderbook_channel_message_parser.ts index 9a9ca8901..c5dd2ee2e 100644 --- a/packages/connect/src/utils/orderbook_channel_message_parser.ts +++ b/packages/connect/src/utils/orderbook_channel_message_parser.ts @@ -7,31 +7,31 @@ import { OrderbookChannelMessage, OrderbookChannelMessageTypes } from '../types' import { relayerResponseJsonParsers } from './relayer_response_json_parsers'; export const orderbookChannelMessageParser = { - parse(utf8Data: string): OrderbookChannelMessage { - const messageObj = JSON.parse(utf8Data); - const type: string = _.get(messageObj, 'type'); - assert.assert(!_.isUndefined(type), `Message is missing a type parameter: ${utf8Data}`); - assert.isString('type', type); - switch (type) { - case OrderbookChannelMessageTypes.Snapshot: { - assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelSnapshotSchema); - const orderbookJson = messageObj.payload; - const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(orderbookJson); - return _.assign(messageObj, { payload: orderbook }); - } - case OrderbookChannelMessageTypes.Update: { - assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelUpdateSchema); - const orderJson = messageObj.payload; - const order = relayerResponseJsonParsers.parseOrderJson(orderJson); - return _.assign(messageObj, { payload: order }); - } - default: { - return { - type: OrderbookChannelMessageTypes.Unknown, - requestId: 0, - payload: undefined, - }; - } - } - }, + parse(utf8Data: string): OrderbookChannelMessage { + const messageObj = JSON.parse(utf8Data); + const type: string = _.get(messageObj, 'type'); + assert.assert(!_.isUndefined(type), `Message is missing a type parameter: ${utf8Data}`); + assert.isString('type', type); + switch (type) { + case OrderbookChannelMessageTypes.Snapshot: { + assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelSnapshotSchema); + const orderbookJson = messageObj.payload; + const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(orderbookJson); + return _.assign(messageObj, { payload: orderbook }); + } + case OrderbookChannelMessageTypes.Update: { + assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelUpdateSchema); + const orderJson = messageObj.payload; + const order = relayerResponseJsonParsers.parseOrderJson(orderJson); + return _.assign(messageObj, { payload: order }); + } + default: { + return { + type: OrderbookChannelMessageTypes.Unknown, + requestId: 0, + payload: undefined, + }; + } + } + }, }; diff --git a/packages/connect/src/utils/relayer_response_json_parsers.ts b/packages/connect/src/utils/relayer_response_json_parsers.ts index 668461bf4..b6c5decaf 100644 --- a/packages/connect/src/utils/relayer_response_json_parsers.ts +++ b/packages/connect/src/utils/relayer_response_json_parsers.ts @@ -7,31 +7,31 @@ import { FeesResponse, OrderbookResponse, SignedOrder, TokenPairsItem } from '.. import { typeConverters } from './type_converters'; export const relayerResponseJsonParsers = { - parseTokenPairsJson(json: any): TokenPairsItem[] { - assert.doesConformToSchema('tokenPairs', json, schemas.relayerApiTokenPairsResponseSchema); - return json.map((tokenPair: any) => { - return typeConverters.convertStringsFieldsToBigNumbers(tokenPair, [ - 'tokenA.minAmount', - 'tokenA.maxAmount', - 'tokenB.minAmount', - 'tokenB.maxAmount', - ]); - }); - }, - parseOrdersJson(json: any): SignedOrder[] { - assert.doesConformToSchema('orders', json, schemas.signedOrdersSchema); - return json.map((order: object) => typeConverters.convertOrderStringFieldsToBigNumber(order)); - }, - parseOrderJson(json: any): SignedOrder { - assert.doesConformToSchema('order', json, schemas.signedOrderSchema); - return typeConverters.convertOrderStringFieldsToBigNumber(json); - }, - parseOrderbookResponseJson(json: any): OrderbookResponse { - assert.doesConformToSchema('orderBook', json, schemas.relayerApiOrderBookResponseSchema); - return typeConverters.convertOrderbookStringFieldsToBigNumber(json); - }, - parseFeesResponseJson(json: any): FeesResponse { - assert.doesConformToSchema('fees', json, schemas.relayerApiFeesResponseSchema); - return typeConverters.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']); - }, + parseTokenPairsJson(json: any): TokenPairsItem[] { + assert.doesConformToSchema('tokenPairs', json, schemas.relayerApiTokenPairsResponseSchema); + return json.map((tokenPair: any) => { + return typeConverters.convertStringsFieldsToBigNumbers(tokenPair, [ + 'tokenA.minAmount', + 'tokenA.maxAmount', + 'tokenB.minAmount', + 'tokenB.maxAmount', + ]); + }); + }, + parseOrdersJson(json: any): SignedOrder[] { + assert.doesConformToSchema('orders', json, schemas.signedOrdersSchema); + return json.map((order: object) => typeConverters.convertOrderStringFieldsToBigNumber(order)); + }, + parseOrderJson(json: any): SignedOrder { + assert.doesConformToSchema('order', json, schemas.signedOrderSchema); + return typeConverters.convertOrderStringFieldsToBigNumber(json); + }, + parseOrderbookResponseJson(json: any): OrderbookResponse { + assert.doesConformToSchema('orderBook', json, schemas.relayerApiOrderBookResponseSchema); + return typeConverters.convertOrderbookStringFieldsToBigNumber(json); + }, + parseFeesResponseJson(json: any): FeesResponse { + assert.doesConformToSchema('fees', json, schemas.relayerApiFeesResponseSchema); + return typeConverters.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']); + }, }; diff --git a/packages/connect/src/utils/type_converters.ts b/packages/connect/src/utils/type_converters.ts index c1808ce8a..beea557c2 100644 --- a/packages/connect/src/utils/type_converters.ts +++ b/packages/connect/src/utils/type_converters.ts @@ -2,29 +2,29 @@ import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; export const typeConverters = { - convertOrderbookStringFieldsToBigNumber(orderbook: any): any { - const bids = _.get(orderbook, 'bids', []); - const asks = _.get(orderbook, 'asks', []); - return { - bids: bids.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)), - asks: asks.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)), - }; - }, - convertOrderStringFieldsToBigNumber(order: any): any { - return this.convertStringsFieldsToBigNumbers(order, [ - 'makerTokenAmount', - 'takerTokenAmount', - 'makerFee', - 'takerFee', - 'expirationUnixTimestampSec', - 'salt', - ]); - }, - convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any { - const result = _.assign({}, obj); - _.each(fields, field => { - _.update(result, field, (value: string) => new BigNumber(value)); - }); - return result; - }, + convertOrderbookStringFieldsToBigNumber(orderbook: any): any { + const bids = _.get(orderbook, 'bids', []); + const asks = _.get(orderbook, 'asks', []); + return { + bids: bids.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)), + asks: asks.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)), + }; + }, + convertOrderStringFieldsToBigNumber(order: any): any { + return this.convertStringsFieldsToBigNumbers(order, [ + 'makerTokenAmount', + 'takerTokenAmount', + 'makerFee', + 'takerFee', + 'expirationUnixTimestampSec', + 'salt', + ]); + }, + convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any { + const result = _.assign({}, obj); + _.each(fields, field => { + _.update(result, field, (value: string) => new BigNumber(value)); + }); + return result; + }, }; diff --git a/packages/connect/src/ws_orderbook_channel.ts b/packages/connect/src/ws_orderbook_channel.ts index 822a022f4..bbb47c649 100644 --- a/packages/connect/src/ws_orderbook_channel.ts +++ b/packages/connect/src/ws_orderbook_channel.ts @@ -4,12 +4,12 @@ import * as _ from 'lodash'; import * as WebSocket from 'websocket'; import { - OrderbookChannel, - OrderbookChannelHandler, - OrderbookChannelMessageTypes, - OrderbookChannelSubscriptionOpts, - WebsocketClientEventType, - WebsocketConnectionEventType, + OrderbookChannel, + OrderbookChannelHandler, + OrderbookChannelMessageTypes, + OrderbookChannelSubscriptionOpts, + WebsocketClientEventType, + WebsocketConnectionEventType, } from './types'; import { orderbookChannelMessageParser } from './utils/orderbook_channel_message_parser'; @@ -18,117 +18,117 @@ import { orderbookChannelMessageParser } from './utils/orderbook_channel_message * that implements the standard relayer API v0 */ export class WebSocketOrderbookChannel implements OrderbookChannel { - private _apiEndpointUrl: string; - private _client: WebSocket.client; - private _connectionIfExists?: WebSocket.connection; - private _subscriptionCounter = 0; - /** - * Instantiates a new WebSocketOrderbookChannel instance - * @param url The relayer API base WS url you would like to interact with - * @return An instance of WebSocketOrderbookChannel - */ - constructor(url: string) { - assert.isUri('url', url); - this._apiEndpointUrl = url; - this._client = new WebSocket.client(); - } - /** - * Subscribe to orderbook snapshots and updates from the websocket - * @param subscriptionOpts An OrderbookChannelSubscriptionOpts instance describing which - * token pair to subscribe to - * @param handler An OrderbookChannelHandler instance that responds to various - * channel updates - */ - public subscribe(subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler): void { - assert.doesConformToSchema( - 'subscriptionOpts', - subscriptionOpts, - schemas.relayerApiOrderbookChannelSubscribePayload, - ); - assert.isFunction('handler.onSnapshot', _.get(handler, 'onSnapshot')); - assert.isFunction('handler.onUpdate', _.get(handler, 'onUpdate')); - assert.isFunction('handler.onError', _.get(handler, 'onError')); - assert.isFunction('handler.onClose', _.get(handler, 'onClose')); - this._subscriptionCounter += 1; - const subscribeMessage = { - type: 'subscribe', - channel: 'orderbook', - requestId: this._subscriptionCounter, - payload: subscriptionOpts, - }; - this._getConnection((error, connection) => { - if (!_.isUndefined(error)) { - handler.onError(this, subscriptionOpts, error); - } else if (!_.isUndefined(connection) && connection.connected) { - connection.on(WebsocketConnectionEventType.Error, wsError => { - handler.onError(this, subscriptionOpts, wsError); - }); - connection.on(WebsocketConnectionEventType.Close, () => { - handler.onClose(this, subscriptionOpts); - }); - connection.on(WebsocketConnectionEventType.Message, message => { - this._handleWebSocketMessage(subscribeMessage.requestId, subscriptionOpts, message, handler); - }); - connection.sendUTF(JSON.stringify(subscribeMessage)); - } - }); - } - /** - * Close the websocket and stop receiving updates - */ - public close() { - if (!_.isUndefined(this._connectionIfExists)) { - this._connectionIfExists.close(); - } - } - private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void) { - if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) { - callback(undefined, this._connectionIfExists); - } else { - this._client.on(WebsocketClientEventType.Connect, connection => { - this._connectionIfExists = connection; - callback(undefined, this._connectionIfExists); - }); - this._client.on(WebsocketClientEventType.ConnectFailed, error => { - callback(error, undefined); - }); - this._client.connect(this._apiEndpointUrl); - } - } - private _handleWebSocketMessage( - requestId: number, - subscriptionOpts: OrderbookChannelSubscriptionOpts, - message: WebSocket.IMessage, - handler: OrderbookChannelHandler, - ): void { - if (!_.isUndefined(message.utf8Data)) { - try { - const utf8Data = message.utf8Data; - const parserResult = orderbookChannelMessageParser.parse(utf8Data); - if (parserResult.requestId === requestId) { - switch (parserResult.type) { - case OrderbookChannelMessageTypes.Snapshot: { - handler.onSnapshot(this, subscriptionOpts, parserResult.payload); - break; - } - case OrderbookChannelMessageTypes.Update: { - handler.onUpdate(this, subscriptionOpts, parserResult.payload); - break; - } - default: { - handler.onError( - this, - subscriptionOpts, - new Error(`Message has missing a type parameter: ${utf8Data}`), - ); - } - } - } - } catch (error) { - handler.onError(this, subscriptionOpts, error); - } - } else { - handler.onError(this, subscriptionOpts, new Error(`Message does not contain utf8Data`)); - } - } + private _apiEndpointUrl: string; + private _client: WebSocket.client; + private _connectionIfExists?: WebSocket.connection; + private _subscriptionCounter = 0; + /** + * Instantiates a new WebSocketOrderbookChannel instance + * @param url The relayer API base WS url you would like to interact with + * @return An instance of WebSocketOrderbookChannel + */ + constructor(url: string) { + assert.isUri('url', url); + this._apiEndpointUrl = url; + this._client = new WebSocket.client(); + } + /** + * Subscribe to orderbook snapshots and updates from the websocket + * @param subscriptionOpts An OrderbookChannelSubscriptionOpts instance describing which + * token pair to subscribe to + * @param handler An OrderbookChannelHandler instance that responds to various + * channel updates + */ + public subscribe(subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler): void { + assert.doesConformToSchema( + 'subscriptionOpts', + subscriptionOpts, + schemas.relayerApiOrderbookChannelSubscribePayload, + ); + assert.isFunction('handler.onSnapshot', _.get(handler, 'onSnapshot')); + assert.isFunction('handler.onUpdate', _.get(handler, 'onUpdate')); + assert.isFunction('handler.onError', _.get(handler, 'onError')); + assert.isFunction('handler.onClose', _.get(handler, 'onClose')); + this._subscriptionCounter += 1; + const subscribeMessage = { + type: 'subscribe', + channel: 'orderbook', + requestId: this._subscriptionCounter, + payload: subscriptionOpts, + }; + this._getConnection((error, connection) => { + if (!_.isUndefined(error)) { + handler.onError(this, subscriptionOpts, error); + } else if (!_.isUndefined(connection) && connection.connected) { + connection.on(WebsocketConnectionEventType.Error, wsError => { + handler.onError(this, subscriptionOpts, wsError); + }); + connection.on(WebsocketConnectionEventType.Close, () => { + handler.onClose(this, subscriptionOpts); + }); + connection.on(WebsocketConnectionEventType.Message, message => { + this._handleWebSocketMessage(subscribeMessage.requestId, subscriptionOpts, message, handler); + }); + connection.sendUTF(JSON.stringify(subscribeMessage)); + } + }); + } + /** + * Close the websocket and stop receiving updates + */ + public close() { + if (!_.isUndefined(this._connectionIfExists)) { + this._connectionIfExists.close(); + } + } + private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void) { + if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) { + callback(undefined, this._connectionIfExists); + } else { + this._client.on(WebsocketClientEventType.Connect, connection => { + this._connectionIfExists = connection; + callback(undefined, this._connectionIfExists); + }); + this._client.on(WebsocketClientEventType.ConnectFailed, error => { + callback(error, undefined); + }); + this._client.connect(this._apiEndpointUrl); + } + } + private _handleWebSocketMessage( + requestId: number, + subscriptionOpts: OrderbookChannelSubscriptionOpts, + message: WebSocket.IMessage, + handler: OrderbookChannelHandler, + ): void { + if (!_.isUndefined(message.utf8Data)) { + try { + const utf8Data = message.utf8Data; + const parserResult = orderbookChannelMessageParser.parse(utf8Data); + if (parserResult.requestId === requestId) { + switch (parserResult.type) { + case OrderbookChannelMessageTypes.Snapshot: { + handler.onSnapshot(this, subscriptionOpts, parserResult.payload); + break; + } + case OrderbookChannelMessageTypes.Update: { + handler.onUpdate(this, subscriptionOpts, parserResult.payload); + break; + } + default: { + handler.onError( + this, + subscriptionOpts, + new Error(`Message has missing a type parameter: ${utf8Data}`), + ); + } + } + } + } catch (error) { + handler.onError(this, subscriptionOpts, error); + } + } else { + handler.onError(this, subscriptionOpts, new Error(`Message does not contain utf8Data`)); + } + } } |