public usdc perp ws test

This commit is contained in:
tiagosiebler
2022-09-16 13:25:25 +01:00
parent d2ba5d3e01
commit 9b673f08d5
6 changed files with 139 additions and 12 deletions

View File

@@ -3,13 +3,15 @@ import { LinearClient } from '../linear-client';
import { SpotClient } from '../spot-client'; import { SpotClient } from '../spot-client';
import { SpotClientV3 } from '../spot-client-v3'; import { SpotClientV3 } from '../spot-client-v3';
import { USDCOptionClient } from '../usdc-option-client'; import { USDCOptionClient } from '../usdc-option-client';
import { USDCPerpetualClient } from '../usdc-perpetual-client';
export type RESTClient = export type RESTClient =
| InverseClient | InverseClient
| LinearClient | LinearClient
| SpotClient | SpotClient
| SpotClientV3 | SpotClientV3
| USDCOptionClient; | USDCOptionClient
| USDCPerpetualClient;
export type numberInString = string; export type numberInString = string;

View File

@@ -1,7 +1,13 @@
import { RestClientOptions, WS_KEY_MAP } from '../util'; import { RestClientOptions, WS_KEY_MAP } from '../util';
/** For spot markets, spotV3 is recommended */ /** 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 // Same as inverse futures
export type WsPublicInverseTopic = export type WsPublicInverseTopic =

View File

@@ -69,6 +69,18 @@ export const WS_BASE_URL_MAP: Record<
testnet: 'wss://stream-testnet.bybit.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',
},
},
}; };
export const WS_KEY_MAP = { export const WS_KEY_MAP = {
@@ -81,8 +93,8 @@ export const WS_KEY_MAP = {
spotV3Public: 'spotV3Public', spotV3Public: 'spotV3Public',
usdcOptionPrivate: 'usdcOptionPrivate', usdcOptionPrivate: 'usdcOptionPrivate',
usdcOptionPublic: 'usdcOptionPublic', usdcOptionPublic: 'usdcOptionPublic',
// usdcPerpPrivate: 'usdcPerpPrivate', usdcPerpPrivate: 'usdcPerpPrivate',
// usdcPerpPublic: 'usdcPerpPublic', usdcPerpPublic: 'usdcPerpPublic',
} as const; } as const;
export const WS_AUTH_ON_CONNECT_KEYS: WsKey[] = [WS_KEY_MAP.spotV3Private]; 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.spotPublic,
WS_KEY_MAP.spotV3Public, WS_KEY_MAP.spotV3Public,
WS_KEY_MAP.usdcOptionPublic, WS_KEY_MAP.usdcOptionPublic,
WS_KEY_MAP.usdcPerpPublic,
] as string[]; ] as string[];
/** Used to automatically determine if a sub request should be to the public or private ws (when there's two) */ /** 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.usdcOptionPrivate
: WS_KEY_MAP.usdcOptionPublic; : WS_KEY_MAP.usdcOptionPublic;
} }
case 'usdcPerp': {
return isPrivateTopic
? WS_KEY_MAP.usdcPerpPrivate
: WS_KEY_MAP.usdcPerpPublic;
}
default: { default: {
throw neverGuard(market, `getWsKeyForTopic(): Unhandled market`); throw neverGuard(market, `getWsKeyForTopic(): Unhandled market`);
} }

View File

@@ -32,6 +32,7 @@ import {
neverGuard, neverGuard,
} from './util'; } from './util';
import { USDCOptionClient } from './usdc-option-client'; import { USDCOptionClient } from './usdc-option-client';
import { USDCPerpetualClient } from './usdc-perpetual-client';
const loggerCategory = { category: 'bybit-ws' }; const loggerCategory = { category: 'bybit-ws' };
@@ -165,6 +166,17 @@ export class WebsocketClient extends EventEmitter {
this.connectPublic(); this.connectPublic();
break; break;
} }
case 'usdcPerp': {
this.restClient = new USDCPerpetualClient(
undefined,
undefined,
!this.isTestnet(),
this.options.restOptions,
this.options.requestOptions
);
this.connectPublic();
break;
}
default: { default: {
throw neverGuard( throw neverGuard(
this.options.market, this.options.market,
@@ -223,7 +235,8 @@ export class WebsocketClient extends EventEmitter {
case 'linear': case 'linear':
case 'spot': case 'spot':
case 'spotv3': case 'spotv3':
case 'usdcOption': { case 'usdcOption':
case 'usdcPerp': {
return [this.connectPublic(), this.connectPrivate()]; return [this.connectPublic(), this.connectPrivate()];
} }
default: { default: {
@@ -249,6 +262,9 @@ export class WebsocketClient extends EventEmitter {
case 'usdcOption': { case 'usdcOption': {
return this.connect(WS_KEY_MAP.usdcOptionPublic); return this.connect(WS_KEY_MAP.usdcOptionPublic);
} }
case 'usdcPerp': {
return this.connect(WS_KEY_MAP.usdcPerpPublic);
}
default: { default: {
throw neverGuard( throw neverGuard(
this.options.market, this.options.market,
@@ -275,6 +291,9 @@ export class WebsocketClient extends EventEmitter {
case 'usdcOption': { case 'usdcOption': {
return this.connect(WS_KEY_MAP.usdcOptionPrivate); return this.connect(WS_KEY_MAP.usdcOptionPrivate);
} }
case 'usdcPerp': {
return this.connect(WS_KEY_MAP.usdcPerpPrivate);
}
default: { default: {
throw neverGuard( throw neverGuard(
this.options.market, this.options.market,
@@ -719,12 +738,12 @@ export class WebsocketClient extends EventEmitter {
case WS_KEY_MAP.usdcOptionPrivate: { case WS_KEY_MAP.usdcOptionPrivate: {
return WS_BASE_URL_MAP.usdcOption.private[networkKey]; return WS_BASE_URL_MAP.usdcOption.private[networkKey];
} }
// case WS_KEY_MAP.usdcPerpPublic: { case WS_KEY_MAP.usdcPerpPublic: {
// return WS_BASE_URL_MAP.usdcOption.public[networkKey]; return WS_BASE_URL_MAP.usdcPerp.public[networkKey];
// } }
// case WS_KEY_MAP.usdcPerpPrivate: { case WS_KEY_MAP.usdcPerpPrivate: {
// return WS_BASE_URL_MAP.usdcOption.private[networkKey]; return WS_BASE_URL_MAP.usdcPerp.private[networkKey];
// } }
default: { default: {
this.logger.error('getWsUrl(): Unhandled wsKey: ', { this.logger.error('getWsUrl(): Unhandled wsKey: ', {
...loggerCategory, ...loggerCategory,

View File

@@ -22,11 +22,11 @@ describe('Public USDC Option Websocket Client', () => {
wsClientOptions, wsClientOptions,
getSilentLogger('expectSuccessNoAuth') getSilentLogger('expectSuccessNoAuth')
); );
// logAllEvents(wsClient);
}); });
beforeEach(() => { beforeEach(() => {
wsClient.removeAllListeners(); wsClient.removeAllListeners();
// logAllEvents(wsClient);
}); });
afterAll(() => { afterAll(() => {

View File

@@ -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();
}
});
});