Merge pull request #129 from tiagosiebler/types

reduce ping timeouts for ws, improve request types, improve response types
This commit is contained in:
Tiago
2021-12-31 00:46:57 +00:00
committed by GitHub
11 changed files with 179 additions and 212 deletions

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "bybit-api",
"version": "2.0.7",
"version": "2.1.6",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

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

View File

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

View File

@@ -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<SymbolParam>): 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<SymbolParam>): 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');

View File

@@ -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<SymbolParam>): 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);
}
};

View File

@@ -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<SymbolParam>): 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);
}
}

View File

@@ -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<SymbolParam>): GenericAPIResponse {
return this.requestWrapper.get('v2/public/tickers', params);
}
getSymbols(): GenericAPIResponse {
getSymbols(): Promise<APIResponse<SymbolInfo[]>> {
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<CoinParam>): 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);
}

View File

@@ -11,3 +11,108 @@ export type KlineInterval = '1m'
| '1d'
| '1w'
| '1M';
export type numberInString = string;
export interface APIResponse<T> {
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;
}

View File

@@ -56,18 +56,18 @@ export default class RequestUtil {
this.secret = secret;
}
get(endpoint: string, params?: any): GenericAPIResponse {
get<T>(endpoint: string, params?: any): Promise<T> {
return this._call('GET', endpoint, params);
}
post(endpoint: string, params?: any): GenericAPIResponse {
post<T>(endpoint: string, params?: any): Promise<T> {
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<T>(method: Method, endpoint: string, params?: any): Promise<T> {
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<number> {
const start = Date.now();
const result = await this.get('v2/public/time');
const result = await this.get<any>('v2/public/time');
const end = Date.now();
return Math.ceil((result.time_now * 1000) - end + ((end - start) / 2));

View File

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

View File

@@ -14,7 +14,6 @@
"sourceMap": true,
"esModuleInterop": true,
"lib": ["es2017","dom"],
"baseUrl": ".",
"outDir": "lib"
},
"include": ["src/**/*"],