unified margin support for ws
This commit is contained in:
@@ -152,15 +152,16 @@ All API groups can be used via a shared `WebsocketClient`. However, make sure to
|
|||||||
The WebsocketClient can be configured to a specific API group using the market parameter. These are the currently available API groups:
|
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 |
|
| API Category | Market | Description |
|
||||||
|:----------------------------: |:-------------------: |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|:----------------------------: |:-------------------: |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| Unified Margin | TBC | The [derivatives v3](https://bybit-exchange.github.io/docs/derivativesV3/unified_margin/#t-websocket) category for unified margin. |
|
| 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 USDT/USDC perps 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 - 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 - 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. |
|
| 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 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. |
|
| 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. |
|
| 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 | TBC | The [USDC perps](https://bybit-exchange.github.io/docs/usdc/perpetual/#t-websocket) category. |
|
| USDC Perps | `market: 'usdcPerp` | The [USDC perps](https://bybit-exchange.github.io/docs/usdc/perpetual/#t-websocket) category. |
|
||||||
| USDC Options | TBC | The [USDC options](https://bybit-exchange.github.io/docs/usdc/option/#t-websocket) category. |
|
| USDC Options | `market: 'usdcOption'`| The [USDC options](https://bybit-exchange.github.io/docs/usdc/option/#t-websocket) category. |
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { WebsocketClient } = require('bybit-api');
|
const { WebsocketClient } = require('bybit-api');
|
||||||
@@ -181,7 +182,6 @@ const wsConfig = {
|
|||||||
|
|
||||||
// NOTE: to listen to multiple markets (spot vs inverse vs linear vs linearfutures) at once, make one WebsocketClient instance per market
|
// NOTE: to listen to multiple markets (spot vs inverse vs linear vs linearfutures) at once, make one WebsocketClient instance per market
|
||||||
|
|
||||||
// defaults to inverse:
|
|
||||||
// market: 'inverse'
|
// market: 'inverse'
|
||||||
// market: 'linear'
|
// market: 'linear'
|
||||||
// market: 'spot'
|
// market: 'spot'
|
||||||
|
|||||||
@@ -1,223 +0,0 @@
|
|||||||
# Websocket API
|
|
||||||
## Class: WebsocketClient
|
|
||||||
|
|
||||||
The `WebsocketClient` inherits from `EventEmitter`. After establishing a
|
|
||||||
connection, the client sends heartbeats in regular intervalls, and reconnects
|
|
||||||
to the server once connection has been lost.
|
|
||||||
|
|
||||||
### new WebsocketClient([options][, logger])
|
|
||||||
- `options` {Object} Configuration options
|
|
||||||
- `key` {String} Bybit API Key. Only needed if private topics are subscribed
|
|
||||||
- `secret` {String} Bybit private Key. Only needed if private topics are
|
|
||||||
subscribed
|
|
||||||
- `livenet` {Bool} Weather to connect to livenet (`true`). Default `false`.
|
|
||||||
- `pingInterval` {Integer} Interval in ms for heartbeat ping. Default: `10000`,
|
|
||||||
- `pongTimeout` {Integer} Timeout in ms waiting for heartbeat pong response
|
|
||||||
from server. Default: `1000`,
|
|
||||||
- `reconnectTimeout` {Integer} Timeout in ms the client waits before trying
|
|
||||||
to reconnect after a lost connection. Default: 500
|
|
||||||
- `logger` {Object} Optional custom logger
|
|
||||||
|
|
||||||
Custom logger must contain the following methods:
|
|
||||||
```js
|
|
||||||
const logger = {
|
|
||||||
silly: function(message, data) {},
|
|
||||||
debug: function(message, data) {},
|
|
||||||
notice: function(message, data) {},
|
|
||||||
info: function(message, data) {},
|
|
||||||
warning: function(message, data) {},
|
|
||||||
error: function(message, data) {},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### ws.subscribe(topics)
|
|
||||||
- `topics` {String|Array} Single topic as string or multiple topics as array of strings.
|
|
||||||
Subscribe to one or multiple topics. See [available topics](#available-topics)
|
|
||||||
|
|
||||||
### ws.unsubscribe(topics)
|
|
||||||
- `topics` {String|Array} Single topic as string or multiple topics as array of strings.
|
|
||||||
Unsubscribe from one or multiple topics.
|
|
||||||
|
|
||||||
### ws.close()
|
|
||||||
Close the connection to the server.
|
|
||||||
|
|
||||||
### Event: 'open'
|
|
||||||
Emmited when the connection has been opened for the first time.
|
|
||||||
|
|
||||||
### Event: 'reconnected'
|
|
||||||
Emmited when the client has been opened after a reconnect.
|
|
||||||
|
|
||||||
### Event: 'update'
|
|
||||||
- `message` {Object}
|
|
||||||
- `topic` {String} the topic for which the update occured
|
|
||||||
- `data` {Array|Object} updated data (see docs for each [topic](#available-topics)).
|
|
||||||
- `type` {String} Some topics might have different update types (see docs for each [topic](#available-topics)).
|
|
||||||
|
|
||||||
Emmited whenever an update to a subscribed topic occurs.
|
|
||||||
|
|
||||||
### Event: 'response'
|
|
||||||
- `response` {Object}
|
|
||||||
- `success` {Bool}
|
|
||||||
- `ret_msg` {String} empty if operation was successfull, otherwise error message.
|
|
||||||
- `conn_id` {String} connection id
|
|
||||||
- `request` {Object} Original request, to which the response belongs
|
|
||||||
- `op` {String} operation
|
|
||||||
- `args` {Array} Request Arguments
|
|
||||||
|
|
||||||
Emited when the server responds to an operation sent by the client (usually after subscribing to a topic).
|
|
||||||
|
|
||||||
### Event: 'close'
|
|
||||||
Emitted when the connection has been finally closed, after a call to `ws.close()`
|
|
||||||
|
|
||||||
### Event: 'reconnect'
|
|
||||||
Emitted when the connection has been closed, but the client will try to reconnect.
|
|
||||||
|
|
||||||
### Event: 'error'
|
|
||||||
- `error` {Error}
|
|
||||||
|
|
||||||
Emitted when an error occurs.
|
|
||||||
|
|
||||||
## Available Topics
|
|
||||||
Generaly all [public](https://bybit-exchange.github.io/docs/inverse/#t-publictopics) and [private](https://bybit-exchange.github.io/docs/inverse/#t-privatetopics)
|
|
||||||
topics are available.
|
|
||||||
|
|
||||||
### Private topics
|
|
||||||
#### Positions of your account
|
|
||||||
All positions of your account.
|
|
||||||
Topic: `position`
|
|
||||||
|
|
||||||
[See bybit documentation](https://bybit-exchange.github.io/docs/inverse/#t-websocketposition)
|
|
||||||
|
|
||||||
#### Execution message
|
|
||||||
Execution message, whenever an order has been (partially) filled.
|
|
||||||
Topic: `execution`
|
|
||||||
|
|
||||||
[See bybit documentation](https://bybit-exchange.github.io/docs/inverse/#t-websocketexecution)
|
|
||||||
|
|
||||||
#### Update for your orders
|
|
||||||
Updates for your active orders
|
|
||||||
Topic: `order`
|
|
||||||
|
|
||||||
[See bybit documentation](https://bybit-exchange.github.io/docs/inverse/#t-websocketorder)
|
|
||||||
|
|
||||||
#### Update for your conditional orders
|
|
||||||
Updates for your active conditional orders
|
|
||||||
Topic: `stop_order`
|
|
||||||
|
|
||||||
[See bybit documentation](https://bybit-exchange.github.io/docs/inverse/#t-websocketstoporder)
|
|
||||||
|
|
||||||
### Public topics
|
|
||||||
#### Candlestick chart
|
|
||||||
Candlestick OHLC "candles" for selected symbol and interval.
|
|
||||||
Example topic: `klineV2.BTCUSD.1m`
|
|
||||||
|
|
||||||
[See bybit documentation](https://bybit-exchange.github.io/docs/inverse/#t-websocketklinev2)
|
|
||||||
|
|
||||||
#### Real-time trading information
|
|
||||||
All trades as they occur.
|
|
||||||
Topic: `trade`
|
|
||||||
|
|
||||||
[See bybit documentation](https://bybit-exchange.github.io/docs/inverse/#t-websockettrade)
|
|
||||||
|
|
||||||
#### Daily insurance fund update
|
|
||||||
Topic: `insurance`
|
|
||||||
|
|
||||||
[See bybit documentation](https://bybit-exchange.github.io/docs/inverse/#t-websocketinsurance)
|
|
||||||
|
|
||||||
#### OrderBook of 25 depth per side
|
|
||||||
OrderBook for selected symbol
|
|
||||||
Example topic: `orderBookL2_25.BTCUSD`
|
|
||||||
|
|
||||||
[See bybit documentation](https://bybit-exchange.github.io/docs/inverse/#t-websocketorderbook25)
|
|
||||||
|
|
||||||
#### OrderBook of 200 depth per side
|
|
||||||
OrderBook for selected symbol
|
|
||||||
Example topic: `orderBook_200.100ms.BTCUS`
|
|
||||||
|
|
||||||
[See bybit documentation](https://bybit-exchange.github.io/docs/inverse/#t-websocketorderbook200)
|
|
||||||
|
|
||||||
#### Latest information for symbol
|
|
||||||
Latest information for selected symbol
|
|
||||||
Example topic: `instrument_info.100ms.BTCUSD`
|
|
||||||
|
|
||||||
[See bybit documentation](https://bybit-exchange.github.io/docs/inverse/#t-websocketinstrumentinfo)
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
### Klines
|
|
||||||
```javascript
|
|
||||||
const {WebsocketClient} = require('bybit-api');
|
|
||||||
|
|
||||||
const API_KEY = 'xxx';
|
|
||||||
const PRIVATE_KEY = 'yyy';
|
|
||||||
|
|
||||||
const ws = new WebsocketClient({key: API_KEY, secret: PRIVATE_KEY});
|
|
||||||
|
|
||||||
ws.subscribe(['position', 'execution', 'trade']);
|
|
||||||
ws.subscribe('kline.BTCUSD.1m');
|
|
||||||
|
|
||||||
ws.on('open', function() {
|
|
||||||
console.log('connection open');
|
|
||||||
});
|
|
||||||
|
|
||||||
ws.on('update', function(message) {
|
|
||||||
console.log('update', message);
|
|
||||||
});
|
|
||||||
|
|
||||||
ws.on('response', function(response) {
|
|
||||||
console.log('response', response);
|
|
||||||
});
|
|
||||||
|
|
||||||
ws.on('close', function() {
|
|
||||||
console.log('connection closed');
|
|
||||||
});
|
|
||||||
|
|
||||||
ws.on('error', function(err) {
|
|
||||||
console.error('ERR', err);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### OrderBook Events
|
|
||||||
```javascript
|
|
||||||
const { WebsocketClient, DefaultLogger } = require('bybit-api');
|
|
||||||
const { OrderBooksStore, OrderBookLevel } = require('orderbooks');
|
|
||||||
|
|
||||||
const OrderBooks = new OrderBooksStore({ traceLog: true, checkTimestamps: false });
|
|
||||||
|
|
||||||
// connect to a websocket and relay orderbook events to handlers
|
|
||||||
DefaultLogger.silly = () => {};
|
|
||||||
const ws = new WebsocketClient({ livenet: true });
|
|
||||||
ws.on('update', message => {
|
|
||||||
if (message.topic.toLowerCase().startsWith('orderbook')) {
|
|
||||||
return handleOrderbookUpdate(message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ws.subscribe('orderBookL2_25.BTCUSD');
|
|
||||||
|
|
||||||
// parse orderbook messages, detect snapshot vs delta, and format properties using OrderBookLevel
|
|
||||||
const handleOrderbookUpdate = message => {
|
|
||||||
const { topic, type, data, timestamp_e6 } = message;
|
|
||||||
const [ topicKey, symbol ] = topic.split('.');
|
|
||||||
|
|
||||||
if (type == 'snapshot') {
|
|
||||||
return OrderBooks.handleSnapshot(symbol, data.map(mapBybitBookSlice), timestamp_e6 / 1000, message).print();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == 'delta') {
|
|
||||||
const deleteLevels = data.delete.map(mapBybitBookSlice);
|
|
||||||
const updateLevels = data.update.map(mapBybitBookSlice);
|
|
||||||
const insertLevels = data.insert.map(mapBybitBookSlice);
|
|
||||||
return OrderBooks.handleDelta(
|
|
||||||
symbol,
|
|
||||||
deleteLevels,
|
|
||||||
updateLevels,
|
|
||||||
insertLevels,
|
|
||||||
timestamp_e6 / 1000
|
|
||||||
).print();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Low level map of exchange properties to expected local properties
|
|
||||||
const mapBybitBookSlice = level => {
|
|
||||||
return OrderBookLevel(level.symbol, +level.price, level.side, level.size);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
@@ -2,6 +2,7 @@ import { InverseClient } from '../inverse-client';
|
|||||||
import { LinearClient } from '../linear-client';
|
import { LinearClient } from '../linear-client';
|
||||||
import { SpotClient } from '../spot-client';
|
import { SpotClient } from '../spot-client';
|
||||||
import { SpotClientV3 } from '../spot-client-v3';
|
import { SpotClientV3 } from '../spot-client-v3';
|
||||||
|
import { UnifiedMarginClient } from '../unified-margin-client';
|
||||||
import { USDCOptionClient } from '../usdc-option-client';
|
import { USDCOptionClient } from '../usdc-option-client';
|
||||||
import { USDCPerpetualClient } from '../usdc-perpetual-client';
|
import { USDCPerpetualClient } from '../usdc-perpetual-client';
|
||||||
|
|
||||||
@@ -11,7 +12,8 @@ export type RESTClient =
|
|||||||
| SpotClient
|
| SpotClient
|
||||||
| SpotClientV3
|
| SpotClientV3
|
||||||
| USDCOptionClient
|
| USDCOptionClient
|
||||||
| USDCPerpetualClient;
|
| USDCPerpetualClient
|
||||||
|
| UnifiedMarginClient;
|
||||||
|
|
||||||
export type numberInString = string;
|
export type numberInString = string;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ export type APIMarket =
|
|||||||
| 'spot'
|
| 'spot'
|
||||||
| 'spotv3'
|
| 'spotv3'
|
||||||
| 'usdcOption'
|
| 'usdcOption'
|
||||||
| 'usdcPerp';
|
| 'usdcPerp'
|
||||||
|
| 'unifiedPerp'
|
||||||
|
| 'unifiedOption';
|
||||||
|
|
||||||
// Same as inverse futures
|
// Same as inverse futures
|
||||||
export type WsPublicInverseTopic =
|
export type WsPublicInverseTopic =
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ interface NetworkMapV3 {
|
|||||||
type PublicPrivateNetwork = 'public' | 'private';
|
type PublicPrivateNetwork = 'public' | 'private';
|
||||||
|
|
||||||
export const WS_BASE_URL_MAP: Record<
|
export const WS_BASE_URL_MAP: Record<
|
||||||
APIMarket,
|
APIMarket | 'unifiedPerpUSDT' | 'unifiedPerpUSDC',
|
||||||
Record<PublicPrivateNetwork, NetworkMapV3>
|
Record<PublicPrivateNetwork, NetworkMapV3>
|
||||||
> = {
|
> = {
|
||||||
inverse: {
|
inverse: {
|
||||||
@@ -81,6 +81,46 @@ export const WS_BASE_URL_MAP: Record<
|
|||||||
testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/private/v1',
|
testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/private/v1',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
unifiedOption: {
|
||||||
|
public: {
|
||||||
|
livenet: 'wss://stream.bybit.com/option/usdc/public/v3',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/option/usdc/public/v3',
|
||||||
|
},
|
||||||
|
private: {
|
||||||
|
livenet: 'wss://stream.bybit.com/unified/private/v3',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/unified/private/v3',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
unifiedPerp: {
|
||||||
|
public: {
|
||||||
|
livenet: 'useBaseSpecificEndpoint',
|
||||||
|
testnet: 'useBaseSpecificEndpoint',
|
||||||
|
},
|
||||||
|
private: {
|
||||||
|
livenet: 'wss://stream.bybit.com/unified/private/v3',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/unified/private/v3',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
unifiedPerpUSDT: {
|
||||||
|
public: {
|
||||||
|
livenet: 'wss://stream.bybit.com/contract/usdt/public/v3',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/contract/usdt/public/v3',
|
||||||
|
},
|
||||||
|
private: {
|
||||||
|
livenet: 'useUnifiedEndpoint',
|
||||||
|
testnet: 'useUnifiedEndpoint',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
unifiedPerpUSDC: {
|
||||||
|
public: {
|
||||||
|
livenet: 'wss://stream.bybit.com/contract/usdc/public/v3',
|
||||||
|
testnet: 'wss://stream-testnet.bybit.com/contract/usdc/public/v3',
|
||||||
|
},
|
||||||
|
private: {
|
||||||
|
livenet: 'useUnifiedEndpoint',
|
||||||
|
testnet: 'useUnifiedEndpoint',
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WS_KEY_MAP = {
|
export const WS_KEY_MAP = {
|
||||||
@@ -95,6 +135,10 @@ export const WS_KEY_MAP = {
|
|||||||
usdcOptionPublic: 'usdcOptionPublic',
|
usdcOptionPublic: 'usdcOptionPublic',
|
||||||
usdcPerpPrivate: 'usdcPerpPrivate',
|
usdcPerpPrivate: 'usdcPerpPrivate',
|
||||||
usdcPerpPublic: 'usdcPerpPublic',
|
usdcPerpPublic: 'usdcPerpPublic',
|
||||||
|
unifiedPrivate: 'unifiedPrivate',
|
||||||
|
unifiedOptionPublic: 'unifiedOptionPublic',
|
||||||
|
unifiedPerpUSDTPublic: 'unifiedPerpUSDTPublic',
|
||||||
|
unifiedPerpUSDCPublic: 'unifiedPerpUSDCPublic',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const WS_AUTH_ON_CONNECT_KEYS: WsKey[] = [
|
export const WS_AUTH_ON_CONNECT_KEYS: WsKey[] = [
|
||||||
@@ -180,6 +224,29 @@ export function getWsKeyForTopic(
|
|||||||
? WS_KEY_MAP.usdcPerpPrivate
|
? WS_KEY_MAP.usdcPerpPrivate
|
||||||
: WS_KEY_MAP.usdcPerpPublic;
|
: WS_KEY_MAP.usdcPerpPublic;
|
||||||
}
|
}
|
||||||
|
case 'unifiedOption': {
|
||||||
|
return isPrivateTopic
|
||||||
|
? WS_KEY_MAP.unifiedPrivate
|
||||||
|
: WS_KEY_MAP.unifiedOptionPublic;
|
||||||
|
}
|
||||||
|
case 'unifiedPerp': {
|
||||||
|
if (isPrivateTopic) {
|
||||||
|
return WS_KEY_MAP.unifiedPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
const upperTopic = topic.toUpperCase();
|
||||||
|
if (upperTopic.indexOf('USDT') !== -1) {
|
||||||
|
return WS_KEY_MAP.unifiedPerpUSDTPublic;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upperTopic.indexOf('USDC') !== -1) {
|
||||||
|
return WS_KEY_MAP.unifiedPerpUSDCPublic;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
`Failed to determine wskey for unified perps topic: "${topic}`
|
||||||
|
);
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(market, `getWsKeyForTopic(): Unhandled market`);
|
throw neverGuard(market, `getWsKeyForTopic(): Unhandled market`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
} from './util';
|
} from './util';
|
||||||
import { USDCOptionClient } from './usdc-option-client';
|
import { USDCOptionClient } from './usdc-option-client';
|
||||||
import { USDCPerpetualClient } from './usdc-perpetual-client';
|
import { USDCPerpetualClient } from './usdc-perpetual-client';
|
||||||
|
import { UnifiedMarginClient } from './unified-margin-client';
|
||||||
|
|
||||||
const loggerCategory = { category: 'bybit-ws' };
|
const loggerCategory = { category: 'bybit-ws' };
|
||||||
|
|
||||||
@@ -163,6 +164,17 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'unifiedOption':
|
||||||
|
case 'unifiedPerp': {
|
||||||
|
this.restClient = new UnifiedMarginClient(
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
!this.isTestnet(),
|
||||||
|
this.options.restOptions,
|
||||||
|
this.options.requestOptions
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(
|
throw neverGuard(
|
||||||
this.options.market,
|
this.options.market,
|
||||||
@@ -198,15 +210,17 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
switch (this.options.market) {
|
switch (this.options.market) {
|
||||||
case 'inverse': {
|
case 'inverse': {
|
||||||
// only one for inverse
|
// only one for inverse
|
||||||
return [this.connectPublic()];
|
return [...this.connectPublic()];
|
||||||
}
|
}
|
||||||
// these all have separate public & private ws endpoints
|
// these all have separate public & private ws endpoints
|
||||||
case 'linear':
|
case 'linear':
|
||||||
case 'spot':
|
case 'spot':
|
||||||
case 'spotv3':
|
case 'spotv3':
|
||||||
case 'usdcOption':
|
case 'usdcOption':
|
||||||
case 'usdcPerp': {
|
case 'usdcPerp':
|
||||||
return [this.connectPublic(), this.connectPrivate()];
|
case 'unifiedPerp':
|
||||||
|
case 'unifiedOption': {
|
||||||
|
return [...this.connectPublic(), this.connectPrivate()];
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(this.options.market, `connectAll(): Unhandled market`);
|
throw neverGuard(this.options.market, `connectAll(): Unhandled market`);
|
||||||
@@ -214,25 +228,34 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public connectPublic(): Promise<WebSocket | undefined> {
|
public connectPublic(): Promise<WebSocket | undefined>[] {
|
||||||
switch (this.options.market) {
|
switch (this.options.market) {
|
||||||
case 'inverse': {
|
case 'inverse': {
|
||||||
return this.connect(WS_KEY_MAP.inverse);
|
return [this.connect(WS_KEY_MAP.inverse)];
|
||||||
}
|
}
|
||||||
case 'linear': {
|
case 'linear': {
|
||||||
return this.connect(WS_KEY_MAP.linearPublic);
|
return [this.connect(WS_KEY_MAP.linearPublic)];
|
||||||
}
|
}
|
||||||
case 'spot': {
|
case 'spot': {
|
||||||
return this.connect(WS_KEY_MAP.spotPublic);
|
return [this.connect(WS_KEY_MAP.spotPublic)];
|
||||||
}
|
}
|
||||||
case 'spotv3': {
|
case 'spotv3': {
|
||||||
return this.connect(WS_KEY_MAP.spotV3Public);
|
return [this.connect(WS_KEY_MAP.spotV3Public)];
|
||||||
}
|
}
|
||||||
case 'usdcOption': {
|
case 'usdcOption': {
|
||||||
return this.connect(WS_KEY_MAP.usdcOptionPublic);
|
return [this.connect(WS_KEY_MAP.usdcOptionPublic)];
|
||||||
}
|
}
|
||||||
case 'usdcPerp': {
|
case 'usdcPerp': {
|
||||||
return this.connect(WS_KEY_MAP.usdcPerpPublic);
|
return [this.connect(WS_KEY_MAP.usdcPerpPublic)];
|
||||||
|
}
|
||||||
|
case 'unifiedOption': {
|
||||||
|
return [this.connect(WS_KEY_MAP.unifiedOptionPublic)];
|
||||||
|
}
|
||||||
|
case 'unifiedPerp': {
|
||||||
|
return [
|
||||||
|
this.connect(WS_KEY_MAP.unifiedPerpUSDTPublic),
|
||||||
|
this.connect(WS_KEY_MAP.unifiedPerpUSDCPublic),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(
|
throw neverGuard(
|
||||||
@@ -263,6 +286,10 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
case 'usdcPerp': {
|
case 'usdcPerp': {
|
||||||
return this.connect(WS_KEY_MAP.usdcPerpPrivate);
|
return this.connect(WS_KEY_MAP.usdcPerpPrivate);
|
||||||
}
|
}
|
||||||
|
case 'unifiedPerp':
|
||||||
|
case 'unifiedOption': {
|
||||||
|
return this.connect(WS_KEY_MAP.unifiedPrivate);
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
throw neverGuard(
|
throw neverGuard(
|
||||||
this.options.market,
|
this.options.market,
|
||||||
@@ -719,6 +746,18 @@ export class WebsocketClient extends EventEmitter {
|
|||||||
case WS_KEY_MAP.usdcPerpPrivate: {
|
case WS_KEY_MAP.usdcPerpPrivate: {
|
||||||
return WS_BASE_URL_MAP.usdcPerp.private[networkKey];
|
return WS_BASE_URL_MAP.usdcPerp.private[networkKey];
|
||||||
}
|
}
|
||||||
|
case WS_KEY_MAP.unifiedOptionPublic: {
|
||||||
|
return WS_BASE_URL_MAP.unifiedOption.public[networkKey];
|
||||||
|
}
|
||||||
|
case WS_KEY_MAP.unifiedPerpUSDTPublic: {
|
||||||
|
return WS_BASE_URL_MAP.unifiedPerpUSDT.public[networkKey];
|
||||||
|
}
|
||||||
|
case WS_KEY_MAP.unifiedPerpUSDCPublic: {
|
||||||
|
return WS_BASE_URL_MAP.unifiedPerpUSDC.public[networkKey];
|
||||||
|
}
|
||||||
|
case WS_KEY_MAP.unifiedPrivate: {
|
||||||
|
return WS_BASE_URL_MAP.unifiedPerp.private[networkKey];
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
this.logger.error('getWsUrl(): Unhandled wsKey: ', {
|
this.logger.error('getWsUrl(): Unhandled wsKey: ', {
|
||||||
...loggerCategory,
|
...loggerCategory,
|
||||||
|
|||||||
Reference in New Issue
Block a user