UNPKG

binance

Version:

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

1,697 lines (1,587 loc) 732 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). ================================================================ 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/, dist/, lib/ - Files matching patterns in .gitignore are excluded - Files matching default ignore patterns are excluded - Content has been compressed - code blocks are separated by ⋮---- delimiter - Files are sorted by Git change count (files with more changes are at the bottom) ================================================================ Directory Structure ================================================================ examples/ auth/ rest-private-ed25519.md rest-private-ed25519.ts rest-private-rsa.md rest-private-rsa.ts REST/ Futures/ rest-future-bracket-order.ts rest-usdm-demo.ts rest-usdm-order-sl.ts rest-usdm-order.ts rest-usdm-private-get.ts rest-usdm-public.ts rest-usdm-testnet.ts misc/ README.md tracking-candles.ts Portfolio Margin/ rest-portfoliomargin-private.ts rest-portfoliomargin-public.ts Spot/ rest-spot-demo.ts rest-spot-exchange-info.ts rest-spot-private-autoinvest.ts rest-spot-private-misc.ts rest-spot-private-trade.ts rest-spot-public.ts WebSockets/ Demo/ ws-demo-spot.ts ws-demo-usdm.ts Misc/ ws-close.ts ws-custom-parser.ts ws-proxy-socks.ts ws-unsubscribe.ts Private(userdata)/ ws-userdata-connection-safety.ts ws-userdata-listenKey-testnet.ts ws-userdata-listenkey.ts ws-userdata-README.MD ws-userdata-wsapi-margin.ts ws-userdata-wsapi.ts Public/ ws-public-spot-orderbook.ts ws-public-spot-trades.ts ws-public-usdm-funding.ts ws-public.ts ws-usdm-market.ts ws-usdm-public.ts WS-API/ ws-api-client.ts ws-api-raw-promises.ts README.md 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 .gitignore .jshintrc .npmignore .nvmrc .prettierrc CHANGELOG.md eslint.config.cjs index.js jest.config.ts jsconfig.json LICENSE.md package.json README.md tsconfig.build.json tsconfig.json tsconfig.linting.json ================================================================ Files ================================================================ ================ 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/REST/Futures/rest-future-bracket-order.ts ================ import { FuturesNewAlgoOrderParams, NewFuturesOrderParams, USDMClient, } from '../../../src/index'; ⋮---- // TODO: check balance and do other validations ⋮---- // create three orders // 1. entry order, // 2. passive reduce-only take profit limit order, // 3. stop loss Algo Service order ================ File: examples/REST/Futures/rest-usdm-demo.ts ================ import { USDMClient } from '../../../src/index'; ⋮---- // or // import { USDMClient } from 'binance'; ⋮---- /** * Demo trading uses real market data with simulated trading. * Perfect for testing strategies without risk. */ ⋮---- async function start() ⋮---- // Get account information on demo trading ⋮---- // Place a test order on demo trading ================ File: examples/REST/Futures/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/Futures/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/Futures/rest-usdm-private-get.ts ================ import { USDMClient } from '../../../src/index'; // import axios from 'axios'; ⋮---- // or // import { USDMClient } from 'binance'; ================ File: examples/REST/Futures/rest-usdm-public.ts ================ import { USDMClient } from '../../../src'; ⋮---- // keepAlive: true, // ... any other params, ================ File: examples/REST/Futures/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/REST/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/REST/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/Portfolio Margin/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/Portfolio Margin/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/Spot/rest-spot-demo.ts ================ import { MainClient } from '../../../src/index'; ⋮---- // or // import { MainClient } from 'binance'; ⋮---- /** * Demo trading uses real market data with simulated trading. * Perfect for testing strategies without risk. */ ⋮---- async function start() ⋮---- // Get account information on demo trading ⋮---- // Place a test order on demo trading ================ File: examples/REST/Spot/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/REST/Spot/rest-spot-private-autoinvest.ts ================ import { MainClient } from '../../../src/index'; ⋮---- // or // import { MainClient } from 'binance'; ================ File: examples/REST/Spot/rest-spot-private-misc.ts ================ import { MainClient } from '../../../src/index'; ⋮---- // or // import { MainClient } from 'binance'; ================ File: examples/REST/Spot/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/Spot/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/README.md ================ # Binance API - Examples This folder contains ready to go examples demonstrating various aspects of this API implementation, written in TypeScript (but they are compatible with pure JavaScript projects). Found something difficult to implement? Contribute to these examples and help others! ## Getting started - Clone the project (or download it as a zip, or install the module in your own project `npm install binance`). - Edit the sample as needed (some samples require edits, e.g API keys or import statements to import from npm, not src). - Execute the sample using tsx: `tsx examples/REST/rest-spot-public.ts`. Samples that refer to API credentials using `process.env.API_KEY_COM` can be spawned with environment variables. Unix/macOS example: ``` APIKEY='apikeypastedhere' APISECRET='apisecretpastedhere' tsx examples/WebSockets/ws-userdata-listenkey.ts ``` Or edit the example directly to hardcode your API keys. ### WebSockets All examples relating to WebSockets can be found in the [examples/WebSockets](./WebSockets/) folder. High level summary of available examples: #### Consumers These are purely for receiving data from Binance's WebSockets (market data, account updates, etc). ##### Market Data These examples demonstrate subscribing to & receiving market data from Binance's WebSockets: - ws-public.ts - Demonstration on general usage of the WebSocket client to subscribe to / unsubscribe from one or more market data topics. - ws-public-spot-orderbook.ts - Subscribing to orderbook events for multiple symbols in spot markets. - ws-public-spot-trades.ts - Subscribing to raw trades for multiple symbols in spot markets. - ws-unsubscribe.ts - Subscribing to a list of topics, and then unsubscribing from a few topics in that list. - ws-public-usdm-funding.ts - Simple example subscribing to a general topic, and how to process incoming events to only extract funding rates from those events. ##### Account Data These examples demonstrate receiving account update events from Binance's WebSockets: - ws-userdata-listenkey.ts - Demonstration on subscribing to various user data streams (spot, margin, futures), - Handling incoming user data events - Using provided type guards to determine which product group the user data event is for (spot, margin, futures, etc). - ws-userdata-listenKey-testnet.ts - Similar to above, but on testnet. - ws-userdata-connection-safety.ts - Demonstration on extra safety around the first user data stream connection. - Note: this is overkill in most situations... ##### WebSocket API These examples demonstrate how to send commands using Binance's WebSocket API (e.g. submitting orders). Very similar to the REST API, but using a persisted WebSocket connection instead of HTTP requests. - ws-api-client.ts - Demonstration of using Binance's WebSocket API in Node.js/JavaScript/TypeScript, using the WebsocketAPIClient. - This WebsocketAPIClient is very similar to a REST client, with one method per available command (endpoint) and fully typed requests & responses. - Routing is automatically handled via the WebsocketClient, including authentication and connection persistence. Just call the functions you need - the SDK does the rest. - From a usage perspective, it feels like a REST API - you can await responses just like a HTTP request. - ws-api-raw-promises.ts - More verbose usage of the WebSocket API using the `sendWSAPIRequest()` method. - The `WebsocketAPIClient` uses this method too, so in most cases it is simple to just use the `WebsocketAPIClient` instead. - ws-userdata-wsapi.ts - The listenKey workflow for the user data stream is deprecated (in spot markets). - This example demonstrates how to subscribe to the user data stream in spot markets, without a listen key, using the WebSocket API. ##### Misc Workflows These are miscellaneous examples that cover one or more of the above categories: - ws-close.ts - Closing the (old listen-key driven) user data stream. - Unsubscribing from various topics. - ws-proxy-socks.ts - Using WebSockets over a SOCKS proxy. - deprecated-ws-public.ts ### REST APIs All examples relating to REST APIs can be found in the [examples/REST](./REST/) folder. Most examples are named around functionality & product group. Any examples with "private" involve API calls relating to your account (such as changing settings or submitting orders, etc), High level summary for some of the available examples, but check the folder for a complete list: #### REST USDM Examples - `rest-future-bracket-order.ts` Creates an entry order plus a passive reduce-only TP limit order and an SL Algo Service order. - `rest-usdm-order.ts` Creates single entry, using `submitNewOrder` - `rest-usdm-order-sl.ts` Modify current Stop Loss order(HedgeMode only) ================ File: src/types/coin.ts ================ import { FuturesContractType, PositionSide } from './futures'; import { numberInString, OrderSide } from './shared'; ⋮---- export interface PositionRisk { symbol: string; positionAmt: numberInString; entryPrice: numberInString; markPrice: numberInString; unRealizedProfit: numberInString; liquidationPrice: numberInString; leverage: numberInString; maxQty: numberInString; marginType: string; isolatedMargin: numberInString; isAutoAddMargin: boolean; positionSide: PositionSide; updateTime: number; } ⋮---- export interface CoinMOpenInterest { symbol: string; pair: string; openInterest: numberInString; contractType: FuturesContractType; time: number; } export type SymbolOrPair = | { pair: string; symbol?: never } | { pair?: never; symbol: string }; ⋮---- export interface CoinMSymbolOrderBookTicker { symbol: string; pair: string; bidPrice: numberInString; bidQty: numberInString; askPrice: numberInString; askQty: numberInString; time: number; } ⋮---- export interface CoinMPaginatedRequest { fromId?: number; startTime?: number; endTime?: number; limit?: number; } ⋮---- export interface CoinMAccountTradeParamsWithPair extends CoinMPaginatedRequest { pair: string; symbol?: never; fromId?: never; } ⋮---- export interface CoinMAccountTradeParamsWithSymbol extends CoinMPaginatedRequest { symbol: string; pair?: never; } ⋮---- export interface CoinMAccountTradeParamsWithFromId extends CoinMPaginatedRequest { fromId: number; startTime?: never; endTime?: never; } ⋮---- export type CoinMAccountTradeParams = | CoinMAccountTradeParamsWithSymbol | CoinMAccountTradeParamsWithPair | CoinMAccountTradeParamsWithFromId; ⋮---- export interface CoinMPositionTrade { symbol: string; id: number; orderId: number; pair: string; side: OrderSide; price: numberInString; qty: numberInString; realizedPnl: numberInString; marginAsset: string; baseQty: numberInString; commission: numberInString; commissionAsset: string; time: number; positionSide: PositionSide; buyer: boolean; maker: boolean; } ⋮---- export interface FundingRate { symbol: string; adjustedFundingRateCap: string; adjustedFundingRateFloor: string; fundingIntervalHours: number; disclaimer: boolean; } ⋮---- export interface GetClassicPortfolioMarginNotionalLimitParams { symbol?: string; pair?: string; } ⋮---- export interface ClassicPortfolioMarginNotionalLimit { symbol: string; pair: string; notionalLimit: string; } ⋮---- export interface ClassicPortfolioMarginAccount { maxWithdrawAmountUSD: string; asset: string; maxWithdrawAmount: string; } ⋮---- export interface FuturesTransactionHistoryDownloadLink { downloadId: string; status: string; url: string; notified: boolean; expirationTimestamp: number; isExpired: boolean | null; } ================ File: src/types/shared.ts ================ // Generic numeric value stored as a string. Can be parsed via parseInt or parseFloat. // Beautifier may convert these to number, if enabled. export type numberInString = string | number; ⋮---- export type ExchangeSymbol = string; ⋮---- export type BooleanString = 'true' | 'false'; export type BooleanStringCapitalised = 'TRUE' | 'FALSE'; ⋮---- export type BinanceBaseUrlKey = | 'spot' | 'spot1' | 'spot2' | 'spot3' | 'spot4' | 'spottest' | 'usdmtest' | 'usdm' | 'coinm' | 'coinmtest' | 'voptions' | 'voptionstest' | 'papi' | 'www'; ⋮---- /** * Time in force. Note: `GTE_GTC` is not officially documented, use at your own risk. */ export type OrderTimeInForce = | 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'GTE_GTC' | 'GTD'; ⋮---- export type StringBoolean = 'TRUE' | 'FALSE'; ⋮---- export type SideEffects = | 'MARGIN_BUY' | 'AUTO_REPAY' | 'NO_SIDE_EFFECT' | 'AUTO_BORROW_REPAY' | 'NO_SIDE_EFFECT'; ⋮---- /** * ACK = confirmation of order acceptance (no placement/fill information) * RESULT = fill state * FULL = fill state + detail on fills and other detail */ export type OrderResponseType = 'ACK' | 'RESULT' | 'FULL'; ⋮---- export type OrderIdProperty = | 'newClientOrderId' | 'newClientStrategyId' | 'listClientOrderId' | 'limitClientOrderId' | 'stopClientOrderId' | 'clientAlgoId' | 'aboveClientOrderId' | 'belowClientOrderId' | 'workingClientOrderId' | 'pendingAboveClientOrderId' | 'pendingBelowClientOrderId' | 'pendingClientOrderId'; ⋮---- export type OrderSide = 'BUY' | 'SELL'; ⋮---- export type OrderStatus = | 'NEW' | 'PARTIALLY_FILLED' | 'FILLED' | 'CANCELED' | 'PENDING_CANCEL' | 'REJECTED' | 'EXPIRED'; ⋮---- export type OrderExecutionType = | 'NEW' | 'CANCELED' | 'REJECTED' | 'TRADE' | 'EXPIRED'; ⋮---- // listStatusType export type OCOStatus = 'RESPONSE' | 'EXEC_STARTED' | 'ALL_DONE'; ⋮---- // listOrderStatus export type OCOOrderStatus = 'EXECUTING' | 'ALL_DONE' | 'REJECT'; ⋮---- export type OrderType = | 'LIMIT' | 'LIMIT_MAKER' | 'MARKET' | 'STOP_LOSS' | 'STOP_LOSS_LIMIT' | 'TAKE_PROFIT' | 'TAKE_PROFIT_LIMIT'; ⋮---- export type OrderListOrderType = | 'STOP_LOSS_LIMIT' | 'STOP_LOSS' | 'LIMIT_MAKER' | 'TAKE_PROFIT' | 'TAKE_PROFIT_LIMIT'; ⋮---- export type SelfTradePreventionMode = | 'EXPIRE_TAKER' | 'EXPIRE_MAKER' | 'EXPIRE_BOTH' | 'NONE'; ⋮---- export interface BasicAssetParam { asset: string; } ⋮---- export interface BasicSymbolParam { symbol: string; isIsolated?: StringBoolean; } ⋮---- export interface SymbolArrayParam { symbols: string[]; } ⋮---- export interface BasicAssetPaginatedParams { asset?: string; startTime?: number; endTime?: number; limit?: number; } export interface BasicSymbolPaginatedParams { symbol?: string; startTime?: number; endTime?: number; limit?: number; } ⋮---- export interface SymbolPrice { symbol: string; price: numberInString; time?: number; } ⋮---- // used by spot and usdm export interface OrderBookParams { symbol: string; limit?: 5 | 10 | 20 | 50 | 100 | 500 | 1000 | 5000; symbolStatus?: string; } ⋮---- export type KlineInterval = | '1s' | '1m' | '3m' | '5m' | '15m' | '30m' | '1h' | '2h' | '4h' | '6h' | '8h' | '12h' | '1d' | '3d' | '1w' | '1M'; ⋮---- export interface GetOrderParams { symbol: string; orderId?: number; origClientOrderId?: string; } ⋮---- export interface GetOrderModifyHistoryParams { symbol: string; orderId?: number; origClientOrderId?: string; startTime?: number; endTime?: number; limit?: number; } ⋮---- export interface HistoricalTradesParams { symbol: string; limit?: number; fromId?: number; } ⋮---- export interface KlinesParams { symbol: string; interval: KlineInterval; startTime?: number; endTime?: number; timeZone?: string; limit?: number; } ⋮---- export type Kline = [ number, // open time numberInString, // open numberInString, // high numberInString, // low numberInString, // close numberInString, // volume number, // close time numberInString, // quote asset volume number, // number of trades numberInString, // taker buy base asset vol numberInString, // taker buy quote asset vol numberInString, // ignore? ]; ⋮---- number, // open time numberInString, // open numberInString, // high numberInString, // low numberInString, // close numberInString, // volume number, // close time numberInString, // quote asset volume number, // number of trades numberInString, // taker buy base asset vol numberInString, // taker buy quote asset vol numberInString, // ignore? ⋮---- /** @deprecated `FuturesKline` will be removed soon. Use `Kline` instead. **/ export type FuturesKline = Kline; export interface RecentTradesParams { symbol: string; limit?: number; } ⋮---- export interface CancelOrderParams { symbol: string; orderId?: number; origClientOrderId?: string; } ⋮---- export interface AmendKeepPriorityParams { symbol: string; orderId?: number; origClientOrderId?: string; newClientOrderId?: string; newQty: numberInString; } ⋮---- export interface CancelOCOParams { symbol: string; orderListId?: number; listClientOrderId?: string; newClientOrderId?: string; } ⋮---- export interface NewOCOParams { symbol: string; listClientOrderId?: string; side: OrderSide; quantity: number; limitClientOrderId?: string; limitStrategyId?: number; limitStrategyType?: number; price: number; limitIcebergQty?: number; trailingDelta?: number; stopClientOrderId?: string; stopPrice: number; stopStrategyId?: number; stopStrategyType?: number; stopLimitPrice?: number; stopIcebergQty?: number; stopLimitTimeInForce?: OrderTimeInForce; newOrderRespType?: OrderResponseType; /** For isolated margin trading only */ isIsolated?: StringBoolean; /** Define a side effect, only for margin trading */ sideEffectType?: SideEffects; } ⋮---- /** For isolated margin trading only */ ⋮---- /** Define a side effect, only for margin trading */ ⋮---- export interface NewOrderListParams< T extends OrderResponseType = OrderResponseType, > { symbol: string; listClientOrderId?: string; side: OrderSide; quantity: number; aboveType: OrderListOrderType; aboveClientOrderId?: string; aboveIcebergQty?: number; abovePrice?: number; aboveStopPrice?: number; aboveTrailingDelta?: number; aboveTimeInForce?: OrderTimeInForce; aboveStrategyId?: number; aboveStrategyType?: number; belowType: OrderListOrderType; belowClientOrderId?: string; belowIcebergQty?: number; belowPrice?: number; belowStopPrice?: number; belowTrailingDelta?: number; belowTimeInForce?: OrderTimeInForce; belowStrategyId?: number; belowStrategyType?: number; newOrderRespType?: T; selfTradePreventionMode?: SelfTradePreventionMode; } ⋮---- export interface SymbolFromPaginatedRequestFromId { symbol: string; fromId?: number; startTime?: number; endTime?: number; limit?: number; } ⋮---- export interface GetAllOrdersParams { symbol: string; orderId?: number; startTime?: number; endTime?: number; limit?: number; } ⋮---- export interface RateLimiter { rateLimitType: 'REQUEST_WEIGHT' | 'ORDERS' | 'RAW_REQUESTS'; interval: 'SECOND' | 'MINUTE' | 'DAY'; intervalNum: number; limit: number; } ⋮---- export interface SymbolPriceFilter { filterType: 'PRICE_FILTER'; minPrice: numberInString; maxPrice: numberInString; tickSize: numberInString; } ⋮---- export interface SymbolPercentPriceFilter { filterType: 'PERCENT_PRICE'; multiplierUp: numberInString; multiplierDown: numberInString; avgPriceMins: number; } ⋮---- export interface SymbolLotSizeFilter { filterType: 'LOT_SIZE'; minQty: numberInString; maxQty: numberInString; stepSize: numberInString; } ⋮---- export interface SymbolMinNotionalFilter { filterType: 'NOTIONAL'; minNotional: numberInString; applyMinToMarket: boolean; maxNotional: numberInString; applyMaxToMarket: boolean; avgPriceMins: number; } ⋮---- export interface SymbolIcebergPartsFilter { filterType: 'ICEBERG_PARTS'; limit: number; } ⋮---- export interface SymbolMarketLotSizeFilter { filterType: 'MARKET_LOT_SIZE'; minQty: numberInString; maxQty: numberInString; stepSize: numberInString; } ⋮---- export interface SymbolMaxOrdersFilter { filterType: 'MAX_NUM_ORDERS'; maxNumOrders: number; } ⋮---- export interface SymbolMaxAlgoOrdersFilter { filterType: 'MAX_NUM_ALGO_ORDERS'; maxNumAlgoOrders: number; } ⋮---- export interface SymbolMaxIcebergOrdersFilter { filterType: 'MAX_NUM_ICEBERG_ORDERS'; maxNumIcebergOrders: number; } ⋮---- export interface SymbolMaxPositionFilter { filterType: 'MAX_POSITION'; maxPosition: numberInString; } ⋮---- export type SymbolFilter = | SymbolPriceFilter | SymbolPercentPriceFilter | SymbolLotSizeFilter | SymbolMinNotionalFilter | SymbolIcebergPartsFilter | SymbolMarketLotSizeFilter | SymbolMaxOrdersFilter | SymbolMaxAlgoOrdersFilter | SymbolMaxIcebergOrdersFilter | SymbolMaxPositionFilter; ⋮---- export interface ExchangeMaxNumOrdersFilter { filterType: 'EXCHANGE_MAX_NUM_ORDERS'; maxNumOrders: number; } ⋮---- export interface ExchangeMaxAlgoOrdersFilter { filterType: 'EXCHANGE_MAX_ALGO_ORDERS'; maxNumAlgoOrders: number; } ⋮---- export type ExchangeFilter = | ExchangeMaxNumOrdersFilter | ExchangeMaxAlgoOrdersFilter; ⋮---- export type OrderBookPrice = numberInString; export type OrderBookAmount = numberInString; ⋮---- export type OrderBookRow = [OrderBookPrice, OrderBookAmount]; ⋮---- export type OrderBookPriceFormatted = number; export type OrderBookAmountFormatted = number; export type OrderBookRowFormatted = [ OrderBookPriceFormatted, OrderBookAmountFormatted, ]; ⋮---- export interface GenericCodeMsgError { code: number; msg: string; } ⋮---- export interface RowsWithTotal<T> { rows: T[]; total: number; } ⋮---- export interface CoinStartEndLimit { coin?: string; startTime?: number; endTime?: number; limit?: number; } ================ File: .jshintrc ================ { "esversion": 8, "asi": true, "laxbreak": true, "predef": [ "-Promise" ] } ================ File: .npmignore ================ .gitignore coverage/ test/ util/ .vscode/ .eslintrc.js .travis.yml .mocharc.json .prettierrc ================ File: .prettierrc ================ { "tabWidth": 2, "singleQuote": true, "trailingComma": "all" } ================ File: CHANGELOG.md ================ # Binance API ## 2.0.14 - Update values thrown by exception parser. ## 2.0.13 - Expose time sync offset getter/setter in base client. `getTimeOffset()/setTimeOffest(value)`. - Add handler to signMessage method, falling back to browser equivalent if method is not a function (react/preact/#141). ## 2.0.12 - Increase default timeout for websocket pong heartbeats to 7500ms. ## 2.0.11 - Fix APIs that use the DELETE method. ## 2.0.9-10 - Fix typo in websocket types. - Fix missing type properties for ws messages. ## 2.0.8 - Emit `reconnected` events for reconnected user data stream. ## 2.0.6 - Fix symbol & margin asset types for futures user data updated position event. ## 2.0.5 - Refine types for user data websocket events (futures) ## 2.0.4 - Disable 'silly' logger category by default to reduce ping/pong noise. - Expand ws support to other API categories. - Expand beautifier support for other WS messages. ## 2.0.3 - Expand main-client APIs. - Expand usdm-client APIs. ## 2.0.2 - Fix getAccountInformation main endpoint. - Fix a few missing APIs. - Refactor SpotClient->MainClient. SpotClient will be deprecated in future (MainClient is the same, just a different name). - Fix build errors from incorrect module imports. ## 2.0.0 - Introduction for typescript with strong types on most request parameters & responses. - NPM package includes transpiled framework & type declarations. - Supports both typescript and vanilla node.js projects. - REST requests and responses include detailed types, though some may still be missing. - Raw and beautified WS events include detailed types, though some may still be missing. - Introduction for webpack. - To generate a browser bundle clone & build the library then run webpack using `npm run pack`. - Introduction for integration tests via jest on all REST clients. - Tests are executed automatically to avoid unintended breaking changes on release. - Real API calls are made to validate integration. - Complete networking overhaul using [axios](https://github.com/axios/axios). - Small & modern framework. Significant reduction in dependencies via deprecation of `request`. - Support for proxies and [other axios-supported functionality](https://github.com/axios/axios#request-config). - Support for backend (node) and frontend (browser) requests. - Complete overhaul in websockets client. - Websocket events are still (optionally) beautified consistently with how the previous library worked. - New event-driven architecture. - Support for USDM Futures. More to come in a future release. - Automatic connection monitoring, with automatic reconnect if the connection goes stale. - Automatic userData connection monitoring, with automatic refresh and respawn if previous listen key expires or the connection closes unexpectedly. - Complete overhaul in REST client. - Revamped spot client (see [spot-client](./src/spot-client.ts)). - Introduction of [usdm-client](./src/usdm-client.ts) for USDM Futures. - Passive tracking & storage of API limit states (IP request weight & order weight). - Parsed automatically via response headers when any request is made, if header is detected. - See `getRateLimitStates()` to query the last seen weights on any of the REST clients. - Smarter time-sync to handle common recvWindow latency issues (optional, default on). ### 2.0.0-beta.4 - Breaking change: refactor most options to camel case (instead of underscore separation). - Add optional beautifier support for REST responses (parses known numbers stored as strings into numbers). ### 2.0.0-beta.5-8 - Breaking change: refactor spot getAllCoinsInformation to getBalances(). - Fix POST request format to www-form-urlencoded. <!-- ## 2.0.1 --> <!-- - Introduction of [coinm-client](./src/coinm-client.ts) for COINM Futures. --> <!-- - Introduction of [vanilla-client](./src/vanilla-client.ts) for Vanilla Options. --> ================ File: index.js ================ ================ File: jest.config.ts ================ /** * For a detailed explanation regarding each configuration property, visit: * https://jestjs.io/docs/configuration */ ⋮---- import type { Config } from 'jest'; ⋮---- // All imported modules in your tests should be mocked automatically // automock: false, ⋮---- // Stop running tests after `n` failures // bail: 0, bail: false, // enable to stop test when an error occur, ⋮---- // The directory where Jest should store its cached dependency information // cacheDirectory: "/private/var/folders/kf/2k3sz4px6c9cbyzj1h_b192h0000gn/T/jest_dx", ⋮---- // Automatically clear mock calls, instances, contexts and results before every test ⋮---- // Indicates whether the coverage information should be collected while executing the test ⋮---- // An array of glob patterns indicating a set of files for which coverage information should be collected ⋮---- // The directory where Jest should output its coverage files ⋮---- // An array of regexp pattern strings used to skip coverage collection // coveragePathIgnorePatterns: [ // "/node_modules/" // ], ⋮---- // Indicates which provider should be used to instrument code for coverage ⋮---- // A list of reporter names that Jest uses when writing coverage reports // coverageReporters: [ // "json", // "text", // "lcov", // "clover" // ], ⋮---- // An object that configures minimum threshold enforcement for coverage results // coverageThreshold: undefined, ⋮---- // A path to a custom dependency extractor // dependencyExtractor: undefined, ⋮---- // Make calling deprecated APIs throw helpful error messages // errorOnDeprecated: false, ⋮---- // The default configuration for fake timers // fakeTimers: { // "enableGlobally": false // }, ⋮---- // Force coverage collection from ignored files using an array of glob patterns // forceCoverageMatch: [], ⋮---- // A path to a module which exports an async function that is triggered once before all test suites // globalSetup: undefined, ⋮---- // A path