add account asset & USDC options clients
This commit is contained in:
21
README.md
21
README.md
@@ -42,13 +42,17 @@ Most methods accept JS objects. These can be populated using parameters specifie
|
|||||||
## REST Clients
|
## REST Clients
|
||||||
Each REST API category has a dedicated REST client. Here are the REST clients and their API group:
|
Each REST API category has a dedicated REST client. Here are the REST clients and their API group:
|
||||||
| Class | Description |
|
| Class | Description |
|
||||||
|:-----------------------------------------------------: |:------------------------------: |
|
|:-----------------------------------------------------: |:-----------------------------------------------------------------------------------------------------: |
|
||||||
| [InverseClient](src/inverse-client.ts) | Inverse Perpetual Futures (v2) |
|
| [InverseClient](src/inverse-client.ts) | [Inverse Perpetual Futures (v2)](https://bybit-exchange.github.io/docs/futuresV2/inverse/) |
|
||||||
| [LinearClient](src/linear-client.ts) | USDT Perpetual Futures (v2) |
|
| [LinearClient](src/linear-client.ts) | [USDT Perpetual Futures (v2)](https://bybit-exchange.github.io/docs/futuresV2/linear/#t-introduction) |
|
||||||
| [InverseFuturesClient](src/inverse-futures-client.ts) | Inverse Futures (v2) |
|
| [InverseFuturesClient](src/inverse-futures-client.ts) | [Inverse Futures (v2)](https://bybit-exchange.github.io/docs/futuresV2/inverse_futures/#t-introduction) |
|
||||||
| [SpotClient](src/spot-client.ts) | Spot Markets |
|
| [SpotClient](src/spot-client.ts) | [Spot Markets](https://bybit-exchange.github.io/docs/spot/#t-introduction) |
|
||||||
|
| [AccountAssetClient](src/account-asset-client.ts) | [Account Asset API](https://bybit-exchange.github.io/docs/account_asset/#t-introduction) |
|
||||||
| USDC Options & Perpetual Contracts | Under Development |
|
| USDC Options & Perpetual Contracts | Under Development |
|
||||||
| Derivatives V3 unified margin | Under Development |
|
| Derivatives V3 unified margin | Under Development |
|
||||||
|
| [WebsocketClient](src/websocket-client.ts) | All WebSocket Events (Public & Private for all API categories) |
|
||||||
|
|
||||||
|
Examples for using each client can be found in the [examples](./examples) folder and the [awesome-crypto-examples](https://github.com/tiagosiebler/awesome-crypto-examples) repository.
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
The connector is written in TypeScript. A pure JavaScript version can be built using `npm run build`, which is also the version published to [npm](https://www.npmjs.com/package/bybit-api). This connector is fully compatible with both TypeScript and pure JavaScript projects.
|
The connector is written in TypeScript. A pure JavaScript version can be built using `npm run build`, which is also the version published to [npm](https://www.npmjs.com/package/bybit-api). This connector is fully compatible with both TypeScript and pure JavaScript projects.
|
||||||
@@ -60,18 +64,13 @@ The connector is written in TypeScript. A pure JavaScript version can be built u
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Usage
|
## Usage
|
||||||
Create API credentials at Bybit
|
Create API credentials at Bybit
|
||||||
- [Livenet](https://bybit.com/app/user/api-management?affiliate_id=9410&language=en-US&group_id=0&group_type=1)
|
- [Livenet](https://bybit.com/app/user/api-management?affiliate_id=9410&language=en-US&group_id=0&group_type=1)
|
||||||
- [Testnet](https://testnet.bybit.com/app/user/api-management)
|
- [Testnet](https://testnet.bybit.com/app/user/api-management)
|
||||||
|
|
||||||
## REST API Clients
|
## REST API Clients
|
||||||
|
|
||||||
There are three REST API modules as there are some differences in each contract type.
|
|
||||||
1. `InverseClient` for inverse perpetual
|
|
||||||
2. `InverseFuturesClient` for inverse futures
|
|
||||||
3. `LinearClient` for linear perpetual
|
|
||||||
|
|
||||||
### REST Inverse
|
### REST Inverse
|
||||||
To use the inverse REST APIs, import the `InverseClient`:
|
To use the inverse REST APIs, import the `InverseClient`:
|
||||||
|
|
||||||
|
|||||||
173
src/account-asset-client.ts
Normal file
173
src/account-asset-client.ts
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
import { AxiosRequestConfig } from 'axios';
|
||||||
|
import {
|
||||||
|
AccountAssetInformationRequest,
|
||||||
|
APIResponseWithTime,
|
||||||
|
DepositRecordsRequest,
|
||||||
|
EnableUniversalTransferRequest,
|
||||||
|
InternalTransferRequest,
|
||||||
|
SubAccountTransferRequest,
|
||||||
|
SupportedDepositListRequest,
|
||||||
|
TransferQueryRequest,
|
||||||
|
UniversalTransferRequest,
|
||||||
|
WithdrawalRecordsRequest,
|
||||||
|
WithdrawalRequest,
|
||||||
|
} from './types';
|
||||||
|
import {
|
||||||
|
RestClientOptions,
|
||||||
|
getRestBaseUrl,
|
||||||
|
REST_CLIENT_TYPE_ENUM,
|
||||||
|
} from './util';
|
||||||
|
import BaseRestClient from './util/BaseRestClient';
|
||||||
|
|
||||||
|
export class AccountAssetClient extends BaseRestClient {
|
||||||
|
/**
|
||||||
|
* @public Creates an instance of the Account Asset REST API client.
|
||||||
|
*
|
||||||
|
* @param {string} key - your API key
|
||||||
|
* @param {string} secret - your API secret
|
||||||
|
* @param {boolean} [useLivenet=false]
|
||||||
|
* @param {RestClientOptions} [restClientOptions={}] options to configure REST API connectivity
|
||||||
|
* @param {AxiosRequestConfig} [requestOptions={}] HTTP networking options for axios
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
key?: string | undefined,
|
||||||
|
secret?: string | undefined,
|
||||||
|
useLivenet: boolean = false,
|
||||||
|
restClientOptions: RestClientOptions = {},
|
||||||
|
requestOptions: AxiosRequestConfig = {}
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
key,
|
||||||
|
secret,
|
||||||
|
getRestBaseUrl(useLivenet, restClientOptions),
|
||||||
|
restClientOptions,
|
||||||
|
requestOptions,
|
||||||
|
REST_CLIENT_TYPE_ENUM.accountAsset
|
||||||
|
);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,7 +1,9 @@
|
|||||||
|
export * from './account-asset-client';
|
||||||
export * from './inverse-client';
|
export * from './inverse-client';
|
||||||
export * from './inverse-futures-client';
|
export * from './inverse-futures-client';
|
||||||
export * from './linear-client';
|
export * from './linear-client';
|
||||||
export * from './spot-client';
|
export * from './spot-client';
|
||||||
|
export * from './usdc-options-client';
|
||||||
export * from './websocket-client';
|
export * from './websocket-client';
|
||||||
export * from './logger';
|
export * from './logger';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
getRestBaseUrl,
|
getRestBaseUrl,
|
||||||
RestClientOptions,
|
RestClientOptions,
|
||||||
REST_CLIENT_TYPE_ENUM,
|
REST_CLIENT_TYPE_ENUM,
|
||||||
} from './util/requestUtils';
|
} from './util';
|
||||||
import {
|
import {
|
||||||
APIResponseWithTime,
|
APIResponseWithTime,
|
||||||
AssetExchangeRecordsReq,
|
AssetExchangeRecordsReq,
|
||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
SymbolPeriodLimitParam,
|
SymbolPeriodLimitParam,
|
||||||
WalletFundRecordsReq,
|
WalletFundRecordsReq,
|
||||||
WithdrawRecordsReq,
|
WithdrawRecordsReq,
|
||||||
} from './types/shared';
|
} from './types';
|
||||||
import BaseRestClient from './util/BaseRestClient';
|
import BaseRestClient from './util/BaseRestClient';
|
||||||
|
|
||||||
export class InverseClient extends BaseRestClient {
|
export class InverseClient extends BaseRestClient {
|
||||||
|
|||||||
94
src/types/request/account-asset.ts
Normal file
94
src/types/request/account-asset.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
export type TransferAccountType =
|
||||||
|
| 'CONTRACT'
|
||||||
|
| 'SPOT'
|
||||||
|
| 'INVESTMENT'
|
||||||
|
| 'OPTION'
|
||||||
|
| 'UNIFIED';
|
||||||
|
|
||||||
|
export type TransferType = 'IN' | 'OUT';
|
||||||
|
|
||||||
|
export type TransferStatus = 'SUCCESS' | 'PENDING' | 'FAILED';
|
||||||
|
|
||||||
|
export type PageDirection = 'Prev' | 'Next';
|
||||||
|
|
||||||
|
export interface InternalTransferRequest {
|
||||||
|
transfer_id: string;
|
||||||
|
coin: string;
|
||||||
|
amount: string;
|
||||||
|
from_account_type: TransferAccountType;
|
||||||
|
to_account_type: TransferAccountType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SubAccountTransferRequest {
|
||||||
|
transfer_id: string;
|
||||||
|
coin: string;
|
||||||
|
amount: string;
|
||||||
|
sub_user_id: string;
|
||||||
|
type: TransferType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransferQueryRequest {
|
||||||
|
transfer_id?: string;
|
||||||
|
coin?: string;
|
||||||
|
status?: TransferStatus;
|
||||||
|
start_time?: number;
|
||||||
|
end_time?: number;
|
||||||
|
direction?: PageDirection;
|
||||||
|
limit?: number;
|
||||||
|
cursor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EnableUniversalTransferRequest {
|
||||||
|
/** A comma-separated list of subaccount UIDs, for example "123,45,14,26,46" */
|
||||||
|
transferable_sub_ids?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UniversalTransferRequest {
|
||||||
|
transfer_id: string;
|
||||||
|
coin: string;
|
||||||
|
amount: string;
|
||||||
|
from_member_id: string;
|
||||||
|
to_member_id: string;
|
||||||
|
from_account_type: TransferAccountType;
|
||||||
|
to_account_type: TransferAccountType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SupportedDepositListRequest {
|
||||||
|
coin?: string;
|
||||||
|
chain?: string;
|
||||||
|
page_index?: number;
|
||||||
|
page_size?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DepositRecordsRequest {
|
||||||
|
start_time?: number;
|
||||||
|
end_time?: number;
|
||||||
|
coin?: string;
|
||||||
|
cursor?: string;
|
||||||
|
direction?: PageDirection;
|
||||||
|
limit?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WithdrawalRecordsRequest {
|
||||||
|
withdraw_id?: number;
|
||||||
|
start_time?: number;
|
||||||
|
end_time?: number;
|
||||||
|
coin?: string;
|
||||||
|
cursor?: string;
|
||||||
|
direction?: PageDirection;
|
||||||
|
limit?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AccountAssetInformationRequest {
|
||||||
|
/** Account type. Default value: ACCOUNT_TYPE_SPOT */
|
||||||
|
account_type?: string;
|
||||||
|
coin?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WithdrawalRequest {
|
||||||
|
address: string;
|
||||||
|
amount: string;
|
||||||
|
coin: string;
|
||||||
|
chain: string;
|
||||||
|
tag?: string;
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
|
export * from './account-asset';
|
||||||
export * from './usdt-perp';
|
export * from './usdt-perp';
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export interface APIResponse<T> {
|
|||||||
result: T;
|
result: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface APIResponseWithTime<T> extends APIResponse<T> {
|
export interface APIResponseWithTime<T = {}> extends APIResponse<T> {
|
||||||
/** UTC timestamp */
|
/** UTC timestamp */
|
||||||
time_now: numberInString;
|
time_now: numberInString;
|
||||||
}
|
}
|
||||||
|
|||||||
306
src/usdc-options-client.ts
Normal file
306
src/usdc-options-client.ts
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
import { AxiosRequestConfig } from 'axios';
|
||||||
|
import { APIResponseWithTime } from './types';
|
||||||
|
import {
|
||||||
|
RestClientOptions,
|
||||||
|
getRestBaseUrl,
|
||||||
|
REST_CLIENT_TYPE_ENUM,
|
||||||
|
} from './util';
|
||||||
|
import BaseRestClient from './util/BaseRestClient';
|
||||||
|
|
||||||
|
export class USDCOptionsClient extends BaseRestClient {
|
||||||
|
/**
|
||||||
|
* @public Creates an instance of the USDC Options REST API client.
|
||||||
|
*
|
||||||
|
* @param {string} key - your API key
|
||||||
|
* @param {string} secret - your API secret
|
||||||
|
* @param {boolean} [useLivenet=false] uses testnet by default
|
||||||
|
* @param {RestClientOptions} [restClientOptions={}] options to configure REST API connectivity
|
||||||
|
* @param {AxiosRequestConfig} [requestOptions={}] HTTP networking options for axios
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
key?: string | undefined,
|
||||||
|
secret?: string | undefined,
|
||||||
|
useLivenet: boolean = false,
|
||||||
|
restClientOptions: RestClientOptions = {},
|
||||||
|
requestOptions: AxiosRequestConfig = {}
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
key,
|
||||||
|
secret,
|
||||||
|
getRestBaseUrl(useLivenet, restClientOptions),
|
||||||
|
restClientOptions,
|
||||||
|
requestOptions,
|
||||||
|
REST_CLIENT_TYPE_ENUM.usdcOptions
|
||||||
|
);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<APIResponseWithTime<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?: unknown): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.get('/option/usdc/openapi/public/v1/symbols', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a symbol price/statistics ticker */
|
||||||
|
getSymbolTicker(symbol: string): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.get('/option/usdc/openapi/public/v1/tick', { symbol });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get delivery information */
|
||||||
|
getDeliveryPrice(params?: unknown): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.get('/option/usdc/openapi/public/v1/delivery-price', params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returned records are Taker Buy in default. */
|
||||||
|
getLastTrades(params: unknown): Promise<APIResponseWithTime<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?: unknown): Promise<APIResponseWithTime<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: unknown): Promise<APIResponseWithTime<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: unknown[]
|
||||||
|
): Promise<APIResponseWithTime<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: unknown): Promise<APIResponseWithTime<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: unknown[]
|
||||||
|
): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate(
|
||||||
|
'/option/usdc/openapi/private/v1/batch-replace-orders',
|
||||||
|
{ replaceOrderRequest }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Cancel order */
|
||||||
|
cancelOrder(params: unknown): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate(
|
||||||
|
'/option/usdc/openapi/private/v1/cancel-order',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Batch cancel orders */
|
||||||
|
batchCancelOrders(
|
||||||
|
cancelRequest: unknown[]
|
||||||
|
): Promise<APIResponseWithTime<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?: unknown): Promise<APIResponseWithTime<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?: unknown): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.getPrivate(
|
||||||
|
'/option/usdc/openapi/private/v1/trade/query-active-orders',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Query Unfilled/Partially Filled Orders */
|
||||||
|
getActiveOrders(params: unknown): Promise<APIResponseWithTime<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: unknown): Promise<APIResponseWithTime<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: unknown): Promise<APIResponseWithTime<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: unknown): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate(
|
||||||
|
'/option/usdc/openapi/private/v1/query-transaction-log',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Wallet info for USDC account. */
|
||||||
|
getBalance(params?: unknown): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate(
|
||||||
|
'/option/usdc/openapi/private/v1/query-wallet-balance',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Asset Info */
|
||||||
|
getAssetInfo(baseCoin?: string): Promise<APIResponseWithTime<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<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate(
|
||||||
|
'/option/usdc/private/asset/account/setMarginMode',
|
||||||
|
{ setMarginMode: newMarginMode }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Query margin mode for USDC account. */
|
||||||
|
getMarginMode(): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate(
|
||||||
|
'/option/usdc/openapi/private/v1/query-margin-info'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -> Positions API */
|
||||||
|
|
||||||
|
/** Query my positions */
|
||||||
|
getPositions(params: unknown): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate(
|
||||||
|
'/option/usdc/openapi/private/v1/query-position',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Query Delivery History */
|
||||||
|
getDeliveryHistory(params: unknown): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate(
|
||||||
|
'/option/usdc/openapi/private/v1/query-delivery-list',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Query Positions Info Upon Expiry */
|
||||||
|
getPositionsInfoUponExpiry(
|
||||||
|
params?: unknown
|
||||||
|
): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate(
|
||||||
|
'/option/usdc/openapi/private/v1/query-position-exp-date',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -> Market Maker Protection */
|
||||||
|
|
||||||
|
/** modifyMMP */
|
||||||
|
modifyMMP(params?: unknown): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate(
|
||||||
|
'/option/usdc/openapi/private/v1/mmp-modify',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** resetMMP */
|
||||||
|
resetMMP(currency: string): Promise<APIResponseWithTime<any>> {
|
||||||
|
return this.postPrivate('/option/usdc/openapi/private/v1/mmp-reset', {
|
||||||
|
currency,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** queryMMPState */
|
||||||
|
queryMMPState(baseCoin: string): Promise<APIResponseWithTime<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');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
interface SignedRequestContext {
|
interface SignedRequestContext {
|
||||||
timestamp: number;
|
timestamp?: number;
|
||||||
api_key?: string;
|
api_key?: string;
|
||||||
recv_window?: number;
|
recv_window?: number;
|
||||||
// spot is diff from the rest...
|
// spot is diff from the rest...
|
||||||
@@ -30,9 +30,19 @@ interface SignedRequestContext {
|
|||||||
interface SignedRequest<T> {
|
interface SignedRequest<T> {
|
||||||
originalParams: T & SignedRequestContext;
|
originalParams: T & SignedRequestContext;
|
||||||
paramsWithSign?: T & SignedRequestContext & { sign: string };
|
paramsWithSign?: T & SignedRequestContext & { sign: string };
|
||||||
|
serializedParams: string;
|
||||||
sign: string;
|
sign: string;
|
||||||
|
timestamp: number;
|
||||||
|
recvWindow: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface UnsignedRequest<T> {
|
||||||
|
originalParams: T;
|
||||||
|
paramsWithSign: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
type SignMethod = 'keyInBody' | 'usdc';
|
||||||
|
|
||||||
export default abstract class BaseRestClient {
|
export default abstract class BaseRestClient {
|
||||||
private timeOffset: number | null;
|
private timeOffset: number | null;
|
||||||
private syncTimePromise: null | Promise<any>;
|
private syncTimePromise: null | Promise<any>;
|
||||||
@@ -61,8 +71,7 @@ export default abstract class BaseRestClient {
|
|||||||
|
|
||||||
this.options = {
|
this.options = {
|
||||||
recv_window: 5000,
|
recv_window: 5000,
|
||||||
|
/** Throw errors if any request params are empty */
|
||||||
/** Throw errors if any params are undefined */
|
|
||||||
strict_param_validation: false,
|
strict_param_validation: false,
|
||||||
/** Disable time sync by default */
|
/** Disable time sync by default */
|
||||||
enable_time_sync: false,
|
enable_time_sync: false,
|
||||||
@@ -102,6 +111,10 @@ export default abstract class BaseRestClient {
|
|||||||
return this.clientType === REST_CLIENT_TYPE_ENUM.spot;
|
return this.clientType === REST_CLIENT_TYPE_ENUM.spot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isUSDCClient() {
|
||||||
|
return this.clientType === REST_CLIENT_TYPE_ENUM.usdcOptions;
|
||||||
|
}
|
||||||
|
|
||||||
get(endpoint: string, params?: any) {
|
get(endpoint: string, params?: any) {
|
||||||
return this._call('GET', endpoint, params, true);
|
return this._call('GET', endpoint, params, true);
|
||||||
}
|
}
|
||||||
@@ -122,7 +135,24 @@ export default abstract class BaseRestClient {
|
|||||||
return this._call('DELETE', endpoint, params, false);
|
return this._call('DELETE', endpoint, params, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async prepareSignParams(params?: any, isPublicApi?: boolean) {
|
private async prepareSignParams<TParams = any>(
|
||||||
|
method: Method,
|
||||||
|
signMethod: SignMethod,
|
||||||
|
params?: TParams,
|
||||||
|
isPublicApi?: true
|
||||||
|
): Promise<UnsignedRequest<TParams>>;
|
||||||
|
private async prepareSignParams<TParams = any>(
|
||||||
|
method: Method,
|
||||||
|
signMethod: SignMethod,
|
||||||
|
params?: TParams,
|
||||||
|
isPublicApi?: false | undefined
|
||||||
|
): Promise<SignedRequest<TParams>>;
|
||||||
|
private async prepareSignParams<TParams = any>(
|
||||||
|
method: Method,
|
||||||
|
signMethod: SignMethod,
|
||||||
|
params?: TParams,
|
||||||
|
isPublicApi?: boolean
|
||||||
|
) {
|
||||||
if (isPublicApi) {
|
if (isPublicApi) {
|
||||||
return {
|
return {
|
||||||
originalParams: params,
|
originalParams: params,
|
||||||
@@ -138,7 +168,85 @@ export default abstract class BaseRestClient {
|
|||||||
await this.syncTime();
|
await this.syncTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.signRequest(params);
|
return this.signRequest(params, method, signMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns an axios request object. Handles signing process automatically if this is a private API call */
|
||||||
|
private async buildRequest(
|
||||||
|
method: Method,
|
||||||
|
url: string,
|
||||||
|
params?: any,
|
||||||
|
isPublicApi?: boolean
|
||||||
|
): Promise<AxiosRequestConfig> {
|
||||||
|
const options: AxiosRequestConfig = {
|
||||||
|
...this.globalRequestOptions,
|
||||||
|
url: url,
|
||||||
|
method: method,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const key in params) {
|
||||||
|
if (typeof params[key] === 'undefined') {
|
||||||
|
delete params[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPublicApi) {
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
params: params,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// USDC Options uses a different way of authenticating requests (headers instead of params)
|
||||||
|
if (this.isUSDCClient()) {
|
||||||
|
if (!options.headers) {
|
||||||
|
options.headers = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const signResult = await this.prepareSignParams(
|
||||||
|
method,
|
||||||
|
'usdc',
|
||||||
|
params,
|
||||||
|
isPublicApi
|
||||||
|
);
|
||||||
|
|
||||||
|
options.headers['X-BAPI-SIGN-TYPE'] = 2;
|
||||||
|
options.headers['X-BAPI-API-KEY'] = this.key;
|
||||||
|
options.headers['X-BAPI-TIMESTAMP'] = signResult.timestamp;
|
||||||
|
options.headers['X-BAPI-SIGN'] = signResult.sign;
|
||||||
|
options.headers['X-BAPI-RECV-WINDOW'] = signResult.recvWindow;
|
||||||
|
|
||||||
|
if (method === 'GET') {
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
params: signResult.originalParams,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
data: signResult.originalParams,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const signResult = await this.prepareSignParams(
|
||||||
|
method,
|
||||||
|
'keyInBody',
|
||||||
|
params,
|
||||||
|
isPublicApi
|
||||||
|
);
|
||||||
|
|
||||||
|
if (method === 'GET' || this.isSpotClient()) {
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
params: signResult.paramsWithSign,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
data: signResult.paramsWithSign,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,27 +258,20 @@ export default abstract class BaseRestClient {
|
|||||||
params?: any,
|
params?: any,
|
||||||
isPublicApi?: boolean
|
isPublicApi?: boolean
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const options = {
|
// Sanity check to make sure it's only ever signed by
|
||||||
...this.globalRequestOptions,
|
const requestUrl = [this.baseUrl, endpoint].join(
|
||||||
url: [this.baseUrl, endpoint].join(endpoint.startsWith('/') ? '' : '/'),
|
endpoint.startsWith('/') ? '' : '/'
|
||||||
method: method,
|
);
|
||||||
json: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const key in params) {
|
// Build a request and handle signature process
|
||||||
if (typeof params[key] === 'undefined') {
|
const options = await this.buildRequest(
|
||||||
delete params[key];
|
method,
|
||||||
}
|
requestUrl,
|
||||||
}
|
params,
|
||||||
|
isPublicApi
|
||||||
const signResult = await this.prepareSignParams(params, isPublicApi);
|
);
|
||||||
|
|
||||||
if (method === 'GET' || this.isSpotClient()) {
|
|
||||||
options.params = signResult.paramsWithSign;
|
|
||||||
} else {
|
|
||||||
options.data = signResult.paramsWithSign;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Dispatch request
|
||||||
return axios(options)
|
return axios(options)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status == 200) {
|
if (response.status == 200) {
|
||||||
@@ -215,37 +316,70 @@ export default abstract class BaseRestClient {
|
|||||||
/**
|
/**
|
||||||
* @private sign request and set recv window
|
* @private sign request and set recv window
|
||||||
*/
|
*/
|
||||||
private async signRequest<T extends Object>(
|
private async signRequest<T = {}>(
|
||||||
data: T & SignedRequestContext
|
data: T,
|
||||||
|
method: Method,
|
||||||
|
signMethod: SignMethod
|
||||||
): Promise<SignedRequest<T>> {
|
): Promise<SignedRequest<T>> {
|
||||||
|
const timestamp = Date.now() + (this.timeOffset || 0);
|
||||||
|
|
||||||
const res: SignedRequest<T> = {
|
const res: SignedRequest<T> = {
|
||||||
originalParams: {
|
originalParams: {
|
||||||
...data,
|
...data,
|
||||||
api_key: this.key,
|
|
||||||
timestamp: Date.now() + (this.timeOffset || 0),
|
|
||||||
},
|
},
|
||||||
sign: '',
|
sign: '',
|
||||||
|
timestamp,
|
||||||
|
recvWindow: 0,
|
||||||
|
serializedParams: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!this.key || !this.secret) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
const key = this.key;
|
||||||
|
const recvWindow =
|
||||||
|
res.originalParams.recv_window || this.options.recv_window || 5000;
|
||||||
|
const strictParamValidation = this.options.strict_param_validation;
|
||||||
|
|
||||||
|
// In case the parent function needs it (e.g. USDC uses a header)
|
||||||
|
res.recvWindow = recvWindow;
|
||||||
|
|
||||||
|
// usdc is different for some reason
|
||||||
|
if (signMethod === 'usdc') {
|
||||||
|
const signRequestParams =
|
||||||
|
method === 'GET'
|
||||||
|
? serializeParams(res.originalParams, strictParamValidation)
|
||||||
|
: JSON.stringify(res.originalParams);
|
||||||
|
|
||||||
|
const paramsStr = timestamp + key + recvWindow + signRequestParams;
|
||||||
|
res.sign = await signMessage(paramsStr, this.secret);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// spot/v2 derivatives
|
||||||
|
if (signMethod === 'keyInBody') {
|
||||||
|
res.originalParams.api_key = key;
|
||||||
|
res.originalParams.timestamp = timestamp;
|
||||||
|
|
||||||
// Optional, set to 5000 by default. Increase if timestamp/recv_window errors are seen.
|
// Optional, set to 5000 by default. Increase if timestamp/recv_window errors are seen.
|
||||||
if (this.options.recv_window && !res.originalParams.recv_window) {
|
if (recvWindow) {
|
||||||
if (this.isSpotClient()) {
|
if (this.isSpotClient()) {
|
||||||
res.originalParams.recvWindow = this.options.recv_window;
|
res.originalParams.recvWindow = recvWindow;
|
||||||
} else {
|
} else {
|
||||||
res.originalParams.recv_window = this.options.recv_window;
|
res.originalParams.recv_window = recvWindow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.key && this.secret) {
|
res.serializedParams = serializeParams(
|
||||||
const serializedParams = serializeParams(
|
|
||||||
res.originalParams,
|
res.originalParams,
|
||||||
this.options.strict_param_validation
|
strictParamValidation
|
||||||
);
|
);
|
||||||
res.sign = await signMessage(serializedParams, this.secret);
|
res.sign = await signMessage(res.serializedParams, this.secret);
|
||||||
res.paramsWithSign = {
|
res.paramsWithSign = {
|
||||||
...res.originalParams,
|
...res.originalParams,
|
||||||
sign: res.sign,
|
sign: res.sign,
|
||||||
};
|
};
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
3
src/util/index.ts
Normal file
3
src/util/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export * from './BaseRestClient';
|
||||||
|
export * from './requestUtils';
|
||||||
|
export * from './WsStore';
|
||||||
@@ -45,8 +45,8 @@ export function serializeParams(
|
|||||||
export function getRestBaseUrl(
|
export function getRestBaseUrl(
|
||||||
useLivenet: boolean,
|
useLivenet: boolean,
|
||||||
restInverseOptions: RestClientOptions
|
restInverseOptions: RestClientOptions
|
||||||
) {
|
): string {
|
||||||
const baseUrlsInverse = {
|
const exchangeBaseUrls = {
|
||||||
livenet: 'https://api.bybit.com',
|
livenet: 'https://api.bybit.com',
|
||||||
testnet: 'https://api-testnet.bybit.com',
|
testnet: 'https://api-testnet.bybit.com',
|
||||||
};
|
};
|
||||||
@@ -56,9 +56,9 @@ export function getRestBaseUrl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (useLivenet === true) {
|
if (useLivenet === true) {
|
||||||
return baseUrlsInverse.livenet;
|
return exchangeBaseUrls.livenet;
|
||||||
}
|
}
|
||||||
return baseUrlsInverse.testnet;
|
return exchangeBaseUrls.testnet;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isPublicEndpoint(endpoint: string): boolean {
|
export function isPublicEndpoint(endpoint: string): boolean {
|
||||||
@@ -92,11 +92,16 @@ export function isWsPong(response: any) {
|
|||||||
|
|
||||||
export const agentSource = 'bybitapinode';
|
export const agentSource = '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 = {
|
export const REST_CLIENT_TYPE_ENUM = {
|
||||||
|
accountAsset: 'accountAsset',
|
||||||
inverse: 'inverse',
|
inverse: 'inverse',
|
||||||
inverseFutures: 'inverseFutures',
|
inverseFutures: 'inverseFutures',
|
||||||
linear: 'linear',
|
linear: 'linear',
|
||||||
spot: 'spot',
|
spot: 'spot',
|
||||||
|
usdcOptions: 'usdcOptions',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type RestClientType =
|
export type RestClientType =
|
||||||
|
|||||||
67
test/account-asset/private.read.test.ts
Normal file
67
test/account-asset/private.read.test.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import { AccountAssetClient } from '../../src/';
|
||||||
|
import { successResponseObject } from '../response.util';
|
||||||
|
|
||||||
|
describe('Private Account Asset REST API Endpoints', () => {
|
||||||
|
const useLivenet = true;
|
||||||
|
const API_KEY = process.env.API_KEY_COM;
|
||||||
|
const API_SECRET = process.env.API_SECRET_COM;
|
||||||
|
|
||||||
|
it('should have api credentials to test with', () => {
|
||||||
|
expect(API_KEY).toStrictEqual(expect.any(String));
|
||||||
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
|
});
|
||||||
|
|
||||||
|
const api = new AccountAssetClient(API_KEY, API_SECRET, useLivenet);
|
||||||
|
|
||||||
|
it('getInternalTransfers()', async () => {
|
||||||
|
expect(await api.getInternalTransfers()).toMatchObject(
|
||||||
|
successResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSubAccountTransfers()', async () => {
|
||||||
|
expect(await api.getSubAccountTransfers()).toMatchObject(
|
||||||
|
successResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSubAccounts()', async () => {
|
||||||
|
expect(await api.getSubAccounts()).toMatchObject(successResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getUniversalTransfers()', async () => {
|
||||||
|
expect(await api.getInternalTransfers()).toMatchObject(
|
||||||
|
successResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getDepositRecords()', async () => {
|
||||||
|
expect(await api.getDepositRecords()).toMatchObject(
|
||||||
|
successResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getWithdrawRecords()', async () => {
|
||||||
|
expect(await api.getWithdrawRecords()).toMatchObject(
|
||||||
|
successResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getCoinInformation()', async () => {
|
||||||
|
expect(await api.getCoinInformation()).toMatchObject(
|
||||||
|
successResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getAssetInformation()', async () => {
|
||||||
|
expect(await api.getAssetInformation()).toMatchObject(
|
||||||
|
successResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getDepositAddress()', async () => {
|
||||||
|
expect(await api.getDepositAddress('BTC')).toMatchObject(
|
||||||
|
successResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
20
test/account-asset/public.read.test.ts
Normal file
20
test/account-asset/public.read.test.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { AccountAssetClient } from '../../src';
|
||||||
|
import { successResponseObject } from '../response.util';
|
||||||
|
|
||||||
|
describe('Public Account Asset REST API Endpoints', () => {
|
||||||
|
const useLivenet = true;
|
||||||
|
const API_KEY = undefined;
|
||||||
|
const API_SECRET = undefined;
|
||||||
|
|
||||||
|
const api = new AccountAssetClient(API_KEY, API_SECRET, useLivenet);
|
||||||
|
|
||||||
|
it('getSupportedDepositList()', async () => {
|
||||||
|
expect(await api.getSupportedDepositList()).toMatchObject(
|
||||||
|
successResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getServerTime()', async () => {
|
||||||
|
expect(await api.getServerTime()).toMatchObject(successResponseObject());
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -30,7 +30,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.POSITION_IDX_NOT_MATCH_POSITION_MODE,
|
ret_code: API_ERROR_CODE.POSITION_IDX_NOT_MATCH_POSITION_MODE,
|
||||||
ret_msg: 'position idx not match position mode',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,7 +40,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
||||||
ret_msg: 'order not exists or too late to cancel',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -63,7 +61,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
||||||
ret_msg: 'order not exists or too late to replace',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -82,7 +79,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.POSITION_IDX_NOT_MATCH_POSITION_MODE,
|
ret_code: API_ERROR_CODE.POSITION_IDX_NOT_MATCH_POSITION_MODE,
|
||||||
ret_msg: 'position idx not match position mode',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -94,7 +90,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
||||||
ret_msg: 'Order not exists',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -115,7 +110,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
||||||
ret_msg: 'order not exists or too late to replace',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -127,7 +121,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.POSITION_IDX_NOT_MATCH_POSITION_MODE,
|
ret_code: API_ERROR_CODE.POSITION_IDX_NOT_MATCH_POSITION_MODE,
|
||||||
ret_msg: 'position idx not match position mode',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -139,7 +132,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.POSITION_IDX_NOT_MATCH_POSITION_MODE,
|
ret_code: API_ERROR_CODE.POSITION_IDX_NOT_MATCH_POSITION_MODE,
|
||||||
ret_msg: 'position idx not match position mode',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -152,7 +144,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.LEVERAGE_NOT_MODIFIED,
|
ret_code: API_ERROR_CODE.LEVERAGE_NOT_MODIFIED,
|
||||||
ret_msg: 'leverage not modified',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -164,7 +155,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.POSITION_MODE_NOT_MODIFIED,
|
ret_code: API_ERROR_CODE.POSITION_MODE_NOT_MODIFIED,
|
||||||
ret_msg: 'position mode not modified',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -178,7 +168,6 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.ISOLATED_NOT_MODIFIED,
|
ret_code: API_ERROR_CODE.ISOLATED_NOT_MODIFIED,
|
||||||
ret_msg: 'Isolated not modified',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { InverseClient } from '../../src/inverse-client';
|
import { InverseClient } from '../../src/';
|
||||||
import { successResponseList, successResponseObject } from '../response.util';
|
import { successResponseList, successResponseObject } from '../response.util';
|
||||||
|
|
||||||
describe('Private Inverse REST API Endpoints', () => {
|
describe('Private Inverse REST API Endpoints', () => {
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ describe('Private Inverse REST API Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
||||||
ret_msg: 'order not exists or too late to cancel',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -62,7 +61,6 @@ describe('Private Inverse REST API Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
||||||
ret_msg: 'order not exists or too late to replace',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -81,7 +79,6 @@ describe('Private Inverse REST API Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.INSUFFICIENT_BALANCE,
|
ret_code: API_ERROR_CODE.INSUFFICIENT_BALANCE,
|
||||||
ret_msg: 'Insufficient wallet balance',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -93,7 +90,6 @@ describe('Private Inverse REST API Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
||||||
ret_msg: expect.any(String),
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -114,7 +110,6 @@ describe('Private Inverse REST API Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE,
|
||||||
ret_msg: 'order not exists or too late to replace',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -126,7 +121,6 @@ describe('Private Inverse REST API Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.POSITION_IS_CROSS_MARGIN,
|
ret_code: API_ERROR_CODE.POSITION_IS_CROSS_MARGIN,
|
||||||
ret_msg: expect.any(String),
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -138,7 +132,6 @@ describe('Private Inverse REST API Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.CANNOT_SET_TRADING_STOP_FOR_ZERO_POS,
|
ret_code: API_ERROR_CODE.CANNOT_SET_TRADING_STOP_FOR_ZERO_POS,
|
||||||
ret_msg: 'can not set tp/sl/ts for zero position',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -162,7 +155,6 @@ describe('Private Inverse REST API Endpoints', () => {
|
|||||||
})
|
})
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
ret_code: API_ERROR_CODE.SAME_SLTP_MODE,
|
ret_code: API_ERROR_CODE.SAME_SLTP_MODE,
|
||||||
ret_msg: 'same tp sl mode2',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,14 @@ export function successResponseObject(successMsg: string | null = 'OK') {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function successUSDCResponseObject() {
|
||||||
|
return {
|
||||||
|
result: expect.any(Object),
|
||||||
|
retCode: 0,
|
||||||
|
retMsg: expect.stringMatching(/OK|SUCCESS|success|success\./gim),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function errorResponseObject(
|
export function errorResponseObject(
|
||||||
result: null | any = null,
|
result: null | any = null,
|
||||||
ret_code: number,
|
ret_code: number,
|
||||||
|
|||||||
82
test/usdc/options/private.read.test.ts
Normal file
82
test/usdc/options/private.read.test.ts
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
import { USDCOptionsClient } from '../../../src';
|
||||||
|
import {
|
||||||
|
successResponseObject,
|
||||||
|
successUSDCResponseObject,
|
||||||
|
} from '../../response.util';
|
||||||
|
|
||||||
|
describe('Private Account Asset REST API Endpoints', () => {
|
||||||
|
const useLivenet = true;
|
||||||
|
const API_KEY = process.env.API_KEY_COM;
|
||||||
|
const API_SECRET = process.env.API_SECRET_COM;
|
||||||
|
const symbol = 'BTC-30SEP22-400000-C';
|
||||||
|
|
||||||
|
it('should have api credentials to test with', () => {
|
||||||
|
expect(API_KEY).toStrictEqual(expect.any(String));
|
||||||
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
|
});
|
||||||
|
|
||||||
|
const api = new USDCOptionsClient(API_KEY, API_SECRET, useLivenet);
|
||||||
|
const category = 'OPTION';
|
||||||
|
|
||||||
|
it('getActiveRealtimeOrders()', async () => {
|
||||||
|
expect(await api.getActiveRealtimeOrders()).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getActiveOrders()', async () => {
|
||||||
|
expect(await api.getActiveOrders({ category })).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getHistoricOrders()', async () => {
|
||||||
|
expect(await api.getHistoricOrders({ category })).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getOrderExecutionHistory()', async () => {
|
||||||
|
expect(await api.getOrderExecutionHistory({ category })).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getTransactionLog()', async () => {
|
||||||
|
expect(await api.getTransactionLog({ type: 'TRADE' })).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getBalance()', async () => {
|
||||||
|
expect(await api.getBalance()).toMatchObject(successUSDCResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getAssetInfo()', async () => {
|
||||||
|
expect(await api.getAssetInfo()).toMatchObject(successUSDCResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getMarginMode()', async () => {
|
||||||
|
expect(await api.getMarginMode()).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getPositions()', async () => {
|
||||||
|
expect(await api.getPositions({ category })).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getDeliveryHistory()', async () => {
|
||||||
|
expect(await api.getDeliveryHistory({ symbol })).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getPositionsInfoUponExpiry()', async () => {
|
||||||
|
expect(await api.getPositionsInfoUponExpiry()).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
54
test/usdc/options/public.read.test.ts
Normal file
54
test/usdc/options/public.read.test.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { USDCOptionsClient } from '../../../src';
|
||||||
|
import {
|
||||||
|
successResponseObject,
|
||||||
|
successUSDCResponseObject,
|
||||||
|
} from '../../response.util';
|
||||||
|
|
||||||
|
describe('Public USDC Options REST API Endpoints', () => {
|
||||||
|
const useLivenet = true;
|
||||||
|
const API_KEY = undefined;
|
||||||
|
const API_SECRET = undefined;
|
||||||
|
|
||||||
|
const api = new USDCOptionsClient(API_KEY, API_SECRET, useLivenet);
|
||||||
|
const symbol = 'BTC-30SEP22-400000-C';
|
||||||
|
|
||||||
|
it('getOrderBook()', async () => {
|
||||||
|
expect(await api.getOrderBook(symbol)).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getContractInfo()', async () => {
|
||||||
|
expect(await api.getContractInfo()).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSymbolTicker()', async () => {
|
||||||
|
expect(await api.getSymbolTicker(symbol)).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getDeliveryPrice()', async () => {
|
||||||
|
expect(await api.getDeliveryPrice()).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getLastTrades()', async () => {
|
||||||
|
expect(await api.getLastTrades({ category: 'OPTION' })).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getHistoricalVolatility()', async () => {
|
||||||
|
expect(await api.getHistoricalVolatility()).toMatchObject(
|
||||||
|
successUSDCResponseObject()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getServerTime()', async () => {
|
||||||
|
expect(await api.getServerTime()).toMatchObject(successResponseObject());
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user