v2.3.0: fix(#158), disable time sync by default. Optionally avoid hitting time API when connecting authenticated websocket.
This commit is contained in:
@@ -64,10 +64,10 @@ const restClientOptions = {
|
|||||||
recv_window?: number;
|
recv_window?: number;
|
||||||
|
|
||||||
// how often to sync time drift with bybit servers
|
// how often to sync time drift with bybit servers
|
||||||
sync_interval_ms?: number | string;
|
sync_interval_ms?: number;
|
||||||
|
|
||||||
// Default: false. Disable above sync mechanism if true.
|
// Default: false. Disable above sync mechanism if true.
|
||||||
disable_time_sync?: boolean;
|
enable_time_sync?: boolean;
|
||||||
|
|
||||||
// Default: false. If true, we'll throw errors if any params are undefined
|
// Default: false. If true, we'll throw errors if any params are undefined
|
||||||
strict_param_validation?: boolean;
|
strict_param_validation?: boolean;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { WebsocketClient, wsKeySpotPublic } from '../src/websocket-client';
|
|||||||
market: market,
|
market: market,
|
||||||
livenet: true,
|
livenet: true,
|
||||||
restOptions: {
|
restOptions: {
|
||||||
// disable_time_sync: true,
|
// enable_time_sync: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
logger
|
logger
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "bybit-api",
|
"name": "bybit-api",
|
||||||
"version": "2.2.2",
|
"version": "2.3.0",
|
||||||
"description": "Node.js connector for Bybit's REST APIs and WebSockets, with TypeScript & integration tests.",
|
"description": "Node.js connector for Bybit's REST APIs and WebSockets, with TypeScript & integration tests.",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
|
|||||||
@@ -61,10 +61,13 @@ export default abstract class BaseRestClient {
|
|||||||
|
|
||||||
this.options = {
|
this.options = {
|
||||||
recv_window: 5000,
|
recv_window: 5000,
|
||||||
// how often to sync time drift with bybit servers
|
|
||||||
sync_interval_ms: 3600000,
|
/** Throw errors if any params are undefined */
|
||||||
// if true, we'll throw errors if any params are undefined
|
|
||||||
strict_param_validation: false,
|
strict_param_validation: false,
|
||||||
|
/** Disable time sync by default */
|
||||||
|
enable_time_sync: false,
|
||||||
|
/** How often to sync time drift with bybit servers (if time sync is enabled) */
|
||||||
|
sync_interval_ms: 3600000,
|
||||||
...options,
|
...options,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -86,7 +89,7 @@ export default abstract class BaseRestClient {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.disable_time_sync !== true) {
|
if (this.options.enable_time_sync) {
|
||||||
this.syncTime();
|
this.syncTime();
|
||||||
setInterval(this.syncTime.bind(this), +this.options.sync_interval_ms!);
|
setInterval(this.syncTime.bind(this), +this.options.sync_interval_ms!);
|
||||||
}
|
}
|
||||||
@@ -254,10 +257,11 @@ export default abstract class BaseRestClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger time sync and store promise
|
* Trigger time sync and store promise. Use force: true, if automatic time sync is disabled
|
||||||
*/
|
*/
|
||||||
private syncTime(): Promise<any> {
|
private syncTime(force?: boolean): Promise<any> {
|
||||||
if (this.options.disable_time_sync === true) {
|
if (!force && !this.options.enable_time_sync) {
|
||||||
|
this.timeOffset = 0;
|
||||||
return Promise.resolve(false);
|
return Promise.resolve(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
export interface RestClientOptions {
|
export interface RestClientOptions {
|
||||||
// override the max size of the request window (in ms)
|
/** Override the max size of the request window (in ms) */
|
||||||
recv_window?: number;
|
recv_window?: number;
|
||||||
|
|
||||||
// how often to sync time drift with bybit servers
|
/** @deprecated Time sync is now disabled by default. To re-enable it, use enable_time_sync instead. */
|
||||||
sync_interval_ms?: number | string;
|
|
||||||
|
|
||||||
// Default: false. Disable above sync mechanism if true.
|
|
||||||
disable_time_sync?: boolean;
|
disable_time_sync?: boolean;
|
||||||
|
|
||||||
// Default: false. If true, we'll throw errors if any params are undefined
|
/** Disabled by default. This can help on machines with consistent latency problems. */
|
||||||
|
enable_time_sync?: boolean;
|
||||||
|
|
||||||
|
/** How often to sync time drift with bybit servers */
|
||||||
|
sync_interval_ms?: number | string;
|
||||||
|
|
||||||
|
/** Default: false. If true, we'll throw errors if any params are undefined */
|
||||||
strict_param_validation?: boolean;
|
strict_param_validation?: boolean;
|
||||||
|
|
||||||
// Optionally override API protocol + domain
|
/**
|
||||||
// e.g 'https://api.bytick.com'
|
* Optionally override API protocol + domain
|
||||||
|
* e.g baseUrl: 'https://api.bytick.com'
|
||||||
|
**/
|
||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
|
|
||||||
// Default: true. whether to try and post-process request exceptions.
|
/** Default: true. whether to try and post-process request exceptions. */
|
||||||
parse_exceptions?: boolean;
|
parse_exceptions?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 { SpotClient } from './spot-client';
|
||||||
import { KlineInterval } from './types/shared';
|
import { KlineInterval } from './types/shared';
|
||||||
import { signMessage } from './util/node-support';
|
import { signMessage } from './util/node-support';
|
||||||
import {
|
import {
|
||||||
@@ -148,6 +149,8 @@ export interface WSClientConfigurableOptions {
|
|||||||
restOptions?: RestClientOptions;
|
restOptions?: RestClientOptions;
|
||||||
requestOptions?: any;
|
requestOptions?: any;
|
||||||
wsUrl?: string;
|
wsUrl?: string;
|
||||||
|
/** If true, fetch server time before trying to authenticate (disabled by default) */
|
||||||
|
fetchTimeOffsetBeforeAuth?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WebsocketClientOptions extends WSClientConfigurableOptions {
|
export interface WebsocketClientOptions extends WSClientConfigurableOptions {
|
||||||
@@ -229,7 +232,7 @@ function resolveMarket(options: WSClientConfigurableOptions): APIMarket {
|
|||||||
|
|
||||||
export class WebsocketClient extends EventEmitter {
|
export class WebsocketClient extends EventEmitter {
|
||||||
private logger: typeof DefaultLogger;
|
private logger: typeof DefaultLogger;
|
||||||
private restClient: InverseClient | LinearClient;
|
private restClient: InverseClient | LinearClient | SpotClient;
|
||||||
private options: WebsocketClientOptions;
|
private options: WebsocketClientOptions;
|
||||||
private wsStore: WsStore;
|
private wsStore: WsStore;
|
||||||
|
|
||||||
@@ -247,6 +250,7 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
pongTimeout: 1000,
|
pongTimeout: 1000,
|
||||||
pingInterval: 10000,
|
pingInterval: 10000,
|
||||||
reconnectTimeout: 500,
|
reconnectTimeout: 500,
|
||||||
|
fetchTimeOffsetBeforeAuth: false,
|
||||||
...options,
|
...options,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -263,8 +267,7 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
this.options.requestOptions
|
this.options.requestOptions
|
||||||
);
|
);
|
||||||
} else if (this.isSpot()) {
|
} else if (this.isSpot()) {
|
||||||
// TODO: spot client
|
this.restClient = new SpotClient(
|
||||||
this.restClient = new LinearClient(
|
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
this.isLivenet(),
|
this.isLivenet(),
|
||||||
@@ -474,7 +477,9 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
wsKey,
|
wsKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
const timeOffset = await this.restClient.fetchTimeOffset();
|
const timeOffset = this.options.fetchTimeOffsetBeforeAuth
|
||||||
|
? await this.restClient.fetchTimeOffset()
|
||||||
|
: 0;
|
||||||
|
|
||||||
const params: any = {
|
const params: any = {
|
||||||
api_key: this.options.key,
|
api_key: this.options.key,
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ describe('Public Inverse-Futures REST API GET Endpoints', () => {
|
|||||||
const API_KEY = process.env.API_KEY_COM;
|
const API_KEY = process.env.API_KEY_COM;
|
||||||
const API_SECRET = process.env.API_SECRET_COM;
|
const API_SECRET = process.env.API_SECRET_COM;
|
||||||
|
|
||||||
const api = new InverseFuturesClient(API_KEY, API_SECRET, useLivenet, {
|
const api = new InverseFuturesClient(API_KEY, API_SECRET, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
|
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
|
||||||
const symbol = 'BTCUSDU22';
|
const symbol = 'BTCUSDU22';
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
});
|
});
|
||||||
|
|
||||||
const api = new InverseFuturesClient(API_KEY, API_SECRET, useLivenet, {
|
const api = new InverseFuturesClient(API_KEY, API_SECRET, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
|
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
|
||||||
const symbol = 'BTCUSDU22';
|
const symbol = 'BTCUSDU22';
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import {
|
|||||||
|
|
||||||
describe('Public Inverse Futures REST API Endpoints', () => {
|
describe('Public Inverse Futures REST API Endpoints', () => {
|
||||||
const useLivenet = true;
|
const useLivenet = true;
|
||||||
const api = new InverseFuturesClient(undefined, undefined, useLivenet, {
|
const api = new InverseFuturesClient(undefined, undefined, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSD';
|
const symbol = 'BTCUSD';
|
||||||
const interval = '15';
|
const interval = '15';
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ describe('Private Inverse REST API Endpoints', () => {
|
|||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
});
|
});
|
||||||
|
|
||||||
const api = new InverseClient(API_KEY, API_SECRET, useLivenet, {
|
const api = new InverseClient(API_KEY, API_SECRET, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSD';
|
const symbol = 'BTCUSD';
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ describe('Private Inverse REST API Endpoints', () => {
|
|||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
});
|
});
|
||||||
|
|
||||||
const api = new InverseClient(API_KEY, API_SECRET, useLivenet, {
|
const api = new InverseClient(API_KEY, API_SECRET, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSD';
|
const symbol = 'BTCUSD';
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import {
|
|||||||
|
|
||||||
describe('Public Inverse REST API Endpoints', () => {
|
describe('Public Inverse REST API Endpoints', () => {
|
||||||
const useLivenet = true;
|
const useLivenet = true;
|
||||||
const api = new InverseClient(undefined, undefined, useLivenet, {
|
const api = new InverseClient(undefined, undefined, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSD';
|
const symbol = 'BTCUSD';
|
||||||
const interval = '15';
|
const interval = '15';
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ describe('Public Linear REST API GET Endpoints', () => {
|
|||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
});
|
});
|
||||||
|
|
||||||
const api = new LinearClient(API_KEY, API_SECRET, useLivenet, {
|
const api = new LinearClient(API_KEY, API_SECRET, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSDT';
|
const symbol = 'BTCUSDT';
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
});
|
});
|
||||||
|
|
||||||
const api = new LinearClient(API_KEY, API_SECRET, useLivenet, {
|
const api = new LinearClient(API_KEY, API_SECRET, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
|
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
|
||||||
const symbol = 'BTCUSDT';
|
const symbol = 'BTCUSDT';
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import {
|
|||||||
|
|
||||||
describe('Public Linear REST API Endpoints', () => {
|
describe('Public Linear REST API Endpoints', () => {
|
||||||
const useLivenet = true;
|
const useLivenet = true;
|
||||||
const api = new LinearClient(undefined, undefined, useLivenet, {
|
const api = new LinearClient(undefined, undefined, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSDT';
|
const symbol = 'BTCUSDT';
|
||||||
const interval = '15';
|
const interval = '15';
|
||||||
|
|||||||
@@ -16,9 +16,7 @@ describe('Private Spot REST API Endpoints', () => {
|
|||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
});
|
});
|
||||||
|
|
||||||
const api = new SpotClient(API_KEY, API_SECRET, useLivenet, {
|
const api = new SpotClient(API_KEY, API_SECRET, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSDT';
|
const symbol = 'BTCUSDT';
|
||||||
const interval = '15m';
|
const interval = '15m';
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
});
|
});
|
||||||
|
|
||||||
const api = new SpotClient(API_KEY, API_SECRET, useLivenet, {
|
const api = new SpotClient(API_KEY, API_SECRET, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
|
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
|
||||||
const symbol = 'BTCUSDT';
|
const symbol = 'BTCUSDT';
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import {
|
|||||||
|
|
||||||
describe('Public Spot REST API Endpoints', () => {
|
describe('Public Spot REST API Endpoints', () => {
|
||||||
const useLivenet = true;
|
const useLivenet = true;
|
||||||
const api = new SpotClient(undefined, undefined, useLivenet, {
|
const api = new SpotClient(undefined, undefined, useLivenet);
|
||||||
disable_time_sync: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSDT';
|
const symbol = 'BTCUSDT';
|
||||||
const interval = '15m';
|
const interval = '15m';
|
||||||
|
|||||||
Reference in New Issue
Block a user