Merge pull request #32 from tiagosiebler/#29
Breaking Change: fix #29 & process recent api deprecations
This commit is contained in:
53
README.md
53
README.md
@@ -5,20 +5,27 @@
|
|||||||
|
|
||||||
[1]: https://www.npmjs.com/package/bybit-api
|
[1]: https://www.npmjs.com/package/bybit-api
|
||||||
|
|
||||||
An light node.js wrapper for the Bybit Cryptocurrency Derivative exchange API. Forked & adapted from [@pxtrn/bybit-api](https://github.com/pixtron/bybit-api).
|
A production-ready Node.js connector for the Bybit APIs and WebSockets.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
`npm install --save bybit-api`
|
`npm install --save bybit-api`
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
Create API credentials at bybit (obviously you need to be logged in):
|
Create API credentials at Bybit
|
||||||
- [Livenet](https://bybit.com/app/user/api-management?affiliate_id=9410&language=en-US&group_id=0&group_type=1)
|
- [Livenet](https://bybit.com/app/user/api-management?affiliate_id=9410&language=en-US&group_id=0&group_type=1)
|
||||||
- [Testnet](https://testnet.bybit.com/app/user/api-management)
|
- [Testnet](https://testnet.bybit.com/app/user/api-management)
|
||||||
|
|
||||||
## Documentation
|
## Issues & Discussion
|
||||||
Most of the documentation is in [Bybit's official API docs](https://bybit-exchange.github.io/docs/inverse/#t-introduction). Most of this library's methods accept objects that directly correspond to expectations from Bybit's API docs.
|
- Issues? Check the [issues tab](https://github.com/tiagosiebler/bybit-api/issues).
|
||||||
|
- Discuss & collaborate with other node devs? Join our [Node.js Algo Traders](https://t.me/nodetraders) engineering community on telegram.
|
||||||
|
|
||||||
### Rest client
|
## Documentation
|
||||||
|
Most methods accept JS objects. These can be populated using parameters specified by Bybit's API documentation.
|
||||||
|
- [Bybit API Inverse Documentation](https://bybit-exchange.github.io/docs/inverse/#t-introduction).
|
||||||
|
- [Bybit API Linear Documentation (not supported yet)](https://bybit-exchange.github.io/docs/linear/#t-introduction)
|
||||||
|
|
||||||
|
### Inverse Contracts
|
||||||
|
#### Rest client
|
||||||
```javascript
|
```javascript
|
||||||
const {RestClient} = require('bybit-api');
|
const {RestClient} = require('bybit-api');
|
||||||
|
|
||||||
@@ -32,13 +39,13 @@ client.changeUserLeverage({leverage: 4, symbol: 'ETHUSD'})
|
|||||||
console.log(result);
|
console.log(result);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error(error);
|
console.error(err);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
See rest client [api docs](./doc/rest-client.md) for further information.
|
See inverse [rest-client.js](./master/lib/rest-client.js) for further information.
|
||||||
|
|
||||||
### Websocket client
|
#### Websocket client
|
||||||
```javascript
|
```javascript
|
||||||
const {WebsocketClient} = require('bybit-api');
|
const {WebsocketClient} = require('bybit-api');
|
||||||
|
|
||||||
@@ -50,28 +57,27 @@ const ws = new WebsocketClient({key: API_KEY, secret: PRIVATE_KEY});
|
|||||||
ws.subscribe(['position', 'execution', 'trade']);
|
ws.subscribe(['position', 'execution', 'trade']);
|
||||||
ws.subscribe('kline.BTCUSD.1m');
|
ws.subscribe('kline.BTCUSD.1m');
|
||||||
|
|
||||||
ws.on('open', function() {
|
ws.on('open', () => {
|
||||||
console.log('connection open');
|
console.log('connection open');
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on('update', function(message) {
|
ws.on('update', message => {
|
||||||
console.log('update', message);
|
console.log('update', message);
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on('response', function(response) {
|
ws.on('response', response => {
|
||||||
console.log('response', response);
|
console.log('response', response);
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on('close', function() {
|
ws.on('close', () => {
|
||||||
console.log('connection closed');
|
console.log('connection closed');
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on('error', function(err) {
|
ws.on('error', err => {
|
||||||
console.error('ERR', err);
|
console.error('ERR', err);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
See inverse [websocket-client.js](./master/lib/websocket-client.js) & [ws api docs](./doc/websocket-client.md) for further information.
|
||||||
See websocket client [api docs](./doc/websocket-client.md) for further information.
|
|
||||||
|
|
||||||
### Customise Logging
|
### Customise Logging
|
||||||
Pass a custom logger which supports the log methods `silly`, `debug`, `notice`, `info`, `warning` and `error`, or override methods from the default logger as desired:
|
Pass a custom logger which supports the log methods `silly`, `debug`, `notice`, `info`, `warning` and `error`, or override methods from the default logger as desired:
|
||||||
@@ -82,20 +88,11 @@ const { RestClient, WebsocketClient, DefaultLogger } = require('bybit-api');
|
|||||||
// Disable all logging on the silly level
|
// Disable all logging on the silly level
|
||||||
DefaultLogger.silly = () => {};
|
DefaultLogger.silly = () => {};
|
||||||
|
|
||||||
const API_KEY = 'xxx';
|
const ws = new WebsocketClient({key: 'xxx', secret: 'yyy'}, DefaultLogger);
|
||||||
const PRIVATE_KEY = 'yyy';
|
|
||||||
|
|
||||||
const ws = new WebsocketClient({key: API_KEY, secret: PRIVATE_KEY}, DefaultLogger);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributions & Thanks
|
## Contributions & Thanks
|
||||||
### Donations
|
### Donations
|
||||||
#### pixtron
|
|
||||||
This library was started by @pixtron. If this library helps you to trade better on bybit, feel free to donate a coffee to @pixtron:
|
|
||||||
- BTC `1Fh1158pXXudfM6ZrPJJMR7Y5SgZUz4EdF`
|
|
||||||
- ETH `0x21aEdeC53ab7593b77C9558942f0c9E78131e8d7`
|
|
||||||
- LTC `LNdHSVtG6UWsriMYLJR3qLdfVNKwJ6GSLF`
|
|
||||||
|
|
||||||
#### tiagosiebler
|
#### tiagosiebler
|
||||||
If you found this project interesting or useful, create accounts with my referral links:
|
If you found this project interesting or useful, create accounts with my referral links:
|
||||||
- [Bybit](https://www.bybit.com/en-US/register?affiliate_id=9410&language=en-US&group_id=0&group_type=1)
|
- [Bybit](https://www.bybit.com/en-US/register?affiliate_id=9410&language=en-US&group_id=0&group_type=1)
|
||||||
@@ -105,5 +102,11 @@ Or buy me a coffee using any of these:
|
|||||||
- BTC: `1C6GWZL1XW3jrjpPTS863XtZiXL1aTK7Jk`
|
- BTC: `1C6GWZL1XW3jrjpPTS863XtZiXL1aTK7Jk`
|
||||||
- ETH (ERC20): `0xd773d8e6a50758e1ada699bb6c4f98bb4abf82da`
|
- ETH (ERC20): `0xd773d8e6a50758e1ada699bb6c4f98bb4abf82da`
|
||||||
|
|
||||||
|
#### pixtron
|
||||||
|
The original library was started by @pixtron. If this library helps you to trade better on bybit, feel free to donate a coffee to @pixtron:
|
||||||
|
- BTC `1Fh1158pXXudfM6ZrPJJMR7Y5SgZUz4EdF`
|
||||||
|
- ETH `0x21aEdeC53ab7593b77C9558942f0c9E78131e8d7`
|
||||||
|
- LTC `LNdHSVtG6UWsriMYLJR3qLdfVNKwJ6GSLF`
|
||||||
|
|
||||||
### Contributions & Pull Requests
|
### Contributions & Pull Requests
|
||||||
Contributions are encouraged, I will review any incoming pull requests. See the issues tab for todo items.
|
Contributions are encouraged, I will review any incoming pull requests. See the issues tab for todo items.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
"**/node_modules/*",
|
"**/node_modules/*",
|
||||||
"coverage"
|
"coverage",
|
||||||
|
"doc"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
|
||||||
const RequestWrapper = require('./util/requestWrapper');
|
const RequestWrapper = require('./util/requestWrapper');
|
||||||
|
|
||||||
module.exports = class RestClient {
|
module.exports = class RestClient {
|
||||||
@@ -54,6 +52,17 @@ module.exports = class RestClient {
|
|||||||
assert(params.order_id || params.order_link_id, 'Parameter order_id OR order_link_id is required');
|
assert(params.order_id || params.order_link_id, 'Parameter order_id OR order_link_id is required');
|
||||||
assert(params.symbol, 'Parameter symbol is required');
|
assert(params.symbol, 'Parameter symbol is required');
|
||||||
|
|
||||||
|
return await this.request.post('v2/private/order/replace', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use replaceActiveOrder()
|
||||||
|
*/
|
||||||
|
async replaceActiveOrderOld(params) {
|
||||||
|
assert(params, 'No params passed');
|
||||||
|
assert(params.order_id || params.order_link_id, 'Parameter order_id OR order_link_id is required');
|
||||||
|
assert(params.symbol, 'Parameter symbol is required');
|
||||||
|
|
||||||
return await this.request.post('open-api/order/replace', params);
|
return await this.request.post('open-api/order/replace', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +75,24 @@ module.exports = class RestClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async placeConditionalOrder(params) {
|
async placeConditionalOrder(params) {
|
||||||
|
assert(params, 'No params passed');
|
||||||
|
assert(params.side, 'Parameter side is required');
|
||||||
|
assert(params.symbol, 'Parameter symbol is required');
|
||||||
|
assert(params.order_type, 'Parameter order_type is required');
|
||||||
|
assert(params.qty, 'Parameter qty is required');
|
||||||
|
assert(params.base_price, 'Parameter base_price is required');
|
||||||
|
assert(params.stop_px, 'Parameter stop_px is required');
|
||||||
|
assert(params.time_in_force, 'Parameter time_in_force is required');
|
||||||
|
|
||||||
|
if (params.order_type === 'Limit') assert(params.price, 'Parameter price is required for limit orders');
|
||||||
|
|
||||||
|
return await this.request.post('v2/private/stop-order/create', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use placeConditionalOrder
|
||||||
|
*/
|
||||||
|
async placeConditionalOrderOld(params) {
|
||||||
assert(params, 'No params passed');
|
assert(params, 'No params passed');
|
||||||
assert(params.side, 'Parameter side is required');
|
assert(params.side, 'Parameter side is required');
|
||||||
assert(params.symbol, 'Parameter symbol is required');
|
assert(params.symbol, 'Parameter symbol is required');
|
||||||
@@ -81,10 +108,28 @@ module.exports = class RestClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getConditionalOrder(params) {
|
async getConditionalOrder(params) {
|
||||||
|
assert(params.symbol, 'Parameter symbol is required');
|
||||||
|
return await this.request.get('v2/private/stop-order/list', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use placeConditionalOrder
|
||||||
|
*/
|
||||||
|
async getConditionalOrderOld(params) {
|
||||||
return await this.request.get('open-api/stop-order/list', params);
|
return await this.request.get('open-api/stop-order/list', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
async cancelConditionalOrder(params) {
|
async cancelConditionalOrder(params) {
|
||||||
|
assert(params, 'No params passed');
|
||||||
|
assert(params.stop_order_id || params.order_link_id, 'Parameter stop_order_id OR order_link_id is required');
|
||||||
|
|
||||||
|
return await this.request.post('v2/private/stop-order/cancel', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use cancelConditionalOrder
|
||||||
|
*/
|
||||||
|
async cancelConditionalOrderOld(params) {
|
||||||
assert(params, 'No params passed');
|
assert(params, 'No params passed');
|
||||||
assert(params.stop_order_id, 'Parameter stop_order_id is required');
|
assert(params.stop_order_id, 'Parameter stop_order_id is required');
|
||||||
|
|
||||||
@@ -99,6 +144,17 @@ module.exports = class RestClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async replaceConditionalOrder(params) {
|
async replaceConditionalOrder(params) {
|
||||||
|
assert(params, 'No params passed');
|
||||||
|
assert(params.stop_order_id || params.order_link_id, 'Parameter stop_order_id OR order_link_id is required');
|
||||||
|
assert(params.symbol, 'Parameter symbol is required');
|
||||||
|
|
||||||
|
return await this.request.post('v2/private/stop-order/replace', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use replaceConditionalOrder
|
||||||
|
*/
|
||||||
|
async replaceConditionalOrderOld(params) {
|
||||||
assert(params, 'No params passed');
|
assert(params, 'No params passed');
|
||||||
assert(params.stop_order_id, 'Parameter stop_order_id is required');
|
assert(params.stop_order_id, 'Parameter stop_order_id is required');
|
||||||
assert(params.symbol, 'Parameter symbol is required');
|
assert(params.symbol, 'Parameter symbol is required');
|
||||||
@@ -114,10 +170,17 @@ module.exports = class RestClient {
|
|||||||
return await this.request.get('v2/private/stop-order', params);
|
return await this.request.get('v2/private/stop-order', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use getPosition() instead
|
||||||
|
*/
|
||||||
async getUserLeverage() {
|
async getUserLeverage() {
|
||||||
return await this.request.get('user/leverage');
|
return await this.request.get('user/leverage');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getPosition(params) {
|
||||||
|
return await this.request.get('v2/private/position/list', params);
|
||||||
|
}
|
||||||
|
|
||||||
async changeUserLeverage(params) {
|
async changeUserLeverage(params) {
|
||||||
assert(params, 'No params passed');
|
assert(params, 'No params passed');
|
||||||
assert(params.leverage, 'Parameter leverage is required');
|
assert(params.leverage, 'Parameter leverage is required');
|
||||||
@@ -126,13 +189,9 @@ module.exports = class RestClient {
|
|||||||
return await this.request.post('user/leverage/save', params);
|
return await this.request.post('user/leverage/save', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPosition(params) {
|
/**
|
||||||
assert(params, 'No params passed');
|
* @deprecated use getPosition() instead
|
||||||
assert(params.symbol, 'Parameter symbol is required');
|
*/
|
||||||
|
|
||||||
return await this.request.get('v2/private/position/list', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getPositions() {
|
async getPositions() {
|
||||||
return await this.request.get('position/list');
|
return await this.request.get('position/list');
|
||||||
}
|
}
|
||||||
|
|||||||
12
package.json
12
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "bybit-api",
|
"name": "bybit-api",
|
||||||
"version": "1.2.1",
|
"version": "1.2.2",
|
||||||
"description": "A node.js wrapper for the Bybit Cryptocurrency Derivative exchange APIs",
|
"description": "A production-ready Node.js connector for the Bybit APIs and WebSockets",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
@@ -18,13 +18,15 @@
|
|||||||
"rest api",
|
"rest api",
|
||||||
"inverse",
|
"inverse",
|
||||||
"nodejs",
|
"nodejs",
|
||||||
|
"node",
|
||||||
"trading",
|
"trading",
|
||||||
"cryptocurrency",
|
"cryptocurrency",
|
||||||
"bitcoin"
|
"bitcoin",
|
||||||
|
"best"
|
||||||
],
|
],
|
||||||
"author": "Stefan Aebischer <os@pixtron.ch> (https://pixtron.ch)",
|
"author": "Tiago Siebler (https://github.com/tiagosiebler)",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Tiago Siebler (https://github.com/tiagosiebler)"
|
"Stefan Aebischer <os@pixtron.ch> (https://pixtron.ch)"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|||||||
Reference in New Issue
Block a user