Merge pull request #3 from tiagosiebler/linearCleaning
move script commands around. Move shared endpoint down.
This commit is contained in:
2
.github/workflows/npmpublish.yml
vendored
2
.github/workflows/npmpublish.yml
vendored
@@ -42,6 +42,8 @@ jobs:
|
|||||||
|
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
if: steps.version-updated.outputs.has-updated
|
if: steps.version-updated.outputs.has-updated
|
||||||
|
- run: npm run clean
|
||||||
|
if: steps.version-updated.outputs.has-updated
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
if: steps.version-updated.outputs.has-updated
|
if: steps.version-updated.outputs.has-updated
|
||||||
- run: npm publish
|
- run: npm publish
|
||||||
|
|||||||
79
README.md
79
README.md
@@ -39,13 +39,10 @@ Build a bundle using webpack:
|
|||||||
The bundle can be found in `dist/`. Altough usage should be largely consistent, smaller differences will exist. Documentation is still TODO.
|
The bundle can be found in `dist/`. Altough usage should be largely consistent, smaller differences will exist. Documentation is still TODO.
|
||||||
|
|
||||||
### Inverse Contracts
|
### Inverse Contracts
|
||||||
#### Rest client
|
Since inverse and linear (USDT) contracts don't use the exact same APIs, the REST abstractions are split into two modules. To use the inverse REST APIs, import the `InverseClient`:
|
||||||
```javascript
|
|
||||||
const { RestClient } = require('bybit-api');
|
|
||||||
|
|
||||||
const API_KEY = 'xxx';
|
```javascript
|
||||||
const PRIVATE_KEY = 'yyy';
|
const { InverseClient } = require('bybit-api');
|
||||||
const useLivenet = false;
|
|
||||||
|
|
||||||
const restInverseOptions = {
|
const restInverseOptions = {
|
||||||
// override the max size of the request window (in ms)
|
// override the max size of the request window (in ms)
|
||||||
@@ -68,7 +65,11 @@ const restInverseOptions = {
|
|||||||
parse_exceptions?: boolean;
|
parse_exceptions?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const client = new RestClient(
|
const API_KEY = 'xxx';
|
||||||
|
const PRIVATE_KEY = 'yyy';
|
||||||
|
const useLivenet = false;
|
||||||
|
|
||||||
|
const client = new InverseClient(
|
||||||
API_KEY,
|
API_KEY,
|
||||||
PRIVATE_KEY,
|
PRIVATE_KEY,
|
||||||
|
|
||||||
@@ -88,9 +89,67 @@ client.changeUserLeverage({leverage: 4, symbol: 'ETHUSD'})
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
See inverse [rest-client.ts](./src/rest-client.ts) for further information.
|
See inverse [inverse-client.ts](./src/inverse-client.ts) for further information.
|
||||||
|
|
||||||
|
### Linear Contracts
|
||||||
|
To use the Linear (USDT) REST APIs, import the `LinearClient`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const { LinearClient } = require('bybit-api');
|
||||||
|
|
||||||
|
const restInverseOptions = {
|
||||||
|
// override the max size of the request window (in ms)
|
||||||
|
recv_window?: number;
|
||||||
|
|
||||||
|
// how often to sync time drift with bybit servers
|
||||||
|
sync_interval_ms?: number | string;
|
||||||
|
|
||||||
|
// Default: false. Disable above sync mechanism if true.
|
||||||
|
disable_time_sync?: boolean;
|
||||||
|
|
||||||
|
// Default: false. If true, we'll throw errors if any params are undefined
|
||||||
|
strict_param_validation?: boolean;
|
||||||
|
|
||||||
|
// Optionally override API protocol + domain
|
||||||
|
// e.g 'https://api.bytick.com'
|
||||||
|
baseUrl?: string;
|
||||||
|
|
||||||
|
// Default: true. whether to try and post-process request exceptions.
|
||||||
|
parse_exceptions?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const API_KEY = 'xxx';
|
||||||
|
const PRIVATE_KEY = 'yyy';
|
||||||
|
const useLivenet = false;
|
||||||
|
|
||||||
|
const client = new LinearClient(
|
||||||
|
API_KEY,
|
||||||
|
PRIVATE_KEY,
|
||||||
|
|
||||||
|
// optional, uses testnet by default. Set to 'true' to use livenet.
|
||||||
|
useLivenet,
|
||||||
|
|
||||||
|
// restInverseOptions,
|
||||||
|
// requestLibraryOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
client.changeUserLeverage({leverage: 4, symbol: 'ETHUSD'})
|
||||||
|
.then(result => {
|
||||||
|
console.log(result);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### WebSockets
|
||||||
|
|
||||||
|
Inverse & linear WebSockets can be used via a shared `WebsocketClient`.
|
||||||
|
|
||||||
|
Note: to use the linear websockets, pass "linear: true" in the constructor options when instancing the `WebsocketClient`.
|
||||||
|
|
||||||
|
To connect to both linear and inverse websockets, make two instances of the WebsocketClient:
|
||||||
|
|
||||||
#### Websocket client
|
|
||||||
```javascript
|
```javascript
|
||||||
const { WebsocketClient } = require('bybit-api');
|
const { WebsocketClient } = require('bybit-api');
|
||||||
|
|
||||||
@@ -123,7 +182,7 @@ const wsConfig = {
|
|||||||
// config options sent to RestClient (used for time sync). See RestClient docs.
|
// config options sent to RestClient (used for time sync). See RestClient docs.
|
||||||
// restOptions: { },
|
// restOptions: { },
|
||||||
|
|
||||||
// config for axios to pass to RestClient. E.g for proxy support
|
// config for axios used for HTTP requests. E.g for proxy support
|
||||||
// requestOptions: { }
|
// requestOptions: { }
|
||||||
|
|
||||||
// override which URL to use for websocket connections
|
// override which URL to use for websocket connections
|
||||||
|
|||||||
@@ -11,10 +11,11 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"clean": "rm -rf lib dist",
|
"clean": "rm -rf lib dist",
|
||||||
"prebuild": "npm run clean",
|
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
"build:clean": "npm run clean && npm run build",
|
||||||
|
"build:watch": "npm run clean && tsc --watch",
|
||||||
"pack": "webpack --config webpack/webpack.config.js",
|
"pack": "webpack --config webpack/webpack.config.js",
|
||||||
"prepublish": "npm run build",
|
"prepublish": "npm run build:clean",
|
||||||
"betapublish": "npm publish --tag beta"
|
"betapublish": "npm publish --tag beta"
|
||||||
},
|
},
|
||||||
"author": "Tiago Siebler (https://github.com/tiagosiebler)",
|
"author": "Tiago Siebler (https://github.com/tiagosiebler)",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { AxiosRequestConfig } from 'axios';
|
import { AxiosRequestConfig } from 'axios';
|
||||||
import { GenericAPIResponse, getBaseRESTInverseUrl, RestClientInverseOptions } from './util/requestUtils';
|
import { GenericAPIResponse, getRestBaseUrl, RestClientOptions } from './util/requestUtils';
|
||||||
import RequestWrapper from './util/requestWrapper';
|
import RequestWrapper from './util/requestWrapper';
|
||||||
import SharedEndpoints from './shared-endpoints';
|
import SharedEndpoints from './shared-endpoints';
|
||||||
|
|
||||||
@@ -12,23 +12,23 @@ export class InverseClient extends SharedEndpoints {
|
|||||||
* @param {string} key - your API key
|
* @param {string} key - your API key
|
||||||
* @param {string} secret - your API secret
|
* @param {string} secret - your API secret
|
||||||
* @param {boolean} [useLivenet=false]
|
* @param {boolean} [useLivenet=false]
|
||||||
* @param {RestClientInverseOptions} [restInverseOptions={}] options to configure REST API connectivity
|
* @param {RestClientOptions} [restInverseOptions={}] options to configure REST API connectivity
|
||||||
* @param {AxiosRequestConfig} [requestOptions={}] HTTP networking options for axios
|
* @param {AxiosRequestConfig} [requestOptions={}] HTTP networking options for axios
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
key?: string | undefined,
|
key?: string | undefined,
|
||||||
secret?: string | undefined,
|
secret?: string | undefined,
|
||||||
useLivenet?: boolean,
|
useLivenet?: boolean,
|
||||||
restInverseOptions: RestClientInverseOptions = {},
|
restInverseOptions: RestClientOptions = {},
|
||||||
httpOptions: AxiosRequestConfig = {}
|
requestOptions: AxiosRequestConfig = {}
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
this.requestWrapper = new RequestWrapper(
|
this.requestWrapper = new RequestWrapper(
|
||||||
key,
|
key,
|
||||||
secret,
|
secret,
|
||||||
getBaseRESTInverseUrl(useLivenet),
|
getRestBaseUrl(useLivenet),
|
||||||
restInverseOptions,
|
restInverseOptions,
|
||||||
httpOptions
|
requestOptions
|
||||||
);
|
);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { AxiosRequestConfig } from 'axios';
|
import { AxiosRequestConfig } from 'axios';
|
||||||
import { GenericAPIResponse, getBaseRESTInverseUrl, RestClientInverseOptions } from './util/requestUtils';
|
import { GenericAPIResponse, getRestBaseUrl, RestClientOptions } from './util/requestUtils';
|
||||||
import RequestWrapper from './util/requestWrapper';
|
import RequestWrapper from './util/requestWrapper';
|
||||||
import SharedEndpoints from './shared-endpoints';
|
import SharedEndpoints from './shared-endpoints';
|
||||||
|
|
||||||
@@ -11,23 +11,22 @@ export class LinearClient extends SharedEndpoints {
|
|||||||
*
|
*
|
||||||
* @param {string} key - your API key
|
* @param {string} key - your API key
|
||||||
* @param {string} secret - your API secret
|
* @param {string} secret - your API secret
|
||||||
* @param {boolean} [livenet=false]
|
* @param {boolean} [useLivenet=false]
|
||||||
* @param {RestClientInverseOptions} [restInverseOptions={}] options to configure REST API connectivity
|
* @param {RestClientOptions} [restInverseOptions={}] options to configure REST API connectivity
|
||||||
* @param {AxiosRequestConfig} [requestOptions={}] HTTP networking options for axios
|
* @param {AxiosRequestConfig} [requestOptions={}] HTTP networking options for axios
|
||||||
*/
|
*/
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
key?: string | undefined,
|
key?: string | undefined,
|
||||||
secret?: string | undefined,
|
secret?: string | undefined,
|
||||||
livenet?: boolean,
|
useLivenet?: boolean,
|
||||||
restInverseOptions:RestClientInverseOptions = {}, // TODO: Rename this type to be more general.
|
restInverseOptions: RestClientOptions = {},
|
||||||
requestOptions: AxiosRequestConfig = {}
|
requestOptions: AxiosRequestConfig = {}
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
this.requestWrapper = new RequestWrapper(
|
this.requestWrapper = new RequestWrapper(
|
||||||
key,
|
key,
|
||||||
secret,
|
secret,
|
||||||
getBaseRESTInverseUrl(livenet),
|
getRestBaseUrl(useLivenet),
|
||||||
restInverseOptions,
|
restInverseOptions,
|
||||||
requestOptions
|
requestOptions
|
||||||
);
|
);
|
||||||
@@ -46,23 +45,11 @@ export class LinearClient extends SharedEndpoints {
|
|||||||
from: number;
|
from: number;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
}): GenericAPIResponse {
|
}): GenericAPIResponse {
|
||||||
return this.requestWrapper.get('/public/linear/kline', params);
|
return this.requestWrapper.get('public/linear/kline', params);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated use getTrades() instead
|
|
||||||
*/
|
|
||||||
getPublicTradingRecords(params: {
|
|
||||||
symbol: string;
|
|
||||||
from?: number;
|
|
||||||
limit?: number;
|
|
||||||
}): GenericAPIResponse {
|
|
||||||
return this.getTrades(params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getTrades(params: {
|
getTrades(params: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
//from?: number;
|
|
||||||
limit?: number;
|
limit?: number;
|
||||||
}): GenericAPIResponse {
|
}): GenericAPIResponse {
|
||||||
return this.requestWrapper.get('public/linear/recent-trading-records', params);
|
return this.requestWrapper.get('public/linear/recent-trading-records', params);
|
||||||
@@ -105,10 +92,6 @@ export class LinearClient extends SharedEndpoints {
|
|||||||
*
|
*
|
||||||
* Account Data Endpoints
|
* Account Data Endpoints
|
||||||
*
|
*
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Active orders
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
placeActiveOrder(params: {
|
placeActiveOrder(params: {
|
||||||
@@ -137,7 +120,6 @@ export class LinearClient extends SharedEndpoints {
|
|||||||
page?: number;
|
page?: number;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
order_status?: string;
|
order_status?: string;
|
||||||
|
|
||||||
}): GenericAPIResponse {
|
}): GenericAPIResponse {
|
||||||
return this.requestWrapper.get('private/linear/order/list', params);
|
return this.requestWrapper.get('private/linear/order/list', params);
|
||||||
}
|
}
|
||||||
@@ -345,7 +327,15 @@ export class LinearClient extends SharedEndpoints {
|
|||||||
getRiskLimitList(params: {
|
getRiskLimitList(params: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
}): GenericAPIResponse {
|
}): GenericAPIResponse {
|
||||||
return this.requestWrapper.get('public/linear/risk-limit');
|
return this.requestWrapper.get('public/linear/risk-limit', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
setRiskLimit(params: {
|
||||||
|
symbol: string;
|
||||||
|
side: string;
|
||||||
|
risk_id: string;
|
||||||
|
}): GenericAPIResponse {
|
||||||
|
return this.requestWrapper.get('private/linear/position/set-risk', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -355,13 +345,12 @@ export class LinearClient extends SharedEndpoints {
|
|||||||
getPredictedFundingFee(params: {
|
getPredictedFundingFee(params: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
}): GenericAPIResponse {
|
}): GenericAPIResponse {
|
||||||
return this.requestWrapper.get('private/linear/funding/predicted-funding');
|
return this.requestWrapper.get('private/linear/funding/predicted-funding', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLastFundingFee(params: {
|
getLastFundingFee(params: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
}): GenericAPIResponse {
|
}): GenericAPIResponse {
|
||||||
return this.requestWrapper.get('private/linear/funding/prev-funding');
|
return this.requestWrapper.get('private/linear/funding/prev-funding', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ export default class SharedEndpoints {
|
|||||||
return this.requestWrapper.get('v2/public/liq-records', params);
|
return this.requestWrapper.get('v2/public/liq-records', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Market Data : Advanced
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
getOpenInterest(params: {
|
getOpenInterest(params: {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
period: string;
|
period: string;
|
||||||
@@ -113,6 +119,14 @@ export default class SharedEndpoints {
|
|||||||
return this.requestWrapper.get('v2/private/exchange-order/list', params);
|
return this.requestWrapper.get('v2/private/exchange-order/list', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAssetExchangeRecords(params?: {
|
||||||
|
limit?: number;
|
||||||
|
from?: number;
|
||||||
|
direction?: string;
|
||||||
|
}): GenericAPIResponse {
|
||||||
|
return this.requestWrapper.get('v2/private/exchange-order/list', params);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* API Data Endpoints
|
* API Data Endpoints
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createHmac } from 'crypto';
|
import { createHmac } from 'crypto';
|
||||||
|
|
||||||
export interface RestClientInverseOptions {
|
export interface RestClientOptions {
|
||||||
// override the max size of the request window (in ms)
|
// override the max size of the request window (in ms)
|
||||||
recv_window?: number;
|
recv_window?: number;
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ export function serializeParams(params: object = {}, strict_validation = false):
|
|||||||
.join('&');
|
.join('&');
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getBaseRESTInverseUrl(useLivenet?: boolean, restInverseOptions?: RestClientInverseOptions) {
|
export function getRestBaseUrl(useLivenet?: boolean, restInverseOptions?: RestClientOptions) {
|
||||||
const baseUrlsInverse = {
|
const baseUrlsInverse = {
|
||||||
livenet: 'https://api.bybit.com',
|
livenet: 'https://api.bybit.com',
|
||||||
testnet: 'https://api-testnet.bybit.com'
|
testnet: 'https://api-testnet.bybit.com'
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import axios, { AxiosRequestConfig, AxiosResponse, Method } from 'axios';
|
import axios, { AxiosRequestConfig, AxiosResponse, Method } from 'axios';
|
||||||
|
|
||||||
import { signMessage, serializeParams, RestClientInverseOptions, GenericAPIResponse, isPublicEndpoint } from './requestUtils';
|
import { signMessage, serializeParams, RestClientOptions, GenericAPIResponse, isPublicEndpoint } from './requestUtils';
|
||||||
|
|
||||||
export default class RequestUtil {
|
export default class RequestUtil {
|
||||||
private timeOffset: number | null;
|
private timeOffset: number | null;
|
||||||
private syncTimePromise: null | Promise<any>;
|
private syncTimePromise: null | Promise<any>;
|
||||||
private options: RestClientInverseOptions;
|
private options: RestClientOptions;
|
||||||
private baseUrl: string;
|
private baseUrl: string;
|
||||||
private globalRequestOptions: AxiosRequestConfig;
|
private globalRequestOptions: AxiosRequestConfig;
|
||||||
private key: string | undefined;
|
private key: string | undefined;
|
||||||
@@ -15,7 +15,7 @@ export default class RequestUtil {
|
|||||||
key: string | undefined,
|
key: string | undefined,
|
||||||
secret: string | undefined,
|
secret: string | undefined,
|
||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
options: RestClientInverseOptions = {},
|
options: RestClientOptions = {},
|
||||||
requestOptions: AxiosRequestConfig = {}
|
requestOptions: AxiosRequestConfig = {}
|
||||||
) {
|
) {
|
||||||
this.timeOffset = null;
|
this.timeOffset = null;
|
||||||
|
|||||||
@@ -75,6 +75,16 @@ const getLinearWsKeyForTopic = (topic: string) => {
|
|||||||
return wsKeyLinearPublic;
|
return wsKeyLinearPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export declare interface WebsocketClient {
|
||||||
|
on(event: 'open', listener: ({ wsKey: string, event: any }) => void): this;
|
||||||
|
on(event: 'reconnected', listener: ({ wsKey: string, event: any }) => void): this;
|
||||||
|
on(event: 'reconnect', listener: () => void): this;
|
||||||
|
on(event: 'close', listener: () => void): this;
|
||||||
|
on(event: 'response', listener: (response: any) => void): this;
|
||||||
|
on(event: 'update', listener: (response: any) => void): this;
|
||||||
|
on(event: 'error', listener: (response: any) => void): this;
|
||||||
|
}
|
||||||
|
|
||||||
export class WebsocketClient extends EventEmitter {
|
export class WebsocketClient extends EventEmitter {
|
||||||
private logger: typeof DefaultLogger;
|
private logger: typeof DefaultLogger;
|
||||||
private restClient: InverseClient | LinearClient;
|
private restClient: InverseClient | LinearClient;
|
||||||
|
|||||||
Reference in New Issue
Block a user