Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bybit-api

Package Overview
Dependencies
Maintainers
1
Versions
126
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bybit-api - npm Package Compare versions

Comparing version 2.4.0-beta.1 to 2.4.0-beta.2

2

lib/index.d.ts

@@ -13,4 +13,4 @@ export * from './account-asset-client';

export * from './util/logger';
export * from './util';
export * from './types';
export * from './util/WsStore';
export * from './constants/enum';

@@ -25,5 +25,5 @@ "use strict";

__exportStar(require("./util/logger"), exports);
__exportStar(require("./util"), exports);
__exportStar(require("./types"), exports);
__exportStar(require("./util/WsStore"), exports);
__exportStar(require("./constants/enum"), exports);
//# sourceMappingURL=index.js.map

@@ -5,3 +5,5 @@ import { InverseClient } from '../inverse-client';

import { SpotClientV3 } from '../spot-client-v3';
export declare type RESTClient = InverseClient | LinearClient | SpotClient | SpotClientV3;
import { USDCOptionClient } from '../usdc-option-client';
import { USDCPerpetualClient } from '../usdc-perpetual-client';
export declare type RESTClient = InverseClient | LinearClient | SpotClient | SpotClientV3 | USDCOptionClient | USDCPerpetualClient;
export declare type numberInString = string;

@@ -8,0 +10,0 @@ export declare type OrderSide = 'Buy' | 'Sell';

@@ -1,3 +0,4 @@

import { RestClientOptions } from '../util';
export declare type APIMarket = 'inverse' | 'linear' | 'spot' | 'v3';
import { RestClientOptions, WS_KEY_MAP } from '../util';
/** For spot markets, spotV3 is recommended */
export declare type APIMarket = 'inverse' | 'linear' | 'spot' | 'spotv3' | 'usdcOption' | 'usdcPerp';
export declare type WsPublicInverseTopic = 'orderBookL2_25' | 'orderBookL2_200' | 'trade' | 'insurance' | 'instrument_info' | 'klineV2';

@@ -14,7 +15,7 @@ export declare type WsPublicUSDTPerpTopic = 'orderBookL2_25' | 'orderBookL2_200' | 'trade' | 'insurance' | 'instrument_info' | 'kline';

/** This is used to differentiate between each of the available websocket streams (as bybit has multiple websockets) */
export declare type WsKey = 'inverse' | 'linearPrivate' | 'linearPublic' | 'spotPrivate' | 'spotPublic';
export declare type WsKey = typeof WS_KEY_MAP[keyof typeof WS_KEY_MAP];
export interface WSClientConfigurableOptions {
key?: string;
secret?: string;
livenet?: boolean;
testnet?: boolean;
/**

@@ -36,3 +37,3 @@ * The API group this client should connect to.

export interface WebsocketClientOptions extends WSClientConfigurableOptions {
livenet: boolean;
testnet?: boolean;
market: APIMarket;

@@ -39,0 +40,0 @@ pongTimeout: number;

@@ -0,1 +1,2 @@

/** This is async because the browser version uses a promise (browser-support) */
export declare function signMessage(message: string, secret: string): Promise<string>;

@@ -14,2 +14,3 @@ "use strict";

const crypto_1 = require("crypto");
/** This is async because the browser version uses a promise (browser-support) */
function signMessage(message, secret) {

@@ -16,0 +17,0 @@ return __awaiter(this, void 0, void 0, function* () {

@@ -22,3 +22,3 @@ export interface RestClientOptions {

export declare function getRestBaseUrl(useLivenet: boolean, restInverseOptions: RestClientOptions): string;
export declare function isWsPong(response: any): any;
export declare function isWsPong(msg: any): boolean;
export declare const agentSource = "bybitapinode";

@@ -25,0 +25,0 @@ /**

@@ -31,10 +31,16 @@ "use strict";

exports.getRestBaseUrl = getRestBaseUrl;
function isWsPong(response) {
if (response.pong || response.ping) {
function isWsPong(msg) {
if (!msg) {
return false;
}
if (msg.pong || msg.ping) {
return true;
}
return (response.request &&
response.request.op === 'ping' &&
response.ret_msg === 'pong' &&
response.success === true);
if (msg['op'] === 'pong') {
return true;
}
return (msg.request &&
msg.request.op === 'ping' &&
msg.ret_msg === 'pong' &&
msg.success === true);
}

@@ -41,0 +47,0 @@ exports.isWsPong = isWsPong;

@@ -1,8 +0,34 @@

import { WsKey } from '../types';
export declare const wsKeyInverse = "inverse";
export declare const wsKeyLinearPrivate = "linearPrivate";
export declare const wsKeyLinearPublic = "linearPublic";
export declare const wsKeySpotPrivate = "spotPrivate";
export declare const wsKeySpotPublic = "spotPublic";
export declare function getLinearWsKeyForTopic(topic: string): WsKey;
export declare function getSpotWsKeyForTopic(topic: string): WsKey;
import { APIMarket, WsKey } from '../types';
interface NetworkMapV3 {
livenet: string;
livenet2?: string;
testnet: string;
testnet2?: string;
}
declare type PublicPrivateNetwork = 'public' | 'private';
export declare const WS_BASE_URL_MAP: Record<APIMarket, Record<PublicPrivateNetwork, NetworkMapV3>>;
export declare const WS_KEY_MAP: {
readonly inverse: "inverse";
readonly linearPrivate: "linearPrivate";
readonly linearPublic: "linearPublic";
readonly spotPrivate: "spotPrivate";
readonly spotPublic: "spotPublic";
readonly spotV3Private: "spotV3Private";
readonly spotV3Public: "spotV3Public";
readonly usdcOptionPrivate: "usdcOptionPrivate";
readonly usdcOptionPublic: "usdcOptionPublic";
readonly usdcPerpPrivate: "usdcPerpPrivate";
readonly usdcPerpPublic: "usdcPerpPublic";
};
export declare const WS_AUTH_ON_CONNECT_KEYS: WsKey[];
export declare const PUBLIC_WS_KEYS: string[];
export declare function getWsKeyForTopic(market: APIMarket, topic: string, isPrivate?: boolean): WsKey;
export declare function getUsdcWsKeyForTopic(topic: string, subGroup: 'option' | 'perp'): WsKey;
export declare const WS_ERROR_ENUM: {
NOT_AUTHENTICATED_SPOT_V3: string;
API_ERROR_GENERIC: string;
API_SIGN_AUTH_FAILED: string;
USDC_OPTION_AUTH_FAILED: string;
};
export declare function neverGuard(x: never, msg: string): Error;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSpotWsKeyForTopic = exports.getLinearWsKeyForTopic = exports.wsKeySpotPublic = exports.wsKeySpotPrivate = exports.wsKeyLinearPublic = exports.wsKeyLinearPrivate = exports.wsKeyInverse = void 0;
exports.wsKeyInverse = 'inverse';
exports.wsKeyLinearPrivate = 'linearPrivate';
exports.wsKeyLinearPublic = 'linearPublic';
exports.wsKeySpotPrivate = 'spotPrivate';
exports.wsKeySpotPublic = 'spotPublic';
function getLinearWsKeyForTopic(topic) {
const privateLinearTopics = [
'position',
'execution',
'order',
'stop_order',
'wallet',
];
if (privateLinearTopics.includes(topic)) {
return exports.wsKeyLinearPrivate;
exports.neverGuard = exports.WS_ERROR_ENUM = exports.getUsdcWsKeyForTopic = exports.getWsKeyForTopic = exports.PUBLIC_WS_KEYS = exports.WS_AUTH_ON_CONNECT_KEYS = exports.WS_KEY_MAP = exports.WS_BASE_URL_MAP = void 0;
exports.WS_BASE_URL_MAP = {
inverse: {
public: {
livenet: 'wss://stream.bybit.com/realtime',
testnet: 'wss://stream-testnet.bybit.com/realtime',
},
private: {
livenet: 'wss://stream.bybit.com/realtime',
testnet: 'wss://stream-testnet.bybit.com/realtime',
},
},
linear: {
public: {
livenet: 'wss://stream.bybit.com/realtime_public',
livenet2: 'wss://stream.bytick.com/realtime_public',
testnet: 'wss://stream-testnet.bybit.com/realtime_public',
},
private: {
livenet: 'wss://stream.bybit.com/realtime_private',
livenet2: 'wss://stream.bytick.com/realtime_private',
testnet: 'wss://stream-testnet.bybit.com/realtime_private',
},
},
spot: {
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',
},
private: {
livenet: 'wss://stream.bybit.com/spot/ws',
testnet: 'wss://stream-testnet.bybit.com/spot/ws',
},
},
spotv3: {
public: {
livenet: 'wss://stream.bybit.com/spot/public/v3',
testnet: 'wss://stream-testnet.bybit.com/spot/public/v3',
},
private: {
livenet: 'wss://stream.bybit.com/spot/private/v3',
testnet: 'wss://stream-testnet.bybit.com/spot/private/v3',
},
},
usdcOption: {
public: {
livenet: 'wss://stream.bybit.com/trade/option/usdc/public/v1',
livenet2: 'wss://stream.bytick.com/trade/option/usdc/public/v1',
testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/public/v1',
},
private: {
livenet: 'wss://stream.bybit.com/trade/option/usdc/private/v1',
livenet2: 'wss://stream.bytick.com/trade/option/usdc/private/v1',
testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/private/v1',
},
},
usdcPerp: {
public: {
livenet: 'wss://stream.bybit.com/perpetual/ws/v1/realtime_public',
livenet2: 'wss://stream.bytick.com/perpetual/ws/v1/realtime_public',
testnet: 'wss://stream-testnet.bybit.com/perpetual/ws/v1/realtime_public',
},
private: {
livenet: 'wss://stream.bybit.com/trade/option/usdc/private/v1',
livenet2: 'wss://stream.bytick.com/trade/option/usdc/private/v1',
testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/private/v1',
},
},
};
exports.WS_KEY_MAP = {
inverse: 'inverse',
linearPrivate: 'linearPrivate',
linearPublic: 'linearPublic',
spotPrivate: 'spotPrivate',
spotPublic: 'spotPublic',
spotV3Private: 'spotV3Private',
spotV3Public: 'spotV3Public',
usdcOptionPrivate: 'usdcOptionPrivate',
usdcOptionPublic: 'usdcOptionPublic',
usdcPerpPrivate: 'usdcPerpPrivate',
usdcPerpPublic: 'usdcPerpPublic',
};
exports.WS_AUTH_ON_CONNECT_KEYS = [
exports.WS_KEY_MAP.spotV3Private,
exports.WS_KEY_MAP.usdcOptionPrivate,
exports.WS_KEY_MAP.usdcPerpPrivate,
];
exports.PUBLIC_WS_KEYS = [
exports.WS_KEY_MAP.linearPublic,
exports.WS_KEY_MAP.spotPublic,
exports.WS_KEY_MAP.spotV3Public,
exports.WS_KEY_MAP.usdcOptionPublic,
exports.WS_KEY_MAP.usdcPerpPublic,
];
/** Used to automatically determine if a sub request should be to the public or private ws (when there's two) */
const PRIVATE_TOPICS = [
'position',
'execution',
'order',
'stop_order',
'wallet',
'outboundAccountInfo',
'executionReport',
'ticketInfo',
// copy trading apis
'copyTradePosition',
'copyTradeOrder',
'copyTradeExecution',
'copyTradeWallet',
// usdc options
'user.openapi.option.position',
'user.openapi.option.trade',
'user.order',
'user.openapi.option.order',
'user.service',
'user.openapi.greeks',
'user.mmp.event',
// usdc perps
'user.openapi.perp.position',
'user.openapi.perp.trade',
'user.openapi.perp.order',
'user.service',
// unified margin
'user.position.unifiedAccount',
'user.execution.unifiedAccount',
'user.order.unifiedAccount',
'user.wallet.unifiedAccount',
'user.greeks.unifiedAccount',
];
function getWsKeyForTopic(market, topic, isPrivate) {
const isPrivateTopic = isPrivate === true || PRIVATE_TOPICS.includes(topic);
switch (market) {
case 'inverse': {
return exports.WS_KEY_MAP.inverse;
}
case 'linear': {
return isPrivateTopic
? exports.WS_KEY_MAP.linearPrivate
: exports.WS_KEY_MAP.linearPublic;
}
case 'spot': {
return isPrivateTopic ? exports.WS_KEY_MAP.spotPrivate : exports.WS_KEY_MAP.spotPublic;
}
case 'spotv3': {
return isPrivateTopic
? exports.WS_KEY_MAP.spotV3Private
: exports.WS_KEY_MAP.spotV3Public;
}
case 'usdcOption': {
return isPrivateTopic
? exports.WS_KEY_MAP.usdcOptionPrivate
: exports.WS_KEY_MAP.usdcOptionPublic;
}
case 'usdcPerp': {
return isPrivateTopic
? exports.WS_KEY_MAP.usdcPerpPrivate
: exports.WS_KEY_MAP.usdcPerpPublic;
}
default: {
throw neverGuard(market, `getWsKeyForTopic(): Unhandled market`);
}
}
return exports.wsKeyLinearPublic;
}
exports.getLinearWsKeyForTopic = getLinearWsKeyForTopic;
function getSpotWsKeyForTopic(topic) {
const privateLinearTopics = [
'position',
'execution',
'order',
'stop_order',
'outboundAccountInfo',
'executionReport',
'ticketInfo',
];
if (privateLinearTopics.includes(topic)) {
return exports.wsKeySpotPrivate;
exports.getWsKeyForTopic = getWsKeyForTopic;
function getUsdcWsKeyForTopic(topic, subGroup) {
const isPrivateTopic = PRIVATE_TOPICS.includes(topic);
if (subGroup === 'option') {
return isPrivateTopic
? exports.WS_KEY_MAP.usdcOptionPrivate
: exports.WS_KEY_MAP.usdcOptionPublic;
}
return exports.wsKeySpotPublic;
return isPrivateTopic
? exports.WS_KEY_MAP.usdcOptionPrivate
: exports.WS_KEY_MAP.usdcOptionPublic;
// return isPrivateTopic
// ? WS_KEY_MAP.usdcPerpPrivate
// : WS_KEY_MAP.usdcPerpPublic;
}
exports.getSpotWsKeyForTopic = getSpotWsKeyForTopic;
exports.getUsdcWsKeyForTopic = getUsdcWsKeyForTopic;
exports.WS_ERROR_ENUM = {
NOT_AUTHENTICATED_SPOT_V3: '-1004',
API_ERROR_GENERIC: '10001',
API_SIGN_AUTH_FAILED: '10003',
USDC_OPTION_AUTH_FAILED: '3303006',
};
function neverGuard(x, msg) {
return new Error(`Unhandled value exception "x", ${msg}`);
}
exports.neverGuard = neverGuard;
//# sourceMappingURL=websocket-util.js.map
import WebSocket from 'isomorphic-ws';
import { WsKey } from '../types';
import { DefaultLogger } from './logger';

@@ -26,2 +27,4 @@ export declare enum WsConnectionStateEnum {

activePongTimer?: ReturnType<typeof setTimeout> | undefined;
/** If a reconnection is in progress, this will have the timer for the delayed reconnect */
activeReconnectTimer?: ReturnType<typeof setTimeout> | undefined;
/**

@@ -37,19 +40,19 @@ * All the topics we are expected to be subscribed to (and we automatically resubscribe to if the connection drops)

/** Get WS stored state for key, optionally create if missing */
get(key: string, createIfMissing?: true): WsStoredState;
get(key: string, createIfMissing?: false): WsStoredState | undefined;
getKeys(): string[];
create(key: string): WsStoredState | undefined;
delete(key: string): void;
hasExistingActiveConnection(key: string): boolean;
getWs(key: string): WebSocket | undefined;
setWs(key: string, wsConnection: WebSocket): WebSocket;
isWsOpen(key: string): boolean;
getConnectionState(key: string): WsConnectionStateEnum;
setConnectionState(key: string, state: WsConnectionStateEnum): void;
isConnectionState(key: string, state: WsConnectionStateEnum): boolean;
getTopics(key: string): WsTopicList;
get(key: WsKey, createIfMissing?: true): WsStoredState;
get(key: WsKey, createIfMissing?: false): WsStoredState | undefined;
getKeys(): WsKey[];
create(key: WsKey): WsStoredState | undefined;
delete(key: WsKey): void;
hasExistingActiveConnection(key: WsKey): boolean;
getWs(key: WsKey): WebSocket | undefined;
setWs(key: WsKey, wsConnection: WebSocket): WebSocket;
isWsOpen(key: WsKey): boolean;
getConnectionState(key: WsKey): WsConnectionStateEnum;
setConnectionState(key: WsKey, state: WsConnectionStateEnum): void;
isConnectionState(key: WsKey, state: WsConnectionStateEnum): boolean;
getTopics(key: WsKey): WsTopicList;
getTopicsByKey(): Record<string, WsTopicList>;
addTopic(key: string, topic: WsTopic): WsTopicList;
deleteTopic(key: string, topic: WsTopic): boolean;
addTopic(key: WsKey, topic: WsTopic): WsTopicList;
deleteTopic(key: WsKey, topic: WsTopic): boolean;
}
export {};

@@ -12,2 +12,3 @@ "use strict";

WsConnectionStateEnum[WsConnectionStateEnum["RECONNECTING"] = 4] = "RECONNECTING";
// ERROR = 5,
})(WsConnectionStateEnum = exports.WsConnectionStateEnum || (exports.WsConnectionStateEnum = {}));

@@ -14,0 +15,0 @@ class WsStore {

/// <reference types="node" />
import { EventEmitter } from 'events';
import WebSocket from 'isomorphic-ws';
import { DefaultLogger } from './util/logger';
import { KlineInterval, WSClientConfigurableOptions, WsKey, WsTopic } from './types';
export declare interface WebsocketClient {
on(event: 'open' | 'reconnected', listener: ({ wsKey: WsKey, event: any }: {
wsKey: any;
import { DefaultLogger } from './util';
export declare type WsClientEvent = 'open' | 'update' | 'close' | 'errorEvent' | 'reconnect' | 'reconnected' | 'response';
interface WebsocketClientEvents {
open: (evt: {
wsKey: WsKey;
event: any;
}) => void): this;
on(event: 'response' | 'update' | 'error', listener: (response: any) => void): this;
on(event: 'reconnect' | 'close', listener: ({ wsKey: WsKey }: {
wsKey: any;
}) => void): this;
}) => void;
reconnect: (evt: {
wsKey: WsKey;
event: any;
}) => void;
reconnected: (evt: {
wsKey: WsKey;
event: any;
}) => void;
close: (evt: {
wsKey: WsKey;
event: any;
}) => void;
response: (response: any) => void;
update: (response: any) => void;
errorEvent: (response: any) => void;
}
export declare interface WebsocketClient {
on<U extends keyof WebsocketClientEvents>(event: U, listener: WebsocketClientEvents[U]): this;
emit<U extends keyof WebsocketClientEvents>(event: U, ...args: Parameters<WebsocketClientEvents[U]>): boolean;
}
export declare class WebsocketClient extends EventEmitter {
private logger;
/** Purely used */
private restClient;
private restClient?;
private options;
private wsStore;
constructor(options: WSClientConfigurableOptions, logger?: typeof DefaultLogger);
isLivenet(): boolean;
isLinear(): boolean;
isSpot(): boolean;
isInverse(): boolean;
/** USDC, spot v3, unified margin, account asset */
isV3(): boolean;
/**
* Add topic/topics to WS subscription list
* Only used if we fetch exchange time before attempting auth.
* Disabled by default.
* I've removed this for ftx and it's working great, tempted to remove this here
*/
subscribe(wsTopics: WsTopic[] | WsTopic): void;
/**
* Remove topic/topics from WS subscription list
*/
unsubscribe(wsTopics: WsTopic[] | WsTopic): void;
prepareRESTClient(): void;
isTestnet(): boolean;
close(wsKey: WsKey): void;
closeAll(): void;
/**
* Request connection of all dependent (public & private) websockets, instead of waiting for automatic connection by library
*/
connectAll(): Promise<WebSocket | undefined>[] | undefined;
connectPublic(): Promise<WebSocket | undefined> | undefined;
connectPrivate(): Promise<WebSocket | undefined> | undefined;
connectAll(): Promise<WebSocket | undefined>[];
connectPublic(): Promise<WebSocket | undefined>;
connectPrivate(): Promise<WebSocket | undefined>;
private connect;

@@ -50,2 +59,4 @@ private parseWsError;

private getAuthParams;
private sendAuthRequest;
private getWsAuthSignature;
private reconnectWithDelay;

@@ -64,3 +75,3 @@ private ping;

private requestUnsubscribeTopics;
private tryWsSend;
tryWsSend(wsKey: WsKey, wsMessage: string): void;
private connectToWsUrl;

@@ -71,12 +82,27 @@ private onWsOpen;

private onWsClose;
private onWsMessageResponse;
private getWs;
private setWsState;
private getWsUrl;
private getWsKeyForTopic;
private wrongMarketError;
/**
* Add topic/topics to WS subscription list
* @param wsTopics topic or list of topics
* @param isPrivateTopic optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
*/
subscribe(wsTopics: WsTopic[] | WsTopic, isPrivateTopic?: boolean): void;
/**
* Remove topic/topics from WS subscription list
* @param wsTopics topic or list of topics
* @param isPrivateTopic optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
*/
unsubscribe(wsTopics: WsTopic[] | WsTopic, isPrivateTopic?: boolean): void;
/** @deprecated use "market: 'spotv3" client */
subscribePublicSpotTrades(symbol: string, binary?: boolean): void;
/** @deprecated use "market: 'spotv3" client */
subscribePublicSpotTradingPair(symbol: string, binary?: boolean): void;
/** @deprecated use "market: 'spotv3" client */
subscribePublicSpotV1Kline(symbol: string, candleSize: KlineInterval, binary?: boolean): void;
/** @deprecated use "market: 'spotv3" client */
subscribePublicSpotOrderbook(symbol: string, depth: 'full' | 'merge' | 'delta', dumpScale?: number, binary?: boolean): void;
}
export {};

@@ -22,34 +22,7 @@ "use strict";

const spot_client_1 = require("./spot-client");
const logger_1 = require("./util/logger");
const node_support_1 = require("./util/node-support");
const WsStore_1 = __importDefault(require("./util/WsStore"));
const util_1 = require("./util");
const inverseEndpoints = {
livenet: 'wss://stream.bybit.com/realtime',
testnet: 'wss://stream-testnet.bybit.com/realtime',
};
const linearEndpoints = {
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 = {
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 usdc_option_client_1 = require("./usdc-option-client");
const usdc_perpetual_client_1 = require("./usdc-perpetual-client");
const loggerCategory = { category: 'bybit-ws' };

@@ -59,67 +32,47 @@ class WebsocketClient extends events_1.EventEmitter {

super();
this.logger = logger || logger_1.DefaultLogger;
this.logger = logger || util_1.DefaultLogger;
this.wsStore = new WsStore_1.default(this.logger);
this.options = Object.assign({ livenet: false, pongTimeout: 1000, pingInterval: 10000, reconnectTimeout: 500, fetchTimeOffsetBeforeAuth: false }, options);
if (this.isV3()) {
this.restClient = new spot_client_v3_1.SpotClientV3(undefined, undefined, this.isLivenet(), this.options.restOptions, this.options.requestOptions);
}
else if (this.isLinear()) {
this.restClient = new linear_client_1.LinearClient(undefined, undefined, this.isLivenet(), this.options.restOptions, this.options.requestOptions);
}
else if (this.isSpot()) {
this.restClient = new spot_client_1.SpotClient(undefined, undefined, this.isLivenet(), this.options.restOptions, this.options.requestOptions);
this.connectPublic();
}
else {
this.restClient = new inverse_client_1.InverseClient(undefined, undefined, this.isLivenet(), this.options.restOptions, this.options.requestOptions);
}
this.options = Object.assign({ testnet: false, pongTimeout: 1000, pingInterval: 10000, reconnectTimeout: 500, fetchTimeOffsetBeforeAuth: false }, options);
this.prepareRESTClient();
}
isLivenet() {
return this.options.livenet === true;
}
isLinear() {
return this.options.market === 'linear';
}
isSpot() {
return this.options.market === 'spot';
}
isInverse() {
return this.options.market === 'inverse';
}
/** USDC, spot v3, unified margin, account asset */
isV3() {
return this.options.market === 'v3';
}
/**
* Add topic/topics to WS subscription list
* Only used if we fetch exchange time before attempting auth.
* Disabled by default.
* I've removed this for ftx and it's working great, tempted to remove this here
*/
subscribe(wsTopics) {
const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
topics.forEach((topic) => this.wsStore.addTopic(this.getWsKeyForTopic(topic), topic));
// attempt to send subscription topic per websocket
this.wsStore.getKeys().forEach((wsKey) => {
// if connected, send subscription request
if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTED)) {
return this.requestSubscribeTopics(wsKey, topics);
prepareRESTClient() {
switch (this.options.market) {
case 'inverse': {
this.restClient = new inverse_client_1.InverseClient(undefined, undefined, !this.isTestnet(), this.options.restOptions, this.options.requestOptions);
break;
}
// start connection process if it hasn't yet begun. Topics are automatically subscribed to on-connect
if (!this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTING) &&
!this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.RECONNECTING)) {
return this.connect(wsKey);
case 'linear': {
this.restClient = new linear_client_1.LinearClient(undefined, undefined, !this.isTestnet(), this.options.restOptions, this.options.requestOptions);
break;
}
});
}
/**
* Remove topic/topics from WS subscription list
*/
unsubscribe(wsTopics) {
const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
topics.forEach((topic) => this.wsStore.deleteTopic(this.getWsKeyForTopic(topic), topic));
this.wsStore.getKeys().forEach((wsKey) => {
// unsubscribe request only necessary if active connection exists
if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTED)) {
this.requestUnsubscribeTopics(wsKey, topics);
case 'spot': {
this.restClient = new spot_client_1.SpotClient(undefined, undefined, !this.isTestnet(), this.options.restOptions, this.options.requestOptions);
this.connectPublic();
break;
}
});
case 'spotv3': {
this.restClient = new spot_client_v3_1.SpotClientV3(undefined, undefined, !this.isTestnet(), this.options.restOptions, this.options.requestOptions);
break;
}
case 'usdcOption': {
this.restClient = new usdc_option_client_1.USDCOptionClient(undefined, undefined, !this.isTestnet(), this.options.restOptions, this.options.requestOptions);
break;
}
case 'usdcPerp': {
this.restClient = new usdc_perpetual_client_1.USDCPerpetualClient(undefined, undefined, !this.isTestnet(), this.options.restOptions, this.options.requestOptions);
break;
}
default: {
throw util_1.neverGuard(this.options.market, `prepareRESTClient(): Unhandled market`);
}
}
}
isTestnet() {
return this.options.testnet === true;
}
close(wsKey) {

@@ -132,2 +85,8 @@ var _a;

}
closeAll() {
const keys = this.wsStore.getKeys();
keys.forEach((key) => {
this.close(key);
});
}
/**

@@ -137,36 +96,69 @@ * Request connection of all dependent (public & private) websockets, instead of waiting for automatic connection by library

connectAll() {
if (this.isInverse()) {
return [this.connect(util_1.wsKeyInverse)];
switch (this.options.market) {
case 'inverse': {
// only one for inverse
return [this.connectPublic()];
}
// these all have separate public & private ws endpoints
case 'linear':
case 'spot':
case 'spotv3':
case 'usdcOption':
case 'usdcPerp': {
return [this.connectPublic(), this.connectPrivate()];
}
default: {
throw util_1.neverGuard(this.options.market, `connectAll(): Unhandled market`);
}
}
if (this.isLinear()) {
return [
this.connect(util_1.wsKeyLinearPublic),
this.connect(util_1.wsKeyLinearPrivate),
];
}
if (this.isSpot()) {
return [this.connect(util_1.wsKeySpotPublic), this.connect(util_1.wsKeySpotPrivate)];
}
}
connectPublic() {
if (this.isInverse()) {
return this.connect(util_1.wsKeyInverse);
switch (this.options.market) {
case 'inverse': {
return this.connect(util_1.WS_KEY_MAP.inverse);
}
case 'linear': {
return this.connect(util_1.WS_KEY_MAP.linearPublic);
}
case 'spot': {
return this.connect(util_1.WS_KEY_MAP.spotPublic);
}
case 'spotv3': {
return this.connect(util_1.WS_KEY_MAP.spotV3Public);
}
case 'usdcOption': {
return this.connect(util_1.WS_KEY_MAP.usdcOptionPublic);
}
case 'usdcPerp': {
return this.connect(util_1.WS_KEY_MAP.usdcPerpPublic);
}
default: {
throw util_1.neverGuard(this.options.market, `connectPublic(): Unhandled market`);
}
}
if (this.isLinear()) {
return this.connect(util_1.wsKeyLinearPublic);
}
if (this.isSpot()) {
return this.connect(util_1.wsKeySpotPublic);
}
}
connectPrivate() {
if (this.isInverse()) {
return this.connect(util_1.wsKeyInverse);
switch (this.options.market) {
case 'inverse': {
return this.connect(util_1.WS_KEY_MAP.inverse);
}
case 'linear': {
return this.connect(util_1.WS_KEY_MAP.linearPrivate);
}
case 'spot': {
return this.connect(util_1.WS_KEY_MAP.spotPrivate);
}
case 'spotv3': {
return this.connect(util_1.WS_KEY_MAP.spotV3Private);
}
case 'usdcOption': {
return this.connect(util_1.WS_KEY_MAP.usdcOptionPrivate);
}
case 'usdcPerp': {
return this.connect(util_1.WS_KEY_MAP.usdcPerpPrivate);
}
default: {
throw util_1.neverGuard(this.options.market, `connectPrivate(): Unhandled market`);
}
}
if (this.isLinear()) {
return this.connect(util_1.wsKeyLinearPrivate);
}
if (this.isSpot()) {
return this.connect(util_1.wsKeySpotPrivate);
}
}

@@ -202,2 +194,3 @@ connect(wsKey) {

this.logger.error(`${context} due to unexpected error: `, error);
this.emit('errorEvent', error);
return;

@@ -213,2 +206,3 @@ }

}
this.emit('errorEvent', error);
}

@@ -220,27 +214,57 @@ /**

return __awaiter(this, void 0, void 0, function* () {
const { key, secret } = this.options;
if (key &&
secret &&
wsKey !== util_1.wsKeyLinearPublic &&
wsKey !== util_1.wsKeySpotPublic) {
this.logger.debug("Getting auth'd request params", Object.assign(Object.assign({}, loggerCategory), { wsKey }));
const timeOffset = this.options.fetchTimeOffsetBeforeAuth
? yield this.restClient.fetchTimeOffset()
: 0;
const params = {
if (util_1.PUBLIC_WS_KEYS.includes(wsKey)) {
this.logger.debug('Starting public only websocket client.', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
return '';
}
try {
const { signature, expiresAt } = yield this.getWsAuthSignature(wsKey);
const authParams = {
api_key: this.options.key,
expires: Date.now() + timeOffset + 5000,
expires: expiresAt,
signature,
};
params.signature = yield node_support_1.signMessage('GET/realtime' + params.expires, secret);
return '?' + util_1.serializeParams(params);
return '?' + util_1.serializeParams(authParams);
}
else if (!key || !secret) {
this.logger.warning('Cannot authenticate websocket, either api or private keys missing.', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
catch (e) {
this.logger.error(e, Object.assign(Object.assign({}, loggerCategory), { wsKey }));
return '';
}
else {
this.logger.debug('Starting public only websocket client.', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
});
}
sendAuthRequest(wsKey) {
return __awaiter(this, void 0, void 0, function* () {
try {
const { signature, expiresAt } = yield this.getWsAuthSignature(wsKey);
const request = {
op: 'auth',
args: [this.options.key, expiresAt, signature],
req_id: `${wsKey}-auth`,
};
return this.tryWsSend(wsKey, JSON.stringify(request));
}
return '';
catch (e) {
this.logger.error(e, Object.assign(Object.assign({}, loggerCategory), { wsKey }));
}
});
}
getWsAuthSignature(wsKey) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const { key, secret } = this.options;
if (!key || !secret) {
this.logger.warning('Cannot authenticate websocket, either api or private keys missing.', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
throw new Error(`Cannot auth - missing api or secret in config`);
}
this.logger.debug("Getting auth'd request params", Object.assign(Object.assign({}, loggerCategory), { wsKey }));
const timeOffset = this.options.fetchTimeOffsetBeforeAuth
? (yield ((_a = this.restClient) === null || _a === void 0 ? void 0 : _a.fetchTimeOffset())) || 0
: 0;
const signatureExpiresAt = Date.now() + timeOffset + 5000;
const signature = yield node_support_1.signMessage('GET/realtime' + signatureExpiresAt, secret);
return {
expiresAt: signatureExpiresAt,
signature,
};
});
}
reconnectWithDelay(wsKey, connectionDelayMs) {

@@ -252,3 +276,3 @@ this.clearTimers(wsKey);

}
setTimeout(() => {
this.wsStore.get(wsKey, true).activeReconnectTimer = setTimeout(() => {
this.logger.info('Reconnecting to websocket', Object.assign(Object.assign({}, loggerCategory), { wsKey }));

@@ -271,2 +295,6 @@ this.connect(wsKey);

this.clearPongTimer(wsKey);
const wsState = this.wsStore.get(wsKey);
if (wsState === null || wsState === void 0 ? void 0 : wsState.activeReconnectTimer) {
clearTimeout(wsState.activeReconnectTimer);
}
}

@@ -297,2 +325,3 @@ // Send a ping at intervals

const wsMessage = JSON.stringify({
req_id: topics.join(','),
op: 'subscribe',

@@ -346,16 +375,23 @@ args: topics,

onWsOpen(event, wsKey) {
if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTING)) {
this.logger.info('Websocket connected', Object.assign(Object.assign({}, loggerCategory), { wsKey, livenet: this.isLivenet(), linear: this.isLinear(), spot: this.isSpot() }));
this.emit('open', { wsKey, event });
}
else if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.RECONNECTING)) {
this.logger.info('Websocket reconnected', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
this.emit('reconnected', { wsKey, event });
}
this.setWsState(wsKey, util_1.WsConnectionStateEnum.CONNECTED);
// TODO: persistence not working yet for spot topics
if (wsKey !== 'spotPublic' && wsKey !== 'spotPrivate') {
this.requestSubscribeTopics(wsKey, [...this.wsStore.getTopics(wsKey)]);
}
this.wsStore.get(wsKey, true).activePingTimer = setInterval(() => this.ping(wsKey), this.options.pingInterval);
return __awaiter(this, void 0, void 0, function* () {
if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTING)) {
this.logger.info('Websocket connected', Object.assign(Object.assign({}, loggerCategory), { wsKey, testnet: this.isTestnet(), market: this.options.market }));
this.emit('open', { wsKey, event });
}
else if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.RECONNECTING)) {
this.logger.info('Websocket reconnected', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
this.emit('reconnected', { wsKey, event });
}
this.setWsState(wsKey, util_1.WsConnectionStateEnum.CONNECTED);
// Some websockets require an auth packet to be sent after opening the connection
if (util_1.WS_AUTH_ON_CONNECT_KEYS.includes(wsKey)) {
this.logger.info(`Sending auth request...`);
yield this.sendAuthRequest(wsKey);
}
// TODO: persistence not working yet for spot v1 topics
if (wsKey !== util_1.WS_KEY_MAP.spotPublic && wsKey !== util_1.WS_KEY_MAP.spotPrivate) {
this.requestSubscribeTopics(wsKey, [...this.wsStore.getTopics(wsKey)]);
}
this.wsStore.get(wsKey, true).activePingTimer = setInterval(() => this.ping(wsKey), this.options.pingInterval);
});
}

@@ -367,9 +403,29 @@ onWsMessage(event, wsKey) {

const msg = JSON.parse((event && event.data) || event);
if (msg['success'] || (msg === null || msg === void 0 ? void 0 : msg.pong)) {
return this.onWsMessageResponse(msg, wsKey);
this.logger.silly('Received event', Object.assign(Object.assign({}, this.logger), { wsKey, msg: JSON.stringify(msg, null, 2) }));
// TODO: cleanme
if (msg['success'] || (msg === null || msg === void 0 ? void 0 : msg.pong) || util_1.isWsPong(msg)) {
if (util_1.isWsPong(msg)) {
this.logger.silly('Received pong', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
}
else {
this.emit('response', msg);
}
return;
}
if (msg.topic) {
if (msg['finalFragment']) {
return this.emit('response', msg);
}
if (msg === null || msg === void 0 ? void 0 : msg.topic) {
return this.emit('update', msg);
}
this.logger.warning('Got unhandled ws message', Object.assign(Object.assign({}, loggerCategory), { message: msg, event,
if (
// spot v1
(msg === null || msg === void 0 ? void 0 : msg.code) ||
// spot v3
(msg === null || msg === void 0 ? void 0 : msg.type) === 'error' ||
// usdc options
(msg === null || msg === void 0 ? void 0 : msg.success) === false) {
return this.emit('errorEvent', msg);
}
this.logger.warning('Unhandled/unrecognised ws event message', Object.assign(Object.assign({}, loggerCategory), { message: msg, event,
wsKey }));

@@ -385,3 +441,3 @@ }

if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTED)) {
this.emit('error', error);
this.emit('errorEvent', error);
}

@@ -393,17 +449,9 @@ }

this.reconnectWithDelay(wsKey, this.options.reconnectTimeout);
this.emit('reconnect', { wsKey });
this.emit('reconnect', { wsKey, event });
}
else {
this.setWsState(wsKey, util_1.WsConnectionStateEnum.INITIAL);
this.emit('close', { wsKey });
this.emit('close', { wsKey, event });
}
}
onWsMessageResponse(response, wsKey) {
if (util_1.isWsPong(response)) {
this.logger.silly('Received pong', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
}
else {
this.emit('response', response);
}
}
getWs(wsKey) {

@@ -419,45 +467,89 @@ return this.wsStore.getWs(wsKey);

}
const networkKey = this.isLivenet() ? 'livenet' : 'testnet';
// TODO: repetitive
if (this.isLinear() || wsKey.startsWith('linear')) {
if (wsKey === util_1.wsKeyLinearPublic) {
return linearEndpoints.public[networkKey];
const networkKey = this.isTestnet() ? 'testnet' : 'livenet';
switch (wsKey) {
case util_1.WS_KEY_MAP.linearPublic: {
return util_1.WS_BASE_URL_MAP.linear.public[networkKey];
}
if (wsKey === util_1.wsKeyLinearPrivate) {
return linearEndpoints.private[networkKey];
case util_1.WS_KEY_MAP.linearPrivate: {
return util_1.WS_BASE_URL_MAP.linear.private[networkKey];
}
this.logger.error('Unhandled linear wsKey: ', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
return linearEndpoints[networkKey];
}
if (this.isSpot() || wsKey.startsWith('spot')) {
if (wsKey === util_1.wsKeySpotPublic) {
return spotEndpoints.public[networkKey];
case util_1.WS_KEY_MAP.spotPublic: {
return util_1.WS_BASE_URL_MAP.spot.public[networkKey];
}
if (wsKey === util_1.wsKeySpotPrivate) {
return spotEndpoints.private[networkKey];
case util_1.WS_KEY_MAP.spotPrivate: {
return util_1.WS_BASE_URL_MAP.spot.private[networkKey];
}
this.logger.error('Unhandled spot wsKey: ', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
return spotEndpoints[networkKey];
case util_1.WS_KEY_MAP.spotV3Public: {
return util_1.WS_BASE_URL_MAP.spotv3.public[networkKey];
}
case util_1.WS_KEY_MAP.spotV3Private: {
return util_1.WS_BASE_URL_MAP.spotv3.private[networkKey];
}
case util_1.WS_KEY_MAP.inverse: {
// private and public are on the same WS connection
return util_1.WS_BASE_URL_MAP.inverse.public[networkKey];
}
case util_1.WS_KEY_MAP.usdcOptionPublic: {
return util_1.WS_BASE_URL_MAP.usdcOption.public[networkKey];
}
case util_1.WS_KEY_MAP.usdcOptionPrivate: {
return util_1.WS_BASE_URL_MAP.usdcOption.private[networkKey];
}
case util_1.WS_KEY_MAP.usdcPerpPublic: {
return util_1.WS_BASE_URL_MAP.usdcPerp.public[networkKey];
}
case util_1.WS_KEY_MAP.usdcPerpPrivate: {
return util_1.WS_BASE_URL_MAP.usdcPerp.private[networkKey];
}
default: {
this.logger.error('getWsUrl(): Unhandled wsKey: ', Object.assign(Object.assign({}, loggerCategory), { wsKey }));
throw util_1.neverGuard(wsKey, `getWsUrl(): Unhandled wsKey`);
}
}
// fallback to inverse
return inverseEndpoints[networkKey];
}
getWsKeyForTopic(topic) {
if (this.isInverse()) {
return util_1.wsKeyInverse;
}
if (this.isLinear()) {
return util_1.getLinearWsKeyForTopic(topic);
}
return util_1.getSpotWsKeyForTopic(topic);
}
wrongMarketError(market) {
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.
/**
* Add topic/topics to WS subscription list
* @param wsTopics topic or list of topics
* @param isPrivateTopic optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
*/
subscribe(wsTopics, isPrivateTopic) {
const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
topics.forEach((topic) => this.wsStore.addTopic(util_1.getWsKeyForTopic(this.options.market, topic, isPrivateTopic), topic));
// attempt to send subscription topic per websocket
this.wsStore.getKeys().forEach((wsKey) => {
// if connected, send subscription request
if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTED)) {
return this.requestSubscribeTopics(wsKey, topics);
}
// start connection process if it hasn't yet begun. Topics are automatically subscribed to on-connect
if (!this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTING) &&
!this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.RECONNECTING)) {
return this.connect(wsKey);
}
});
}
/**
* Remove topic/topics from WS subscription list
* @param wsTopics topic or list of topics
* @param isPrivateTopic optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
*/
unsubscribe(wsTopics, isPrivateTopic) {
const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
topics.forEach((topic) => this.wsStore.deleteTopic(util_1.getWsKeyForTopic(this.options.market, topic, isPrivateTopic), topic));
this.wsStore.getKeys().forEach((wsKey) => {
// unsubscribe request only necessary if active connection exists
if (this.wsStore.isConnectionState(wsKey, util_1.WsConnectionStateEnum.CONNECTED)) {
this.requestUnsubscribeTopics(wsKey, topics);
}
});
}
/** @deprecated use "market: 'spotv3" client */
subscribePublicSpotTrades(symbol, binary) {
if (!this.isSpot()) {
if (this.options.market !== 'spot') {
throw this.wrongMarketError('spot');
}
return this.tryWsSend(util_1.wsKeySpotPublic, JSON.stringify({
return this.tryWsSend(util_1.WS_KEY_MAP.spotPublic, JSON.stringify({
topic: 'trade',

@@ -471,7 +563,8 @@ event: 'sub',

}
/** @deprecated use "market: 'spotv3" client */
subscribePublicSpotTradingPair(symbol, binary) {
if (!this.isSpot()) {
if (this.options.market !== 'spot') {
throw this.wrongMarketError('spot');
}
return this.tryWsSend(util_1.wsKeySpotPublic, JSON.stringify({
return this.tryWsSend(util_1.WS_KEY_MAP.spotPublic, JSON.stringify({
symbol,

@@ -485,7 +578,8 @@ topic: 'realtimes',

}
/** @deprecated use "market: 'spotv3" client */
subscribePublicSpotV1Kline(symbol, candleSize, binary) {
if (!this.isSpot()) {
if (this.options.market !== 'spot') {
throw this.wrongMarketError('spot');
}
return this.tryWsSend(util_1.wsKeySpotPublic, JSON.stringify({
return this.tryWsSend(util_1.WS_KEY_MAP.spotPublic, JSON.stringify({
symbol,

@@ -502,4 +596,5 @@ topic: 'kline_' + candleSize,

//ws.send('{"symbol":"BTCUSDT","topic":"diffDepth","event":"sub","params":{"binary":false}}');
/** @deprecated use "market: 'spotv3" client */
subscribePublicSpotOrderbook(symbol, depth, dumpScale, binary) {
if (!this.isSpot()) {
if (this.options.market !== 'spot') {
throw this.wrongMarketError('spot');

@@ -536,3 +631,3 @@ }

}
return this.tryWsSend(util_1.wsKeySpotPublic, JSON.stringify(msg));
return this.tryWsSend(util_1.WS_KEY_MAP.spotPublic, JSON.stringify(msg));
}

@@ -539,0 +634,0 @@ }

{
"name": "bybit-api",
"version": "2.4.0-beta.1",
"version": "2.4.0-beta.2",
"description": "Node.js connector for Bybit's REST APIs and WebSockets, with TypeScript & integration tests.",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -14,4 +14,4 @@ # bybit-api

- TypeScript support (with type declarations for most API requests & responses).
- Over 200 integration tests making real API calls, validating any changes before they reach npm.
- Robust WebSocket integration with connection heartbeats & automatic reconnection.
- Over 300 integration tests making real API calls & WebSocket connections, validating any changes before they reach npm.
- Robust WebSocket integration with configurable connection heartbeats & automatic reconnect then resubscribe workflows.
- Browser support (via webpack bundle - see "Browser Usage" below).

@@ -49,3 +49,3 @@

- [lib](./lib) - the JavaScript version of the project (built from TypeScript). This should not be edited directly, as it will be overwritten with each release.
- [dist](./dist) - the packed bundle of the project for use in browser environments.
- [dist](./dist) - the web-packed bundle of the project for use in browser environments.
- [examples](./examples) - some implementation examples & demonstrations. Contributions are welcome!

@@ -154,2 +154,15 @@

The WebsocketClient can be configured to a specific API group using the market parameter. These are the currently available API groups:
| API Category | Market | Description |
|:----------------------------: |:-------------------: |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Unified Margin | TBC | The [derivatives v3](https://bybit-exchange.github.io/docs/derivativesV3/unified_margin/#t-websocket) category for unified margin. |
| Futures v2 - Inverse Perps | `market: 'inverse'` | The [inverse v2 perps](https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-websocket) category. |
| Futures v2 - USDT Perps | `market: 'linear'` | The [USDT/linear v2 perps](https://bybit-exchange.github.io/docs/futuresV2/linear/#t-websocket) category. |
| Futures v2 - Inverse Futures | `market: 'inverse'` | The [inverse futures v2](https://bybit-exchange.github.io/docs/futuresV2/inverse_futures/#t-websocket) category uses the same market as inverse perps. |
| Spot v3 | `market: 'spotv3'` | The [spot v3](https://bybit-exchange.github.io/docs/spot/v3/#t-websocket) category. |
| Spot v1 | `market: 'spot'` | The older [spot v1](https://bybit-exchange.github.io/docs/spot/v1/#t-websocket) category. Use the `spotv3` market if possible, as the v1 category does not have automatic re-subscribe if reconnected. |
| Copy Trading | `market: 'linear'` | The [copy trading](https://bybit-exchange.github.io/docs/copy_trading/#t-websocket) category. Use the linear market to listen to all copy trading topics. |
| USDC Perps | TBC | The [USDC perps](https://bybit-exchange.github.io/docs/usdc/perpetual/#t-websocket) category. |
| USDC Options | TBC | The [USDC options](https://bybit-exchange.github.io/docs/usdc/option/#t-websocket) category. |
```javascript

@@ -156,0 +169,0 @@ const { WebsocketClient } = require('bybit-api');

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc