Merge pull request #224 from tiagosiebler/v5rest

v3.5.0: release RestClientV5 with end-to-end tests for v5 Bybit APIs
This commit is contained in:
Tiago
2023-02-23 12:19:04 +00:00
committed by GitHub
96 changed files with 5537 additions and 1722 deletions

View File

@@ -1,36 +0,0 @@
module.exports = {
env: {
es6: true,
node: true,
},
extends: ['eslint:recommended'],
parserOptions: {
sourceType: 'module',
ecmaVersion: 9
},
plugins: [],
rules: {
'array-bracket-spacing': ['error', 'never'],
indent: ['warn', 2],
'linebreak-style': ['error', 'unix'],
'lines-between-class-members': ['warn', 'always'],
semi: ['error', 'always'],
'new-cap': 'off',
'no-console': 'off',
'no-debugger': 'off',
'no-mixed-spaces-and-tabs': 2,
'no-use-before-define': [2, 'nofunc'],
'no-unreachable': ['warn'],
'no-unused-vars': ['warn'],
'no-extra-parens': ['off'],
'no-mixed-operators': ['off'],
quotes: [2, 'single', 'avoid-escape'],
'block-scoped-var': 2,
'brace-style': [2, '1tbs', { allowSingleLine: true }],
'computed-property-spacing': [2, 'never'],
'keyword-spacing': 2,
'space-unary-ops': 2,
'max-len': ['warn', { 'code': 140 }]
}
};

85
.eslintrc.json Normal file
View File

@@ -0,0 +1,85 @@
{
"env": {
"es6": true,
"node": true
},
"extends": ["eslint:recommended"],
"parser": "@typescript-eslint/parser",
"root": true,
"plugins": ["@typescript-eslint"],
"overrides": [
{
"files": ["**/*.ts", "**/*.tsx"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"parserOptions": {
"projecasdft": true,
"project": [
"./tsconfig.json",
"./tsconfig.examples.json",
"./tsconfig.test.json"
]
},
"rules": {
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-unused-expressions": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-floating-promises": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/promise-function-async": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-ts-comment": "off",
"no-dupe-class-members": "off",
"no-param-reassign": ["error"],
"array-bracket-spacing": ["error", "never"],
"indent": ["off"],
"linebreak-style": ["error", "unix"],
"lines-between-class-members": ["warn", "always"],
"semi": "off",
"@typescript-eslint/semi": ["error"],
"new-cap": "off",
"no-console": "off",
"no-debugger": "off",
"no-mixed-spaces-and-tabs": 2,
"no-use-before-define": [2, "nofunc"],
"no-unreachable": ["warn"],
"no-unused-vars": ["warn"],
"no-extra-parens": ["off"],
"no-mixed-operators": ["off"],
"quotes": [2, "single", "avoid-escape"],
"block-scoped-var": 2,
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
"computed-property-spacing": [2, "never"],
"keyword-spacing": 2,
"space-unary-ops": 2,
"sort-imports": [
"error",
{
"ignoreCase": false,
"ignoreDeclarationSort": true,
"ignoreMemberSort": false,
"memberSyntaxSortOrder": ["none", "all", "multiple", "single"],
"allowSeparatedGroups": false
}
],
"max-len": ["warn", { "code": 140 }]
}
},
{
"files": ["examples/*.js"],
"extends": ["eslint:recommended"]
}
]
}

3
.gitignore vendored
View File

@@ -21,4 +21,5 @@ node_modules/
.cache
lib
bundleReport.html
.history/
.history/
rawReq.ts

2
.nvmrc
View File

@@ -1 +1 @@
v12.18.1
v18.14.1

View File

@@ -13,7 +13,7 @@ Node.js SDK for the Bybit APIs and WebSockets:
- Complete integration with all Bybit APIs.
- TypeScript support (with type declarations for most API requests & responses).
- Over 300 end-to-end tests making real API calls & WebSocket connections, validating any changes before they reach npm.
- Over 450 end-to-end tests making real API calls & WebSocket connections, validating any changes before they reach npm.
- Robust WebSocket integration with configurable connection heartbeats & automatic reconnect then resubscribe workflows.
- Browser support (via webpack bundle - see "Browser Usage" below).
@@ -43,9 +43,9 @@ Check out my related projects:
## Documentation
Most methods accept JS objects. These can be populated using parameters specified by Bybit's API documentation, or check the type definition in each class within this repository (see table below for convenient links to each class).
Most methods accept JS objects. These can be populated using parameters specified by Bybit's API documentation, or check the type definition in each class within the github repository (see table below for convenient links to each class).
- [Bybit API Docs (choose API category from the tabs at the top)](https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-introduction).
- [Bybit API Docs (choose API category from the tabs at the top)](https://bybit-exchange.github.io/docs/v5/intro).
## Structure
@@ -62,18 +62,23 @@ The version on npm is the output from the `build` command and can be used in pro
## REST API Clients
Each REST API group has a dedicated REST client. To avoid confusion, here are the available REST clients and the corresponding API groups:
Bybit has several API groups (originally one per product). Each generation is labelled with the version number (e.g. v1/v2/v3/v5). Some of the newer API groups can only be used by upgrading your account to the unified account, but doing so will prevent you from using the V1 and V2 APIs.
Refer to the [V5 upgrade guide](https://bybit-exchange.github.io/docs/v5/upgrade-guide) for more information on requirements to use each API group. If you have a choice, you should use the newest generation that is available (e.g. use the V5 instead of the V3 APIs if you can).
Here are the available REST clients and the corresponding API groups described in the documentation:
| Class | Description |
|:------------------------------------------------------------------: |:----------------------------------------------------------------------------------------------------------------------------: |
| [ **V5 API** ] | The new unified V5 APIs (successor to previously fragmented APIs for all API groups). To learn more about the V5 API, please read the [V5 upgrade guideline](https://bybit-exchange.github.io/docs/v5/upgrade-guide). |
| [RestClientV5](src/rest-client-v5.ts) | Coming soon... Unified V5 all-in-one REST client for all [V5 REST APIs](https://bybit-exchange.github.io/docs/v5/intro) |
| [RestClientV5](src/rest-client-v5.ts) | Unified V5 all-in-one REST client for all [V5 REST APIs](https://bybit-exchange.github.io/docs/v5/intro) |
| [ **Derivatives v3** ] | The Derivatives v3 APIs (successor to the Futures V2 APIs) |
| [UnifiedMarginClient](src/unified-margin-client.ts) | [Derivatives (v3) Unified Margin APIs](https://bybit-exchange.github.io/docs/derivatives/unified/place-order) |
| [ContractClient](src/contract-client.ts) | [Derivatives (v3) Contract APIs](https://bybit-exchange.github.io/docs/derivatives/contract/place-order). |
| [ **Futures v2** ] | The Futures v2 APIs |
| [InverseClient](src/inverse-client.ts) | [Inverse Perpetual Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/inverse/) |
| [LinearClient](src/linear-client.ts) | [USDT Perpetual Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/linear/#t-introduction) |
| [InverseFuturesClient](src/inverse-futures-client.ts) | [Inverse Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/inverse_futures/#t-introduction) |
| Deprecated! ContractClient or RestClientV5 recommended | Please read the [V5 upgrade guideline](https://bybit-exchange.github.io/docs/v5/upgrade-guide) |
| [~InverseClient~](src/inverse-client.ts)| [Inverse Perpetual Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/inverse/) |
| [~LinearClient~](src/linear-client.ts) | [USDT Perpetual Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/linear/#t-introduction) |
| [~InverseFuturesClient~](src/inverse-futures-client.ts) | [Inverse Futures (v2) APIs](https://bybit-exchange.github.io/docs/futuresV2/inverse_futures/#t-introduction) |
| [ **Spot** ] | The spot APIs |
| [SpotClientV3](src/spot-client-v3.ts) | [Spot Market (v3) APIs](https://bybit-exchange.github.io/docs/spot/public/instrument) |
| [~SpotClient~](src/spot-client.ts) (deprecated, SpotClientV3 recommended)| [Spot Market (v1) APIs](https://bybit-exchange.github.io/docs/spot/v1/#t-introduction) |
@@ -109,13 +114,13 @@ const {
InverseClient,
LinearClient,
InverseFuturesClient,
SpotClient,
SpotClientV3,
UnifiedMarginClient,
USDCOptionClient,
USDCPerpetualClient,
AccountAssetClient,
CopyTradingClient,
RestClientV5,
} = require('bybit-api');
const restClientOptions = {
@@ -154,7 +159,7 @@ const API_KEY = 'xxx';
const API_SECRET = 'yyy';
const useTestnet = false;
const client = new InverseClient({
const client = new RestClientV5({
key: API_KEY,
secret: API_SECRET,
testnet: useTestnet
@@ -163,17 +168,17 @@ const client = new InverseClient({
);
// For public-only API calls, simply don't provide a key & secret or set them to undefined
// const client = new InverseClient({});
// const client = new RestClientV5({});
client.getApiKeyInfo()
client.getAccountInfo()
.then(result => {
console.log("getApiKeyInfo result: ", result);
console.log("getAccountInfo result: ", result);
})
.catch(err => {
console.error("getApiKeyInfo error: ", err);
console.error("getAccountInfo error: ", err);
});
client.getOrderBook({ symbol: 'BTCUSD' })
client.getOrderbook({ category: 'linear', symbol: 'BTCUSD' })
.then(result => {
console.log("getOrderBook result: ", result);
})
@@ -201,6 +206,7 @@ The WebsocketClient can be configured to a specific API group using the market p
| USDC Options | `market: 'usdcOption'`| The [USDC options](https://bybit-exchange.github.io/docs/usdc/option/#t-websocket) category. |
| Contract v3 USDT | `market: 'contractUSDT'`| The [Contract V3](https://bybit-exchange.github.io/docs/derivativesV3/contract/#t-websocket) category (USDT perps) |
| Contract v3 Inverse | `market: 'contractInverse'`| The [Contract V3](https://bybit-exchange.github.io/docs/derivativesV3/contract/#t-websocket) category (inverse perps) |
| V5 Subscriptions | Coming soon | The [v5](https://bybit-exchange.github.io/docs/v5/ws/connect) websockets will be supported in the next release. |
```javascript
const { WebsocketClient } = require('bybit-api');

View File

@@ -0,0 +1,33 @@
import { ContractClient } from '../src/index';
// or
// import { ContractClient } from 'bybit-api';
const key = process.env.API_KEY_COM;
const secret = process.env.API_SECRET_COM;
const client = new ContractClient({
key,
secret,
strict_param_validation: true,
});
(async () => {
try {
/**
* You can make raw HTTP requests without the per-endpoint abstraction.
*
* The REST ContractClient uses bybit's v3 signature mechanism,
* so it can be used for raw calls to any v3-supporting endpoints (incl the V5 APIs).
* e.g. if an endpoint is missing and you desperately need it (but please raise an issue or PR if you're missing an endpoint)
*/
const rawCall = await client.getPrivate('/v5/order/realtime', {
category: 'linear',
symbol: 'BTCUSDT',
});
console.log('rawCall:', rawCall);
} catch (e) {
console.error('request failed: ', e);
}
})();

46
examples/rest-v5-all.ts Normal file
View File

@@ -0,0 +1,46 @@
import { RestClientV5 } from '../src/index';
// or
// import { RestClientV5 } from 'bybit-api';
const key = process.env.API_KEY_COM;
const secret = process.env.API_SECRET_COM;
const client = new RestClientV5({
key: key,
secret: secret,
});
/**
* If you don't plan on making any private api calls,
* you can instance the REST client without any parameters:
*
* const client = new RestClientV5();
*/
(async () => {
try {
const klineResult = await client.getKline({
category: 'linear',
interval: '15',
symbol: 'BTCUSDT',
});
console.log('klineResult: ', klineResult);
const markPriceKlineResult = await client.getMarkPriceKline({
category: 'linear',
interval: '15',
symbol: 'BTCUSDT',
});
console.log('markPriceKlineResult: ', markPriceKlineResult);
const indexPriceKline = await client.getIndexPriceKline({
category: 'linear',
interval: '15',
symbol: 'BTCUSDT',
});
console.log('indexPriceKline: ', indexPriceKline);
} catch (e) {
console.error('request failed: ', e);
}
})();

View File

@@ -0,0 +1,45 @@
import { RestClientV5 } from '../src/index';
// or
// import { RestClientV5 } from 'bybit-api';
const key = process.env.API_KEY_COM;
const secret = process.env.API_SECRET_COM;
const client = new RestClientV5({
key: key,
secret: secret,
});
(async () => {
try {
/** Simple examples for private REST API calls with bybit's V5 REST APIs */
const response = await client.getPositionInfo({
category: 'option',
symbol: 'BTCUSDT',
});
console.log('response:', response);
// Trade USDT linear perps
const buyOrderResult = await client.submitOrder({
category: 'linear',
symbol: 'BTCUSDT',
orderType: 'Market',
qty: '1',
side: 'Buy',
});
console.log('buyOrderResult:', buyOrderResult);
const sellOrderResult = await client.submitOrder({
category: 'linear',
symbol: 'BTCUSDT',
orderType: 'Market',
qty: '1',
side: 'Sell',
});
console.log('sellOrderResult:', sellOrderResult);
} catch (e) {
console.error('request failed: ', e);
}
})();

View File

@@ -1,4 +1,7 @@
import { WebsocketClient, WS_KEY_MAP, DefaultLogger } from '../src';
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-empty-function */
import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../src';
// or
// import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from 'bybit-api';

View File

@@ -18,8 +18,8 @@ import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../src';
// market: 'spot',
// market: 'spotv3',
// market: 'usdcOption',
// market: 'usdcPerp',
market: 'unifiedPerp',
market: 'usdcPerp',
// market: 'unifiedPerp',
// market: 'unifiedOption',
},
logger
@@ -138,11 +138,13 @@ import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../src';
// ]);
// usdc perps (note: the syntax is different for the unified perp market)
// (market: 'usdcPerp')
// wsClient.subscribe('trade.BTCUSDC');
wsClient.subscribe('instrument_info.100ms.BTCPERP');
// unified perps
// wsClient.subscribe('publicTrade.BTCUSDT');
wsClient.subscribe('publicTrade.BTCPERP');
// wsClient.subscribe('publicTrade.BTCPERP');
// For spot v1 (the old, deprecated client), request public connection first then send required topics on 'open'
// Not necessary for spot v3

2644
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "bybit-api",
"version": "3.4.2",
"description": "Complete & robust node.js SDK for Bybit's REST APIs and WebSockets, with TypeScript & integration tests.",
"version": "3.5.0",
"description": "Complete & robust Node.js SDK for Bybit's REST APIs and WebSockets, with TypeScript & strong end to end tests.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
@@ -29,12 +29,14 @@
"ws": "^7.4.0"
},
"devDependencies": {
"@types/jest": "^26.0.23",
"@types/jest": "^27.0.4",
"@types/node": "^14.14.7",
"eslint": "^7.10.0",
"@typescript-eslint/eslint-plugin": "^5.46.0",
"@typescript-eslint/parser": "^5.46.0",
"eslint": "^8.29.0",
"jest": "^27.0.4",
"source-map-loader": "^2.0.0",
"ts-jest": "^27.0.3",
"ts-jest": "^27.0.4",
"ts-loader": "^8.0.11",
"typescript": "^4.0.5",
"webpack": "^5.4.0",

View File

@@ -1,10 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
AccountCoinBalanceResponseV3,
AccountCoinBalancesRequestV3,
AccountCoinBalancesResponseV3,
APIKeyInfoV3,
APIResponseV3WithTime,
APIResponseWithTime,
AccountCoinBalanceResponseV3,
AccountCoinBalancesRequestV3,
AccountCoinBalancesResponseV3,
AssetInfoRequestV3,
AssetInfoResponseV3,
CoinInfoQueryResponseV3,
@@ -18,8 +19,8 @@ import {
InternalTransferRequestV3,
ModifyAPIKeyRequestV3,
QueryDepositAddressRequestV3,
QueryInternalTransfersRequestV3,
QueryInternalTransferSResponseV3,
QueryInternalTransfersRequestV3,
QuerySubAccountDepositAddressRequestV3,
SingleAccountCoinBalanceRequestV3,
SubAccountTransferRequestV3,

View File

@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
AccountAssetInformationRequest,
APIResponseWithTime,
AccountAssetInformationRequest,
DepositRecordsRequest,
EnableUniversalTransferRequest,
InternalTransferRequest,

View File

@@ -44,9 +44,20 @@ export const API_ERROR_CODE = {
POSITION_MODE_NOT_MODIFIED: 30083,
ISOLATED_NOT_MODIFIED: 30084,
RISK_LIMIT_NOT_EXISTS: 30090,
SUB_USER_ALREADY_EXISTS: 31005,
LEVERAGE_NOT_MODIFIED: 34036,
SAME_SLTP_MODE: 37002,
COPY_TRADE_NOT_OPEN_ORDER: 39426,
V5_ORDER_NOT_FOUND: 110001,
V5_INSUFFICIENT_BALANCE: 110007,
V5_API_KEY_PERMISSION_DENIED: 10005,
V5_CROSS_ISOLATED_MARGIN_NOT_CHANGED: 110026,
V5_LEVERAGE_NOT_CHANGED: 110043,
V5_MARGIN_MODE_NOT_CHANGED: 110073,
V5_TPSL_NOT_CHANGED: 10001,
V5_RISK_ID_NOT_CHANGED: 10001,
V5_AUTO_ADD_MARGIN_NOT_CHANGED: 10001,
V5_TPSL_ERROR_NO_POSITION: 10001,
QTY_EXCEEDS_MAX_LIMIT: 130006,
ORDER_NOT_FOUND_OR_TOO_LATE_LINEAR: 130010,
ORDER_COST_NOT_AVAILABLE: 130021,
@@ -56,6 +67,7 @@ export const API_ERROR_CODE = {
AUTO_ADD_MARGIN_NOT_MODIFIED: 130060,
INSUFFICIENT_BALANCE_FOR_ORDER_COST_LINEAR: 130080,
SAME_SLTP_MODE_LINEAR: 130150,
TRANSFER_ID_EXISTS: 131214,
RISK_ID_NOT_MODIFIED: 134026,
CONTRACT_ORDER_NOT_EXISTS: 140001,
CONTRACT_INSUFFICIENT_BALANCE: 140007,
@@ -63,6 +75,12 @@ export const API_ERROR_CODE = {
CONTRACT_MARGIN_MODE_NOT_MODIFIED: 140026,
CONTRACT_RISK_LIMIT_INFO_NOT_EXISTS: 140031,
CONTRACT_SET_LEVERAGE_NOT_MODIFIED: 140043,
SUB_USER_NOT_FOUND: 141009,
SPOT_LEVERAGE_TOKEN_INSUFFICIENT_BALANCE: 175006,
SPOT_LEVERAGE_TOKEN_ORDER_NOT_FOUND: 175007,
SPOT_LEVERAGE_QUIZ_REQUIRED: 175010,
SPOT_MARGIN_NOT_ENABLED: 176008,
SPOT_MARGIN_QUESTIONNAIRE_NOT_SUBMIT: 176037,
/** E.g. USDC Options trading, trying to access a symbol that is no longer active */
CONTRACT_NAME_NOT_EXIST: 3100111,
ORDER_NOT_EXIST: 3100136,

View File

@@ -1,6 +1,24 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
APIResponseWithTime,
APIResponseV3,
APIResponseWithTime,
ContractActiveOrdersRequest,
ContractCancelOrderRequest,
ContractClosedPNLRequest,
ContractHistoricOrder,
ContractHistoricOrdersRequest,
ContractListResult,
ContractModifyOrderRequest,
ContractOrderRequest,
ContractPositionsRequest,
ContractSetAutoAddMarginRequest,
ContractSetMarginSwitchRequest,
ContractSetPositionModeRequest,
ContractSetTPSLRequest,
ContractSymbolTicker,
ContractUserExecutionHistoryRequest,
ContractWalletFundRecordRequest,
PaginatedResult,
UMCandlesRequest,
UMCategory,
UMFundingRateHistoryRequest,
@@ -8,23 +26,6 @@ import {
UMOpenInterestRequest,
UMOptionDeliveryPriceRequest,
UMPublicTradesRequest,
ContractOrderRequest,
ContractHistoricOrdersRequest,
ContractCancelOrderRequest,
ContractModifyOrderRequest,
ContractActiveOrdersRequest,
ContractPositionsRequest,
ContractSetAutoAddMarginRequest,
ContractSetMarginSwitchRequest,
ContractSetPositionModeRequest,
ContractSetTPSLRequest,
ContractUserExecutionHistoryRequest,
ContractClosedPNLRequest,
ContractWalletFundRecordRequest,
PaginatedResult,
ContractHistoricOrder,
ContractSymbolTicker,
ContractListResult,
} from './types';
import { REST_CLIENT_TYPE_ENUM } from './util';
import BaseRestClient from './util/BaseRestClient';

View File

@@ -1,4 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
APIResponseV3,
APIResponseWithTime,
CopyTradingCancelOrderRequest,
CopyTradingCloseOrderRequest,
@@ -6,7 +8,6 @@ import {
CopyTradingOrderRequest,
CopyTradingTradingStopRequest,
CopyTradingTransferRequest,
APIResponseV3,
} from './types';
import { REST_CLIENT_TYPE_ENUM } from './util';
import BaseRestClient from './util/BaseRestClient';

View File

@@ -4,6 +4,7 @@ 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';

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { REST_CLIENT_TYPE_ENUM } from './util';
import {
APIResponseWithTime,

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { REST_CLIENT_TYPE_ENUM } from './util/requestUtils';
import {
APIResponseWithTime,

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { REST_CLIENT_TYPE_ENUM } from './util/requestUtils';
import {
APIResponse,
@@ -37,7 +38,6 @@ import {
WalletFundRecordsReq,
WithdrawRecordsReq,
} from './types';
import { linearPositionModeEnum, positionTpSlModeEnum } from './constants/enum';
import BaseRestClient from './util/BaseRestClient';
/**
@@ -273,6 +273,7 @@ export class LinearClient extends BaseRestClient {
*/
getPosition(): Promise<APIResponseWithTime<PerpPositionRoot[]>>;
getPosition(
params: Partial<SymbolParam>
): Promise<APIResponseWithTime<PerpPosition[]>>;
@@ -344,7 +345,10 @@ export class LinearClient extends BaseRestClient {
getHistoryTradeRecords(
params: LinearGetHistoryTradeRecordsRequest
): Promise<APIResponseWithTime<any>> {
return this.getPrivate('/private/linear/trade/execution/history-list', params);
return this.getPrivate(
'/private/linear/trade/execution/history-list',
params
);
}
getClosedPnl(

1257
src/rest-client-v5.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,16 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
APIResponseWithTime,
APIResponseV3,
SpotOrderQueryById,
OrderSide,
OrderTypeSpot,
SpotBalances,
APIResponseWithTime,
KlineInterval,
NewSpotOrderV3,
SpotMyTradesRequest,
SpotLeveragedTokenPRHistoryRequest,
SpotBalances,
SpotCancelOrderBatchRequest,
SpotCrossMarginBorrowingInfoRequest,
SpotCrossMarginRepaymentHistoryRequest,
SpotCancelOrderBatchRequest,
SpotLeveragedTokenPRHistoryRequest,
SpotMyTradesRequest,
SpotOrderQueryById,
} from './types';
import { REST_CLIENT_TYPE_ENUM } from './util';
import BaseRestClient from './util/BaseRestClient';
@@ -167,6 +166,7 @@ export class SpotClientV3 extends BaseRestClient {
symbol,
orderId,
limit,
orderCategory,
});
}

View File

@@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
NewSpotOrder,
APIResponse,
KlineInterval,
NewSpotOrder,
OrderSide,
OrderTypeSpot,
SpotBalances,
@@ -87,7 +88,9 @@ export class SpotClient extends BaseRestClient {
}
getLastTradedPrice(): Promise<APIResponse<SpotLastPrice[]>>;
getLastTradedPrice(symbol: string): Promise<APIResponse<SpotLastPrice>>;
getLastTradedPrice(
symbol?: string
): Promise<APIResponse<SpotLastPrice | SpotLastPrice[]>> {

View File

@@ -1,4 +1,5 @@
export * from './response';
export * from './request';
export * from './shared';
export * from './v5-shared';
export * from './websockets';

View File

@@ -1,5 +1,6 @@
export * from './account-asset';
export * from './copy-trading';
export * from './contract';
export * from './linear';
export * from './inverse';
export * from './spot';
@@ -7,4 +8,10 @@ export * from './usdc-perp';
export * from './usdc-options';
export * from './usdc-shared';
export * from './unified-margin';
export * from './contract';
export * from './v5-account';
export * from './v5-asset';
export * from './v5-market';
export * from './v5-position';
export * from './v5-trade';
export * from './v5-user';
export * from './v5-spot-leverage-token';

View File

@@ -1,4 +1,4 @@
import { numberInString, OrderSide } from '../shared';
import { OrderSide, numberInString } from '../shared';
export type OrderTypeSpot = 'LIMIT' | 'MARKET' | 'LIMIT_MAKER';
export type OrderTimeInForce = 'GTC' | 'FOK' | 'IOC';

View File

@@ -0,0 +1,34 @@
import { AccountTypeV5, CategoryV5, TransactionTypeV5 } from '../v5-shared';
export interface GetWalletBalanceParamsV5 {
accountType: AccountTypeV5;
coin?: string;
}
export interface GetBorrowHistoryParamsV5 {
currency?: string;
startTime?: number;
endTime?: number;
limit?: number;
cursor?: string;
}
export interface GetTransactionLogParamsV5 {
accountType?: AccountTypeV5;
category?: CategoryV5;
currency?: string;
baseCoin?: string;
type?: TransactionTypeV5;
startTime?: number;
endTime?: number;
limit?: number;
cursor?: string;
}
export interface MMPModifyParamsV5 {
baseCoin: string;
window: string;
frozenPeriod: string;
qtyLimit: string;
deltaLimit: string;
}

View File

@@ -0,0 +1,123 @@
import { AccountTypeV5, CategoryV5 } from '../v5-shared';
export interface GetCoinExchangeRecordParamsV5 {
fromCoin?: string;
toCoin?: string;
limit?: number;
cursor?: string;
}
export interface GetDeliveryRecordParamsV5 {
category: CategoryV5;
symbol?: string;
expDate?: string;
limit?: number;
cursor?: string;
}
export interface GetSettlementRecordParamsV5 {
category: CategoryV5;
symbol?: string;
limit?: number;
cursor?: string;
}
export interface GetAssetInfoParamsV5 {
accountType: AccountTypeV5;
coin?: string;
}
export interface GetAllCoinsBalanceParamsV5 {
memberId?: string;
accountType: AccountTypeV5;
coin?: string;
withBonus?: number;
}
export interface GetAccountCoinBalanceParamsV5 {
memberId?: string;
accountType: AccountTypeV5;
coin: string;
withBonus?: number;
}
export interface GetInternalTransferParamsV5 {
transferId?: string;
coin?: string;
status?: string;
startTime?: number;
endTime?: number;
limit?: number;
cursor?: string;
}
export interface UniversalTransferParamsV5 {
transferId: string;
coin: string;
amount: string;
fromMemberId: number;
toMemberId: number;
fromAccountType: AccountTypeV5;
toAccountType: AccountTypeV5;
}
export interface GetUniversalTransferRecordsParamsV5 {
transferId?: string;
coin?: string;
status?: string;
startTime?: number;
endTime?: number;
limit?: number;
cursor?: string;
}
export interface GetAllowedDepositCoinInfoParamsV5 {
coin?: string;
chain?: string;
limit?: number;
cursor?: string;
}
export interface GetDepositRecordParamsV5 {
coin?: string;
startTime?: number;
endTime?: number;
limit?: number;
cursor?: string;
}
export interface GetSubAccountDepositRecordParamsV5 {
subMemberId: string;
coin?: string;
startTime?: number;
endTime?: number;
limit?: number;
cursor?: string;
}
export interface GetWithdrawalRecordsParamsV5 {
withdrawID?: string;
coin?: string;
withdrawType?: number;
startTime?: number;
endTime?: number;
limit?: number;
cursor?: string;
}
export interface WithdrawParamsV5 {
coin: string;
chain: string;
address: string;
tag?: string;
amount: string;
forceChain?: number;
accountType?: 'SPOT' | 'FUND';
}
export interface CreateSubMemberParamsV5 {
username: string;
memberType: 1 | 6;
switch?: 0 | 1;
note?: string;
}

View File

@@ -0,0 +1,118 @@
import { KlineIntervalV3 } from '../shared';
import { CategoryV5, OptionTypeV5 } from '../v5-shared';
export interface GetKlineParamsV5 {
category: 'spot' | 'linear' | 'inverse';
symbol: string;
interval: KlineIntervalV3;
start?: number;
end?: number;
limit?: number;
}
export interface GetMarkPriceKlineParamsV5 {
category: 'linear' | 'inverse';
symbol: string;
interval: KlineIntervalV3;
start?: number;
end?: number;
limit?: number;
}
export interface GetIndexPriceKlineParamsV5 {
category: 'linear' | 'inverse';
symbol: string;
interval: KlineIntervalV3;
start?: number;
end?: number;
limit?: number;
}
export interface GetPremiumIndexPriceKlineParamsV5 {
category: 'linear';
symbol: string;
interval: KlineIntervalV3;
start?: number;
end?: number;
limit?: number;
}
export interface GetInstrumentsInfoParamsV5 {
category: CategoryV5;
symbol?: string;
baseCoin?: string;
limit?: number;
cursor?: string;
}
export interface GetOrderbookParamsV5 {
category: CategoryV5;
symbol: string;
limit?: number;
}
export interface GetTickersParamsV5 {
category: CategoryV5;
symbol?: string;
baseCoin?: string;
expDate?: string;
}
export interface GetFundingRateHistoryParamsV5 {
category: 'linear' | 'inverse';
symbol: string;
startTime?: number;
endTime?: number;
limit?: number;
}
export interface GetPublicTradingHistoryParamsV5 {
category: CategoryV5;
symbol: string;
baseCoin?: string;
optionType?: OptionTypeV5;
limit?: number;
}
export type OpenInterestIntervalV5 =
| '5min'
| '15min'
| '30min'
| '1h'
| '4h'
| '1d';
export interface GetOpenInterestParamsV5 {
category: 'linear' | 'inverse';
symbol: string;
intervalTime: OpenInterestIntervalV5;
startTime?: number;
endTime?: number;
limit?: number;
cursor?: string;
}
export interface GetHistoricalVolatilityParamsV5 {
category: 'option';
baseCoin?: string;
period?: number;
startTime?: number;
endTime?: number;
}
export interface GetInsuranceParamsV5 {
coin?: string;
}
export interface GetRiskLimitParamsV5 {
category?: 'linear' | 'inverse';
symbol?: string;
}
export interface GetOptionDeliveryPriceParamsV5 {
category: 'option';
symbol?: string;
baseCoin?: string;
limit?: number;
cursor?: string;
}

View File

@@ -0,0 +1,94 @@
import {
CategoryV5,
ExecTypeV5,
OrderTriggerByV5,
PositionIdx,
TPSLModeV5,
} from '../v5-shared';
export interface PositionInfoParamsV5 {
category: CategoryV5;
symbol?: string;
baseCoin?: string;
settleCoin?: string;
limit?: number;
cursor?: string;
}
export interface SetLeverageParamsV5 {
category: 'linear' | 'inverse';
symbol: string;
buyLeverage: string;
sellLeverage: string;
}
export interface SwitchIsolatedMarginParamsV5 {
category: 'linear' | 'inverse';
symbol: string;
tradeMode: 0 | 1;
buyLeverage: string;
sellLeverage: string;
}
export interface SetTPSLModeParamsV5 {
category: 'linear' | 'inverse';
symbol: string;
tpSlMode: TPSLModeV5;
}
export interface SwitchPositionModeParamsV5 {
category: 'linear' | 'inverse';
symbol?: string;
coin?: string;
mode: 0 | 3;
}
export interface SetRiskLimitParamsV5 {
category: 'linear' | 'inverse';
symbol: string;
riskId: number;
positionIdx?: PositionIdx;
}
export interface SetTradingStopParamsV5 {
symbol: string;
category: CategoryV5;
takeProfit?: string;
stopLoss?: string;
trailingStop?: string;
tpTriggerBy?: OrderTriggerByV5;
slTriggerBy?: OrderTriggerByV5;
activePrice?: string;
tpSize?: string;
slSize?: string;
positionIdx: PositionIdx;
}
export interface SetAutoAddMarginParamsV5 {
category: 'linear';
symbol: string;
autoAddMargin: 0 | 1;
positionIdx?: PositionIdx;
}
export interface GetExecutionListParamsV5 {
category: CategoryV5;
symbol?: string;
orderId?: string;
orderLinkId?: string;
baseCoin?: string;
startTime?: number;
endTime?: number;
execType?: ExecTypeV5;
limit?: number;
cursor?: string;
}
export interface GetClosedPnLParamsV5 {
category: CategoryV5;
symbol?: string;
startTime?: number;
endTime?: number;
limit?: number;
cursor?: string;
}

View File

@@ -0,0 +1,23 @@
import { LTOrderTypeV5 } from '../v5-shared';
export interface PurchaseSpotLeveragedTokenParamsV5 {
ltCoin: string;
amount: string;
serialNo?: string;
}
export interface RedeemSpotLeveragedTokenParamsV5 {
ltCoin: string;
quantity: string;
serialNo?: string;
}
export interface GetSpotLeveragedTokenOrderHistoryParamsV5 {
ltCoin?: string;
orderId?: string;
startTime?: number;
endTime?: number;
limit?: number;
ltOrderType?: LTOrderTypeV5;
serialNo?: string;
}

View File

@@ -0,0 +1,107 @@
import {
CategoryV5,
OrderFilterV5,
OrderSideV5,
OrderTimeInForceV5,
OrderTriggerByV5,
OrderTypeV5,
PositionIdx,
} from '../v5-shared';
export interface OrderParamsV5 {
category: CategoryV5;
symbol: string;
isLeverage?: 0 | 1;
side: OrderSideV5;
orderType: OrderTypeV5;
qty: string;
price?: string;
triggerDirection?: 1 | 2;
orderFilter?: 'Order' | 'tpslOrder';
triggerPrice?: string;
triggerBy?: OrderTriggerByV5;
orderIv?: string;
timeInForce?: OrderTimeInForceV5;
positionIdx?: PositionIdx;
orderLinkId?: string;
takeProfit?: string;
stopLoss?: string;
tpTriggerBy?: OrderTriggerByV5;
slTriggerBy?: OrderTriggerByV5;
reduceOnly?: boolean;
closeOnTrigger?: boolean;
mmp?: boolean;
}
export interface AmendOrderParamsV5 {
category: CategoryV5;
symbol: string;
orderId?: string;
orderLinkId?: string;
orderIv?: string;
triggerPrice?: string;
qty?: string;
price?: string;
takeProfit?: string;
stopLoss?: string;
tpTriggerBy?: OrderTriggerByV5;
slTriggerBy?: OrderTriggerByV5;
triggerBy?: OrderTriggerByV5;
}
export interface CancelOrderParamsV5 {
category: CategoryV5;
symbol: string;
orderId?: string;
orderLinkId?: string;
orderFilter?: OrderFilterV5;
}
export interface GetAccountOrdersParams {
category: CategoryV5;
symbol?: string;
baseCoin?: string;
settleCoin?: string;
orderId?: string;
orderLinkId?: string;
openOnly?: 0 | 1 | 2;
orderFilter?: OrderFilterV5;
limit?: number;
cursor?: string;
}
export interface CancelAllOrdersParamsV5 {
category: CategoryV5;
symbol?: string;
baseCoin?: string;
settleCoin?: string;
orderFilter?: OrderFilterV5;
}
export interface BatchOrderParamsV5 {
symbol: string;
side: OrderSideV5;
orderType: OrderTypeV5;
qty: string;
price?: string;
orderIv?: string;
timeInForce?: OrderTimeInForceV5;
orderLinkId: string;
reduceOnly?: boolean;
mmp?: boolean;
}
export interface BatchAmendOrderParamsV5 {
symbol: string;
orderId?: string;
orderLinkId?: string;
qty?: string;
price?: string;
orderIv?: string;
}
export interface BatchCancelOrderParamsV5 {
symbol: string;
orderId?: string;
orderLinkId?: string;
}

View File

@@ -0,0 +1,21 @@
import { PermissionsV5 } from '../v5-shared';
export interface CreateSubApiKeyParamsV5 {
subuid: number;
note?: string;
readOnly: 0 | 1;
ips?: string[];
permissions: PermissionsV5;
}
export interface UpdateApiKeyParamsV5 {
readOnly?: 0 | 1;
ips?: string[];
permissions: PermissionsV5;
}
export interface UpdateSubApiKeyUpdateParamsV5 {
readOnly?: number;
ips?: string[];
permissions: PermissionsV5;
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
export interface PaginatedResult<TList = any> {
nextPageCursor: string;
list: TList[];

View File

@@ -4,3 +4,10 @@ export * from './shared';
export * from './spot';
export * from './usdt-perp';
export * from './unified-margin';
export * from './v5-account';
export * from './v5-asset';
export * from './v5-market';
export * from './v5-position';
export * from './v5-trade';
export * from './v5-user';
export * from './v5-spot-leverage-token';

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface UMPaginatedResult<List = any> {
nextPageCursor: string;
category: string;

View File

@@ -0,0 +1,117 @@
import {
AccountMarginModeV5,
AccountTypeV5,
CategoryV5,
TransactionTypeV5,
UnifiedUpdateStatusV5,
} from '../v5-shared';
export interface WalletBalanceV5Coin {
coin: string;
equity: string;
usdValue: string;
walletBalance: string;
borrowAmount: string;
availableToBorrow: string;
availableToWithdraw: string;
accruedInterest: string;
totalOrderIM: string;
totalPositionIM: string;
totalPositionMM: string;
unrealisedPnl: string;
cumRealisedPnl: string;
}
export interface WalletBalanceV5 {
accountType: AccountTypeV5;
accountIMRate: string;
accountMMRate: string;
totalEquity: string;
totalWalletBalance: string;
totalMarginBalance: string;
totalAvailableBalance: string;
totalPerpUPL: string;
totalInitialMargin: string;
totalMaintenanceMargin: string;
coin: WalletBalanceV5Coin[];
}
export interface UnifiedAccountUpgradeResultV5 {
unifiedUpdateStatus: UnifiedUpdateStatusV5;
unifiedUpdateMsg: {
msg: string[] | null;
};
}
export interface BorrowHistoryRecordV5 {
currency: string;
createdTime: number;
borrowCost: string;
hourlyBorrowRate: string;
InterestBearingBorrowSize: string;
costExemption: string;
}
export interface CollateralInfoV5 {
currency: string;
hourlyBorrowRate: string;
maxBorrowingAmount: string;
freeBorrowingAmount: string;
borrowAmount: string;
availableToBorrow: string;
borrowable: boolean;
marginCollateral: boolean;
collateralRatio: string;
}
export interface CoinGreeksV5 {
baseCoin: string;
totalDelta: string;
totalGamma: string;
totalVega: string;
totalTheta: string;
}
export interface FeeRateV5 {
symbol: string;
takerFeeRate: string;
makerFeeRate: string;
}
export interface AccountInfoV5 {
unifiedMarginStatus: number;
marginMode: AccountMarginModeV5;
updatedTime: string;
}
export interface TransactionLogV5 {
symbol: string;
category: CategoryV5;
side: string;
transactionTime: string;
type: TransactionTypeV5;
qty: string;
size: string;
currency: string;
tradePrice: string;
funding: string;
fee: string;
cashFlow: string;
change: string;
cashBalance: string;
feeRate: string;
tradeId: string;
orderId: string;
orderLinkId: string;
}
export interface MMPStateV5 {
baseCoin: string;
mmpEnabled: boolean;
window: string;
frozenPeriod: string;
qtyLimit: string;
deltaLimit: string;
mmpFrozenUntil: string;
mmpFrozen: boolean;
}

View File

@@ -0,0 +1,160 @@
import { AccountTypeV5, OrderSideV5, WithdrawalTypeV5 } from '../v5-shared';
export interface CoinExchangeRecordV5 {
fromCoin: string;
fromAmount: string;
toCoin: string;
toAmount: string;
exchangeRate: string;
createdTime: string;
exchangeTxId: string;
}
export interface DeliveryRecordV5 {
deliveryTime: number;
symbol: string;
side: OrderSideV5;
position: string;
deliveryPrice: string;
strike: string;
fee: string;
deliveryRpl: string;
}
export interface SettlementRecordV5 {
symbol: string;
side: string;
size: number;
sessionAvgPrice: string;
markPrice: string;
realisedPnl: string;
createdTime: string;
}
export interface AssetInfoAssetV5 {
coin: string;
frozen: string;
free: string;
withdraw: string;
}
export interface AssetInfoV5 {
status: 'ACCOUNT_STATUS_NORMAL' | 'ACCOUNT_STATUS_UNSPECIFIED';
assets: AssetInfoAssetV5[];
}
export interface CoinBalanceV5 {
coin: string;
walletBalance: string;
transferBalance: string;
bonus?: string;
}
export interface AllCoinsBalanceV5 {
accountType: AccountTypeV5;
memberId?: string;
balance: CoinBalanceV5[];
}
export interface AccountCoinBalanceV5 {
accountType: AccountTypeV5;
bizType: number;
accountId: string;
memberId: string;
balance: {
coin: string;
walletBalance: string;
transferBalance: string;
bonus: string;
};
}
export interface InternalTransferRecordV5 {
transferId: string;
coin: string;
amount: string;
fromAccountType: AccountTypeV5;
toAccountType: AccountTypeV5;
timestamp: string;
status: string;
}
export interface UniversalTransferRecordV5 {
transferId: string;
coin: string;
amount: string;
fromMemberId: string;
toMemberId: string;
fromAccountType: AccountTypeV5;
toAccountType: AccountTypeV5;
timestamp: string;
status: string;
}
export interface AllowedDepositCoinInfoV5 {
coin: string;
chain: string;
coinShowName: string;
chainType: string;
blockConfirmNumber: number;
minDepositAmount: string;
}
export interface DepositRecordV5 {
coin: string;
chain: string;
amount: string;
txID: string;
status: number;
toAddress: string;
tag: string;
depositFee: string;
successAt: string;
confirmations: string;
txIndex: string;
blockHash: string;
}
export interface DepositAddressChainV5 {
chainType: string;
addressDeposit: string;
tagDeposit: string;
chain: string;
}
export interface DepositAddressResultV5 {
coin: string;
chains: DepositAddressChainV5[];
}
export interface CoinInfoV5 {
name: number;
coin: string;
remainAmount: string;
chains: {
chain: string;
chainType: string;
confirmation: string;
withdrawFee: string;
depositMin: string;
withdrawMin: string;
minAccuracy: string;
chainDeposit: string;
chainWithdraw: string;
}[];
}
export interface WithdrawalRecordV5 {
withdrawId: string;
txID: string;
withdrawType: WithdrawalTypeV5;
coin: string;
chain: string;
amount: string;
withdrawFee: string;
status: string;
toAddress: string;
tag: string;
createTime: string;
updateTime: string;
}

View File

@@ -0,0 +1,264 @@
import {
CategoryCursorListV5,
ContractTypeV5,
InstrumentStatusV5,
OptionTypeV5,
OrderSideV5,
} from '../v5-shared';
/**
* OHLCVT candle used by v5 APIs
*
* - list[0]: startTime string Start time of the candle (ms)
* - list[1]: openPrice string Open price
* - list[2]: highPrice string Highest price
* - list[3]: lowPrice string Lowest price
* - list[4]: closePrice string Close price. Is the last traded price when the candle is not closed
* - list[5]: volume string Trade volume. Unit of contract: pieces of contract. Unit of spot: quantity of coins
* - list[6]: turnover string Turnover. Unit of figure: quantity of quota coin
*/
export type OHLCVKlineV5 = [
string,
string,
string,
string,
string,
string,
string
];
/**
* OHLC candle used by v5 APIs
*
* - list[0]: startTime string Start time of the candle (ms)
* - list[1]: openPrice string Open price
* - list[2]: highPrice string Highest price
* - list[3]: lowPrice string Lowest price
* - list[4]: closePrice string Close price. Is the last traded price when the candle is not closed
*/
export type OHLCKlineV5 = [string, string, string, string, string];
export interface LinearInverseInstrumentInfoV5 {
symbol: string;
contractType: ContractTypeV5;
status: InstrumentStatusV5;
baseCoin: string;
quoteCoin: string;
launchTime: string;
deliveryTime?: string;
deliveryFeeRate?: string;
priceScale: string;
leverageFilter: {
minLeverage: string;
maxLeverage: string;
leverageStep: string;
};
priceFilter: {
minPrice: string;
maxPrice: string;
tickSize: string;
};
lotSizeFilter: {
maxOrderQty: string;
minOrderQty: string;
qtyStep: string;
postOnlyMaxOrderQty?: string;
};
unifiedMarginTrade: boolean;
fundingInterval: number;
settleCoin: string;
}
export interface OptionInstrumentInfoV5 {
symbol: string;
optionsType: OptionTypeV5;
status: InstrumentStatusV5;
baseCoin: string;
quoteCoin: string;
settleCoin: boolean;
launchTime: string;
deliveryTime: string;
deliveryFeeRate: string;
priceFilter: {
minPrice: string;
maxPrice: string;
tickSize: string;
};
lotSizeFilter: {
maxOrderQty: string;
minOrderQty: string;
qtyStep: string;
};
}
export interface SpotInstrumentInfoV5 {
symbol: string;
baseCoin: string;
quoteCoin: string;
innovation: '0' | '1';
status: InstrumentStatusV5;
lotSizeFilter: {
basePrecision: string;
quotePrecision: string;
minOrderQty: string;
maxOrderQty: string;
minOrderAmt: string;
maxOrderAmt: string;
};
priceFilter: {
tickSize: string;
};
}
export type InstrumentInfoResponseV5 =
| CategoryCursorListV5<LinearInverseInstrumentInfoV5[], 'linear' | 'inverse'>
| CategoryCursorListV5<OptionInstrumentInfoV5[], 'option'>
| CategoryCursorListV5<SpotInstrumentInfoV5[], 'spot'>;
export default interface OrderbookLevelV5 {
price: string;
size: string;
}
export interface OrderbookResponseV5 {
s: string;
b: OrderbookLevelV5[];
a: OrderbookLevelV5[];
ts: number;
u: number;
}
export interface TickerLinearInverseV5 {
symbol: string;
lastPrice: string;
indexPrice: string;
markPrice: string;
prevPrice24h: string;
price24hPcnt: string;
highPrice24h: string;
lowPrice24h: string;
prevPrice1h: string;
openInterest: string;
openInterestValue: string;
turnover24h: string;
volume24h: string;
fundingRate: string;
nextFundingTime: string;
predictedDeliveryPrice: string;
basisRate: string;
deliveryFeeRate: string;
deliveryTime: string;
ask1Size: string;
bid1Price: string;
ask1Price: string;
bid1Size: string;
}
export interface TickerOptionV5 {
symbol: string;
bid1Price: string;
bid1Size: string;
bid1Iv: string;
ask1Price: string;
ask1Size: string;
ask1Iv: string;
lastPrice: string;
highPrice24h: string;
lowPrice24h: string;
markPrice: string;
indexPrice: string;
markIv: string;
underlyingPrice: string;
openInterest: string;
turnover24h: string;
volume24h: string;
totalVolume: string;
totalTurnover: string;
delta: string;
gamma: string;
vega: string;
theta: string;
predictedDeliveryPrice: string;
change24h: string;
}
export interface TickerSpotV5 {
symbol: string;
bid1Price: string;
bid1Size: string;
ask1Price: string;
ask1Size: string;
lastPrice: string;
prevPrice24h: string;
price24hPcnt: string;
highPrice24h: string;
lowPrice24h: string;
turnover24h: string;
volume24h: string;
usdIndexPrice: string;
}
export interface FundingRateHistoryResponseV5 {
symbol: string;
fundingRate: string;
fundingRateTimestamp: string;
}
export interface PublicTradeV5 {
execId: string;
symbol: string;
price: string;
size: string;
side: OrderSideV5;
time: string;
isBlockTrade: boolean;
}
/**
*
* - openInterest string Open interest
* - timestamp string The timestamp (ms)
*/
export type OpenInterestV5 = [string, string];
export interface OpenInterestResponseV5 {
category: 'linear' | 'inverse';
symbol: string;
list: OpenInterestV5[];
nextPageCursor?: string;
}
export interface HistoricalVolatilityV5 {
period: number;
value: string;
time: string;
}
export interface InsuranceDataV5 {
coin: string;
balance: string;
value: string;
}
export interface InsuranceResponseV5 {
updatedTime: string;
list: InsuranceDataV5[];
}
export interface RiskLimitV5 {
id: number;
symbol: string;
riskLimitValue: string;
maintenanceMargin: number;
initialMargin: number;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
section: any;
isLowestRisk: 0 | 1;
maxLeverage: string;
}
export interface OptionDeliveryPriceV5 {
symbol: string;
deliveryPrice: string;
deliveryTime: string;
}

View File

@@ -0,0 +1,91 @@
import {
CategoryV5,
ExecTypeV5,
OrderSideV5,
OrderTypeV5,
PositionIdx,
StopOrderTypeV5,
TPSLModeV5,
TradeModeV5,
} from '../v5-shared';
export interface PositionV5 {
positionIdx: PositionIdx;
riskId: number;
riskLimitValue: string;
symbol: string;
side: 'Buy' | 'Sell' | 'None';
size: string;
avgPrice: string;
positionValue: string;
tradeMode: TradeModeV5;
autoAddMargin?: number;
positionStatus: 'Normal' | 'Liq' | 'Adl';
leverage?: string;
markPrice: string;
liqPrice: string;
bustPrice?: string;
positionIM?: string;
positionMM?: string;
tpslMode?: TPSLModeV5;
takeProfit?: string;
stopLoss?: string;
trailingStop?: string;
unrealisedPnl: string;
cumRealisedPnl: string;
createdTime: string;
updatedTime: string;
}
export interface SetRiskLimitResultV5 {
category: CategoryV5;
riskId: number;
riskLimitValue: string;
}
export interface ExecutionV5 {
symbol: string;
orderId: string;
orderLinkId: string;
side: OrderSideV5;
orderPrice: string;
orderQty: string;
leavesQty: string;
orderType: OrderTypeV5;
stopOrderType?: StopOrderTypeV5;
execFee: string;
execId: string;
execPrice: string;
execQty: string;
execType: ExecTypeV5;
execValue: string;
execTime: string;
isMaker: boolean;
feeRate: string;
tradeIv?: string;
markIv?: string;
markPrice: string;
indexPrice: string;
underlyingPrice?: string;
blockTradeId?: string;
}
export interface ClosedPnLV5 {
symbol: string;
orderId: string;
side: string;
qty: string;
orderPrice: string;
orderType: OrderTypeV5;
execType: ExecTypeV5;
closedSize: string;
cumEntryValue: string;
avgEntryPrice: string;
cumExitValue: string;
avgExitPrice: string;
closedPnl: string;
fillCount: string;
leverage: string;
createdTime: string;
updatedTime: string;
}

View File

@@ -0,0 +1,70 @@
import {
LTOrderStatusV5,
LTOrderTypeV5,
LeverageTokenStatusV5,
} from '../v5-shared';
export interface LeverageTokenInfoV5 {
ltCoin: string;
ltName: string;
maxPurchase: string;
minPurchase: string;
maxPurchaseDaily: string;
maxRedeem: string;
minRedeem: string;
maxRedeemDaily: string;
purchaseFeeRate: string;
redeemFeeRate: string;
ltStatus: LeverageTokenStatusV5;
fundFee: string;
fundFeeTime: string;
manageFeeRate: string;
manageFeeTime: string;
value: string;
netValue: string;
total: string;
}
export interface LeveragedTokenMarketResultV5 {
ltCoin: string;
nav: string;
navTime: string;
circulation: string;
basket: string;
leverage: string;
}
export interface PurchaseSpotLeveragedTokenResultV5 {
ltCoin: string;
ltOrderStatus: LTOrderStatusV5;
execQty: string;
execAmt: string;
amount: string;
purchaseId: string;
serialNo: string;
valueCoin: string;
}
export interface RedeemSpotLeveragedTokenResultV5 {
ltCoin: string;
ltOrderStatus: LTOrderStatusV5;
quantity: string;
execQty: string;
execAmt: string;
redeemId: string;
serialNo: string;
valueCoin: string;
}
export interface SpotLeveragedTokenOrderHistoryV5 {
ltCoin: string;
orderId: string;
ltOrderType: LTOrderTypeV5;
orderTime: number;
updateTime: number;
ltOrderStatus: LTOrderStatusV5;
fee: string;
amount: string;
value: string;
valueCoin: string;
serialNo: string;
}

View File

@@ -0,0 +1,96 @@
import {
CategoryV5,
OrderCancelTypeV5,
OrderRejectReasonV5,
OrderSideV5,
OrderStatusV5,
OrderTimeInForceV5,
OrderTriggerByV5,
OrderTypeV5,
PositionIdx,
StopOrderTypeV5,
} from '../v5-shared';
export interface OrderResultV5 {
orderId: string;
orderLinkId: string;
}
export interface AccountOrderV5 {
orderId: string;
orderLinkId?: string;
blockTradeId?: string;
symbol: string;
price: string;
qty: string;
side: OrderSideV5;
isLeverage?: string;
positionIdx?: PositionIdx;
orderStatus: OrderStatusV5;
cancelType?: OrderCancelTypeV5;
rejectReason?: OrderRejectReasonV5;
avgPrice: string;
leavesQty: string;
leavesValue: string;
cumExecQty: string;
cumExecValue: string;
cumExecFee: string;
timeInForce?: OrderTimeInForceV5;
orderType?: OrderTypeV5;
stopOrderType?: StopOrderTypeV5;
orderIv?: string;
triggerPrice?: string;
takeProfit?: string;
stopLoss?: string;
tpTriggerBy?: OrderTriggerByV5;
slTriggerBy?: OrderTriggerByV5;
triggerDirection?: number;
triggerBy?: OrderTriggerByV5;
lastPriceOnCreated?: string;
reduceOnly?: boolean;
closeOnTrigger?: boolean;
createdTime: string;
updatedTime: string;
}
export interface BatchCreateOrderResultV5 {
category: CategoryV5;
symbol: string;
orderId: string;
orderLinkId: string;
createAt: string;
}
export interface BatchOrdersResponseV5<T extends unknown[]> {
result: {
list: T;
};
retExtInfo: {
list: {
code: number;
msg: string;
}[];
};
}
export interface BatchAmendOrderResultV5 {
category: CategoryV5;
symbol: string;
orderId: string;
orderLinkId: string;
}
export interface BatchCancelOrderResultV5 {
category: CategoryV5;
symbol: string;
orderId: string;
orderLinkId: string;
}
export interface SpotBorrowCheckResultV5 {
symbol: string;
side: OrderSideV5;
maxTradeQty: string;
maxTradeAmount: string;
borrowCoin: string;
}

View File

@@ -0,0 +1,58 @@
import { PermissionsV5 } from '../v5-shared';
export interface CreateSubMemberResultV5 {
uid: string;
username: string;
memberType: number;
status: number;
remark: string;
}
export interface CreateSubApiKeyResultV5 {
id: string;
note: string;
apiKey: string;
readOnly: number;
secret: string;
permissions: PermissionsV5;
}
export interface SubMemberV5 {
uid: string;
username: string;
memberType: number;
status: number;
remark: string;
}
export type ApiKeyType = 1 | 2;
export interface ApiKeyInfoV5 {
id: string;
note: string;
apiKey: string;
readOnly: 0 | 1;
secret: string;
permissions: PermissionsV5;
ips?: string[];
type: 1 | 2;
deadlineDay?: number;
expiredAt?: string;
createdAt: string;
unified: 0 | 1;
uta: 0 | 1;
userID: number;
inviterID: number;
vipLevel?: string;
mktMakerLevel?: string;
affiliateID?: number;
}
export interface UpdateApiKeyResultV5 {
id: string;
note: string;
apiKey: string;
readOnly: 0 | 1;
secret: string;
permissions: PermissionsV5;
ips: string[];
}

199
src/types/v5-shared.ts Normal file
View File

@@ -0,0 +1,199 @@
export type CategoryV5 = 'spot' | 'linear' | 'inverse' | 'option';
export type ContractTypeV5 =
| 'InversePerpetual'
| 'LinearPerpetual'
| 'InverseFutures';
export type InstrumentStatusV5 = 'Pending' | 'Trading' | 'Settling' | 'Closed';
export type OrderFilterV5 = 'Order' | 'tpslOrder';
export type OrderSideV5 = 'Buy' | 'Sell';
export type OrderTypeV5 = 'Market' | 'Limit';
export type OrderTimeInForceV5 = 'GTC' | 'IOC' | 'FOK' | 'PostOnly';
export type OrderTriggerByV5 = 'LastPrice' | 'IndexPrice' | 'MarkPrice';
export type OrderStatusV5 =
| 'Created'
| 'New'
| 'Rejected'
| 'PartiallyFilled'
| 'PartiallyFilledCanceled'
| 'Filled'
| 'Cancelled'
| 'Untriggered'
| 'Triggered'
| 'Deactivated'
| 'Active';
export type OrderCancelTypeV5 =
| 'CancelByUser'
| 'CancelByReduceOnly'
| 'CancelByPrepareLiq'
| 'CancelAllBeforeLiq'
| 'CancelByPrepareAdl'
| 'CancelAllBeforeAdl'
| 'CancelByAdmin'
| 'CancelByTpSlTsClear'
| 'CancelByPzSideCh';
export type OrderRejectReasonV5 =
| 'EC_NoError'
| 'EC_Others'
| 'EC_UnknownMessageType'
| 'EC_MissingClOrdID'
| 'EC_MissingOrigClOrdID'
| 'EC_ClOrdIDOrigClOrdIDAreTheSame'
| 'EC_DuplicatedClOrdID'
| 'EC_OrigClOrdIDDoesNotExist'
| 'EC_TooLateToCancel'
| 'EC_UnknownOrderType'
| 'EC_UnknownSide'
| 'EC_UnknownTimeInForce'
| 'EC_WronglyRouted'
| 'EC_MarketOrderPriceIsNotZero'
| 'EC_LimitOrderInvalidPrice'
| 'EC_NoEnoughQtyToFill'
| 'EC_NoImmediateQtyToFill'
| 'EC_PerCancelRequest'
| 'EC_MarketOrderCannotBePostOnly'
| 'EC_PostOnlyWillTakeLiquidity'
| 'EC_CancelReplaceOrder'
| 'EC_InvalidSymbolStatus';
export type StopOrderTypeV5 =
| 'TakeProfit'
| 'StopLoss'
| 'TrailingStop'
| 'Stop'
| 'PartialTakeProfit'
| 'PartialStopLoss'
| 'tpslOrder';
/**
* Position index. Used to identify positions in different position modes.
*
* - 0 one-way mode position
* - 1 Buy side of hedge-mode position
* - 2 Sell side of hedge-mode position
*/
export type PositionIdx = 0 | 1 | 2;
export type OptionTypeV5 = 'Call' | 'Put';
/**
* Trade mode.
*
* - 0 cross-margin,
* - 1 isolated margin
*/
export type TradeModeV5 = 0 | 1;
export type TPSLModeV5 = 'Full' | 'Partial';
export type AccountMarginModeV5 = 'REGULAR_MARGIN' | 'PORTFOLIO_MARGIN';
export type UnifiedUpdateStatusV5 = 'FAIL' | 'PROCESS' | 'SUCCESS';
export type AccountTypeV5 =
| 'CONTRACT'
| 'SPOT'
| 'INVESTMENT'
| 'OPTION'
| 'UNIFIED'
| 'FUND';
export type TransactionTypeV5 =
| 'TRANSFER_IN'
| 'TRANSFER_OUT'
| 'TRADE'
| 'SETTLEMENT'
| 'DELIVERY'
| 'LIQUIDATION'
| 'BONUS'
| 'FEE_REFUND'
| 'INTEREST'
| 'CURRENCY_BUY'
| 'CURRENCY_SELL';
export type PermissionTypeV5 =
| 'ContractTrade'
| 'Spot'
| 'Wallet'
| 'Options'
| 'Derivatives'
| 'Exchange'
| 'NFT';
/**
* Leveraged token status:
*
* - '1' LT can be purchased and redeemed
* - '2' LT can be purchased, but not redeemed
* - '3' LT can be redeemed, but not purchased
* - '4' LT cannot be purchased nor redeemed
* - '5' Adjusting position
*/
export type LeverageTokenStatusV5 = '1' | '2' | '3' | '4' | '5';
/**
* Leveraged token order type: '1': purchase, '2': redeem
*/
export type LTOrderTypeV5 = '1' | '2';
/**
* Leveraged token order status: '1': completed, '2': in progress, '3': failed
*/
export type LTOrderStatusV5 = '1' | '2' | '3';
export type ExecTypeV5 =
| 'Trade'
| 'AdlTrade'
| 'Funding'
| 'BustTrade'
| 'Settle';
/**
* Withdraw type. 0(default): on chain. 1: off chain. 2: all.
*/
export type WithdrawalTypeV5 = '0' | '1' | '2';
export interface PermissionsV5 {
ContractTrade?: string[];
Spot?: string[];
Wallet?: string[];
Options?: string[];
Derivatives?: string[];
Exchange?: string[];
NFT?: string[];
}
export interface CategoryCursorListV5<
T extends unknown[],
TCategory extends CategoryV5 = CategoryV5
> {
category: TCategory;
list: T;
nextPageCursor?: string;
}
/**
* Next page cursor does not exist for spot!
*/
export interface CursorListV5<T extends unknown[]> {
nextPageCursor: string;
list: T;
}
export interface CategoryListV5<
T extends unknown[],
TCategory extends CategoryV5
> {
category: TCategory;
list: T;
}
export interface CategorySymbolListV5<
T extends unknown[],
TCategory extends CategoryV5
> {
category: TCategory;
symbol: string;
list: T;
}

View File

@@ -98,6 +98,7 @@ export interface WSClientConfigurableOptions {
pingInterval?: number;
reconnectTimeout?: number;
restOptions?: RestClientOptions;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
requestOptions?: any;
wsUrl?: string;
/** If true, fetch server time before trying to authenticate (disabled by default) */

View File

@@ -1,34 +1,35 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
APIResponseWithTime,
APIResponseV3,
UMCategory,
UMCandlesRequest,
UMInstrumentInfoRequest,
UMFundingRateHistoryRequest,
UMOptionDeliveryPriceRequest,
UMPublicTradesRequest,
UMOpenInterestRequest,
UMOrderRequest,
UMModifyOrderRequest,
UMCancelOrderRequest,
UMActiveOrdersRequest,
UMHistoricOrdersRequest,
UMBatchOrder,
UMBatchOrderReplace,
UMBatchOrderCancel,
UMCancelAllOrdersRequest,
UMPositionsRequest,
UMSetTPSLRequest,
UM7DayTradingHistoryRequest,
UMOptionsSettlementHistoryRequest,
UMPerpSettlementHistoryRequest,
UMTransactionLogRequest,
APIResponseWithTime,
InternalTransferRequest,
UMExchangeCoinsRequest,
UM7DayTradingHistoryRequest,
UMActiveOrdersRequest,
UMBatchOrder,
UMBatchOrderCancel,
UMBatchOrderReplace,
UMBorrowHistoryRequest,
UMPaginatedResult,
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';

View File

@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
APIResponseWithTime,
APIResponseV3,
APIResponseWithTime,
USDCOptionsActiveOrdersRealtimeRequest,
USDCOptionsActiveOrdersRequest,
USDCOptionsCancelAllOrdersRequest,
@@ -8,8 +9,8 @@ import {
USDCOptionsContractInfoRequest,
USDCOptionsDeliveryHistoryRequest,
USDCOptionsDeliveryPriceRequest,
USDCOptionsHistoricalVolatilityRequest,
USDCOptionsHistoricOrdersRequest,
USDCOptionsHistoricalVolatilityRequest,
USDCOptionsModifyMMPRequest,
USDCOptionsModifyOrderRequest,
USDCOptionsOrderExecutionRequest,
@@ -203,7 +204,11 @@ export class USDCOptionClient extends BaseRestClient {
);
}
/** 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. */
/**
* 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>> {
@@ -241,7 +246,9 @@ export class USDCOptionClient extends BaseRestClient {
}
/**
* 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.
* 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(

View File

@@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
APIResponseV3,
APIResponseWithTime,
SymbolLimitParam,
SymbolPeriodLimitParam,
APIResponseV3,
USDCKlineRequest,
USDCLast500TradesRequest,
USDCOpenInterestRequest,
@@ -213,7 +214,9 @@ export class USDCPerpetualClient extends BaseRestClient {
}
/**
* 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.
* 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(

View File

@@ -1,14 +1,15 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import axios, { AxiosRequestConfig, AxiosResponse, Method } from 'axios';
import { signMessage } from './node-support';
import {
RestClientOptions,
serializeParams,
RestClientType,
REST_CLIENT_TYPE_ENUM,
APIID,
REST_CLIENT_TYPE_ENUM,
RestClientOptions,
RestClientType,
getRestBaseUrl,
serializeParams,
} from './requestUtils';
import { signMessage } from './node-support';
// axios.interceptors.request.use((request) => {
// console.log(new Date(), 'Starting Request', JSON.stringify(request, null, 2));
@@ -48,7 +49,7 @@ interface SignedRequestContext {
}
interface SignedRequest<T> {
originalParams: T & SignedRequestContext;
originalParams: (T & SignedRequestContext) | SignedRequestContext;
paramsWithSign?: T & SignedRequestContext & { sign: string };
serializedParams: string;
sign: string;
@@ -61,16 +62,23 @@ interface UnsignedRequest<T> {
paramsWithSign: T;
}
type SignMethod = 'keyInBody' | 'usdc';
type SignMethod = 'v2auth' | 'v5auth';
export default abstract class BaseRestClient {
private timeOffset: number | null = null;
private syncTimePromise: null | Promise<any> = null;
private options: RestClientOptions;
private baseUrl: string;
private globalRequestOptions: AxiosRequestConfig;
private key: string | undefined;
private secret: string | undefined;
private clientType: RestClientType;
/** Function that calls exchange API to query & resolve server time, used by time sync, disabled by default */
@@ -159,13 +167,15 @@ export default abstract class BaseRestClient {
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>(
private async prepareSignParams<TParams extends SignedRequestContext = any>(
method: Method,
signMethod: SignMethod,
params?: TParams,
@@ -186,7 +196,7 @@ export default abstract class BaseRestClient {
await this.syncTime();
}
return this.signRequest(params, method, signMethod);
return this.signRequest(params || {}, method, signMethod);
}
/** Returns an axios request object. Handles signing process automatically if this is a private API call */
@@ -223,7 +233,7 @@ export default abstract class BaseRestClient {
const signResult = await this.prepareSignParams(
method,
'usdc',
'v5auth',
params,
isPublicApi
);
@@ -235,11 +245,9 @@ export default abstract class BaseRestClient {
options.headers['X-BAPI-RECV-WINDOW'] = signResult.recvWindow;
if (method === 'GET') {
// const serialisedParams = signResult.serializedParams;
return {
...options,
params: signResult.originalParams,
// url: url + (serialisedParams ? '?' + serialisedParams : ''),
};
}
@@ -251,7 +259,7 @@ export default abstract class BaseRestClient {
const signResult = await this.prepareSignParams(
method,
'keyInBody',
'v2auth',
params,
isPublicApi
);
@@ -336,7 +344,7 @@ export default abstract class BaseRestClient {
/**
* @private sign request and set recv window
*/
private async signRequest<T = {}>(
private async signRequest<T extends SignedRequestContext | {} = {}>(
data: T,
method: Method,
signMethod: SignMethod
@@ -366,7 +374,7 @@ export default abstract class BaseRestClient {
res.recvWindow = recvWindow;
// usdc is different for some reason
if (signMethod === 'usdc') {
if (signMethod === 'v5auth') {
const sortProperties = false;
const signRequestParams =
method === 'GET'
@@ -387,7 +395,7 @@ export default abstract class BaseRestClient {
}
// spot/v2 derivatives
if (signMethod === 'keyInBody') {
if (signMethod === 'v2auth') {
res.originalParams.api_key = key;
res.originalParams.timestamp = timestamp;
@@ -409,10 +417,13 @@ export default abstract class BaseRestClient {
encodeValues
);
res.sign = await signMessage(res.serializedParams, this.secret);
// @ts-ignore
res.paramsWithSign = {
...res.originalParams,
sign: res.sign,
};
return res;
}

View File

@@ -16,7 +16,8 @@ type WsTopic = string;
/**
* A "Set" is used to ensure we only subscribe to a topic once (tracking a list of unique topics we're expected to be connected to)
* Note: Accurate duplicate tracking only works for plaintext topics. E.g. JSON objects may not be seen as duplicates if keys are in different orders. If that's needed, check the FTX implementation.
* Note: Accurate duplicate tracking only works for plaintext topics.
* E.g. JSON objects may not be seen as duplicates if keys are in different orders. If that's needed, check the FTX implementation.
*/
type WsTopicList = Set<WsTopic>;
@@ -39,6 +40,7 @@ interface WsStoredState {
export default class WsStore {
private wsState: Record<string, WsStoredState>;
private logger: typeof DefaultLogger;
constructor(logger: typeof DefaultLogger) {
@@ -48,7 +50,9 @@ export default class WsStore {
/** Get WS stored state for key, optionally create if missing */
get(key: WsKey, createIfMissing?: true): WsStoredState;
get(key: WsKey, createIfMissing?: false): WsStoredState | undefined;
get(key: WsKey, createIfMissing?: boolean): WsStoredState | undefined {
if (this.wsState[key]) {
return this.wsState[key];

View File

@@ -3,6 +3,7 @@ export async function signMessage(
secret: string
): Promise<string> {
const encoder = new TextEncoder();
// eslint-disable-next-line no-undef
const key = await window.crypto.subtle.importKey(
'raw',
encoder.encode(secret),
@@ -11,6 +12,7 @@ export async function signMessage(
['sign']
);
// eslint-disable-next-line no-undef
const signature = await window.crypto.subtle.sign(
'HMAC',
key,
@@ -18,8 +20,10 @@ export async function signMessage(
);
return Array.prototype.map
.call(new Uint8Array(signature), (x: any) =>
('00' + x.toString(16)).slice(-2)
.call(
new Uint8Array(signature),
(x: { toString: (arg0: number) => string }) =>
('00' + x.toString(16)).slice(-2)
)
.join('');
}

View File

@@ -1,3 +1,6 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-unused-vars */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type LogParams = null | any;
export const DefaultLogger = {

View File

@@ -91,6 +91,7 @@ export function getRestBaseUrl(
return exchangeBaseUrls.livenet;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function isWsPong(msg: any): boolean {
if (!msg) {
return false;

View File

@@ -298,7 +298,7 @@ export function getWsKeyForTopic(
: WS_KEY_MAP.contractUSDTPublic;
}
default: {
throw neverGuard(market, `getWsKeyForTopic(): Unhandled market`);
throw neverGuard(market, 'getWsKeyForTopic(): Unhandled market');
}
}
}
@@ -322,7 +322,7 @@ export function getMaxTopicsPerSubscribeEvent(
return 10;
}
default: {
throw neverGuard(market, `getWsKeyForTopic(): Unhandled market`);
throw neverGuard(market, 'getWsKeyForTopic(): Unhandled market');
}
}
}

View File

@@ -1,3 +1,5 @@
/* eslint-disable max-len */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { EventEmitter } from 'events';
import WebSocket from 'isomorphic-ws';
@@ -17,24 +19,24 @@ import {
APIMarket,
KlineInterval,
RESTClient,
WebsocketClientOptions,
WSClientConfigurableOptions,
WebsocketClientOptions,
WsKey,
WsTopic,
} from './types';
import {
serializeParams,
isWsPong,
WsConnectionStateEnum,
DefaultLogger,
PUBLIC_WS_KEYS,
WS_AUTH_ON_CONNECT_KEYS,
WS_KEY_MAP,
DefaultLogger,
WS_BASE_URL_MAP,
getWsKeyForTopic,
neverGuard,
WS_KEY_MAP,
WsConnectionStateEnum,
getMaxTopicsPerSubscribeEvent,
getWsKeyForTopic,
isWsPong,
neverGuard,
serializeParams,
} from './util';
const loggerCategory = { category: 'bybit-ws' };
@@ -78,10 +80,14 @@ export declare interface WebsocketClient {
): boolean;
}
// eslint-disable-next-line no-redeclare
export class WebsocketClient extends EventEmitter {
private logger: typeof DefaultLogger;
private restClient?: RESTClient;
private options: WebsocketClientOptions;
private wsStore: WsStore;
constructor(
@@ -109,6 +115,7 @@ export class WebsocketClient extends EventEmitter {
this.prepareRESTClient();
// 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', () => {});
}
@@ -247,7 +254,7 @@ export class WebsocketClient extends EventEmitter {
default: {
throw neverGuard(
this.options.market,
`prepareRESTClient(): Unhandled market`
'prepareRESTClient(): Unhandled market'
);
}
}
@@ -304,7 +311,7 @@ export class WebsocketClient extends EventEmitter {
return [...this.connectPublic(), this.connectPrivate()];
}
default: {
throw neverGuard(this.options.market, `connectAll(): Unhandled market`);
throw neverGuard(this.options.market, 'connectAll(): Unhandled market');
}
}
}
@@ -345,7 +352,7 @@ export class WebsocketClient extends EventEmitter {
default: {
throw neverGuard(
this.options.market,
`connectPublic(): Unhandled market`
'connectPublic(): Unhandled market'
);
}
}
@@ -382,7 +389,7 @@ export class WebsocketClient extends EventEmitter {
default: {
throw neverGuard(
this.options.market,
`connectPrivate(): Unhandled market`
'connectPrivate(): Unhandled market'
);
}
}
@@ -517,7 +524,7 @@ export class WebsocketClient extends EventEmitter {
'Cannot authenticate websocket, either api or private keys missing.',
{ ...loggerCategory, wsKey }
);
throw new Error(`Cannot auth - missing api or secret in config`);
throw new Error('Cannot auth - missing api or secret in config');
}
this.logger.debug("Getting auth'd request params", {
@@ -660,7 +667,7 @@ export class WebsocketClient extends EventEmitter {
this.logger.silly(
`Subscribing to topics in batches of ${maxTopicsPerEvent}`
);
for (var i = 0; i < topics.length; i += maxTopicsPerEvent) {
for (let i = 0; i < topics.length; i += maxTopicsPerEvent) {
const batch = topics.slice(i, i + maxTopicsPerEvent);
this.logger.silly(`Subscribing to batch of ${batch.length}`);
this.requestSubscribeTopics(wsKey, batch);
@@ -695,7 +702,7 @@ export class WebsocketClient extends EventEmitter {
this.logger.silly(
`Unsubscribing to topics in batches of ${maxTopicsPerEvent}`
);
for (var i = 0; i < topics.length; i += maxTopicsPerEvent) {
for (let i = 0; i < topics.length; i += maxTopicsPerEvent) {
const batch = topics.slice(i, i + maxTopicsPerEvent);
this.logger.silly(`Unsubscribing to batch of ${batch.length}`);
this.requestUnsubscribeTopics(wsKey, batch);
@@ -716,7 +723,7 @@ export class WebsocketClient extends EventEmitter {
public tryWsSend(wsKey: WsKey, wsMessage: string) {
try {
this.logger.silly(`Sending upstream ws message: `, {
this.logger.silly('Sending upstream ws message: ', {
...loggerCategory,
wsMessage,
wsKey,
@@ -734,7 +741,7 @@ export class WebsocketClient extends EventEmitter {
}
ws.send(wsMessage);
} catch (e) {
this.logger.error(`Failed to send WS message`, {
this.logger.error('Failed to send WS message', {
...loggerCategory,
wsMessage,
wsKey,
@@ -782,7 +789,7 @@ export class WebsocketClient extends EventEmitter {
// Some websockets require an auth packet to be sent after opening the connection
if (WS_AUTH_ON_CONNECT_KEYS.includes(wsKey)) {
this.logger.info(`Sending auth request...`);
this.logger.info('Sending auth request...');
await this.sendAuthRequest(wsKey);
}
@@ -955,7 +962,7 @@ export class WebsocketClient extends EventEmitter {
...loggerCategory,
wsKey,
});
throw neverGuard(wsKey, `getWsUrl(): Unhandled wsKey`);
throw neverGuard(wsKey, 'getWsUrl(): Unhandled wsKey');
}
}
}
@@ -1051,7 +1058,7 @@ export class WebsocketClient extends EventEmitter {
case 'merge': {
topic = 'mergedDepth';
if (!dumpScale) {
throw new Error(`Dumpscale must be provided for merged orderbooks`);
throw new Error('Dumpscale must be provided for merged orderbooks');
}
break;
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable max-len */
import { API_ERROR_CODE, ContractClient } from '../../src';
import { successResponseObjectV3 } from '../response.util';
@@ -30,8 +31,9 @@ describe('Private Contract REST API GET Endpoints', () => {
expect(
await api.getHistoricOrders({ symbol, cursor, limit: 1 })
).toMatchObject({
...successResponseObjectV3(),
// retCode: API_ERROR_CODE.DB_ERROR_WRONG_CURSOR,
...successResponseObjectV3(),
retMsg: 'OK',
});
});

View File

@@ -89,8 +89,8 @@ describe('Private Contract REST API POST Endpoints', () => {
await api.setMarginSwitch({
symbol,
tradeMode: 1,
buyLeverage: '5',
sellLeverage: '5',
buyLeverage: '10',
sellLeverage: '10',
})
).toMatchObject({
retCode: API_ERROR_CODE.CONTRACT_MARGIN_MODE_NOT_MODIFIED,
@@ -116,7 +116,7 @@ describe('Private Contract REST API POST Endpoints', () => {
});
it('setLeverage()', async () => {
expect(await api.setLeverage(symbol, '5', '5')).toMatchObject({
expect(await api.setLeverage(symbol, '10', '10')).toMatchObject({
retCode: API_ERROR_CODE.CONTRACT_SET_LEVERAGE_NOT_MODIFIED,
});
});

View File

@@ -1,4 +1,4 @@
import { UMCandlesRequest, ContractClient } from '../../src';
import { ContractClient, UMCandlesRequest } from '../../src';
import {
successResponseObject,
successResponseObjectV3,

View File

@@ -1,14 +1,16 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
logAllEvents,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
fullLogger,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
} from '../ws.util';
describe('Private Contract Websocket Client', () => {

View File

@@ -1,13 +1,15 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
logAllEvents,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
} from '../ws.util';
describe('Public Contract Inverse Websocket Client', () => {

View File

@@ -1,13 +1,15 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
logAllEvents,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
} from '../ws.util';
describe('Public Contract USDT Websocket Client', () => {

View File

@@ -11,7 +11,8 @@ describe('Private Inverse-Futures REST API GET Endpoints', () => {
testnet: false,
});
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
// Warning: if some of these start to fail with 10001 params error,
// it's probably that this future expired and a newer one exists with a different symbol!
let symbol = '';
beforeAll(async () => {

View File

@@ -16,7 +16,8 @@ describe('Private Inverse-Futures REST API POST Endpoints', () => {
testnet: false,
});
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
// Warning: if some of these start to fail with 10001 params error,
// it's probably that this future expired and a newer one exists with a different symbol!
let symbol = '';
beforeAll(async () => {

View File

@@ -1,12 +1,12 @@
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
WS_OPEN_EVENT_PARTIAL,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
} from '../ws.util';
describe('Private Inverse Perps Websocket Client', () => {

View File

@@ -1,14 +1,16 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
LinearClient,
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
promiseSleep,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
getSilentLogger,
promiseSleep,
waitForSocketEvent,
} from '../ws.util';
describe('Public Inverse Perps Websocket Client', () => {

View File

@@ -16,7 +16,8 @@ describe('Private Linear REST API POST Endpoints', () => {
testnet: false,
});
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
// Warning: if some of these start to fail with 10001 params error,
// it's probably that this future expired and a newer one exists with a different symbol!
const symbol = 'BTCUSDT';
// These tests are primarily check auth is working by expecting balance or order not found style errors
@@ -137,8 +138,8 @@ describe('Private Linear REST API POST Endpoints', () => {
await api.setMarginSwitch({
symbol,
is_isolated: true,
buy_leverage: 5,
sell_leverage: 5,
buy_leverage: 10,
sell_leverage: 10,
})
).toMatchObject({
ret_code: API_ERROR_CODE.ISOLATED_NOT_MODIFIED_LINEAR,
@@ -185,8 +186,8 @@ describe('Private Linear REST API POST Endpoints', () => {
expect(
await api.setUserLeverage({
symbol,
buy_leverage: 5,
sell_leverage: 5,
buy_leverage: 10,
sell_leverage: 10,
})
).toMatchObject({
ret_code: API_ERROR_CODE.LEVERAGE_NOT_MODIFIED,
@@ -205,7 +206,7 @@ describe('Private Linear REST API POST Endpoints', () => {
});
});
it('setRiskLimit()', async () => {
it.skip('setRiskLimit()', async () => {
expect(
await api.setRiskLimit({
symbol,

View File

@@ -1,12 +1,12 @@
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
WS_OPEN_EVENT_PARTIAL,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
} from '../ws.util';
describe('Private Linear Perps Websocket Client', () => {

View File

@@ -1,12 +1,12 @@
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
WS_OPEN_EVENT_PARTIAL,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
} from '../ws.util';
describe('Public Linear Perps Websocket Client', () => {

View File

@@ -1,12 +1,14 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { API_ERROR_CODE } from '../src';
const SUCCESS_MSG_REGEX = /OK|SUCCESS|success|success\.|Request accepted|/gim;
export const SUCCESS_MSG_REGEX =
/OK|SUCCESS|success|success\.|Request accepted|/gim;
export function successResponseList(successMsg: string | null = 'OK') {
return {
result: expect.any(Array),
ret_code: API_ERROR_CODE.SUCCESS,
ret_msg: successMsg,
ret_code: API_ERROR_CODE.SUCCESS,
};
}
@@ -19,11 +21,11 @@ export function successResponseListV3() {
};
}
export function successResponseObject(successMsg: string | null = 'OK') {
export function successResponseObject() {
return {
result: expect.any(Object),
ret_code: API_ERROR_CODE.SUCCESS,
ret_msg: expect.stringMatching(SUCCESS_MSG_REGEX),
ret_code: API_ERROR_CODE.SUCCESS,
};
}

View File

@@ -16,7 +16,8 @@ describe('Private Spot REST API POST Endpoints', () => {
testnet: false,
});
// Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol!
// Warning: if some of these start to fail with 10001 params error,
// it's probably that this future expired and a newer one exists with a different symbol!
const symbol = 'BTCUSDT';
// These tests are primarily check auth is working by expecting balance or order not found style errors

View File

@@ -21,7 +21,7 @@ describe('Private Spot REST API GET Endpoints', () => {
});
const symbol = 'BTCUSDT';
const interval = '15m';
// const interval = '15m';
const ltCode = 'BTC3S';
it('getOrder()', async () => {
@@ -82,7 +82,8 @@ describe('Private Spot REST API GET Endpoints', () => {
it('getLeveragedTokenPRHistory()', async () => {
expect(await api.getLeveragedTokenPRHistory()).toMatchObject({
retCode: API_ERROR_CODE.ORDER_NOT_FOUND_LEVERAGED_TOKEN,
...successResponseObjectV3(),
// retCode: API_ERROR_CODE.ORDER_NOT_FOUND_LEVERAGED_TOKEN,
});
});

View File

@@ -1,3 +1,5 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { SpotClient } from '../../src';
import {
notAuthenticatedError,
@@ -28,43 +30,39 @@ describe('Public Spot REST API Endpoints', () => {
it('getOrderBook()', async () => {
expect(await api.getOrderBook(symbol)).toMatchObject(
successResponseObject(null)
successResponseObject()
);
});
it('getMergedOrderBook()', async () => {
expect(await api.getMergedOrderBook(symbol)).toMatchObject(
successResponseObject(null)
successResponseObject()
);
});
it('getTrades()', async () => {
expect(await api.getTrades(symbol)).toMatchObject(
successResponseObject(null)
);
expect(await api.getTrades(symbol)).toMatchObject(successResponseObject());
});
it('getCandles()', async () => {
expect(await api.getCandles(symbol, interval)).toMatchObject(
successResponseObject(null)
successResponseObject()
);
});
it('get24hrTicker()', async () => {
expect(await api.get24hrTicker()).toMatchObject(
successResponseObject(null)
);
expect(await api.get24hrTicker()).toMatchObject(successResponseObject());
});
it('getLastTradedPrice()', async () => {
expect(await api.getLastTradedPrice()).toMatchObject(
successResponseObject(null)
successResponseObject()
);
});
it('getBestBidAskPrice()', async () => {
expect(await api.getBestBidAskPrice()).toMatchObject(
successResponseObject(null)
successResponseObject()
);
});

View File

@@ -1,3 +1,5 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { SpotClientV3 } from '../../src';
import {
notAuthenticatedError,

View File

@@ -1,15 +1,17 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
logAllEvents,
promiseSleep,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
fullLogger,
getSilentLogger,
logAllEvents,
promiseSleep,
waitForSocketEvent,
} from '../ws.util';
describe('Private Spot V1 Websocket Client', () => {

View File

@@ -1,13 +1,15 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_ERROR_ENUM,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
WS_OPEN_EVENT_PARTIAL,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
} from '../ws.util';
describe('Private Spot V3 Websocket Client', () => {
@@ -19,7 +21,7 @@ describe('Private Spot V3 Websocket Client', () => {
key: API_KEY,
secret: API_SECRET,
};
const wsTopic = `outboundAccountInfo`;
const wsTopic = 'outboundAccountInfo';
describe('with invalid credentials', () => {
it('should reject private subscribe if keys/signature are incorrect', async () => {

View File

@@ -1,14 +1,16 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
logAllEvents,
getSilentLogger,
fullLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
fullLogger,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
} from '../ws.util';
describe('Public Spot V1 Websocket Client', () => {
@@ -64,7 +66,7 @@ describe('Public Spot V1 Websocket Client', () => {
try {
await wsUpdatePromise;
} catch (e) {
console.error(`Wait for spot v1 orderbook event exception: `, e);
console.error('Wait for spot v1 orderbook event exception: ', e);
}
});
});

View File

@@ -1,14 +1,16 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
logAllEvents,
getSilentLogger,
fullLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
fullLogger,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
} from '../ws.util';
describe('Public Spot V3 Websocket Client', () => {

View File

@@ -1,4 +1,4 @@
import { UnifiedMarginClient, UMCandlesRequest } from '../../src';
import { UMCandlesRequest, UnifiedMarginClient } from '../../src';
import {
successResponseObject,
successResponseObjectV3,

View File

@@ -1,14 +1,16 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
logAllEvents,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
fullLogger,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
} from '../ws.util';
describe('Private Unified Margin Websocket Client', () => {

View File

@@ -1,13 +1,15 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
logAllEvents,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
} from '../ws.util';
describe('Public Unified Margin Websocket Client (Options)', () => {

View File

@@ -1,14 +1,16 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
logAllEvents,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
fullLogger,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
} from '../ws.util';
describe('Public Unified Margin Websocket Client (Perps - USDC)', () => {

View File

@@ -1,14 +1,16 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../src';
import {
logAllEvents,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
fullLogger,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
} from '../ws.util';
describe('Public Unified Margin Websocket Client (Perps - USDT)', () => {

View File

@@ -1,5 +1,5 @@
import { API_ERROR_CODE, USDCOptionClient } from '../../../src';
import { successResponseObjectV3 } from '../../response.util';
// import { successResponseObjectV3 } from '../../response.util';
describe('Private USDC Options REST API POST Endpoints', () => {
const API_KEY = process.env.API_KEY_COM;

View File

@@ -1,15 +1,17 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_ERROR_ENUM,
WS_KEY_MAP,
WebsocketClient,
} from '../../../src';
import {
WS_OPEN_EVENT_PARTIAL,
fullLogger,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
} from '../../ws.util';
describe('Private USDC Option Websocket Client', () => {
@@ -22,7 +24,7 @@ describe('Private USDC Option Websocket Client', () => {
secret: API_SECRET,
};
const wsTopic = `user.openapi.option.position`;
const wsTopic = 'user.openapi.option.position';
describe('with invalid credentials', () => {
it('should reject private subscribe if keys/signature are incorrect', async () => {

View File

@@ -1,13 +1,15 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../../src';
import {
logAllEvents,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
} from '../../ws.util';
describe('Public USDC Option Websocket Client', () => {

View File

@@ -1,8 +1,5 @@
import { API_ERROR_CODE, USDCPerpetualClient } from '../../../src';
import {
successEmptyResponseObjectV3,
successResponseObjectV3,
} from '../../response.util';
import { successEmptyResponseObjectV3 } from '../../response.util';
describe('Private USDC Perp REST API POST Endpoints', () => {
const API_KEY = process.env.API_KEY_COM;

View File

@@ -1,15 +1,17 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_ERROR_ENUM,
WS_KEY_MAP,
WebsocketClient,
} from '../../../src';
import {
WS_OPEN_EVENT_PARTIAL,
fullLogger,
getSilentLogger,
logAllEvents,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
} from '../../ws.util';
describe('Private USDC Perp Websocket Client', () => {
@@ -22,7 +24,7 @@ describe('Private USDC Perp Websocket Client', () => {
secret: API_SECRET,
};
const wsTopic = `user.openapi.perp.position`;
const wsTopic = 'user.openapi.perp.position';
describe('with invalid credentials', () => {
it('should reject private subscribe if keys/signature are incorrect', async () => {

View File

@@ -1,13 +1,12 @@
import {
WebsocketClient,
WSClientConfigurableOptions,
WS_KEY_MAP,
WebsocketClient,
} from '../../../src';
import {
logAllEvents,
WS_OPEN_EVENT_PARTIAL,
getSilentLogger,
waitForSocketEvent,
WS_OPEN_EVENT_PARTIAL,
} from '../../ws.util';
describe('Public USDC Perp Websocket Client', () => {

View File

@@ -0,0 +1,265 @@
import { API_ERROR_CODE, RestClientV5 } from '../../src';
import { successResponseObjectV3 } from '../response.util';
describe('Private READ V5 REST API Endpoints', () => {
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 RestClientV5({
key: API_KEY,
secret: API_SECRET,
testnet: false,
});
const settleCoin = 'USDT';
const linearSymbol = 'BTCUSDT';
describe('misc endpoints', () => {
it('fetchServerTime()', async () => {
expect(await api.fetchServerTime()).toEqual(expect.any(Number));
});
});
describe('Trade APIs', () => {
it('getActiveOrders()', async () => {
expect(
await api.getActiveOrders({ category: 'linear', settleCoin })
).toMatchObject({
...successResponseObjectV3(),
});
});
it('getHistoricOrders()', async () => {
expect(await api.getHistoricOrders({ category: 'linear' })).toMatchObject(
{ ...successResponseObjectV3() }
);
});
it('getSpotBorrowCheck()', async () => {
expect(await api.getSpotBorrowCheck(linearSymbol, 'Buy')).toMatchObject({
...successResponseObjectV3(),
});
});
});
describe('Position APIs', () => {
it('getPositionInfo()', async () => {
expect(
await api.getPositionInfo({ category: 'linear', settleCoin })
).toMatchObject({
...successResponseObjectV3(),
});
});
it('getExecutionList()', async () => {
expect(
await api.getExecutionList({ category: 'linear', symbol: linearSymbol })
).toMatchObject({
...successResponseObjectV3(),
});
});
it('getClosedPnL()', async () => {
expect(
await api.getClosedPnL({ category: 'linear', symbol: linearSymbol })
).toMatchObject({
...successResponseObjectV3(),
});
});
});
describe('Account APIs', () => {
it('getWalletBalance()', async () => {
expect(
await api.getWalletBalance({ accountType: 'CONTRACT' })
).toMatchObject({ ...successResponseObjectV3() });
});
it('getBorrowHistory()', async () => {
expect(await api.getBorrowHistory()).toMatchObject({
...successResponseObjectV3(),
});
});
it('getCollateralInfo()', async () => {
expect(await api.getCollateralInfo()).toMatchObject({
...successResponseObjectV3(),
});
});
// Not available on this test account
it.skip('getCoinGreeks()', async () => {
expect(await api.getCoinGreeks()).toMatchObject({
...successResponseObjectV3(),
retMsg: '',
});
});
it('getFeeRate()', async () => {
expect(await api.getFeeRate()).toMatchObject({
...successResponseObjectV3(),
});
});
// Fails on this test account, since it's not upgraded
it.skip('getAccountInfo()', async () => {
expect(await api.getAccountInfo()).toMatchObject({
...successResponseObjectV3(),
retMsg: '',
});
});
it('getTransactionLog()', async () => {
expect(await api.getTransactionLog()).toMatchObject({
...successResponseObjectV3(),
});
});
// Not available on this test account
it.skip('getMMPState()', async () => {
expect(await api.getMMPState(settleCoin)).toMatchObject({
...successResponseObjectV3(),
retMsg: '',
});
});
});
describe('Asset APIs', () => {
it('getCoinExchangeRecords()', async () => {
expect(await api.getCoinExchangeRecords()).toMatchObject({
...successResponseObjectV3(),
});
});
it('getDeliveryRecord()', async () => {
expect(await api.getDeliveryRecord({ category: 'option' })).toMatchObject(
{ ...successResponseObjectV3() }
);
});
it('getSettlementRecords()', async () => {
expect(
await api.getSettlementRecords({ category: 'linear' })
).toMatchObject({ ...successResponseObjectV3() });
});
it('getAssetInfo()', async () => {
expect(await api.getAssetInfo({ accountType: 'SPOT' })).toMatchObject({
...successResponseObjectV3(),
});
});
it('getAllCoinsBalance()', async () => {
expect(
await api.getAllCoinsBalance({ accountType: 'SPOT' })
).toMatchObject({ ...successResponseObjectV3() });
});
it('getCoinBalance()', async () => {
expect(
await api.getCoinBalance({ accountType: 'SPOT', coin: settleCoin })
).toMatchObject({ ...successResponseObjectV3() });
});
it('getTransferableCoinList()', async () => {
expect(
await api.getTransferableCoinList('SPOT', 'CONTRACT')
).toMatchObject({ ...successResponseObjectV3() });
});
it('getInternalTransferRecords()', async () => {
expect(await api.getInternalTransferRecords()).toMatchObject({
...successResponseObjectV3(),
});
});
it('getSubUID()', async () => {
expect(await api.getSubUID()).toMatchObject({
...successResponseObjectV3(),
});
});
it('getUniversalTransferRecords()', async () => {
expect(await api.getUniversalTransferRecords()).toMatchObject({
...successResponseObjectV3(),
});
});
it('getAllowedDepositCoinInfo()', async () => {
expect(await api.getAllowedDepositCoinInfo()).toMatchObject({
...successResponseObjectV3(),
});
});
it('getDepositRecords()', async () => {
expect(await api.getDepositRecords()).toMatchObject({
...successResponseObjectV3(),
});
});
it('getSubAccountDepositRecords()', async () => {
expect(
await api.getSubAccountDepositRecords({ subMemberId: 'fakeid' })
).toMatchObject({
// ...successResponseObjectV3(),
// Expected, since sub account ID is fake
retCode: API_ERROR_CODE.PARAMS_MISSING_OR_WRONG,
});
});
it('getMasterDepositAddress()', async () => {
expect(await api.getMasterDepositAddress(settleCoin)).toMatchObject({
...successResponseObjectV3(),
});
});
it('querySubMemberAddress()', async () => {
expect(
await api.querySubMemberAddress(settleCoin, 'TRC20', 'fakeid')
).toMatchObject({
// ...successResponseObjectV3(),
// Expected, since sub account ID is fake
retCode: API_ERROR_CODE.PARAMS_MISSING_OR_WRONG,
});
});
it('getCoinInfo()', async () => {
expect(await api.getCoinInfo()).toMatchObject({
...successResponseObjectV3(),
});
});
it('getWithdrawalRecords()', async () => {
expect(await api.getWithdrawalRecords()).toMatchObject({
...successResponseObjectV3(),
});
});
});
describe('User APIs', () => {
it('getSubUIDList()', async () => {
expect(await api.getSubUIDList()).toMatchObject({
...successResponseObjectV3(),
});
});
it('getQueryApiKey()', async () => {
expect(await api.getQueryApiKey()).toMatchObject({
...successResponseObjectV3(),
});
});
});
describe('Spot Leverage Token APIs', () => {
it('getSpotLeveragedTokenOrderHistory()', async () => {
expect(await api.getSpotLeveragedTokenOrderHistory()).toMatchObject({
...successResponseObjectV3(),
});
});
});
});

View File

@@ -0,0 +1,463 @@
import {
API_ERROR_CODE,
LeverageTokenInfoV5,
OrderSideV5,
OrderTypeV5,
RestClientV5,
} from '../../src';
import { successResponseObjectV3 } from '../response.util';
describe('Private WRITE V5 REST API Endpoints', () => {
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 RestClientV5({
key: API_KEY,
secret: API_SECRET,
testnet: false,
});
const settleCoin = 'USDT';
const linearSymbol = 'BTCUSDT';
const orderType: OrderTypeV5 = 'Market';
const orderSide: OrderSideV5 = 'Buy';
const fakeOrderId = 'fakeOrderId';
const fakeTransferId = '42c0cfb0-6bca-c242-bc76-4e6df6cbcb16';
describe('misc endpoints', () => {
it('fetchServerTime()', async () => {
expect(await api.fetchServerTime()).toEqual(expect.any(Number));
});
});
describe('Trade APIs', () => {
it('submitOrder()', async () => {
expect(
await api.submitOrder({
category: 'linear',
symbol: linearSymbol,
orderType: orderType,
side: orderSide,
qty: '1',
positionIdx: 1,
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_INSUFFICIENT_BALANCE,
});
});
it('amendOrder()', async () => {
expect(
await api.amendOrder({
category: 'linear',
symbol: linearSymbol,
qty: '2',
orderId: fakeOrderId,
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_ORDER_NOT_FOUND,
});
});
it('cancelOrder()', async () => {
expect(
await api.cancelOrder({
category: 'linear',
symbol: linearSymbol,
orderId: fakeOrderId,
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_ORDER_NOT_FOUND,
});
});
it('cancelAllOrders()', async () => {
expect(
await api.cancelAllOrders({
category: 'linear',
settleCoin: settleCoin,
})
).toMatchObject({
...successResponseObjectV3(),
});
});
describe('options only methods', () => {
// These should use a real symbol from the options category
let optionsSymbol: string;
beforeAll(async () => {
const deliveryPriceResponse = await api.getOptionDeliveryPrice({
category: 'option',
});
const resultsList = deliveryPriceResponse.result.list;
optionsSymbol = resultsList[0].symbol;
});
it('batchSubmitOrders()', async () => {
expect(
await api.batchSubmitOrders('option', [
{
orderLinkId: 'customOrderId1',
orderType: orderType,
qty: '1',
side: orderSide,
symbol: optionsSymbol,
},
{
orderLinkId: 'customOrderId2',
orderType: orderType,
qty: '2',
side: orderSide,
symbol: optionsSymbol,
},
])
).toMatchObject({
...successResponseObjectV3(),
});
});
it('batchAmendOrders()', async () => {
expect(
await api.batchAmendOrders('option', [
{
orderLinkId: 'customOrderId1',
qty: '3',
symbol: optionsSymbol,
},
{
orderLinkId: 'customOrderId2',
qty: '4',
symbol: optionsSymbol,
},
])
).toMatchObject({
...successResponseObjectV3(),
});
});
it('batchCancelOrders()', async () => {
expect(
await api.batchCancelOrders('option', [
{
orderLinkId: 'customOrderId1',
symbol: optionsSymbol,
},
{
orderLinkId: 'customOrderId2',
symbol: optionsSymbol,
},
])
).toMatchObject({
...successResponseObjectV3(),
});
});
});
it('setDisconnectCancelAllWindow()', async () => {
expect(await api.setDisconnectCancelAllWindow('option', 5)).toMatchObject(
{
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_API_KEY_PERMISSION_DENIED,
}
);
});
});
describe('Position APIs', () => {
it('setLeverage()', async () => {
expect(
await api.setLeverage({
category: 'linear',
buyLeverage: '10',
sellLeverage: '10',
symbol: linearSymbol,
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_LEVERAGE_NOT_CHANGED,
});
});
it('switchIsolatedMargin()', async () => {
expect(
await api.switchIsolatedMargin({
category: 'linear',
buyLeverage: '10',
sellLeverage: '10',
symbol: linearSymbol,
// isolated
tradeMode: 1,
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_CROSS_ISOLATED_MARGIN_NOT_CHANGED,
});
});
it('setTPSLMode()', async () => {
expect(
await api.setTPSLMode({
category: 'linear',
symbol: linearSymbol,
tpSlMode: 'Full',
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_TPSL_NOT_CHANGED,
});
});
it('switchPositionMode()', async () => {
expect(
await api.switchPositionMode({
category: 'linear',
// both sides
mode: 3,
coin: settleCoin,
})
).toMatchObject({
...successResponseObjectV3(),
});
});
it('setRiskLimit()', async () => {
expect(
await api.setRiskLimit({
category: 'linear',
positionIdx: 1,
riskId: 1,
symbol: linearSymbol,
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_RISK_ID_NOT_CHANGED,
});
});
it('setTradingStop()', async () => {
expect(
await api.setTradingStop({
category: 'linear',
positionIdx: 1,
symbol: linearSymbol,
slSize: '100',
slTriggerBy: 'LastPrice',
stopLoss: '25000',
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_TPSL_ERROR_NO_POSITION,
});
});
it('setAutoAddMargin()', async () => {
expect(
await api.setAutoAddMargin({
category: 'linear',
autoAddMargin: 0,
symbol: linearSymbol,
positionIdx: 0,
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_AUTO_ADD_MARGIN_NOT_CHANGED,
});
});
});
describe('Account APIs', () => {
it('setMarginMode()', async () => {
expect(await api.setMarginMode('REGULAR_MARGIN')).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.V5_MARGIN_MODE_NOT_CHANGED,
});
});
it('setMMP()', async () => {
expect(
await api.setMMP({
baseCoin: settleCoin,
deltaLimit: '1',
frozenPeriod: '1',
qtyLimit: '1',
window: '1',
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.INSTITION_MMP_PROFILE_NOT_FOUND,
});
});
it('resetMMP()', async () => {
expect(await api.resetMMP(settleCoin)).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.INSTITION_MMP_PROFILE_NOT_FOUND,
});
});
});
describe('Asset APIs', () => {
it('createInternalTransfer()', async () => {
expect(
await api.createInternalTransfer(
fakeTransferId,
settleCoin,
'100',
'SPOT',
'CONTRACT'
)
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: expect.any(Number),
});
});
it('enableUniversalTransferForSubUIDs()', async () => {
expect(await api.enableUniversalTransferForSubUIDs([])).toMatchObject({
...successResponseObjectV3(),
});
});
it('createUniversalTransfer()', async () => {
expect(
await api.createUniversalTransfer({
amount: '100',
coin: settleCoin,
fromAccountType: 'SPOT',
fromMemberId: 1,
toAccountType: 'CONTRACT',
toMemberId: 2,
transferId: fakeTransferId,
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: expect.any(Number),
});
});
it('submitWithdrawal()', async () => {
expect(
await api.submitWithdrawal({
address: '0x000000',
amount: '100',
chain: 'TRC20',
coin: settleCoin,
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.INCORRECT_API_KEY_PERMISSIONS,
});
});
it('cancelWithdrawal()', async () => {
expect(await api.cancelWithdrawal('fakeId')).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.INCORRECT_API_KEY_PERMISSIONS,
});
});
});
describe('User APIs', () => {
it('createSubMember()', async () => {
expect(
await api.createSubMember({
memberType: 1,
username: 'sub1account',
switch: 1,
note: 'created via e2e test',
})
).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.SUB_USER_ALREADY_EXISTS,
});
});
it('setSubUIDFrozenState()', async () => {
expect(await api.setSubUIDFrozenState(0, 1)).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.SUB_USER_NOT_FOUND,
});
});
});
describe('Spot Leverage Token APIs', () => {
let leverageToken: LeverageTokenInfoV5;
beforeAll(async () => {
const tokenResult = await api.getLeveragedTokenInfo();
leverageToken = tokenResult.result.list[0];
});
it('purchaseSpotLeveragedToken()', async () => {
expect(
await api.purchaseSpotLeveragedToken({
amount: '100',
ltCoin: leverageToken.ltCoin,
})
).toMatchObject({
// ...successResponseObjectV3(),
retCode: API_ERROR_CODE.SPOT_LEVERAGE_QUIZ_REQUIRED,
// retMsg: '',
});
});
it('redeemSpotLeveragedToken()', async () => {
expect(
await api.redeemSpotLeveragedToken({
quantity: '100',
ltCoin: leverageToken.ltCoin,
})
).toMatchObject({
// ...successResponseObjectV3(),
retCode: API_ERROR_CODE.SPOT_LEVERAGE_TOKEN_INSUFFICIENT_BALANCE,
// retMsg: '',
});
});
});
describe('Spot Margin APIs', () => {
it('toggleSpotMarginTrade()', async () => {
expect(await api.toggleSpotMarginTrade('1')).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.SPOT_MARGIN_QUESTIONNAIRE_NOT_SUBMIT,
});
});
it('setSpotMarginLeverage()', async () => {
expect(await api.setSpotMarginLeverage('2')).toMatchObject({
// ...successResponseObjectV3(),
// retMsg: '',
retCode: API_ERROR_CODE.SPOT_MARGIN_NOT_ENABLED,
});
});
});
});

153
test/v5/public.read.test.ts Normal file
View File

@@ -0,0 +1,153 @@
import { RestClientV5 } from '../../src';
import { successResponseObjectV3 } from '../response.util';
describe('Public V5 REST API Endpoints', () => {
const API_KEY = undefined;
const API_SECRET = undefined;
const api = new RestClientV5({
key: API_KEY,
secret: API_SECRET,
testnet: false,
});
const linearSymbol = 'BTCUSDT';
describe('Misc Endpoints', () => {
it('fetchServerTime()', async () => {
expect(await api.fetchServerTime()).toEqual(expect.any(Number));
});
it('getServerTime()', async () => {
expect(await api.getServerTime()).toMatchObject(
successResponseObjectV3()
);
});
});
describe('Market Endpoints', () => {
it('getKline()', async () => {
expect(
await api.getKline({
category: 'linear',
interval: '1',
symbol: linearSymbol,
})
).toMatchObject(successResponseObjectV3());
});
it('getMarkPriceKline()', async () => {
expect(
await api.getMarkPriceKline({
category: 'linear',
interval: '1',
symbol: linearSymbol,
})
).toMatchObject(successResponseObjectV3());
});
it('getIndexPriceKline()', async () => {
expect(
await api.getIndexPriceKline({
category: 'linear',
interval: '1',
symbol: linearSymbol,
})
).toMatchObject(successResponseObjectV3());
});
it('getPremiumIndexPriceKline()', async () => {
expect(
await api.getPremiumIndexPriceKline({
category: 'linear',
interval: '1',
symbol: linearSymbol,
})
).toMatchObject(successResponseObjectV3());
});
it('getInstrumentsInfo()', async () => {
expect(
await api.getInstrumentsInfo({
category: 'linear',
symbol: linearSymbol,
})
).toMatchObject(successResponseObjectV3());
});
it('getOrderbook()', async () => {
expect(
await api.getOrderbook({
category: 'linear',
symbol: linearSymbol,
})
).toMatchObject(successResponseObjectV3());
});
it('getTickers()', async () => {
expect(
await api.getTickers({
category: 'linear',
symbol: linearSymbol,
})
).toMatchObject(successResponseObjectV3());
});
it('getFundingRateHistory()', async () => {
expect(
await api.getFundingRateHistory({
category: 'linear',
symbol: linearSymbol,
})
).toMatchObject(successResponseObjectV3());
});
it('getPublicTradingHistory()', async () => {
expect(
await api.getPublicTradingHistory({
category: 'linear',
symbol: linearSymbol,
})
).toMatchObject(successResponseObjectV3());
});
it('getOpenInterest()', async () => {
expect(
await api.getOpenInterest({
category: 'linear',
symbol: linearSymbol,
intervalTime: '15min',
})
).toMatchObject(successResponseObjectV3());
});
it('getHistoricalVolatility()', async () => {
expect(
await api.getHistoricalVolatility({
category: 'option',
})
).toMatchObject(successResponseObjectV3());
});
it('getInsurance()', async () => {
expect(await api.getInsurance()).toMatchObject(successResponseObjectV3());
});
it('getRiskLimit()', async () => {
expect(
await api.getRiskLimit({
category: 'linear',
symbol: linearSymbol,
})
).toMatchObject(successResponseObjectV3());
});
it('getOptionDeliveryPrice()', async () => {
expect(
await api.getOptionDeliveryPrice({
category: 'option',
})
).toMatchObject(successResponseObjectV3());
});
});
});

View File

@@ -1,6 +1,9 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-empty-function */
import { WebsocketClient, WsClientEvent } from '../src';
export function getSilentLogger(logHint?: string) {
export function getSilentLogger(_logHint?: string) {
return {
silly: () => {},
debug: () => {},
@@ -33,6 +36,7 @@ export function waitForSocketEvent(
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(
// eslint-disable-next-line max-len
`Failed to receive "${event}" event before timeout. Check that these are correct: topic, api keys (if private), signature process (if private)`
);
}, timeoutMs);
@@ -126,7 +130,7 @@ export function logAllEvents(wsClient: WebsocketClient) {
}
export function promiseSleep(ms: number) {
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

8
tsconfig.examples.json Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "distExamples",
"allowJs": true
},
"include": ["examples/**/*.ts", "examples/**/*.js"]
}

View File

@@ -13,14 +13,9 @@
"skipLibCheck": true,
"sourceMap": true,
"esModuleInterop": true,
"lib": ["es2017","dom"],
"lib": ["es2017", "dom"],
"outDir": "lib"
},
"include": ["src/**/*"],
"exclude": [
"node_modules",
"**/node_modules/*",
"coverage",
"doc"
]
"exclude": ["node_modules", "**/node_modules/*", "coverage", "doc"]
}

8
tsconfig.test.json Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "distTest",
"allowJs": true
},
"include": ["test/**/*.ts", "test/**/*.js"]
}