diff --git a/package-lock.json b/package-lock.json index c28f24e..d370465 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "bybit-api", - "version": "2.0.7", + "version": "2.1.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e8dcdc2..9708c7e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bybit-api", - "version": "2.1.6", + "version": "2.1.7", "description": "Node.js connector for Bybit's REST APIs and WebSockets, with TypeScript & integration tests.", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/src/index.ts b/src/index.ts index 7f3aa47..ab33042 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,3 +4,5 @@ export * from './linear-client'; export * from './spot-client'; export * from './websocket-client'; export * from './logger'; +export * from './types/shared'; +export * from './types/spot'; diff --git a/src/inverse-client.ts b/src/inverse-client.ts index 1120ca4..76e5358 100644 --- a/src/inverse-client.ts +++ b/src/inverse-client.ts @@ -2,6 +2,7 @@ import { AxiosRequestConfig } from 'axios'; import { GenericAPIResponse, getRestBaseUrl, RestClientOptions } from './util/requestUtils'; import RequestWrapper from './util/requestWrapper'; import SharedEndpoints from './shared-endpoints'; +import { SymbolFromLimitParam, SymbolIntervalFromLimitParam, SymbolParam } from './types/shared'; export class InverseClient extends SharedEndpoints { protected requestWrapper: RequestWrapper; @@ -40,67 +41,37 @@ export class InverseClient extends SharedEndpoints { * */ - getKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/kline/list', params); } /** * @deprecated use getTickers() instead */ - getLatestInformation(params?: { - symbol?: string; - }): GenericAPIResponse { + getLatestInformation(params?: Partial): GenericAPIResponse { return this.getTickers(params); } /** * @deprecated use getTrades() instead */ - getPublicTradingRecords(params: { - symbol: string; - from?: number; - limit?: number; - }): GenericAPIResponse { + getPublicTradingRecords(params: SymbolFromLimitParam): GenericAPIResponse { return this.getTrades(params); } - getTrades(params: { - symbol: string; - from?: number; - limit?: number; - }): GenericAPIResponse { + getTrades(params: SymbolFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/trading-records', params); } - getMarkPriceKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getMarkPriceKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/mark-price-kline', params); } - getIndexPriceKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getIndexPriceKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/index-price-kline', params); } - getPremiumIndexKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getPremiumIndexKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/premium-index-kline', params); } @@ -150,9 +121,7 @@ export class InverseClient extends SharedEndpoints { return this.requestWrapper.post('v2/private/order/cancel', params); } - cancelAllActiveOrders(params: { - symbol: string; - }): GenericAPIResponse { + cancelAllActiveOrders(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.post('v2/private/order/cancelAll', params); } @@ -212,9 +181,7 @@ export class InverseClient extends SharedEndpoints { return this.requestWrapper.post('v2/private/stop-order/cancel', params); } - cancelAllConditionalOrders(params: { - symbol: string; - }): GenericAPIResponse { + cancelAllConditionalOrders(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.post('v2/private/stop-order/cancelAll', params); } @@ -248,9 +215,7 @@ export class InverseClient extends SharedEndpoints { return this.requestWrapper.get('user/leverage'); } - getPosition(params?: { - symbol?: string; - }): GenericAPIResponse { + getPosition(params?: Partial): GenericAPIResponse { return this.requestWrapper.get('v2/private/position/list', params); } @@ -359,21 +324,15 @@ export class InverseClient extends SharedEndpoints { * Funding */ - getLastFundingRate(params: { - symbol: string; - }): GenericAPIResponse { + getLastFundingRate(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/funding/prev-funding-rate', params); } - getMyLastFundingFee(params: { - symbol: string; - }): GenericAPIResponse { + getMyLastFundingFee(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('v2/private/funding/prev-funding', params); } - getPredictedFunding(params: { - symbol: string; - }): GenericAPIResponse { + getPredictedFunding(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('v2/private/funding/predicted-funding', params); } @@ -381,12 +340,10 @@ export class InverseClient extends SharedEndpoints { * LCP Info */ - getLcpInfo(params: { - symbol: string; - }): GenericAPIResponse { + getLcpInfo(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('v2/private/account/lcp', params); } - + //API Key Info getAPIKeyInfo(): GenericAPIResponse { return this.requestWrapper.get('v2/private/account/api-key'); diff --git a/src/inverse-futures-client.ts b/src/inverse-futures-client.ts index 9605e19..9b24dcd 100644 --- a/src/inverse-futures-client.ts +++ b/src/inverse-futures-client.ts @@ -2,6 +2,7 @@ import { AxiosRequestConfig } from 'axios'; import { GenericAPIResponse, getRestBaseUrl, RestClientOptions } from './util/requestUtils'; import RequestWrapper from './util/requestWrapper'; import SharedEndpoints from './shared-endpoints'; +import { SymbolFromLimitParam, SymbolIntervalFromLimitParam, SymbolParam } from './types/shared'; export class InverseFuturesClient extends SharedEndpoints { protected requestWrapper: RequestWrapper; @@ -40,50 +41,26 @@ export class InverseFuturesClient extends SharedEndpoints { * Note: These are currently the same as the inverse client */ - getKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/kline/list', params); } /** * Public trading records */ - getTrades(params: { - symbol: string; - from?: number; - limit?: number; - }): GenericAPIResponse { + getTrades(params: SymbolFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/trading-records', params); } - getMarkPriceKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getMarkPriceKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/mark-price-kline', params); } - getIndexPriceKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getIndexPriceKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/index-price-kline', params); } - getPremiumIndexKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getPremiumIndexKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/premium-index-kline', params); } @@ -131,9 +108,7 @@ export class InverseFuturesClient extends SharedEndpoints { return this.requestWrapper.post('futures/private/order/cancel', params); } - cancelAllActiveOrders(params: { - symbol: string; - }): GenericAPIResponse { + cancelAllActiveOrders(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.post('futures/private/order/cancelAll', params); } @@ -193,9 +168,7 @@ export class InverseFuturesClient extends SharedEndpoints { return this.requestWrapper.post('futures/private/stop-order/cancel', params); } - cancelAllConditionalOrders(params: { - symbol: string; - }): GenericAPIResponse { + cancelAllConditionalOrders(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.post('futures/private/stop-order/cancelAll', params); } @@ -226,9 +199,7 @@ export class InverseFuturesClient extends SharedEndpoints { /** * Get position list */ - getPosition(params?: { - symbol?: string; - }): GenericAPIResponse { + getPosition(params?: Partial): GenericAPIResponse { return this.requestWrapper.get('futures/private/position/list', params); } @@ -325,21 +296,15 @@ export class InverseFuturesClient extends SharedEndpoints { * Funding */ - getLastFundingRate(params: { - symbol: string; - }): GenericAPIResponse { + getLastFundingRate(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/funding/prev-funding-rate', params); } - getMyLastFundingFee(params: { - symbol: string; - }): GenericAPIResponse { + getMyLastFundingFee(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('v2/private/funding/prev-funding', params); } - getPredictedFunding(params: { - symbol: string; - }): GenericAPIResponse { + getPredictedFunding(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('v2/private/funding/predicted-funding', params); } @@ -347,9 +312,7 @@ export class InverseFuturesClient extends SharedEndpoints { * LCP Info */ - getLcpInfo(params: { - symbol: string; - }): GenericAPIResponse { + getLcpInfo(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('v2/private/account/lcp', params); } }; diff --git a/src/linear-client.ts b/src/linear-client.ts index 09c86ca..f482afb 100644 --- a/src/linear-client.ts +++ b/src/linear-client.ts @@ -2,6 +2,7 @@ import { AxiosRequestConfig } from 'axios'; import { GenericAPIResponse, getRestBaseUrl, RestClientOptions } from './util/requestUtils'; import RequestWrapper from './util/requestWrapper'; import SharedEndpoints from './shared-endpoints'; +import { SymbolIntervalFromLimitParam, SymbolLimitParam, SymbolParam } from '.'; export class LinearClient extends SharedEndpoints { protected requestWrapper: RequestWrapper; @@ -40,52 +41,27 @@ export class LinearClient extends SharedEndpoints { * */ - getKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('public/linear/kline', params); } - getTrades(params: { - symbol: string; - limit?: number; - }): GenericAPIResponse { + getTrades(params: SymbolLimitParam): GenericAPIResponse { return this.requestWrapper.get('public/linear/recent-trading-records', params); } - getLastFundingRate(params: { - symbol: string; - }): GenericAPIResponse { + getLastFundingRate(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('public/linear/funding/prev-funding-rate', params); } - getMarkPriceKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getMarkPriceKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('public/linear/mark-price-kline', params); } - getIndexPriceKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getIndexPriceKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('public/linear/index-price-kline', params); } - getPremiumIndexKline(params: { - symbol: string; - interval: string; - from: number; - limit?: number; - }): GenericAPIResponse { + getPremiumIndexKline(params: SymbolIntervalFromLimitParam): GenericAPIResponse { return this.requestWrapper.get('public/linear/premium-index-kline', params); } @@ -133,9 +109,7 @@ export class LinearClient extends SharedEndpoints { return this.requestWrapper.post('private/linear/order/cancel', params); } - cancelAllActiveOrders(params: { - symbol: string; - }): GenericAPIResponse { + cancelAllActiveOrders(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.post('private/linear/order/cancel-all', params); } @@ -206,9 +180,7 @@ export class LinearClient extends SharedEndpoints { return this.requestWrapper.post('private/linear/stop-order/cancel', params); } - cancelAllConditionalOrders(params: { - symbol: string; - }): GenericAPIResponse { + cancelAllConditionalOrders(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.post('private/linear/stop-order/cancel-all', params); } @@ -239,9 +211,7 @@ export class LinearClient extends SharedEndpoints { * Position */ - getPosition(params?: { - symbol?: string; - }): GenericAPIResponse { + getPosition(params?: Partial): GenericAPIResponse { return this.requestWrapper.get('private/linear/position/list', params); } @@ -325,9 +295,7 @@ export class LinearClient extends SharedEndpoints { * Risk Limit */ - getRiskLimitList(params: { - symbol: string; - }): GenericAPIResponse { + getRiskLimitList(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('public/linear/risk-limit', params); } @@ -343,15 +311,11 @@ export class LinearClient extends SharedEndpoints { * Funding */ - getPredictedFundingFee(params: { - symbol: string; - }): GenericAPIResponse { + getPredictedFundingFee(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('private/linear/funding/predicted-funding', params); } - getLastFundingFee(params: { - symbol: string; - }): GenericAPIResponse { + getLastFundingFee(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('private/linear/funding/prev-funding', params); } } diff --git a/src/shared-endpoints.ts b/src/shared-endpoints.ts index c3ffd73..d778877 100644 --- a/src/shared-endpoints.ts +++ b/src/shared-endpoints.ts @@ -1,3 +1,14 @@ +import { + APIResponse, + AssetExchangeRecordsReq, + CoinParam, + SymbolInfo, + SymbolLimitParam, + SymbolParam, + SymbolPeriodLimitParam, + WalletFundRecordsReq, + WithdrawRecordsReq, +} from './types/shared'; import { GenericAPIResponse } from './util/requestUtils'; import RequestWrapper from './util/requestWrapper'; @@ -11,22 +22,18 @@ export default class SharedEndpoints { * */ - getOrderBook(params: { - symbol: string; - }): GenericAPIResponse { + getOrderBook(params: SymbolParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/orderBook/L2', params); } /** * Get latest information for symbol */ - getTickers(params?: { - symbol?: string; - }): GenericAPIResponse { + getTickers(params?: Partial): GenericAPIResponse { return this.requestWrapper.get('v2/public/tickers', params); } - getSymbols(): GenericAPIResponse { + getSymbols(): Promise> { return this.requestWrapper.get('v2/public/symbols'); } @@ -36,26 +43,15 @@ export default class SharedEndpoints { * */ - getOpenInterest(params: { - symbol: string; - period: string; - limit?: number; - }): GenericAPIResponse { + getOpenInterest(params: SymbolPeriodLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/open-interest', params); } - getLatestBigDeal(params: { - symbol: string; - limit?: number; - }): GenericAPIResponse { + getLatestBigDeal(params: SymbolLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/big-deal', params); } - getLongShortRatio(params: { - symbol: string; - period: string; - limit?: number; - }): GenericAPIResponse { + getLongShortRatio(params: SymbolPeriodLimitParam): GenericAPIResponse { return this.requestWrapper.get('v2/public/account-ratio', params); } @@ -75,40 +71,19 @@ export default class SharedEndpoints { * */ - getWalletBalance(params: { - coin?: string; - }): GenericAPIResponse { + getWalletBalance(params?: Partial): GenericAPIResponse { return this.requestWrapper.get('v2/private/wallet/balance', params) } - getWalletFundRecords(params?: { - start_date?: string; - end_date?: string; - currency?: string; - coin?: string; - wallet_fund_type?: string; - page?: number; - limit?: number; - }): GenericAPIResponse { + getWalletFundRecords(params?: WalletFundRecordsReq): GenericAPIResponse { return this.requestWrapper.get('v2/private/wallet/fund/records', params); } - getWithdrawRecords(params: { - start_date?: string; - end_date?: string; - coin?: string; - status?: string; - page?: number; - limit?: number; - }): GenericAPIResponse { + getWithdrawRecords(params: WithdrawRecordsReq): GenericAPIResponse { return this.requestWrapper.get('v2/private/wallet/withdraw/list', params); } - getAssetExchangeRecords(params?: { - limit?: number; - from?: number; - direction?: string; - }): GenericAPIResponse { + getAssetExchangeRecords(params?: AssetExchangeRecordsReq): GenericAPIResponse { return this.requestWrapper.get('v2/private/exchange-order/list', params); } diff --git a/src/types/shared.ts b/src/types/shared.ts index 73ea211..76e3fa7 100644 --- a/src/types/shared.ts +++ b/src/types/shared.ts @@ -11,3 +11,108 @@ export type KlineInterval = '1m' | '1d' | '1w' | '1M'; + +export type numberInString = string; + +export interface APIResponse { + ret_code: number; + ret_msg: "OK" | string; + ext_code: string; + ext_info: string; + result: T; +} + +/** + * Request Parameter Types + */ +export interface SymbolParam { + symbol: string; +} + +export interface SymbolLimitParam { + symbol: string; + limit?: number; +} + +export interface SymbolPeriodLimitParam { + symbol: string; + period: string; + limit?: number; +} + +export interface SymbolFromLimitParam { + symbol: string; + from?: number; + limit?: number; +} + +export interface SymbolIntervalFromLimitParam { + symbol: string; + interval: string; + from: number; + limit?: number; +} + +export interface CoinParam { + coin: string; +} + +export interface WalletFundRecordsReq { + start_date?: string; + end_date?: string; + currency?: string; + coin?: string; + wallet_fund_type?: string; + page?: number; + limit?: number; +} + +export interface WithdrawRecordsReq { + start_date?: string; + end_date?: string; + coin?: string; + status?: string; + page?: number; + limit?: number; +} + +export interface AssetExchangeRecordsReq { + limit?: number; + from?: number; + direction?: string; +} + +/** + * Response types + */ + +export interface LeverageFilter { + min_leverage: numberInString; + max_leveage: numberInString; + leverage_step: numberInString; +} +export interface PriceFilter { + min_price: numberInString; + max_price: numberInString; + tick_size: numberInString; +} + +export interface LotSizeFilter { + max_trading_qty: number; + min_trading_qty: number; + qty_step: number; +} + +export interface SymbolInfo { + name: string; + alias: string; + status: 'Trading' | string; + base_currency: string; + quote_currency: string; + price_scale: number; + taker_fee: numberInString; + maker_fee: numberInString; + leverage_filter: LeverageFilter; + price_filter: PriceFilter; + lot_size_filter: LotSizeFilter; +} diff --git a/src/util/requestWrapper.ts b/src/util/requestWrapper.ts index aed143f..be0e9c2 100644 --- a/src/util/requestWrapper.ts +++ b/src/util/requestWrapper.ts @@ -56,18 +56,18 @@ export default class RequestUtil { this.secret = secret; } - get(endpoint: string, params?: any): GenericAPIResponse { + get(endpoint: string, params?: any): Promise { return this._call('GET', endpoint, params); } - post(endpoint: string, params?: any): GenericAPIResponse { + post(endpoint: string, params?: any): Promise { return this._call('POST', endpoint, params); } /** * @private Make a HTTP request to a specific endpoint. Private endpoints are automatically signed. */ - async _call(method: Method, endpoint: string, params?: any): GenericAPIResponse { + async _call(method: Method, endpoint: string, params?: any): Promise { if (!isPublicEndpoint(endpoint)) { if (!this.key || !this.secret) { throw new Error('Private endpoints require api and private keys set'); @@ -183,7 +183,7 @@ export default class RequestUtil { */ async getTimeOffset(): Promise { const start = Date.now(); - const result = await this.get('v2/public/time'); + const result = await this.get('v2/public/time'); const end = Date.now(); return Math.ceil((result.time_now * 1000) - end + ((end - start) / 2)); diff --git a/src/websocket-client.ts b/src/websocket-client.ts index 2eca7c7..1398585 100644 --- a/src/websocket-client.ts +++ b/src/websocket-client.ts @@ -544,6 +544,9 @@ export class WebsocketClient extends EventEmitter { private onWsMessage(event, wsKey: WsKey) { try { + // any message can clear the pong timer - wouldn't get a message if the ws dropped + this.clearPongTimer(wsKey); + const msg = JSON.parse(event && event.data || event); if ('success' in msg || msg?.pong) { this.onWsMessageResponse(msg, wsKey); @@ -579,7 +582,6 @@ export class WebsocketClient extends EventEmitter { private onWsMessageResponse(response: any, wsKey: WsKey) { if (isWsPong(response)) { this.logger.silly('Received pong', { ...loggerCategory, wsKey }); - this.clearPongTimer(wsKey); } else { this.emit('response', response); } diff --git a/tsconfig.json b/tsconfig.json index 0e8a4ca..4af98e5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,6 @@ "sourceMap": true, "esModuleInterop": true, "lib": ["es2017","dom"], - "baseUrl": ".", "outDir": "lib" }, "include": ["src/**/*"],