diff options
Diffstat (limited to 'packages/connect/src')
-rw-r--r-- | packages/connect/src/index.ts | 4 | ||||
-rw-r--r-- | packages/connect/src/types.ts | 12 | ||||
-rw-r--r-- | packages/connect/src/utils/orderbook_channel_message_parsers.ts | 12 | ||||
-rw-r--r-- | packages/connect/src/ws_orderbook_channel.ts | 43 |
4 files changed, 42 insertions, 29 deletions
diff --git a/packages/connect/src/index.ts b/packages/connect/src/index.ts index aabf233fe..ec369a606 100644 --- a/packages/connect/src/index.ts +++ b/packages/connect/src/index.ts @@ -1,10 +1,14 @@ export {HttpClient} from './http_client'; +export {WebSocketOrderbookChannel} from './ws_orderbook_channel'; export { Client, ECSignature, FeesRequest, FeesResponse, Order, + OrderbookChannel, + OrderbookChannelHandler, + OrderbookChannelSubscriptionOpts, OrderbookRequest, OrderbookResponse, OrdersRequest, diff --git a/packages/connect/src/types.ts b/packages/connect/src/types.ts index 71dd8dac2..0657a1d63 100644 --- a/packages/connect/src/types.ts +++ b/packages/connect/src/types.ts @@ -57,9 +57,12 @@ export interface OrderbookChannelSubscriptionOpts { } export interface OrderbookChannelHandler { - onSnapshot: (channel: OrderbookChannel, snapshot: OrderbookResponse) => void; - onUpdate: (channel: OrderbookChannel, order: SignedOrder) => void; - onError: (channel: OrderbookChannel, err: Error) => 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) => void; } @@ -76,16 +79,19 @@ export enum OrderbookChannelMessageTypes { export interface SnapshotOrderbookChannelMessage { type: OrderbookChannelMessageTypes.Snapshot; + requestId: number; payload: OrderbookResponse; } export interface UpdateOrderbookChannelMessage { type: OrderbookChannelMessageTypes.Update; + requestId: number; payload: SignedOrder; } export interface UnknownOrderbookChannelMessage { type: OrderbookChannelMessageTypes.Unknown; + requestId: number; payload: undefined; } diff --git a/packages/connect/src/utils/orderbook_channel_message_parsers.ts b/packages/connect/src/utils/orderbook_channel_message_parsers.ts index 9cd160428..486a416ef 100644 --- a/packages/connect/src/utils/orderbook_channel_message_parsers.ts +++ b/packages/connect/src/utils/orderbook_channel_message_parsers.ts @@ -15,28 +15,24 @@ export const orderbookChannelMessageParsers = { 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 orderbook = messageObj.payload; typeConverters.convertOrderbookStringFieldsToBigNumber(orderbook); - return { - type, - payload: orderbook, - }; + return messageObj; } case (OrderbookChannelMessageTypes.Update): { assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelUpdateSchema); const order = messageObj.payload; typeConverters.convertOrderStringFieldsToBigNumber(order); - return { - type, - payload: order, - }; + return messageObj; } default: { return { type: OrderbookChannelMessageTypes.Unknown, + requestId: 0, payload: undefined, }; } diff --git a/packages/connect/src/ws_orderbook_channel.ts b/packages/connect/src/ws_orderbook_channel.ts index d9cc1b4c5..346be20c0 100644 --- a/packages/connect/src/ws_orderbook_channel.ts +++ b/packages/connect/src/ws_orderbook_channel.ts @@ -22,9 +22,10 @@ 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 base url for making API calls + * @param url The relayer API base WS url you would like to interact with * @return An instance of WebSocketOrderbookChannel */ constructor(url: string) { @@ -46,23 +47,25 @@ export class WebSocketOrderbookChannel implements OrderbookChannel { 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, error); + handler.onError(this, subscriptionOpts, error); } else if (!_.isUndefined(connection) && connection.connected) { connection.on(WebsocketConnectionEventType.Error, wsError => { - handler.onError(this, wsError); + handler.onError(this, subscriptionOpts, wsError); }); connection.on(WebsocketConnectionEventType.Close, () => { handler.onClose(this); }); connection.on(WebsocketConnectionEventType.Message, message => { - this._handleWebSocketMessage(message, handler); + this._handleWebSocketMessage(subscribeMessage.requestId, subscriptionOpts, message, handler); }); connection.sendUTF(JSON.stringify(subscribeMessage)); } @@ -90,30 +93,34 @@ export class WebSocketOrderbookChannel implements OrderbookChannel { this.client.connect(this.apiEndpointUrl); } } - private _handleWebSocketMessage(message: WebSocket.IMessage, handler: OrderbookChannelHandler): void { + private _handleWebSocketMessage(requestId: number, subscriptionOpts: OrderbookChannelSubscriptionOpts, + message: WebSocket.IMessage, handler: OrderbookChannelHandler): void { if (!_.isUndefined(message.utf8Data)) { try { const utf8Data = message.utf8Data; const parserResult = orderbookChannelMessageParsers.parser(utf8Data); const type = parserResult.type; - switch (parserResult.type) { - case (OrderbookChannelMessageTypes.Snapshot): { - handler.onSnapshot(this, parserResult.payload); - break; - } - case (OrderbookChannelMessageTypes.Update): { - handler.onUpdate(this, parserResult.payload); - break; - } - default: { - handler.onError(this, new Error(`Message has missing a type parameter: ${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, error); + handler.onError(this, subscriptionOpts, error); } } else { - handler.onError(this, new Error(`Message does not contain utf8Data`)); + handler.onError(this, subscriptionOpts, new Error(`Message does not contain utf8Data`)); } } } |