Merge pull request #3 from tiagosiebler/linearCleaning

move script commands around. Move shared endpoint down.
This commit is contained in:
CryptoCompiler
2021-02-14 16:59:18 +00:00
committed by GitHub
9 changed files with 139 additions and 64 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)",

View File

@@ -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;
} }
@@ -47,7 +47,7 @@ export class InverseClient extends SharedEndpoints {
}): GenericAPIResponse { }): GenericAPIResponse {
return this.requestWrapper.get('v2/public/kline/list', params); return this.requestWrapper.get('v2/public/kline/list', params);
} }
/** /**
* @deprecated use getTickers() instead * @deprecated use getTickers() instead
*/ */
@@ -56,7 +56,7 @@ export class InverseClient extends SharedEndpoints {
}): GenericAPIResponse { }): GenericAPIResponse {
return this.getTickers(params); return this.getTickers(params);
} }
/** /**
* @deprecated use getTrades() instead * @deprecated use getTrades() instead
*/ */
@@ -75,7 +75,7 @@ export class InverseClient extends SharedEndpoints {
}): GenericAPIResponse { }): GenericAPIResponse {
return this.requestWrapper.get('v2/public/trading-records', params); return this.requestWrapper.get('v2/public/trading-records', params);
} }
/** /**
* @deprecated use getLiquidations() instead * @deprecated use getLiquidations() instead
*/ */
@@ -97,7 +97,7 @@ export class InverseClient extends SharedEndpoints {
}): GenericAPIResponse { }): GenericAPIResponse {
return this.requestWrapper.get('v2/public/mark-price-kline', params); return this.requestWrapper.get('v2/public/mark-price-kline', params);
} }
getIndexPriceKline(params: { getIndexPriceKline(params: {
symbol: string; symbol: string;
interval: string; interval: string;
@@ -106,7 +106,7 @@ export class InverseClient extends SharedEndpoints {
}): GenericAPIResponse { }): GenericAPIResponse {
return this.requestWrapper.get('v2/public/index-price-kline', params); return this.requestWrapper.get('v2/public/index-price-kline', params);
} }
getPremiumIndexKline(params: { getPremiumIndexKline(params: {
symbol: string; symbol: string;
interval: string; interval: string;
@@ -121,7 +121,7 @@ export class InverseClient extends SharedEndpoints {
* Account Data Endpoints * Account Data Endpoints
* *
*/ */
/** /**
* Active orders * Active orders
*/ */
@@ -183,7 +183,7 @@ export class InverseClient extends SharedEndpoints {
}): GenericAPIResponse { }): GenericAPIResponse {
return this.requestWrapper.get('v2/private/order', params); return this.requestWrapper.get('v2/private/order', params);
} }
/** /**
* Conditional orders * Conditional orders
*/ */
@@ -246,7 +246,7 @@ export class InverseClient extends SharedEndpoints {
}): GenericAPIResponse { }): GenericAPIResponse {
return this.requestWrapper.get('v2/private/stop-order', params); return this.requestWrapper.get('v2/private/stop-order', params);
} }
/** /**
* Position * Position
*/ */
@@ -328,7 +328,7 @@ export class InverseClient extends SharedEndpoints {
/** /**
* Risk Limit * Risk Limit
*/ */
getRiskLimitList(): GenericAPIResponse { getRiskLimitList(): GenericAPIResponse {
return this.requestWrapper.get('open-api/wallet/risk-limit/list'); return this.requestWrapper.get('open-api/wallet/risk-limit/list');
} }
@@ -339,7 +339,7 @@ export class InverseClient extends SharedEndpoints {
}): GenericAPIResponse { }): GenericAPIResponse {
return this.requestWrapper.post('open-api/wallet/risk-limit', params); return this.requestWrapper.post('open-api/wallet/risk-limit', params);
} }
/** /**
* Funding * Funding
*/ */
@@ -361,7 +361,7 @@ export class InverseClient extends SharedEndpoints {
}): GenericAPIResponse { }): GenericAPIResponse {
return this.requestWrapper.get('v2/private/funding/predicted-funding', params); return this.requestWrapper.get('v2/private/funding/predicted-funding', params);
} }
/** /**
* LCP Info * LCP Info
*/ */

View File

@@ -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);
@@ -82,7 +69,7 @@ export class LinearClient extends SharedEndpoints {
}): GenericAPIResponse { }): GenericAPIResponse {
return this.requestWrapper.get('public/linear/mark-price-kline', params); return this.requestWrapper.get('public/linear/mark-price-kline', params);
} }
getIndexPriceKline(params: { getIndexPriceKline(params: {
symbol: string; symbol: string;
interval: string; interval: string;
@@ -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);
} }
} }

View File

@@ -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

View File

@@ -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'

View File

@@ -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;

View File

@@ -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;