diff --git a/examples/ws-private.ts b/examples/ws-private.ts index fa74781..f9975cf 100644 --- a/examples/ws-private.ts +++ b/examples/ws-private.ts @@ -1,7 +1,7 @@ -import { WebsocketClient, DefaultLogger } from '../src'; +import { WebsocketClientV2, DefaultLogger } from '../src'; // or -// import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from 'bitget-api'; +// import { DefaultLogger, WS_KEY_MAP, WebsocketClientV2 } from 'bitget-api'; (async () => { const logger = { @@ -13,7 +13,7 @@ import { WebsocketClient, DefaultLogger } from '../src'; const API_SECRET = process.env.API_SECRET_COM; const API_PASS = process.env.API_PASS_COM; - const wsClient = new WebsocketClient( + const wsClient = new WebsocketClientV2( { apiKey: API_KEY, apiSecret: API_SECRET, @@ -57,17 +57,21 @@ import { WebsocketClient, DefaultLogger } from '../src'; // spot private // : account updates - // wsClient.subscribeTopic('SPBL', 'account'); - // : order updates - // wsClient.subscribeTopic('SPBL', 'orders'); + // wsClient.subscribeTopic('SPOT', 'account'); + + // : order updates (note: symbol is required) + // wsClient.subscribeTopic('SPOT', 'orders', 'BTCUSDT'); // futures private // : account updates - // wsClient.subscribeTopic('UMCBL', 'account'); - // // : position updates - // wsClient.subscribeTopic('UMCBL', 'positions'); - // // : order updates - // wsClient.subscribeTopic('UMCBL', 'orders'); - // // : plan order updates - // wsClient.subscribeTopic('UMCBL', 'ordersAlgo'); + // wsClient.subscribeTopic('USDT-FUTURES', 'account'); + + // : position updates + // wsClient.subscribeTopic('USDT-FUTURES', 'positions'); + + // : order updates + // wsClient.subscribeTopic('USDT-FUTURES', 'orders'); + + // : plan order updates + wsClient.subscribeTopic('USDT-FUTURES', 'orders-algo'); })(); diff --git a/src/types/websockets/client.ts b/src/types/websockets/client.ts index 6ea8be0..f1c414a 100644 --- a/src/types/websockets/client.ts +++ b/src/types/websockets/client.ts @@ -66,9 +66,19 @@ export type WSPrivateTopicFuturesV2 = | 'orders-algo' | 'positions-history'; -export type WsPrivateTopicV2 = 'account' | 'orders' | WSPrivateTopicFuturesV2; +export type WSPrivateTopicMarginV2 = + | 'orders-crossed' + | 'account-crossed' + | 'account-isolated' + | 'orders-isolated'; -export type WsTopicV2 = WsPublicTopicV2; +export type WsPrivateTopicV2 = + | 'account' + | 'orders' + | WSPrivateTopicFuturesV2 + | WSPrivateTopicMarginV2; + +export type WsTopicV2 = WsPublicTopicV2 | WsPrivateTopicV2; /** This is used to differentiate between each of the available websocket streams */ export type WsKey = (typeof WS_KEY_MAP)[keyof typeof WS_KEY_MAP]; @@ -77,25 +87,50 @@ export type WsKey = (typeof WS_KEY_MAP)[keyof typeof WS_KEY_MAP]; * Event args for subscribing/unsubscribing */ -// TODO: generalise so this can be made a reusable module for other clients export interface WsTopicSubscribeEventArgs { instType: BitgetInstType; channel: WsTopic; - /** The symbol, e.g. "BTCUSDT" */ - instId: string; + instId?: string; } -export type WsTopicSubscribeCommonArgsV2 = { +export type WsTopicSubscribePublicArgsV2 = { instType: BitgetInstTypeV2; - channel: WsTopicV2; -}; - -export type WsTopicSubscribePublicArgsV2 = WsTopicSubscribeCommonArgsV2 & { channel: WsPublicTopicV2; + /** The symbol, e.g. "BTCUSDT" */ instId: string; }; -export type WsTopicSubscribeEventArgsV2 = WsTopicSubscribePublicArgsV2; +export type WsInstIdChannelsV2 = + | 'orders' + | WSPrivateTopicFuturesV2 + | 'orders-crossed' + | 'orders-isolated'; + +export type WsTopicSubscribePrivateInstIdArgsV2 = { + instType: BitgetInstTypeV2; + channel: WsInstIdChannelsV2; + /** The symbol, e.g. "BTCUSDT" */ + instId?: string; +}; + +export type WsCoinChannelsV2 = + | 'account' + | 'account-crossed' + | 'account-isolated'; + +export type WsTopicSubscribePrivateCoinArgsV2 = { + instType: BitgetInstTypeV2; + channel: WsCoinChannelsV2; + coin: 'default' | string; +}; + +export type WsTopicSubscribePrivateArgsV2 = + | WsTopicSubscribePrivateInstIdArgsV2 + | WsTopicSubscribePrivateCoinArgsV2; + +export type WsTopicSubscribeEventArgsV2 = + | WsTopicSubscribePublicArgsV2 + | WsTopicSubscribePrivateArgsV2; /** General configuration for the WebsocketClient */ export interface WSClientConfigurableOptions { diff --git a/src/util/websocket-util.ts b/src/util/websocket-util.ts index fe069d9..36ffc27 100644 --- a/src/util/websocket-util.ts +++ b/src/util/websocket-util.ts @@ -75,9 +75,13 @@ export const PRIVATE_TOPICS = ['account', 'orders', 'positions', 'ordersAlgo']; export const PRIVATE_TOPICS_V2: WsPrivateTopicV2[] = [ 'account', 'orders', - 'orders-algo', 'positions', + 'orders-algo', 'positions-history', + 'orders-crossed', + 'account-crossed', + 'account-isolated', + 'orders-isolated', ]; export function isPrivateChannel( diff --git a/src/websocket-client-v2.ts b/src/websocket-client-v2.ts index e13e0d6..c124d28 100644 --- a/src/websocket-client-v2.ts +++ b/src/websocket-client-v2.ts @@ -3,8 +3,13 @@ import WebSocket from 'isomorphic-ws'; import { BitgetInstTypeV2, WebsocketClientOptions, + WsCoinChannelsV2, + WsInstIdChannelsV2, WsKey, + WsPublicTopicV2, WsTopicSubscribeEventArgsV2, + WsTopicSubscribePrivateCoinArgsV2, + WsTopicSubscribePrivateInstIdArgsV2, WsTopicV2, } from './types'; @@ -22,6 +27,12 @@ import { BaseWebsocketClient } from './util/BaseWSClient'; const LOGGER_CATEGORY = { category: 'bitget-ws' }; +const COIN_CHANNELS: WsTopicV2[] = [ + 'account', + 'account-crossed', + 'account-isolated', +]; + export class WebsocketClientV2 extends BaseWebsocketClient< WsKey, WsTopicSubscribeEventArgsV2 @@ -92,6 +103,38 @@ export class WebsocketClientV2 extends BaseWebsocketClient< ]; } + /** Some private channels use `coin` instead of `instId`. This method handles building the sub/unsub request */ + private getSubRequest( + instType: BitgetInstTypeV2, + topic: WsTopicV2, + coin: string = 'default', + ): WsTopicSubscribeEventArgsV2 { + if (isPrivateChannel(topic)) { + if (COIN_CHANNELS.includes(topic)) { + const subscribeRequest: WsTopicSubscribePrivateCoinArgsV2 = { + instType, + channel: topic as WsCoinChannelsV2, + coin, + }; + return subscribeRequest; + } + + const subscribeRequest: WsTopicSubscribePrivateInstIdArgsV2 = { + instType, + channel: topic as WsInstIdChannelsV2, + instId: coin, + }; + + return subscribeRequest; + } + + return { + instType, + channel: topic as WsPublicTopicV2, + instId: coin, + }; + } + /** * Subscribe to a PUBLIC topic * @param instType instrument type (refer to API docs). @@ -101,41 +144,24 @@ export class WebsocketClientV2 extends BaseWebsocketClient< public subscribeTopic( instType: BitgetInstTypeV2, topic: WsTopicV2, - instId: string = 'default', + coin: string = 'default', ) { - return this.subscribe({ - instType, - instId, - channel: topic, - }); + const subRequest = this.getSubRequest(instType, topic, coin); + return this.subscribe(subRequest); } - // public subscribeTopicV2( - // instType: BitgetInstTypeV2, - // topic: WsTopicV2, - // instId: string = 'default', - // ) { - // if (isPrivateChannel(topic)) { - // } - // } - /** * Unsubscribe from a topic * @param instType instrument type (refer to API docs). * @param topic topic name (e.g. "ticker"). * @param instId instrument ID (e.g. "BTCUSDT"). Use "default" for private topics to get all symbols. - * - * @deprecated, use `subscribe(topics, isPrivate) instead */ public unsubscribeTopic( instType: BitgetInstTypeV2, topic: WsTopicV2, - instId: string = 'default', + coin: string = 'default', ) { - return this.unsubscribe({ - instType, - instId, - channel: topic, - }); + const subRequest = this.getSubRequest(instType, topic, coin); + return this.unsubscribe(subRequest); } }