From 62750228c4989d51f763737ae3261acb141b0351 Mon Sep 17 00:00:00 2001 From: tiagosiebler Date: Sun, 14 Feb 2021 16:13:35 +0000 Subject: [PATCH 1/5] move script commands around. Move shared endpoint down. Add event annotations to ws client. --- .github/workflows/npmpublish.yml | 2 ++ package.json | 3 ++- src/shared-endpoints.ts | 16 ++++++++-------- src/websocket-client.ts | 10 ++++++++++ 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml index f2af8e7..b0b36fc 100644 --- a/.github/workflows/npmpublish.yml +++ b/.github/workflows/npmpublish.yml @@ -42,6 +42,8 @@ jobs: - run: npm ci if: steps.version-updated.outputs.has-updated + - run: npm run clean + if: steps.version-updated.outputs.has-updated - run: npm run build if: steps.version-updated.outputs.has-updated - run: npm publish diff --git a/package.json b/package.json index 47ac72c..b933318 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,9 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "clean": "rm -rf lib dist", - "prebuild": "npm run clean", + "buildclean": "npm run clean && npm run build", "build": "tsc", + "build:watch": "npm run clean && tsc --watch", "pack": "webpack --config webpack/webpack.config.js", "prepublish": "npm run build", "betapublish": "npm publish --tag beta" diff --git a/src/shared-endpoints.ts b/src/shared-endpoints.ts index fe7daed..0f868a0 100644 --- a/src/shared-endpoints.ts +++ b/src/shared-endpoints.ts @@ -82,14 +82,6 @@ export default class SharedEndpoints { return this.requestWrapper.get('v2/private/wallet/balance', params) } - getAssetExchangeRecords(params?: { - limit?: number; - from?: number; - direction?: string; - }): GenericAPIResponse { - return this.requestWrapper.get('v2/private/exchange-order/list', params); - } - getWalletFundRecords(params?: { start_date?: string; end_date?: string; @@ -113,6 +105,14 @@ export default class SharedEndpoints { return this.requestWrapper.get('v2/private/wallet/withdraw/list', params); } + getAssetExchangeRecords(params?: { + limit?: number; + from?: number; + direction?: string; + }): GenericAPIResponse { + return this.requestWrapper.get('v2/private/exchange-order/list', params); + } + /** * * API Data Endpoints diff --git a/src/websocket-client.ts b/src/websocket-client.ts index b81520b..27d9825 100644 --- a/src/websocket-client.ts +++ b/src/websocket-client.ts @@ -75,6 +75,16 @@ const getLinearWsKeyForTopic = (topic: string) => { 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 { private logger: typeof DefaultLogger; private restClient: InverseClient | LinearClient; From 3b2af548d0c53277ef7cc2078518cec5f88b6e76 Mon Sep 17 00:00:00 2001 From: tiagosiebler Date: Sun, 14 Feb 2021 16:15:45 +0000 Subject: [PATCH 2/5] cleaning in package json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b933318..98ff433 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,11 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "clean": "rm -rf lib dist", - "buildclean": "npm run clean && npm run build", "build": "tsc", + "build:clean": "npm run clean && npm run build", "build:watch": "npm run clean && tsc --watch", "pack": "webpack --config webpack/webpack.config.js", - "prepublish": "npm run build", + "prepublish": "npm run build:clean", "betapublish": "npm publish --tag beta" }, "author": "Tiago Siebler (https://github.com/tiagosiebler)", From 26602cfa05be58475d596969568f6ca13161f099 Mon Sep 17 00:00:00 2001 From: tiagosiebler Date: Sun, 14 Feb 2021 16:29:35 +0000 Subject: [PATCH 3/5] rename rest client options to be more generic --- src/inverse-client.ts | 34 +++++++++++++++++----------------- src/linear-client.ts | 17 ++++++++--------- src/util/requestUtils.ts | 4 ++-- src/util/requestWrapper.ts | 6 +++--- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/inverse-client.ts b/src/inverse-client.ts index a22e327..405c4b1 100644 --- a/src/inverse-client.ts +++ b/src/inverse-client.ts @@ -1,5 +1,5 @@ import { AxiosRequestConfig } from 'axios'; -import { GenericAPIResponse, getBaseRESTInverseUrl, RestClientInverseOptions } from './util/requestUtils'; +import { GenericAPIResponse, getRestBaseUrl, RestClientOptions } from './util/requestUtils'; import RequestWrapper from './util/requestWrapper'; import SharedEndpoints from './shared-endpoints'; @@ -12,23 +12,23 @@ export class InverseClient extends SharedEndpoints { * @param {string} key - your API key * @param {string} secret - your API secret * @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 */ constructor( key?: string | undefined, secret?: string | undefined, useLivenet?: boolean, - restInverseOptions: RestClientInverseOptions = {}, - httpOptions: AxiosRequestConfig = {} + restInverseOptions: RestClientOptions = {}, + requestOptions: AxiosRequestConfig = {} ) { super() this.requestWrapper = new RequestWrapper( key, secret, - getBaseRESTInverseUrl(useLivenet), + getRestBaseUrl(useLivenet), restInverseOptions, - httpOptions + requestOptions ); return this; } @@ -47,7 +47,7 @@ export class InverseClient extends SharedEndpoints { }): GenericAPIResponse { return this.requestWrapper.get('v2/public/kline/list', params); } - + /** * @deprecated use getTickers() instead */ @@ -56,7 +56,7 @@ export class InverseClient extends SharedEndpoints { }): GenericAPIResponse { return this.getTickers(params); } - + /** * @deprecated use getTrades() instead */ @@ -75,7 +75,7 @@ export class InverseClient extends SharedEndpoints { }): GenericAPIResponse { return this.requestWrapper.get('v2/public/trading-records', params); } - + /** * @deprecated use getLiquidations() instead */ @@ -97,7 +97,7 @@ export class InverseClient extends SharedEndpoints { }): GenericAPIResponse { return this.requestWrapper.get('v2/public/mark-price-kline', params); } - + getIndexPriceKline(params: { symbol: string; interval: string; @@ -106,7 +106,7 @@ export class InverseClient extends SharedEndpoints { }): GenericAPIResponse { return this.requestWrapper.get('v2/public/index-price-kline', params); } - + getPremiumIndexKline(params: { symbol: string; interval: string; @@ -121,7 +121,7 @@ export class InverseClient extends SharedEndpoints { * Account Data Endpoints * */ - + /** * Active orders */ @@ -183,7 +183,7 @@ export class InverseClient extends SharedEndpoints { }): GenericAPIResponse { return this.requestWrapper.get('v2/private/order', params); } - + /** * Conditional orders */ @@ -246,7 +246,7 @@ export class InverseClient extends SharedEndpoints { }): GenericAPIResponse { return this.requestWrapper.get('v2/private/stop-order', params); } - + /** * Position */ @@ -328,7 +328,7 @@ export class InverseClient extends SharedEndpoints { /** * Risk Limit */ - + getRiskLimitList(): GenericAPIResponse { return this.requestWrapper.get('open-api/wallet/risk-limit/list'); } @@ -339,7 +339,7 @@ export class InverseClient extends SharedEndpoints { }): GenericAPIResponse { return this.requestWrapper.post('open-api/wallet/risk-limit', params); } - + /** * Funding */ @@ -361,7 +361,7 @@ export class InverseClient extends SharedEndpoints { }): GenericAPIResponse { return this.requestWrapper.get('v2/private/funding/predicted-funding', params); } - + /** * LCP Info */ diff --git a/src/linear-client.ts b/src/linear-client.ts index e62f9e0..4ef2566 100644 --- a/src/linear-client.ts +++ b/src/linear-client.ts @@ -1,5 +1,5 @@ import { AxiosRequestConfig } from 'axios'; -import { GenericAPIResponse, getBaseRESTInverseUrl, RestClientInverseOptions } from './util/requestUtils'; +import { GenericAPIResponse, getRestBaseUrl, RestClientOptions } from './util/requestUtils'; import RequestWrapper from './util/requestWrapper'; import SharedEndpoints from './shared-endpoints'; @@ -11,23 +11,22 @@ export class LinearClient extends SharedEndpoints { * * @param {string} key - your API key * @param {string} secret - your API secret - * @param {boolean} [livenet=false] - * @param {RestClientInverseOptions} [restInverseOptions={}] options to configure REST API connectivity + * @param {boolean} [useLivenet=false] + * @param {RestClientOptions} [restInverseOptions={}] options to configure REST API connectivity * @param {AxiosRequestConfig} [requestOptions={}] HTTP networking options for axios */ - constructor( key?: string | undefined, secret?: string | undefined, - livenet?: boolean, - restInverseOptions:RestClientInverseOptions = {}, // TODO: Rename this type to be more general. + useLivenet?: boolean, + restInverseOptions: RestClientOptions = {}, requestOptions: AxiosRequestConfig = {} ) { super() this.requestWrapper = new RequestWrapper( key, secret, - getBaseRESTInverseUrl(livenet), + getRestBaseUrl(useLivenet), restInverseOptions, requestOptions ); @@ -46,7 +45,7 @@ export class LinearClient extends SharedEndpoints { from: number; limit?: number; }): GenericAPIResponse { - return this.requestWrapper.get('/public/linear/kline', params); + return this.requestWrapper.get('public/linear/kline', params); } /** @@ -82,7 +81,7 @@ export class LinearClient extends SharedEndpoints { }): GenericAPIResponse { return this.requestWrapper.get('public/linear/mark-price-kline', params); } - + getIndexPriceKline(params: { symbol: string; interval: string; diff --git a/src/util/requestUtils.ts b/src/util/requestUtils.ts index f75f106..903a7a2 100644 --- a/src/util/requestUtils.ts +++ b/src/util/requestUtils.ts @@ -1,6 +1,6 @@ import { createHmac } from 'crypto'; -export interface RestClientInverseOptions { +export interface RestClientOptions { // override the max size of the request window (in ms) recv_window?: number; @@ -42,7 +42,7 @@ export function serializeParams(params: object = {}, strict_validation = false): .join('&'); }; -export function getBaseRESTInverseUrl(useLivenet?: boolean, restInverseOptions?: RestClientInverseOptions) { +export function getRestBaseUrl(useLivenet?: boolean, restInverseOptions?: RestClientOptions) { const baseUrlsInverse = { livenet: 'https://api.bybit.com', testnet: 'https://api-testnet.bybit.com' diff --git a/src/util/requestWrapper.ts b/src/util/requestWrapper.ts index 7645061..e19f8f3 100644 --- a/src/util/requestWrapper.ts +++ b/src/util/requestWrapper.ts @@ -1,11 +1,11 @@ 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 { private timeOffset: number | null; private syncTimePromise: null | Promise; - private options: RestClientInverseOptions; + private options: RestClientOptions; private baseUrl: string; private globalRequestOptions: AxiosRequestConfig; private key: string | undefined; @@ -15,7 +15,7 @@ export default class RequestUtil { key: string | undefined, secret: string | undefined, baseUrl: string, - options: RestClientInverseOptions = {}, + options: RestClientOptions = {}, requestOptions: AxiosRequestConfig = {} ) { this.timeOffset = null; From 581cbe7d43208006739ca95a44c14ad89b2dd35f Mon Sep 17 00:00:00 2001 From: tiagosiebler Date: Sun, 14 Feb 2021 16:40:53 +0000 Subject: [PATCH 4/5] remove deprecated new method, fix missing parms --- src/linear-client.ts | 32 +++++++++++--------------------- src/shared-endpoints.ts | 6 ++++++ 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/linear-client.ts b/src/linear-client.ts index 4ef2566..59f7f52 100644 --- a/src/linear-client.ts +++ b/src/linear-client.ts @@ -48,20 +48,8 @@ export class LinearClient extends SharedEndpoints { 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: { symbol: string; - //from?: number; limit?: number; }): GenericAPIResponse { return this.requestWrapper.get('public/linear/recent-trading-records', params); @@ -104,10 +92,6 @@ export class LinearClient extends SharedEndpoints { * * Account Data Endpoints * - */ - - /** - * Active orders */ placeActiveOrder(params: { @@ -136,7 +120,6 @@ export class LinearClient extends SharedEndpoints { page?: number; limit?: number; order_status?: string; - }): GenericAPIResponse { return this.requestWrapper.get('private/linear/order/list', params); } @@ -344,7 +327,15 @@ export class LinearClient extends SharedEndpoints { getRiskLimitList(params: { symbol: string; }): 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); } /** @@ -354,13 +345,12 @@ export class LinearClient extends SharedEndpoints { getPredictedFundingFee(params: { symbol: string; }): GenericAPIResponse { - return this.requestWrapper.get('private/linear/funding/predicted-funding'); + return this.requestWrapper.get('private/linear/funding/predicted-funding', params); } getLastFundingFee(params: { symbol: string; }): GenericAPIResponse { - return this.requestWrapper.get('private/linear/funding/prev-funding'); + return this.requestWrapper.get('private/linear/funding/prev-funding', params); } - } diff --git a/src/shared-endpoints.ts b/src/shared-endpoints.ts index 0f868a0..1f3a9b2 100644 --- a/src/shared-endpoints.ts +++ b/src/shared-endpoints.ts @@ -37,6 +37,12 @@ export default class SharedEndpoints { return this.requestWrapper.get('v2/public/liq-records', params); } + /** + * + * Market Data : Advanced + * + */ + getOpenInterest(params: { symbol: string; period: string; From ce83b3a6662072a8ab236988591b0deb885ccae9 Mon Sep 17 00:00:00 2001 From: tiagosiebler Date: Sun, 14 Feb 2021 16:49:48 +0000 Subject: [PATCH 5/5] readme notes --- README.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 854b870..c13d7c5 100644 --- a/README.md +++ b/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. ### Inverse Contracts -#### Rest client -```javascript -const { RestClient } = require('bybit-api'); +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`: -const API_KEY = 'xxx'; -const PRIVATE_KEY = 'yyy'; -const useLivenet = false; +```javascript +const { InverseClient } = require('bybit-api'); const restInverseOptions = { // override the max size of the request window (in ms) @@ -68,7 +65,11 @@ const restInverseOptions = { parse_exceptions?: boolean; }; -const client = new RestClient( +const API_KEY = 'xxx'; +const PRIVATE_KEY = 'yyy'; +const useLivenet = false; + +const client = new InverseClient( API_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 const { WebsocketClient } = require('bybit-api'); @@ -123,7 +182,7 @@ const wsConfig = { // config options sent to RestClient (used for time sync). See RestClient docs. // 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: { } // override which URL to use for websocket connections