Initial implementation of OrderbookChannelFactory
This commit is contained in:
parent
16ddd1edfc
commit
47debf0134
@ -1,5 +1,4 @@
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as WebSocket from 'websocket';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
OrderbookChannel,
|
OrderbookChannel,
|
||||||
@ -22,17 +21,16 @@ interface Subscription {
|
|||||||
* that implements the standard relayer API v0 in a browser environment
|
* that implements the standard relayer API v0 in a browser environment
|
||||||
*/
|
*/
|
||||||
export class BrowserWebSocketOrderbookChannel implements OrderbookChannel {
|
export class BrowserWebSocketOrderbookChannel implements OrderbookChannel {
|
||||||
private _apiEndpointUrl: string;
|
private _client: WebSocket;
|
||||||
private _clientIfExists?: WebSocket.w3cwebsocket;
|
|
||||||
private _subscriptions: Subscription[] = [];
|
private _subscriptions: Subscription[] = [];
|
||||||
/**
|
/**
|
||||||
* Instantiates a new WebSocketOrderbookChannel instance
|
* Instantiates a new WebSocketOrderbookChannel instance
|
||||||
* @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
|
||||||
* @return An instance of WebSocketOrderbookChannel
|
* @return An instance of WebSocketOrderbookChannel
|
||||||
*/
|
*/
|
||||||
constructor(url: string) {
|
constructor(client: WebSocket) {
|
||||||
assert.isUri('url', url);
|
// assert.isUri('url', url);
|
||||||
this._apiEndpointUrl = url;
|
this._client = client;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Subscribe to orderbook snapshots and updates from the websocket
|
* Subscribe to orderbook snapshots and updates from the websocket
|
||||||
@ -55,40 +53,31 @@ export class BrowserWebSocketOrderbookChannel implements OrderbookChannel {
|
|||||||
requestId: this._subscriptions.length - 1,
|
requestId: this._subscriptions.length - 1,
|
||||||
payload: subscriptionOpts,
|
payload: subscriptionOpts,
|
||||||
};
|
};
|
||||||
if (_.isUndefined(this._clientIfExists)) {
|
this._client.onerror = () => {
|
||||||
this._clientIfExists = new WebSocket.w3cwebsocket(this._apiEndpointUrl);
|
this._alertAllHandlersToError(new Error('hello'));
|
||||||
this._clientIfExists.onopen = () => {
|
|
||||||
this._sendMessage(subscribeMessage);
|
|
||||||
};
|
};
|
||||||
this._clientIfExists.onerror = error => {
|
this._client.onclose = () => {
|
||||||
this._alertAllHandlersToError(error);
|
|
||||||
};
|
|
||||||
this._clientIfExists.onclose = () => {
|
|
||||||
_.forEach(this._subscriptions, subscription => {
|
_.forEach(this._subscriptions, subscription => {
|
||||||
subscription.handler.onClose(this, subscription.subscriptionOpts);
|
subscription.handler.onClose(this, subscription.subscriptionOpts);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
this._clientIfExists.onmessage = message => {
|
this._client.onmessage = message => {
|
||||||
this._handleWebSocketMessage(message);
|
this._handleWebSocketMessage(message);
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
this._sendMessage(subscribeMessage);
|
this._sendMessage(subscribeMessage);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Close the websocket and stop receiving updates
|
* Close the websocket and stop receiving updates
|
||||||
*/
|
*/
|
||||||
public close(): void {
|
public close(): void {
|
||||||
if (!_.isUndefined(this._clientIfExists)) {
|
this._client.close();
|
||||||
this._clientIfExists.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Send a message to the client if it has been instantiated and it is open
|
* Send a message to the client if it has been instantiated and it is open
|
||||||
*/
|
*/
|
||||||
private _sendMessage(message: any): void {
|
private _sendMessage(message: any): void {
|
||||||
if (!_.isUndefined(this._clientIfExists) && this._clientIfExists.readyState === WebSocket.w3cwebsocket.OPEN) {
|
if (this._client.readyState === WebSocket.OPEN) {
|
||||||
this._clientIfExists.send(JSON.stringify(message));
|
this._client.send(JSON.stringify(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
export { HttpClient } from './http_client';
|
export { HttpClient } from './http_client';
|
||||||
export { BrowserWebSocketOrderbookChannel } from './browser_ws_orderbook_channel';
|
export { BrowserWebSocketOrderbookChannel } from './browser_ws_orderbook_channel';
|
||||||
export { NodeWebSocketOrderbookChannel } from './node_ws_orderbook_channel';
|
export { NodeWebSocketOrderbookChannel } from './node_ws_orderbook_channel';
|
||||||
|
export { orderbookChannelFactory } from './orderbook_channel_factory';
|
||||||
export {
|
export {
|
||||||
Client,
|
Client,
|
||||||
FeesRequest,
|
FeesRequest,
|
||||||
|
33
packages/connect/src/orderbook_channel_factory.ts
Normal file
33
packages/connect/src/orderbook_channel_factory.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// import * as WebSocket from 'websocket';
|
||||||
|
|
||||||
|
import { BrowserWebSocketOrderbookChannel } from './browser_ws_orderbook_channel';
|
||||||
|
import { NodeWebSocketOrderbookChannel } from './node_ws_orderbook_channel';
|
||||||
|
|
||||||
|
export const orderbookChannelFactory = {
|
||||||
|
async createBrowserOrderbookChannelAsync(url: string): Promise<BrowserWebSocketOrderbookChannel> {
|
||||||
|
return new Promise<BrowserWebSocketOrderbookChannel>((resolve, reject) => {
|
||||||
|
const client = new WebSocket(url);
|
||||||
|
console.log(client);
|
||||||
|
client.onopen = () => {
|
||||||
|
const orderbookChannel = new BrowserWebSocketOrderbookChannel(client);
|
||||||
|
console.log(orderbookChannel);
|
||||||
|
resolve(orderbookChannel);
|
||||||
|
};
|
||||||
|
client.onerror = err => {
|
||||||
|
reject(err);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// async createNodeOrderbookChannelAsync(url: string): Promise<NodeWebSocketOrderbookChannel> {
|
||||||
|
// return new Promise<BrowserWebSocketOrderbookChannel>((resolve, reject) => {
|
||||||
|
// const client = new WebSocket.w3cwebsocket(url);
|
||||||
|
// client.onopen = () => {
|
||||||
|
// const orderbookChannel = new BrowserWebSocketOrderbookChannel(client);
|
||||||
|
// resolve(orderbookChannel);
|
||||||
|
// };
|
||||||
|
// client.onerror = err => {
|
||||||
|
// reject(err);
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
};
|
@ -1,61 +1,63 @@
|
|||||||
import * as chai from 'chai';
|
// import * as chai from 'chai';
|
||||||
import * as dirtyChai from 'dirty-chai';
|
// import * as dirtyChai from 'dirty-chai';
|
||||||
import * as _ from 'lodash';
|
// import * as _ from 'lodash';
|
||||||
import 'mocha';
|
// import 'mocha';
|
||||||
|
// import * as WebSocket from 'websocket';
|
||||||
|
|
||||||
import { BrowserWebSocketOrderbookChannel } from '../src/browser_ws_orderbook_channel';
|
// import { BrowserWebSocketOrderbookChannel } from '../src/browser_ws_orderbook_channel';
|
||||||
|
|
||||||
chai.config.includeStack = true;
|
// chai.config.includeStack = true;
|
||||||
chai.use(dirtyChai);
|
// chai.use(dirtyChai);
|
||||||
const expect = chai.expect;
|
// const expect = chai.expect;
|
||||||
|
|
||||||
describe('BrowserWebSocketOrderbookChannel', () => {
|
// describe('BrowserWebSocketOrderbookChannel', () => {
|
||||||
const websocketUrl = 'ws://localhost:8080';
|
// const websocketUrl = 'ws://localhost:8080';
|
||||||
const orderbookChannel = new BrowserWebSocketOrderbookChannel(websocketUrl);
|
// const client = new WebSocket.w3cwebsocket(websocketUrl);
|
||||||
const subscriptionOpts = {
|
// const orderbookChannel = new BrowserWebSocketOrderbookChannel(client);
|
||||||
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
// const subscriptionOpts = {
|
||||||
quoteTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
|
// baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
||||||
snapshot: true,
|
// quoteTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
|
||||||
limit: 100,
|
// snapshot: true,
|
||||||
};
|
// limit: 100,
|
||||||
const emptyOrderbookChannelHandler = {
|
// };
|
||||||
onSnapshot: () => {
|
// const emptyOrderbookChannelHandler = {
|
||||||
_.noop();
|
// onSnapshot: () => {
|
||||||
},
|
// _.noop();
|
||||||
onUpdate: () => {
|
// },
|
||||||
_.noop();
|
// onUpdate: () => {
|
||||||
},
|
// _.noop();
|
||||||
onError: () => {
|
// },
|
||||||
_.noop();
|
// onError: () => {
|
||||||
},
|
// _.noop();
|
||||||
onClose: () => {
|
// },
|
||||||
_.noop();
|
// onClose: () => {
|
||||||
},
|
// _.noop();
|
||||||
};
|
// },
|
||||||
describe('#subscribe', () => {
|
// };
|
||||||
it('throws when subscriptionOpts does not conform to schema', () => {
|
// describe('#subscribe', () => {
|
||||||
const badSubscribeCall = orderbookChannel.subscribe.bind(
|
// it('throws when subscriptionOpts does not conform to schema', () => {
|
||||||
orderbookChannel,
|
// const badSubscribeCall = orderbookChannel.subscribe.bind(
|
||||||
{},
|
// orderbookChannel,
|
||||||
emptyOrderbookChannelHandler,
|
// {},
|
||||||
);
|
// emptyOrderbookChannelHandler,
|
||||||
expect(badSubscribeCall).throws(
|
// );
|
||||||
'Expected subscriptionOpts to conform to schema /RelayerApiOrderbookChannelSubscribePayload\nEncountered: {}\nValidation errors: instance requires property "baseTokenAddress", instance requires property "quoteTokenAddress"',
|
// expect(badSubscribeCall).throws(
|
||||||
);
|
// 'Expected subscriptionOpts to conform to schema /RelayerApiOrderbookChannelSubscribePayload\nEncountered: {}\nValidation errors: instance requires property "baseTokenAddress", instance requires property "quoteTokenAddress"',
|
||||||
});
|
// );
|
||||||
it('throws when handler has the incorrect members', () => {
|
// });
|
||||||
const badSubscribeCall = orderbookChannel.subscribe.bind(orderbookChannel, subscriptionOpts, {});
|
// it('throws when handler has the incorrect members', () => {
|
||||||
expect(badSubscribeCall).throws(
|
// const badSubscribeCall = orderbookChannel.subscribe.bind(orderbookChannel, subscriptionOpts, {});
|
||||||
'Expected handler.onSnapshot to be of type function, encountered: undefined',
|
// expect(badSubscribeCall).throws(
|
||||||
);
|
// 'Expected handler.onSnapshot to be of type function, encountered: undefined',
|
||||||
});
|
// );
|
||||||
it('does not throw when inputs are of correct types', () => {
|
// });
|
||||||
const goodSubscribeCall = orderbookChannel.subscribe.bind(
|
// it('does not throw when inputs are of correct types', () => {
|
||||||
orderbookChannel,
|
// const goodSubscribeCall = orderbookChannel.subscribe.bind(
|
||||||
subscriptionOpts,
|
// orderbookChannel,
|
||||||
emptyOrderbookChannelHandler,
|
// subscriptionOpts,
|
||||||
);
|
// emptyOrderbookChannelHandler,
|
||||||
expect(goodSubscribeCall).to.not.throw();
|
// );
|
||||||
});
|
// expect(goodSubscribeCall).to.not.throw();
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
// });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user