Merge branch 'wsapi' into wsapi
This commit is contained in:
@@ -1,314 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
APIKeyInfoV3,
|
||||
APIResponseV3WithTime,
|
||||
APIResponseWithTime,
|
||||
AccountCoinBalanceResponseV3,
|
||||
AccountCoinBalancesRequestV3,
|
||||
AccountCoinBalancesResponseV3,
|
||||
AssetInfoRequestV3,
|
||||
AssetInfoResponseV3,
|
||||
CoinInfoQueryResponseV3,
|
||||
CreateSubAPIKeyRequestV3,
|
||||
CreateSubAPIKeyResponseV3,
|
||||
CreateSubMemberRequestV3,
|
||||
CreateSubMemberResponseV3,
|
||||
DepositAddressResponseV3,
|
||||
DepositRecordQueryRequestV3,
|
||||
DepositRecordQueryResponseV3,
|
||||
InternalTransferRequestV3,
|
||||
ModifyAPIKeyRequestV3,
|
||||
QueryDepositAddressRequestV3,
|
||||
QueryInternalTransferSResponseV3,
|
||||
QueryInternalTransfersRequestV3,
|
||||
QuerySubAccountDepositAddressRequestV3,
|
||||
SingleAccountCoinBalanceRequestV3,
|
||||
SubAccountTransferRequestV3,
|
||||
SubAccountTransferResponseV3,
|
||||
SubDepositRecordQueryRequestV3,
|
||||
SubMemberResponseV3,
|
||||
SupportedDepositListRequestV3,
|
||||
SupportedDepositListResponseV3,
|
||||
TransferCoinListRequestV3,
|
||||
UniversalTransferCreateResponse,
|
||||
UniversalTransferListRequestV3,
|
||||
UniversalTransferListResponseV3,
|
||||
UniversalTransferRequestV3,
|
||||
WithdrawCreateRequestV3,
|
||||
WithdrawRecordQueryRequestV3,
|
||||
WithdrawRecordsQueryResponseV3,
|
||||
} from './types';
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
/**
|
||||
* REST API client for Account Asset V3 APIs
|
||||
* @deprecated WARNING
|
||||
* These endpoints are being switched off gradually and are expected to be completely turned off by the end of 2024.
|
||||
* They may stop working at any point before then.
|
||||
* Please update your code as soon as possible to use the V5 APIs instead.
|
||||
*/
|
||||
export class AccountAssetClientV3 extends BaseRestClient {
|
||||
getClientType() {
|
||||
return REST_CLIENT_TYPE_ENUM.v3;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
const res = await this.getServerTime();
|
||||
return Number(res.time);
|
||||
}
|
||||
|
||||
getServerTime(): Promise<
|
||||
APIResponseV3WithTime<{ timeSecond: string; timeNano: string }>
|
||||
> {
|
||||
return this.get('/v3/public/time');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Transfer Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
createInternalTransfer(
|
||||
params: InternalTransferRequestV3,
|
||||
): Promise<APIResponseWithTime<{ transferId: string }>> {
|
||||
return this.postPrivate(
|
||||
'/asset/v3/private/transfer/inter-transfer',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getInternalTransfers(
|
||||
params: QueryInternalTransfersRequestV3,
|
||||
): Promise<APIResponseWithTime<QueryInternalTransferSResponseV3>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v3/private/transfer/inter-transfer/list/query',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
createSubAccountTransfer(params: {
|
||||
transferId: string;
|
||||
coin: string;
|
||||
amount: string;
|
||||
subMemberId: number;
|
||||
type: 'IN' | 'OUT';
|
||||
}): Promise<APIResponseWithTime<{ transferId: string }>> {
|
||||
return this.postPrivate(
|
||||
'/asset/v3/private/transfer/sub-member-transfer',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getSubAccountTransfers(
|
||||
params?: SubAccountTransferRequestV3,
|
||||
): Promise<APIResponseWithTime<SubAccountTransferResponseV3>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v3/private/transfer/sub-member-transfer/list/query',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getSubAccounts(): Promise<
|
||||
APIResponseWithTime<{
|
||||
subMemberIds: string[];
|
||||
transferableSubMemberIds: string[];
|
||||
}>
|
||||
> {
|
||||
return this.getPrivate('/asset/v3/private/transfer/sub-member/list/query');
|
||||
}
|
||||
|
||||
enableUniversalTransfer(params?: {
|
||||
subMemberIds?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate(
|
||||
'/asset/v3/private/transfer/transfer-sub-member-save',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
createUniversalTransfer(
|
||||
params: UniversalTransferRequestV3,
|
||||
): Promise<APIResponseWithTime<UniversalTransferCreateResponse>> {
|
||||
return this.postPrivate(
|
||||
'/asset/v3/private/transfer/universal-transfer',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getUniversalTransfers(
|
||||
params: UniversalTransferListRequestV3,
|
||||
): Promise<APIResponseWithTime<UniversalTransferListResponseV3>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v3/private/transfer/universal-transfer/list/query',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getTransferableCoinList(
|
||||
params: TransferCoinListRequestV3,
|
||||
): Promise<APIResponseWithTime<{ list: string[] }>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v3/private/transfer/transfer-coin/list/query',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getAccountCoinBalance(
|
||||
params: SingleAccountCoinBalanceRequestV3,
|
||||
): Promise<APIResponseWithTime<AccountCoinBalanceResponseV3>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v3/private/transfer/account-coin/balance/query',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getAccountCoinBalances(
|
||||
params: AccountCoinBalancesRequestV3,
|
||||
): Promise<APIResponseWithTime<AccountCoinBalancesResponseV3>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v3/private/transfer/account-coins/balance/query',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getAssetInfo(
|
||||
params?: AssetInfoRequestV3,
|
||||
): Promise<APIResponseWithTime<AssetInfoResponseV3>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v3/private/transfer/asset-info/query',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Wallet & Deposit Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** Get Deposit Spec */
|
||||
getSupportedDepositList(
|
||||
params?: SupportedDepositListRequestV3,
|
||||
): Promise<APIResponseWithTime<SupportedDepositListResponseV3>> {
|
||||
return this.get(
|
||||
'/asset/v3/public/deposit/allowed-deposit-list/query',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getDepositRecords(
|
||||
params?: DepositRecordQueryRequestV3,
|
||||
): Promise<APIResponseWithTime<DepositRecordQueryResponseV3>> {
|
||||
return this.getPrivate('/asset/v3/private/deposit/record/query', params);
|
||||
}
|
||||
|
||||
getSubDepositRecords(
|
||||
params: SubDepositRecordQueryRequestV3,
|
||||
): Promise<APIResponseWithTime<DepositRecordQueryResponseV3>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v3/private/deposit/sub-member-record/query',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getWithdrawRecords(
|
||||
params?: WithdrawRecordQueryRequestV3,
|
||||
): Promise<APIResponseWithTime<WithdrawRecordsQueryResponseV3>> {
|
||||
return this.getPrivate('/asset/v3/private/withdraw/record/query', params);
|
||||
}
|
||||
|
||||
getCoinInformation(
|
||||
coin?: string,
|
||||
): Promise<APIResponseWithTime<CoinInfoQueryResponseV3>> {
|
||||
return this.getPrivate('/asset/v3/private/coin-info/query', { coin });
|
||||
}
|
||||
|
||||
submitWithdrawal(
|
||||
params: WithdrawCreateRequestV3,
|
||||
): Promise<APIResponseWithTime<{ id: string }>> {
|
||||
return this.postPrivate('/asset/v3/private/withdraw/create', params);
|
||||
}
|
||||
|
||||
cancelWithdrawal(
|
||||
withdrawalId: number,
|
||||
): Promise<APIResponseWithTime<{ status: 1 | 0 }>> {
|
||||
return this.postPrivate('/asset/v3/private/withdraw/create', {
|
||||
withdrawalId,
|
||||
});
|
||||
}
|
||||
|
||||
getMasterAccountDepositAddress(
|
||||
params?: QueryDepositAddressRequestV3,
|
||||
): Promise<APIResponseWithTime<DepositAddressResponseV3>> {
|
||||
return this.getPrivate('/asset/v3/private/deposit/address/query', params);
|
||||
}
|
||||
|
||||
getSubAccountDepositAddress(
|
||||
params: QuerySubAccountDepositAddressRequestV3,
|
||||
): Promise<APIResponseWithTime<DepositAddressResponseV3>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v3/private/deposit/sub-member-address/query',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
createSubMember(
|
||||
params: CreateSubMemberRequestV3,
|
||||
): Promise<APIResponseWithTime<CreateSubMemberResponseV3>> {
|
||||
return this.postPrivate('/user/v3/private/create-sub-member', params);
|
||||
}
|
||||
|
||||
createSubAPIKey(
|
||||
params: CreateSubAPIKeyRequestV3,
|
||||
): Promise<APIResponseWithTime<CreateSubAPIKeyResponseV3>> {
|
||||
return this.postPrivate('/user/v3/private/create-sub-api', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Sub UID List
|
||||
*/
|
||||
getSubMembers(): Promise<APIResponseWithTime<SubMemberResponseV3>> {
|
||||
return this.getPrivate('/user/v3/private/query-sub-members');
|
||||
}
|
||||
|
||||
/**
|
||||
* Froze Sub UID
|
||||
*/
|
||||
freezeSubMember(
|
||||
subuid: number,
|
||||
frozenStatus: 0 | 1,
|
||||
): Promise<APIResponseWithTime<{}>> {
|
||||
return this.postPrivate('/user/v3/private/frozen-sub-member', {
|
||||
subuid,
|
||||
frozen: frozenStatus,
|
||||
});
|
||||
}
|
||||
|
||||
getAPIKeyInformation(): Promise<APIResponseWithTime<APIKeyInfoV3>> {
|
||||
return this.getPrivate('/user/v3/private/query-api');
|
||||
}
|
||||
|
||||
modifyMasterAPIKey(
|
||||
params: ModifyAPIKeyRequestV3,
|
||||
): Promise<APIResponseWithTime<APIKeyInfoV3>> {
|
||||
return this.postPrivate('/user/v3/private/update-api', params);
|
||||
}
|
||||
|
||||
modifySubAPIKey(
|
||||
params: ModifyAPIKeyRequestV3,
|
||||
): Promise<APIResponseWithTime<APIKeyInfoV3>> {
|
||||
return this.postPrivate('/user/v3/private/update-sub-api', params);
|
||||
}
|
||||
|
||||
/** WARNING: BE CAREFUL! The API key used to call this interface will be invalid immediately. */
|
||||
deleteMasterAPIKey(): Promise<APIResponseWithTime<{}>> {
|
||||
return this.postPrivate('/user/v3/private/delete-api');
|
||||
}
|
||||
|
||||
/** WARNING: BE CAREFUL! The API key used to call this interface will be invalid immediately. */
|
||||
deleteSubAPIKey(): Promise<APIResponseWithTime<{}>> {
|
||||
return this.postPrivate('/user/v3/private/delete-sub-api');
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
APIResponseWithTime,
|
||||
AccountAssetInformationRequest,
|
||||
DepositRecordsRequest,
|
||||
EnableUniversalTransferRequest,
|
||||
InternalTransferRequest,
|
||||
SubAccountTransferRequest,
|
||||
SupportedDepositListRequest,
|
||||
TransferQueryRequest,
|
||||
UniversalTransferRequest,
|
||||
WithdrawalRecordsRequest,
|
||||
WithdrawalRequest,
|
||||
} from './types';
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
/**
|
||||
* REST API client for Account Asset APIs
|
||||
*
|
||||
* @deprecated WARNING: V1/V2 private endpoints (Rest API & Websocket Stream) for mainnet
|
||||
* will be switched off gradually from 30 Oct 2023 UTC, so they are not promised a stability.
|
||||
* Please note that you are at your own risk of using old endpoints going forward, and please move to V5 ASAP.
|
||||
*/
|
||||
export class AccountAssetClient extends BaseRestClient {
|
||||
getClientType() {
|
||||
return REST_CLIENT_TYPE_ENUM.accountAsset;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
const res = await this.getServerTime();
|
||||
return Number(res.time_now);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Transfer Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
createInternalTransfer(
|
||||
params: InternalTransferRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('/asset/v1/private/transfer', params);
|
||||
}
|
||||
|
||||
createSubAccountTransfer(
|
||||
params: SubAccountTransferRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('/asset/v1/private/sub-member/transfer', params);
|
||||
}
|
||||
|
||||
getInternalTransfers(
|
||||
params?: TransferQueryRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('/asset/v1/private/transfer/list', params);
|
||||
}
|
||||
|
||||
getSubAccountTransfers(
|
||||
params?: TransferQueryRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v1/private/sub-member/transfer/list',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getSubAccounts(): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('/asset/v1/private/sub-member/member-ids');
|
||||
}
|
||||
|
||||
enableUniversalTransfer(
|
||||
params?: EnableUniversalTransferRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('/asset/v1/private/transferable-subs/save', params);
|
||||
}
|
||||
|
||||
createUniversalTransfer(
|
||||
params: UniversalTransferRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('/asset/v1/private/universal/transfer', params);
|
||||
}
|
||||
|
||||
getUniversalTransfers(
|
||||
params?: TransferQueryRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('/asset/v1/private/universal/transfer/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Wallet & Deposit Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getSupportedDepositList(
|
||||
params?: SupportedDepositListRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.get('/asset/v1/public/deposit/allowed-deposit-list', params);
|
||||
}
|
||||
|
||||
getDepositRecords(
|
||||
params?: DepositRecordsRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('/asset/v1/private/deposit/record/query', params);
|
||||
}
|
||||
|
||||
getWithdrawRecords(
|
||||
params?: WithdrawalRecordsRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('/asset/v1/private/withdraw/record/query', params);
|
||||
}
|
||||
|
||||
getCoinInformation(coin?: string): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('/asset/v1/private/coin-info/query', { coin });
|
||||
}
|
||||
|
||||
getAssetInformation(
|
||||
params?: AccountAssetInformationRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('/asset/v1/private/asset-info/query', params);
|
||||
}
|
||||
|
||||
submitWithdrawal(
|
||||
params: WithdrawalRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('/asset/v1/private/withdraw', params);
|
||||
}
|
||||
|
||||
cancelWithdrawal(withdrawalId: number): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('/asset/v1/private/withdraw/cancel', {
|
||||
id: withdrawalId,
|
||||
});
|
||||
}
|
||||
|
||||
getDepositAddress(coin: string): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('/asset/v1/private/deposit/address', { coin });
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* API Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getServerTime(): Promise<APIResponseWithTime> {
|
||||
return this.get('/v2/public/time');
|
||||
}
|
||||
|
||||
getApiAnnouncements(): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('/v2/public/announcement');
|
||||
}
|
||||
}
|
||||
@@ -1,364 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
APIResponseV3,
|
||||
APIResponseWithTime,
|
||||
ContractActiveOrdersRequest,
|
||||
ContractCancelOrderRequest,
|
||||
ContractClosedPNLRequest,
|
||||
ContractHistoricOrder,
|
||||
ContractHistoricOrdersRequest,
|
||||
ContractListResult,
|
||||
ContractModifyOrderRequest,
|
||||
ContractOrderRequest,
|
||||
ContractPositionsRequest,
|
||||
ContractSetAutoAddMarginRequest,
|
||||
ContractSetMarginSwitchRequest,
|
||||
ContractSetPositionModeRequest,
|
||||
ContractSetTPSLRequest,
|
||||
ContractSymbolTicker,
|
||||
ContractUserExecutionHistoryRequest,
|
||||
ContractWalletFundRecordRequest,
|
||||
PaginatedResult,
|
||||
UMCandlesRequest,
|
||||
UMCategory,
|
||||
UMFundingRateHistoryRequest,
|
||||
UMInstrumentInfoRequest,
|
||||
UMOpenInterestRequest,
|
||||
UMOptionDeliveryPriceRequest,
|
||||
UMPublicTradesRequest,
|
||||
} from './types';
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
/**
|
||||
* REST API client for Derivatives V3 Contract APIs
|
||||
* @deprecated WARNING
|
||||
* These endpoints are being switched off gradually and are expected to be completely turned off by the end of 2024.
|
||||
* They may stop working at any point before then.
|
||||
* Please update your code as soon as possible to use the V5 APIs instead.
|
||||
*/
|
||||
export class ContractClient extends BaseRestClient {
|
||||
getClientType() {
|
||||
// Follows the same authentication mechanism as other v3 APIs (e.g. USDC)
|
||||
return REST_CLIENT_TYPE_ENUM.v3;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
const res = await this.getServerTime();
|
||||
return Number(res.time_now);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data Endpoints : these seem exactly the same as the unified margin market data endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** Query order book info. Each side has a depth of 25 orders. */
|
||||
getOrderBook(
|
||||
symbol: string,
|
||||
category?: string,
|
||||
limit?: number,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/order-book/L2', {
|
||||
category,
|
||||
symbol,
|
||||
limit,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get candles/klines */
|
||||
getCandles(params: UMCandlesRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/kline', params);
|
||||
}
|
||||
|
||||
/** Get a symbol price/statistics ticker */
|
||||
getSymbolTicker(
|
||||
category: UMCategory | '',
|
||||
symbol?: string,
|
||||
): Promise<APIResponseV3<ContractListResult<ContractSymbolTicker>>> {
|
||||
return this.get('/derivatives/v3/public/tickers', { category, symbol });
|
||||
}
|
||||
|
||||
/** Get trading rules per symbol/contract, incl price/amount/value/leverage filters */
|
||||
getInstrumentInfo(
|
||||
params: UMInstrumentInfoRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/instruments-info', params);
|
||||
}
|
||||
|
||||
/** Query mark price kline (like getCandles() but for mark price). */
|
||||
getMarkPriceCandles(params: UMCandlesRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/mark-price-kline', params);
|
||||
}
|
||||
|
||||
/** Query Index Price Kline */
|
||||
getIndexPriceCandles(params: UMCandlesRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/index-price-kline', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* The funding rate is generated every 8 hours at 00:00 UTC, 08:00 UTC and 16:00 UTC.
|
||||
* For example, if a request is sent at 12:00 UTC, the funding rate generated earlier that day at 08:00 UTC will be sent.
|
||||
*/
|
||||
getFundingRateHistory(
|
||||
params: UMFundingRateHistoryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get(
|
||||
'/derivatives/v3/public/funding/history-funding-rate',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Get Risk Limit */
|
||||
getRiskLimit(
|
||||
category: UMCategory,
|
||||
symbol: string,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/risk-limit/list', {
|
||||
category,
|
||||
symbol,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get option delivery price */
|
||||
getOptionDeliveryPrice(
|
||||
params: UMOptionDeliveryPriceRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/delivery-price', params);
|
||||
}
|
||||
|
||||
/** Get public trading history */
|
||||
getTrades(params: UMPublicTradesRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/recent-trade', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total amount of unsettled contracts.
|
||||
* In other words, the total number of contracts held in open positions.
|
||||
*/
|
||||
getOpenInterest(params: UMOpenInterestRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/open-interest', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Contract Account Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** -> Order API */
|
||||
|
||||
/** Place an order */
|
||||
submitOrder(params: ContractOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/contract/v3/private/order/create', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query order history.
|
||||
*
|
||||
* As order creation/cancellation is asynchronous, the data returned from the interface may be delayed.
|
||||
* To access order information in real-time, call getActiveOrders().
|
||||
*/
|
||||
getHistoricOrders(
|
||||
params: ContractHistoricOrdersRequest,
|
||||
): Promise<APIResponseV3<PaginatedResult<ContractHistoricOrder>>> {
|
||||
return this.getPrivate('/contract/v3/private/order/list', params);
|
||||
}
|
||||
|
||||
/** Cancel order */
|
||||
cancelOrder(params: ContractCancelOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/contract/v3/private/order/cancel', params);
|
||||
}
|
||||
|
||||
/** Cancel all orders */
|
||||
cancelAllOrders(symbol: string): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/contract/v3/private/order/cancel-all', {
|
||||
symbol,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace order
|
||||
*
|
||||
* Active order parameters (such as quantity, price) and stop order parameters
|
||||
* cannot be modified in one request at the same time.
|
||||
*
|
||||
* Please request modification separately.
|
||||
*/
|
||||
modifyOrder(params: ContractModifyOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/contract/v3/private/order/replace', params);
|
||||
}
|
||||
|
||||
/** Query Open Order(s) (real-time) */
|
||||
getActiveOrders(
|
||||
params: ContractActiveOrdersRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate(
|
||||
'/contract/v3/private/order/unfilled-orders',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** -> Positions API */
|
||||
|
||||
/**
|
||||
* Query my positions real-time. Accessing personal list of positions.
|
||||
* Either symbol or settleCoin is required.
|
||||
* Users can access their position holding information through this interface, such as the number of position holdings and wallet balance.
|
||||
*/
|
||||
getPositions(params?: ContractPositionsRequest): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/contract/v3/private/position/list', params);
|
||||
}
|
||||
|
||||
/** Set auto add margin, or Auto-Margin Replenishment. */
|
||||
setAutoAddMargin(
|
||||
params: ContractSetAutoAddMarginRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/contract/v3/private/position/set-auto-add-margin',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Switch cross margin mode/isolated margin mode */
|
||||
setMarginSwitch(
|
||||
params: ContractSetMarginSwitchRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/contract/v3/private/position/switch-isolated',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Supports switching between One-Way Mode and Hedge Mode at the coin level. */
|
||||
setPositionMode(
|
||||
params: ContractSetPositionModeRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/contract/v3/private/position/switch-mode',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch mode between Full or Partial
|
||||
*/
|
||||
setTPSLMode(
|
||||
symbol: string,
|
||||
tpSlMode: 'Full' | 'Partial',
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/contract/v3/private/position/switch-tpsl-mode', {
|
||||
symbol,
|
||||
tpSlMode,
|
||||
});
|
||||
}
|
||||
|
||||
/** Leverage setting. */
|
||||
setLeverage(
|
||||
symbol: string,
|
||||
buyLeverage: string,
|
||||
sellLeverage: string,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/contract/v3/private/position/set-leverage', {
|
||||
symbol,
|
||||
buyLeverage,
|
||||
sellLeverage,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set take profit, stop loss, and trailing stop for your open position.
|
||||
* If using partial mode, TP/SL/TS orders will not close your entire position.
|
||||
*/
|
||||
setTPSL(params: ContractSetTPSLRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/contract/v3/private/position/trading-stop',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Set risk limit */
|
||||
setRiskLimit(
|
||||
symbol: string,
|
||||
riskId: number,
|
||||
/** 0-one-way, 1-buy side, 2-sell side */
|
||||
positionIdx: 0 | 1 | 2,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/contract/v3/private/position/set-risk-limit', {
|
||||
symbol,
|
||||
riskId,
|
||||
positionIdx,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's trading records.
|
||||
* The results are ordered in descending order (the first item is the latest). Returns records up to 2 years old.
|
||||
*/
|
||||
getUserExecutionHistory(
|
||||
params: ContractUserExecutionHistoryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/contract/v3/private/execution/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's closed profit and loss records.
|
||||
* The results are ordered in descending order (the first item is the latest).
|
||||
*/
|
||||
getClosedProfitAndLoss(
|
||||
params: ContractClosedPNLRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/contract/v3/private/position/closed-pnl', params);
|
||||
}
|
||||
|
||||
/** Get the information of open interest limit. */
|
||||
getOpenInterestLimitInfo(symbol: string): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/contract/v3/private/position/limit-info', {
|
||||
symbol,
|
||||
});
|
||||
}
|
||||
|
||||
/** -> Account API */
|
||||
|
||||
/** Query wallet balance */
|
||||
getBalances(coin?: string): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/contract/v3/private/account/wallet/balance', {
|
||||
coin,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get user trading fee rate */
|
||||
getTradingFeeRate(symbol?: string): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/contract/v3/private/account/fee-rate', {
|
||||
symbol,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get wallet fund records.
|
||||
* This endpoint also shows exchanges from the Asset Exchange,
|
||||
* where the types for the exchange are ExchangeOrderWithdraw and ExchangeOrderDeposit.
|
||||
*
|
||||
* This endpoint returns incomplete information for transfers involving the derivatives wallet.
|
||||
* Use the account asset API for creating and querying internal transfers.
|
||||
*/
|
||||
getWalletFundRecords(
|
||||
params?: ContractWalletFundRecordRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate(
|
||||
'/contract/v3/private/account/wallet/fund-records',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* API Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getServerTime(): Promise<APIResponseWithTime> {
|
||||
return this.get('/v2/public/time');
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
APIResponseV3,
|
||||
APIResponseWithTime,
|
||||
CopyTradingCancelOrderRequest,
|
||||
CopyTradingCloseOrderRequest,
|
||||
CopyTradingOrderListRequest,
|
||||
CopyTradingOrderRequest,
|
||||
CopyTradingTradingStopRequest,
|
||||
CopyTradingTransferRequest,
|
||||
} from './types';
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
/**
|
||||
* REST API client for USDC Perpetual APIs
|
||||
* @deprecated WARNING
|
||||
* These endpoints are being switched off gradually and are expected to be completely turned off by the end of 2024.
|
||||
* They may stop working at any point before then.
|
||||
* Please update your code as soon as possible to use the V5 APIs instead.
|
||||
*/
|
||||
export class CopyTradingClient extends BaseRestClient {
|
||||
getClientType() {
|
||||
// Follows the same authentication mechanism as USDC APIs
|
||||
return REST_CLIENT_TYPE_ENUM.v3;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
const res = await this.getServerTime();
|
||||
return Number(res.time_now);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getSymbols(): Promise<APIResponseV3<any>> {
|
||||
return this.get('/contract/v3/public/copytrading/symbol/list');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Account Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** -> Order API */
|
||||
|
||||
/** Create order */
|
||||
submitOrder(params: CopyTradingOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/contract/v3/private/copytrading/order/create',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Set Trading Stop */
|
||||
setTradingStop(
|
||||
params: CopyTradingTradingStopRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/contract/v3/private/copytrading/order/trading-stop',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Query Order List */
|
||||
getActiveOrders(
|
||||
params?: CopyTradingOrderListRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate(
|
||||
'/contract/v3/private/copytrading/order/list',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Cancel order */
|
||||
cancelOrder(
|
||||
params: CopyTradingCancelOrderRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/contract/v3/private/copytrading/order/cancel',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Close Order.
|
||||
* This endpoint's rate_limit will decrease by 10 per request;
|
||||
* ie, one request to this endpoint consumes 10 from the limit allowed per minute.
|
||||
*/
|
||||
closeOrder(
|
||||
params: CopyTradingCloseOrderRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/contract/v3/private/copytrading/order/close',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** -> Positions API */
|
||||
|
||||
/** Position List */
|
||||
getPositions(symbol?: string): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/contract/v3/private/copytrading/position/list', {
|
||||
symbol,
|
||||
});
|
||||
}
|
||||
|
||||
/** Close Position */
|
||||
closePosition(
|
||||
symbol: string,
|
||||
positionIdx: string,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/contract/v3/private/copytrading/position/close', {
|
||||
symbol,
|
||||
positionIdx,
|
||||
});
|
||||
}
|
||||
|
||||
/** Only integers can be set to set the leverage */
|
||||
setLeverage(
|
||||
symbol: string,
|
||||
buyLeverage: string,
|
||||
sellLeverage: string,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/contract/v3/private/copytrading/position/set-leverage',
|
||||
{ symbol, buyLeverage, sellLeverage },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Wallet Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** Get Wallet Balance */
|
||||
getBalances(): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/contract/v3/private/copytrading/wallet/balance');
|
||||
}
|
||||
|
||||
/** Transfer */
|
||||
transfer(params: CopyTradingTransferRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/contract/v3/private/copytrading/wallet/transfer',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* API Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getServerTime(): Promise<APIResponseWithTime> {
|
||||
return this.get('/v2/public/time');
|
||||
}
|
||||
}
|
||||
11
src/index.ts
11
src/index.ts
@@ -1,16 +1,5 @@
|
||||
export * from './account-asset-client';
|
||||
export * from './account-asset-client-v3';
|
||||
export * from './copy-trading-client';
|
||||
export * from './inverse-client';
|
||||
export * from './inverse-futures-client';
|
||||
export * from './linear-client';
|
||||
export * from './rest-client-v5';
|
||||
export * from './spot-client';
|
||||
export * from './spot-client-v3';
|
||||
export * from './usdc-option-client';
|
||||
export * from './usdc-perpetual-client';
|
||||
export * from './unified-margin-client';
|
||||
export * from './contract-client';
|
||||
export * from './websocket-client';
|
||||
export * from './util/logger';
|
||||
export * from './util';
|
||||
|
||||
@@ -1,341 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util';
|
||||
import {
|
||||
APIResponseWithTime,
|
||||
AssetExchangeRecordsReq,
|
||||
CoinParam,
|
||||
InverseActiveConditionalOrderRequest,
|
||||
InverseActiveOrdersRequest,
|
||||
InverseCancelConditionalOrderRequest,
|
||||
InverseCancelOrderRequest,
|
||||
InverseChangePositionMarginRequest,
|
||||
InverseConditionalOrderRequest,
|
||||
InverseGetClosedPnlRequest,
|
||||
InverseGetOrderRequest,
|
||||
InverseGetTradeRecordsRequest,
|
||||
InverseOrderRequest,
|
||||
InverseReplaceConditionalOrderRequest,
|
||||
InverseReplaceOrderRequest,
|
||||
InverseSetLeverageRequest,
|
||||
InverseSetMarginTypeRequest,
|
||||
InverseSetSlTpPositionModeRequest,
|
||||
InverseSetTradingStopRequest,
|
||||
SymbolInfo,
|
||||
SymbolIntervalFromLimitParam,
|
||||
SymbolLimitParam,
|
||||
SymbolParam,
|
||||
SymbolPeriodLimitParam,
|
||||
WalletFundRecordsReq,
|
||||
WithdrawRecordsReq,
|
||||
} from './types';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
/**
|
||||
* REST API client for Inverse Perpetual Futures APIs (v2)
|
||||
*
|
||||
* @deprecated WARNING: V1/V2 private endpoints (Rest API & Websocket Stream) for mainnet
|
||||
* will be switched off gradually from 30 Oct 2023 UTC, so they are not promised a stability.
|
||||
* Please note that you are at your own risk of using old endpoints going forward, and please move to V5 ASAP.
|
||||
*/
|
||||
export class InverseClient extends BaseRestClient {
|
||||
getClientType() {
|
||||
return REST_CLIENT_TYPE_ENUM.inverse;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
const res = await this.getServerTime();
|
||||
return Number(res.time_now);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getOrderBook(params: SymbolParam): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/orderBook/L2', params);
|
||||
}
|
||||
|
||||
getKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/kline/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest information for symbol
|
||||
*/
|
||||
getTickers(
|
||||
params?: Partial<SymbolParam>,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/tickers', params);
|
||||
}
|
||||
|
||||
getTrades(params: SymbolLimitParam): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/trading-records', params);
|
||||
}
|
||||
|
||||
getSymbols(): Promise<APIResponseWithTime<SymbolInfo[]>> {
|
||||
return this.get('v2/public/symbols');
|
||||
}
|
||||
|
||||
getMarkPriceKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/mark-price-kline', params);
|
||||
}
|
||||
|
||||
getIndexPriceKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/index-price-kline', params);
|
||||
}
|
||||
|
||||
getPremiumIndexKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/premium-index-kline', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data : Advanced
|
||||
*
|
||||
*/
|
||||
|
||||
getOpenInterest(
|
||||
params: SymbolPeriodLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/open-interest', params);
|
||||
}
|
||||
|
||||
getLatestBigDeal(
|
||||
params: SymbolLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/big-deal', params);
|
||||
}
|
||||
|
||||
getLongShortRatio(
|
||||
params: SymbolPeriodLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/account-ratio', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Account Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getApiKeyInfo(): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/account/api-key');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Wallet Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getWalletBalance(
|
||||
params?: Partial<CoinParam>,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/wallet/balance', params);
|
||||
}
|
||||
|
||||
getWalletFundRecords(
|
||||
params?: WalletFundRecordsReq,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/wallet/fund/records', params);
|
||||
}
|
||||
|
||||
getWithdrawRecords(
|
||||
params?: WithdrawRecordsReq,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/wallet/withdraw/list', params);
|
||||
}
|
||||
|
||||
getAssetExchangeRecords(
|
||||
params?: AssetExchangeRecordsReq,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/exchange-order/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* API Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getServerTime(): Promise<APIResponseWithTime<{}>> {
|
||||
return this.get('v2/public/time');
|
||||
}
|
||||
|
||||
getApiAnnouncements(): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/announcement');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Account Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Active orders
|
||||
*/
|
||||
|
||||
placeActiveOrder(
|
||||
orderRequest: InverseOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/order/create', orderRequest);
|
||||
}
|
||||
|
||||
getActiveOrderList(
|
||||
params: InverseActiveOrdersRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/order/list', params);
|
||||
}
|
||||
|
||||
cancelActiveOrder(
|
||||
params: InverseCancelOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/order/cancel', params);
|
||||
}
|
||||
|
||||
cancelAllActiveOrders(
|
||||
params: SymbolParam,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/order/cancelAll', params);
|
||||
}
|
||||
|
||||
replaceActiveOrder(
|
||||
params: InverseReplaceOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/order/replace', params);
|
||||
}
|
||||
|
||||
queryActiveOrder(
|
||||
params: InverseGetOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/order', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditional orders
|
||||
*/
|
||||
|
||||
placeConditionalOrder(
|
||||
params: InverseConditionalOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/stop-order/create', params);
|
||||
}
|
||||
|
||||
/** get conditional order list. This may see delays, use queryConditionalOrder() for real-time queries */
|
||||
getConditionalOrder(
|
||||
params: InverseActiveConditionalOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/stop-order/list', params);
|
||||
}
|
||||
|
||||
cancelConditionalOrder(
|
||||
params: InverseCancelConditionalOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/stop-order/cancel', params);
|
||||
}
|
||||
|
||||
cancelAllConditionalOrders(
|
||||
params: SymbolParam,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/stop-order/cancelAll', params);
|
||||
}
|
||||
|
||||
replaceConditionalOrder(
|
||||
params: InverseReplaceConditionalOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/stop-order/replace', params);
|
||||
}
|
||||
|
||||
queryConditionalOrder(
|
||||
params: InverseGetOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/stop-order', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Position
|
||||
*/
|
||||
|
||||
getPosition(
|
||||
params?: Partial<SymbolParam>,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/position/list', params);
|
||||
}
|
||||
|
||||
changePositionMargin(
|
||||
params: InverseChangePositionMarginRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('position/change-position-margin', params);
|
||||
}
|
||||
|
||||
setTradingStop(
|
||||
params: InverseSetTradingStopRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/position/trading-stop', params);
|
||||
}
|
||||
|
||||
setUserLeverage(
|
||||
params: InverseSetLeverageRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/position/leverage/save', params);
|
||||
}
|
||||
|
||||
getTradeRecords(
|
||||
params: InverseGetTradeRecordsRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/execution/list', params);
|
||||
}
|
||||
|
||||
getClosedPnl(
|
||||
params: InverseGetClosedPnlRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/trade/closed-pnl/list', params);
|
||||
}
|
||||
|
||||
setSlTpPositionMode(
|
||||
params: InverseSetSlTpPositionModeRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/tpsl/switch-mode', params);
|
||||
}
|
||||
|
||||
setMarginType(
|
||||
params: InverseSetMarginTypeRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('v2/private/position/switch-isolated', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Funding
|
||||
*/
|
||||
|
||||
getLastFundingRate(params: SymbolParam): Promise<APIResponseWithTime<any>> {
|
||||
return this.get('v2/public/funding/prev-funding-rate', params);
|
||||
}
|
||||
|
||||
getMyLastFundingFee(params: SymbolParam): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/funding/prev-funding', params);
|
||||
}
|
||||
|
||||
getPredictedFunding(params: SymbolParam): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/funding/predicted-funding', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* LCP Info
|
||||
*/
|
||||
|
||||
getLcpInfo(params: SymbolParam): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/account/lcp', params);
|
||||
}
|
||||
}
|
||||
@@ -1,407 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util/requestUtils';
|
||||
import {
|
||||
APIResponseWithTime,
|
||||
AssetExchangeRecordsReq,
|
||||
CoinParam,
|
||||
SymbolInfo,
|
||||
SymbolIntervalFromLimitParam,
|
||||
SymbolLimitParam,
|
||||
SymbolParam,
|
||||
SymbolPeriodLimitParam,
|
||||
WalletFundRecordsReq,
|
||||
WithdrawRecordsReq,
|
||||
} from './types/shared';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
/**
|
||||
* REST API client for Inverse Futures APIs (e.g. quarterly futures) (v2)
|
||||
*
|
||||
* @deprecated WARNING: V1/V2 private endpoints (Rest API & Websocket Stream) for mainnet
|
||||
* will be switched off gradually from 30 Oct 2023 UTC, so they are not promised a stability.
|
||||
* Please note that you are at your own risk of using old endpoints going forward, and please move to V5 ASAP.
|
||||
*/
|
||||
export class InverseFuturesClient extends BaseRestClient {
|
||||
getClientType() {
|
||||
return REST_CLIENT_TYPE_ENUM.inverseFutures;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
const res = await this.getServerTime();
|
||||
return Number(res.time_now);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getOrderBook(params: SymbolParam): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/orderBook/L2', params);
|
||||
}
|
||||
|
||||
getKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/kline/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest information for symbol
|
||||
*/
|
||||
getTickers(
|
||||
params?: Partial<SymbolParam>,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/tickers', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public trading records
|
||||
*/
|
||||
getTrades(params: SymbolLimitParam): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/trading-records', params);
|
||||
}
|
||||
|
||||
getSymbols(): Promise<APIResponseWithTime<SymbolInfo[]>> {
|
||||
return this.get('v2/public/symbols');
|
||||
}
|
||||
|
||||
getMarkPriceKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/mark-price-kline', params);
|
||||
}
|
||||
|
||||
getIndexPriceKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/index-price-kline', params);
|
||||
}
|
||||
|
||||
getPremiumIndexKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/premium-index-kline', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data : Advanced
|
||||
*
|
||||
*/
|
||||
|
||||
getOpenInterest(
|
||||
params: SymbolPeriodLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/open-interest', params);
|
||||
}
|
||||
|
||||
getLatestBigDeal(
|
||||
params: SymbolLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/big-deal', params);
|
||||
}
|
||||
|
||||
getLongShortRatio(
|
||||
params: SymbolPeriodLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/account-ratio', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Account Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getApiKeyInfo(): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/account/api-key');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Wallet Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getWalletBalance(
|
||||
params?: Partial<CoinParam>,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/wallet/balance', params);
|
||||
}
|
||||
|
||||
getWalletFundRecords(
|
||||
params?: WalletFundRecordsReq,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/wallet/fund/records', params);
|
||||
}
|
||||
|
||||
getWithdrawRecords(
|
||||
params?: WithdrawRecordsReq,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/wallet/withdraw/list', params);
|
||||
}
|
||||
|
||||
getAssetExchangeRecords(
|
||||
params?: AssetExchangeRecordsReq,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/exchange-order/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* API Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getServerTime(): Promise<APIResponseWithTime<{}>> {
|
||||
return this.get('v2/public/time');
|
||||
}
|
||||
|
||||
getApiAnnouncements(): Promise<APIResponseWithTime<any>> {
|
||||
return this.get('v2/public/announcement');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Account Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Active orders
|
||||
*/
|
||||
|
||||
placeActiveOrder(orderRequest: {
|
||||
side: string;
|
||||
symbol: string;
|
||||
order_type: string;
|
||||
qty: number;
|
||||
price?: number;
|
||||
time_in_force: string;
|
||||
take_profit?: number;
|
||||
stop_loss?: number;
|
||||
reduce_only?: boolean;
|
||||
close_on_trigger?: boolean;
|
||||
order_link_id?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/order/create', orderRequest);
|
||||
}
|
||||
|
||||
getActiveOrderList(params: {
|
||||
symbol: string;
|
||||
order_status?: string;
|
||||
direction?: string;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('futures/private/order/list', params);
|
||||
}
|
||||
|
||||
cancelActiveOrder(params: {
|
||||
symbol: string;
|
||||
order_id?: string;
|
||||
order_link_id?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/order/cancel', params);
|
||||
}
|
||||
|
||||
cancelAllActiveOrders(
|
||||
params: SymbolParam,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/order/cancelAll', params);
|
||||
}
|
||||
|
||||
replaceActiveOrder(params: {
|
||||
order_id?: string;
|
||||
order_link_id?: string;
|
||||
symbol: string;
|
||||
p_r_qty?: string;
|
||||
p_r_price?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/order/replace', params);
|
||||
}
|
||||
|
||||
queryActiveOrder(params: {
|
||||
order_id?: string;
|
||||
order_link_id?: string;
|
||||
symbol: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('futures/private/order', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditional orders
|
||||
*/
|
||||
|
||||
placeConditionalOrder(params: {
|
||||
side: string;
|
||||
symbol: string;
|
||||
order_type: string;
|
||||
qty: string;
|
||||
price?: string;
|
||||
base_price: string;
|
||||
stop_px: string;
|
||||
time_in_force: string;
|
||||
trigger_by?: string;
|
||||
close_on_trigger?: boolean;
|
||||
order_link_id?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/stop-order/create', params);
|
||||
}
|
||||
|
||||
getConditionalOrder(params: {
|
||||
symbol: string;
|
||||
stop_order_status?: string;
|
||||
direction?: string;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('futures/private/stop-order/list', params);
|
||||
}
|
||||
|
||||
cancelConditionalOrder(params: {
|
||||
symbol: string;
|
||||
stop_order_id?: string;
|
||||
order_link_id?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/stop-order/cancel', params);
|
||||
}
|
||||
|
||||
cancelAllConditionalOrders(
|
||||
params: SymbolParam,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/stop-order/cancelAll', params);
|
||||
}
|
||||
|
||||
replaceConditionalOrder(params: {
|
||||
stop_order_id?: string;
|
||||
order_link_id?: string;
|
||||
symbol: string;
|
||||
p_r_qty?: number;
|
||||
p_r_price?: string;
|
||||
p_r_trigger_price?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/stop-order/replace', params);
|
||||
}
|
||||
|
||||
queryConditionalOrder(params: {
|
||||
symbol: string;
|
||||
stop_order_id?: string;
|
||||
order_link_id?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('futures/private/stop-order', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Position
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get position list
|
||||
*/
|
||||
getPosition(
|
||||
params?: Partial<SymbolParam>,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('futures/private/position/list', params);
|
||||
}
|
||||
|
||||
changePositionMargin(params: {
|
||||
symbol: string;
|
||||
margin: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate(
|
||||
'futures/private/position/change-position-margin',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
setTradingStop(params: {
|
||||
symbol: string;
|
||||
take_profit?: number;
|
||||
stop_loss?: number;
|
||||
trailing_stop?: number;
|
||||
tp_trigger_by?: string;
|
||||
sl_trigger_by?: string;
|
||||
new_trailing_active?: number;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/position/trading-stop', params);
|
||||
}
|
||||
|
||||
setUserLeverage(params: {
|
||||
symbol: string;
|
||||
buy_leverage: number;
|
||||
sell_leverage: number;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/position/leverage/save', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Position mode switch
|
||||
*/
|
||||
setPositionMode(params: {
|
||||
symbol: string;
|
||||
mode: number;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/position/switch-mode', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross/Isolated margin switch. Must set leverage value when switching.
|
||||
*/
|
||||
setMarginType(params: {
|
||||
symbol: string;
|
||||
is_isolated: boolean;
|
||||
buy_leverage: number;
|
||||
sell_leverage: number;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('futures/private/position/switch-isolated', params);
|
||||
}
|
||||
|
||||
getTradeRecords(params: {
|
||||
order_id?: string;
|
||||
symbol: string;
|
||||
start_time?: number;
|
||||
page?: number;
|
||||
limit?: number;
|
||||
order?: string;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('futures/private/execution/list', params);
|
||||
}
|
||||
|
||||
getClosedPnl(params: {
|
||||
symbol: string;
|
||||
start_time?: number;
|
||||
end_time?: number;
|
||||
exec_type?: string;
|
||||
page?: number;
|
||||
limit?: number;
|
||||
}): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('futures/private/trade/closed-pnl/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Funding
|
||||
*/
|
||||
|
||||
getLastFundingRate(params: SymbolParam): Promise<APIResponseWithTime<any>> {
|
||||
return this.get('v2/public/funding/prev-funding-rate', params);
|
||||
}
|
||||
|
||||
getMyLastFundingFee(params: SymbolParam): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/funding/prev-funding', params);
|
||||
}
|
||||
|
||||
getPredictedFunding(params: SymbolParam): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/funding/predicted-funding', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* LCP Info
|
||||
*/
|
||||
|
||||
getLcpInfo(params: SymbolParam): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/account/lcp', params);
|
||||
}
|
||||
}
|
||||
@@ -1,391 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util/requestUtils';
|
||||
import {
|
||||
APIResponse,
|
||||
APIResponseWithTime,
|
||||
AssetExchangeRecordsReq,
|
||||
CoinParam,
|
||||
LinearCancelConditionalOrderRequest,
|
||||
LinearCancelOrderRequest,
|
||||
LinearConditionalOrderRequest,
|
||||
LinearGetClosedPnlRequest,
|
||||
LinearGetConditionalOrderRequest,
|
||||
LinearGetHistoryTradeRecordsRequest,
|
||||
LinearGetOrderRequest,
|
||||
LinearGetOrdersRequest,
|
||||
LinearGetTradeRecordsRequest,
|
||||
LinearOrder,
|
||||
LinearQueryConditionalOrderRequest,
|
||||
LinearReplaceConditionalOrderRequest,
|
||||
LinearReplaceOrderRequest,
|
||||
LinearSetAddReduceMarginRequest,
|
||||
LinearSetAutoAddMarginRequest,
|
||||
LinearSetMarginSwitchRequest,
|
||||
LinearSetPositionModeRequest,
|
||||
LinearSetPositionTpSlModeRequest,
|
||||
LinearSetRiskLimitRequest,
|
||||
LinearSetTradingStopRequest,
|
||||
LinearSetUserLeverageRequest,
|
||||
NewLinearOrder,
|
||||
PerpPosition,
|
||||
PerpPositionRoot,
|
||||
SymbolInfo,
|
||||
SymbolIntervalFromLimitParam,
|
||||
SymbolLimitParam,
|
||||
SymbolParam,
|
||||
SymbolPeriodLimitParam,
|
||||
WalletBalances,
|
||||
WalletFundRecordsReq,
|
||||
WithdrawRecordsReq,
|
||||
} from './types';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
/**
|
||||
* REST API client for linear/USD perpetual futures APIs (v2)
|
||||
*
|
||||
* @deprecated WARNING: V1/V2 private endpoints (Rest API & Websocket Stream) for mainnet
|
||||
* will be switched off gradually from 30 Oct 2023 UTC, so they are not promised a stability.
|
||||
* Please note that you are at your own risk of using old endpoints going forward, and please move to V5 ASAP.
|
||||
*/
|
||||
export class LinearClient extends BaseRestClient {
|
||||
getClientType() {
|
||||
return REST_CLIENT_TYPE_ENUM.linear;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
const timeRes = await this.getServerTime();
|
||||
return Number(timeRes.time_now);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getOrderBook(params: SymbolParam): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/orderBook/L2', params);
|
||||
}
|
||||
|
||||
getKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('public/linear/kline', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest information for symbol
|
||||
*/
|
||||
getTickers(
|
||||
params?: Partial<SymbolParam>,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/tickers', params);
|
||||
}
|
||||
|
||||
getTrades(params: SymbolLimitParam): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('public/linear/recent-trading-records', params);
|
||||
}
|
||||
|
||||
getSymbols(): Promise<APIResponse<SymbolInfo[]>> {
|
||||
return this.get('v2/public/symbols');
|
||||
}
|
||||
|
||||
getLastFundingRate(params: SymbolParam): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('public/linear/funding/prev-funding-rate', params);
|
||||
}
|
||||
|
||||
getMarkPriceKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('public/linear/mark-price-kline', params);
|
||||
}
|
||||
|
||||
getIndexPriceKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('public/linear/index-price-kline', params);
|
||||
}
|
||||
|
||||
getPremiumIndexKline(
|
||||
params: SymbolIntervalFromLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('public/linear/premium-index-kline', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data : Advanced
|
||||
*
|
||||
*/
|
||||
|
||||
getOpenInterest(
|
||||
params: SymbolPeriodLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/open-interest', params);
|
||||
}
|
||||
|
||||
getLatestBigDeal(
|
||||
params: SymbolLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/big-deal', params);
|
||||
}
|
||||
|
||||
getLongShortRatio(
|
||||
params: SymbolPeriodLimitParam,
|
||||
): Promise<APIResponseWithTime<any[]>> {
|
||||
return this.get('v2/public/account-ratio', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Account Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getApiKeyInfo(): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/account/api-key');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Wallet Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getWalletBalance(
|
||||
params?: Partial<CoinParam>,
|
||||
): Promise<APIResponseWithTime<WalletBalances>> {
|
||||
return this.getPrivate('v2/private/wallet/balance', params);
|
||||
}
|
||||
|
||||
getWalletFundRecords(
|
||||
params?: WalletFundRecordsReq,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/wallet/fund/records', params);
|
||||
}
|
||||
|
||||
getWithdrawRecords(
|
||||
params?: WithdrawRecordsReq,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/wallet/withdraw/list', params);
|
||||
}
|
||||
|
||||
getAssetExchangeRecords(
|
||||
params?: AssetExchangeRecordsReq,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('v2/private/exchange-order/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* API Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getServerTime(): Promise<APIResponseWithTime<{}>> {
|
||||
return this.get('v2/public/time');
|
||||
}
|
||||
|
||||
getApiAnnouncements(): Promise<APIResponseWithTime<any>> {
|
||||
return this.get('v2/public/announcement');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Account Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
placeActiveOrder(
|
||||
params: NewLinearOrder,
|
||||
): Promise<APIResponseWithTime<LinearOrder | null>> {
|
||||
return this.postPrivate('private/linear/order/create', params);
|
||||
}
|
||||
|
||||
getActiveOrderList(
|
||||
params: LinearGetOrdersRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('private/linear/order/list', params);
|
||||
}
|
||||
|
||||
cancelActiveOrder(
|
||||
params: LinearCancelOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/order/cancel', params);
|
||||
}
|
||||
|
||||
cancelAllActiveOrders(
|
||||
params: SymbolParam,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/order/cancel-all', params);
|
||||
}
|
||||
|
||||
replaceActiveOrder(
|
||||
params: LinearReplaceOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/order/replace', params);
|
||||
}
|
||||
|
||||
queryActiveOrder(
|
||||
params: LinearGetOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('private/linear/order/search', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditional orders
|
||||
*/
|
||||
|
||||
placeConditionalOrder(
|
||||
params: LinearConditionalOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/stop-order/create', params);
|
||||
}
|
||||
|
||||
getConditionalOrder(
|
||||
params: LinearGetConditionalOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('private/linear/stop-order/list', params);
|
||||
}
|
||||
|
||||
cancelConditionalOrder(
|
||||
params: LinearCancelConditionalOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/stop-order/cancel', params);
|
||||
}
|
||||
|
||||
cancelAllConditionalOrders(
|
||||
params: SymbolParam,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/stop-order/cancel-all', params);
|
||||
}
|
||||
|
||||
replaceConditionalOrder(
|
||||
params: LinearReplaceConditionalOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/stop-order/replace', params);
|
||||
}
|
||||
|
||||
queryConditionalOrder(
|
||||
params: LinearQueryConditionalOrderRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('private/linear/stop-order/search', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Position
|
||||
*/
|
||||
|
||||
getPosition(): Promise<APIResponseWithTime<PerpPositionRoot[]>>;
|
||||
|
||||
getPosition(
|
||||
params: Partial<SymbolParam>,
|
||||
): Promise<APIResponseWithTime<PerpPosition[]>>;
|
||||
|
||||
getPosition(
|
||||
params?: Partial<SymbolParam>,
|
||||
): Promise<APIResponseWithTime<PerpPosition[] | PerpPositionRoot[]>> {
|
||||
return this.getPrivate('private/linear/position/list', params);
|
||||
}
|
||||
|
||||
setAutoAddMargin(
|
||||
params?: LinearSetAutoAddMarginRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate(
|
||||
'private/linear/position/set-auto-add-margin',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
setMarginSwitch(
|
||||
params?: LinearSetMarginSwitchRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/position/switch-isolated', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch between one-way vs hedge mode. Use `linearPositionModeEnum` for the mode parameter.
|
||||
*/
|
||||
setPositionMode(
|
||||
params: LinearSetPositionModeRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/position/switch-mode', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch TP/SL mode between full or partial. When set to Partial, TP/SL orders may have a quantity less than the position size.
|
||||
* This is set with the setTradingStop() method. Use `positionTpSlModeEnum` for the tp_sl_mode parameter.
|
||||
*/
|
||||
setPositionTpSlMode(
|
||||
params: LinearSetPositionTpSlModeRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/tpsl/switch-mode', params);
|
||||
}
|
||||
|
||||
setAddReduceMargin(
|
||||
params?: LinearSetAddReduceMarginRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/position/add-margin', params);
|
||||
}
|
||||
|
||||
setUserLeverage(
|
||||
params: LinearSetUserLeverageRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/position/set-leverage', params);
|
||||
}
|
||||
|
||||
setTradingStop(
|
||||
params: LinearSetTradingStopRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/position/trading-stop', params);
|
||||
}
|
||||
|
||||
getTradeRecords(
|
||||
params: LinearGetTradeRecordsRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('private/linear/trade/execution/list', params);
|
||||
}
|
||||
|
||||
getHistoryTradeRecords(
|
||||
params: LinearGetHistoryTradeRecordsRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate(
|
||||
'/private/linear/trade/execution/history-list',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getClosedPnl(
|
||||
params: LinearGetClosedPnlRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('private/linear/trade/closed-pnl/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Risk Limit
|
||||
*/
|
||||
|
||||
getRiskLimitList(params: SymbolParam): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('public/linear/risk-limit', params);
|
||||
}
|
||||
|
||||
setRiskLimit(
|
||||
params: LinearSetRiskLimitRequest,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.postPrivate('private/linear/position/set-risk', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Funding
|
||||
*/
|
||||
|
||||
getPredictedFundingFee(
|
||||
params: SymbolParam,
|
||||
): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('private/linear/funding/predicted-funding', params);
|
||||
}
|
||||
|
||||
getLastFundingFee(params: SymbolParam): Promise<APIResponseWithTime<any>> {
|
||||
return this.getPrivate('private/linear/funding/prev-funding', params);
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ import {
|
||||
DeleteSubMemberParamsV5,
|
||||
DeliveryPriceV5,
|
||||
DeliveryRecordV5,
|
||||
DepositAddressResultV5,
|
||||
DepositAddressChainV5,
|
||||
DepositRecordV5,
|
||||
ExchangeBrokerAccountInfoV5,
|
||||
ExchangeBrokerEarningResultV5,
|
||||
@@ -272,7 +272,7 @@ export class RestClientV5 extends BaseRestClient {
|
||||
*/
|
||||
|
||||
getClientType() {
|
||||
return REST_CLIENT_TYPE_ENUM.v3;
|
||||
return REST_CLIENT_TYPE_ENUM.v5;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
@@ -1489,7 +1489,12 @@ export class RestClientV5 extends BaseRestClient {
|
||||
getMasterDepositAddress(
|
||||
coin: string,
|
||||
chainType?: string,
|
||||
): Promise<APIResponseV3WithTime<DepositAddressResultV5>> {
|
||||
): Promise<
|
||||
APIResponseV3WithTime<{
|
||||
coin: string;
|
||||
chains: DepositAddressChainV5[];
|
||||
}>
|
||||
> {
|
||||
return this.getPrivate('/v5/asset/deposit/query-address', {
|
||||
coin,
|
||||
chainType,
|
||||
@@ -1503,7 +1508,12 @@ export class RestClientV5 extends BaseRestClient {
|
||||
coin: string,
|
||||
chainType: string,
|
||||
subMemberId: string,
|
||||
): Promise<APIResponseV3WithTime<DepositAddressResultV5>> {
|
||||
): Promise<
|
||||
APIResponseV3WithTime<{
|
||||
coin: string;
|
||||
chains: DepositAddressChainV5;
|
||||
}>
|
||||
> {
|
||||
return this.getPrivate('/v5/asset/deposit/query-sub-member-address', {
|
||||
coin,
|
||||
chainType,
|
||||
@@ -1514,6 +1524,7 @@ export class RestClientV5 extends BaseRestClient {
|
||||
/**
|
||||
* @deprecated - duplicate function, use getSubDepositAddress() instead
|
||||
* Query the deposit address information of SUB account.
|
||||
* @deprecated Duplicate endpoint - Use getSubDepositAddress() instead
|
||||
*
|
||||
* CAUTION
|
||||
* Can use master UID's api key only
|
||||
@@ -1522,7 +1533,12 @@ export class RestClientV5 extends BaseRestClient {
|
||||
coin: string,
|
||||
chainType: string,
|
||||
subMemberId: string,
|
||||
): Promise<APIResponseV3<DepositAddressResultV5>> {
|
||||
): Promise<
|
||||
APIResponseV3<{
|
||||
coin: string;
|
||||
chains: DepositAddressChainV5;
|
||||
}>
|
||||
> {
|
||||
return this.getPrivate('/v5/asset/deposit/query-sub-member-address', {
|
||||
coin,
|
||||
chainType,
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
APIResponseV3,
|
||||
APIResponseWithTime,
|
||||
KlineInterval,
|
||||
NewSpotOrderV3,
|
||||
SpotBalances,
|
||||
SpotCancelOrderBatchRequest,
|
||||
SpotCrossMarginBorrowingInfoRequest,
|
||||
SpotCrossMarginRepaymentHistoryRequest,
|
||||
SpotLeveragedTokenPRHistoryRequest,
|
||||
SpotMyTradesRequest,
|
||||
SpotOrderQueryById,
|
||||
} from './types';
|
||||
import { APIResponseV3, numberInString } from './types';
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
@@ -24,8 +12,8 @@ import BaseRestClient from './util/BaseRestClient';
|
||||
*/
|
||||
export class SpotClientV3 extends BaseRestClient {
|
||||
getClientType() {
|
||||
// Follows the same authentication mechanism as other v3 APIs (e.g. USDC)
|
||||
return REST_CLIENT_TYPE_ENUM.v3;
|
||||
// Doesn't really matter here, since the only remaining endpoint does not require auth.
|
||||
return REST_CLIENT_TYPE_ENUM.v5;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
@@ -39,17 +27,11 @@ export class SpotClientV3 extends BaseRestClient {
|
||||
*
|
||||
*/
|
||||
|
||||
/** Get all symbols */
|
||||
getSymbols(): Promise<APIResponseV3<any>> {
|
||||
return this.get('/spot/v3/public/symbols');
|
||||
}
|
||||
|
||||
/** Get orderbook for symbol */
|
||||
getOrderBook(symbol: string, limit?: number): Promise<APIResponseV3<any>> {
|
||||
return this.get('/spot/v3/public/quote/depth', { symbol, limit });
|
||||
}
|
||||
|
||||
/** Get merged orderbook for symbol */
|
||||
/**
|
||||
* Get merged orderbook for symbol
|
||||
*
|
||||
* This is the only known pre-V5 endpoint to still be online.
|
||||
*/
|
||||
getMergedOrderBook(
|
||||
symbol: string,
|
||||
scale?: number,
|
||||
@@ -62,246 +44,13 @@ export class SpotClientV3 extends BaseRestClient {
|
||||
});
|
||||
}
|
||||
|
||||
/** Get public trading records (raw trades) */
|
||||
getTrades(symbol: string, limit?: number): Promise<APIResponseV3<any>> {
|
||||
return this.get('/spot/v3/public/quote/trades', { symbol, limit });
|
||||
}
|
||||
|
||||
/** Get candles/klines */
|
||||
getCandles(
|
||||
symbol: string,
|
||||
interval: KlineInterval,
|
||||
limit?: number,
|
||||
startTime?: number,
|
||||
endTime?: number,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/spot/v3/public/quote/kline', {
|
||||
symbol,
|
||||
interval,
|
||||
limit,
|
||||
startTime,
|
||||
endTime,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get latest information for symbol (24hr ticker) */
|
||||
get24hrTicker(symbol?: string): Promise<APIResponseV3<any>> {
|
||||
return this.get('/spot/v3/public/quote/ticker/24hr', { symbol });
|
||||
}
|
||||
|
||||
/** Get last traded price */
|
||||
getLastTradedPrice(symbol?: string): Promise<APIResponseV3<any>> {
|
||||
return this.get('/spot/v3/public/quote/ticker/price', { symbol });
|
||||
}
|
||||
|
||||
/** Get best bid/ask price */
|
||||
getBestBidAskPrice(symbol?: string): Promise<APIResponseV3<any>> {
|
||||
return this.get('/spot/v3/public/quote/ticker/bookTicker', { symbol });
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Account Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** -> Order API */
|
||||
|
||||
/** Create order */
|
||||
submitOrder(params: NewSpotOrderV3): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/spot/v3/private/order', params);
|
||||
}
|
||||
|
||||
/** Get active order state */
|
||||
getOrder(params: SpotOrderQueryById): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/spot/v3/private/order', params);
|
||||
}
|
||||
|
||||
/** Cancel order */
|
||||
cancelOrder(params: SpotOrderQueryById): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/spot/v3/private/cancel-order', params);
|
||||
}
|
||||
|
||||
/** Batch cancel orders */
|
||||
cancelOrderBatch(
|
||||
params: SpotCancelOrderBatchRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
const orderTypes = params.orderTypes
|
||||
? params.orderTypes.join(',')
|
||||
: undefined;
|
||||
|
||||
return this.postPrivate('/spot/v3/private/cancel-orders', {
|
||||
...params,
|
||||
orderTypes,
|
||||
});
|
||||
}
|
||||
|
||||
/** Batch cancel up to 100 orders by ID */
|
||||
cancelOrderBatchIDs(orderIds: string[]): Promise<APIResponseV3<any>> {
|
||||
const orderIdsCsv = orderIds.join(',');
|
||||
return this.postPrivate('/spot/v3/private/cancel-orders-by-ids', {
|
||||
orderIds: orderIdsCsv,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get open orders */
|
||||
getOpenOrders(
|
||||
symbol?: string,
|
||||
orderId?: string,
|
||||
limit?: number,
|
||||
orderCategory?: 0 | 1,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/spot/v3/private/open-orders', {
|
||||
symbol,
|
||||
orderId,
|
||||
limit,
|
||||
orderCategory,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get order history */
|
||||
getPastOrders(
|
||||
symbol?: string,
|
||||
orderId?: string,
|
||||
limit?: number,
|
||||
orderCategory?: 0 | 1,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/spot/v3/private/history-orders', {
|
||||
symbol,
|
||||
orderId,
|
||||
limit,
|
||||
orderCategory,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get your trade history.
|
||||
* If startTime is not specified, you can only query for records in the last 7 days.
|
||||
* If you want to query for records older than 7 days, startTime is required.
|
||||
*/
|
||||
getMyTrades(params?: SpotMyTradesRequest): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/spot/v3/private/my-trades', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Wallet Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** Get Wallet Balance */
|
||||
getBalances(): Promise<APIResponseV3<SpotBalances>> {
|
||||
return this.getPrivate('/spot/v3/private/account');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* API Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getServerTime(): Promise<APIResponseWithTime> {
|
||||
getServerTime(): Promise<{ time_now: numberInString }> {
|
||||
return this.get('/v2/public/time');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Leveraged Token Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** Get all asset infos */
|
||||
getLeveragedTokenAssetInfos(ltCode?: string): Promise<APIResponseV3<any>> {
|
||||
return this.get('/spot/v3/public/infos', { ltCode });
|
||||
}
|
||||
|
||||
/** Get leveraged token market info */
|
||||
getLeveragedTokenMarketInfo(ltCode: string): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/spot/v3/private/reference', { ltCode });
|
||||
}
|
||||
|
||||
/** Purchase leveraged token */
|
||||
purchaseLeveragedToken(
|
||||
ltCode: string,
|
||||
ltAmount: string,
|
||||
serialNo?: string,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/spot/v3/private/purchase', {
|
||||
ltCode,
|
||||
ltAmount,
|
||||
serialNo,
|
||||
});
|
||||
}
|
||||
|
||||
/** Redeem leveraged token */
|
||||
redeemLeveragedToken(
|
||||
ltCode: string,
|
||||
ltAmount: string,
|
||||
serialNo?: string,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/spot/v3/private/redeem', {
|
||||
ltCode,
|
||||
ltAmount,
|
||||
serialNo,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get leveraged token purchase/redemption history */
|
||||
getLeveragedTokenPRHistory(
|
||||
params?: SpotLeveragedTokenPRHistoryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/spot/v3/private/record', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Cross Margin Trading Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** Borrow margin loan */
|
||||
borrowCrossMarginLoan(
|
||||
coin: string,
|
||||
qty: string,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/spot/v3/private/cross-margin-loan', {
|
||||
coin,
|
||||
qty,
|
||||
});
|
||||
}
|
||||
|
||||
/** Repay margin loan */
|
||||
repayCrossMarginLoan(coin: string, qty: string): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/spot/v3/private/cross-margin-repay', {
|
||||
coin,
|
||||
qty,
|
||||
});
|
||||
}
|
||||
|
||||
/** Query borrowing info */
|
||||
getCrossMarginBorrowingInfo(
|
||||
params?: SpotCrossMarginBorrowingInfoRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/spot/v3/private/cross-margin-orders', params);
|
||||
}
|
||||
|
||||
/** Query account info */
|
||||
getCrossMarginAccountInfo(): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/spot/v3/private/cross-margin-account');
|
||||
}
|
||||
|
||||
/** Query interest & quota */
|
||||
getCrossMarginInterestQuota(coin: string): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/spot/v3/private/cross-margin-loan-info', { coin });
|
||||
}
|
||||
|
||||
/** Query repayment history */
|
||||
getCrossMarginRepaymentHistory(
|
||||
params?: SpotCrossMarginRepaymentHistoryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate(
|
||||
'/spot/v3/private/cross-margin-repay-history',
|
||||
params,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
APIResponse,
|
||||
KlineInterval,
|
||||
NewSpotOrder,
|
||||
OrderSide,
|
||||
OrderTypeSpot,
|
||||
SpotBalances,
|
||||
SpotLastPrice,
|
||||
SpotOrderQueryById,
|
||||
SpotSymbolInfo,
|
||||
} from './types';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util/requestUtils';
|
||||
|
||||
/**
|
||||
* REST API client for Spot APIs (v1)
|
||||
*
|
||||
* @deprecated WARNING: V1/V2 private endpoints (Rest API & Websocket Stream) for mainnet
|
||||
* will be switched off gradually from 30 Oct 2023 UTC, so they are not promised a stability.
|
||||
* Please note that you are at your own risk of using old endpoints going forward, and please move to V5 ASAP.
|
||||
*/
|
||||
export class SpotClient extends BaseRestClient {
|
||||
getClientType() {
|
||||
return REST_CLIENT_TYPE_ENUM.spot;
|
||||
}
|
||||
|
||||
fetchServerTime(): Promise<number> {
|
||||
return this.getServerTime();
|
||||
}
|
||||
|
||||
async getServerTime(): Promise<number> {
|
||||
const res = await this.get('/spot/v1/time');
|
||||
return res.result.serverTime;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data Endpoints
|
||||
*
|
||||
**/
|
||||
|
||||
getSymbols(): Promise<APIResponse<SpotSymbolInfo[]>> {
|
||||
return this.get('/spot/v1/symbols');
|
||||
}
|
||||
|
||||
getOrderBook(symbol: string, limit?: number): Promise<APIResponse<any>> {
|
||||
return this.get('/spot/quote/v1/depth', {
|
||||
symbol,
|
||||
limit,
|
||||
});
|
||||
}
|
||||
|
||||
getMergedOrderBook(
|
||||
symbol: string,
|
||||
scale?: number,
|
||||
limit?: number,
|
||||
): Promise<APIResponse<any>> {
|
||||
return this.get('/spot/quote/v1/depth/merged', {
|
||||
symbol,
|
||||
scale,
|
||||
limit,
|
||||
});
|
||||
}
|
||||
|
||||
getTrades(symbol: string, limit?: number): Promise<APIResponse<any[]>> {
|
||||
return this.get('/spot/quote/v1/trades', {
|
||||
symbol,
|
||||
limit,
|
||||
});
|
||||
}
|
||||
|
||||
getCandles(
|
||||
symbol: string,
|
||||
interval: KlineInterval,
|
||||
limit?: number,
|
||||
startTime?: number,
|
||||
endTime?: number,
|
||||
): Promise<APIResponse<any[]>> {
|
||||
return this.get('/spot/quote/v1/kline', {
|
||||
symbol,
|
||||
interval,
|
||||
limit,
|
||||
startTime,
|
||||
endTime,
|
||||
});
|
||||
}
|
||||
|
||||
get24hrTicker(symbol?: string): Promise<APIResponse<any>> {
|
||||
return this.get('/spot/quote/v1/ticker/24hr', { symbol });
|
||||
}
|
||||
|
||||
getLastTradedPrice(): Promise<APIResponse<SpotLastPrice[]>>;
|
||||
|
||||
getLastTradedPrice(symbol: string): Promise<APIResponse<SpotLastPrice>>;
|
||||
|
||||
getLastTradedPrice(
|
||||
symbol?: string,
|
||||
): Promise<APIResponse<SpotLastPrice | SpotLastPrice[]>> {
|
||||
return this.get('/spot/quote/v1/ticker/price', { symbol });
|
||||
}
|
||||
|
||||
getBestBidAskPrice(symbol?: string): Promise<APIResponse<any>> {
|
||||
return this.get('/spot/quote/v1/ticker/book_ticker', { symbol });
|
||||
}
|
||||
|
||||
/**
|
||||
* Account Data Endpoints
|
||||
*/
|
||||
|
||||
submitOrder(params: NewSpotOrder): Promise<APIResponse<any>> {
|
||||
return this.postPrivate('/spot/v1/order', params);
|
||||
}
|
||||
|
||||
getOrder(params: SpotOrderQueryById): Promise<APIResponse<any>> {
|
||||
return this.getPrivate('/spot/v1/order', params);
|
||||
}
|
||||
|
||||
cancelOrder(params: SpotOrderQueryById): Promise<APIResponse<any>> {
|
||||
return this.deletePrivate('/spot/v1/order', params);
|
||||
}
|
||||
|
||||
cancelOrderBatch(params: {
|
||||
symbol: string;
|
||||
side?: OrderSide;
|
||||
orderTypes: OrderTypeSpot[];
|
||||
}): Promise<APIResponse<any>> {
|
||||
const orderTypes = params.orderTypes
|
||||
? params.orderTypes.join(',')
|
||||
: undefined;
|
||||
|
||||
return this.deletePrivate('/spot/order/batch-cancel', {
|
||||
...params,
|
||||
orderTypes,
|
||||
});
|
||||
}
|
||||
|
||||
getOpenOrders(
|
||||
symbol?: string,
|
||||
orderId?: string,
|
||||
limit?: number,
|
||||
): Promise<APIResponse<any>> {
|
||||
return this.getPrivate('/spot/v1/open-orders', {
|
||||
symbol,
|
||||
orderId,
|
||||
limit,
|
||||
});
|
||||
}
|
||||
|
||||
getPastOrders(
|
||||
symbol?: string,
|
||||
orderId?: string,
|
||||
limit?: number,
|
||||
): Promise<APIResponse<any>> {
|
||||
return this.getPrivate('/spot/v1/history-orders', {
|
||||
symbol,
|
||||
orderId,
|
||||
limit,
|
||||
});
|
||||
}
|
||||
|
||||
getMyTrades(
|
||||
symbol?: string,
|
||||
limit?: number,
|
||||
fromId?: number,
|
||||
toId?: number,
|
||||
): Promise<APIResponse<any>> {
|
||||
return this.getPrivate('/spot/v1/myTrades', {
|
||||
symbol,
|
||||
limit,
|
||||
fromId,
|
||||
toId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wallet Data Endpoints
|
||||
*/
|
||||
|
||||
getBalances(): Promise<APIResponse<SpotBalances>> {
|
||||
return this.getPrivate('/spot/v1/account');
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ export * from './copy-trading';
|
||||
export * from './contract';
|
||||
export * from './linear';
|
||||
export * from './inverse';
|
||||
export * from './spot';
|
||||
export * from './usdc-perp';
|
||||
export * from './usdc-options';
|
||||
export * from './usdc-shared';
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
import { OrderSide, numberInString } from '../shared';
|
||||
|
||||
export type OrderTypeSpot = 'LIMIT' | 'MARKET' | 'LIMIT_MAKER';
|
||||
export type OrderTimeInForce = 'GTC' | 'FOK' | 'IOC';
|
||||
|
||||
export interface NewSpotOrder {
|
||||
symbol: string;
|
||||
qty: number;
|
||||
side: OrderSide;
|
||||
type: OrderTypeSpot;
|
||||
timeInForce?: OrderTimeInForce;
|
||||
price?: number;
|
||||
orderLinkId?: string;
|
||||
}
|
||||
|
||||
export interface NewSpotOrderV3 {
|
||||
symbol: string;
|
||||
orderQty: string;
|
||||
side: OrderSide;
|
||||
orderType: OrderTypeSpot;
|
||||
timeInForce?: OrderTimeInForce;
|
||||
orderPrice?: string;
|
||||
orderLinkId?: string;
|
||||
orderCategory?: 0 | 1;
|
||||
triggerPrice?: string;
|
||||
}
|
||||
|
||||
export interface SpotCancelOrderBatchRequest {
|
||||
symbol: string;
|
||||
side?: OrderSide;
|
||||
orderTypes: OrderTypeSpot[];
|
||||
orderCategory?: 0 | 1;
|
||||
}
|
||||
|
||||
export interface SpotOrderQueryById {
|
||||
orderId?: string;
|
||||
orderLinkId?: string;
|
||||
orderCategory?: 0 | 1;
|
||||
}
|
||||
|
||||
export interface SpotSymbolInfo {
|
||||
name: string;
|
||||
alias: string;
|
||||
baseCurrency: string;
|
||||
quoteCurrency: string;
|
||||
basePrecision: numberInString;
|
||||
quotePrecision: numberInString;
|
||||
minTradeQuantity: numberInString;
|
||||
minTradeAmount: numberInString;
|
||||
minPricePrecision: numberInString;
|
||||
maxTradeQuantity: numberInString;
|
||||
maxTradeAmount: numberInString;
|
||||
category: numberInString;
|
||||
}
|
||||
|
||||
export interface SpotMyTradesRequest {
|
||||
symbol?: string;
|
||||
orderId?: string;
|
||||
limit?: string;
|
||||
startTime?: number;
|
||||
endTime?: number;
|
||||
fromTradeId?: string;
|
||||
toTradeId?: string;
|
||||
}
|
||||
|
||||
export interface SpotLeveragedTokenPRHistoryRequest {
|
||||
ltCode?: string;
|
||||
orderId?: string;
|
||||
startTime?: number;
|
||||
endTime?: number;
|
||||
limit?: number;
|
||||
orderType?: 1 | 2;
|
||||
serialNo?: string;
|
||||
}
|
||||
|
||||
export interface SpotCrossMarginBorrowingInfoRequest {
|
||||
startTime?: number;
|
||||
endTime?: number;
|
||||
coin?: string;
|
||||
status?: 0 | 1 | 2;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export interface SpotCrossMarginRepaymentHistoryRequest {
|
||||
startTime?: number;
|
||||
endTime?: number;
|
||||
coin?: string;
|
||||
limit?: number;
|
||||
}
|
||||
@@ -10,6 +10,8 @@ export interface GetCoinExchangeRecordParamsV5 {
|
||||
export interface GetDeliveryRecordParamsV5 {
|
||||
category: CategoryV5;
|
||||
symbol?: string;
|
||||
startTime?: number;
|
||||
endTime?: number;
|
||||
expDate?: string;
|
||||
limit?: number;
|
||||
cursor?: string;
|
||||
|
||||
@@ -1,23 +1,7 @@
|
||||
import { ContractClient } from '../contract-client';
|
||||
import { InverseClient } from '../inverse-client';
|
||||
import { LinearClient } from '../linear-client';
|
||||
import { RestClientV5 } from '../rest-client-v5';
|
||||
import { SpotClient } from '../spot-client';
|
||||
import { SpotClientV3 } from '../spot-client-v3';
|
||||
import { UnifiedMarginClient } from '../unified-margin-client';
|
||||
import { USDCOptionClient } from '../usdc-option-client';
|
||||
import { USDCPerpetualClient } from '../usdc-perpetual-client';
|
||||
|
||||
export type RESTClient =
|
||||
| InverseClient
|
||||
| LinearClient
|
||||
| SpotClient
|
||||
| SpotClientV3
|
||||
| USDCOptionClient
|
||||
| USDCPerpetualClient
|
||||
| UnifiedMarginClient
|
||||
| ContractClient
|
||||
| RestClientV5;
|
||||
export type RESTClient = SpotClientV3 | RestClientV5;
|
||||
|
||||
export type numberInString = string;
|
||||
|
||||
@@ -53,14 +37,6 @@ export type KlineIntervalV3 =
|
||||
| 'W'
|
||||
| 'M';
|
||||
|
||||
export interface APIResponse<T> {
|
||||
ret_code: number;
|
||||
ret_msg: 'OK' | string;
|
||||
ext_code: string | null;
|
||||
ext_info: string | null;
|
||||
result: T;
|
||||
}
|
||||
|
||||
export interface APIRateLimit {
|
||||
/** Remaining requests to this endpoint before the next reset */
|
||||
remainingRequests: number;
|
||||
@@ -88,12 +64,6 @@ export interface APIResponseV3<T> {
|
||||
}
|
||||
|
||||
export type APIResponseV3WithTime<T> = APIResponseV3<T> & { time: number };
|
||||
|
||||
export interface APIResponseWithTime<T = {}> extends APIResponse<T> {
|
||||
/** UTC timestamp */
|
||||
time_now: numberInString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request Parameter Types
|
||||
*/
|
||||
|
||||
@@ -202,6 +202,7 @@ export interface WSExecutionV5 {
|
||||
execId: string;
|
||||
execPrice: string;
|
||||
execQty: string;
|
||||
execPnl: string;
|
||||
execType: ExecTypeV5;
|
||||
execValue: string;
|
||||
execTime: string;
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
import { RestClientOptions, WS_KEY_MAP } from '../../util';
|
||||
|
||||
/** For spot markets, spotV3 is recommended */
|
||||
export type APIMarket =
|
||||
| 'inverse'
|
||||
| 'linear'
|
||||
| 'spot'
|
||||
| 'spotv3'
|
||||
| 'usdcOption'
|
||||
| 'usdcPerp'
|
||||
| 'unifiedPerp'
|
||||
| 'unifiedOption'
|
||||
| 'contractUSDT'
|
||||
| 'contractInverse'
|
||||
| 'v5';
|
||||
export type APIMarket = 'v5';
|
||||
|
||||
// Same as inverse futures
|
||||
export type WsPublicInverseTopic =
|
||||
@@ -111,7 +100,7 @@ export interface WSClientConfigurableOptions {
|
||||
/**
|
||||
* The API group this client should connect to. The V5 market is currently used by default.
|
||||
*
|
||||
* For the V3 APIs use `v3` as the market (spot/unified margin/usdc/account asset/copy trading)
|
||||
* Only the "V5" "market" is supported here.
|
||||
*/
|
||||
market?: APIMarket;
|
||||
|
||||
@@ -128,11 +117,21 @@ export interface WSClientConfigurableOptions {
|
||||
reconnectTimeout?: number;
|
||||
|
||||
restOptions?: RestClientOptions;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
requestOptions?: any;
|
||||
|
||||
wsUrl?: string;
|
||||
|
||||
/**
|
||||
* Default: false.
|
||||
*
|
||||
* When enabled, any calls to the subscribe method will return a promise.
|
||||
* Note: internally, subscription requests are sent in batches. This may not behave as expected when
|
||||
* subscribing to a large number of topics, especially if you are not yet connected when subscribing.
|
||||
*/
|
||||
promiseSubscribeRequests?: boolean;
|
||||
|
||||
/**
|
||||
* Allows you to provide a custom "signMessage" function, e.g. to use node's much faster createHmac method
|
||||
*
|
||||
|
||||
@@ -1,401 +0,0 @@
|
||||
/* eslint-disable max-len */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
APIResponseV3,
|
||||
APIResponseWithTime,
|
||||
InternalTransferRequest,
|
||||
UM7DayTradingHistoryRequest,
|
||||
UMActiveOrdersRequest,
|
||||
UMBatchOrder,
|
||||
UMBatchOrderCancel,
|
||||
UMBatchOrderReplace,
|
||||
UMBorrowHistoryRequest,
|
||||
UMCancelAllOrdersRequest,
|
||||
UMCancelOrderRequest,
|
||||
UMCandlesRequest,
|
||||
UMCategory,
|
||||
UMExchangeCoinsRequest,
|
||||
UMFundingRateHistoryRequest,
|
||||
UMHistoricOrder,
|
||||
UMHistoricOrdersRequest,
|
||||
UMInstrumentInfo,
|
||||
UMInstrumentInfoRequest,
|
||||
UMModifyOrderRequest,
|
||||
UMOpenInterestRequest,
|
||||
UMOptionDeliveryPriceRequest,
|
||||
UMOptionsSettlementHistoryRequest,
|
||||
UMOrderRequest,
|
||||
UMPaginatedResult,
|
||||
UMPerpSettlementHistoryRequest,
|
||||
UMPositionsRequest,
|
||||
UMPublicTradesRequest,
|
||||
UMSetTPSLRequest,
|
||||
UMTransactionLogRequest,
|
||||
} from './types';
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
/**
|
||||
* REST API client for Derivatives V3 unified margin APIs
|
||||
* @deprecated WARNING
|
||||
* These endpoints are being switched off gradually and are expected to be completely turned off by the end of 2024.
|
||||
* They may stop working at any point before then.
|
||||
* Please update your code as soon as possible to use the V5 APIs instead.
|
||||
*/
|
||||
export class UnifiedMarginClient extends BaseRestClient {
|
||||
getClientType() {
|
||||
return REST_CLIENT_TYPE_ENUM.v3;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
const res = await this.getServerTime();
|
||||
return Number(res.time_now);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** Query order book info. Each side has a depth of 25 orders. */
|
||||
getOrderBook(
|
||||
symbol: string,
|
||||
category: string,
|
||||
limit?: number,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/order-book/L2', {
|
||||
category,
|
||||
symbol,
|
||||
limit,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get candles/klines */
|
||||
getCandles(params: UMCandlesRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/kline', params);
|
||||
}
|
||||
|
||||
/** Get a symbol price/statistics ticker */
|
||||
getSymbolTicker(
|
||||
category: UMCategory,
|
||||
symbol?: string,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/tickers', { category, symbol });
|
||||
}
|
||||
|
||||
/** Get trading rules per symbol/contract, incl price/amount/value/leverage filters */
|
||||
getInstrumentInfo(
|
||||
params: UMInstrumentInfoRequest,
|
||||
): Promise<APIResponseV3<UMPaginatedResult<UMInstrumentInfo>>> {
|
||||
return this.get('/derivatives/v3/public/instruments-info', params);
|
||||
}
|
||||
|
||||
/** Query mark price kline (like getCandles() but for mark price). */
|
||||
getMarkPriceCandles(params: UMCandlesRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/mark-price-kline', params);
|
||||
}
|
||||
|
||||
/** Query Index Price Kline */
|
||||
getIndexPriceCandles(params: UMCandlesRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/index-price-kline', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* The funding rate is generated every 8 hours at 00:00 UTC, 08:00 UTC and 16:00 UTC.
|
||||
* For example, if a request is sent at 12:00 UTC, the funding rate generated earlier that day at 08:00 UTC will be sent.
|
||||
*/
|
||||
getFundingRateHistory(
|
||||
params: UMFundingRateHistoryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get(
|
||||
'/derivatives/v3/public/funding/history-funding-rate',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Get Risk Limit */
|
||||
getRiskLimit(
|
||||
category: UMCategory,
|
||||
symbol: string,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/risk-limit/list', {
|
||||
category,
|
||||
symbol,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get option delivery price */
|
||||
getOptionDeliveryPrice(
|
||||
params: UMOptionDeliveryPriceRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/delivery-price', params);
|
||||
}
|
||||
|
||||
/** Get recent trades */
|
||||
getTrades(params: UMPublicTradesRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/recent-trade', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total amount of unsettled contracts.
|
||||
* In other words, the total number of contracts held in open positions.
|
||||
*/
|
||||
getOpenInterest(params: UMOpenInterestRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/derivatives/v3/public/open-interest', params);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Unified Margin Account Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** -> Order API */
|
||||
|
||||
/** Place an order */
|
||||
submitOrder(params: UMOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/unified/v3/private/order/create', params);
|
||||
}
|
||||
|
||||
/** Active order parameters (such as quantity, price) and stop order parameters cannot be modified in one request at the same time. Please request modification separately. */
|
||||
modifyOrder(params: UMModifyOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/unified/v3/private/order/replace', params);
|
||||
}
|
||||
|
||||
/** Cancel order */
|
||||
cancelOrder(params: UMCancelOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/unified/v3/private/order/cancel', params);
|
||||
}
|
||||
|
||||
/** Query Open Orders */
|
||||
getActiveOrders(params: UMActiveOrdersRequest): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/unified/v3/private/order/unfilled-orders', params);
|
||||
}
|
||||
|
||||
/** Query order history. As order creation/cancellation is asynchronous, the data returned from the interface may be delayed. To access order information in real-time, call getActiveOrders() */
|
||||
getHistoricOrders(
|
||||
params: UMHistoricOrdersRequest,
|
||||
): Promise<APIResponseV3<UMPaginatedResult<UMHistoricOrder>>> {
|
||||
return this.getPrivate('/unified/v3/private/order/list', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* This API provides the batch order mode under the unified margin account.
|
||||
* Max 10 per request
|
||||
*/
|
||||
batchSubmitOrders(
|
||||
category: UMCategory,
|
||||
orders: UMBatchOrder[],
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/unified/v3/private/order/create-batch', {
|
||||
category,
|
||||
request: orders,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface can modify the open order information in batches.
|
||||
* Currently, it is not supported to modify the conditional order information.
|
||||
* Please note that only unfilled or partial filled orders can be modified.
|
||||
* If both futures and options orders are in one request, only the orders matching the category will be operated according to the category type
|
||||
*/
|
||||
batchReplaceOrders(
|
||||
category: UMCategory,
|
||||
orders: UMBatchOrderReplace[],
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/unified/v3/private/order/replace-batch', {
|
||||
category,
|
||||
request: orders,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This API provides batch cancellation under the unified margin account.
|
||||
* Order cancellation of futures and options cannot be canceled in one request at the same time.
|
||||
* If both futures and options orders are in one request, only the orders matching the category will be operated according to the category type.
|
||||
*/
|
||||
batchCancelOrders(
|
||||
category: UMCategory,
|
||||
orders: UMBatchOrderCancel[],
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/unified/v3/private/order/cancel-batch', {
|
||||
category,
|
||||
request: orders,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This API provides the cancellation of all open orders under the unified margin account.
|
||||
* Order cancellation of futures and options cannot be canceled in one request at the same time.
|
||||
* If both futures and options orders are in one request, only the orders matching the category will be operated according to the category type.
|
||||
*/
|
||||
cancelAllOrders(
|
||||
params: UMCancelAllOrdersRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/unified/v3/private/order/cancel-all', params);
|
||||
}
|
||||
|
||||
/** -> Positions API */
|
||||
|
||||
/**
|
||||
* Query my positions real-time. Accessing personal list of positions.
|
||||
* Users can access their position holding information through this interface, such as the number of position holdings and wallet balance.
|
||||
*/
|
||||
getPositions(params: UMPositionsRequest): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/unified/v3/private/position/list', params);
|
||||
}
|
||||
|
||||
/** Leverage setting. */
|
||||
setLeverage(
|
||||
category: UMCategory,
|
||||
symbol: string,
|
||||
buyLeverage: number,
|
||||
sellLeverage: number,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/unified/v3/private/position/set-leverage', {
|
||||
category,
|
||||
symbol,
|
||||
buyLeverage,
|
||||
sellLeverage,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Switching the TP/SL mode to the cross margin mode or selected positions.
|
||||
* When you set the TP/SL mode on the selected positions, the quantity of take-profit or stop-loss orders can be smaller than the position size. Please use Trading-Stop endpoint.
|
||||
*/
|
||||
setTPSLMode(
|
||||
category: UMCategory,
|
||||
symbol: string,
|
||||
tpSlMode: 1 | 0,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/unified/v3/private/position/tpsl/switch-mode', {
|
||||
category,
|
||||
symbol,
|
||||
tpSlMode,
|
||||
});
|
||||
}
|
||||
|
||||
/** Set risk limit */
|
||||
setRiskLimit(
|
||||
category: UMCategory,
|
||||
symbol: string,
|
||||
riskId: number,
|
||||
positionIdx: number,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/unified/v3/private/position/set-risk-limit', {
|
||||
category,
|
||||
symbol,
|
||||
riskId,
|
||||
positionIdx,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set position TP/SL and trailing stop.
|
||||
* Pass the following parameters, then the system will create conditional orders.
|
||||
* If the position is closed, the system will cancel these orders, and adjust the position size.
|
||||
*/
|
||||
setTPSL(params: UMSetTPSLRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/unified/v3/private/position/trading-stop',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the user's filled history, ranked by time in descending order.
|
||||
* There might be multiple filled histories for an order.
|
||||
*/
|
||||
get7DayTradingHistory(
|
||||
params: UM7DayTradingHistoryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/unified/v3/private/execution/list', params);
|
||||
}
|
||||
|
||||
/** Query the settlement history, ranked by time in descending order. */
|
||||
getOptionsSettlementHistory(
|
||||
params: UMOptionsSettlementHistoryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/unified/v3/private/delivery-record', params);
|
||||
}
|
||||
|
||||
/** Query session settlement records, only for USDC perpetual */
|
||||
getUSDCPerpetualSettlementHistory(
|
||||
params: UMPerpSettlementHistoryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/unified/v3/private/settlement-record', params);
|
||||
}
|
||||
|
||||
/** -> Account API */
|
||||
|
||||
/** Query wallet balance */
|
||||
getBalances(coin?: string): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/unified/v3/private/account/wallet/balance', {
|
||||
coin,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade to unified margin account.
|
||||
* WARNING: This is currently not reversable!
|
||||
*/
|
||||
upgradeToUnifiedMargin(): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/unified/v3/private/account/upgrade-unified-account',
|
||||
);
|
||||
}
|
||||
|
||||
/** Query trading history */
|
||||
getTransactionLog(
|
||||
params: UMTransactionLogRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate(
|
||||
'/unified/v3/private/account/transaction-log',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Fund transfer between accounts (v2) */
|
||||
transferFunds(params: InternalTransferRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/asset/v1/private/transfer', params);
|
||||
}
|
||||
|
||||
/** Exchange Coins */
|
||||
getCoinExchangeHistory(
|
||||
params?: UMExchangeCoinsRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate(
|
||||
'/asset/v2/private/exchange/exchange-order-all',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Get Borrow History */
|
||||
getBorrowHistory(
|
||||
params?: UMBorrowHistoryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate(
|
||||
'/unified/v3/private/account/borrow-history',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Get Borrow Rate */
|
||||
getBorrowRate(currency?: string): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate('/unified/v3/private/account/borrow-rate', {
|
||||
currency,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* API Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getServerTime(): Promise<APIResponseWithTime> {
|
||||
return this.get('/v2/public/time');
|
||||
}
|
||||
}
|
||||
@@ -1,337 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
APIResponseV3,
|
||||
APIResponseWithTime,
|
||||
USDCOptionsActiveOrdersRealtimeRequest,
|
||||
USDCOptionsActiveOrdersRequest,
|
||||
USDCOptionsCancelAllOrdersRequest,
|
||||
USDCOptionsCancelOrderRequest,
|
||||
USDCOptionsContractInfoRequest,
|
||||
USDCOptionsDeliveryHistoryRequest,
|
||||
USDCOptionsDeliveryPriceRequest,
|
||||
USDCOptionsHistoricOrdersRequest,
|
||||
USDCOptionsHistoricalVolatilityRequest,
|
||||
USDCOptionsModifyMMPRequest,
|
||||
USDCOptionsModifyOrderRequest,
|
||||
USDCOptionsOrderExecutionRequest,
|
||||
USDCOptionsOrderRequest,
|
||||
USDCOptionsPositionsInfoExpiryRequest,
|
||||
USDCOptionsRecentTradesRequest,
|
||||
USDCPositionsRequest,
|
||||
USDCTransactionLogRequest,
|
||||
} from './types';
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
/**
|
||||
* REST API client for USDC Option APIs
|
||||
*
|
||||
* @deprecated WARNING: V1/V2 private endpoints (Rest API & Websocket Stream) for mainnet
|
||||
* will be switched off gradually from 30 Oct 2023 UTC, so they are not promised a stability.
|
||||
* Please note that you are at your own risk of using old endpoints going forward, and please move to V5 ASAP.
|
||||
*/
|
||||
export class USDCOptionClient extends BaseRestClient {
|
||||
getClientType() {
|
||||
return REST_CLIENT_TYPE_ENUM.v3;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
const res = await this.getServerTime();
|
||||
return Number(res.time_now);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** Query order book info. Each side has a depth of 25 orders. */
|
||||
getOrderBook(symbol: string): Promise<APIResponseV3<any>> {
|
||||
return this.get('/option/usdc/openapi/public/v1/order-book', { symbol });
|
||||
}
|
||||
|
||||
/** Fetch trading rules (such as min/max qty). Query for all if blank. */
|
||||
getContractInfo(
|
||||
params?: USDCOptionsContractInfoRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/option/usdc/openapi/public/v1/symbols', params);
|
||||
}
|
||||
|
||||
/** Get a symbol price/statistics ticker */
|
||||
getSymbolTicker(symbol: string): Promise<APIResponseV3<any>> {
|
||||
return this.get('/option/usdc/openapi/public/v1/tick', { symbol });
|
||||
}
|
||||
|
||||
/** Get delivery information */
|
||||
getDeliveryPrice(
|
||||
params?: USDCOptionsDeliveryPriceRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/option/usdc/openapi/public/v1/delivery-price', params);
|
||||
}
|
||||
|
||||
/** Returned records are Taker Buy in default. */
|
||||
getLast500Trades(
|
||||
params: USDCOptionsRecentTradesRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get(
|
||||
'/option/usdc/openapi/public/v1/query-trade-latest',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The data is in hourly.
|
||||
* If time field is not passed, it returns the recent 1 hour data by default.
|
||||
* It could be any timeframe by inputting startTime & endTime, but it must satisfy [endTime - startTime] <= 30 days.
|
||||
* It returns all data in 2 years when startTime & endTime are not passed.
|
||||
* Both startTime & endTime entered together or both are left blank
|
||||
*/
|
||||
getHistoricalVolatility(
|
||||
params?: USDCOptionsHistoricalVolatilityRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get(
|
||||
'/option/usdc/openapi/public/v1/query-historical-volatility',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Account Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** -> Order API */
|
||||
|
||||
/**
|
||||
* Place an order using the USDC Derivatives Account.
|
||||
* The request status can be queried in real-time.
|
||||
* The response parameters must be queried through a query or a WebSocket response.
|
||||
*/
|
||||
submitOrder(params: USDCOptionsOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/place-order',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each request supports a max. of four orders. The reduceOnly parameter should be separate and unique for each order in the request.
|
||||
*/
|
||||
batchSubmitOrders(
|
||||
orderRequest: USDCOptionsOrderRequest[],
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/batch-place-orders',
|
||||
{ orderRequest },
|
||||
);
|
||||
}
|
||||
|
||||
/** For Options, at least one of the three parameters — price, quantity or implied volatility — must be input. */
|
||||
modifyOrder(
|
||||
params: USDCOptionsModifyOrderRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/replace-order',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Each request supports a max. of four orders. The reduceOnly parameter should be separate and unique for each order in the request. */
|
||||
batchModifyOrders(
|
||||
replaceOrderRequest: USDCOptionsModifyOrderRequest[],
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/batch-replace-orders',
|
||||
{ replaceOrderRequest },
|
||||
);
|
||||
}
|
||||
|
||||
/** Cancel order */
|
||||
cancelOrder(
|
||||
params: USDCOptionsCancelOrderRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/cancel-order',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Batch cancel orders */
|
||||
batchCancelOrders(
|
||||
cancelRequest: USDCOptionsCancelOrderRequest[],
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/batch-cancel-orders',
|
||||
{ cancelRequest },
|
||||
);
|
||||
}
|
||||
|
||||
/** This is used to cancel all active orders. The real-time response indicates whether the request is successful, depending on retCode. */
|
||||
cancelActiveOrders(
|
||||
params?: USDCOptionsCancelAllOrdersRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/cancel-all',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Query Unfilled/Partially Filled Orders(real-time), up to last 7 days of partially filled/unfilled orders */
|
||||
getActiveRealtimeOrders(
|
||||
params?: USDCOptionsActiveOrdersRealtimeRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate(
|
||||
'/option/usdc/openapi/private/v1/trade/query-active-orders',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Query Unfilled/Partially Filled Orders */
|
||||
getActiveOrders(
|
||||
params: USDCOptionsActiveOrdersRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-active-orders',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Query order history. The endpoint only supports up to 30 days of queried records */
|
||||
getHistoricOrders(
|
||||
params: USDCOptionsHistoricOrdersRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-order-history',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query trade history.
|
||||
* The endpoint only supports up to 30 days of queried records.
|
||||
* An error will be returned if startTime is more than 30 days.
|
||||
*/
|
||||
getOrderExecutionHistory(
|
||||
params: USDCOptionsOrderExecutionRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/execution-list',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** -> Account API */
|
||||
|
||||
/** The endpoint only supports up to 30 days of queried records. An error will be returned if startTime is more than 30 days. */
|
||||
getTransactionLog(
|
||||
params: USDCTransactionLogRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-transaction-log',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Wallet info for USDC account. */
|
||||
getBalances(): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-wallet-balance',
|
||||
);
|
||||
}
|
||||
|
||||
/** Asset Info */
|
||||
getAssetInfo(baseCoin?: string): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-asset-info',
|
||||
{ baseCoin },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If USDC derivatives account balance is greater than X, you can open PORTFOLIO_MARGIN,
|
||||
* and if it is less than Y, it will automatically close PORTFOLIO_MARGIN and change back to REGULAR_MARGIN.
|
||||
* X and Y will be adjusted according to operational requirements.
|
||||
* Rest API returns the result of checking prerequisites. You could get the real status of margin mode change by subscribing margin mode.
|
||||
*/
|
||||
setMarginMode(
|
||||
newMarginMode: 'REGULAR_MARGIN' | 'PORTFOLIO_MARGIN',
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/private/asset/account/setMarginMode',
|
||||
{ setMarginMode: newMarginMode },
|
||||
);
|
||||
}
|
||||
|
||||
/** Query margin mode for USDC account. */
|
||||
getMarginMode(): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-margin-info',
|
||||
);
|
||||
}
|
||||
|
||||
/** -> Positions API */
|
||||
|
||||
/** Query my positions */
|
||||
getPositions(params: USDCPositionsRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-position',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Query Delivery History */
|
||||
getDeliveryHistory(
|
||||
params: USDCOptionsDeliveryHistoryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-delivery-list',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Query Positions Info Upon Expiry */
|
||||
getPositionsInfoUponExpiry(
|
||||
params?: USDCOptionsPositionsInfoExpiryRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-position-exp-date',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** -> Market Maker Protection */
|
||||
|
||||
/** modifyMMP */
|
||||
modifyMMP(params: USDCOptionsModifyMMPRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/mmp-modify',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** resetMMP */
|
||||
resetMMP(currency: string): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/option/usdc/openapi/private/v1/mmp-reset', {
|
||||
currency,
|
||||
});
|
||||
}
|
||||
|
||||
/** queryMMPState */
|
||||
queryMMPState(baseCoin: string): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/option/usdc/openapi/private/v1/get-mmp-state', {
|
||||
baseCoin,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* API Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getServerTime(): Promise<APIResponseWithTime> {
|
||||
return this.get('/v2/public/time');
|
||||
}
|
||||
}
|
||||
@@ -1,320 +0,0 @@
|
||||
/* eslint-disable max-len */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
APIResponseV3,
|
||||
APIResponseWithTime,
|
||||
SymbolLimitParam,
|
||||
SymbolPeriodLimitParam,
|
||||
USDCKlineRequest,
|
||||
USDCLast500TradesRequest,
|
||||
USDCOpenInterestRequest,
|
||||
USDCOrderFilter,
|
||||
USDCPerpActiveOrdersRequest,
|
||||
USDCPerpCancelOrderRequest,
|
||||
USDCPerpHistoricOrdersRequest,
|
||||
USDCPerpModifyOrderRequest,
|
||||
USDCPerpOrderRequest,
|
||||
USDCPositionsRequest,
|
||||
USDCSymbolDirectionLimit,
|
||||
USDCSymbolDirectionLimitCursor,
|
||||
USDCTransactionLogRequest,
|
||||
} from './types';
|
||||
import { REST_CLIENT_TYPE_ENUM } from './util';
|
||||
import BaseRestClient from './util/BaseRestClient';
|
||||
|
||||
/**
|
||||
* REST API client for USDC Perpetual APIs
|
||||
*
|
||||
* @deprecated WARNING: V1/V2 private endpoints (Rest API & Websocket Stream) for mainnet
|
||||
* will be switched off gradually from 30 Oct 2023 UTC, so they are not promised a stability.
|
||||
* Please note that you are at your own risk of using old endpoints going forward, and please move to V5 ASAP.
|
||||
*/
|
||||
export class USDCPerpetualClient extends BaseRestClient {
|
||||
getClientType() {
|
||||
// Follows the same authentication mechanism as other v3 APIs (e.g. USDC)
|
||||
return REST_CLIENT_TYPE_ENUM.v3;
|
||||
}
|
||||
|
||||
async fetchServerTime(): Promise<number> {
|
||||
const res = await this.getServerTime();
|
||||
return Number(res.time_now);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Market Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getOrderBook(symbol: string): Promise<APIResponseV3<any>> {
|
||||
return this.get('/perpetual/usdc/openapi/public/v1/order-book', { symbol });
|
||||
}
|
||||
|
||||
/** Fetch trading rules (such as min/max qty). Query for all if blank. */
|
||||
getContractInfo(
|
||||
params?: USDCSymbolDirectionLimit,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/perpetual/usdc/openapi/public/v1/symbols', params);
|
||||
}
|
||||
|
||||
/** Get a symbol price/statistics ticker */
|
||||
getSymbolTicker(symbol: string): Promise<APIResponseV3<any>> {
|
||||
return this.get('/perpetual/usdc/openapi/public/v1/tick', { symbol });
|
||||
}
|
||||
|
||||
getCandles(params: USDCKlineRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get('/perpetual/usdc/openapi/public/v1/kline/list', params);
|
||||
}
|
||||
|
||||
getMarkPrice(params: USDCKlineRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get(
|
||||
'/perpetual/usdc/openapi/public/v1/mark-price-kline',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getIndexPrice(params: USDCKlineRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get(
|
||||
'/perpetual/usdc/openapi/public/v1/index-price-kline',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getIndexPremium(params: USDCKlineRequest): Promise<APIResponseV3<any>> {
|
||||
return this.get(
|
||||
'/perpetual/usdc/openapi/public/v1/premium-index-kline',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
getOpenInterest(
|
||||
params: USDCOpenInterestRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/perpetual/usdc/openapi/public/v1/open-interest', params);
|
||||
}
|
||||
|
||||
getLargeOrders(
|
||||
params: SymbolLimitParam<string>,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/perpetual/usdc/openapi/public/v1/big-deal', params);
|
||||
}
|
||||
|
||||
getLongShortRatio(
|
||||
params: SymbolPeriodLimitParam<string>,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get('/perpetual/usdc/openapi/public/v1/account-ratio', params);
|
||||
}
|
||||
|
||||
getLast500Trades(
|
||||
params: USDCLast500TradesRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.get(
|
||||
'/option/usdc/openapi/public/v1/query-trade-latest',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Account Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
/** -> Order API */
|
||||
|
||||
/**
|
||||
* Place an order using the USDC Derivatives Account.
|
||||
* The request status can be queried in real-time.
|
||||
* The response parameters must be queried through a query or a WebSocket response.
|
||||
*/
|
||||
submitOrder(params: USDCPerpOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/perpetual/usdc/openapi/private/v1/place-order',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Active order parameters (such as quantity, price) and stop order parameters cannot be modified in one request at the same time.
|
||||
* Please request modification separately.
|
||||
*/
|
||||
modifyOrder(params: USDCPerpModifyOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/perpetual/usdc/openapi/private/v1/replace-order',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Cancel order */
|
||||
cancelOrder(params: USDCPerpCancelOrderRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/perpetual/usdc/openapi/private/v1/cancel-order',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Cancel all active orders. The real-time response indicates whether the request is successful, depending on retCode. */
|
||||
cancelActiveOrders(
|
||||
symbol: string,
|
||||
orderFilter: USDCOrderFilter,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate('/perpetual/usdc/openapi/private/v1/cancel-all', {
|
||||
symbol,
|
||||
orderFilter,
|
||||
});
|
||||
}
|
||||
|
||||
/** Query Unfilled/Partially Filled Orders */
|
||||
getActiveOrders(
|
||||
params: USDCPerpActiveOrdersRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-active-orders',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Query order history. The endpoint only supports up to 30 days of queried records */
|
||||
getHistoricOrders(
|
||||
params: USDCPerpHistoricOrdersRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-order-history',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Query trade history. The endpoint only supports up to 30 days of queried records. An error will be returned if startTime is more than 30 days. */
|
||||
getOrderExecutionHistory(
|
||||
params: USDCPerpActiveOrdersRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/execution-list',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** -> Account API */
|
||||
|
||||
/** The endpoint only supports up to 30 days of queried records. An error will be returned if startTime is more than 30 days. */
|
||||
getTransactionLog(
|
||||
params: USDCTransactionLogRequest,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-transaction-log',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Wallet info for USDC account. */
|
||||
getBalances(): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-wallet-balance',
|
||||
);
|
||||
}
|
||||
|
||||
/** Asset Info */
|
||||
getAssetInfo(baseCoin?: string): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-asset-info',
|
||||
{ baseCoin },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If USDC derivatives account balance is greater than X, you can open PORTFOLIO_MARGIN,
|
||||
* and if it is less than Y, it will automatically close PORTFOLIO_MARGIN and change back to REGULAR_MARGIN.
|
||||
* X and Y will be adjusted according to operational requirements.
|
||||
* Rest API returns the result of checking prerequisites. You could get the real status of margin mode change by subscribing margin mode.
|
||||
*/
|
||||
setMarginMode(
|
||||
newMarginMode: 'REGULAR_MARGIN' | 'PORTFOLIO_MARGIN',
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/private/asset/account/setMarginMode',
|
||||
{ setMarginMode: newMarginMode },
|
||||
);
|
||||
}
|
||||
|
||||
/** Query margin mode for USDC account. */
|
||||
getMarginMode(): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-margin-info',
|
||||
);
|
||||
}
|
||||
|
||||
/** -> Positions API */
|
||||
|
||||
/** Query my positions */
|
||||
getPositions(params: USDCPositionsRequest): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/query-position',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** Only for REGULAR_MARGIN */
|
||||
setLeverage(symbol: string, leverage: string): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/perpetual/usdc/openapi/private/v1/position/leverage/save',
|
||||
{ symbol, leverage },
|
||||
);
|
||||
}
|
||||
|
||||
/** Query Settlement History */
|
||||
getSettlementHistory(
|
||||
params?: USDCSymbolDirectionLimitCursor,
|
||||
): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/option/usdc/openapi/private/v1/session-settlement',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
/** -> Risk Limit API */
|
||||
|
||||
/** Query risk limit */
|
||||
getRiskLimit(symbol: string): Promise<APIResponseV3<any>> {
|
||||
return this.getPrivate(
|
||||
'/perpetual/usdc/openapi/public/v1/risk-limit/list',
|
||||
{
|
||||
symbol,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** Set risk limit */
|
||||
setRiskLimit(symbol: string, riskId: number): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/perpetual/usdc/openapi/private/v1/position/set-risk-limit',
|
||||
{ symbol, riskId },
|
||||
);
|
||||
}
|
||||
|
||||
/** -> Funding API */
|
||||
|
||||
/** Funding settlement occurs every 8 hours at 00:00 UTC, 08:00 UTC and 16:00 UTC. The current interval's fund fee settlement is based on the previous interval's fund rate. For example, at 16:00, the settlement is based on the fund rate generated at 8:00. The fund rate generated at 16:00 will be used at 0:00 the next day. */
|
||||
getLastFundingRate(symbol: string): Promise<APIResponseV3<any>> {
|
||||
return this.get('/perpetual/usdc/openapi/public/v1/prev-funding-rate', {
|
||||
symbol,
|
||||
});
|
||||
}
|
||||
|
||||
/** Get predicted funding rate and my predicted funding fee */
|
||||
getPredictedFundingRate(symbol: string): Promise<APIResponseV3<any>> {
|
||||
return this.postPrivate(
|
||||
'/perpetual/usdc/openapi/private/v1/predicted-funding',
|
||||
{ symbol },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* API Data Endpoints
|
||||
*
|
||||
*/
|
||||
|
||||
getServerTime(): Promise<APIResponseWithTime> {
|
||||
return this.get('/v2/public/time');
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import https from 'https';
|
||||
|
||||
import {
|
||||
APIID,
|
||||
REST_CLIENT_TYPE_ENUM,
|
||||
RestClientOptions,
|
||||
RestClientType,
|
||||
getRestBaseUrl,
|
||||
@@ -51,8 +50,6 @@ interface SignedRequestContext {
|
||||
timestamp?: number;
|
||||
api_key?: string;
|
||||
recv_window?: number;
|
||||
// spot v1 is diff from the rest...
|
||||
recvWindow?: number;
|
||||
}
|
||||
|
||||
interface SignedRequest<T> {
|
||||
@@ -72,7 +69,7 @@ interface UnsignedRequest<T> {
|
||||
recvWindow?: number;
|
||||
}
|
||||
|
||||
type SignMethod = 'v2auth' | 'v5auth';
|
||||
type SignMethod = 'v5auth';
|
||||
|
||||
export default abstract class BaseRestClient {
|
||||
private timeOffset: number | null = null;
|
||||
@@ -164,10 +161,6 @@ export default abstract class BaseRestClient {
|
||||
}
|
||||
}
|
||||
|
||||
private isSpotV1Client() {
|
||||
return this.clientType === REST_CLIENT_TYPE_ENUM.spot;
|
||||
}
|
||||
|
||||
get(endpoint: string, params?: any) {
|
||||
return this._call('GET', endpoint, params, true);
|
||||
}
|
||||
@@ -263,56 +256,34 @@ export default abstract class BaseRestClient {
|
||||
};
|
||||
}
|
||||
|
||||
// USDC endpoints, unified margin and a few others use a different way of authenticating requests (headers instead of params)
|
||||
if (this.clientType === REST_CLIENT_TYPE_ENUM.v3) {
|
||||
const signResult = await this.prepareSignParams(
|
||||
method,
|
||||
'v5auth',
|
||||
params,
|
||||
isPublicApi,
|
||||
);
|
||||
|
||||
const headers: AxiosRequestConfig['headers'] = {
|
||||
'X-BAPI-SIGN-TYPE': 2,
|
||||
'X-BAPI-API-KEY': this.key,
|
||||
'X-BAPI-TIMESTAMP': signResult.timestamp,
|
||||
'X-BAPI-SIGN': signResult.sign,
|
||||
'X-BAPI-RECV-WINDOW': signResult.recvWindow,
|
||||
...options.headers,
|
||||
};
|
||||
|
||||
if (method === 'GET') {
|
||||
return {
|
||||
...options,
|
||||
headers,
|
||||
params: signResult.originalParams,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...options,
|
||||
headers,
|
||||
data: signResult.originalParams,
|
||||
};
|
||||
}
|
||||
|
||||
const signResult = await this.prepareSignParams(
|
||||
method,
|
||||
'v2auth',
|
||||
'v5auth',
|
||||
params,
|
||||
isPublicApi,
|
||||
);
|
||||
|
||||
if (method === 'GET' || this.isSpotV1Client()) {
|
||||
const headers: AxiosRequestConfig['headers'] = {
|
||||
'X-BAPI-SIGN-TYPE': 2,
|
||||
'X-BAPI-API-KEY': this.key,
|
||||
'X-BAPI-TIMESTAMP': signResult.timestamp,
|
||||
'X-BAPI-SIGN': signResult.sign,
|
||||
'X-BAPI-RECV-WINDOW': signResult.recvWindow,
|
||||
...options.headers,
|
||||
};
|
||||
|
||||
if (method === 'GET') {
|
||||
return {
|
||||
...options,
|
||||
params: signResult.paramsWithSign,
|
||||
headers,
|
||||
params: signResult.originalParams,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...options,
|
||||
data: signResult.paramsWithSign,
|
||||
headers,
|
||||
data: signResult.originalParams,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -469,44 +440,6 @@ export default abstract class BaseRestClient {
|
||||
return res;
|
||||
}
|
||||
|
||||
// spot/v2 derivatives
|
||||
if (signMethod === 'v2auth') {
|
||||
res.originalParams.api_key = key;
|
||||
res.originalParams.timestamp = timestamp;
|
||||
|
||||
// Optional, set to 5000 by default. Increase if timestamp/recv_window errors are seen.
|
||||
if (recvWindow) {
|
||||
if (this.isSpotV1Client()) {
|
||||
res.originalParams.recvWindow = recvWindow;
|
||||
} else {
|
||||
res.originalParams.recv_window = recvWindow;
|
||||
}
|
||||
}
|
||||
const sortProperties = true;
|
||||
const encodeValues = false;
|
||||
|
||||
res.serializedParams = serializeParams(
|
||||
res.originalParams,
|
||||
strictParamValidation,
|
||||
sortProperties,
|
||||
encodeValues,
|
||||
);
|
||||
res.sign = await this.signMessage(
|
||||
res.serializedParams,
|
||||
this.secret,
|
||||
'hex',
|
||||
'SHA-256',
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
res.paramsWithSign = {
|
||||
...res.originalParams,
|
||||
sign: res.sign,
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ import {
|
||||
} from './websockets';
|
||||
import { WsOperation } from '../types/websockets/ws-api';
|
||||
|
||||
type UseTheExceptionEventInstead = never;
|
||||
|
||||
interface WSClientEventMap<WsKey extends string> {
|
||||
/** Connection opened. If this connection was previously opened and reconnected, expect the reconnected event instead */
|
||||
open: (evt: { wsKey: WsKey; event: any }) => void;
|
||||
@@ -38,8 +40,17 @@ interface WSClientEventMap<WsKey extends string> {
|
||||
) => void;
|
||||
/** Received data for topic */
|
||||
update: (response: any & { wsKey: WsKey }) => void;
|
||||
/** Exception from ws client OR custom listeners (e.g. if you throw inside your event handler) */
|
||||
error: (response: any & { wsKey: WsKey; isWSAPIResponse?: boolean }) => void;
|
||||
/**
|
||||
* See for more information: https://github.com/tiagosiebler/bybit-api/issues/413
|
||||
* @deprecated Use the 'exception' event instead. The 'error' event had the unintended consequence of throwing an unhandled promise rejection.
|
||||
*/
|
||||
error: UseTheExceptionEventInstead;
|
||||
/**
|
||||
* Exception from ws client OR custom listeners (e.g. if you throw inside your event handler)
|
||||
*/
|
||||
exception: (
|
||||
response: any & { wsKey: WsKey; isWSAPIResponse?: boolean },
|
||||
) => void;
|
||||
/** Confirmation that a connection successfully authenticated */
|
||||
authenticated: (event: {
|
||||
wsKey: WsKey;
|
||||
@@ -48,12 +59,6 @@ interface WSClientEventMap<WsKey extends string> {
|
||||
}) => void;
|
||||
}
|
||||
|
||||
export interface EmittableEvent<TEvent = any> {
|
||||
eventType: 'response' | 'update' | 'error' | 'authenticated';
|
||||
event: TEvent;
|
||||
isWSAPIResponse?: boolean;
|
||||
}
|
||||
|
||||
// Type safety for on and emit handlers: https://stackoverflow.com/a/61609010/880837
|
||||
export interface BaseWebsocketClient<
|
||||
TWSKey extends string,
|
||||
@@ -71,13 +76,11 @@ export interface BaseWebsocketClient<
|
||||
): boolean;
|
||||
}
|
||||
|
||||
// interface TopicsPendingSubscriptions {
|
||||
// wsKey: string;
|
||||
// failedTopicsSubscriptions: Set<string>;
|
||||
// pendingTopicsSubscriptions: Set<string>;
|
||||
// resolver: TopicsPendingSubscriptionsResolver;
|
||||
// rejector: TopicsPendingSubscriptionsRejector;
|
||||
// }
|
||||
export interface EmittableEvent<TEvent = any> {
|
||||
eventType: 'response' | 'update' | 'exception' | 'authenticated';
|
||||
event: TEvent;
|
||||
isWSAPIResponse?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A midflight WS request event (e.g. subscribe to these topics).
|
||||
@@ -160,16 +163,17 @@ export abstract class BaseWebsocketClient<
|
||||
reconnectTimeout: 500,
|
||||
recvWindow: 5000,
|
||||
|
||||
// Calls to subscribeV5() are wrapped in a promise, allowing you to await a subscription request.
|
||||
// Note: due to internal complexity, it's only recommended if you connect before subscribing.
|
||||
promiseSubscribeRequests: false,
|
||||
|
||||
// Automatically send an authentication op/request after a connection opens, for private connections.
|
||||
authPrivateConnectionsOnConnect: true,
|
||||
// Individual requests do not require a signature, so this is disabled.
|
||||
authPrivateRequests: false,
|
||||
|
||||
...options,
|
||||
};
|
||||
|
||||
// add default error handling so this doesn't crash node (if the user didn't set a handler)
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
this.on('error', () => {});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,6 +310,9 @@ export abstract class BaseWebsocketClient<
|
||||
|
||||
for (const requestKey in pendingSubReqs) {
|
||||
const request = pendingSubReqs[requestKey];
|
||||
this.logger.trace(
|
||||
`clearTopicsPendingSubscriptions(${wsKey}, ${rejectAll}, ${rejectReason}, ${requestKey}): rejecting promise for: ${JSON.stringify(request?.requestData || {})}`,
|
||||
);
|
||||
request?.rejector(request.requestData, rejectReason);
|
||||
}
|
||||
}
|
||||
@@ -339,10 +346,18 @@ export abstract class BaseWebsocketClient<
|
||||
pendingSubscriptionRequest.requestData,
|
||||
);
|
||||
} else {
|
||||
pendingSubscriptionRequest.rejector(
|
||||
pendingSubscriptionRequest.requestData,
|
||||
this.logger.trace(
|
||||
`updatePendingTopicSubscriptionStatus.reject(${wsKey}, ${requestKey}, ${msg}, ${isTopicSubscriptionSuccessEvent}): `,
|
||||
msg,
|
||||
);
|
||||
try {
|
||||
pendingSubscriptionRequest.rejector(
|
||||
pendingSubscriptionRequest.requestData,
|
||||
msg,
|
||||
);
|
||||
} catch (e) {
|
||||
console.error('Exception rejecting promise: ', e);
|
||||
}
|
||||
}
|
||||
|
||||
this.removeTopicPendingSubscription(wsKey, requestKey);
|
||||
@@ -582,7 +597,7 @@ export abstract class BaseWebsocketClient<
|
||||
if (!error.message) {
|
||||
this.logger.error(`${context} due to unexpected error: `, error);
|
||||
this.emit('response', { ...error, wsKey });
|
||||
this.emit('error', { ...error, wsKey });
|
||||
this.emit('exception', { ...error, wsKey });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -614,8 +629,10 @@ export abstract class BaseWebsocketClient<
|
||||
break;
|
||||
}
|
||||
|
||||
this.logger.error(`parseWsError(${context}, ${error}, ${wsKey}) `, error);
|
||||
|
||||
this.emit('response', { ...error, wsKey });
|
||||
this.emit('error', { ...error, wsKey });
|
||||
this.emit('exception', { ...error, wsKey });
|
||||
}
|
||||
|
||||
/** Get a signature, build the auth request and send it */
|
||||
@@ -845,9 +862,11 @@ export abstract class BaseWebsocketClient<
|
||||
for (const midflightRequest of subscribeWsMessages) {
|
||||
const wsMessage = midflightRequest.requestEvent;
|
||||
|
||||
promises.push(
|
||||
this.upsertPendingTopicSubscribeRequests(wsKey, midflightRequest),
|
||||
);
|
||||
if (this.options.promiseSubscribeRequests) {
|
||||
promises.push(
|
||||
this.upsertPendingTopicSubscribeRequests(wsKey, midflightRequest),
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.trace(
|
||||
`Sending batch via message: "${JSON.stringify(wsMessage)}"`,
|
||||
@@ -890,9 +909,11 @@ export abstract class BaseWebsocketClient<
|
||||
for (const midflightRequest of subscribeWsMessages) {
|
||||
const wsMessage = midflightRequest.requestEvent;
|
||||
|
||||
promises.push(
|
||||
this.upsertPendingTopicSubscribeRequests(wsKey, midflightRequest),
|
||||
);
|
||||
if (this.options.promiseSubscribeRequests) {
|
||||
promises.push(
|
||||
this.upsertPendingTopicSubscribeRequests(wsKey, midflightRequest),
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.trace(`Sending batch via message: "${wsMessage}"`);
|
||||
this.tryWsSend(wsKey, JSON.stringify(wsMessage));
|
||||
@@ -908,7 +929,11 @@ export abstract class BaseWebsocketClient<
|
||||
/**
|
||||
* Try sending a string event on a WS connection (identified by the WS Key)
|
||||
*/
|
||||
public tryWsSend(wsKey: TWSKey, wsMessage: string) {
|
||||
public tryWsSend(
|
||||
wsKey: TWSKey,
|
||||
wsMessage: string,
|
||||
throwExceptions?: boolean,
|
||||
) {
|
||||
try {
|
||||
this.logger.trace('Sending upstream ws message: ', {
|
||||
...WS_LOGGER_CATEGORY,
|
||||
@@ -934,6 +959,9 @@ export abstract class BaseWebsocketClient<
|
||||
wsKey,
|
||||
exception: e,
|
||||
});
|
||||
if (throwExceptions) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -988,6 +1016,7 @@ export abstract class BaseWebsocketClient<
|
||||
} catch (e) {
|
||||
this.logger.error(
|
||||
'Exception trying to resolve "connectionInProgress" promise',
|
||||
e,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1001,12 +1030,28 @@ export abstract class BaseWebsocketClient<
|
||||
);
|
||||
|
||||
// Request sub to public topics, if any
|
||||
this.requestSubscribeTopics(wsKey, publicReqs);
|
||||
try {
|
||||
await this.requestSubscribeTopics(wsKey, publicReqs);
|
||||
} catch (e) {
|
||||
this.logger.error(
|
||||
`onWsOpen(): exception in public requestSubscribeTopics(${wsKey}): `,
|
||||
publicReqs,
|
||||
e,
|
||||
);
|
||||
}
|
||||
|
||||
// Request sub to private topics, if auth on connect isn't needed
|
||||
// Else, this is automatic after authentication is successfully confirmed
|
||||
if (!this.options.authPrivateConnectionsOnConnect) {
|
||||
this.requestSubscribeTopics(wsKey, privateReqs);
|
||||
try {
|
||||
this.requestSubscribeTopics(wsKey, privateReqs);
|
||||
} catch (e) {
|
||||
this.logger.error(
|
||||
`onWsOpen(): exception in private requestSubscribeTopics(${wsKey}: `,
|
||||
privateReqs,
|
||||
e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Some websockets require an auth packet to be sent after opening the connection
|
||||
@@ -1041,6 +1086,7 @@ export abstract class BaseWebsocketClient<
|
||||
} catch (e) {
|
||||
this.logger.error(
|
||||
'Exception trying to resolve "connectionInProgress" promise',
|
||||
e,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1107,10 +1153,6 @@ export abstract class BaseWebsocketClient<
|
||||
}
|
||||
|
||||
for (const emittable of emittableEvents) {
|
||||
// if (emittable.event?.op) {
|
||||
// console.log('emittable: ', emittable);
|
||||
// }
|
||||
|
||||
if (this.isWsPong(emittable)) {
|
||||
this.logger.trace('Received pong2', {
|
||||
...WS_LOGGER_CATEGORY,
|
||||
@@ -1136,7 +1178,22 @@ export abstract class BaseWebsocketClient<
|
||||
continue;
|
||||
}
|
||||
|
||||
this.emit(emittable.eventType, emittableFinalEvent);
|
||||
// this.logger.trace(
|
||||
// `onWsMessage().emit(${emittable.eventType})`,
|
||||
// emittableFinalEvent,
|
||||
// );
|
||||
try {
|
||||
this.emit(emittable.eventType, emittableFinalEvent);
|
||||
} catch (e) {
|
||||
this.logger.error(
|
||||
`Exception in onWsMessage().emit(${emittable.eventType}) handler:`,
|
||||
e,
|
||||
);
|
||||
}
|
||||
// this.logger.trace(
|
||||
// `onWsMessage().emit(${emittable.eventType}).done()`,
|
||||
// emittableFinalEvent,
|
||||
// );
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -1173,6 +1230,9 @@ export abstract class BaseWebsocketClient<
|
||||
if (
|
||||
this.wsStore.getConnectionState(wsKey) !== WsConnectionStateEnum.CLOSING
|
||||
) {
|
||||
this.logger.trace(
|
||||
`onWsClose(${wsKey}): rejecting all deferred promises...`,
|
||||
);
|
||||
// clean up any pending promises for this connection
|
||||
this.getWsStore().rejectAllDeferredPromises(
|
||||
wsKey,
|
||||
@@ -1187,6 +1247,9 @@ export abstract class BaseWebsocketClient<
|
||||
this.emit('reconnect', { wsKey, event });
|
||||
} else {
|
||||
// clean up any pending promises for this connection
|
||||
this.logger.trace(
|
||||
`onWsClose(${wsKey}): rejecting all deferred promises...`,
|
||||
);
|
||||
this.getWsStore().rejectAllDeferredPromises(wsKey, 'disconnected');
|
||||
this.setWsState(wsKey, WsConnectionStateEnum.INITIAL);
|
||||
this.emit('close', { wsKey, event });
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { APIRateLimit } from '../types';
|
||||
import {
|
||||
WebsocketSucceededTopicSubscriptionConfirmationEvent,
|
||||
WebsocketTopicSubscriptionConfirmationEvent,
|
||||
} from '../types/websockets/ws-confirmations';
|
||||
import { WSAPIResponse, WS_API_Operations } from '../types/websockets/ws-api';
|
||||
|
||||
export interface RestClientOptions {
|
||||
/** Your API key */
|
||||
@@ -188,58 +183,13 @@ export function isWsPong(msg: any): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
export function isTopicSubscriptionConfirmation(
|
||||
msg: unknown,
|
||||
): msg is WebsocketTopicSubscriptionConfirmationEvent {
|
||||
if (typeof msg !== 'object') {
|
||||
return false;
|
||||
}
|
||||
if (!msg) {
|
||||
return false;
|
||||
}
|
||||
if (typeof msg['op'] !== 'string') {
|
||||
return false;
|
||||
}
|
||||
if (msg['op'] !== 'subscribe') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isWSAPIResponse(
|
||||
msg: unknown,
|
||||
): msg is Omit<WSAPIResponse, 'wsKey'> {
|
||||
if (typeof msg !== 'object' || !msg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof msg['op'] !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (WS_API_Operations as string[]).includes(msg['op']);
|
||||
}
|
||||
|
||||
export function isTopicSubscriptionSuccess(
|
||||
msg: unknown,
|
||||
): msg is WebsocketSucceededTopicSubscriptionConfirmationEvent {
|
||||
if (!isTopicSubscriptionConfirmation(msg)) return false;
|
||||
return msg.success === true;
|
||||
}
|
||||
|
||||
export const APIID = 'bybitapinode';
|
||||
|
||||
/**
|
||||
* Used to switch how authentication/requests work under the hood (primarily for SPOT since it's different there)
|
||||
*/
|
||||
export const REST_CLIENT_TYPE_ENUM = {
|
||||
accountAsset: 'accountAsset',
|
||||
inverse: 'inverse',
|
||||
inverseFutures: 'inverseFutures',
|
||||
linear: 'linear',
|
||||
spot: 'spot',
|
||||
v3: 'v3',
|
||||
v5: 'v5',
|
||||
} as const;
|
||||
|
||||
export type RestClientType =
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
* Use type guards to narrow down types with minimal efforts.
|
||||
*/
|
||||
|
||||
import {
|
||||
WebsocketSucceededTopicSubscriptionConfirmationEvent,
|
||||
WebsocketTopicSubscriptionConfirmationEvent,
|
||||
} from '../types';
|
||||
import { WSAPIResponse, WS_API_Operations } from '../types/websockets/ws-api';
|
||||
import {
|
||||
WSAccountOrderEventV5,
|
||||
WSExecutionEventV5,
|
||||
@@ -92,3 +97,47 @@ export function isWsExecutionEventV5(
|
||||
|
||||
return event['topic'] === 'execution';
|
||||
}
|
||||
|
||||
export function neverGuard(x: never, msg: string): Error {
|
||||
return new Error(`Unhandled value exception "${x}", ${msg}`);
|
||||
}
|
||||
|
||||
export function isWSAPIResponse(
|
||||
msg: unknown,
|
||||
): msg is Omit<WSAPIResponse, 'wsKey'> {
|
||||
if (typeof msg !== 'object' || !msg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof msg['op'] !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (WS_API_Operations as string[]).includes(msg['op']);
|
||||
}
|
||||
|
||||
export function isTopicSubscriptionSuccess(
|
||||
msg: unknown,
|
||||
): msg is WebsocketSucceededTopicSubscriptionConfirmationEvent {
|
||||
if (!isTopicSubscriptionConfirmation(msg)) return false;
|
||||
return msg.success === true;
|
||||
}
|
||||
|
||||
export function isTopicSubscriptionConfirmation(
|
||||
msg: unknown,
|
||||
): msg is WebsocketTopicSubscriptionConfirmationEvent {
|
||||
if (typeof msg !== 'object') {
|
||||
return false;
|
||||
}
|
||||
if (!msg) {
|
||||
return false;
|
||||
}
|
||||
if (typeof msg['op'] !== 'string') {
|
||||
return false;
|
||||
}
|
||||
if (msg['op'] !== 'subscribe') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { neverGuard } from './websockets';
|
||||
import { neverGuard } from './typeGuards';
|
||||
|
||||
function bufferToB64(buffer: ArrayBuffer): string {
|
||||
let binary = '';
|
||||
|
||||
@@ -205,6 +205,9 @@ export class WsStore<
|
||||
const promise = this.getDeferredPromise(wsKey, promiseRef);
|
||||
|
||||
if (promise?.reject) {
|
||||
this.logger.trace(
|
||||
`rejectDeferredPromise(): rejecting ${wsKey}/${promiseRef}/${value}`,
|
||||
);
|
||||
promise.reject(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,33 +4,16 @@ import {
|
||||
CategoryV5,
|
||||
WebsocketClientOptions,
|
||||
WsKey,
|
||||
WsTopic,
|
||||
} from '../../types';
|
||||
|
||||
import { DefaultLogger } from '../logger';
|
||||
import { WSAPIRequest } from '../../types/websockets/ws-api';
|
||||
import { neverGuard } from '../typeGuards';
|
||||
|
||||
export const WS_LOGGER_CATEGORY = { category: 'bybit-ws' };
|
||||
|
||||
export const WS_KEY_MAP = {
|
||||
inverse: 'inverse',
|
||||
linearPrivate: 'linearPrivate',
|
||||
linearPublic: 'linearPublic',
|
||||
spotPrivate: 'spotPrivate',
|
||||
spotPublic: 'spotPublic',
|
||||
spotV3Private: 'spotV3Private',
|
||||
spotV3Public: 'spotV3Public',
|
||||
usdcOptionPrivate: 'usdcOptionPrivate',
|
||||
usdcOptionPublic: 'usdcOptionPublic',
|
||||
usdcPerpPrivate: 'usdcPerpPrivate',
|
||||
usdcPerpPublic: 'usdcPerpPublic',
|
||||
unifiedPrivate: 'unifiedPrivate',
|
||||
unifiedOptionPublic: 'unifiedOptionPublic',
|
||||
unifiedPerpUSDTPublic: 'unifiedPerpUSDTPublic',
|
||||
unifiedPerpUSDCPublic: 'unifiedPerpUSDCPublic',
|
||||
contractUSDTPublic: 'contractUSDTPublic',
|
||||
contractUSDTPrivate: 'contractUSDTPrivate',
|
||||
contractInversePublic: 'contractInversePublic',
|
||||
contractInversePrivate: 'contractInversePrivate',
|
||||
v5SpotPublic: 'v5SpotPublic',
|
||||
v5LinearPublic: 'v5LinearPublic',
|
||||
v5InversePublic: 'v5InversePublic',
|
||||
@@ -43,27 +26,11 @@ export const WS_KEY_MAP = {
|
||||
} as const;
|
||||
|
||||
export const WS_AUTH_ON_CONNECT_KEYS: WsKey[] = [
|
||||
WS_KEY_MAP.spotV3Private,
|
||||
WS_KEY_MAP.usdcOptionPrivate,
|
||||
WS_KEY_MAP.usdcPerpPrivate,
|
||||
WS_KEY_MAP.unifiedPrivate,
|
||||
WS_KEY_MAP.contractUSDTPrivate,
|
||||
WS_KEY_MAP.contractInversePrivate,
|
||||
WS_KEY_MAP.v5Private,
|
||||
WS_KEY_MAP.v5PrivateTrade,
|
||||
];
|
||||
|
||||
export const PUBLIC_WS_KEYS = [
|
||||
WS_KEY_MAP.linearPublic,
|
||||
WS_KEY_MAP.spotPublic,
|
||||
WS_KEY_MAP.spotV3Public,
|
||||
WS_KEY_MAP.usdcOptionPublic,
|
||||
WS_KEY_MAP.usdcPerpPublic,
|
||||
WS_KEY_MAP.unifiedOptionPublic,
|
||||
WS_KEY_MAP.unifiedPerpUSDTPublic,
|
||||
WS_KEY_MAP.unifiedPerpUSDCPublic,
|
||||
WS_KEY_MAP.contractUSDTPublic,
|
||||
WS_KEY_MAP.contractInversePublic,
|
||||
WS_KEY_MAP.v5SpotPublic,
|
||||
WS_KEY_MAP.v5LinearPublic,
|
||||
WS_KEY_MAP.v5InversePublic,
|
||||
@@ -156,8 +123,6 @@ type PublicPrivateNetwork = 'public' | 'private';
|
||||
* For the v5 endpoints, the subscribe/unsubscribe call must specify the category the subscription should route to.
|
||||
*/
|
||||
type PublicOnlyWsKeys =
|
||||
| 'unifiedPerpUSDT'
|
||||
| 'unifiedPerpUSDC'
|
||||
| 'v5SpotPublic'
|
||||
| 'v5LinearPublic'
|
||||
| 'v5InversePublic'
|
||||
@@ -216,126 +181,6 @@ export const WS_BASE_URL_MAP: Record<
|
||||
testnet: 'wss://stream-testnet.bybit.com/v5/public/option',
|
||||
},
|
||||
},
|
||||
inverse: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/realtime',
|
||||
testnet: 'wss://stream-testnet.bybit.com/realtime',
|
||||
},
|
||||
private: {
|
||||
livenet: 'wss://stream.bybit.com/realtime',
|
||||
testnet: 'wss://stream-testnet.bybit.com/realtime',
|
||||
},
|
||||
},
|
||||
linear: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/realtime_public',
|
||||
livenet2: 'wss://stream.bytick.com/realtime_public',
|
||||
testnet: 'wss://stream-testnet.bybit.com/realtime_public',
|
||||
},
|
||||
private: {
|
||||
livenet: 'wss://stream.bybit.com/realtime_private',
|
||||
livenet2: 'wss://stream.bytick.com/realtime_private',
|
||||
testnet: 'wss://stream-testnet.bybit.com/realtime_private',
|
||||
},
|
||||
},
|
||||
spot: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/spot/quote/ws/v1',
|
||||
livenet2: 'wss://stream.bybit.com/spot/quote/ws/v2',
|
||||
testnet: 'wss://stream-testnet.bybit.com/spot/quote/ws/v1',
|
||||
testnet2: 'wss://stream-testnet.bybit.com/spot/quote/ws/v2',
|
||||
},
|
||||
private: {
|
||||
livenet: 'wss://stream.bybit.com/spot/ws',
|
||||
testnet: 'wss://stream-testnet.bybit.com/spot/ws',
|
||||
},
|
||||
},
|
||||
spotv3: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/spot/public/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/spot/public/v3',
|
||||
},
|
||||
private: {
|
||||
livenet: 'wss://stream.bybit.com/spot/private/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/spot/private/v3',
|
||||
},
|
||||
},
|
||||
usdcOption: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/trade/option/usdc/public/v1',
|
||||
livenet2: 'wss://stream.bytick.com/trade/option/usdc/public/v1',
|
||||
testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/public/v1',
|
||||
},
|
||||
private: {
|
||||
livenet: 'wss://stream.bybit.com/trade/option/usdc/private/v1',
|
||||
livenet2: 'wss://stream.bytick.com/trade/option/usdc/private/v1',
|
||||
testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/private/v1',
|
||||
},
|
||||
},
|
||||
usdcPerp: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/perpetual/ws/v1/realtime_public',
|
||||
livenet2: 'wss://stream.bytick.com/perpetual/ws/v1/realtime_public',
|
||||
testnet: 'wss://stream-testnet.bybit.com/perpetual/ws/v1/realtime_public',
|
||||
},
|
||||
private: {
|
||||
livenet: 'wss://stream.bybit.com/trade/option/usdc/private/v1',
|
||||
livenet2: 'wss://stream.bytick.com/trade/option/usdc/private/v1',
|
||||
testnet: 'wss://stream-testnet.bybit.com/trade/option/usdc/private/v1',
|
||||
},
|
||||
},
|
||||
unifiedOption: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/option/usdc/public/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/option/usdc/public/v3',
|
||||
},
|
||||
private: {
|
||||
livenet: 'wss://stream.bybit.com/unified/private/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/unified/private/v3',
|
||||
},
|
||||
},
|
||||
unifiedPerp: {
|
||||
public: {
|
||||
livenet: 'useBaseSpecificEndpoint',
|
||||
testnet: 'useBaseSpecificEndpoint',
|
||||
},
|
||||
private: {
|
||||
livenet: 'wss://stream.bybit.com/unified/private/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/unified/private/v3',
|
||||
},
|
||||
},
|
||||
unifiedPerpUSDT: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/contract/usdt/public/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/contract/usdt/public/v3',
|
||||
},
|
||||
},
|
||||
unifiedPerpUSDC: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/contract/usdc/public/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/contract/usdc/public/v3',
|
||||
},
|
||||
},
|
||||
contractUSDT: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/contract/usdt/public/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/contract/usdt/public/v3',
|
||||
},
|
||||
private: {
|
||||
livenet: 'wss://stream.bybit.com/contract/private/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/contract/private/v3',
|
||||
},
|
||||
},
|
||||
contractInverse: {
|
||||
public: {
|
||||
livenet: 'wss://stream.bybit.com/contract/inverse/public/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/contract/inverse/public/v3',
|
||||
},
|
||||
private: {
|
||||
livenet: 'wss://stream.bybit.com/contract/private/v3',
|
||||
testnet: 'wss://stream-testnet.bybit.com/contract/private/v3',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export function isPrivateWsTopic(topic: string): boolean {
|
||||
@@ -350,68 +195,6 @@ export function getWsKeyForTopic(
|
||||
): WsKey {
|
||||
const isPrivateTopic = isPrivate === true || PRIVATE_TOPICS.includes(topic);
|
||||
switch (market) {
|
||||
case 'inverse': {
|
||||
return WS_KEY_MAP.inverse;
|
||||
}
|
||||
case 'linear': {
|
||||
return isPrivateTopic
|
||||
? WS_KEY_MAP.linearPrivate
|
||||
: WS_KEY_MAP.linearPublic;
|
||||
}
|
||||
case 'spot': {
|
||||
return isPrivateTopic ? WS_KEY_MAP.spotPrivate : WS_KEY_MAP.spotPublic;
|
||||
}
|
||||
case 'spotv3': {
|
||||
return isPrivateTopic
|
||||
? WS_KEY_MAP.spotV3Private
|
||||
: WS_KEY_MAP.spotV3Public;
|
||||
}
|
||||
case 'usdcOption': {
|
||||
return isPrivateTopic
|
||||
? WS_KEY_MAP.usdcOptionPrivate
|
||||
: WS_KEY_MAP.usdcOptionPublic;
|
||||
}
|
||||
case 'usdcPerp': {
|
||||
return isPrivateTopic
|
||||
? WS_KEY_MAP.usdcPerpPrivate
|
||||
: WS_KEY_MAP.usdcPerpPublic;
|
||||
}
|
||||
case 'unifiedOption': {
|
||||
return isPrivateTopic
|
||||
? WS_KEY_MAP.unifiedPrivate
|
||||
: WS_KEY_MAP.unifiedOptionPublic;
|
||||
}
|
||||
case 'unifiedPerp': {
|
||||
if (isPrivateTopic) {
|
||||
return WS_KEY_MAP.unifiedPrivate;
|
||||
}
|
||||
|
||||
const upperTopic = topic.toUpperCase();
|
||||
if (upperTopic.indexOf('USDT') !== -1) {
|
||||
return WS_KEY_MAP.unifiedPerpUSDTPublic;
|
||||
}
|
||||
|
||||
if (
|
||||
upperTopic.indexOf('USDC') !== -1 ||
|
||||
upperTopic.indexOf('PERP') !== -1
|
||||
) {
|
||||
return WS_KEY_MAP.unifiedPerpUSDCPublic;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Failed to determine wskey for unified perps topic: "${topic}"`,
|
||||
);
|
||||
}
|
||||
case 'contractInverse': {
|
||||
return isPrivateTopic
|
||||
? WS_KEY_MAP.contractInversePrivate
|
||||
: WS_KEY_MAP.contractInversePublic;
|
||||
}
|
||||
case 'contractUSDT': {
|
||||
return isPrivateTopic
|
||||
? WS_KEY_MAP.contractUSDTPrivate
|
||||
: WS_KEY_MAP.contractUSDTPublic;
|
||||
}
|
||||
case 'v5': {
|
||||
if (isPrivateTopic) {
|
||||
return WS_KEY_MAP.v5Private;
|
||||
@@ -458,19 +241,23 @@ export function getWsUrl(
|
||||
}
|
||||
|
||||
// https://bybit-exchange.github.io/docs/v5/demo
|
||||
const isDemoTrading = wsClientOptions.demoTrading;
|
||||
if (isDemoTrading) {
|
||||
return 'wss://stream-demo.bybit.com/v5/private';
|
||||
}
|
||||
const DEMO_TRADING_ENDPOINT = 'wss://stream-demo.bybit.com/v5/private';
|
||||
|
||||
const isDemoTrading = wsClientOptions.demoTrading;
|
||||
const isTestnet = wsClientOptions.testnet;
|
||||
const networkKey = isTestnet ? 'testnet' : 'livenet';
|
||||
|
||||
switch (wsKey) {
|
||||
case WS_KEY_MAP.v5Private: {
|
||||
if (isDemoTrading) {
|
||||
return DEMO_TRADING_ENDPOINT;
|
||||
}
|
||||
return WS_BASE_URL_MAP.v5.private[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.v5PrivateTrade: {
|
||||
if (isDemoTrading) {
|
||||
return DEMO_TRADING_ENDPOINT;
|
||||
}
|
||||
return WS_BASE_URL_MAP[wsKey].private[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.v5SpotPublic: {
|
||||
@@ -485,64 +272,6 @@ export function getWsUrl(
|
||||
case WS_KEY_MAP.v5OptionPublic: {
|
||||
return WS_BASE_URL_MAP.v5OptionPublic.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.linearPublic: {
|
||||
return WS_BASE_URL_MAP.linear.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.linearPrivate: {
|
||||
return WS_BASE_URL_MAP.linear.private[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.spotPublic: {
|
||||
return WS_BASE_URL_MAP.spot.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.spotPrivate: {
|
||||
return WS_BASE_URL_MAP.spot.private[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.spotV3Public: {
|
||||
return WS_BASE_URL_MAP.spotv3.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.spotV3Private: {
|
||||
return WS_BASE_URL_MAP.spotv3.private[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.inverse: {
|
||||
// private and public are on the same WS connection
|
||||
return WS_BASE_URL_MAP.inverse.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.usdcOptionPublic: {
|
||||
return WS_BASE_URL_MAP.usdcOption.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.usdcOptionPrivate: {
|
||||
return WS_BASE_URL_MAP.usdcOption.private[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.usdcPerpPublic: {
|
||||
return WS_BASE_URL_MAP.usdcPerp.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.usdcPerpPrivate: {
|
||||
return WS_BASE_URL_MAP.usdcPerp.private[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.unifiedOptionPublic: {
|
||||
return WS_BASE_URL_MAP.unifiedOption.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.unifiedPerpUSDTPublic: {
|
||||
return WS_BASE_URL_MAP.unifiedPerpUSDT.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.unifiedPerpUSDCPublic: {
|
||||
return WS_BASE_URL_MAP.unifiedPerpUSDC.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.unifiedPrivate: {
|
||||
return WS_BASE_URL_MAP.unifiedPerp.private[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.contractInversePrivate: {
|
||||
return WS_BASE_URL_MAP.contractInverse.private[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.contractInversePublic: {
|
||||
return WS_BASE_URL_MAP.contractInverse.public[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.contractUSDTPrivate: {
|
||||
return WS_BASE_URL_MAP.contractUSDT.private[networkKey];
|
||||
}
|
||||
case WS_KEY_MAP.contractUSDTPublic: {
|
||||
return WS_BASE_URL_MAP.contractUSDT.public[networkKey];
|
||||
}
|
||||
default: {
|
||||
logger.error('getWsUrl(): Unhandled wsKey: ', {
|
||||
category: 'bybit-ws',
|
||||
@@ -557,50 +286,19 @@ export function getMaxTopicsPerSubscribeEvent(
|
||||
market: APIMarket,
|
||||
wsKey: WsKey,
|
||||
): number | null {
|
||||
const topicsPerEventSpot = 10;
|
||||
switch (market) {
|
||||
case 'inverse':
|
||||
case 'linear':
|
||||
case 'usdcOption':
|
||||
case 'usdcPerp':
|
||||
case 'unifiedOption':
|
||||
case 'unifiedPerp':
|
||||
case 'spot':
|
||||
case 'contractInverse':
|
||||
case 'contractUSDT':
|
||||
case 'v5': {
|
||||
if (wsKey === WS_KEY_MAP.v5SpotPublic) {
|
||||
return topicsPerEventSpot;
|
||||
return 10;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
case 'spotv3': {
|
||||
return topicsPerEventSpot;
|
||||
}
|
||||
default: {
|
||||
throw neverGuard(market, 'getWsKeyForTopic(): Unhandled market');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getUsdcWsKeyForTopic(
|
||||
topic: string,
|
||||
subGroup: 'option' | 'perp',
|
||||
): WsKey {
|
||||
const isPrivateTopic = PRIVATE_TOPICS.includes(topic);
|
||||
if (subGroup === 'option') {
|
||||
return isPrivateTopic
|
||||
? WS_KEY_MAP.usdcOptionPrivate
|
||||
: WS_KEY_MAP.usdcOptionPublic;
|
||||
}
|
||||
return isPrivateTopic
|
||||
? WS_KEY_MAP.usdcOptionPrivate
|
||||
: WS_KEY_MAP.usdcOptionPublic;
|
||||
// return isPrivateTopic
|
||||
// ? WS_KEY_MAP.usdcPerpPrivate
|
||||
// : WS_KEY_MAP.usdcPerpPublic;
|
||||
}
|
||||
|
||||
export const WS_ERROR_ENUM = {
|
||||
NOT_AUTHENTICATED_SPOT_V3: '-1004',
|
||||
API_ERROR_GENERIC: '10001',
|
||||
@@ -608,10 +306,6 @@ export const WS_ERROR_ENUM = {
|
||||
USDC_OPTION_AUTH_FAILED: '3303006',
|
||||
};
|
||||
|
||||
export function neverGuard(x: never, msg: string): Error {
|
||||
return new Error(`Unhandled value exception "x", ${msg}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* #305: ws.terminate() is undefined in browsers.
|
||||
* This only works in node.js, not in browsers.
|
||||
@@ -660,3 +354,44 @@ export function getNormalisedTopicRequests(
|
||||
}
|
||||
return normalisedTopicRequests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups topics in request into per-wsKey groups
|
||||
* @param normalisedTopicRequests
|
||||
* @param wsKey
|
||||
* @param isPrivateTopic
|
||||
* @returns
|
||||
*/
|
||||
export function getTopicsPerWSKey(
|
||||
market: APIMarket,
|
||||
normalisedTopicRequests: WsTopicRequest[],
|
||||
wsKey?: WsKey,
|
||||
isPrivateTopic?: boolean,
|
||||
): {
|
||||
[key in WsKey]?: WsTopicRequest<WsTopic>[];
|
||||
} {
|
||||
const perWsKeyTopics: { [key in WsKey]?: WsTopicRequest<WsTopic>[] } = {};
|
||||
|
||||
// Sort into per wsKey arrays, in case topics are mixed together for different wsKeys
|
||||
for (const topicRequest of normalisedTopicRequests) {
|
||||
const derivedWsKey =
|
||||
wsKey ||
|
||||
getWsKeyForTopic(
|
||||
market,
|
||||
topicRequest.topic,
|
||||
isPrivateTopic,
|
||||
topicRequest.category,
|
||||
);
|
||||
|
||||
if (
|
||||
!perWsKeyTopics[derivedWsKey] ||
|
||||
!Array.isArray(perWsKeyTopics[derivedWsKey])
|
||||
) {
|
||||
perWsKeyTopics[derivedWsKey] = [];
|
||||
}
|
||||
|
||||
perWsKeyTopics[derivedWsKey]!.push(topicRequest);
|
||||
}
|
||||
|
||||
return perWsKeyTopics;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
|
||||
/* eslint-disable max-len */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import WebSocket from 'isomorphic-ws';
|
||||
|
||||
import {
|
||||
@@ -19,6 +16,7 @@ import {
|
||||
getMaxTopicsPerSubscribeEvent,
|
||||
getNormalisedTopicRequests,
|
||||
getPromiseRefForWSAPIRequest,
|
||||
getTopicsPerWSKey,
|
||||
getWsKeyForTopic,
|
||||
getWsUrl,
|
||||
isPrivateWsTopic,
|
||||
@@ -35,6 +33,7 @@ import {
|
||||
} from './util/BaseWSClient';
|
||||
import {
|
||||
Exact,
|
||||
WSAPIOperation,
|
||||
WSAPIRequest,
|
||||
WsAPIOperationResponseMap,
|
||||
WsAPITopicRequestParamMap,
|
||||
@@ -46,74 +45,18 @@ import { SignAlgorithm, signMessage } from './util/webCryptoAPI';
|
||||
|
||||
const WS_LOGGER_CATEGORY = { category: 'bybit-ws' };
|
||||
|
||||
/**
|
||||
* Groups topics in request into per-wsKey groups
|
||||
* @param normalisedTopicRequests
|
||||
* @param wsKey
|
||||
* @param isPrivateTopic
|
||||
* @returns
|
||||
*/
|
||||
function getTopicsPerWSKey(
|
||||
normalisedTopicRequests: WsTopicRequest[],
|
||||
wsKey?: WsKey,
|
||||
isPrivateTopic?: boolean,
|
||||
): {
|
||||
[key in WsKey]?: WsTopicRequest<WsTopic>[];
|
||||
} {
|
||||
const perWsKeyTopics: { [key in WsKey]?: WsTopicRequest<WsTopic>[] } = {};
|
||||
|
||||
// Sort into per wsKey arrays, in case topics are mixed together for different wsKeys
|
||||
for (const topicRequest of normalisedTopicRequests) {
|
||||
const derivedWsKey =
|
||||
wsKey ||
|
||||
getWsKeyForTopic(
|
||||
this.options.market,
|
||||
topicRequest.topic,
|
||||
isPrivateTopic,
|
||||
topicRequest.category,
|
||||
);
|
||||
|
||||
if (
|
||||
!perWsKeyTopics[derivedWsKey] ||
|
||||
!Array.isArray(perWsKeyTopics[derivedWsKey])
|
||||
) {
|
||||
perWsKeyTopics[derivedWsKey] = [];
|
||||
}
|
||||
|
||||
perWsKeyTopics[derivedWsKey]!.push(topicRequest);
|
||||
}
|
||||
|
||||
return perWsKeyTopics;
|
||||
}
|
||||
|
||||
// export class WebsocketClient extends EventEmitter {
|
||||
export class WebsocketClient extends BaseWebsocketClient<
|
||||
WsKey,
|
||||
WsRequestOperationBybit<WsTopic>
|
||||
> {
|
||||
/**
|
||||
* Request connection of all dependent (public & private) websockets, instead of waiting for automatic connection by library
|
||||
* Request connection of all dependent (public & private) websockets, instead of waiting
|
||||
* for automatic connection by SDK.
|
||||
*/
|
||||
public connectAll(): Promise<WSConnectedResult | undefined>[] {
|
||||
switch (this.options.market) {
|
||||
case 'inverse': {
|
||||
// only one for inverse
|
||||
return [...this.connectPublic()];
|
||||
}
|
||||
// these all have separate public & private ws endpoints
|
||||
case 'linear':
|
||||
case 'spot':
|
||||
case 'spotv3':
|
||||
case 'usdcOption':
|
||||
case 'usdcPerp':
|
||||
case 'unifiedPerp':
|
||||
case 'unifiedOption':
|
||||
case 'contractUSDT':
|
||||
case 'contractInverse': {
|
||||
return [...this.connectPublic(), this.connectPrivate()];
|
||||
}
|
||||
case 'v5': {
|
||||
return [this.connectPrivate()];
|
||||
return [...this.connectPublic(), this.connectPrivate()];
|
||||
}
|
||||
default: {
|
||||
throw neverGuard(this.options.market, 'connectAll(): Unhandled market');
|
||||
@@ -143,37 +86,6 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
this.connect(WS_KEY_MAP.v5OptionPublic),
|
||||
];
|
||||
}
|
||||
case 'inverse': {
|
||||
return [this.connect(WS_KEY_MAP.inverse)];
|
||||
}
|
||||
case 'linear': {
|
||||
return [this.connect(WS_KEY_MAP.linearPublic)];
|
||||
}
|
||||
case 'spot': {
|
||||
return [this.connect(WS_KEY_MAP.spotPublic)];
|
||||
}
|
||||
case 'spotv3': {
|
||||
return [this.connect(WS_KEY_MAP.spotV3Public)];
|
||||
}
|
||||
case 'usdcOption': {
|
||||
return [this.connect(WS_KEY_MAP.usdcOptionPublic)];
|
||||
}
|
||||
case 'usdcPerp': {
|
||||
return [this.connect(WS_KEY_MAP.usdcPerpPublic)];
|
||||
}
|
||||
case 'unifiedOption': {
|
||||
return [this.connect(WS_KEY_MAP.unifiedOptionPublic)];
|
||||
}
|
||||
case 'unifiedPerp': {
|
||||
return [
|
||||
this.connect(WS_KEY_MAP.unifiedPerpUSDTPublic),
|
||||
this.connect(WS_KEY_MAP.unifiedPerpUSDCPublic),
|
||||
];
|
||||
}
|
||||
case 'contractUSDT':
|
||||
return [this.connect(WS_KEY_MAP.contractUSDTPublic)];
|
||||
case 'contractInverse':
|
||||
return [this.connect(WS_KEY_MAP.contractInversePublic)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,41 +95,16 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
default: {
|
||||
return this.connect(WS_KEY_MAP.v5Private);
|
||||
}
|
||||
case 'inverse': {
|
||||
return this.connect(WS_KEY_MAP.inverse);
|
||||
}
|
||||
case 'linear': {
|
||||
return this.connect(WS_KEY_MAP.linearPrivate);
|
||||
}
|
||||
case 'spot': {
|
||||
return this.connect(WS_KEY_MAP.spotPrivate);
|
||||
}
|
||||
case 'spotv3': {
|
||||
return this.connect(WS_KEY_MAP.spotV3Private);
|
||||
}
|
||||
case 'usdcOption': {
|
||||
return this.connect(WS_KEY_MAP.usdcOptionPrivate);
|
||||
}
|
||||
case 'usdcPerp': {
|
||||
return this.connect(WS_KEY_MAP.usdcPerpPrivate);
|
||||
}
|
||||
case 'unifiedPerp':
|
||||
case 'unifiedOption': {
|
||||
return this.connect(WS_KEY_MAP.unifiedPrivate);
|
||||
}
|
||||
case 'contractUSDT':
|
||||
return this.connect(WS_KEY_MAP.contractUSDTPrivate);
|
||||
case 'contractInverse':
|
||||
return this.connect(WS_KEY_MAP.contractInversePrivate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Subscribe to V5 topics & track/persist them.
|
||||
* @param wsTopics - topic or list of topics
|
||||
* @param category - the API category this topic is for (e.g. "linear"). The value is only important when connecting to public topics and will be ignored for private topics.
|
||||
* @param isPrivateTopic - optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
|
||||
* @param category - the API category this topic is for (e.g. "linear").
|
||||
* The value is only important when connecting to public topics and will be ignored for private topics.
|
||||
* @param isPrivateTopic - optional - the library will try to detect private topics, you can use this
|
||||
* to mark a topic as private (if the topic isn't recognised yet)
|
||||
*/
|
||||
public subscribeV5(
|
||||
wsTopics: WsTopic[] | WsTopic,
|
||||
@@ -249,7 +136,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
perWsKeyTopics[derivedWsKey] = [];
|
||||
}
|
||||
|
||||
perWsKeyTopics[derivedWsKey].push(wsRequest);
|
||||
perWsKeyTopics[derivedWsKey]!.push(wsRequest);
|
||||
}
|
||||
|
||||
const promises: Promise<unknown>[] = [];
|
||||
@@ -276,10 +163,14 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from V5 topics & remove them from memory. They won't be re-subscribed to if the connection reconnects.
|
||||
* Unsubscribe from V5 topics & remove them from memory. They won't be re-subscribed to if the
|
||||
* connection reconnects.
|
||||
*
|
||||
* @param wsTopics - topic or list of topics
|
||||
* @param category - the API category this topic is for (e.g. "linear"). The value is only important when connecting to public topics and will be ignored for private topics.
|
||||
* @param isPrivateTopic - optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
|
||||
* @param category - the API category this topic is for (e.g. "linear"). The value is only
|
||||
* important when connecting to public topics and will be ignored for private topics.
|
||||
* @param isPrivateTopic - optional - the library will try to detect private topics, you can
|
||||
* use this to mark a topic as private (if the topic isn't recognised yet)
|
||||
*/
|
||||
public unsubscribeV5(
|
||||
wsTopics: WsTopic[] | WsTopic,
|
||||
@@ -338,7 +229,11 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
}
|
||||
|
||||
/**
|
||||
* Request subscription to one or more topics. Pass topics as either an array of strings, or array of objects (if the topic has parameters).
|
||||
* Note: subscribeV5() might be simpler to use. The end result is the same.
|
||||
*
|
||||
* Request subscription to one or more topics. Pass topics as either an array of strings,
|
||||
* or array of objects (if the topic has parameters).
|
||||
*
|
||||
* Objects should be formatted as {topic: string, params: object, category: CategoryV5}.
|
||||
*
|
||||
* - Subscriptions are automatically routed to the correct websocket connection.
|
||||
@@ -356,7 +251,11 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
const topicRequests = Array.isArray(requests) ? requests : [requests];
|
||||
const normalisedTopicRequests = getNormalisedTopicRequests(topicRequests);
|
||||
|
||||
const perWsKeyTopics = getTopicsPerWSKey(normalisedTopicRequests, wsKey);
|
||||
const perWsKeyTopics = getTopicsPerWSKey(
|
||||
this.options.market,
|
||||
normalisedTopicRequests,
|
||||
wsKey,
|
||||
);
|
||||
|
||||
// Batch sub topics per ws key
|
||||
for (const wsKey in perWsKeyTopics) {
|
||||
@@ -368,6 +267,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: unsubscribe() might be simpler to use. The end result is the same.
|
||||
* Unsubscribe from one or more topics. Similar to subscribe() but in reverse.
|
||||
*
|
||||
* - Requests are automatically routed to the correct websocket connection.
|
||||
@@ -382,7 +282,11 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
const topicRequests = Array.isArray(requests) ? requests : [requests];
|
||||
const normalisedTopicRequests = getNormalisedTopicRequests(topicRequests);
|
||||
|
||||
const perWsKeyTopics = getTopicsPerWSKey(normalisedTopicRequests, wsKey);
|
||||
const perWsKeyTopics = getTopicsPerWSKey(
|
||||
this.options.market,
|
||||
normalisedTopicRequests,
|
||||
wsKey,
|
||||
);
|
||||
|
||||
// Batch sub topics per ws key
|
||||
for (const wsKey in perWsKeyTopics) {
|
||||
@@ -393,108 +297,124 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
}
|
||||
}
|
||||
|
||||
/*******
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* OLD WS CLIENT BELOW
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
* WS API Methods - similar to the REST API, but via WebSockets
|
||||
* https://bybit-exchange.github.io/docs/v5/websocket/trade/guideline
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Subscribe to V1-V3 topics & track/persist them.
|
||||
* Send a Websocket API command/request on a connection. Returns a promise that resolves on reply.
|
||||
*
|
||||
* @deprecated The V1-V3 websockets are very old and may not work properly anymore. Support for them will be removed soon. Use subcribeV5/unsubscribeV5 or subscribe/unsubscribe instead.
|
||||
* WS API Documentation for list of operations and parameters:
|
||||
* https://bybit-exchange.github.io/docs/v5/websocket/trade/guideline
|
||||
*
|
||||
* Note: for public V5 topics use the `subscribeV5()` method.
|
||||
* Returned promise is rejected if:
|
||||
* - an exception is detected in the reply, OR
|
||||
* - the connection disconnects for any reason (even if automatic reconnect will happen).
|
||||
*
|
||||
* Topics will be automatically resubscribed to if the connection resets/drops/reconnects.
|
||||
* @param wsTopics - topic or list of topics
|
||||
* @param isPrivateTopic optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
|
||||
* Authentication is automatic. If you didn't request authentication yourself, there might
|
||||
* be a small delay after your first request, while the SDK automatically authenticates.
|
||||
*
|
||||
* @param wsKey - The connection this event is for. Currently only "v5PrivateTrade" is supported
|
||||
* for Bybit, since that is the dedicated WS API connection.
|
||||
* @param operation - The command being sent, e.g. "order.create" to submit a new order.
|
||||
* @param params - Any request parameters for the command. E.g. `OrderParamsV5` to submit a new
|
||||
* order. Only send parameters for the request body. Everything else is automatically handled.
|
||||
* @returns Promise - tries to resolve with async WS API response. Rejects if disconnected or exception is seen in async WS API response
|
||||
*/
|
||||
public subscribeV3(
|
||||
wsTopics: WsTopic[] | WsTopic,
|
||||
isPrivateTopic?: boolean,
|
||||
): Promise<unknown>[] {
|
||||
const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
|
||||
if (this.options.market === 'v5') {
|
||||
topics.forEach((topic) => {
|
||||
if (!isPrivateWsTopic(topic)) {
|
||||
throw new Error(
|
||||
'For public "v5" websocket topics, use the subscribeV5() method & provide the category parameter',
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const promises: Promise<unknown>[] = [];
|
||||
// This overload allows the caller to omit the 3rd param, if it isn't required
|
||||
sendWSAPIRequest<
|
||||
TWSKey extends keyof WsAPIWsKeyTopicMap,
|
||||
TWSOperation extends WsAPIWsKeyTopicMap[TWSKey],
|
||||
TWSParams extends Exact<WsAPITopicRequestParamMap[TWSOperation]>,
|
||||
>(
|
||||
wsKey: TWSKey,
|
||||
operation: TWSOperation,
|
||||
...params: TWSParams extends undefined ? [] : [TWSParams]
|
||||
): Promise<WsAPIOperationResponseMap[TWSOperation]>;
|
||||
|
||||
topics.forEach((topic) => {
|
||||
const wsKey = getWsKeyForTopic(
|
||||
this.options.market,
|
||||
topic,
|
||||
isPrivateTopic,
|
||||
// These overloads give stricter types than mapped generics, since generic constraints
|
||||
// do not trigger excess property checks
|
||||
// Without these overloads, TypeScript won't complain if you include an
|
||||
// unexpected property with your request (if it doesn't clash with an existing property)
|
||||
sendWSAPIRequest<TWSOpreation extends WSAPIOperation = 'order.create'>(
|
||||
wsKey: typeof WS_KEY_MAP.v5PrivateTrade,
|
||||
operation: TWSOpreation,
|
||||
params: WsAPITopicRequestParamMap[TWSOpreation],
|
||||
): Promise<WsAPIOperationResponseMap[TWSOpreation]>;
|
||||
|
||||
sendWSAPIRequest<TWSOpreation extends WSAPIOperation = 'order.amend'>(
|
||||
wsKey: typeof WS_KEY_MAP.v5PrivateTrade,
|
||||
operation: TWSOpreation,
|
||||
params: WsAPITopicRequestParamMap[TWSOpreation],
|
||||
): Promise<WsAPIOperationResponseMap[TWSOpreation]>;
|
||||
|
||||
sendWSAPIRequest<TWSOpreation extends WSAPIOperation = 'order.cancel'>(
|
||||
wsKey: typeof WS_KEY_MAP.v5PrivateTrade,
|
||||
operation: TWSOpreation,
|
||||
params: WsAPITopicRequestParamMap[TWSOpreation],
|
||||
): Promise<WsAPIOperationResponseMap[TWSOpreation]>;
|
||||
|
||||
async sendWSAPIRequest<
|
||||
TWSKey extends keyof WsAPIWsKeyTopicMap,
|
||||
TWSOperation extends WsAPIWsKeyTopicMap[TWSKey],
|
||||
TWSParams extends Exact<WsAPITopicRequestParamMap[TWSOperation]>,
|
||||
TWSAPIResponse extends
|
||||
WsAPIOperationResponseMap[TWSOperation] = WsAPIOperationResponseMap[TWSOperation],
|
||||
>(
|
||||
wsKey: WsKey = WS_KEY_MAP.v5PrivateTrade,
|
||||
operation: TWSOperation,
|
||||
params: TWSParams,
|
||||
): Promise<WsAPIOperationResponseMap[TWSOperation]> {
|
||||
this.logger.trace(`sendWSAPIRequest(): assert "${wsKey}" is connected`);
|
||||
await this.assertIsConnected(wsKey);
|
||||
this.logger.trace('sendWSAPIRequest()->assertIsConnected() ok');
|
||||
|
||||
await this.assertIsAuthenticated(wsKey);
|
||||
this.logger.trace('sendWSAPIRequest()->assertIsAuthenticated() ok');
|
||||
|
||||
const requestEvent: WSAPIRequest<TWSParams> = {
|
||||
reqId: this.getNewRequestId(),
|
||||
header: {
|
||||
'X-BAPI-RECV-WINDOW': `${this.options.recvWindow}`,
|
||||
'X-BAPI-TIMESTAMP': `${Date.now()}`,
|
||||
Referer: APIID,
|
||||
},
|
||||
op: operation,
|
||||
args: [params],
|
||||
};
|
||||
|
||||
// Sign, if needed
|
||||
const signedEvent = await this.signWSAPIRequest(requestEvent);
|
||||
|
||||
// Store deferred promise, resolved within the "resolveEmittableEvents" method while parsing incoming events
|
||||
const promiseRef = getPromiseRefForWSAPIRequest(requestEvent);
|
||||
|
||||
const deferredPromise =
|
||||
this.getWsStore().createDeferredPromise<TWSAPIResponse>(
|
||||
wsKey,
|
||||
promiseRef,
|
||||
false,
|
||||
);
|
||||
|
||||
const wsRequest: WsTopicRequest<WsTopic> = {
|
||||
topic: topic,
|
||||
};
|
||||
this.logger.trace(
|
||||
`sendWSAPIRequest(): sending raw request: ${JSON.stringify(signedEvent, null, 2)}`,
|
||||
);
|
||||
|
||||
// Persist topic for reconnects
|
||||
const requestPromise = this.subscribeTopicsForWsKey([wsRequest], wsKey);
|
||||
// Send event
|
||||
this.tryWsSend(wsKey, JSON.stringify(signedEvent));
|
||||
|
||||
promises.push(requestPromise);
|
||||
});
|
||||
this.logger.trace(`sendWSAPIRequest(): sent ${operation} event`);
|
||||
|
||||
// Return promise to resolve midflight WS request (only works if already connected before request)
|
||||
return promises;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from V1-V3 topics & remove them from memory. They won't be re-subscribed to if the connection reconnects.
|
||||
*
|
||||
* @deprecated The V1-V3 websockets are very old and may not work properly anymore. Support for them will be removed soon. Use subcribeV5/unsubscribeV5 or subscribe/unsubscribe instead.
|
||||
*
|
||||
* Note: For public V5 topics, use `unsubscribeV5()` instead!
|
||||
*
|
||||
* @param wsTopics topic or list of topics
|
||||
* @param isPrivateTopic optional - the library will try to detect private topics, you can use this to mark a topic as private (if the topic isn't recognised yet)
|
||||
*/
|
||||
public unsubscribeV3(
|
||||
wsTopics: WsTopic[] | WsTopic,
|
||||
isPrivateTopic?: boolean,
|
||||
) {
|
||||
const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
|
||||
if (this.options.market === 'v5') {
|
||||
topics.forEach((topic) => {
|
||||
if (!isPrivateWsTopic(topic)) {
|
||||
throw new Error(
|
||||
'For public "v5" websocket topics, use the unsubscribeV5() method & provide the category parameter',
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
topics.forEach((topic) => {
|
||||
const wsKey = getWsKeyForTopic(
|
||||
this.options.market,
|
||||
topic,
|
||||
isPrivateTopic,
|
||||
);
|
||||
|
||||
const wsRequest: WsTopicRequest<WsTopic> = {
|
||||
topic: topic,
|
||||
};
|
||||
|
||||
// Persist topic for reconnects
|
||||
this.unsubscribeTopicsForWsKey([wsRequest], wsKey);
|
||||
});
|
||||
// Return deferred promise, so caller can await this call
|
||||
return deferredPromise.promise!;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -512,7 +432,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
const wsBaseURL = getWsUrl(wsKey, this.options, this.logger);
|
||||
|
||||
// If auth is needed for this wsKey URL, this returns a suffix
|
||||
const authParams = await this.getWsAuthURLSuffix(wsKey);
|
||||
const authParams = await this.getWsAuthURLSuffix();
|
||||
if (!authParams) {
|
||||
return wsBaseURL;
|
||||
}
|
||||
@@ -523,8 +443,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
/**
|
||||
* Return params required to make authorized request
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
|
||||
private async getWsAuthURLSuffix(wsKey: WsKey): Promise<string> {
|
||||
private async getWsAuthURLSuffix(): Promise<string> {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -540,7 +459,9 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
return await signMessage(paramsStr, secret, method, algorithm);
|
||||
}
|
||||
|
||||
protected async getWsAuthRequestEvent(wsKey: WsKey): Promise<any> {
|
||||
protected async getWsAuthRequestEvent(
|
||||
wsKey: WsKey,
|
||||
): Promise<WsRequestOperationBybit<string>> {
|
||||
try {
|
||||
const { signature, expiresAt } = await this.getWsAuthSignature(wsKey);
|
||||
|
||||
@@ -608,7 +529,6 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
}
|
||||
|
||||
/** Force subscription requests to be sent in smaller batches, if a number is returned */
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected getMaxTopicsPerSubscribeEvent(wsKey: WsKey): number | null {
|
||||
return getMaxTopicsPerSubscribeEvent(this.options.market, wsKey);
|
||||
}
|
||||
@@ -630,10 +550,18 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
|
||||
switch (market) {
|
||||
case 'all': {
|
||||
const topics = requests.map((r) => r.topic);
|
||||
|
||||
// Previously used to track topics in a request. Keeping this for subscribe/unsubscribe requests, no need for incremental values
|
||||
const req_id =
|
||||
['subscribe', 'unsubscribe'].includes(operation) && topics.length
|
||||
? topics.join(',')
|
||||
: this.getNewRequestId();
|
||||
|
||||
const wsEvent: WsRequestOperationBybit<WsTopic> = {
|
||||
req_id: this.getNewRequestId(),
|
||||
req_id: req_id,
|
||||
op: operation,
|
||||
args: requests.map((r) => r.topic),
|
||||
args: topics,
|
||||
};
|
||||
|
||||
const midflightWsEvent: MidflightWsRequestEvent<
|
||||
@@ -656,6 +584,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
if (wsRequestBuildingErrors.length) {
|
||||
const label =
|
||||
wsRequestBuildingErrors.length === requests.length ? 'all' : 'some';
|
||||
|
||||
this.logger.error(
|
||||
`Failed to build/send ${wsRequestBuildingErrors.length} event(s) for ${label} WS requests due to exceptions`,
|
||||
{
|
||||
@@ -674,17 +603,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
}
|
||||
|
||||
protected getPrivateWSKeys(): WsKey[] {
|
||||
return [
|
||||
WS_KEY_MAP.linearPrivate,
|
||||
WS_KEY_MAP.spotPrivate,
|
||||
WS_KEY_MAP.spotV3Private,
|
||||
WS_KEY_MAP.usdcOptionPrivate,
|
||||
WS_KEY_MAP.usdcPerpPrivate,
|
||||
WS_KEY_MAP.unifiedPrivate,
|
||||
WS_KEY_MAP.contractUSDTPrivate,
|
||||
WS_KEY_MAP.contractInversePrivate,
|
||||
WS_KEY_MAP.v5Private,
|
||||
];
|
||||
return WS_AUTH_ON_CONNECT_KEYS;
|
||||
}
|
||||
|
||||
protected isAuthOnConnectWsKey(wsKey: WsKey): boolean {
|
||||
@@ -694,11 +613,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
/**
|
||||
* Determines if a topic is for a private channel, using a hardcoded list of strings
|
||||
*/
|
||||
protected isPrivateTopicRequest(
|
||||
request: WsTopicRequest<string>,
|
||||
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
||||
wsKey: WsKey,
|
||||
): boolean {
|
||||
protected isPrivateTopicRequest(request: WsTopicRequest<string>): boolean {
|
||||
const topicName = request?.topic?.toLowerCase();
|
||||
if (!topicName) {
|
||||
return false;
|
||||
@@ -707,6 +622,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
return isPrivateWsTopic(topicName);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
protected isWsPing(msg: any): boolean {
|
||||
if (!msg) {
|
||||
return false;
|
||||
@@ -726,6 +642,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
return false;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
protected isWsPong(msg: any): boolean {
|
||||
if (!msg) {
|
||||
return false;
|
||||
@@ -763,7 +680,6 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
event: MessageEventLike,
|
||||
): EmittableEvent[] {
|
||||
const results: EmittableEvent[] = [];
|
||||
// const isWSAPIResponseEvent = wsKey === WS_KEY_MAP.v5PrivateTrade;
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(event.data);
|
||||
@@ -839,7 +755,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
}
|
||||
|
||||
results.push({
|
||||
eventType: 'error',
|
||||
eventType: 'exception',
|
||||
event: parsed,
|
||||
isWSAPIResponse: true,
|
||||
});
|
||||
@@ -879,7 +795,6 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
results.push({
|
||||
eventType: 'update',
|
||||
event: parsed,
|
||||
// isWSAPIResponse: isWSAPIResponseEvent,
|
||||
});
|
||||
return results;
|
||||
}
|
||||
@@ -889,9 +804,8 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
// Failed request
|
||||
if (parsed.success === false) {
|
||||
results.push({
|
||||
eventType: 'error',
|
||||
eventType: 'exception',
|
||||
event: parsed,
|
||||
// isWSAPIResponse: isWSAPIResponseEvent,
|
||||
});
|
||||
return results;
|
||||
}
|
||||
@@ -901,7 +815,6 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
results.push({
|
||||
eventType: 'response',
|
||||
event: parsed,
|
||||
// isWSAPIResponse: isWSAPIResponseEvent,
|
||||
});
|
||||
return results;
|
||||
}
|
||||
@@ -911,7 +824,6 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
results.push({
|
||||
eventType: 'authenticated',
|
||||
event: parsed,
|
||||
// isWSAPIResponse: isWSAPIResponseEvent,
|
||||
});
|
||||
return results;
|
||||
}
|
||||
@@ -939,7 +851,7 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
exception: e,
|
||||
eventData: event.data,
|
||||
},
|
||||
eventType: 'error',
|
||||
eventType: 'exception',
|
||||
});
|
||||
|
||||
this.logger.error('Failed to parse event data due to exception: ', {
|
||||
@@ -950,121 +862,4 @@ export class WebsocketClient extends BaseWebsocketClient<
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
* WS API Methods - similar to the REST API, but via WebSockets
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send a Websocket API event on a connection. Returns a promise that resolves on reply.
|
||||
*
|
||||
* Authentication is automatic. If you didn't request authentication yourself, there might be a small delay after your first request, while the SDK automatically authenticates.
|
||||
*
|
||||
* Returned promise is rejected if:
|
||||
* - an exception is detected in the reply, OR
|
||||
* - the connection disconnects for any reason (even if automatic reconnect will happen).
|
||||
*
|
||||
* If you authenticated once and you're reconnected later (e.g. connection temporarily lost), the SDK will by default automatically:
|
||||
* - Detect you were authenticated to the WS API before
|
||||
* - Try to re-authenticate (up to 5 times, in case something (bad timestamp) goes wrong)
|
||||
* - If it succeeds, it will emit the 'authenticated' event.
|
||||
* - If it fails and gives up, it will emit an 'exception' event.
|
||||
*
|
||||
* @param wsKey - The connection this event is for. Currently only "v5PrivateTrade" is supported, since that is the dedicated WS API connection.
|
||||
* @param operation - The command being sent, e.g. "order.create" to submit a new order.
|
||||
* @param params - Any request parameters for the command. E.g. `OrderParamsV5` to submit a new order. Only send parameters for the request body. Everything else is automatically handled.
|
||||
* @returns Promise - tries to resolve with async WS API response. Rejects if disconnected or exception is seen in async WS API response
|
||||
*/
|
||||
|
||||
// This overload allows the caller to omit the 3rd param, if it isn't required
|
||||
sendWSAPIRequest<
|
||||
TWSKey extends keyof WsAPIWsKeyTopicMap,
|
||||
TWSOperation extends WsAPIWsKeyTopicMap[TWSKey],
|
||||
TWSParams extends Exact<WsAPITopicRequestParamMap[TWSOperation]>,
|
||||
>(
|
||||
wsKey: TWSKey,
|
||||
operation: TWSOperation,
|
||||
...params: TWSParams extends undefined ? [] : [TWSParams]
|
||||
): Promise<WsAPIOperationResponseMap[TWSOperation]>;
|
||||
|
||||
// These overloads give stricter types than mapped generics, since generic constraints do not trigger excess property checks
|
||||
// Without these overloads, TypeScript won't complain if you include an unexpected property with your request (if it doesn't clash with an existing property)
|
||||
sendWSAPIRequest(
|
||||
wsKey: typeof WS_KEY_MAP.v5PrivateTrade,
|
||||
operation: 'order.create',
|
||||
params: WsAPITopicRequestParamMap['order.create'],
|
||||
): Promise<WsAPIOperationResponseMap['order.create']>;
|
||||
|
||||
sendWSAPIRequest(
|
||||
wsKey: typeof WS_KEY_MAP.v5PrivateTrade,
|
||||
operation: 'order.amend',
|
||||
params: WsAPITopicRequestParamMap['order.amend'],
|
||||
): Promise<WsAPIOperationResponseMap['order.amend']>;
|
||||
|
||||
sendWSAPIRequest(
|
||||
wsKey: typeof WS_KEY_MAP.v5PrivateTrade,
|
||||
operation: 'order.cancel',
|
||||
params: WsAPITopicRequestParamMap['order.cancel'],
|
||||
): Promise<WsAPIOperationResponseMap['order.cancel']>;
|
||||
|
||||
async sendWSAPIRequest<
|
||||
TWSKey extends keyof WsAPIWsKeyTopicMap,
|
||||
TWSOperation extends WsAPIWsKeyTopicMap[TWSKey],
|
||||
TWSParams extends Exact<WsAPITopicRequestParamMap[TWSOperation]>,
|
||||
TWSAPIResponse extends
|
||||
WsAPIOperationResponseMap[TWSOperation] = WsAPIOperationResponseMap[TWSOperation],
|
||||
>(
|
||||
wsKey: WsKey = WS_KEY_MAP.v5PrivateTrade,
|
||||
operation: TWSOperation,
|
||||
params: TWSParams,
|
||||
): Promise<WsAPIOperationResponseMap[TWSOperation]> {
|
||||
this.logger.trace(`sendWSAPIRequest(): assert "${wsKey}" is connected`);
|
||||
await this.assertIsConnected(wsKey);
|
||||
this.logger.trace('sendWSAPIRequest()->assertIsConnected() ok');
|
||||
|
||||
await this.assertIsAuthenticated(wsKey);
|
||||
this.logger.trace('sendWSAPIRequest()->assertIsAuthenticated() ok');
|
||||
|
||||
const requestEvent: WSAPIRequest<TWSParams> = {
|
||||
reqId: this.getNewRequestId(),
|
||||
header: {
|
||||
'X-BAPI-RECV-WINDOW': `${this.options.recvWindow}`,
|
||||
'X-BAPI-TIMESTAMP': `${Date.now()}`,
|
||||
Referer: APIID,
|
||||
},
|
||||
op: operation,
|
||||
args: [params],
|
||||
};
|
||||
|
||||
// Sign, if needed
|
||||
const signedEvent = await this.signWSAPIRequest(requestEvent);
|
||||
|
||||
// Store deferred promise, resolved within the "resolveEmittableEvents" method while parsing incoming events
|
||||
const promiseRef = getPromiseRefForWSAPIRequest(requestEvent);
|
||||
|
||||
const deferredPromise =
|
||||
this.getWsStore().createDeferredPromise<TWSAPIResponse>(
|
||||
wsKey,
|
||||
promiseRef,
|
||||
false,
|
||||
);
|
||||
|
||||
this.logger.trace(
|
||||
`sendWSAPIRequest(): sending raw request: ${JSON.stringify(signedEvent, null, 2)}`,
|
||||
);
|
||||
|
||||
// Send event
|
||||
this.tryWsSend(wsKey, JSON.stringify(signedEvent));
|
||||
|
||||
this.logger.trace(`sendWSAPIRequest(): sent ${operation} event`);
|
||||
|
||||
// Return deferred promise, so caller can await this call
|
||||
return deferredPromise.promise!;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user