UNPKG

binance

Version:

Professional Node.js & JavaScript SDK for Binance REST APIs & WebSockets, with TypeScript & end-to-end tests.

421 lines (420 loc) 20.9 kB
import WebSocket from 'isomorphic-ws'; import { KlineInterval } from './types/shared'; import { Exact, WsAPIOperationResponseMap, WsAPITopicRequestParamMap, WsAPIWsKeyTopicMap, WsOperation, WsRequestOperationBinance } from './types/websockets/ws-api'; import { MessageEventLike, WSClientConfigurableOptions, WsMarket, WsTopic } from './types/websockets/ws-general'; import { BaseWebsocketClient, EmittableEvent, MidflightWsRequestEvent } from './util/BaseWSClient'; import { DefaultLogger } from './util/logger'; import { MiscUserDataConnectionState, WSAPIWsKey, WsKey, WsTopicRequest } from './util/websockets/websocket-util'; import { WSConnectedResult } from './util/websockets/WsStore.types'; export interface WSAPIRequestFlags { /** If true, will skip auth requirement for WS API connection */ authIsOptional?: boolean | undefined; } /** * Multiplex Node.js, JavaScript & TypeScript Websocket Client for all of Binance's available WebSockets. * * When possible, it will subscribe to all requested topics on a single websocket connection. A list of * all available streams can be seen in the WS_KEY_URL_MAP found in util/websockets/websocket-util.ts. * * Connectivity is automatically maintained. If disconnected, the WebsocketClient will automatically * clean out the old dead connection, respawn a fresh one and resubscribe to all the requested topics. * * If any connection is reconnected, the WS client will: * - Emit the "reconnecting" event when the process begins. * - Emit the "reconnected" event, when the process has completed. When this event arrives, it is often a * good time to execute any synchorisation workflow (e.g. via the REST API) if any information was missed * while disconnected. * * User data streams will use a dedicated connection per stream for increased resilience. */ export declare class WebsocketClient extends BaseWebsocketClient<WsKey, WsRequestOperationBinance<WsTopic>> { private restClientCache; private beautifier; private userDataStreamManager; private respawnTimeoutCache; constructor(options?: WSClientConfigurableOptions, logger?: DefaultLogger); private getUserDataStreamManager; private getRestClientOptions; /** * Request connection of all dependent (public & WS API) websockets in prod, instead of waiting * for automatic connection by SDK. * * For the Binance SDK, this will only open public connections (without auth), but is almost definitely overkill if you're only working with one product group. */ connectAll(): Promise<WSConnectedResult | undefined>[]; /** * Request connection to all public websockets in prod (spot, margin, futures, options). Overkill if * you're only working with one product group. */ connectPublic(): Promise<WSConnectedResult | undefined>[]; /** * This function serves no purpose in the Binance SDK */ connectPrivate(): Promise<WebSocket | undefined>; /** * Ensures the WS API connection is active and ready. * * You do not need to call this, but if you call this before making any WS API requests, * it can accelerate the first request (by preparing the connection in advance). */ connectWSAPI(wsKey: WSAPIWsKey, skipAuth?: boolean): Promise<unknown>; /** * Request subscription to one or more topics. Pass topics as either an array of strings, * or array of objects (if the topic has parameters). * * Objects should be formatted as {topic: string, params: object, category: CategoryV5}. * * - Subscriptions are automatically routed to the correct websocket connection. * - Authentication/connection is automatic. * - Resubscribe after network issues is automatic. * * Call `unsubscribe(topics)` to remove topics */ subscribe(requests: (WsTopicRequest<WsTopic> | WsTopic) | (WsTopicRequest<WsTopic> | WsTopic)[], wsKey: WsKey): Promise<unknown>; /** * Unsubscribe from one or more topics. Similar to subscribe() but in reverse. * * - Requests are automatically routed to the correct websocket connection. * - These topics will be removed from the topic cache, so they won't be subscribed to again. */ unsubscribe(requests: (WsTopicRequest<WsTopic> | WsTopic) | (WsTopicRequest<WsTopic> | WsTopic)[], wsKey: WsKey): Promise<unknown>; /** * * * * WS API Methods - similar to the REST API, but via WebSockets * https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/general-api-information * * https://github.com/tiagosiebler/awesome-crypto-examples/wiki/REST-API-vs-WebSockets-vs-WebSocket-API * * * */ /** * Send a Websocket API command/request on a connection. Returns a promise that resolves on reply. * * WS API Documentation for list of operations and parameters: * * - Spot: https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/general-api-information * - USDM Futures: https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-api-general-info * - COINM Futures: https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-api-general-info * * * Returned promise is rejected if: * - an exception is detected in the reply, OR * - the connection disconnects for any reason (even if automatic reconnect will happen). * * Authentication is automatic. If you didn't request authentication yourself, there might * be a small delay after your first request, while the SDK automatically authenticates. * * Misc options: * - signRequest: boolean - if included, this request will automatically be signed with the available credentials. * * @param wsKey - The connection this event is for. Currently only "v5PrivateTrade" is supported * for Bybit, since that is the dedicated WS API connection. * @param operation - The command being sent, e.g. "order.create" to submit a new order. * @param params - Any request parameters for the command. E.g. `OrderParamsV5` to submit a new * order. Only send parameters for the request body. Everything else is automatically handled. * @returns Promise - tries to resolve with async WS API response. Rejects if disconnected or exception is seen in async WS API response */ sendWSAPIRequest<TWSKey extends keyof WsAPIWsKeyTopicMap, TWSOperation extends WsAPIWsKeyTopicMap[TWSKey], TWSParams extends Exact<WsAPITopicRequestParamMap<TWSKey>[TWSOperation]>, TWSAPIResponse extends WsAPIOperationResponseMap[TWSOperation] = WsAPIOperationResponseMap[TWSOperation]>(wsKey: TWSKey, operation: TWSOperation, params?: TWSParams extends void | never ? undefined : TWSParams, requestFlags?: WSAPIRequestFlags): Promise<TWSAPIResponse>; /** * * * Internal methods - not intended for public use * * */ /** * @returns The WS URL to connect to for this WS key */ getWsUrl(wsKey: WsKey, connectionType?: 'market' | 'userData'): Promise<string>; private signMessage; private signWSAPIRequest; protected getWsAuthRequestEvent(wsKey: WsKey): Promise<WsRequestOperationBinance<string, { apiKey: string; signature: string; timestamp: number; }>>; protected sendPingEvent(wsKey: WsKey): void; protected sendPongEvent(wsKey: WsKey): void; /** Force subscription requests to be sent in smaller batches, if a number is returned */ protected getMaxTopicsPerSubscribeEvent(wsKey: WsKey): number | null; /** * @returns one or more correctly structured request events for performing a operations over WS. This can vary per exchange spec. */ protected getWsRequestEvents(wsKey: WsKey, operation: WsOperation, requests: WsTopicRequest<string>[]): Promise<MidflightWsRequestEvent<WsRequestOperationBinance<WsTopic>>[]>; protected getPrivateWSKeys(): WsKey[]; protected isAuthOnConnectWsKey(wsKey: WsKey): boolean; /** * Determines if a topic is for a private channel, using a hardcoded list of strings */ protected isPrivateTopicRequest(request: WsTopicRequest<string>): boolean; protected isWsPing(msg: any): boolean; protected isWsPong(msg: any): boolean; /** * Abstraction called to sort ws events into emittable event types (response to a request, data update, etc) */ protected resolveEmittableEvents(wsKey: WsKey, event: MessageEventLike): EmittableEvent[]; /** * * * * * * User Data Streams * * * * * */ /** * -------------------------- * User data listen key tracking & persistence * -------------------------- **/ /** * Subscribe to a spot user data stream. Use REST client to generate and persist listen key. * Supports spot, margin & isolated margin listen keys. */ subscribeSpotUserDataStreamWithListenKey(wsKey: WsKey, listenKey: string, forceNewConnection?: boolean, miscState?: MiscUserDataConnectionState): Promise<WSConnectedResult | undefined>; /** * Subscribe to spot user data stream - listen key is automatically generated. Calling multiple times only opens one connection. * * Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group (e.g. port 9443 (main) vs 443 (main2)) */ subscribeSpotUserDataStream(wsKey?: WsKey, forceNewConnection?: boolean, miscState?: MiscUserDataConnectionState): Promise<WSConnectedResult | void>; unsubscribeSpotUserDataStream(wsKey?: WsKey): Promise<void>; /** * Subscribe to margin user data stream - listen key is automatically generated. Calling multiple times only opens one connection. * * Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group (e.g. port 9443 (main) vs 443 (main2)) */ subscribeCrossMarginUserDataStream(wsKey?: WsKey, forceNewConnection?: boolean, miscState?: MiscUserDataConnectionState): Promise<WSConnectedResult | undefined>; unsubscribeCrossMarginUserDataStream(wsKey?: WsKey): Promise<void>; /** * Subscribe to isolated margin user data stream - listen key is automatically generated. Calling multiple times only opens one connection. * * Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group (e.g. port 9443 (main) vs 443 (main2)) */ subscribeIsolatedMarginUserDataStream(symbol: string, wsKey?: WsKey, forceNewConnection?: boolean, miscState?: MiscUserDataConnectionState): Promise<WSConnectedResult | undefined>; unsubscribeIsolatedMarginUserDataStream(symbol: string, wsKey?: WsKey): Promise<void>; /** * Subscribe to margin risk user data stream - listen key is automatically generated. Calling multiple times only opens one connection. * * Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group (e.g. port 9443 (main) vs 443 (main2)) */ subscribeMarginRiskUserDataStream(wsKey?: WsKey, forceNewConnection?: boolean, miscState?: MiscUserDataConnectionState): Promise<WSConnectedResult | undefined>; unsubscribeMarginRiskUserDataStream(wsKey?: WsKey): Promise<void>; /** * -------------------------- * End of SPOT market websocket streams * -------------------------- **/ /** * Subscribe to USD-M Futures user data stream - listen key is automatically generated. Calling multiple times only opens one connection. * * Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group. */ subscribeUsdFuturesUserDataStream(wsKey?: WsKey, // usdm | usdmTestnet forceNewConnection?: boolean, miscState?: MiscUserDataConnectionState): Promise<WSConnectedResult | undefined>; unsubscribeUsdFuturesUserDataStream(wsKey?: WsKey): Promise<void>; /** * Subscribe to COIN-M Futures user data stream - listen key is automatically generated. Calling multiple times only opens one connection. * * Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group. */ subscribeCoinFuturesUserDataStream(wsKey?: WsKey, // coinm | coinmTestnet forceNewConnection?: boolean, miscState?: MiscUserDataConnectionState): Promise<WSConnectedResult | undefined>; unsubscribeCoinFuturesUserDataStream(wsKey?: WsKey): Promise<void>; /** * Subscribe to Portfolio Margin user data stream - listen key is automatically generated. Calling multiple times only opens one connection. * * Note: the wsKey parameter is optional, but can be used to connect to other environments for this product group. */ subscribePortfolioMarginUserDataStream(wsKey?: WsKey, forceNewConnection?: boolean, miscState?: MiscUserDataConnectionState): Promise<WSConnectedResult | undefined>; unsubscribePortfolioMarginUserDataStream(wsKey?: WsKey): Promise<void>; /** * Close an active, dedicated, user data stream connection. * * @param wsKey - the connection key used to open the connection (excluding any automatic parameters such as the listen key). E.g. 'main' for spot/margin, 'usdm' for futures. * @param wsMarket - the product group, recommended if you're subscribed to both spot and margin (since they're on the same wsKey (main)). */ closeUserDataStream(wsKey: WsKey, wsMarket: WsMarket, symbol?: string): Promise<void>; protected isCustomReconnectionNeeded(wsKey: string): boolean; protected triggerCustomReconnectionWorkflow(legacyWsKey: string): Promise<void>; private respawnUserDataStream; /** * Subscribe to the European Options user data stream - listen key is automatically generated. * * Not supported at this time. Please get in touch if you need this. */ /** * * * * * Convenient subscribe methods, similar to the legacy WebsocketClient for Binance. * * * * */ /** * -------------------------- * Universal market websocket streams (may apply to one or more API markets) * -------------------------- **/ /** * Advanced: Subscribe to a universal market websocket stream * * This is NOT recommended unless you're very confident with what you're doing. */ subscribeEndpoint(endpoint: string, market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to aggregate trades for a symbol in a market category */ subscribeAggregateTrades(symbol: string, market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to trades for a symbol in a market category * IMPORTANT: This topic for usdm and coinm is not listed in the api docs and might stop working without warning */ subscribeTrades(symbol: string, market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to coin index for a symbol in COINM Futures markets */ subscribeCoinIndexPrice(symbol: string, updateSpeedMs?: 1000 | 3000): Promise<unknown>; /** * Subscribe to mark price for a symbol in a market category */ subscribeMarkPrice(symbol: string, market: 'usdm' | 'coinm', updateSpeedMs?: 1000 | 3000): Promise<unknown>; /** * Subscribe to mark price for all symbols in a market category */ subscribeAllMarketMarkPrice(market: 'usdm' | 'coinm', updateSpeedMs?: 1000 | 3000): Promise<unknown>; /** * Subscribe to klines(candles) for a symbol in a market category */ subscribeKlines(symbol: string, interval: KlineInterval, market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to continuous contract klines(candles) for a symbol futures */ subscribeContinuousContractKlines(symbol: string, contractType: 'perpetual' | 'current_quarter' | 'next_quarter', interval: KlineInterval, market: 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to index klines(candles) for a symbol in a coinm futures */ subscribeIndexKlines(symbol: string, interval: KlineInterval): Promise<unknown>; /** * Subscribe to index klines(candles) for a symbol in a coinm futures */ subscribeMarkPriceKlines(symbol: string, interval: KlineInterval): Promise<unknown>; /** * Subscribe to mini 24hr ticker for a symbol in market category. */ subscribeSymbolMini24hrTicker(symbol: string, market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to mini 24hr mini ticker in market category. */ subscribeAllMini24hrTickers(market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to 24hr ticker for a symbol in any market. */ subscribeSymbol24hrTicker(symbol: string, market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to 24hr ticker in any market. */ subscribeAll24hrTickers(market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to rolling window ticker statistics for all market symbols, * computed over multiple windows. Note that only tickers that have * changed will be present in the array. * * Notes: * - Supported window sizes: 1h,4h,1d. * - Supported markets: spot */ subscribeAllRollingWindowTickers(market: 'spot', windowSize: '1h' | '4h' | '1d'): Promise<unknown>; /** * Subscribe to best bid/ask for symbol in spot markets. */ subscribeSymbolBookTicker(symbol: string, market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to best bid/ask for all symbols in spot markets. */ subscribeAllBookTickers(market: 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to best bid/ask for symbol in spot markets. */ subscribeSymbolLiquidationOrders(symbol: string, market: 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to best bid/ask for all symbols in spot markets. */ subscribeAllLiquidationOrders(market: 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to partial book depths (snapshots). * * Note: * - spot only supports 1000ms or 100ms for updateMs * - futures only support 100, 250 or 500ms for updateMs */ subscribePartialBookDepths(symbol: string, levels: 5 | 10 | 20, updateMs: 100 | 250 | 500 | 1000, market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to orderbook depth updates to locally manage an order book. * * Note that the updatems parameter depends on which market you're trading * * - Spot: https://binance-docs.github.io/apidocs/spot/en/#diff-depth-stream * - USDM Futures: https://binance-docs.github.io/apidocs/futures/en/#diff-book-depth-streams */ subscribeDiffBookDepth(symbol: string, updateMs: 100 | 250 | 500 | 1000 | undefined, market: 'spot' | 'usdm' | 'coinm'): Promise<unknown>; /** * Subscribe to best bid/ask for all symbols in spot markets. */ subscribeContractInfoStream(market: 'usdm' | 'coinm'): Promise<unknown>; /** * -------------------------- * SPOT market websocket streams * -------------------------- **/ /** * Subscribe to aggregate trades for a symbol in spot markets. */ subscribeSpotAggregateTrades(symbol: string): Promise<unknown>; /** * Subscribe to trades for a symbol in spot markets. */ subscribeSpotTrades(symbol: string): Promise<unknown>; /** * Subscribe to candles for a symbol in spot markets. */ subscribeSpotKline(symbol: string, interval: KlineInterval): Promise<unknown>; /** * Subscribe to mini 24hr ticker for a symbol in spot markets. */ subscribeSpotSymbolMini24hrTicker(symbol: string): Promise<unknown>; /** * Subscribe to mini 24hr mini ticker in spot markets. */ subscribeSpotAllMini24hrTickers(): Promise<unknown>; /** * Subscribe to 24hr ticker for a symbol in spot markets. */ subscribeSpotSymbol24hrTicker(symbol: string): Promise<unknown>; /** * Subscribe to 24hr ticker in spot markets. */ subscribeSpotAll24hrTickers(): Promise<unknown>; /** * Subscribe to best bid/ask for symbol in spot markets. */ subscribeSpotSymbolBookTicker(symbol: string): Promise<unknown>; /** * Subscribe to top bid/ask levels for symbol in spot markets. */ subscribeSpotPartialBookDepth(symbol: string, levels: 5 | 10 | 20, updateMs?: 1000 | 100): Promise<unknown>; /** * Subscribe to spot orderbook depth updates to locally manage an order book. */ subscribeSpotDiffBookDepth(symbol: string, updateMs?: 1000 | 100): Promise<unknown>; }