expand spot public socket support
This commit is contained in:
55
examples/ws-public.ts
Normal file
55
examples/ws-public.ts
Normal 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
13
src/types/shared.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
export type KlineInterval = '1m'
|
||||||
|
| '3m'
|
||||||
|
| '5m'
|
||||||
|
| '15m'
|
||||||
|
| '30m'
|
||||||
|
| '1h'
|
||||||
|
| '2h'
|
||||||
|
| '4h'
|
||||||
|
| '6h'
|
||||||
|
| '12h'
|
||||||
|
| '1d'
|
||||||
|
| '1w'
|
||||||
|
| '1M';
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user