From 9b673f08d5b331e778a7f36b44a15197a2e57a88 Mon Sep 17 00:00:00 2001 From: tiagosiebler Date: Fri, 16 Sep 2022 13:25:25 +0100 Subject: [PATCH] public usdc perp ws test --- src/types/shared.ts | 4 +- src/types/websockets.ts | 8 ++- src/util/websocket-util.ts | 22 ++++++- src/websocket-client.ts | 33 ++++++++--- test/usdc/options/ws.public.test.ts | 2 +- test/usdc/perpetual/ws.public.test.ts | 82 +++++++++++++++++++++++++++ 6 files changed, 139 insertions(+), 12 deletions(-) create mode 100644 test/usdc/perpetual/ws.public.test.ts diff --git a/src/types/shared.ts b/src/types/shared.ts index 77bd21f..10aa83d 100644 --- a/src/types/shared.ts +++ b/src/types/shared.ts @@ -3,13 +3,15 @@ import { LinearClient } from '../linear-client'; import { SpotClient } from '../spot-client'; import { SpotClientV3 } from '../spot-client-v3'; import { USDCOptionClient } from '../usdc-option-client'; +import { USDCPerpetualClient } from '../usdc-perpetual-client'; export type RESTClient = | InverseClient | LinearClient | SpotClient | SpotClientV3 - | USDCOptionClient; + | USDCOptionClient + | USDCPerpetualClient; export type numberInString = string; diff --git a/src/types/websockets.ts b/src/types/websockets.ts index 67b86d4..a44a737 100644 --- a/src/types/websockets.ts +++ b/src/types/websockets.ts @@ -1,7 +1,13 @@ import { RestClientOptions, WS_KEY_MAP } from '../util'; /** For spot markets, spotV3 is recommended */ -export type APIMarket = 'inverse' | 'linear' | 'spot' | 'spotv3' | 'usdcOption'; +export type APIMarket = + | 'inverse' + | 'linear' + | 'spot' + | 'spotv3' + | 'usdcOption' + | 'usdcPerp'; // Same as inverse futures export type WsPublicInverseTopic = diff --git a/src/util/websocket-util.ts b/src/util/websocket-util.ts index 7efc262..7507529 100644 --- a/src/util/websocket-util.ts +++ b/src/util/websocket-util.ts @@ -69,6 +69,18 @@ export const WS_BASE_URL_MAP: Record< 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', + }, + }, }; export const WS_KEY_MAP = { @@ -81,8 +93,8 @@ export const WS_KEY_MAP = { spotV3Public: 'spotV3Public', usdcOptionPrivate: 'usdcOptionPrivate', usdcOptionPublic: 'usdcOptionPublic', - // usdcPerpPrivate: 'usdcPerpPrivate', - // usdcPerpPublic: 'usdcPerpPublic', + usdcPerpPrivate: 'usdcPerpPrivate', + usdcPerpPublic: 'usdcPerpPublic', } as const; export const WS_AUTH_ON_CONNECT_KEYS: WsKey[] = [WS_KEY_MAP.spotV3Private]; @@ -92,6 +104,7 @@ export const PUBLIC_WS_KEYS = [ WS_KEY_MAP.spotPublic, WS_KEY_MAP.spotV3Public, WS_KEY_MAP.usdcOptionPublic, + WS_KEY_MAP.usdcPerpPublic, ] as string[]; /** Used to automatically determine if a sub request should be to the public or private ws (when there's two) */ @@ -158,6 +171,11 @@ export function getWsKeyForTopic( ? WS_KEY_MAP.usdcOptionPrivate : WS_KEY_MAP.usdcOptionPublic; } + case 'usdcPerp': { + return isPrivateTopic + ? WS_KEY_MAP.usdcPerpPrivate + : WS_KEY_MAP.usdcPerpPublic; + } default: { throw neverGuard(market, `getWsKeyForTopic(): Unhandled market`); } diff --git a/src/websocket-client.ts b/src/websocket-client.ts index 99610cf..fe73c3e 100644 --- a/src/websocket-client.ts +++ b/src/websocket-client.ts @@ -32,6 +32,7 @@ import { neverGuard, } from './util'; import { USDCOptionClient } from './usdc-option-client'; +import { USDCPerpetualClient } from './usdc-perpetual-client'; const loggerCategory = { category: 'bybit-ws' }; @@ -165,6 +166,17 @@ export class WebsocketClient extends EventEmitter { this.connectPublic(); break; } + case 'usdcPerp': { + this.restClient = new USDCPerpetualClient( + undefined, + undefined, + !this.isTestnet(), + this.options.restOptions, + this.options.requestOptions + ); + this.connectPublic(); + break; + } default: { throw neverGuard( this.options.market, @@ -223,7 +235,8 @@ export class WebsocketClient extends EventEmitter { case 'linear': case 'spot': case 'spotv3': - case 'usdcOption': { + case 'usdcOption': + case 'usdcPerp': { return [this.connectPublic(), this.connectPrivate()]; } default: { @@ -249,6 +262,9 @@ export class WebsocketClient extends EventEmitter { case 'usdcOption': { return this.connect(WS_KEY_MAP.usdcOptionPublic); } + case 'usdcPerp': { + return this.connect(WS_KEY_MAP.usdcPerpPublic); + } default: { throw neverGuard( this.options.market, @@ -275,6 +291,9 @@ export class WebsocketClient extends EventEmitter { case 'usdcOption': { return this.connect(WS_KEY_MAP.usdcOptionPrivate); } + case 'usdcPerp': { + return this.connect(WS_KEY_MAP.usdcPerpPrivate); + } default: { throw neverGuard( this.options.market, @@ -719,12 +738,12 @@ export class WebsocketClient extends EventEmitter { case WS_KEY_MAP.usdcOptionPrivate: { return WS_BASE_URL_MAP.usdcOption.private[networkKey]; } - // case WS_KEY_MAP.usdcPerpPublic: { - // return WS_BASE_URL_MAP.usdcOption.public[networkKey]; - // } - // case WS_KEY_MAP.usdcPerpPrivate: { - // return WS_BASE_URL_MAP.usdcOption.private[networkKey]; - // } + case WS_KEY_MAP.usdcPerpPublic: { + return WS_BASE_URL_MAP.usdcPerp.public[networkKey]; + } + case WS_KEY_MAP.usdcPerpPrivate: { + return WS_BASE_URL_MAP.usdcPerp.private[networkKey]; + } default: { this.logger.error('getWsUrl(): Unhandled wsKey: ', { ...loggerCategory, diff --git a/test/usdc/options/ws.public.test.ts b/test/usdc/options/ws.public.test.ts index 8aeb862..0771099 100644 --- a/test/usdc/options/ws.public.test.ts +++ b/test/usdc/options/ws.public.test.ts @@ -22,11 +22,11 @@ describe('Public USDC Option Websocket Client', () => { wsClientOptions, getSilentLogger('expectSuccessNoAuth') ); - // logAllEvents(wsClient); }); beforeEach(() => { wsClient.removeAllListeners(); + // logAllEvents(wsClient); }); afterAll(() => { diff --git a/test/usdc/perpetual/ws.public.test.ts b/test/usdc/perpetual/ws.public.test.ts new file mode 100644 index 0000000..4707645 --- /dev/null +++ b/test/usdc/perpetual/ws.public.test.ts @@ -0,0 +1,82 @@ +import { + WebsocketClient, + WSClientConfigurableOptions, + WS_KEY_MAP, +} from '../../../src'; +import { + logAllEvents, + getSilentLogger, + waitForSocketEvent, + WS_OPEN_EVENT_PARTIAL, +} from '../../ws.util'; + +describe('Public USDC Perp Websocket Client', () => { + let wsClient: WebsocketClient; + + const wsClientOptions: WSClientConfigurableOptions = { + market: 'usdcPerp', + }; + + beforeAll(() => { + wsClient = new WebsocketClient( + wsClientOptions, + getSilentLogger('expectSuccessNoAuth') + ); + // logAllEvents(wsClient); + }); + + beforeEach(() => { + wsClient.removeAllListeners(); + // logAllEvents(wsClient); + }); + + afterAll(() => { + wsClient.closeAll(); + }); + + it('should open a public ws connection', async () => { + const wsOpenPromise = waitForSocketEvent(wsClient, 'open'); + + expect(wsOpenPromise).resolves.toMatchObject({ + event: WS_OPEN_EVENT_PARTIAL, + wsKey: WS_KEY_MAP.usdcPerpPublic, + }); + + await Promise.all([wsOpenPromise]); + }); + + it('should subscribe to public trade events', async () => { + const wsResponsePromise = waitForSocketEvent(wsClient, 'response'); + const wsUpdatePromise = waitForSocketEvent(wsClient, 'update'); + + const topic = 'orderBook_200.100ms.BTCPERP'; + wsClient.subscribe(topic); + + try { + expect(await wsResponsePromise).toMatchObject({ + success: true, + ret_msg: '', + request: { + op: 'subscribe', + args: [topic], + }, + }); + } catch (e) { + // sub failed + expect(e).toBeFalsy(); + } + + try { + expect(await wsUpdatePromise).toMatchSnapshot({ + crossSeq: expect.any(String), + data: { orderBook: expect.any(Array) }, + timestampE6: expect.any(String), + topic: topic, + type: 'snapshot', + }); + } catch (e) { + // no data + expect(e).toBeFalsy(); + } + }); +});