From 43c1f91b50765279f4b231b822e16454a3c2fdd2 Mon Sep 17 00:00:00 2001 From: tiagosiebler Date: Tue, 12 Jul 2022 11:32:17 +0100 Subject: [PATCH] v2.3.0: fix(#158), disable time sync by default. Optionally avoid hitting time API when connecting authenticated websocket. --- README.md | 4 ++-- examples/ws-private.ts | 2 +- package.json | 2 +- src/util/BaseRestClient.ts | 18 ++++++++++------- src/util/requestUtils.ts | 23 +++++++++++++--------- src/websocket-client.ts | 13 ++++++++---- test/inverse-futures/private.read.test.ts | 4 +--- test/inverse-futures/private.write.test.ts | 4 +--- test/inverse-futures/public.test.ts | 4 +--- test/inverse/private.read.test.ts | 4 +--- test/inverse/private.write.test.ts | 4 +--- test/inverse/public.test.ts | 4 +--- test/linear/private.read.test.ts | 4 +--- test/linear/private.write.test.ts | 4 +--- test/linear/public.test.ts | 4 +--- test/spot/private.read.test.ts | 4 +--- test/spot/private.write.test.ts | 4 +--- test/spot/public.test.ts | 4 +--- 18 files changed, 50 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 82c1eca..c451745 100644 --- a/README.md +++ b/README.md @@ -64,10 +64,10 @@ const restClientOptions = { recv_window?: number; // 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. - disable_time_sync?: boolean; + enable_time_sync?: boolean; // Default: false. If true, we'll throw errors if any params are undefined strict_param_validation?: boolean; diff --git a/examples/ws-private.ts b/examples/ws-private.ts index 34e0685..51ce8d7 100644 --- a/examples/ws-private.ts +++ b/examples/ws-private.ts @@ -27,7 +27,7 @@ import { WebsocketClient, wsKeySpotPublic } from '../src/websocket-client'; market: market, livenet: true, restOptions: { - // disable_time_sync: true, + // enable_time_sync: true, }, }, logger diff --git a/package.json b/package.json index f50c778..e8e4092 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "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.", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/src/util/BaseRestClient.ts b/src/util/BaseRestClient.ts index c38f890..bd00855 100644 --- a/src/util/BaseRestClient.ts +++ b/src/util/BaseRestClient.ts @@ -61,10 +61,13 @@ export default abstract class BaseRestClient { this.options = { recv_window: 5000, - // how often to sync time drift with bybit servers - sync_interval_ms: 3600000, - // if true, we'll throw errors if any params are undefined + + /** Throw errors if any params are undefined */ 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, }; @@ -86,7 +89,7 @@ export default abstract class BaseRestClient { ); } - if (this.options.disable_time_sync !== true) { + if (this.options.enable_time_sync) { this.syncTime(); 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 { - if (this.options.disable_time_sync === true) { + private syncTime(force?: boolean): Promise { + if (!force && !this.options.enable_time_sync) { + this.timeOffset = 0; return Promise.resolve(false); } diff --git a/src/util/requestUtils.ts b/src/util/requestUtils.ts index 621fb3b..f8add05 100644 --- a/src/util/requestUtils.ts +++ b/src/util/requestUtils.ts @@ -1,21 +1,26 @@ 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; - // how often to sync time drift with bybit servers - sync_interval_ms?: number | string; - - // Default: false. Disable above sync mechanism if true. + /** @deprecated Time sync is now disabled by default. To re-enable it, use enable_time_sync instead. */ 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; - // 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; - // Default: true. whether to try and post-process request exceptions. + /** Default: true. whether to try and post-process request exceptions. */ parse_exceptions?: boolean; } diff --git a/src/websocket-client.ts b/src/websocket-client.ts index d9dd4c6..939058c 100644 --- a/src/websocket-client.ts +++ b/src/websocket-client.ts @@ -4,6 +4,7 @@ import WebSocket from 'isomorphic-ws'; import { InverseClient } from './inverse-client'; import { LinearClient } from './linear-client'; import { DefaultLogger } from './logger'; +import { SpotClient } from './spot-client'; import { KlineInterval } from './types/shared'; import { signMessage } from './util/node-support'; import { @@ -148,6 +149,8 @@ export interface WSClientConfigurableOptions { restOptions?: RestClientOptions; requestOptions?: any; wsUrl?: string; + /** If true, fetch server time before trying to authenticate (disabled by default) */ + fetchTimeOffsetBeforeAuth?: boolean; } export interface WebsocketClientOptions extends WSClientConfigurableOptions { @@ -229,7 +232,7 @@ function resolveMarket(options: WSClientConfigurableOptions): APIMarket { export class WebsocketClient extends EventEmitter { private logger: typeof DefaultLogger; - private restClient: InverseClient | LinearClient; + private restClient: InverseClient | LinearClient | SpotClient; private options: WebsocketClientOptions; private wsStore: WsStore; @@ -247,6 +250,7 @@ export class WebsocketClient extends EventEmitter { pongTimeout: 1000, pingInterval: 10000, reconnectTimeout: 500, + fetchTimeOffsetBeforeAuth: false, ...options, }; @@ -263,8 +267,7 @@ export class WebsocketClient extends EventEmitter { this.options.requestOptions ); } else if (this.isSpot()) { - // TODO: spot client - this.restClient = new LinearClient( + this.restClient = new SpotClient( undefined, undefined, this.isLivenet(), @@ -474,7 +477,9 @@ export class WebsocketClient extends EventEmitter { wsKey, }); - const timeOffset = await this.restClient.fetchTimeOffset(); + const timeOffset = this.options.fetchTimeOffsetBeforeAuth + ? await this.restClient.fetchTimeOffset() + : 0; const params: any = { api_key: this.options.key, diff --git a/test/inverse-futures/private.read.test.ts b/test/inverse-futures/private.read.test.ts index 8fd5ec8..6e24cf5 100644 --- a/test/inverse-futures/private.read.test.ts +++ b/test/inverse-futures/private.read.test.ts @@ -6,9 +6,7 @@ describe('Public Inverse-Futures REST API GET Endpoints', () => { const API_KEY = process.env.API_KEY_COM; const API_SECRET = process.env.API_SECRET_COM; - const api = new InverseFuturesClient(API_KEY, API_SECRET, useLivenet, { - disable_time_sync: true, - }); + const api = new InverseFuturesClient(API_KEY, API_SECRET, useLivenet); // 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'; diff --git a/test/inverse-futures/private.write.test.ts b/test/inverse-futures/private.write.test.ts index bea07a6..257fe36 100644 --- a/test/inverse-futures/private.write.test.ts +++ b/test/inverse-futures/private.write.test.ts @@ -11,9 +11,7 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => { expect(API_SECRET).toStrictEqual(expect.any(String)); }); - const api = new InverseFuturesClient(API_KEY, API_SECRET, useLivenet, { - disable_time_sync: true, - }); + const api = new InverseFuturesClient(API_KEY, API_SECRET, useLivenet); // 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'; diff --git a/test/inverse-futures/public.test.ts b/test/inverse-futures/public.test.ts index 5a99aa4..24ba232 100644 --- a/test/inverse-futures/public.test.ts +++ b/test/inverse-futures/public.test.ts @@ -7,9 +7,7 @@ import { describe('Public Inverse Futures REST API Endpoints', () => { const useLivenet = true; - const api = new InverseFuturesClient(undefined, undefined, useLivenet, { - disable_time_sync: true, - }); + const api = new InverseFuturesClient(undefined, undefined, useLivenet); const symbol = 'BTCUSD'; const interval = '15'; diff --git a/test/inverse/private.read.test.ts b/test/inverse/private.read.test.ts index 42b4271..e1b847c 100644 --- a/test/inverse/private.read.test.ts +++ b/test/inverse/private.read.test.ts @@ -11,9 +11,7 @@ describe('Private Inverse REST API Endpoints', () => { expect(API_SECRET).toStrictEqual(expect.any(String)); }); - const api = new InverseClient(API_KEY, API_SECRET, useLivenet, { - disable_time_sync: true, - }); + const api = new InverseClient(API_KEY, API_SECRET, useLivenet); const symbol = 'BTCUSD'; diff --git a/test/inverse/private.write.test.ts b/test/inverse/private.write.test.ts index 7da7662..4fa1eb0 100644 --- a/test/inverse/private.write.test.ts +++ b/test/inverse/private.write.test.ts @@ -12,9 +12,7 @@ describe('Private Inverse REST API Endpoints', () => { expect(API_SECRET).toStrictEqual(expect.any(String)); }); - const api = new InverseClient(API_KEY, API_SECRET, useLivenet, { - disable_time_sync: true, - }); + const api = new InverseClient(API_KEY, API_SECRET, useLivenet); const symbol = 'BTCUSD'; diff --git a/test/inverse/public.test.ts b/test/inverse/public.test.ts index a61cebf..310641a 100644 --- a/test/inverse/public.test.ts +++ b/test/inverse/public.test.ts @@ -7,9 +7,7 @@ import { describe('Public Inverse REST API Endpoints', () => { const useLivenet = true; - const api = new InverseClient(undefined, undefined, useLivenet, { - disable_time_sync: true, - }); + const api = new InverseClient(undefined, undefined, useLivenet); const symbol = 'BTCUSD'; const interval = '15'; diff --git a/test/linear/private.read.test.ts b/test/linear/private.read.test.ts index fea1db4..5b5179b 100644 --- a/test/linear/private.read.test.ts +++ b/test/linear/private.read.test.ts @@ -11,9 +11,7 @@ describe('Public Linear REST API GET Endpoints', () => { expect(API_SECRET).toStrictEqual(expect.any(String)); }); - const api = new LinearClient(API_KEY, API_SECRET, useLivenet, { - disable_time_sync: true, - }); + const api = new LinearClient(API_KEY, API_SECRET, useLivenet); const symbol = 'BTCUSDT'; diff --git a/test/linear/private.write.test.ts b/test/linear/private.write.test.ts index 9a987ae..9747029 100644 --- a/test/linear/private.write.test.ts +++ b/test/linear/private.write.test.ts @@ -11,9 +11,7 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => { expect(API_SECRET).toStrictEqual(expect.any(String)); }); - const api = new LinearClient(API_KEY, API_SECRET, useLivenet, { - disable_time_sync: true, - }); + const api = new LinearClient(API_KEY, API_SECRET, useLivenet); // 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'; diff --git a/test/linear/public.test.ts b/test/linear/public.test.ts index 6b6cadd..169f93f 100644 --- a/test/linear/public.test.ts +++ b/test/linear/public.test.ts @@ -7,9 +7,7 @@ import { describe('Public Linear REST API Endpoints', () => { const useLivenet = true; - const api = new LinearClient(undefined, undefined, useLivenet, { - disable_time_sync: true, - }); + const api = new LinearClient(undefined, undefined, useLivenet); const symbol = 'BTCUSDT'; const interval = '15'; diff --git a/test/spot/private.read.test.ts b/test/spot/private.read.test.ts index 77762d6..34a6870 100644 --- a/test/spot/private.read.test.ts +++ b/test/spot/private.read.test.ts @@ -16,9 +16,7 @@ describe('Private Spot REST API Endpoints', () => { expect(API_SECRET).toStrictEqual(expect.any(String)); }); - const api = new SpotClient(API_KEY, API_SECRET, useLivenet, { - disable_time_sync: true, - }); + const api = new SpotClient(API_KEY, API_SECRET, useLivenet); const symbol = 'BTCUSDT'; const interval = '15m'; diff --git a/test/spot/private.write.test.ts b/test/spot/private.write.test.ts index 811d9e4..1140755 100644 --- a/test/spot/private.write.test.ts +++ b/test/spot/private.write.test.ts @@ -11,9 +11,7 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => { expect(API_SECRET).toStrictEqual(expect.any(String)); }); - const api = new SpotClient(API_KEY, API_SECRET, useLivenet, { - disable_time_sync: true, - }); + const api = new SpotClient(API_KEY, API_SECRET, useLivenet); // 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'; diff --git a/test/spot/public.test.ts b/test/spot/public.test.ts index 0aa7fb2..c3c7c76 100644 --- a/test/spot/public.test.ts +++ b/test/spot/public.test.ts @@ -7,9 +7,7 @@ import { describe('Public Spot REST API Endpoints', () => { const useLivenet = true; - const api = new SpotClient(undefined, undefined, useLivenet, { - disable_time_sync: true, - }); + const api = new SpotClient(undefined, undefined, useLivenet); const symbol = 'BTCUSDT'; const interval = '15m';