UNPKG

binance

Version:

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

1,540 lines (1,442 loc) 669 kB
This file is a merged representation of a subset of the codebase, containing files not matching ignore patterns, combined into a single document by Repomix. The content has been processed where content has been compressed (code blocks are separated by ⋮---- delimiter), security check has been disabled. ================================================================ File Summary ================================================================ Purpose: -------- This file contains a packed representation of a subset of the repository's contents that is considered the most important context. It is designed to be easily consumable by AI systems for analysis, code review, or other automated processes. File Format: ------------ The content is organized as follows: 1. This summary section 2. Repository information 3. Directory structure 4. Repository files (if enabled) 5. Multiple file entries, each consisting of: a. A separator line (================) b. The file path (File: path/to/file) c. Another separator line d. The full contents of the file e. A blank line Usage Guidelines: ----------------- - This file should be treated as read-only. Any changes should be made to the original repository files, not this packed version. - When processing this file, use the file path to distinguish between different files in the repository. - Be aware that this file may contain sensitive information. Handle it with the same level of security as you would the original repository. Notes: ------ - Some files may have been excluded based on .gitignore rules and Repomix's configuration - Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files - Files matching these patterns are excluded: .github/, examples/apidoc/, docs/images/, docs/endpointFunctionList.md, test/, src/util/ - Files matching patterns in .gitignore are excluded - Files matching default ignore patterns are excluded - Content has been compressed - code blocks are separated by ⋮---- delimiter - Security check has been disabled - content may contain sensitive information - Files are sorted by Git change count (files with more changes are at the bottom) ================================================================ Directory Structure ================================================================ .circleci/ config.yml examples/ auth/ rest-private-ed25519.md rest-private-ed25519.ts rest-private-rsa.md rest-private-rsa.ts misc/ README.md rest-spot-exchange-info.ts tracking-candles.ts REST/ rest-future-bracket-order.ts rest-portfoliomargin-private.ts rest-portfoliomargin-public.ts rest-spot-private-autoinvest.ts rest-spot-private-misc.ts rest-spot-private-trade.ts rest-spot-public.ts rest-usdm-order-sl.ts rest-usdm-order.ts rest-usdm-private-get.ts rest-usdm-public.ts rest-usdm-testnet.ts WebSockets/ deprecated-ws-public.ts ws-api-client.ts ws-api-raw-promises.ts ws-close.ts ws-custom-parser.ts ws-proxy-socks.ts ws-public-spot-orderbook.ts ws-public-spot-trades.ts ws-public-usdm-funding.ts ws-public.ts ws-unsubscribe.ts ws-userdata-connection-safety.ts ws-userdata-listenKey-testnet.ts ws-userdata-listenkey.ts ws-userdata-README.MD ws-userdata-wsapi.ts README.md src/ types/ websockets/ ws-api-requests.ts ws-api-responses.ts ws-api.ts ws-events-formatted.ts ws-events-raw.ts ws-general.ts coin.ts futures.ts portfolio-margin.ts shared.ts spot.ts coinm-client.ts index.ts main-client.ts portfolio-client.ts usdm-client.ts websocket-api-client.ts websocket-client-legacy.ts websocket-client.ts webpack/ webpack.config.js .eslintrc.cjs .gitignore .jshintrc .npmignore .nvmrc .prettierrc CHANGELOG.md index.js jest.config.ts jsconfig.json LICENSE.md package.json README.md tea.yaml tsconfig.build.json tsconfig.json tsconfig.linting.json ================================================================ Files ================================================================ ================ File: .circleci/config.yml ================ version: 2.1 jobs: test: docker: - image: cimg/node:15.1 # resource_class: tiagosiebler/localcirunner # The resource_class feature allows configuring CPU and RAM resources for each job. Different resource classes are available for different executors. https://circleci.com/docs/2.0/configuration-reference/#resourceclass resource_class: large steps: - checkout - restore_cache: # See the configuration reference documentation for more details on using restore_cache and save_cache steps # https://circleci.com/docs/2.0/configuration-reference/?section=reference#save_cache keys: - node-deps-v1-{{ .Branch }}-{{checksum "package-lock.json"}} - run: name: install packages command: npm ci --ignore-scripts - save_cache: key: node-deps-v1-{{ .Branch }}-{{checksum "package-lock.json"}} paths: - ~/.npm - run: name: Run Build command: npm run build - run: name: Run Tests command: npm run test workflows: integrationtests: jobs: - test ================ File: examples/auth/rest-private-ed25519.md ================ # Ed25519 Authentication with Binance APIs in Node.js ## Creating Ed25519 Keys Officially, binance recommends downloading and running a key generator from their repo. Guidance for this can be found on the [binance website](https://www.binance.com/en/support/faq/detail/6b9a63f1e3384cf48a2eedb82767a69a) when trying to add a new Ed25519 API key, or in their GitHub repository: https://github.com/binance/asymmetric-key-generator ## Using the Ed25519 public key to get an API key from Binance Once created, keep your **private key** completely secret! The **public** key needs to be provided to binance when creating new API credentials with the "Self-generated" option. Your public key should look something like this: ```pem -----BEGIN PUBLIC KEY----- lkn123bx123x+7lkmlkn123bx123xAMDO/lkm123x= -----END PUBLIC KEY----- ``` Submit this in the "Upload public key" form, shown when creating a new API key on binance and choosing the "self-generated" option. Note: the "-----BEGIN PUBLIC KEY-----" and "-----END PUBLIC KEY-----" header & footer can be included. After using the public key to create a new API key, you will be given an API Key such as the following: ``` mlk2mx3l12m3lxk1m3lxk1m3l1k2mx3l12km3xl1km23x1l2k3mx1l2km3x ``` This is the first piece, used as the "apiKey" in the [rest-private-ed25519.ts](./rest-private-ed25519.ts) example. ## Using the Ed25519 private key for Ed25519 authentication with binance APIs in Node.js Your private key, if generated with the above steps, should look something like this (but with much more text): ```pem -----BEGIN PRIVATE KEY----- lx1k2m3xl12lkm2l1kmx312312l3mx1lk23m -----END PRIVATE KEY----- ``` This is your secret, you should **never** share this with anyone, not even binance! Treat this like a password. As part of this authentication process, your private key is used to generate a signature. This SDK handles this process automatically for you. Ed25519 authentication is automatically detected if the "api_secret" parameter contains the words "PRIVATE KEY", such as the header shown in the example above. From here, simply use the key provided by binance as the `api_key` parameter and your private key (with the header) as the `api_secret` parameter. Based on the above example, the following would prepare the main REST client using the above credentials: ```typescript const ed25519PrivateKey = ` -----BEGIN PRIVATE KEY----- lkmlkm123lkms1s12s+lkmlkm123lkms1s12s -----END PRIVATE KEY----- `; const ed25519APIKey = 'lkmlkm123lkms1s12slkmlkm123lkms1s12slkmlkm123lkms1s12s'; const client = new MainClient({ api_key: ed25519APIKey, api_secret: ed25519PrivateKey, beautifyResponses: true, }); ``` The rest is automatic - just continue using the SDK as you would normally. It will automatically handle signing requests using Ed25519 for you. For a complete example, refer to the [rest-private-ed25519.ts](./rest-private-ed25519.ts) file on GitHub. ================ File: examples/auth/rest-private-ed25519.ts ================ import { MainClient } from '../../src/index'; ⋮---- // or // import { MainClient } from 'binance'; ⋮---- // Received after creating a new API key with a self-generated RSA public key on binance ⋮---- // The self-generated RSA private key, this is never directly given to binance, but used to generate a signature // Note: this MUST include the "BEGIN PRIVATE KEY" header so the SDK understands this is RSA auth ================ File: examples/auth/rest-private-rsa.md ================ # RSA Authentication with Binance APIs in Node.js ## Creating RSA Keys Officially, binance recommends downloading and running a key generator from their repo. Guidance for this can be found on the binance website when trying to add a new RSA API key. However, openssl can be used to create the public & private key files using the following steps: ```bash # Generate a private key with either 2048 or 4096 bit length openssl genrsa -out rsa-private-key.pem 4096 # Generate a corresponding public key openssl rsa -in rsa-private-key.pem -pubout -out rsa-public-key.pem ``` ## Using the RSA public key to get an API key from Binance Once created, keep your **private key** completely secret! The **public** key needs to be provided to binance when creating new API credentials with the "Self-generated" option. Your public key should look something like this: ```pem -----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1uWxxOXZUaX6AeZszf4x rBsU6axA5ipwxG7VPihVgssphDrrSOD0hZqnBmtF2bvT9ee1U0XOfMn+H+J5SH+1 jgUpfioqH0L+KXl6wmLoPsadgfJz0SiQlFnKTkDXvMmecr6cdMHi2qNEx4CMc68C obvQ4Voz5qqpDwbohGtJh0p10PB//0Ejcoz0UwrTDq8BGeFmWa9pL/7h2vHtw+QU UxlnGmt98M8KkKqqvVicMK+IVtng/QlDw9ofG2kQcbBkPRaTjNI+8ULtCDH0sOkZ nT8PtGm4sEwmWH/dRWtUTWkMnUwCzuo/rWPb7WMprW2pKDTrLjUAr9M161t3Xa6W JO03K3NOxupy7ilululLY8d/WKWYDOZMvS5bPiPRUoZqlJneC0CT/2q1W6GfWzsT DCDTpgq/Ao7jTtnME9iadpwvFn0nMtNgJSrFDWPq8vKY9pRcEp/Na5qvIEOQIFnp /kIDPuMf+LZwO8lGFO3jnndY+62835rm7t6ZNM3NLoNCarvUCEasobgDJHw7x7c1 fW/OxYtLrWGdMpsP0MewgGJZXcT7mvlBjQ+JWLoyIc5rYMIDw9RLWUPnrlRCxvPp sD9kDX7eaipdoik5yLyMaRvd16Vt9Bck/9pbSHazm41m/nd4KCZeGdsvrAA2beww zFWQQV9EX6/VLBgbnGTsMe0CAwEAAQ== -----END PUBLIC KEY----- ``` Submit this in the "Upload public key" form, shown when creating a new API key on binance and choosing the "self-generated" option. Note: the "-----BEGIN PUBLIC KEY-----" and "-----END PUBLIC KEY-----" header & footer can be included. After using the public key to create a new API key, you will be given an API Key such as the following: ``` SIHqWcDeRoj6gkOjLjQh1dnV1CD7IgwQTfL4LVa8wu04zNTYVSmJBIHsjQjgwWqt ``` This is the first piece, used as the "apiKey" in the [rest-private-rsa.ts](./rest-private-rsa.ts) example. ## Using the RSA private key for RSA authentication with binance APIs in Node.js Your private key, if generated with the above steps, should look something like this (but with much more text): ```pem -----BEGIN RSA PRIVATE KEY----- uayyi6wFTaNeG1/WCqhrowj2kCx8eB6NDZYl+OS9ZI9WC q/44iFERNuP0TXvQx8tgvSZXyu4/G618QzKh0Ii1uAATt2upa8dp1uGl2U7EqBE8 p5y4pPzJuwvB3j6LQON20u2Wpbg8PQZACMfKym7lYDO+9MloK/gAQpyeYJzbw92C YE/ymq4JVjCMCQKCAQEA4/X0I9TO8vT0D0l83o693QA3C09uSZ6j9Obx5UrtDnA9 sMkkRoe+R/vvIpVDzukMEEOmCuxbcdPoniVUKlTooK0Llo6JJ1l8CdFzQsOR97Pe csB6pxkLLH2qHx05xPBy4PyoB -----END RSA PRIVATE KEY----- ``` This is your secret, you should never share this with anyone, not even binance! Treat this like a password. As part of this authentication process, your private key is used to generate a signature (using `RSA-SHA256`). This SDK handles this process automatically for you. RSA authentication is automatically detected if the "api_secret" parameter contains the words "PRIVATE KEY", such as the header shown in the example above. Note: Binance also supports Ed25519 authentication. If your "secret" matches the following condition, the SDK will revert to to Ed25519 authentication: - Contains "PRIVATE KEY" as a header - Does NOT contain "RSA PRIVATE KEY" as a header. From here, simply use the key provided by binance as the `api_key` parameter and your private key (with the header) as the `api_secret` parameter. Based on the above example, the following would prepare the main REST client using the above credentials: ```typescript const api_key = `SIHqWcDeRoj6gkOjLjQh1dnV1CD7IgwQTfL4LVa8wu04zNTYVSmJBIHsjQjgwWqt`; const rsaPrivateKey = ` -----BEGIN RSA PRIVATE KEY----- uayyi6wFTaNeG1/WCqhrowj2kCx8eB6NDZYl+OS9ZI9WC q/44iFERNuP0TXvQx8tgvSZXyu4/G618QzKh0Ii1uAATt2upa8dp1uGl2U7EqBE8 p5y4pPzJuwvB3j6LQON20u2Wpbg8PQZACMfKym7lYDO+9MloK/gAQpyeYJzbw92C YE/ymq4JVjCMCQKCAQEA4/X0I9TO8vT0D0l83o693QA3C09uSZ6j9Obx5UrtDnA9 sMkkRoe+R/vvIpVDzukMEEOmCuxbcdPoniVUKlTooK0Llo6JJ1l8CdFzQsOR97Pe csB6pxkLLH2qHx05xPBy4PyoB -----END RSA PRIVATE KEY----- `; const client = new MainClient({ api_key: api_key, api_secret: rsaPrivateKey, beautifyResponses: true, }); ``` For a complete example, refer to the [rest-private-rsa.ts](./rest-private-rsa.ts) file on GitHub. ================ File: examples/misc/README.md ================ # Utilities These are miscellaneous utilities used by some of the examples in this repo. These do not represent best practices and are merely for easier demonstrations. ================ File: examples/misc/rest-spot-exchange-info.ts ================ import { ExchangeInfo, MainClient, numberInString, roundToStepSize, roundToTickSize, } from '../../src'; // from 'binance'; ⋮---- } from '../../src'; // from 'binance'; ⋮---- // or // import { MainClient } from 'binance'; ⋮---- // Optional (default: false) - when true, response strings are parsed to floats (only for known keys). // beautifyResponses: true, ⋮---- interface SymbolInfo { tickSize: numberInString; qtyStepSize: numberInString; minOrderQty: numberInString; maxOrderQty: numberInString; maxMarketQty: numberInString; maxNumOfOrders: number; minNotional: numberInString; maxNotional: numberInString; maxBasePrecisionDecimals: number; maxQuotePrecisionDecimals: number; } ⋮---- // Get full exchange info so we can cache it and use it for other functions without making request every time async function fetchExchangeInfo() ⋮---- async function getSymbolInfo( exchangeInfo: ExchangeInfo, symbol: string, ): Promise<SymbolInfo> ⋮---- // Find the symbol information once ⋮---- // console.log(symbolInfo); ⋮---- // Extract filters from the symbol info ⋮---- /** * Validates and formats an order based on symbol constraints */ function formatOrderParams( symbol: string, price: number, quantity: number, symbolInfo: any, ): ⋮---- // Check if price is within allowed range ⋮---- // Check if quantity is within allowed range ⋮---- // Check notional value (price * quantity) ⋮---- // Format price and quantity according to exchange requirements ⋮---- // Example usage async function testSymbolUtils() ⋮---- // Test price formatting ⋮---- // Test quantity formatting ⋮---- // Test full order formatting ⋮---- // example how to use the order params ================ File: examples/misc/tracking-candles.ts ================ import { EventEmitter } from 'events'; ⋮---- import { DefaultLogger, isWsFormattedKline, KlineInterval, USDMClient, WebsocketClient, } from '../../src'; ⋮---- // or, with the npm package /* import { WebsocketClient, isWsFormattedKline, USDMClient, KlineInterval, } from 'binance'; */ ⋮---- /** * This elaborate example serves the following key functions: * - Connect to various candle websockets to receive realtime candle events (update open candle & append closed candle) * - Backfill some candles using the REST API * - Once backfilled, start processing candle events (update & append in-memory, depending if candle closed or not) * - Keep the candle stores trimmed, so we never store more than `maxStoredCandles` candles per symbol * - When a connection opens or reconnects, the backfill is executed again to ensure there are no gaps * * The "onCandleClosed()" function is where you would run custom logic with a dataset of candles (e.g. run some indicator calculations) */ ⋮---- /** * Configuration logic */ ⋮---- /** * Data stores */ ⋮---- interface EngineCandle { open: number; close: number; high: number; low: number; volume: number; openTime: number; openDt: Date; closeTime: number; closeDt: Date; } ⋮---- /** * The shape of the events produced by the candle store. * All the info needed to query the candle store for all candles, after receiving a candle closed event */ interface CandleStoreEvent { symbol: string; interval: string; } ⋮---- /** These are the events produced by the candle store, which can be used to implement this abstraction layer */ export declare interface CandleEmitter extends EventEmitter { on(event: 'candleClose', listener: (event: CandleStoreEvent) => void): this; on(event: 'candleUpdate', listener: (event: CandleStoreEvent) => void): this; } ⋮---- on(event: 'candleClose', listener: (event: CandleStoreEvent) on(event: 'candleUpdate', listener: (event: CandleStoreEvent) ⋮---- /** Some options to configure the behaviour of the candle store */ interface CandleStoreOptions { /** Keep a ceiling on how many candles are stored, before old ones are discarded (prevent the store from growing forever into infinity) */ maxStoredCandles?: number; eventEmitter: EventEmitter; } ⋮---- /** Keep a ceiling on how many candles are stored, before old ones are discarded (prevent the store from growing forever into infinity) */ ⋮---- /** /** * A general store for symbol/interval candles, including handling the currently open candle, with some utility methods */ export class CandleStore ⋮---- // Closed candles are stored as an array of candles per interval in this store. // This is essentially an object acting as a key/value store (key: interval, value: candle array) ⋮---- // Open candles are kept separate from the closed candles, also in a key/value store (key: interval, value: current open candle) ⋮---- constructor(symbol: string, options: CandleStoreOptions) ⋮---- // super(); ⋮---- /** * Overwrite the current candle store, e.g. after backfilling. Candles are sorted automatically before overwriting the store */ public setCandles(candles: EngineCandle[], interval: string): void ⋮---- public setOpenCandle(candle: EngineCandle | null, interval: string): void ⋮---- /** * Provide a candle event to the store for processing (e.g candle closed vs open candle updated). * - Closed candles are appended to the array. * - Open candles are tracked separately and only (optionally) used during the getCandles(true) query. */ public processCandleEvent( candle: EngineCandle, interval: string, isCandleClosed: boolean, ): void ⋮---- // console.log(this.symbol, `Open candle update`); ⋮---- // console.log(`Emit candle closed evt`, evt); ⋮---- private initCandleStores(interval: string) ⋮---- /** * Execute a store-trim. This is called automatically during candle-closed events, but * can be called manually (e.g. after backfilling) to ensure the store only keeps the most recent `maxStoredCandles`. */ public trimExcessCandles(interval: string): void ⋮---- // This mutates the closed candle store to remove the first x elements ⋮---- /** * Query all candles in the store for an interval. * Optionally append the currently open candle to the end of the array. */ public getCandles( interval: string, includeOpenCandle?: boolean, ): EngineCandle[] ⋮---- // check last candle has same open time as open candle, just in case ⋮---- // Include open candle at end of array ⋮---- /** * A key value store for all symbols & intervals * * // All CandleStores for that symbol (one per symbol, supports many intervals in one store) * const symbolCandles = allCandleStores[symbol]; * */ ⋮---- /** * Get a candle store for a symbol. * Since a missing candle store is automatically initialised, you can assume this will always return a candle store. */ function getCandleStore(symbol: string): CandleStore ⋮---- // Hook up event consumers on the shared event emitter ⋮---- // eventEmitter.on('candleUpdate', (e) => { // console.log('candle updated', { // dt: new Date(), // symbol: e.symbol, // interval: e.interval, // }); // }); ⋮---- /** Ensure a candle store exists for this symbol & attach consumers to the store */ function initCandleStoreIfMissing(symbol: string): void ⋮---- // Inject your own event emitter and initialise one candle store per symbol (it supports multiple intervals) ⋮---- /** * Websocket Listeners */ ⋮---- // console.log('kline received ', { candle, isCandleClosed }); ⋮---- // const candleStore: CandleStore = allIntervalCandleStores[symbol][interval]; ⋮---- // response to command sent via WS stream (e.g. subscription confirmation) // this will automatically trigger a backfill for that symbol. ⋮---- // empty response result === success ⋮---- // btcusdt@kline_1m -> btcusdt, kline_1m ⋮---- // kline_1m -> kline, 1m // eslint-disable-next-line @typescript-eslint/no-unused-vars ⋮---- /** * Execute a 1-page backfill (1000 candles). Called automatically when a connection opens OR reconnects. */ async function backfillCandles( symbol: string, interval: KlineInterval, ): Promise<void> ⋮---- // Map to a standard candle structure ⋮---- // Last candle might not be closed, so filter that out (ignore any candles with close time in the future) ⋮---- // const candleStore: CandleStore = allIntervalCandleStores[symbol][interval]; ⋮---- // Overwrite the current candles in the store and remove excess candles ⋮---- /** * Bootstrap a connection per symbol & timeframe. Backfill will automatically trigger when the connection opens successfully. * Note: this will spawn one websocket connection per symbol per timeframe. For complex cases, this may create too many connections. */ ⋮---- // Open a websocket to start consuming candle events ⋮---- function onCandleClosed(symbol: string, interval: string): void ⋮---- // When a candle closes, fetch all closed candles from the store for that symbol, e.g. to calculate some indicators ================ File: examples/REST/rest-future-bracket-order.ts ================ import { NewFuturesOrderParams, USDMClient } from '../../src/index'; ⋮---- // submit a 1:1 bracket market buy order with market entry order ⋮---- // TODO: check balance and do other validations ⋮---- // create three orders // 1. entry order (GTC), // 2. take profit order (GTE_GTC), // 3. stop loss order (GTE_GTC) ================ File: examples/REST/rest-portfoliomargin-private.ts ================ import { PortfolioClient } from '../../src/index'; ⋮---- // or // import { PortfolioClient } from 'binance'; ⋮---- // const newOrderRes = await client.submitNewUMOrder({ // symbol: 'BTCUSDT', // side: 'BUY', // type: 'MARKET', // quantity: '10', // }); ⋮---- // console.log('new order res: ', newOrderRes); ================ File: examples/REST/rest-portfoliomargin-public.ts ================ import { PortfolioClient } from '../../src/index'; ⋮---- // or // import { PortfolioClient } from 'binance'; ⋮---- // const serverTime = await client.getServerTime(); // console.log('serverTime: ', serverTime); ================ File: examples/REST/rest-spot-private-autoinvest.ts ================ import { MainClient } from '../../src/index'; ⋮---- // or // import { MainClient } from 'binance'; ================ File: examples/REST/rest-spot-private-misc.ts ================ import { MainClient } from '../../src/index'; ⋮---- // or // import { MainClient } from 'binance'; ================ File: examples/REST/rest-spot-private-trade.ts ================ import { MainClient, NewSpotOrderParams, OrderResponseFull, SymbolPrice, } from '../../src/index'; ⋮---- // or // import { MainClient } from 'binance'; ⋮---- const entryAmountPercent = 50; // trigger trade with 50% ⋮---- const assetDecimalPlaces = 4; // get this from exchange info, it varies per asset ⋮---- // method to trim down to decimal. function trimToDecimalPlaces(number: number, precision: number): number ⋮---- /** * This is a very silly demonstration on placing market orders using various parts of the module. * By default it will use 50% of your available USDT balance to buy BTC and sell it again. */ ⋮---- /** * Get available balance */ ⋮---- // console.log('USDT balance object: ', usdtBal); ⋮---- /** * Get last asset price */ ⋮---- /** * Calculate and submit buy amount */ ⋮---- /** * ACK = confirmation of order acceptance (no placement/fill information) -> OrderResponseACK * RESULT = fill state -> OrderResponseResult * FULL = fill state + detail on fills and other detail -> OrderResponseFull */ ⋮---- /** * Process bought fills and submit sell amount */ ================ File: examples/REST/rest-spot-public.ts ================ import { MainClient } from '../../src/index'; ⋮---- // or // import { MainClient } from 'binance'; ⋮---- // Optional (default: false) - when true, response strings are parsed to floats (only for known keys). // beautifyResponses: true, ⋮---- // console.log( // 'getAvgPrice: ', // await client.getAvgPrice({ symbol: 'BTCUSDT' }), // ); // console.log( // 'getExchangeInfo: ', // JSON.stringify(await client.getExchangeInfo(), null, 2), // ); ================ File: examples/REST/rest-usdm-order-sl.ts ================ /* eslint-disable @typescript-eslint/no-unused-vars */ import { USDMClient } from '../../src/index'; ⋮---- // or // import { USDMClient } from 'binance'; ⋮---- async function start() ⋮---- // ### This is for Hedge Mode Only ### // assuming you currently have a open position, and you want to modify the SL order. ⋮---- /** * first we get all long and short positions status * the result of this method in hedge mode is array of two objects * first index for LONG and second index for SHORT */ ⋮---- // if longAmount is bigger than 0 means we have open long position and if shortAmount is below 0 means we have open short position ⋮---- // if we have any open position then we continue ⋮---- // we get ourstop loss here ⋮---- // we want to modify our long position SL here ⋮---- // we get the StopLoss order which is realted to long ⋮---- // if it exists, cancel it. ⋮---- // creating SL order ⋮---- side: 'SELL', // the action of order, means this order will sell which is sl for long position positionSide: 'LONG', // based on the headge mode we either LONG or SHORT, here we are doing it for our long pos ⋮---- closePosition: 'true', // this is here because we don't have the position quantity value, and it means closee all quantity stopPrice: parseFloat((markPrice * 0.99).toFixed(3)), // set sl price 1% below current price ================ File: examples/REST/rest-usdm-order.ts ================ import { USDMClient } from '../../src/index'; ⋮---- // or // import { USDMClient } from 'binance'; ⋮---- async function start() ⋮---- // To open a short position - if you don't have a position yet, and your account is set to one-way mode, just place a sell order to open a short position ⋮---- // newOrderRespType: 'FULL', ================ File: examples/REST/rest-usdm-private-get.ts ================ import { USDMClient } from '../../src/index'; // import axios from 'axios'; ⋮---- // or // import { USDMClient } from 'binance'; ================ File: examples/REST/rest-usdm-public.ts ================ import { USDMClient } from '../../src'; ⋮---- // keepAlive: true, // ... any other params, ================ File: examples/REST/rest-usdm-testnet.ts ================ import { USDMClient } from '../../src/index'; ⋮---- // or // import { USDMClient } from 'binance'; ⋮---- /** * Note: testnet is NOT a good place to test strategy performance. * * For more information and guidance, refer to: * https://github.com/tiagosiebler/awesome-crypto-examples/wiki/CEX-Testnets */ ⋮---- async function start() ⋮---- // To open a short position - if you don't have a position yet, and your account is set to one-way mode, just place a sell order to open a short position ⋮---- // newOrderRespType: 'FULL', ================ File: examples/WebSockets/deprecated-ws-public.ts ================ /* eslint-disable @typescript-eslint/no-unused-vars */ import { DefaultLogger, isWsFormatted24hrTicker, isWsFormatted24hrTickerArray, isWsFormattedKline, isWsFormattedRollingWindowTickerArray, WebsocketClientV1, } from '../../src/index'; ⋮---- // or, with the npm package /* import { WebsocketClientV1, DefaultLogger, isWsFormatted24hrTicker, isWsFormattedKline, } from 'binance'; */ ⋮---- /** * * This example demonstrates basic usage of the previous WebsocketClientV1, which should be considered deprecated. * */ ⋮---- // api_key: key, // api_secret: secret, ⋮---- // manually handle events and narrow down to desired types ⋮---- // or use a supplied type guard (if available - not all type guards have been written yet) ⋮---- // console.log('log formattedMessage: ', JSON.stringify(data[0], null, 2)); ⋮---- // response to command sent via WS stream (e.g LIST_SUBSCRIPTIONS) ⋮---- // wsClient.subscribeCoinIndexPrice(coinMSymbol); // wsClient.subscribeSpotAllBookTickers(); ⋮---- // wsClient.subscribeSpotKline(market, '1m'); // wsClient.subscribeKlines(market, '1m', 'usdm'); // wsClient.subscribeMarkPrice(market, 'usdm'); // wsClient.subscribeMarkPrice(coinMSymbol, 'coinm'); // wsClient.subscribeAllMarketMarkPrice('usdm'); // wsClient.subscribeAllMarketMarkPrice('coinm'); // wsClient.subscribeKlines(market, '1m', 'usdm'); // wsClient.subscribeContinuousContractKlines(market, 'perpetual', '1m', 'usdm'); // wsClient.subscribeIndexKlines(coinMSymbol, '1m'); // wsClient.subscribeMarkPriceKlines(coinMSymbol, '1m'); // wsClient.subscribeSymbolMini24hrTicker(market, 'usdm'); // wsClient.subscribeSymbolMini24hrTicker(coinMSymbol, 'coinm'); // wsClient.subscribeSymbolMini24hrTicker(market, 'spot'); // wsClient.subscribeSymbol24hrTicker(market, 'usdm'); // wsClient.subscribeSymbol24hrTicker(market, 'coinm'); // wsClient.subscribeSymbol24hrTicker(coinMSymbol, 'spot'); // wsClient.subscribeAllMini24hrTickers('usdm'); // wsClient.subscribeAllMini24hrTickers('coinm'); // wsClient.subscribeAllMini24hrTickers('spot'); // wsClient.subscribeAll24hrTickers('usdm'); // wsClient.subscribeAll24hrTickers('coinm'); // wsClient.subscribeAll24hrTickers('spot'); // wsClient.subscribeAllLiquidationOrders('usdm'); // wsClient.subscribeAllLiquidationOrders('coinm'); // wsClient.subscribeSpotSymbol24hrTicker(market); // wsClient.subscribeAggregateTrades(market, 'usdm'); // wsClient.subscribeSpotPartialBookDepth('ETHBTC', 5, 1000); ⋮---- // wsClient.subscribeAllRollingWindowTickers('spot', '1d'); ================ File: examples/WebSockets/ws-api-client.ts ================ /* eslint-disable @typescript-eslint/no-unused-vars */ // or // import { DefaultLogger, WebsocketAPIClient, WS_KEY_MAP } from 'binance'; // or // const { DefaultLogger, WebsocketAPIClient, WS_KEY_MAP } = require('binance'); ⋮---- import { DefaultLogger, WebsocketAPIClient } from '../../src'; ⋮---- /** * The WS API only works with an Ed25519 API key. * * Check the rest-private-ed25519.md in this folder for more guidance * on preparing this Ed25519 API key. */ ⋮---- // returned by binance, generated using the publicKey (above) // const key = 'BVv39ATnIme5TTZRcC3I04C3FqLVM7vCw3Hf7mMT7uu61nEZK8xV1V5dmhf9kifm'; // Your Ed25519 private key is passed as the "secret" // const secret = privateKey; ⋮---- // function attachEventHandlers<TWSClient extends WebsocketClient>( // wsClient: TWSClient, // ): void { // /** // * General event handlers for monitoring the WebsocketClient // */ // wsClient.on('message', (data) => { // // console.log('raw message received ', JSON.stringify(data)); // }); // wsClient.on('response', (data) => { // // console.log('ws response: ', JSON.stringify(data)); // }); // wsClient.on('open', (data) => { // console.log('ws connected', data.wsKey); // }); // wsClient.on('reconnecting', ({ wsKey }) => { // console.log('ws automatically reconnecting.... ', wsKey); // }); // wsClient.on('reconnected', (data) => { // console.log('ws has reconnected ', data?.wsKey); // }); // wsClient.on('authenticated', (data) => { // console.log('ws has authenticated ', data?.wsKey); // }); // wsClient.on('exception', (data) => { // console.error('ws exception: ', JSON.stringify(data)); // }); // } ⋮---- async function main() ⋮---- // For a more detailed view of the WebsocketClient, enable the `trace` level by uncommenting the below line: // trace: (...params) => console.log(new Date(), 'trace', ...params), ⋮---- // Enforce testnet ws connections, regardless of supplied wsKey // testnet: true, ⋮---- // Note: unless you set this to false, the SDK will automatically call // the `subscribeUserDataStream()` method again if reconnected (if you called it before): // resubscribeUserDataStreamAfterReconnect: true, ⋮---- // If you want your own event handlers instead of the default ones with logs, disable this setting and see the `attachEventHandlers` example below: // attachEventListeners: false ⋮---- // Optional, attach basic event handlers, so nothing is left unhandled // attachEventHandlers(wsClient.getWSClient()); ⋮---- // Optional, if you see RECV Window errors, you can use this to manage time issues. // ! However, make sure you sync your system clock first! // https://github.com/tiagosiebler/awesome-crypto-examples/wiki/Timestamp-for-this-request-is-outside-of-the-recvWindow // wsClient.setTimeOffsetMs(-5000); ⋮---- // Optional. Can be used to prepare a connection before sending commands. // Can be done as part of a bootstrapping workflow, to reduce initial latency when sending the first command // await wsClient.getWSClient().connectWSAPI(WS_KEY_MAP.mainWSAPI); ⋮---- // SPOT - Market data requests ⋮---- // SPOT - Trading requests ⋮---- // SPOT - Account requests ⋮---- // FUTURES - Market data requests ⋮---- // FUTURES - Trading requests ⋮---- // FUTURES - Account requests ⋮---- // Start executing the example workflow ================ File: examples/WebSockets/ws-api-raw-promises.ts ================ /* eslint-disable @typescript-eslint/no-unused-vars */ import { DefaultLogger, WebsocketClient, WS_KEY_MAP, WSAPIWsKey, } from '../../src/index'; ⋮---- // or // import { DefaultLogger, WS_KEY_MAP, WebsocketClient, WSAPIWsKey } from 'binance'; ⋮---- // For a more detailed view of the WebsocketClient, enable the `trace` level by uncommenting the below line: ⋮---- // testnet: true, ⋮---- logger, // Optional: inject a custom logger ⋮---- /** * General event handlers for monitoring the WebsocketClient */ ⋮---- // WS API responses can be processed here too, but that is optional // console.log('ws response: ', JSON.stringify(data)); ⋮---- async function main() ⋮---- /** * * If you haven't connected yet, the WebsocketClient will automatically connect and authenticate you as soon as you send * your first command. That connection will then be reused for every command you send, unless the connection drops - then * it will automatically be replaced with a healthy connection. * * This "not connected yet" scenario can add an initial delay to your first command. If you want to prepare a connection * in advance, you can ask the WebsocketClient to prepare it before you start submitting commands (using the connectWSAPI() method shown below). This is optional. * */ ⋮---- /** * Websockets (with their unique URLs) are tracked using the concept of a "WsKey". * * This WsKey identifies the "main" WS API connection URL (e.g. for spot & margin markets): * wss://ws-api.binance.com:443/ws-api/v3 * * Other notable keys: * - mainWSAPI2: alternative for "main" * - mainWSAPITestnet: "main" testnet * - usdmWSAPI: usdm futures * - usdmWSAPITestnet: usdm futures testnet * - coinmWSAPI: coinm futures * - coinmWSAPITestnet: coinm futures testnet */ ⋮---- // Note: if you set "testnet: true" in the config, this will automatically resolve to WS_KEY_MAP.mainWSAPITestnet (you can keep using mainWSAPI). ⋮---- // Optional, if you see RECV Window errors, you can use this to manage time issues. However, make sure you sync your system clock first! // https://github.com/tiagosiebler/awesome-crypto-examples/wiki/Timestamp-for-this-request-is-outside-of-the-recvWindow // wsClient.setTimeOffsetMs(-5000); ⋮---- // Optional, see above. Can be used to prepare a connection before sending commands. This is not required and will happen automatically // await wsClient.connectWSAPI(WS_API_WS_KEY); ⋮---- // rateLimits: wsAPIResponse.result.rateLimits, // symbols: wsAPIResponse.result.symbols, ⋮---- // Start executing the example workflow ================ File: examples/WebSockets/ws-close.ts ================ import { DefaultLogger, WebsocketClient } from '../../src/index'; ⋮---- // or // import { DefaultLogger, WebsocketClient } from 'binance'; ⋮---- // unsubscribe from user data stream (for usd futures) ⋮---- // unsubscribe from individual topics on a connection, one at a time: // wsClient.unsubscribe('!miniTicker@arr', 'main'); ⋮---- // arrays also supported: ================ File: examples/WebSockets/ws-proxy-socks.ts ================ /** * Minimal example for using a socks proxy with the ws client, extracted from https://github.com/tiagosiebler/binance/pull/319 */ import { WebsocketClient } from '../../src/index'; ⋮---- // or // import { WebsocketClient } from 'binance'; ================ File: examples/WebSockets/ws-public-spot-orderbook.ts ================ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable no-unused-vars */ import { DefaultLogger, isWsPartialBookDepthEventFormatted, WebsocketClient, WsMessagePartialBookDepthEventFormatted, } from '../../src/index'; ⋮---- // or, with the npm package /* import { WebsocketClient, DefaultLogger, isWsFormattedTrade, } from 'binance'; */ ⋮---- // trace: () => {}, ⋮---- /** * Simple example for receiving depth snapshots from spot orderbooks */ ⋮---- // Request subscription to the following symbol events: ⋮---- // const symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT']; ⋮---- // Loop through symbols ⋮---- // The old way, convenient but unnecessary: // wsClient.subscribePartialBookDepths(symbol, levels, 1000, 'spot'); ⋮---- // Manually build a topic matching the structure expected by binance: // btcusdt@depth20@1000ms ⋮---- // Request subscribe for these topics in the main product group (spot markets are under "main") ================ File: examples/WebSockets/ws-public-spot-trades.ts ================ import { DefaultLogger, isWsFormattedTrade, WebsocketClient, } from '../../src/index'; ⋮---- // or, with the npm package /* import { WebsocketClient, DefaultLogger, isWsFormattedTrade, } from 'binance'; */ ⋮---- // trace: () => {}, ⋮---- // Request subscription to the following symbol trade events: ⋮---- // Loop through symbols ================ File: examples/WebSockets/ws-public-usdm-funding.ts ================ import { DefaultLogger, isWsFormattedMarkPriceUpdateArray, WebsocketClient, } from '../../src/index'; ⋮---- // or, with the npm package /* import { WebsocketClient, DefaultLogger, isWsFormattedMarkPriceUpdateArray, } from 'binance'; */ ⋮---- // trace: () => {}, ⋮---- // api_key: key, // api_secret: secret, ⋮---- // value is in decimal, multiply by 100 to get percent value ⋮---- // log table sorted alphabetically by symbol ⋮---- // response to command sent via WS stream (e.g LIST_SUBSCRIPTIONS) ================ File: examples/WebSockets/ws-unsubscribe.ts ================ /* eslint-disable @typescript-eslint/no-unused-vars */ import { WebsocketClient } from '../../src/index'; ⋮---- // or, with the npm package /* import { WebsocketClient, DefaultLogger, isWsFormatted24hrTicker, isWsFormattedKline, } from 'binance'; */ ⋮---- /** * * A simple demonstration on how to unsubscribe from one or more topics. * */ ⋮---- // Raw unprocessed incoming data, e.g. if you have the beautifier disabled ⋮---- /** * The Websocket Client will automatically manage connectivity and active topics/subscriptions for you. * * Simply call wsClient.subscribe(topic, wsKey) as many times as you want, with or without an array. */ ⋮---- // Aggregate Trade Streams // https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#aggregate-trade-streams ⋮---- // Kline/Candlestick Streams for UTC // https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#klinecandlestick-streams-for-utc ⋮---- // Individual Symbol Mini Ticker Stream // https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#individual-symbol-mini-ticker-stream ⋮---- // Individual Symbol Ticker Streams // https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#individual-symbol-ticker-streams ⋮---- // Individual Symbol Rolling Window Statistics Streams // https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#individual-symbol-rolling-window-statistics-streams ⋮---- // Average Price // https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#average-price ⋮---- /** * Subscribe to each available type of spot market topic, the new way */ ⋮---- // 5 seconds later, unsubscribe from almost all topics except avg price ================ File: examples/WebSockets/ws-userdata-connection-safety.ts ================ import { DefaultLogger, isWsFormattedFuturesUserDataEvent, isWsFormattedSpotUserDataEvent, isWsFormattedSpotUserDataExecutionReport, isWsFormattedUserDataEvent, WebsocketClient, WsUserDataEvents, } from '../../src/index'; ⋮---- // or // import { DefaultLogger, WebsocketClient } from 'binance'; ⋮---- /** * This extended example for using the user data stream demonstrates one way to handle failures in the first connection attempt of the user data stream. * In most cases this is overkill! */ ⋮---- // optionally block some silly logs from showing in the logger ⋮---- // Optional, hook and customise logging behavior ⋮---- // wsClient.on('message', (data) => { // console.log('raw message received ', JSON.stringify(data, null, 2)); // }); ⋮---- function onUserDataEvent(data: WsUserDataEvents) ⋮---- // the market denotes which API category it came from // if (data.wsMarket.includes('spot')) { ⋮---- // or use a type guard, if one exists (PRs welcome) ⋮---- // The wsKey can be parsed to determine the type of message (what websocket it came from) // if (!Array.isArray(data) && data.wsKey.includes('userData')) { // return onUserDataEvent(data); // } ⋮---- // or use a type guard if available ⋮---- // response to command sent via WS stream (e.g LIST_SUBSCRIPTIONS) ⋮---- // Note: manually re-subscribing like this may only be needed if the FIRST user data connection attempt failed // Capture exceptions using the error event, and handle this. ⋮---- // wsClient.subscribeMarginUserDataStream(); // wsClient.subscribeIsolatedMarginUserDataStream('BTCUSDT'); ================ File: examples/WebSockets/ws-userdata-listenKey-testnet.ts ================ import { DefaultLogger, isWsFormattedFuturesUserDataEvent, isWsFormattedSpotUserDataEvent, isWsFormattedSpotUserDataExecutionReport, isWsFormattedUserDataEvent, WebsocketClient, WsUserDataEvents, } from '../../src/index'; ⋮---- // or // import { DefaultLogger, WebsocketClient } from 'binance'; ⋮---- // console.log('using api credentials: ', { key, secret }); ⋮---- // Optional, hook and customise logging behavior ⋮---- // If you prefer, you can receive raw unprocessed data without the "beautifier": // wsClient.on('message', (data) => { // console.log('raw message received ', JSON.stringify(data, null, 2)); // }); ⋮---- function onUserDataEvent(data: WsUserDataEvents) ⋮---- // the market denotes which API category it came from // if (data.wsMarket.includes('spot')) { ⋮---- // or use a type guard, if one exists (PRs welcome) ⋮---- // Beautified/formatted events from binance: ⋮---- // The wsKey can be parsed to determine the type of message (what websocket it came from) // if (!Array.isArray(data) && data.wsKey.includes('userData')) { // return onUserDataEvent(data); // } ⋮---- // or use a type guard if available ⋮---- // response to command sent via WS stream (e.g LIST_SUBSCRIPTIONS) ⋮---- // This is a good place to check your own state is still in sync with the account state on the exchange, in case any events were missed while the library was reconnecting: // - fetch balances // - fetch positions // - fetch orders ⋮---- // wsClient.subscribeMarginUserDataStream(); // wsClient.subscribeIsolatedMarginUserDataStream('BTCUSDT'); // wsClient.subscribeUsdFuturesUserDataStream(); ⋮---- // setTimeout(() => { // console.log('killing all connections'); // wsClient.closeAll(); // }, 1000 * 15); ================ File: examples/WebSockets/ws-userdata-listenkey.ts ================ // or // import { // DefaultLogger, // isWsFormattedFuturesUserDataEvent, // isWsFormattedSpotUserDataEvent, // isWsFormattedSpotUserDataExecutionReport, // isWsFormattedUserDataEvent, // WebsocketClient, // WsUserDataEvents, // } from 'binance'; ⋮---- import { DefaultLogger, isWsFormattedFuturesUserDataEvent, isWsFormattedSpotUserDataEvent, isWsFormattedSpotUserDataExecutionReport, isWsFormattedUserDataEvent, WebsocketClient, WsUserDataEvents, } from '../../src/index'; import { WsConnectionStateEnum } from '../../src/util/websockets/WsStore.types'; ⋮---- // Optional, hook and customise logging behavior ⋮---- // testnet: true, ⋮---- // wsClient.on('message', (data) => { // console.log('raw message received ', JSON.stringify(data, null, 2)); // }); ⋮---- function onUserDataEvent(data: WsUserDataEvents) ⋮---- // the market denotes which API category it came from // if (data.wsMarket.includes('spot')) { ⋮---- // or use a type guard, if one exists (PRs welcome) ⋮---- // The wsKey can be parsed to determine the type of message (what websocket it came from) // if (!Array.isArray(data) && data.wsKey.includes('userData')) { // return onUserDataEvent(data); // } ⋮---- // or use a type guard if available ⋮---- // response to command sent via WS stream (e.g LIST_SUBSCRIPTIONS) ⋮---- // This is a good place to check your own state is still in sync with the account state on the exchange, in case any events were missed while the library was reconnecting: // - fetch balances // - fetch positions // - fetch orders ⋮---- /** * This example demonstrates subscribing to the user data stream via the * listen key workflow. * * Note: the listen key workflow is deprecated for "spot" markets. Use the * WebSocket API `userDataStream.subscribe` workflow instead (only available * in spot right now). See `subscribeUserDataStream()` in the WebsocketAPIClient. * * Each method below opens a dedicated WS connection attached to an automatically * fetched listen key (a session for your user data stream). * * Once subscribed, you don't need to do anything else. Listen-key keep-alive, refresh, reconnects, etc are all automatically handled by the SDK. */ ⋮---- // Example 1: Spot, by default, routes to the "main" wss domain "wss://stream.binance.com:9443". // No parameters needed, just call the subscribe function. ⋮---- // // Example 2: Optional: subscribe to spot via other wss domains wsClient.subscribeSpotUserDataStream('main2'); // routed to "wss://stream.binance.com:443" ⋮---- // // Example 3: cross margin ⋮---- // Example 4: isolated margin ⋮---- /** * Futures */ ⋮---- // Example 5: usdm futures ⋮---- // Example 6: coinm futures ⋮---- // Example 7: portfolio margin // wsClient.subscribePortfolioMarginUserDataStream(); ⋮---- // Example 8: portfolio margin pro // wsClient.subscribePortfolioMarginUserDataStream('portfolioMarginProUserData'); ⋮---- // after 15 seconds, kill user data connections one by one (or all at once) ⋮---- // console.log('killing all connections at once'); // wsClient.closeAll(); ⋮---- // or: ⋮---- // console.log('killing all connections'); // wsClient.closeAll(); // Example 1: ⋮---- // Example 2: use the wsKey to route to another domain ⋮---- // Example 3: cross margin ⋮---- // Example 4: isolated margin ⋮---- // Example 5: usdm futures ⋮---- // Example 6: coinm futures ⋮---- // // Example 7: portfolio margin // wsClient.unsubscribePortfolioMarginUserDataStream(); // // Example 8: portfolio margin pro // wsClient.unsubscribePortfolioMarginUserDataStream( // 'portfolioMarginProUserData', // ); ⋮---- // after 20 seconds, list the remaining open connections ================ File: examples/WebSockets/ws-userdata-README.MD ================ # User Data Streams - Binance The user data streams are the WebSocket method for asynchronously receiving events when any changes happen on your account. Including but not limited to: - order events (filled/cancelled/updated/etc) - position events - balance events (deposit/withdraw/etc) - misc events (leverage changed, position mode changed, etc) ## Mechanisms There are currently two key mechanisms for subscribing to user data events ### Mechanisms - Listen Key The older and original mechanism involves a listen key. This is requested via the REST API and then used when opening a connection