cleaning around tests
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { RestClientOptions, WS_KEY_MAP } from '../util';
|
import { RestClientOptions, WS_KEY_MAP } from '../util';
|
||||||
|
|
||||||
export type APIMarket = 'inverse' | 'linear' | 'spot'; //| 'v3';
|
export type APIMarket = 'inverse' | 'linear' | 'spot' | 'spotV3'; //| 'v3';
|
||||||
|
|
||||||
// Same as inverse futures
|
// Same as inverse futures
|
||||||
export type WsPublicInverseTopic =
|
export type WsPublicInverseTopic =
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { WsKey } from '../types';
|
import { APIMarket, WsKey } from '../types';
|
||||||
|
|
||||||
interface NetworkMapV3 {
|
interface NetworkMapV3 {
|
||||||
livenet: string;
|
livenet: string;
|
||||||
@@ -10,42 +10,52 @@ interface NetworkMapV3 {
|
|||||||
type PublicPrivateNetwork = 'public' | 'private';
|
type PublicPrivateNetwork = 'public' | 'private';
|
||||||
|
|
||||||
export const WS_BASE_URL_MAP: Record<
|
export const WS_BASE_URL_MAP: Record<
|
||||||
string,
|
APIMarket,
|
||||||
Record<PublicPrivateNetwork, NetworkMapV3>
|
Record<PublicPrivateNetwork, NetworkMapV3>
|
||||||
> = {
|
> = {
|
||||||
inverse: {
|
inverse: {
|
||||||
private: {
|
public: {
|
||||||
livenet: 'wss://stream.bybit.com/realtime',
|
livenet: 'wss://stream.bybit.com/realtime',
|
||||||
testnet: 'wss://stream-testnet.bybit.com/realtime',
|
testnet: 'wss://stream-testnet.bybit.com/realtime',
|
||||||
},
|
},
|
||||||
public: {
|
private: {
|
||||||
livenet: 'wss://stream.bybit.com/realtime',
|
livenet: 'wss://stream.bybit.com/realtime',
|
||||||
testnet: 'wss://stream-testnet.bybit.com/realtime',
|
testnet: 'wss://stream-testnet.bybit.com/realtime',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
linear: {
|
linear: {
|
||||||
private: {
|
|
||||||
livenet: 'wss://stream.bybit.com/realtime_private',
|
|
||||||
livenet2: 'wss://stream.bytick.com/realtime_private',
|
|
||||||
testnet: 'wss://stream-testnet.bybit.com/realtime_private',
|
|
||||||
},
|
|
||||||
public: {
|
public: {
|
||||||
livenet: 'wss://stream.bybit.com/realtime_public',
|
livenet: 'wss://stream.bybit.com/realtime_public',
|
||||||
livenet2: 'wss://stream.bytick.com/realtime_public',
|
livenet2: 'wss://stream.bytick.com/realtime_public',
|
||||||
testnet: 'wss://stream-testnet.bybit.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: {
|
spot: {
|
||||||
private: {
|
|
||||||
livenet: 'wss://stream.bybit.com/spot/ws',
|
|
||||||
testnet: 'wss://stream-testnet.bybit.com/spot/ws',
|
|
||||||
},
|
|
||||||
public: {
|
public: {
|
||||||
livenet: 'wss://stream.bybit.com/spot/quote/ws/v1',
|
livenet: 'wss://stream.bybit.com/spot/quote/ws/v1',
|
||||||
livenet2: 'wss://stream.bybit.com/spot/quote/ws/v2',
|
livenet2: 'wss://stream.bybit.com/spot/quote/ws/v2',
|
||||||
testnet: 'wss://stream-testnet.bybit.com/spot/quote/ws/v1',
|
testnet: 'wss://stream-testnet.bybit.com/spot/quote/ws/v1',
|
||||||
testnet2: 'wss://stream-testnet.bybit.com/spot/quote/ws/v2',
|
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',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -55,6 +65,8 @@ export const WS_KEY_MAP = {
|
|||||||
linearPublic: 'linearPublic',
|
linearPublic: 'linearPublic',
|
||||||
spotPrivate: 'spotPrivate',
|
spotPrivate: 'spotPrivate',
|
||||||
spotPublic: 'spotPublic',
|
spotPublic: 'spotPublic',
|
||||||
|
spotV3Private: 'spotV3Private',
|
||||||
|
spotV3Public: 'spotV3Public',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const PUBLIC_WS_KEYS = [
|
export const PUBLIC_WS_KEYS = [
|
||||||
@@ -77,7 +89,10 @@ export function getLinearWsKeyForTopic(topic: string): WsKey {
|
|||||||
return WS_KEY_MAP.linearPublic;
|
return WS_KEY_MAP.linearPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSpotWsKeyForTopic(topic: string): WsKey {
|
export function getSpotWsKeyForTopic(
|
||||||
|
topic: string,
|
||||||
|
apiVersion: 'v1' | 'v3'
|
||||||
|
): WsKey {
|
||||||
const privateTopics = [
|
const privateTopics = [
|
||||||
'position',
|
'position',
|
||||||
'execution',
|
'execution',
|
||||||
@@ -88,6 +103,13 @@ export function getSpotWsKeyForTopic(topic: string): WsKey {
|
|||||||
'ticketInfo',
|
'ticketInfo',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (apiVersion === 'v3') {
|
||||||
|
if (privateTopics.includes(topic)) {
|
||||||
|
return WS_KEY_MAP.spotV3Private;
|
||||||
|
}
|
||||||
|
return WS_KEY_MAP.spotV3Public;
|
||||||
|
}
|
||||||
|
|
||||||
if (privateTopics.includes(topic)) {
|
if (privateTopics.includes(topic)) {
|
||||||
return WS_KEY_MAP.spotPrivate;
|
return WS_KEY_MAP.spotPrivate;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,6 +136,17 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
this.connectPublic();
|
this.connectPublic();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'spotV3': {
|
||||||
|
this.restClient = new SpotClientV3(
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
!this.isTestnet(),
|
||||||
|
this.options.restOptions,
|
||||||
|
this.options.requestOptions
|
||||||
|
);
|
||||||
|
this.connectPublic();
|
||||||
|
break;
|
||||||
|
}
|
||||||
// if (this.isV3()) {
|
// if (this.isV3()) {
|
||||||
// this.restClient = new SpotClientV3(
|
// this.restClient = new SpotClientV3(
|
||||||
// undefined,
|
// undefined,
|
||||||
@@ -175,59 +186,6 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
// return this.options.market === 'v3';
|
// return this.options.market === 'v3';
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/**
|
|
||||||
* Add topic/topics to WS subscription list
|
|
||||||
*/
|
|
||||||
public subscribe(wsTopics: WsTopic[] | WsTopic) {
|
|
||||||
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: WsKey) => {
|
|
||||||
// if connected, send subscription request
|
|
||||||
if (
|
|
||||||
this.wsStore.isConnectionState(wsKey, 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,
|
|
||||||
WsConnectionStateEnum.CONNECTING
|
|
||||||
) &&
|
|
||||||
!this.wsStore.isConnectionState(
|
|
||||||
wsKey,
|
|
||||||
WsConnectionStateEnum.RECONNECTING
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return this.connect(wsKey);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove topic/topics from WS subscription list
|
|
||||||
*/
|
|
||||||
public unsubscribe(wsTopics: WsTopic[] | WsTopic) {
|
|
||||||
const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
|
|
||||||
topics.forEach((topic) =>
|
|
||||||
this.wsStore.deleteTopic(this.getWsKeyForTopic(topic), topic)
|
|
||||||
);
|
|
||||||
|
|
||||||
this.wsStore.getKeys().forEach((wsKey: WsKey) => {
|
|
||||||
// unsubscribe request only necessary if active connection exists
|
|
||||||
if (
|
|
||||||
this.wsStore.isConnectionState(wsKey, WsConnectionStateEnum.CONNECTED)
|
|
||||||
) {
|
|
||||||
this.requestUnsubscribeTopics(wsKey, topics);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public close(wsKey: WsKey) {
|
public close(wsKey: WsKey) {
|
||||||
this.logger.info('Closing connection', { ...loggerCategory, wsKey });
|
this.logger.info('Closing connection', { ...loggerCategory, wsKey });
|
||||||
this.setWsState(wsKey, WsConnectionStateEnum.CLOSING);
|
this.setWsState(wsKey, WsConnectionStateEnum.CLOSING);
|
||||||
@@ -263,6 +221,12 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
this.connect(WS_KEY_MAP.spotPrivate),
|
this.connect(WS_KEY_MAP.spotPrivate),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
case 'spotV3': {
|
||||||
|
return [
|
||||||
|
this.connect(WS_KEY_MAP.spotV3Public),
|
||||||
|
this.connect(WS_KEY_MAP.spotV3Private),
|
||||||
|
];
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(this.options.market, `connectAll(): Unhandled market`);
|
throw neverGuard(this.options.market, `connectAll(): Unhandled market`);
|
||||||
}
|
}
|
||||||
@@ -280,6 +244,9 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
case 'spot': {
|
case 'spot': {
|
||||||
return this.connect(WS_KEY_MAP.spotPublic);
|
return this.connect(WS_KEY_MAP.spotPublic);
|
||||||
}
|
}
|
||||||
|
case 'spotV3': {
|
||||||
|
return this.connect(WS_KEY_MAP.spotV3Public);
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(
|
throw neverGuard(
|
||||||
this.options.market,
|
this.options.market,
|
||||||
@@ -300,6 +267,9 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
case 'spot': {
|
case 'spot': {
|
||||||
return this.connect(WS_KEY_MAP.spotPrivate);
|
return this.connect(WS_KEY_MAP.spotPrivate);
|
||||||
}
|
}
|
||||||
|
case 'spotV3': {
|
||||||
|
return this.connect(WS_KEY_MAP.spotV3Private);
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(
|
throw neverGuard(
|
||||||
this.options.market,
|
this.options.market,
|
||||||
@@ -503,7 +473,7 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
this.tryWsSend(wsKey, wsMessage);
|
this.tryWsSend(wsKey, wsMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private tryWsSend(wsKey: WsKey, wsMessage: string) {
|
public tryWsSend(wsKey: WsKey, wsMessage: string) {
|
||||||
try {
|
try {
|
||||||
this.logger.silly(`Sending upstream ws message: `, {
|
this.logger.silly(`Sending upstream ws message: `, {
|
||||||
...loggerCategory,
|
...loggerCategory,
|
||||||
@@ -666,7 +636,13 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
return WS_BASE_URL_MAP.spot.public[networkKey];
|
return WS_BASE_URL_MAP.spot.public[networkKey];
|
||||||
}
|
}
|
||||||
case WS_KEY_MAP.spotPrivate: {
|
case WS_KEY_MAP.spotPrivate: {
|
||||||
return WS_BASE_URL_MAP.linear.private[networkKey];
|
return WS_BASE_URL_MAP.spot.private[networkKey];
|
||||||
|
}
|
||||||
|
case WS_KEY_MAP.spotV3Public: {
|
||||||
|
return WS_BASE_URL_MAP.spot.public[networkKey];
|
||||||
|
}
|
||||||
|
case WS_KEY_MAP.spotV3Private: {
|
||||||
|
return WS_BASE_URL_MAP.spot.private[networkKey];
|
||||||
}
|
}
|
||||||
case WS_KEY_MAP.inverse: {
|
case WS_KEY_MAP.inverse: {
|
||||||
// private and public are on the same WS connection
|
// private and public are on the same WS connection
|
||||||
@@ -691,7 +667,10 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
return getLinearWsKeyForTopic(topic);
|
return getLinearWsKeyForTopic(topic);
|
||||||
}
|
}
|
||||||
case 'spot': {
|
case 'spot': {
|
||||||
return getSpotWsKeyForTopic(topic);
|
return getSpotWsKeyForTopic(topic, 'v1');
|
||||||
|
}
|
||||||
|
case 'spotV3': {
|
||||||
|
return getSpotWsKeyForTopic(topic, 'v3');
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(
|
throw neverGuard(
|
||||||
@@ -708,6 +687,59 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add topic/topics to WS subscription list
|
||||||
|
*/
|
||||||
|
public subscribe(wsTopics: WsTopic[] | WsTopic) {
|
||||||
|
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: WsKey) => {
|
||||||
|
// if connected, send subscription request
|
||||||
|
if (
|
||||||
|
this.wsStore.isConnectionState(wsKey, 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,
|
||||||
|
WsConnectionStateEnum.CONNECTING
|
||||||
|
) &&
|
||||||
|
!this.wsStore.isConnectionState(
|
||||||
|
wsKey,
|
||||||
|
WsConnectionStateEnum.RECONNECTING
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return this.connect(wsKey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove topic/topics from WS subscription list
|
||||||
|
*/
|
||||||
|
public unsubscribe(wsTopics: WsTopic[] | WsTopic) {
|
||||||
|
const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
|
||||||
|
topics.forEach((topic) =>
|
||||||
|
this.wsStore.deleteTopic(this.getWsKeyForTopic(topic), topic)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.wsStore.getKeys().forEach((wsKey: WsKey) => {
|
||||||
|
// unsubscribe request only necessary if active connection exists
|
||||||
|
if (
|
||||||
|
this.wsStore.isConnectionState(wsKey, WsConnectionStateEnum.CONNECTED)
|
||||||
|
) {
|
||||||
|
this.requestUnsubscribeTopics(wsKey, topics);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: persistance for subbed topics. Look at ftx-api implementation.
|
// TODO: persistance for subbed topics. Look at ftx-api implementation.
|
||||||
public subscribePublicSpotTrades(symbol: string, binary?: boolean) {
|
public subscribePublicSpotTrades(symbol: string, binary?: boolean) {
|
||||||
if (!this.isSpot()) {
|
if (!this.isSpot()) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ describe('Public Inverse Perps Websocket Client', () => {
|
|||||||
wsClient.closeAll();
|
wsClient.closeAll();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should open a private ws connection', async () => {
|
it('should open a public ws connection', async () => {
|
||||||
const wsOpenPromise = waitForSocketEvent(wsClient, 'open');
|
const wsOpenPromise = waitForSocketEvent(wsClient, 'open');
|
||||||
|
|
||||||
expect(wsOpenPromise).resolves.toMatchObject({
|
expect(wsOpenPromise).resolves.toMatchObject({
|
||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
WS_OPEN_EVENT_PARTIAL,
|
WS_OPEN_EVENT_PARTIAL,
|
||||||
} from '../ws.util';
|
} from '../ws.util';
|
||||||
|
|
||||||
describe('Private Linear Websocket Client', () => {
|
describe('Private Linear Perps Websocket Client', () => {
|
||||||
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;
|
||||||
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
LinearClient,
|
|
||||||
WebsocketClient,
|
WebsocketClient,
|
||||||
WSClientConfigurableOptions,
|
WSClientConfigurableOptions,
|
||||||
WS_KEY_MAP,
|
WS_KEY_MAP,
|
||||||
@@ -10,7 +9,7 @@ import {
|
|||||||
WS_OPEN_EVENT_PARTIAL,
|
WS_OPEN_EVENT_PARTIAL,
|
||||||
} from '../ws.util';
|
} from '../ws.util';
|
||||||
|
|
||||||
describe('Public Linear Websocket Client', () => {
|
describe('Public Linear Perps Websocket Client', () => {
|
||||||
let wsClient: WebsocketClient;
|
let wsClient: WebsocketClient;
|
||||||
|
|
||||||
const wsClientOptions: WSClientConfigurableOptions = {
|
const wsClientOptions: WSClientConfigurableOptions = {
|
||||||
@@ -26,7 +25,7 @@ describe('Public Linear Websocket Client', () => {
|
|||||||
wsClient.closeAll();
|
wsClient.closeAll();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should open a private ws connection', async () => {
|
it('should open a public ws connection', async () => {
|
||||||
const wsOpenPromise = waitForSocketEvent(wsClient, 'open');
|
const wsOpenPromise = waitForSocketEvent(wsClient, 'open');
|
||||||
|
|
||||||
expect(wsOpenPromise).resolves.toMatchObject({
|
expect(wsOpenPromise).resolves.toMatchObject({
|
||||||
58
test/spot/ws.private.v1.test.ts
Normal file
58
test/spot/ws.private.v1.test.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import {
|
||||||
|
WebsocketClient,
|
||||||
|
WSClientConfigurableOptions,
|
||||||
|
WS_KEY_MAP,
|
||||||
|
} from '../../src';
|
||||||
|
import {
|
||||||
|
logAllEvents,
|
||||||
|
promiseSleep,
|
||||||
|
silentLogger,
|
||||||
|
waitForSocketEvent,
|
||||||
|
WS_OPEN_EVENT_PARTIAL,
|
||||||
|
} from '../ws.util';
|
||||||
|
|
||||||
|
describe('Private Spot V1 Websocket Client', () => {
|
||||||
|
let wsClient: WebsocketClient;
|
||||||
|
const API_KEY = process.env.API_KEY_COM;
|
||||||
|
const API_SECRET = process.env.API_SECRET_COM;
|
||||||
|
|
||||||
|
it('should have api credentials to test with', () => {
|
||||||
|
expect(API_KEY).toStrictEqual(expect.any(String));
|
||||||
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
|
});
|
||||||
|
|
||||||
|
const wsClientOptions: WSClientConfigurableOptions = {
|
||||||
|
market: 'spot',
|
||||||
|
key: API_KEY,
|
||||||
|
secret: API_SECRET,
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
wsClient = new WebsocketClient(wsClientOptions, silentLogger);
|
||||||
|
logAllEvents(wsClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
wsClient.closeAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: how to detect if auth failed for the v1 spot ws
|
||||||
|
it('should open a private ws connection', async () => {
|
||||||
|
const wsOpenPromise = waitForSocketEvent(wsClient, 'open');
|
||||||
|
// const wsUpdatePromise = waitForSocketEvent(wsClient, 'update');
|
||||||
|
|
||||||
|
wsClient.connectPrivate();
|
||||||
|
|
||||||
|
expect(wsOpenPromise).resolves.toMatchObject({
|
||||||
|
event: WS_OPEN_EVENT_PARTIAL,
|
||||||
|
wsKey: WS_KEY_MAP.spotPrivate,
|
||||||
|
});
|
||||||
|
// expect(wsUpdatePromise).resolves.toMatchObject({
|
||||||
|
// topic: 'wsTopic',
|
||||||
|
// data: expect.any(Array),
|
||||||
|
// });
|
||||||
|
await Promise.all([wsOpenPromise]);
|
||||||
|
// await Promise.all([wsUpdatePromise]);
|
||||||
|
// await promiseSleep(4000);
|
||||||
|
});
|
||||||
|
});
|
||||||
64
test/spot/ws.public.v1.test.ts
Normal file
64
test/spot/ws.public.v1.test.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import {
|
||||||
|
WebsocketClient,
|
||||||
|
WSClientConfigurableOptions,
|
||||||
|
WS_KEY_MAP,
|
||||||
|
} from '../../src';
|
||||||
|
import {
|
||||||
|
logAllEvents,
|
||||||
|
silentLogger,
|
||||||
|
waitForSocketEvent,
|
||||||
|
WS_OPEN_EVENT_PARTIAL,
|
||||||
|
} from '../ws.util';
|
||||||
|
|
||||||
|
describe('Public Spot V1 Websocket Client', () => {
|
||||||
|
let wsClient: WebsocketClient;
|
||||||
|
|
||||||
|
const wsClientOptions: WSClientConfigurableOptions = {
|
||||||
|
market: 'spot',
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
wsClient = new WebsocketClient(wsClientOptions, silentLogger);
|
||||||
|
wsClient.connectPublic();
|
||||||
|
// 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.spotPublic,
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all([wsOpenPromise]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should subscribe to public orderbook events', async () => {
|
||||||
|
const wsUpdatePromise = waitForSocketEvent(wsClient, 'update');
|
||||||
|
|
||||||
|
const symbol = 'BTCUSDT';
|
||||||
|
expect(wsUpdatePromise).resolves.toMatchObject({
|
||||||
|
symbol: symbol,
|
||||||
|
symbolName: symbol,
|
||||||
|
topic: 'diffDepth',
|
||||||
|
params: {
|
||||||
|
realtimeInterval: '24h',
|
||||||
|
binary: 'false',
|
||||||
|
},
|
||||||
|
data: expect.any(Array),
|
||||||
|
});
|
||||||
|
|
||||||
|
wsClient.subscribePublicSpotOrderbook(symbol, 'delta');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await wsUpdatePromise;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Wait for spot v1 orderbook event exception: `, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
72
test/spot/ws.public.v3.test.ts
Normal file
72
test/spot/ws.public.v3.test.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import {
|
||||||
|
WebsocketClient,
|
||||||
|
WSClientConfigurableOptions,
|
||||||
|
WS_KEY_MAP,
|
||||||
|
} from '../../src';
|
||||||
|
import {
|
||||||
|
logAllEvents,
|
||||||
|
silentLogger,
|
||||||
|
waitForSocketEvent,
|
||||||
|
WS_OPEN_EVENT_PARTIAL,
|
||||||
|
} from '../ws.util';
|
||||||
|
|
||||||
|
describe('Public Spot V3 Websocket Client', () => {
|
||||||
|
let wsClient: WebsocketClient;
|
||||||
|
|
||||||
|
const wsClientOptions: WSClientConfigurableOptions = {
|
||||||
|
market: 'spotV3',
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
wsClient = new WebsocketClient(wsClientOptions, silentLogger);
|
||||||
|
wsClient.connectPublic();
|
||||||
|
// 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.spotV3Public,
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all([wsOpenPromise]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should subscribe to public orderbook events', async () => {
|
||||||
|
const wsResponsePromise = waitForSocketEvent(wsClient, 'response');
|
||||||
|
const wsUpdatePromise = waitForSocketEvent(wsClient, 'update');
|
||||||
|
|
||||||
|
const wsTopic = 'orderbook.40.BTCUSDT';
|
||||||
|
expect(wsResponsePromise).resolves.toMatchObject({
|
||||||
|
request: {
|
||||||
|
args: [wsTopic],
|
||||||
|
op: 'subscribe',
|
||||||
|
},
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
expect(wsUpdatePromise).resolves.toStrictEqual('');
|
||||||
|
|
||||||
|
wsClient.subscribe(wsTopic);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await wsResponsePromise;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
`Wait for "${wsTopic}" subscription response exception: `,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await wsUpdatePromise;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Wait for "${wsTopic}" event exception: `, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user