cleaning around websocket client
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { DefaultLogger } from '../src';
|
import { DefaultLogger } from '../src';
|
||||||
import { WebsocketClient, wsKeySpotPublic } from '../src/websocket-client';
|
import { WebsocketClient } from '../src/websocket-client';
|
||||||
|
|
||||||
// or
|
// or
|
||||||
// import { DefaultLogger, WebsocketClient } from 'bybit-api';
|
// import { DefaultLogger, WebsocketClient } from 'bybit-api';
|
||||||
@@ -33,6 +33,8 @@ import { WebsocketClient, wsKeySpotPublic } from '../src/websocket-client';
|
|||||||
logger
|
logger
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// wsClient.subscribePublicSpotOrderbook('test', 'full');
|
||||||
|
|
||||||
wsClient.on('update', (data) => {
|
wsClient.on('update', (data) => {
|
||||||
console.log('raw message received ', JSON.stringify(data, null, 2));
|
console.log('raw message received ', JSON.stringify(data, null, 2));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { DefaultLogger } from '../src';
|
import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../src';
|
||||||
import { WebsocketClient, wsKeySpotPublic } from '../src/websocket-client';
|
|
||||||
|
|
||||||
// or
|
// or
|
||||||
// import { DefaultLogger, WebsocketClient } from 'bybit-api';
|
// import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from 'bybit-api';
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const logger = {
|
const logger = {
|
||||||
@@ -10,13 +9,16 @@ import { WebsocketClient, wsKeySpotPublic } from '../src/websocket-client';
|
|||||||
// silly: () => {},
|
// silly: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const wsClient = new WebsocketClient({
|
const wsClient = new WebsocketClient(
|
||||||
// key: key,
|
{
|
||||||
// secret: secret,
|
// key: key,
|
||||||
// market: 'inverse',
|
// secret: secret,
|
||||||
// market: 'linear',
|
market: 'linear',
|
||||||
market: 'spot',
|
// market: 'inverse',
|
||||||
}, logger);
|
// market: 'spot',
|
||||||
|
},
|
||||||
|
logger
|
||||||
|
);
|
||||||
|
|
||||||
wsClient.on('update', (data) => {
|
wsClient.on('update', (data) => {
|
||||||
console.log('raw message received ', JSON.stringify(data, null, 2));
|
console.log('raw message received ', JSON.stringify(data, null, 2));
|
||||||
@@ -25,7 +27,7 @@ import { WebsocketClient, wsKeySpotPublic } from '../src/websocket-client';
|
|||||||
wsClient.on('open', (data) => {
|
wsClient.on('open', (data) => {
|
||||||
console.log('connection opened open:', data.wsKey);
|
console.log('connection opened open:', data.wsKey);
|
||||||
|
|
||||||
if (data.wsKey === wsKeySpotPublic) {
|
if (data.wsKey === WS_KEY_MAP.spotPublic) {
|
||||||
// Spot public.
|
// Spot public.
|
||||||
// wsClient.subscribePublicSpotTrades('BTCUSDT');
|
// wsClient.subscribePublicSpotTrades('BTCUSDT');
|
||||||
// wsClient.subscribePublicSpotTradingPair('BTCUSDT');
|
// wsClient.subscribePublicSpotTradingPair('BTCUSDT');
|
||||||
@@ -40,16 +42,20 @@ import { WebsocketClient, wsKeySpotPublic } from '../src/websocket-client';
|
|||||||
console.log('ws automatically reconnecting.... ', wsKey);
|
console.log('ws automatically reconnecting.... ', wsKey);
|
||||||
});
|
});
|
||||||
wsClient.on('reconnected', (data) => {
|
wsClient.on('reconnected', (data) => {
|
||||||
console.log('ws has reconnected ', data?.wsKey );
|
console.log('ws has reconnected ', data?.wsKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Inverse
|
// Inverse
|
||||||
// wsClient.subscribe('trade');
|
// wsClient.subscribe('trade');
|
||||||
|
|
||||||
// Linear
|
// Linear
|
||||||
// wsClient.subscribe('trade.BTCUSDT');
|
wsClient.subscribe('trade.BTCUSDT');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log('unsubscribing');
|
||||||
|
wsClient.unsubscribe('trade.BTCUSDT');
|
||||||
|
}, 5 * 1000);
|
||||||
|
|
||||||
// For spot, request public connection first then send required topics on 'open'
|
// For spot, request public connection first then send required topics on 'open'
|
||||||
// wsClient.connectPublic();
|
// wsClient.connectPublic();
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ export * from './usdc-perpetual-client';
|
|||||||
export * from './unified-margin-client';
|
export * from './unified-margin-client';
|
||||||
export * from './websocket-client';
|
export * from './websocket-client';
|
||||||
export * from './util/logger';
|
export * from './util/logger';
|
||||||
|
export * from './util';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
export * from './util/WsStore';
|
|
||||||
export * from './constants/enum';
|
export * from './constants/enum';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { RestClientOptions } from '../util';
|
import { RestClientOptions, WS_KEY_MAP } from '../util';
|
||||||
|
|
||||||
export type APIMarket = 'inverse' | 'linear' | 'spot'; //| 'v3';
|
export type APIMarket = 'inverse' | 'linear' | 'spot'; //| 'v3';
|
||||||
|
|
||||||
@@ -69,12 +69,7 @@ export type WsPrivateTopic =
|
|||||||
export type WsTopic = WsPublicTopics | WsPrivateTopic;
|
export type WsTopic = WsPublicTopics | WsPrivateTopic;
|
||||||
|
|
||||||
/** This is used to differentiate between each of the available websocket streams (as bybit has multiple websockets) */
|
/** This is used to differentiate between each of the available websocket streams (as bybit has multiple websockets) */
|
||||||
export type WsKey =
|
export type WsKey = typeof WS_KEY_MAP[keyof typeof WS_KEY_MAP];
|
||||||
| 'inverse'
|
|
||||||
| 'linearPrivate'
|
|
||||||
| 'linearPublic'
|
|
||||||
| 'spotPrivate'
|
|
||||||
| 'spotPublic';
|
|
||||||
|
|
||||||
export interface WSClientConfigurableOptions {
|
export interface WSClientConfigurableOptions {
|
||||||
key?: string;
|
key?: string;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import WebSocket from 'isomorphic-ws';
|
import WebSocket from 'isomorphic-ws';
|
||||||
|
import { WsKey } from '../types';
|
||||||
|
|
||||||
import { DefaultLogger } from './logger';
|
import { DefaultLogger } from './logger';
|
||||||
|
|
||||||
@@ -44,9 +45,9 @@ export default class WsStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Get WS stored state for key, optionally create if missing */
|
/** Get WS stored state for key, optionally create if missing */
|
||||||
get(key: string, createIfMissing?: true): WsStoredState;
|
get(key: WsKey, createIfMissing?: true): WsStoredState;
|
||||||
get(key: string, createIfMissing?: false): WsStoredState | undefined;
|
get(key: WsKey, createIfMissing?: false): WsStoredState | undefined;
|
||||||
get(key: string, createIfMissing?: boolean): WsStoredState | undefined {
|
get(key: WsKey, createIfMissing?: boolean): WsStoredState | undefined {
|
||||||
if (this.wsState[key]) {
|
if (this.wsState[key]) {
|
||||||
return this.wsState[key];
|
return this.wsState[key];
|
||||||
}
|
}
|
||||||
@@ -56,11 +57,11 @@ export default class WsStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getKeys(): string[] {
|
getKeys(): WsKey[] {
|
||||||
return Object.keys(this.wsState);
|
return Object.keys(this.wsState) as WsKey[];
|
||||||
}
|
}
|
||||||
|
|
||||||
create(key: string): WsStoredState | undefined {
|
create(key: WsKey): WsStoredState | undefined {
|
||||||
if (this.hasExistingActiveConnection(key)) {
|
if (this.hasExistingActiveConnection(key)) {
|
||||||
this.logger.warning(
|
this.logger.warning(
|
||||||
'WsStore setConnection() overwriting existing open connection: ',
|
'WsStore setConnection() overwriting existing open connection: ',
|
||||||
@@ -74,7 +75,7 @@ export default class WsStore {
|
|||||||
return this.get(key);
|
return this.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(key: string) {
|
delete(key: WsKey) {
|
||||||
if (this.hasExistingActiveConnection(key)) {
|
if (this.hasExistingActiveConnection(key)) {
|
||||||
const ws = this.getWs(key);
|
const ws = this.getWs(key);
|
||||||
this.logger.warning(
|
this.logger.warning(
|
||||||
@@ -88,15 +89,15 @@ export default class WsStore {
|
|||||||
|
|
||||||
/* connection websocket */
|
/* connection websocket */
|
||||||
|
|
||||||
hasExistingActiveConnection(key: string) {
|
hasExistingActiveConnection(key: WsKey) {
|
||||||
return this.get(key) && this.isWsOpen(key);
|
return this.get(key) && this.isWsOpen(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
getWs(key: string): WebSocket | undefined {
|
getWs(key: WsKey): WebSocket | undefined {
|
||||||
return this.get(key)?.ws;
|
return this.get(key)?.ws;
|
||||||
}
|
}
|
||||||
|
|
||||||
setWs(key: string, wsConnection: WebSocket): WebSocket {
|
setWs(key: WsKey, wsConnection: WebSocket): WebSocket {
|
||||||
if (this.isWsOpen(key)) {
|
if (this.isWsOpen(key)) {
|
||||||
this.logger.warning(
|
this.logger.warning(
|
||||||
'WsStore setConnection() overwriting existing open connection: ',
|
'WsStore setConnection() overwriting existing open connection: ',
|
||||||
@@ -109,7 +110,7 @@ export default class WsStore {
|
|||||||
|
|
||||||
/* connection state */
|
/* connection state */
|
||||||
|
|
||||||
isWsOpen(key: string): boolean {
|
isWsOpen(key: WsKey): boolean {
|
||||||
const existingConnection = this.getWs(key);
|
const existingConnection = this.getWs(key);
|
||||||
return (
|
return (
|
||||||
!!existingConnection &&
|
!!existingConnection &&
|
||||||
@@ -117,37 +118,37 @@ export default class WsStore {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getConnectionState(key: string): WsConnectionStateEnum {
|
getConnectionState(key: WsKey): WsConnectionStateEnum {
|
||||||
return this.get(key, true)!.connectionState!;
|
return this.get(key, true)!.connectionState!;
|
||||||
}
|
}
|
||||||
|
|
||||||
setConnectionState(key: string, state: WsConnectionStateEnum) {
|
setConnectionState(key: WsKey, state: WsConnectionStateEnum) {
|
||||||
this.get(key, true)!.connectionState = state;
|
this.get(key, true)!.connectionState = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
isConnectionState(key: string, state: WsConnectionStateEnum): boolean {
|
isConnectionState(key: WsKey, state: WsConnectionStateEnum): boolean {
|
||||||
return this.getConnectionState(key) === state;
|
return this.getConnectionState(key) === state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* subscribed topics */
|
/* subscribed topics */
|
||||||
|
|
||||||
getTopics(key: string): WsTopicList {
|
getTopics(key: WsKey): WsTopicList {
|
||||||
return this.get(key, true).subscribedTopics;
|
return this.get(key, true).subscribedTopics;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTopicsByKey(): Record<string, WsTopicList> {
|
getTopicsByKey(): Record<string, WsTopicList> {
|
||||||
const result = {};
|
const result = {};
|
||||||
for (const refKey in this.wsState) {
|
for (const refKey in this.wsState) {
|
||||||
result[refKey] = this.getTopics(refKey);
|
result[refKey] = this.getTopics(refKey as WsKey);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
addTopic(key: string, topic: WsTopic) {
|
addTopic(key: WsKey, topic: WsTopic) {
|
||||||
return this.getTopics(key).add(topic);
|
return this.getTopics(key).add(topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteTopic(key: string, topic: WsTopic) {
|
deleteTopic(key: WsKey, topic: WsTopic) {
|
||||||
return this.getTopics(key).delete(topic);
|
return this.getTopics(key).delete(topic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,84 @@
|
|||||||
import { WsKey } from '../types';
|
import { WsKey } from '../types';
|
||||||
|
|
||||||
export const wsKeyInverse = 'inverse';
|
interface NetworkMapV3 {
|
||||||
export const wsKeyLinearPrivate = 'linearPrivate';
|
livenet: string;
|
||||||
export const wsKeyLinearPublic = 'linearPublic';
|
livenet2?: string;
|
||||||
export const wsKeySpotPrivate = 'spotPrivate';
|
testnet: string;
|
||||||
export const wsKeySpotPublic = 'spotPublic';
|
testnet2?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export const WS_KEY_MAP = {
|
type PublicPrivateNetwork = 'public' | 'private';
|
||||||
inverse: wsKeyInverse,
|
|
||||||
linearPrivate: wsKeyLinearPrivate,
|
export const WS_BASE_URL_MAP: Record<
|
||||||
linearPublic: wsKeyLinearPublic,
|
string,
|
||||||
spotPrivate: wsKeySpotPrivate,
|
Record<PublicPrivateNetwork, NetworkMapV3>
|
||||||
spotPublic: wsKeySpotPublic,
|
> = {
|
||||||
|
inverse: {
|
||||||
|
private: {
|
||||||
|
livenet: 'wss://stream.bybit.com/realtime',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/realtime',
|
||||||
|
},
|
||||||
|
public: {
|
||||||
|
livenet: 'wss://stream.bybit.com/realtime',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/realtime',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
linear: {
|
||||||
|
private: {
|
||||||
|
livenet: 'wss://stream.bybit.com/realtime_private',
|
||||||
|
livenet2: 'wss://stream.bytick.com/realtime_private',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/realtime_private',
|
||||||
|
},
|
||||||
|
public: {
|
||||||
|
livenet: 'wss://stream.bybit.com/realtime_public',
|
||||||
|
livenet2: 'wss://stream.bytick.com/realtime_public',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/realtime_public',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
spot: {
|
||||||
|
private: {
|
||||||
|
livenet: 'wss://stream.bybit.com/spot/ws',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/spot/ws',
|
||||||
|
},
|
||||||
|
public: {
|
||||||
|
livenet: 'wss://stream.bybit.com/spot/quote/ws/v1',
|
||||||
|
livenet2: 'wss://stream.bybit.com/spot/quote/ws/v2',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/spot/quote/ws/v1',
|
||||||
|
testnet2: 'wss://stream-testnet.bybit.com/spot/quote/ws/v2',
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PUBLIC_WS_KEYS = [WS_KEY_MAP.linearPublic, WS_KEY_MAP.spotPublic];
|
export const WS_KEY_MAP = {
|
||||||
|
inverse: 'inverse',
|
||||||
|
linearPrivate: 'linearPrivate',
|
||||||
|
linearPublic: 'linearPublic',
|
||||||
|
spotPrivate: 'spotPrivate',
|
||||||
|
spotPublic: 'spotPublic',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const PUBLIC_WS_KEYS = [
|
||||||
|
WS_KEY_MAP.linearPublic,
|
||||||
|
WS_KEY_MAP.spotPublic,
|
||||||
|
] as string[];
|
||||||
|
|
||||||
export function getLinearWsKeyForTopic(topic: string): WsKey {
|
export function getLinearWsKeyForTopic(topic: string): WsKey {
|
||||||
const privateLinearTopics = [
|
const privateTopics = [
|
||||||
'position',
|
'position',
|
||||||
'execution',
|
'execution',
|
||||||
'order',
|
'order',
|
||||||
'stop_order',
|
'stop_order',
|
||||||
'wallet',
|
'wallet',
|
||||||
];
|
];
|
||||||
if (privateLinearTopics.includes(topic)) {
|
if (privateTopics.includes(topic)) {
|
||||||
return wsKeyLinearPrivate;
|
return WS_KEY_MAP.linearPrivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wsKeyLinearPublic;
|
return WS_KEY_MAP.linearPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSpotWsKeyForTopic(topic: string): WsKey {
|
export function getSpotWsKeyForTopic(topic: string): WsKey {
|
||||||
const privateLinearTopics = [
|
const privateTopics = [
|
||||||
'position',
|
'position',
|
||||||
'execution',
|
'execution',
|
||||||
'order',
|
'order',
|
||||||
@@ -42,9 +88,8 @@ export function getSpotWsKeyForTopic(topic: string): WsKey {
|
|||||||
'ticketInfo',
|
'ticketInfo',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (privateLinearTopics.includes(topic)) {
|
if (privateTopics.includes(topic)) {
|
||||||
return wsKeySpotPrivate;
|
return WS_KEY_MAP.spotPrivate;
|
||||||
}
|
}
|
||||||
|
return WS_KEY_MAP.spotPublic;
|
||||||
return wsKeySpotPublic;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import { LinearClient } from './linear-client';
|
|||||||
import { SpotClientV3 } from './spot-client-v3';
|
import { SpotClientV3 } from './spot-client-v3';
|
||||||
import { SpotClient } from './spot-client';
|
import { SpotClient } from './spot-client';
|
||||||
|
|
||||||
import { DefaultLogger } from './util/logger';
|
import { signMessage } from './util/node-support';
|
||||||
|
import WsStore from './util/WsStore';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
APIMarket,
|
APIMarket,
|
||||||
KlineInterval,
|
KlineInterval,
|
||||||
@@ -17,82 +19,22 @@ import {
|
|||||||
WsTopic,
|
WsTopic,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
import { signMessage } from './util/node-support';
|
|
||||||
|
|
||||||
import WsStore from './util/WsStore';
|
|
||||||
import {
|
import {
|
||||||
serializeParams,
|
serializeParams,
|
||||||
isWsPong,
|
isWsPong,
|
||||||
getLinearWsKeyForTopic,
|
getLinearWsKeyForTopic,
|
||||||
getSpotWsKeyForTopic,
|
getSpotWsKeyForTopic,
|
||||||
wsKeyInverse,
|
|
||||||
wsKeyLinearPrivate,
|
|
||||||
wsKeyLinearPublic,
|
|
||||||
wsKeySpotPrivate,
|
|
||||||
wsKeySpotPublic,
|
|
||||||
WsConnectionStateEnum,
|
WsConnectionStateEnum,
|
||||||
PUBLIC_WS_KEYS,
|
PUBLIC_WS_KEYS,
|
||||||
|
WS_KEY_MAP,
|
||||||
|
DefaultLogger,
|
||||||
|
WS_BASE_URL_MAP,
|
||||||
} from './util';
|
} from './util';
|
||||||
|
|
||||||
const inverseEndpoints = {
|
|
||||||
livenet: 'wss://stream.bybit.com/realtime',
|
|
||||||
testnet: 'wss://stream-testnet.bybit.com/realtime',
|
|
||||||
};
|
|
||||||
|
|
||||||
interface NetworkMapV3 {
|
|
||||||
livenet: string;
|
|
||||||
livenet2?: string;
|
|
||||||
testnet: string;
|
|
||||||
testnet2?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type NetworkType = 'public' | 'private';
|
|
||||||
|
|
||||||
function neverGuard(x: never, msg: string): Error {
|
function neverGuard(x: never, msg: string): Error {
|
||||||
return new Error(`Unhandled value exception "x", ${msg}`);
|
return new Error(`Unhandled value exception "x", ${msg}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const WS_BASE_URL_MAP: Record<string, Record<NetworkType, NetworkMapV3>> = {
|
|
||||||
linear: {
|
|
||||||
private: {
|
|
||||||
livenet: 'wss://stream.bybit.com/realtime_private',
|
|
||||||
livenet2: 'wss://stream.bytick.com/realtime_private',
|
|
||||||
testnet: 'wss://stream-testnet.bybit.com/realtime_private',
|
|
||||||
},
|
|
||||||
public: {
|
|
||||||
livenet: 'wss://stream.bybit.com/realtime_public',
|
|
||||||
livenet2: 'wss://stream.bytick.com/realtime_public',
|
|
||||||
testnet: 'wss://stream-testnet.bybit.com/realtime_public',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const linearEndpoints: Record<NetworkType, NetworkMapV3> = {
|
|
||||||
private: {
|
|
||||||
livenet: 'wss://stream.bybit.com/realtime_private',
|
|
||||||
livenet2: 'wss://stream.bytick.com/realtime_private',
|
|
||||||
testnet: 'wss://stream-testnet.bybit.com/realtime_private',
|
|
||||||
},
|
|
||||||
public: {
|
|
||||||
livenet: 'wss://stream.bybit.com/realtime_public',
|
|
||||||
livenet2: 'wss://stream.bytick.com/realtime_public',
|
|
||||||
testnet: 'wss://stream-testnet.bybit.com/realtime_public',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const spotEndpoints: Record<NetworkType, NetworkMapV3> = {
|
|
||||||
private: {
|
|
||||||
livenet: 'wss://stream.bybit.com/spot/ws',
|
|
||||||
testnet: 'wss://stream-testnet.bybit.com/spot/ws',
|
|
||||||
},
|
|
||||||
public: {
|
|
||||||
livenet: 'wss://stream.bybit.com/spot/quote/ws/v1',
|
|
||||||
livenet2: 'wss://stream.bybit.com/spot/quote/ws/v2',
|
|
||||||
testnet: 'wss://stream-testnet.bybit.com/spot/quote/ws/v1',
|
|
||||||
testnet2: 'wss://stream-testnet.bybit.com/spot/quote/ws/v2',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const loggerCategory = { category: 'bybit-ws' };
|
const loggerCategory = { category: 'bybit-ws' };
|
||||||
|
|
||||||
export declare interface WebsocketClient {
|
export declare interface WebsocketClient {
|
||||||
@@ -280,16 +222,19 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
public connectAll(): Promise<WebSocket | undefined>[] {
|
public connectAll(): Promise<WebSocket | undefined>[] {
|
||||||
switch (this.options.market) {
|
switch (this.options.market) {
|
||||||
case 'inverse': {
|
case 'inverse': {
|
||||||
return [this.connect(wsKeyInverse)];
|
return [this.connect(WS_KEY_MAP.inverse)];
|
||||||
}
|
}
|
||||||
case 'linear': {
|
case 'linear': {
|
||||||
return [
|
return [
|
||||||
this.connect(wsKeyLinearPublic),
|
this.connect(WS_KEY_MAP.linearPublic),
|
||||||
this.connect(wsKeyLinearPrivate),
|
this.connect(WS_KEY_MAP.linearPrivate),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
case 'spot': {
|
case 'spot': {
|
||||||
return [this.connect(wsKeySpotPublic), this.connect(wsKeySpotPrivate)];
|
return [
|
||||||
|
this.connect(WS_KEY_MAP.spotPublic),
|
||||||
|
this.connect(WS_KEY_MAP.spotPrivate),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(this.options.market, `connectAll(): Unhandled market`);
|
throw neverGuard(this.options.market, `connectAll(): Unhandled market`);
|
||||||
@@ -300,13 +245,13 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
public connectPublic(): Promise<WebSocket | undefined> {
|
public connectPublic(): Promise<WebSocket | undefined> {
|
||||||
switch (this.options.market) {
|
switch (this.options.market) {
|
||||||
case 'inverse': {
|
case 'inverse': {
|
||||||
return this.connect(wsKeyInverse);
|
return this.connect(WS_KEY_MAP.inverse);
|
||||||
}
|
}
|
||||||
case 'linear': {
|
case 'linear': {
|
||||||
return this.connect(wsKeyLinearPublic);
|
return this.connect(WS_KEY_MAP.linearPublic);
|
||||||
}
|
}
|
||||||
case 'spot': {
|
case 'spot': {
|
||||||
return this.connect(wsKeySpotPublic);
|
return this.connect(WS_KEY_MAP.spotPublic);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(
|
throw neverGuard(
|
||||||
@@ -320,13 +265,13 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
public connectPrivate(): Promise<WebSocket | undefined> | undefined {
|
public connectPrivate(): Promise<WebSocket | undefined> | undefined {
|
||||||
switch (this.options.market) {
|
switch (this.options.market) {
|
||||||
case 'inverse': {
|
case 'inverse': {
|
||||||
return this.connect(wsKeyInverse);
|
return this.connect(WS_KEY_MAP.inverse);
|
||||||
}
|
}
|
||||||
case 'linear': {
|
case 'linear': {
|
||||||
return this.connect(wsKeyLinearPrivate);
|
return this.connect(WS_KEY_MAP.linearPrivate);
|
||||||
}
|
}
|
||||||
case 'spot': {
|
case 'spot': {
|
||||||
return this.connect(wsKeySpotPrivate);
|
return this.connect(WS_KEY_MAP.spotPrivate);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(
|
throw neverGuard(
|
||||||
@@ -672,7 +617,7 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getWs(wsKey: string) {
|
private getWs(wsKey: WsKey) {
|
||||||
return this.wsStore.getWs(wsKey);
|
return this.wsStore.getWs(wsKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,20 +633,21 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
const networkKey = this.isLivenet() ? 'livenet' : 'testnet';
|
const networkKey = this.isLivenet() ? 'livenet' : 'testnet';
|
||||||
|
|
||||||
switch (wsKey) {
|
switch (wsKey) {
|
||||||
case wsKeyLinearPublic: {
|
case WS_KEY_MAP.linearPublic: {
|
||||||
return linearEndpoints.public[networkKey];
|
return WS_BASE_URL_MAP.linear.public[networkKey];
|
||||||
}
|
}
|
||||||
case wsKeyLinearPrivate: {
|
case WS_KEY_MAP.linearPrivate: {
|
||||||
return linearEndpoints.private[networkKey];
|
return WS_BASE_URL_MAP.linear.private[networkKey];
|
||||||
}
|
}
|
||||||
case wsKeySpotPublic: {
|
case WS_KEY_MAP.spotPublic: {
|
||||||
return spotEndpoints.public[networkKey];
|
return WS_BASE_URL_MAP.spot.public[networkKey];
|
||||||
}
|
}
|
||||||
case wsKeySpotPrivate: {
|
case WS_KEY_MAP.spotPrivate: {
|
||||||
return spotEndpoints.private[networkKey];
|
return WS_BASE_URL_MAP.linear.private[networkKey];
|
||||||
}
|
}
|
||||||
case wsKeyInverse: {
|
case WS_KEY_MAP.inverse: {
|
||||||
return inverseEndpoints[networkKey];
|
// private and public are on the same WS connection
|
||||||
|
return WS_BASE_URL_MAP.inverse.public[networkKey];
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
this.logger.error('getWsUrl(): Unhandled wsKey: ', {
|
this.logger.error('getWsUrl(): Unhandled wsKey: ', {
|
||||||
@@ -713,14 +659,24 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getWsKeyForTopic(topic: string) {
|
private getWsKeyForTopic(topic: string): WsKey {
|
||||||
if (this.isInverse()) {
|
switch (this.options.market) {
|
||||||
return wsKeyInverse;
|
case 'inverse': {
|
||||||
|
return WS_KEY_MAP.inverse;
|
||||||
|
}
|
||||||
|
case 'linear': {
|
||||||
|
return getLinearWsKeyForTopic(topic);
|
||||||
|
}
|
||||||
|
case 'spot': {
|
||||||
|
return getSpotWsKeyForTopic(topic);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw neverGuard(
|
||||||
|
this.options.market,
|
||||||
|
`connectPublic(): Unhandled market`
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.isLinear()) {
|
|
||||||
return getLinearWsKeyForTopic(topic);
|
|
||||||
}
|
|
||||||
return getSpotWsKeyForTopic(topic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private wrongMarketError(market: APIMarket) {
|
private wrongMarketError(market: APIMarket) {
|
||||||
@@ -736,7 +692,7 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.tryWsSend(
|
return this.tryWsSend(
|
||||||
wsKeySpotPublic,
|
WS_KEY_MAP.spotPublic,
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
topic: 'trade',
|
topic: 'trade',
|
||||||
event: 'sub',
|
event: 'sub',
|
||||||
@@ -754,7 +710,7 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.tryWsSend(
|
return this.tryWsSend(
|
||||||
wsKeySpotPublic,
|
WS_KEY_MAP.spotPublic,
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
symbol,
|
symbol,
|
||||||
topic: 'realtimes',
|
topic: 'realtimes',
|
||||||
@@ -776,7 +732,7 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.tryWsSend(
|
return this.tryWsSend(
|
||||||
wsKeySpotPublic,
|
WS_KEY_MAP.spotPublic,
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
symbol,
|
symbol,
|
||||||
topic: 'kline_' + candleSize,
|
topic: 'kline_' + candleSize,
|
||||||
@@ -791,6 +747,7 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
//ws.send('{"symbol":"BTCUSDT","topic":"depth","event":"sub","params":{"binary":false}}');
|
//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":"mergedDepth","event":"sub","params":{"binary":false,"dumpScale":1}}');
|
||||||
//ws.send('{"symbol":"BTCUSDT","topic":"diffDepth","event":"sub","params":{"binary":false}}');
|
//ws.send('{"symbol":"BTCUSDT","topic":"diffDepth","event":"sub","params":{"binary":false}}');
|
||||||
|
|
||||||
public subscribePublicSpotOrderbook(
|
public subscribePublicSpotOrderbook(
|
||||||
symbol: string,
|
symbol: string,
|
||||||
depth: 'full' | 'merge' | 'delta',
|
depth: 'full' | 'merge' | 'delta',
|
||||||
@@ -831,6 +788,6 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
if (dumpScale) {
|
if (dumpScale) {
|
||||||
msg.params.dumpScale = dumpScale;
|
msg.params.dumpScale = dumpScale;
|
||||||
}
|
}
|
||||||
return this.tryWsSend(wsKeySpotPublic, JSON.stringify(msg));
|
return this.tryWsSend(WS_KEY_MAP.spotPublic, JSON.stringify(msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user