expand spot public socket support

This commit is contained in:
tiagosiebler
2021-08-15 11:11:33 +01:00
parent 572bd19abd
commit 10ac2ec384
3 changed files with 161 additions and 16 deletions

55
examples/ws-public.ts Normal file
View File

@@ -0,0 +1,55 @@
import { DefaultLogger } from '../src';
import { WebsocketClient, wsKeySpotPublic } from '../src/websocket-client';
// or
// import { DefaultLogger, WebsocketClient } from 'bybit-api';
(async () => {
const logger = {
...DefaultLogger,
// silly: () => {},
};
const wsClient = new WebsocketClient({
// key: key,
// secret: secret,
// market: 'inverse',
// market: 'linear',
market: 'spot',
}, logger);
wsClient.on('update', (data) => {
console.log('raw message received ', JSON.stringify(data, null, 2));
});
wsClient.on('open', (data) => {
console.log('connection opened open:', data.wsKey);
if (data.wsKey === wsKeySpotPublic) {
// Spot public.
// wsClient.subscribePublicSpotTrades('BTCUSDT');
// wsClient.subscribePublicSpotTradingPair('BTCUSDT');
// wsClient.subscribePublicSpotV1Kline('BTCUSDT', '1m');
// wsClient.subscribePublicSpotOrderbook('BTCUSDT', 'full');
}
});
wsClient.on('response', (data) => {
console.log('log response: ', JSON.stringify(data, null, 2));
});
wsClient.on('reconnect', ({ wsKey }) => {
console.log('ws automatically reconnecting.... ', wsKey);
});
wsClient.on('reconnected', (data) => {
console.log('ws has reconnected ', data?.wsKey );
});
// Inverse
// wsClient.subscribe('trade');
// Linear
// wsClient.subscribe('trade.BTCUSDT');
// For spot, request public connection first then send required topics on 'open'
// wsClient.connectPublic();
})();

13
src/types/shared.ts Normal file
View File

@@ -0,0 +1,13 @@
export type KlineInterval = '1m'
| '3m'
| '5m'
| '15m'
| '30m'
| '1h'
| '2h'
| '4h'
| '6h'
| '12h'
| '1d'
| '1w'
| '1M';

View File

@@ -4,6 +4,7 @@ import WebSocket from 'isomorphic-ws';
import { InverseClient } from './inverse-client'; import { InverseClient } from './inverse-client';
import { LinearClient } from './linear-client'; import { LinearClient } from './linear-client';
import { DefaultLogger } from './logger'; import { DefaultLogger } from './logger';
import { KlineInterval } from './types/shared';
import { signMessage } from './util/node-support'; import { signMessage } from './util/node-support';
import { serializeParams, isWsPong } from './util/requestUtils'; import { serializeParams, isWsPong } from './util/requestUtils';
@@ -541,8 +542,8 @@ export class WebsocketClient extends EventEmitter {
} }
private onWsMessage(event, wsKey: WsKey) { private onWsMessage(event, wsKey: WsKey) {
try {
const msg = JSON.parse(event && event.data || event); const msg = JSON.parse(event && event.data || event);
if ('success' in msg || msg?.pong) { if ('success' in msg || msg?.pong) {
this.onWsMessageResponse(msg, wsKey); this.onWsMessageResponse(msg, wsKey);
} else if (msg.topic) { } else if (msg.topic) {
@@ -550,6 +551,9 @@ export class WebsocketClient extends EventEmitter {
} else { } else {
this.logger.warning('Got unhandled ws message', { ...loggerCategory, message: msg, event, wsKey}); this.logger.warning('Got unhandled ws message', { ...loggerCategory, message: msg, event, wsKey});
} }
} catch (e) {
this.logger.error('Failed to parse ws event message', { ...loggerCategory, error: e, event, wsKey})
}
} }
private onWsError(error: any, wsKey: WsKey) { private onWsError(error: any, wsKey: WsKey) {
@@ -639,24 +643,97 @@ export class WebsocketClient extends EventEmitter {
return getSpotWsKeyForTopic(topic); return getSpotWsKeyForTopic(topic);
} }
private wrongMarketError(market: APIMarket) {
return new Error(`This WS client was instanced for the ${this.options.market} market. Make another WebsocketClient instance with "market: '${market}' to listen to spot topics`);
}
// TODO: persistance for subbed topics. Look at ftx-api implementation. // TODO: persistance for subbed topics. Look at ftx-api implementation.
public subscribePublicSpotTrades(symbol: string, binary?: boolean) { public subscribePublicSpotTrades(symbol: string, binary?: boolean) {
if (!this.isSpot()) { if (!this.isSpot()) {
throw new Error(`This WS client was instanced for the ${this.options.market} market. Make another WebsocketClient instance with "market: 'spot' to listen to spot topics`); throw this.wrongMarketError('spot');
} }
const subscribeMessage = { return this.tryWsSend(wsKeySpotPublic, JSON.stringify({
topic: 'trade', topic: 'trade',
event: 'sub', event: 'sub',
symbol, symbol,
params: {}, params: {
};
if (binary) {
subscribeMessage.params = {
binary: !!binary, binary: !!binary,
}; }
}));
} }
this.tryWsSend(wsKeySpotPublic, JSON.stringify(subscribeMessage)); public subscribePublicSpotTradingPair(symbol: string, binary?: boolean) {
if (!this.isSpot()) {
throw this.wrongMarketError('spot');
} }
return this.tryWsSend(wsKeySpotPublic, JSON.stringify({
symbol,
topic: 'realtimes',
event: 'sub',
params: {
binary: !!binary,
},
}));
}
public subscribePublicSpotV1Kline(symbol: string, candleSize: KlineInterval, binary?: boolean) {
if (!this.isSpot()) {
throw this.wrongMarketError('spot');
}
return this.tryWsSend(wsKeySpotPublic, JSON.stringify({
symbol,
topic: 'kline_' + candleSize,
event: 'sub',
params: {
binary: !!binary,
},
}));
}
//ws.send('{"symbol":"BTCUSDT","topic":"depth","event":"sub","params":{"binary":false}}');
//ws.send('{"symbol":"BTCUSDT","topic":"mergedDepth","event":"sub","params":{"binary":false,"dumpScale":1}}');
//ws.send('{"symbol":"BTCUSDT","topic":"diffDepth","event":"sub","params":{"binary":false}}');
public subscribePublicSpotOrderbook(symbol: string, depth: 'full' | 'merge' | 'delta', dumpScale?: number, binary?: boolean) {
if (!this.isSpot()) {
throw this.wrongMarketError('spot');
}
let topic: string;
switch (depth) {
case 'full': {
topic = 'depth';
break;
};
case 'merge': {
topic = 'mergedDepth';
if (!dumpScale) {
throw new Error(`Dumpscale must be provided for merged orderbooks`);
}
break;
}
case 'delta': {
topic = 'diffDepth';
break;
}
}
const msg: any = {
symbol,
topic,
event: 'sub',
params: {
binary: !!binary,
},
};
if (dumpScale) {
msg.params.dumpScale = dumpScale;
}
return this.tryWsSend(wsKeySpotPublic, JSON.stringify(msg));
}
}; };