diff options
author | Brandon Millman <brandon.millman@gmail.com> | 2018-05-17 02:15:02 +0800 |
---|---|---|
committer | Brandon Millman <brandon.millman@gmail.com> | 2018-07-12 01:17:45 +0800 |
commit | 16ddd1edfccdd7768447bfff9afec1f4a1ce014e (patch) | |
tree | ac4209c77775a1b7c326204c0f7d49b9fcab7bff /packages/connect/src/ws_orderbook_channel.ts | |
parent | 8fcc7aefa7651311c5a6348101eb023d28799934 (diff) | |
download | dexon-0x-contracts-16ddd1edfccdd7768447bfff9afec1f4a1ce014e.tar dexon-0x-contracts-16ddd1edfccdd7768447bfff9afec1f4a1ce014e.tar.gz dexon-0x-contracts-16ddd1edfccdd7768447bfff9afec1f4a1ce014e.tar.bz2 dexon-0x-contracts-16ddd1edfccdd7768447bfff9afec1f4a1ce014e.tar.lz dexon-0x-contracts-16ddd1edfccdd7768447bfff9afec1f4a1ce014e.tar.xz dexon-0x-contracts-16ddd1edfccdd7768447bfff9afec1f4a1ce014e.tar.zst dexon-0x-contracts-16ddd1edfccdd7768447bfff9afec1f4a1ce014e.zip |
Implement web browser socket
Diffstat (limited to 'packages/connect/src/ws_orderbook_channel.ts')
-rw-r--r-- | packages/connect/src/ws_orderbook_channel.ts | 166 |
1 files changed, 0 insertions, 166 deletions
diff --git a/packages/connect/src/ws_orderbook_channel.ts b/packages/connect/src/ws_orderbook_channel.ts deleted file mode 100644 index bdcc8a75d..000000000 --- a/packages/connect/src/ws_orderbook_channel.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { assert } from '@0xproject/assert'; -import { schemas } from '@0xproject/json-schemas'; -import * as _ from 'lodash'; -import * as WebSocket from 'websocket'; - -import { schemas as clientSchemas } from './schemas/schemas'; -import { - OrderbookChannel, - OrderbookChannelHandler, - OrderbookChannelMessageTypes, - OrderbookChannelSubscriptionOpts, - WebsocketClientEventType, - WebsocketConnectionEventType, - WebSocketOrderbookChannelConfig, -} from './types'; -import { orderbookChannelMessageParser } from './utils/orderbook_channel_message_parser'; - -const DEFAULT_HEARTBEAT_INTERVAL_MS = 15000; -const MINIMUM_HEARTBEAT_INTERVAL_MS = 10; - -/** - * This class includes all the functionality related to interacting with a websocket endpoint - * that implements the standard relayer API v0 - */ -export class WebSocketOrderbookChannel implements OrderbookChannel { - private _apiEndpointUrl: string; - private _client: WebSocket.client; - private _connectionIfExists?: WebSocket.connection; - private _heartbeatTimerIfExists?: NodeJS.Timer; - private _subscriptionCounter = 0; - private _heartbeatIntervalMs: number; - /** - * Instantiates a new WebSocketOrderbookChannel instance - * @param url The relayer API base WS url you would like to interact with - * @param config The configuration object. Look up the type for the description. - * @return An instance of WebSocketOrderbookChannel - */ - constructor(url: string, config?: WebSocketOrderbookChannelConfig) { - assert.isUri('url', url); - if (!_.isUndefined(config)) { - assert.doesConformToSchema('config', config, clientSchemas.webSocketOrderbookChannelConfigSchema); - } - this._apiEndpointUrl = url; - this._heartbeatIntervalMs = - _.isUndefined(config) || _.isUndefined(config.heartbeatIntervalMs) - ? DEFAULT_HEARTBEAT_INTERVAL_MS - : config.heartbeatIntervalMs; - 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, (_code: number, _desc: string) => { - 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(): void { - if (!_.isUndefined(this._connectionIfExists)) { - this._connectionIfExists.close(); - } - if (!_.isUndefined(this._heartbeatTimerIfExists)) { - clearInterval(this._heartbeatTimerIfExists); - } - } - private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void): void { - if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) { - callback(undefined, this._connectionIfExists); - } else { - this._client.on(WebsocketClientEventType.Connect, connection => { - this._connectionIfExists = connection; - if (this._heartbeatIntervalMs >= MINIMUM_HEARTBEAT_INTERVAL_MS) { - this._heartbeatTimerIfExists = setInterval(() => { - connection.ping(''); - }, this._heartbeatIntervalMs); - } else { - callback( - new Error( - `Heartbeat interval is ${ - this._heartbeatIntervalMs - }ms which is less than the required minimum of ${MINIMUM_HEARTBEAT_INTERVAL_MS}ms`, - ), - undefined, - ); - } - 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`)); - } - } -} |