diff --git a/README.md b/README.md index 1239f734..4fbc7da5 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ Node.js & JavaScript SDK for the Bybit REST APIs and WebSockets: Check out my related projects: - Try my connectors: - - [binance](https://www.npmjs.com/package/binance) - [bybit-api](https://www.npmjs.com/package/bybit-api) + - [binance](https://www.npmjs.com/package/binance) - [okx-api](https://www.npmjs.com/package/okx-api) - [bitget-api](https://www.npmjs.com/package/bitget-api) - Try my misc utilities: @@ -44,7 +44,8 @@ Check out my related projects: Most methods accept JS objects. These can be populated using parameters specified by Bybit's API documentation, or check the type definition in each class within the github repository (see table below for convenient links to each class). -- [Bybit API Docs (choose API category from the tabs at the top)](https://bybit-exchange.github.io/docs/v5/intro). +- [Bybit API Docs](https://bybit-exchange.github.io/docs/v5/intro) +- [TSDoc Documentation (generated using typedoc via npm module)](https://tsdocs.dev/docs/bybit-api) ## Structure @@ -66,29 +67,44 @@ Refer to the [V5 interface mapping page](https://bybit-exchange.github.io/docs/v Here are the available REST clients and the corresponding API groups described in the documentation: -| Class | Description | -| :------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| [ **V5 API** ] | The new unified V5 APIs (successor to previously fragmented APIs for all API groups). To learn more about the V5 API, please read the [V5 upgrade guideline](https://bybit-exchange.github.io/docs/v5/upgrade-guide). | -| [RestClientV5](src/rest-client-v5.ts) | Unified V5 all-in-one REST client for all [V5 REST APIs](https://bybit-exchange.github.io/docs/v5/intro) | -| [ **Derivatives v3** ] | The Derivatives v3 APIs (successor to the Futures V2 APIs) | -| [UnifiedMarginClient](src/unified-margin-client.ts) | [Derivatives (v3) Unified Margin APIs](https://bybit-exchange.github.io/docs/derivatives/unified/place-order) | -| [ContractClient](src/contract-client.ts) | [Derivatives (v3) Contract APIs](https://bybit-exchange.github.io/docs/derivatives/contract/place-order). | -| [ **Futures v2** ] | The Futures v2 APIs | -| Deprecated! RestClientV5 recommended | Please read the [V5 interface mapping page](https://bybit-exchange.github.io/docs/v5/intro#v5-and-v3-interface-mapping-list) | -| [~InverseClient~](src/inverse-client.ts) | [Inverse Perpetual Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/inverse/) | -| [~LinearClient~](src/linear-client.ts) | [USDT Perpetual Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/linear/#t-introduction) | -| [~InverseFuturesClient~](src/inverse-futures-client.ts) | [Inverse Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/inverse_futures/#t-introduction) | -| [ **Spot** ] | The spot APIs | -| [SpotClientV3](src/spot-client-v3.ts) | [Spot Market (v3) APIs](https://bybit-exchange.github.io/docs/spot/public/instrument) | -| [~SpotClient~](src/spot-client.ts) (deprecated, SpotClientV3 recommended) | [Spot Market (v1) APIs](https://bybit-exchange.github.io/docs/spot/v1/#t-introduction) | -| [ **USDC Contract** ] | The USDC Contract APIs | -| [USDCPerpetualClient](src/usdc-perpetual-client.ts) | [USDC Perpetual APIs](https://bybit-exchange.github.io/docs/usdc/option/?console#t-querydeliverylog) | -| [USDCOptionClient](src/usdc-option-client.ts) | [USDC Option APIs](https://bybit-exchange.github.io/docs/usdc/option/#t-introduction) | -| [ **Other** ] | Other standalone API groups | -| [CopyTradingClient](src/copy-trading-client.ts) | [Copy Trading APIs](https://bybit-exchange.github.io/docs/category/copy-trade) | -| [AccountAssetClientV3](src/account-asset-client-v3.ts) | [Account Asset V3 APIs](https://bybit-exchange.github.io/docs/account-asset/internal-transfer) | -| [~AccountAssetClient~](src/account-asset-client.ts) (deprecated, AccountAssetClientV3 recommended) | [Account Asset V1 APIs](https://bybit-exchange.github.io/docs/account_asset/v1/#t-introduction) | -| [WebsocketClient](src/websocket-client.ts) | All WebSocket Events (Public & Private for all API categories) | +| Class | Description | +| :----------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| [ **V5 API** ] | The new unified V5 APIs (successor to previously fragmented APIs for all API groups). To learn more about the V5 API, please read the [V5 upgrade guideline](https://bybit-exchange.github.io/docs/v5/upgrade-guide). | +| [RestClientV5](src/rest-client-v5.ts) | Unified V5 all-in-one REST client for all [V5 REST APIs](https://bybit-exchange.github.io/docs/v5/intro) | +| [WebsocketClient](src/websocket-client.ts) | All WebSocket Events (Public & Private for all API categories) | +| [ **Derivatives v3** ] | The Derivatives v3 APIs (successor to the Futures V2 APIs) | +| [UnifiedMarginClient](src/unified-margin-client.ts) | [Derivatives (v3) Unified Margin APIs](https://bybit-exchange.github.io/docs/derivatives/unified/place-order) | +| [ContractClient](src/contract-client.ts) | [Derivatives (v3) Contract APIs](https://bybit-exchange.github.io/docs/derivatives/contract/place-order). | +| [ **Other** ] | Other standalone API groups | +| [CopyTradingClient](src/copy-trading-client.ts) | [Copy Trading APIs](https://bybit-exchange.github.io/docs/category/copy-trade) | +| [AccountAssetClientV3](src/account-asset-client-v3.ts) | [Account Asset V3 APIs](https://bybit-exchange.github.io/docs/account-asset/internal-transfer) | + +--- + +### Deprecated/Obsolete APIs + +The following API clients are for previous generation REST APIs and will be removed in the next major release. Some have already stopped working (because bybit stopped supporting them). You should use the V5 APIs for all new development. + +
+ Click me to see the list of APIs + +| Class | Description | +| :--------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------: | +| [ **Futures v2** ] | The Futures v2 APIs | +| [~~InverseClient~~](src/inverse-client.ts) | [Inverse Perpetual Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/inverse/) | +| [~~LinearClient~~](src/linear-client.ts) | [USDT Perpetual Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/linear/#t-introduction) | +| [~~InverseFuturesClient~~](src/inverse-futures-client.ts) | [Inverse Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/inverse_futures/#t-introduction) | +| [ **Spot** ] | The spot APIs | +| [SpotClientV3](src/spot-client-v3.ts) | [Spot Market (v3) APIs](https://bybit-exchange.github.io/docs/spot/public/instrument) | +| [~~SpotClient~~](src/spot-client.ts) (deprecated, SpotClientV3 recommended) | [Spot Market (v1) APIs](https://bybit-exchange.github.io/docs/spot/v1/#t-introduction) | +| [ **USDC Contract** ] | The USDC Contract APIs | +| [USDCPerpetualClient](src/usdc-perpetual-client.ts) | [USDC Perpetual APIs](https://bybit-exchange.github.io/docs/usdc/option/?console#t-querydeliverylog) | +| [USDCOptionClient](src/usdc-option-client.ts) | [USDC Option APIs](https://bybit-exchange.github.io/docs/usdc/option/#t-introduction) | +| [~~AccountAssetClient~~](src/account-asset-client.ts) (deprecated, AccountAssetClientV3 recommended) | [Account Asset V1 APIs](https://bybit-exchange.github.io/docs/account_asset/v1/#t-introduction) | + +
+ +--- Examples for using each client can be found in: @@ -137,12 +153,6 @@ const restClientOptions = { /** Override the max size of the request window (in ms) */ recv_window?: number; - /** Disabled by default. This can help on machines with consistent latency problems. */ - enable_time_sync?: boolean; - - /** How often to sync time drift with bybit servers */ - sync_interval_ms?: number | string; - /** Default: false. If true, we'll throw errors if any params are undefined */ strict_param_validation?: boolean; @@ -169,7 +179,9 @@ const useTestnet = false; const client = new RestClientV5({ key: API_KEY, secret: API_SECRET, - testnet: useTestnet + testnet: useTestnet, + // Optional: enable to try parsing rate limit values from responses + // parseAPIRateLimits: true }, // requestLibraryOptions ); @@ -201,21 +213,39 @@ All API groups can be used via a shared `WebsocketClient`. However, to listen to The WebsocketClient can be configured to a specific API group using the market parameter. These are the currently available API groups: | API Category | Market | Description | |:----------------------------: |:-------------------: |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Unified Margin - Options | `market: 'unifiedOption'`| The [derivatives v3](https://bybit-exchange.github.io/docs/derivativesV3/unified_margin/#t-websocket) category for unified margin. Note: public topics only support options topics. If you need USDC/USDT perps, use `unifiedPerp` instead. | -| Unified Margin - Perps | `market: 'unifiedPerp'` | The [derivatives v3](https://bybit-exchange.github.io/docs/derivativesV3/unified_margin/#t-websocket) category for unified margin. Note: public topics only support USDT/USDC perpetual topics - use `unifiedOption` if you need public options topics. | -| Futures v2 - Inverse Perps | `market: 'inverse'` | The [inverse v2 perps](https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-websocket) category. | -| Futures v2 - USDT Perps | `market: 'linear'` | The [USDT/linear v2 perps](https://bybit-exchange.github.io/docs/futuresV2/linear/#t-websocket) category. | -| Futures v2 - Inverse Futures | `market: 'inverse'` | The [inverse futures v2](https://bybit-exchange.github.io/docs/futuresV2/inverse_futures/#t-websocket) category uses the same market as inverse perps. | -| Spot v3 | `market: 'spotv3'` | The [spot v3](https://bybit-exchange.github.io/docs/spot/v3/#t-websocket) category. | -| Spot v1 | `market: 'spot'` | The older [spot v1](https://bybit-exchange.github.io/docs/spot/v1/#t-websocket) category. Use the `spotv3` market if possible, as the v1 category does not have automatic re-subscribe if reconnected. | -| Copy Trading | `market: 'linear'` | The [copy trading](https://bybit-exchange.github.io/docs/copy_trading/#t-websocket) category. Use the linear market to listen to all copy trading topics. | -| USDC Perps | `market: 'usdcPerp` | The [USDC perps](https://bybit-exchange.github.io/docs/usdc/perpetual/#t-websocket) category. | -| USDC Options | `market: 'usdcOption'`| The [USDC options](https://bybit-exchange.github.io/docs/usdc/option/#t-websocket) category. | -| Contract v3 USDT | `market: 'contractUSDT'`| The [Contract V3](https://bybit-exchange.github.io/docs/derivativesV3/contract/#t-websocket) category (USDT perps) | -| Contract v3 Inverse | `market: 'contractInverse'`| The [Contract V3](https://bybit-exchange.github.io/docs/derivativesV3/contract/#t-websocket) category (inverse perps) | | V5 Subscriptions | `market: 'v5'` | The [v5](https://bybit-exchange.github.io/docs/v5/ws/connect) websocket topics for all categories under one market. Use the subscribeV5 method when subscribing to v5 topics. | -For more complete examples, look into the ws-\* examples in the [examples](./examples/) folder in the repo on GitHub. Here's a minimal example for using the websocket client: +--- + +### Older Websocket APIs + +The following API groups are still available in the WebsocketClient but are deprecated and may no longer work. They will be removed in the next major release: + +
+ Click me to see the table + +| API Category | Market | Description | +| :------------------------------: | :-------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ~~Unified Margin - Options~~ | `market: 'unifiedOption'` | The [derivatives v3](https://bybit-exchange.github.io/docs/derivativesV3/unified_margin/#t-websocket) category for unified margin. Note: public topics only support options topics. If you need USDC/USDT perps, use `unifiedPerp` instead. | +| ~~Unified Margin - Perps~~ | `market: 'unifiedPerp'` | The [derivatives v3](https://bybit-exchange.github.io/docs/derivativesV3/unified_margin/#t-websocket) category for unified margin. Note: public topics only support USDT/USDC perpetual topics - use `unifiedOption` if you need public options topics. | +| ~~Futures v2 - Inverse Perps~~ | `market: 'inverse'` | The [inverse v2 perps](https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-websocket) category. | +| ~~Futures v2 - USDT Perps~~ | `market: 'linear'` | The [USDT/linear v2 perps](https://bybit-exchange.github.io/docs/futuresV2/linear/#t-websocket) category. | +| ~~Futures v2 - Inverse Futures~~ | `market: 'inverse'` | The [inverse futures v2](https://bybit-exchange.github.io/docs/futuresV2/inverse_futures/#t-websocket) category uses the same market as inverse perps. | +| ~~Spot v3~~ | `market: 'spotv3'` | The [spot v3](https://bybit-exchange.github.io/docs/spot/v3/#t-websocket) category. | +| ~~Spot v1~~ | `market: 'spot'` | The older [spot v1](https://bybit-exchange.github.io/docs/spot/v1/#t-websocket) category. Use the `spotv3` market if possible, as the v1 category does not have automatic re-subscribe if reconnected. | +| ~~Copy Trading~~ | `market: 'linear'` | The [copy trading](https://bybit-exchange.github.io/docs/copy_trading/#t-websocket) category. Use the linear market to listen to all copy trading topics. | +| ~~USDC Perps~~ | `market: 'usdcPerp` | The [USDC perps](https://bybit-exchange.github.io/docs/usdc/perpetual/#t-websocket) category. | +| ~~USDC Options~~ | `market: 'usdcOption'` | The [USDC options](https://bybit-exchange.github.io/docs/usdc/option/#t-websocket) category. | +| ~~Contract v3 USDT~~ | `market: 'contractUSDT'` | The [Contract V3](https://bybit-exchange.github.io/docs/derivativesV3/contract/#t-websocket) category (USDT perps) | +| ~~Contract v3 Inverse~~ | `market: 'contractInverse'` | The [Contract V3](https://bybit-exchange.github.io/docs/derivativesV3/contract/#t-websocket) category (inverse perps) | + +
{ diff --git a/examples/rest-v5-proxies.ts b/examples/rest-v5-proxies.ts new file mode 100644 index 00000000..89a2c7a1 --- /dev/null +++ b/examples/rest-v5-proxies.ts @@ -0,0 +1,66 @@ +import { RestClientV5 } from '../src/index'; + +// or +// import { RestClientV5 } from 'bybit-api'; + +const key = process.env.API_KEY_COM; +const secret = process.env.API_SECRET_COM; + +const client = new RestClientV5( + { + key: key, + secret: secret, + parseAPIRateLimits: true, + testnet: true, + // Sometimes using a proxy introduces recv timestamp errors (due to the extra latency) + // If that happens, you can try increasing the recv window (which is 5000ms by default) + // recv_window: 10000, + }, + { + proxy: { + host: 'proxyhost', + port: Number('proxyport'), + auth: { + username: 'proxyuserifneeded', + password: 'proxypassifneeded', + }, + }, + }, +); + +(async () => { + try { + const res = await client.getWalletBalance({ accountType: 'UNIFIED' }); + + console.log('response: ', JSON.stringify(res, null, 2)); + + // const orders = await client.batchSubmitOrders('linear', [ + // { + // symbol: 'ETHUSDT', + // orderType: 'Limit', + // side: 'Buy', + // qty: '1', + // orderIv: '6', + // timeInForce: 'GTC', + // orderLinkId: 'option-test-001', + // mmp: false, + // reduceOnly: false, + // }, + // { + // symbol: 'ETHUSDT', + // orderType: 'Limit', + // side: 'Sell', + // qty: '2', + // price: '700', + // timeInForce: 'GTC', + // orderLinkId: 'option-test-001', + // mmp: false, + // reduceOnly: false, + // }, + // ]); + + // console.log('orders: ', JSON.stringify(orders, null, 2)); + } catch (e) { + console.error('request failed: ', e); + } +})(); diff --git a/examples/rest-v5-public.ts b/examples/rest-v5-public.ts new file mode 100644 index 00000000..51377c0b --- /dev/null +++ b/examples/rest-v5-public.ts @@ -0,0 +1,61 @@ +import { RestClientV5 } from '../src/index'; + +// or +// import { RestClientV5 } from 'bybit-api'; + +/** + * If you don't plan on making any private api calls, + * you can instance the REST client without any parameters + */ +const client = new RestClientV5(); + +(async () => { + try { + // const klineResult = await client.getKline({ + // category: 'linear', + // interval: '15', + // symbol: 'BTCUSDT', + // }); + // console.log('klineResult: ', klineResult); + + // const markPriceKlineResult = await client.getMarkPriceKline({ + // category: 'linear', + // interval: '15', + // symbol: 'BTCUSDT', + // }); + // console.log('markPriceKlineResult: ', markPriceKlineResult); + + // const indexPriceKline = await client.getIndexPriceKline({ + // category: 'linear', + // interval: '15', + // symbol: 'BTCUSDT', + // }); + // console.log('indexPriceKline: ', indexPriceKline); + + // const openInterest = await client.getOpenInterest({ + // category: 'linear', + // symbol: 'BTCUSDT', + // intervalTime: '5min', + // }); + + const tickers = await client.getTickers({ category: 'linear' }); + // console.log( + // JSON.stringify( + // tickers.result.list.map((ticker) => ticker.symbol), + // null, + // 2, + // ), + // ); + + console.log('response', tickers); + // openInterest.result.list.forEach((row) => { + // console.log('int: ', { + // timestamp: row.timestamp, + // value: row.openInterest, + // }); + // }); + // console.log('openInterest: ', openInterest.result.list); + } catch (e) { + console.error('request failed: ', e); + } +})(); diff --git a/package-lock.json b/package-lock.json index 0fafd4eb..60c0db2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bybit-api", - "version": "3.7.6", + "version": "3.8.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "bybit-api", - "version": "3.7.6", + "version": "3.8.0", "license": "MIT", "dependencies": { "axios": "^0.21.0", diff --git a/package.json b/package.json index 13e2c41b..e5a1af9e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bybit-api", - "version": "3.7.8", + "version": "3.8.0", "description": "Complete & robust Node.js SDK for Bybit's REST APIs and WebSockets, with TypeScript & strong end to end tests.", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/src/types/request/v5-asset.ts b/src/types/request/v5-asset.ts index 3e151427..b20402de 100644 --- a/src/types/request/v5-asset.ts +++ b/src/types/request/v5-asset.ts @@ -127,7 +127,15 @@ export interface WithdrawParamsV5 { export interface CreateSubMemberParamsV5 { username: string; + password?: string; + /** + * 1: normal, 6: custodial + */ memberType: 1 | 6; + /** + * 0: quick login disabled (default), 1: quick login enabled + */ switch?: 0 | 1; + isUta?: boolean; note?: string; } diff --git a/src/util/websocket-util.ts b/src/util/websocket-util.ts index a2d27f83..400b81f1 100644 --- a/src/util/websocket-util.ts +++ b/src/util/websocket-util.ts @@ -1,3 +1,5 @@ +import WebSocket from 'isomorphic-ws'; + import { APIMarket, CategoryV5, WsKey } from '../types'; import { DefaultLogger } from './logger'; @@ -548,3 +550,15 @@ export const WS_ERROR_ENUM = { export function neverGuard(x: never, msg: string): Error { return new Error(`Unhandled value exception "x", ${msg}`); } + +/** + * #305: ws.terminate() is undefined in browsers. + * This only works in node.js, not in browsers. + * Does nothing if `ws` is undefined. + */ +export function safeTerminateWs(ws?: WebSocket | unknown) { + // #305: ws.terminate() undefined in browsers + if (ws && typeof ws['terminate'] === 'function') { + ws.terminate(); + } +} diff --git a/src/websocket-client.ts b/src/websocket-client.ts index ade0eeb0..595243ea 100644 --- a/src/websocket-client.ts +++ b/src/websocket-client.ts @@ -40,6 +40,7 @@ import { isTopicSubscriptionSuccess, isWsPong, neverGuard, + safeTerminateWs, serializeParams, } from './util'; import { RestClientV5 } from './rest-client-v5'; @@ -462,7 +463,7 @@ export class WebsocketClient extends EventEmitter { const ws = this.getWs(wsKey); ws?.close(); if (force) { - ws?.terminate(); + safeTerminateWs(ws); } } @@ -808,11 +809,16 @@ export class WebsocketClient extends EventEmitter { const wasOpen = this.wsStore.isWsOpen(wsKey); - this.getWs(wsKey)?.terminate(); - delete this.wsStore.get(wsKey, true).activePongTimer; this.clearPingTimer(wsKey); this.clearPongTimer(wsKey); + const ws = this.getWs(wsKey); + + if (ws) { + ws.close(); + safeTerminateWs(ws); + } + if (!wasOpen) { this.logger.info( `${reason} - socket already closed - trigger immediate reconnect`, diff --git a/test/account-asset/private.read.test.ts b/test/account-asset/private.read.test.ts index e7f1326a..371f2c75 100644 --- a/test/account-asset/private.read.test.ts +++ b/test/account-asset/private.read.test.ts @@ -40,7 +40,7 @@ describe('Private Account Asset REST API GET Endpoints', () => { }); }); - it('getUniversalTransfers()', async () => { + it.skip('getUniversalTransfers()', async () => { expect(await api.getInternalTransfers()).toMatchObject( successResponseObject(), ); diff --git a/test/account-asset/private.v3.read.test.ts b/test/account-asset/private.v3.read.test.ts index 4dc99648..895b1fb3 100644 --- a/test/account-asset/private.v3.read.test.ts +++ b/test/account-asset/private.v3.read.test.ts @@ -49,7 +49,7 @@ describe('Private Account Asset V3 REST API Endpoints', () => { }); }); - it('getUniversalTransfers()', async () => { + it.skip('getUniversalTransfers()', async () => { expect(await api.getUniversalTransfers({ coin: coin })).toMatchObject({ ...successResponseObjectV3(), retCode: API_ERROR_CODE.INCORRECT_API_KEY_PERMISSIONS,