This file is a merged representation of a subset of the codebase, containing files not matching ignore patterns, combined into a single document by Repomix.
The content has been processed where content has been compressed (code blocks are separated by ⋮---- delimiter).
================================================================
File Summary
================================================================
Purpose:
--------
This file contains a packed representation of a subset of the repository's contents that is considered the most important context.
It is designed to be easily consumable by AI systems for analysis, code review,
or other automated processes.
File Format:
------------
The content is organized as follows:
1. This summary section
2. Repository information
3. Directory structure
4. Repository files (if enabled)
5. Multiple file entries, each consisting of:
a. A separator line (================)
b. The file path (File: path/to/file)
c. Another separator line
d. The full contents of the file
e. A blank line
Usage Guidelines:
-----------------
- This file should be treated as read-only. Any changes should be made to the
original repository files, not this packed version.
- When processing this file, use the file path to distinguish
between different files in the repository.
- Be aware that this file may contain sensitive information. Handle it with
the same level of security as you would the original repository.
Notes:
------
- Some files may have been excluded based on .gitignore rules and Repomix's configuration
- Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files
- Files matching these patterns are excluded: .github/, examples/apidoc/, docs/images/, docs/endpointFunctionList.md, test/, src/util/
- Files matching patterns in .gitignore are excluded
- Files matching default ignore patterns are excluded
- Content has been compressed - code blocks are separated by ⋮---- delimiter
- Files are sorted by Git change count (files with more changes are at the bottom)
================================================================
Directory Structure
================================================================
examples/
kucoin-FUTURES-examples-nodejs.md
kucoin-SPOT-examples-nodejs.md
rest-futures-orders-guide.ts
rest-futures-private-trade.ts
rest-futures-public.ts
rest-spot-private-trade.ts
rest-spot-public.ts
tsconfig.examples.json
ws-futures-private.ts
ws-futures-public.ts
ws-spot-private.ts
ws-spot-public.ts
src/
lib/
websocket/
logger.ts
websocket-util.ts
WsStore.ts
WsStore.types.ts
BaseRestClient.ts
BaseWSClient.ts
misc-util.ts
requestUtils.ts
webCryptoAPI.ts
types/
request/
broker.types.ts
futures.types.ts
spot-account.ts
spot-affiliate.ts
spot-convert.ts
spot-earn.ts
spot-funding.ts
spot-margin-trading.ts
spot-misc.ts
spot-trading.ts
response/
broker.types.ts
futures.types.ts
shared.types.ts
spot-account.ts
spot-affiliate.ts
spot-convert.ts
spot-earn.ts
spot-funding.ts
spot-margin-trading.ts
spot-misc.ts
spot-trading.ts
spot-vip.ts
ws.ts
websockets/
client.ts
events.ts
requests.ts
wsAPI.ts
BrokerClient.ts
FuturesClient.ts
index.ts
SpotClient.ts
WebsocketClient.ts
.eslintrc.cjs
.gitignore
.nvmrc
.prettierrc
jest.config.ts
package.json
postBuild.sh
README.md
tea.yaml
tsconfig.cjs.json
tsconfig.esm.json
tsconfig.json
tsconfig.linting.json
================================================================
Files
================================================================
================
File: examples/kucoin-FUTURES-examples-nodejs.md
================
# **KuCoin FUTURES API Examples** - Node.js, JavaScript & Typescript SDK for Kucoin REST APIs & WebSockets
This document provides comprehensive examples for using the KuCoin FUTURES API with Node.js and JavaScript. It covers various functionalities including account management, fund transfers, trade execution, order management, and market data retrieval. The examples are designed to help developers quickly integrate KuCoin Futures API into their NodeJS, Javascript and Typscript applications.
If you are here, it means you will be great addition to our [Node.js Traders](https://t.me/nodetraders) community on Telegram where we discuss trading ideas, provide support regarding SDKs and share valuable resources!
- [KuCoin Documentation](https://docs.kucoin.com/futures/#introduction) - official Kucoin API docs
- [Node.js & JavaScript SDK for Kucoin](https://github.com/tiagosiebler/kucoin-api) - Github repo of our SDK
Current file contains only certain most used examples. If you can't find what you need, you can search through [FuturesClient.ts](https://github.com/tiagosiebler/kucoin-api/blob/master/src/FuturesClient.ts) - all of the endpoints and functions will be there! Otherwise, just ask in [Node.js Traders](https://t.me/nodetraders) Telegram group.
Do you need help with Spot? Check out [Spot Quickstart guide](https://github.com/tiagosiebler/kucoin-api/blob/master/examples/kucoin-SPOT-examples-nodejs.md)
**Table of contents:**
- [Installation](#installation)
- [Usage](#usage)
- [REST API](#rest-api)
- [Account and balance](#account-examples)
- [Subaccount API management](#subaccount-api-management)
- [Market Data](#market-data)
- [Symbol and exchange info](#symbol-and-exchange-info)
- [Order Book data](#order-book-data)
- [Public Trades and Index data](#public-trades-and-index-data)
- [Funding Fees](#funding-fees)
- [Kline/Candles](#klinecandles)
- [Transfer funds in and out of Futures Account](#transfer-funds-in-and-out-of-futures-account)
- [Trade Execution](#trade)
- [General info](#general-info)
- [Market short](#market-short)
- [Market long](#market-long)
- [Limit short](#limit-short)
- [Limit long](#limit-long)
- [Market close](#market-close)
- [Limit close](#limit-close)
- [Stop loss](#stop-loss)
- [Place multiple orders](#place-multiple-orders)
- [Cancel order](#cancel-order)
- [Cancel all orders for specific symbol](#cancel-all-orders-for-specific-symbol)
- [Trade/Order/Positions Management](#tradeorderpositions-management)
- [Fetching orders](#fetching-orders)
- [Fills](#fills)
- [Positions](#positions)
- [WebSocket](#websocket)
- [Community group](#community-group)
## Installation:
```js
// Install by npm
npm install kucoin-api
// Install by yarn
yarn add kucoin-api
```
## Usage
#### Create API credentials
- [Kucoin API Key Management](https://www.kucoin.com/account/api)
#### Import SDK to your project
```js
// require
const { FuturesClient } = require('kucoin-api');
// import
import { FuturesClient } from 'kucoin-api';
// initialise Futures Client
const futuresClient = new FuturesClient({
// insert your api key, secret and passphrase - use env vars, if not just fill the string values
apiKey: process.env.KUCOIN_API_KEY || 'insert-your-api-key',
apiSecret: process.env.KUCOIN_API_SECRET || 'insert-your-api-secret',
apiPassphrase:
process.env.KUCOIN_API_PASSPHRASE || 'insert-your-api-passphrase',
});
```
## REST API
### Account examples
#### Get Account Overview
```js
// Get Account Balance - XBT or USDT, default XBT
futuresClient.getBalance({ currency: 'XBT' });
// Get All Subaccount Accounts Balance
futuresClient.getSubBalances({ currency: 'XBT' });
```
#### Get Transaction History
```js
futuresClient.getTransactions({
type: 'RealisedPNL', // 'RealisedPNL' | 'Deposit' | 'Withdrawal' | 'Transferin' | 'TransferOut'
maxCount: 10,
currency: 'USDT',
});
```
### Subaccount API management
```js
// Get all subaccount APIs
futuresClient.getSubAPIs({
subName: 'my_sub_name',
});
// Create Futures APIs for Sub-Account
futuresClient.createSubAPI({
subName: 'my_sub_name',
passphrase: 'my_passphrase',
remark: 'my_remark',
});
// Modify Sub-Account Futures APIs
futuresClient.updateSubAPI({
subName: 'my_sub_name',
passphrase: 'my_passphrase',
apiKey: 'my_api_key',
});
// Delete Sub-Account Futures APIs
futuresClient.deleteSubAPI({
subName: 'my_sub_name',
passphrase: 'my_passphrase',
apiKey: 'my_api_key',
});
```
### Market Data
#### Symbol and exchange info
```js
// Get All Contract List
futuresClient.getSymbols();
// Get Order Info of the Contract
futuresClient.getSymbol({ symbol: 'XBTUSDTM' });
// Get Ticker
futuresClient.getTicker({ symbol: 'XBTUSDTM' });
```
#### Order Book data
```js
// Get Full Order Book - Level 2
futuresClient.getFullOrderBookLevel2({ symbol: 'XBTUSDTM' });
// Get Level2 depth20
futuresClient.getPartOrderBookLevel2Depth20({ symbol: 'XBTUSDTM' });
// Get Level2 depth100
futuresClient.getPartOrderBookLevel2Depth100({ symbol: 'XBTUSDTM' });
```
#### Public Trades and Index data
```js
// Get Public Trades
futuresClient.getMarketTrades({ symbol: 'XBTUSDTM' });
// Get Interest Rate List
futuresClient.getInterestRates({ symbol: '.XBTINT' });
// Get Index List
futuresClient.getIndex({ symbol: '.KXBT' });
// Get Current Mark Price
futuresClient.getMarkPrice({ symbol: 'XBTUSDM' });
// Get Premium Index
futuresClient.getPremiumIndex({ symbol: '.XBTUSDMPI' });
// Get 24hour futures transaction volume
futuresClient.get24HourTransactionVolume();
```
#### Funding Fees
```js
// Get Current Funding Rate
futuresClient.getFundingRate({ symbol: 'XBTUSDM' });
// Get Public Funding History
futuresClient.getFundingRates({
symbol: 'XBTUSDTM',
from: '1700310700000',
to: '1702310700000',
});
// Get Private Funding History
futuresClient.getFundingHistory({ symbol: 'ETHUSDTM' });
```
#### Kline/Candles
```js
futuresClient.getKlines({
symbol: 'XBTUSDTM',
granularity: 60,
from: new Date().getTime() - 24 * 60 * 60 * 1000, // 24 hours ago
to: new Date().getTime(),
});
```
### Transfer funds in and out of Futures Account
```js
// Transfer out of the Futures to main acc
futuresClient.submitTransferOut({
amount: 0.01,
currency: 'USDT',
recAccountType: 'MAIN',
});
// Transfer to Futures Account
futuresClient.submitTransferIn({
amount: 0.01,
currency: 'USDT',
payAccountType: 'MAIN',
});
// Get All Transfers
futuresClient.futureTransfers({
status: 'SUCCESS', // optional, 'PROCESSING' | 'SUCCESS' | 'FAILURE';
currency: 'USDT', // optional
startAt: 1723550000, // optional
endAt: 1723557472, // optional
currentPage: 1, // optional
pageSize: 100, // optional
});
```
---
### Trade
#### General info
Futures are contracts, not currencies. In the futures symbols list you will see a "multiplier" field for each of the symbols. Each contract is equal to Multiplier x Size.
For example click on this endpoint and get a symbol info for XRPUSDTM: https://api-futures.kucoin.com/api/v1/contracts/XRPUSDTM
In the object, find the "multiplier" value.
```js
// In your code, you can fetch it like this
const symbolInfo = await client.getSymbol({ symbol: 'XRPUSDTM' });
const multiplier = symbolInfo.data.multiplier;
```
E.g. if multiplier is 10(what you can see from the endpoint), that means each SIZE is 10 XRP. So if XRP is currently at $0.5, then each 1 contract (size 10) is going to cost $5.00
size = (Funds x leverage) / (price x multiplier)
```js
const XRPPriceExample = 0.5;
const leverage = 5;
const fundsToTradeUSDT = 100;
const costOfContract = XRPPriceExample * multiplier;
const size = (fundsToTradeUSDT * leverage) / costOfContract;
console.log(`Size: ${size}`);
```
The trade amount indicates the amount of contract to buy or sell, and contract uses the base currency(USD contracts e.g. XBTUSDM) or lot( USDT contracts e.g. XBTUSDTM) as the trading unit.
The trade amount must be no less than 1 lot for the contract and no larger than the maxOrderQty.
It should be a multiple number of the lot, or the system will report an error when you place the order.
E.g. 1 lot of XBTUSDTM is 0.001 Bitcoin, while 1 lot of XBTUSDM is 1 USD.
You can get info about any contract on the link: https://api-futures.kucoin.com/api/v1/contracts/****\_\_**** - just replace the empty space with the symbol of the contract.
Here are function examples using the Futures Create Order endpoint:
#### Market Short
```js
// A MARKET SHORT of 2 contracts of XBT using leverage of 5:
const marketShort = futureTransfers.submitOrder({
clientOid: '123456789',
leverage: '5',
side: 'sell',
size: 2,
symbol: 'XBTUSDTM',
timeInForce: 'GTC',
type: 'market',
});
```
#### Market Long
```js
// A MARKET LONG of 2 contracts of XBT using leverage of 5:
const marketLong = futureTransfers.submitOrder({
clientOid: '123456789',
leverage: '5',
side: 'buy',
size: 2,
symbol: 'XBTUSDTM',
timeInForce: 'GTC',
type: 'market',
});
```
#### Limit Short
```js
// A LIMIT SHORT of 2 contracts of XBT using leverage of 5:
const limitShort = futureTransfers.submitOrder({
clientOid: '123456789',
leverage: '5',
price: '70300.31',
side: 'sell',
size: 2,
symbol: 'XBTUSDTM',
timeInForce: 'GTC',
type: 'limit',
});
```
#### Limit Long
```js
// A LIMIT LONG of 2 contracts of XBT using leverage of 5:
const limitLong = futureTransfers.submitOrder({
clientOid: '123456789',
leverage: '5',
price: '40300.31',
side: 'buy',
size: 2,
symbol: 'XBTUSDTM',
timeInForce: 'GTC',
type: 'limit',
});
```
On any "close position" action, if you specify a SIZE=0 or leave off the SIZE parameter,
then it will close the whole position, regardless of the size.
If you specify a SIZE, it will close only the number of contracts you specify.
If closeOrder is set to TRUE,
the system will close the position and the position size will become 0.
Side, Size and Leverage fields can be left empty and the system will determine the side and size automatically.
#### Market close
```js
// A MARKET CLOSE POSITION example:
const marketClose = futureTransfers.submitOrder({
clientOid: '123456789',
closeOrder: true,
symbol: 'XBTUSDTM',
timeInForce: 'GTC',
type: 'market',
side: 'sell',
size: 0,
});
```
#### Limit close
```js
// A LIMIT CLOSE of a LONG example:
const limitCloseLong = futureTransfers.submitOrder({
clientOid: '123456789',
leverage: '5',
price: '70300.31',
closeOrder: true,
side: 'sell',
size: 2,
symbol: 'XBTUSDTM',
timeInForce: 'GTC',
type: 'limit',
});
// A LIMIT CLOSE of a SHORT example:
const limitCloseShort = futureTransfers.submitOrder({
clientOid: '123456789',
leverage: '5',
price: '40300.31',
closeOrder: true,
side: 'buy',
size: 2,
symbol: 'XBTUSDTM',
timeInForce: 'GTC',
type: 'limit',
});
```
#### Stop loss
```js
// A STOP LOSS example for a LONG position:
const stopLossLong = futureTransfers.submitOrder({
clientOid: '123456789',
closeOrder: true,
stop: 'down',
stopPrice: '40200.31',
stopPriceType: 'TP',
symbol: 'XBTUSDTM',
timeInForce: 'GTC',
type: 'market',
});
// A STOP LOSS example for a SHORT position:
const stopLossShort = futureTransfers.submitOrder({
clientOid: '123456789',
closeOrder: true,
stop: 'up',
stopPrice: '40200.31',
stopPriceType: 'TP',
symbol: 'XBTUSDTM',
timeInForce: 'GTC',
type: 'market',
});
```
##### Place Multiple Orders
```js
//request
const orders = [
{
clientOid: '5c52e11203aa677f33e491',
side: 'buy',
symbol: 'ETHUSDTM',
type: 'limit',
price: '2150',
leverage: '1',
size: 2,
},
{
clientOid: 'je12019ka012ja013099',
side: 'buy',
symbol: 'XBTUSDTM',
type: 'limit',
price: '32150',
leverage: '1',
size: 2,
},
];
futuresClient.submitMultipleOrders(orders);
```
#### Cancel Order
```js
futuresClient.cancelOrderById({ orderId: 'orderId' });
futuresClient.cancelOrderByClientOid({ clientOid: 'clientOid' });
```
#### Cancel all orders for specific symbol
```js
futuresClient.cancelAllOrders({ symbol: 'XBTUSDTM' });
futuresClient.cancelAllStopOrders({ symbol: 'XBTUSDTM' });
```
### Trade/Order/Positions Management
#### Fetching orders
```js
// Get open orders
futuresClient.getOrders({ status: 'active' });
// Get closed orders
futuresClient.getOrders({ status: 'done' });
// Get Untriggered Stop Orders
futuresClient.getStopOrders({ type: 'limit' });
// Get List of Orders Completed in 24h
futuresClient.getRecentOrders();
// Get Details of a Single Order by ClientOrderId
futuresClient.getOrderByClientOrderId({ clientOid: 'clientOid' });
// Or By OrderId
futuresClient.getOrderByOrderId({ orderId: 'orderId' });
```
#### Fills
```js
// Get Specific Fills
futuresClient.getFills({ type: 'market' });
// or search for all
futuresClient.getFills({});
// Recent Fills from last 24 hours
futuresClient.futuresRecentFills({ symbol: 'ETHUSDTM' });
// Or Search All
futuresClient.futuresRecentFills({});
// Active Order Value Calculation
futuresClient.getOpenOrderStatistics({ symbol: 'ETHUSDTM' });
```
#### Positions
```js
// Get Position Details
futuresClient.getPosition({ symbol: 'ETHUSDTM' });
// Get Position List
futuresClient.getPositions({ currency: 'USDT' });
// Or Search All
futuresClient.getPositions();
// Get History Positions
futuresClient.getHistoryPositions({ symbol: 'ETHUSDTM' });
```
## Websocket
For Websocket examples, please refer to these links:
- [Spot Public Websocket](https://github.com/tiagosiebler/kucoin-api/blob/master/examples/ws-spot-public.ts)
- [Spot Private Websocket](https://github.com/tiagosiebler/kucoin-api/blob/master/examples/ws-spot-private.ts)
- [Futures Public Websocket](https://github.com/tiagosiebler/kucoin-api/blob/master/examples/ws-futures-public.ts)
- [Futures Private Websocket](https://github.com/tiagosiebler/kucoin-api/blob/master/examples/ws-futures-private.ts)
## Community group
If you need help, something is wrong/missing or you have suggestions, please join our [Node.js Traders](https://t.me/nodetraders) community group on Telegram and let us know!
================
File: examples/kucoin-SPOT-examples-nodejs.md
================
# **KuCoin SPOT API Examples** - Node.js, JavaScript & Typescript SDK for Kucoin REST APIs & WebSockets
This document provides comprehensive examples for using the KuCoin SPOT API with Node.js and JavaScript. It covers various functionalities including account management, fund transfers, trade execution, order management, and market data retrieval. The examples are designed to help developers quickly integrate KuCoin Spot API into their NodeJS, Javascript and Typscript applications.
If you are here, it means you will be great addition to our [Node.js Traders](https://t.me/nodetraders) community on Telegram where we discuss trading ideas, provide support regarding SDKs and share valuable resources!
- [KuCoin Documentation](https://www.kucoin.com/docs/beginners/introduction) - official Kucoin API docs
- [Node.js & JavaScript SDK for Kucoin](https://github.com/tiagosiebler/kucoin-api) - Github repo of our SDK
Current file contains only certain most used examples. If you can't find what you need, you can search through [SpotClient.ts](https://github.com/tiagosiebler/kucoin-api/blob/master/src/SpotClient.ts) - all of the endpoints and functions will be there! Otherwise, just ask in [Node.js Traders](https://t.me/nodetraders) Telegram group.
Do you need help with Futures? Check out [Futures Quickstart guide](https://github.com/tiagosiebler/kucoin-api/blob/master/examples/kucoin-FUTURES-examples-nodejs.md)
**Table of contents:**
- [Installation](#installation)
- [Usage](#usage)
- [REST API](#rest-api)
- [Account and balance](#account-examples)
- [Account overview](#account-overview)
- [Transactions](#transactions)
- [Deposit and Withdrawal](#deposit-and-withdrawal)
- [Subaccount](#subaccount)
- [Subaccount management](#subaccount-management)
- [Subaccount API management](#subaccount-api-management)
- [Market Data](#market-data)
- [Symbol and exchange info](#symbol-and-exchange-info)
- [Order Book data](#order-book-data)
- [Kline/Candles](#klinecandles)
- [Trade Execution](#trade)
- [General info](#general-info)
- [Market short](#market-short)
- [Market long](#market-long)
- [Limit short](#limit-short)
- [Limit long](#limit-long)
- [Place multiple orders](#place-multiple-orders)
- [Trade/Order/Positions Management](#tradeorderpositions-management)
- [Fetching orders](#fetching-orders)
- [Cancel order](#cancel-order)
- [Cancel all orders for specific symbol](#cancel-all-orders-for-specific-symbol)
- [Fills](#fills)
- [Spot HF trade](#spot-hf-trade)
- [Margin trade](#margin-trade--margin-hf-trade)
- [WebSocket](#websocket)
- [Community group](#community-group)
## Installation:
```js
// Install by npm
npm install kucoin-api
// Install by yarn
yarn add kucoin-api
```
## Usage
#### Create API credentials
- [Kucoin API Key Management](https://www.kucoin.com/account/api)
#### Import SDK to your project
```js
// require
const { SpotClient } = require('kucoin-api');
// import
import { SpotClient } from 'kucoin-api';
// initialise Spot Client
const spotClient = new SpotClient({
// insert your api key, secret and passphrase - use env vars, if not just fill the string values
apiKey: process.env.KUCOIN_API_KEY || 'insert-your-api-key',
apiSecret: process.env.KUCOIN_API_SECRET || 'insert-your-api-secret',
apiPassphrase:
process.env.KUCOIN_API_PASSPHRASE || 'insert-your-api-passphrase',
});
```
## REST API
### Account examples
#### Account Overview
```js
// Get Account Summary
spotClient.getAccountSummary();
// Get all Account Balances
spotClient.getBalances();
// Get specific Account or Currency Balance
spotClient.getBalance({
currency: 'USDT',
type: 'main', // 'trade' | 'margin' | 'trade_hf'
});
// Example call to get account details by ID
spotClient.getAccountDetails({ accountId: '5bd6e9286d99522a52e458de' });
// Margin endpoints for balances
spotClient.getMarginBalances();
spotClient.getMarginBalance();
spotClient.getIsolatedMarginBalance();
```
#### Transactions
```js
// Example call to get account ledgers with specified parameters
spotClient.getTransactions({ currency: 'BTC', startAt: 1601395200000 });
// Example call to get high-frequency account ledgers with specified parameters
spotClient.getHFTransactions({
bizType: 'TRADE_EXCHANGE',
currency: 'YOP,DAI',
startAt: 1601395200000,
});
// Example call to get high-frequency margin account ledgers with specified parameters
spotClient.getHFMarginTransactions({
bizType: 'MARGIN_EXCHANGE',
currency: 'YOP,DAI',
startAt: 1601395200000,
});
```
#### Deposit and Withdrawal
```js
// Example call to create a deposit address
spotClient.createDepositAddress({
currency: 'BTC',
// Optional parameter
chain: 'BTC',
});
// Example call to get deposit addresses with specified parameters
spotClient.getDepositAddressesV2({
currency: 'BTC',
});
// Example call to get deposits
spotClient.getDeposits();
// Example call to get withdrawals with specified parameters
spotClient.getWithdrawals({
currency: 'BTC', // Optional parameter
});
// Example call to submit a withdrawal
spotClient.submitWithdraw({
currency: 'BTC',
address: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
amount: 0.01,
// Optional parameters
memo: 'exampleMemo',
chain: 'BTC',
});
// Example call to cancel a withdrawal by ID
spotClient.cancelWithdrawal({
withdrawalId: '5bffb63303aa675e8bbe18f9',
});
```
### Subaccount
#### Subaccount Management
```js
// Get all subaccounts
spotClient.getSubAccountsV2({});
// Example call to create a sub-account
spotClient.createSubAccount({
// Fill in the required parameters for creating a sub-account
subName: 'exampleSubAccount',
password: 'examplePassword',
access: 'trade',
});
// Example call to get sub-account balance with specified parameters
spotClient.getSubAccountBalance({
subUserId: '5caefba7d9575a0688f83c45',
includeBaseAmount: false,
});
// Example call to get sub-account balances
spotClient.getSubAccountBalancesV2();
// Example call to get transferable funds
spotClient.getTransferable({
currency: 'BTC',
type: 'MAIN',
});
// Example call to submit a transfer from master to sub-account
spotClient.submitTransferMasterSub({
clientOid: client.generateNewOrderID(), // or use your custom UUID
amount: 0.01,
currency: 'USDT',
direction: 'OUT', // 'IN' for transfer to master, 'OUT' for transfer to sub
subUserId: 'enter_sub_user_id_here',
});
// Example call to submit an inner transfer within same account
spotClient.submitInnerTransfer({
clientOid: client.generateNewOrderID(), // or use your custom UUID
amount: 0.01,
currency: 'USDT',
from: 'main', // Source account type
to: 'trade', // Destination account type
});
```
#### Subaccount API management
```js
// Get all subaccount APIs
spotClient.getSubAPIs({
subName: 'my_sub_name',
});
// Create APIs for Sub-Account
spotClient.createSubAPI({
subName: 'my_sub_name',
passphrase: 'my_passphrase',
remark: 'my_remark',
});
// Modify Sub-Account APIs
spotClient.updateSubAPI({
subName: 'my_sub_name',
passphrase: 'my_passphrase',
apiKey: 'my_api_key',
});
// Delete Sub-Account APIs
spotClient.deleteSubAPI({
subName: 'my_sub_name',
passphrase: 'my_passphrase',
apiKey: 'my_api_key',
});
```
### Market Data
#### Symbol and exchange info
```js
// Get All Currencies List
spotClient.getCurrencies();
// Get info for a specific currency
spotClient.getCurrency({
currency: 'BTC',
});
// Get all Symbols
spotClient.getSymbols();
// Example call to get ticker information for a specific symbol
spotClient.getTicker({
symbol: 'BTC-USDT',
});
// All tickers
spotClient.getTickers();
// Get 24h stats for a specific symbol
spotClient.get24hrStats({
symbol: 'BTC-USDT',
});
```
#### Order Book data
```js
// get partial orderbook
spotClient.getOrderBookLevel20({ symbol: 'BTC-USDT' });
// get partial orderbook
spotClient.getOrderBookLevel100({ symbol: 'BTC-USDT' });
// get full orderbook
spotClient.getFullOrderBook({ symbol: 'BTC-USDT' });
```
#### Kline/Candles
```js
// Example call to get Klines (candlestick data) with specified parameters
spotClient.getKlines({
type: '1min',
symbol: 'BTC-USDT',
startAt: 1566703297,
endAt: 1566789757,
});
```
---
### Trade
#### General info
Please, read official [Kucoin API docs](https://www.kucoin.com/docs/rest/spot-trading/orders/place-order) to understand how to place orders, cancel orders, etc. and what is needed for each endpoint. These are just low-end examples to understand how to use it with SDK.
#### Market Short
```js
// Market short order
const marketShort = spotClient.submitOrder({
clientOid: client.generateNewOrderID(), // or use your custom UUID
side: 'sell',
symbol: 'ETH-BTC',
type: 'market',
size: '0.5', // Specify the quantity to sell
});
```
#### Market Long
```js
// Market long order
const marketLong = spotClient.submitOrder({
clientOid: client.generateNewOrderID(), // or use your custom UUID
side: 'buy',
symbol: 'ETH-BTC',
type: 'market',
size: '0.5', // Specify the quantity to buy
});
```
#### Limit Short
```js
// Limit short order
const limitShort = spotClient.submitOrder({
clientOid: client.generateNewOrderID(), // or use your custom UUID
side: 'sell',
symbol: 'ETH-BTC',
type: 'limit',
price: '0.03', // Specify the price to sell
size: '0.5', // Specify the quantity to sell
timeInForce: 'GTC', // Good Till Canceled
});
```
#### Limit Long
```js
// Limit long order
const limitLong = spotClient.submitOrder({
clientOid: client.generateNewOrderID(), // or use your custom UUID
side: 'buy',
symbol: 'ETH-BTC',
type: 'limit',
price: '0.03', // Specify the price to buy
size: '0.5', // Specify the quantity to buy
timeInForce: 'GTC', // Good Till Canceled
});
```
##### Place Multiple Orders
```js
//request
const multipleOrders = [
{
clientOid: '3d07008668054da6b3cb12e432c2b13a',
side: 'buy',
type: 'limit',
price: '0.01',
size: '0.01',
},
{
clientOid: '37245dbe6e134b5c97732bfb36cd4a9d',
side: 'buy',
type: 'limit',
price: '0.01',
size: '0.01',
},
];
spotClient.submitMultipleOrders({
symbol: 'KCS-USDT',
orderList: multipleOrders,
});
```
### Trade/Order/Positions Management
#### Fetching orders
```js
// Get open orders
spotClient.getOrders({ status: 'active' });
// Get closed orders
spotClient.getOrders({ status: 'done' });
// Get List of Orders Completed in 24h
spotClient.getRecentOrders();
// Get Details of a Single Order by ClientOrderId
spotClient.getOrderByClientOid({ clientOid: 'clientOid' });
// Or By OrderId
spotClient.getOrderByOrderId({ orderId: 'orderId' });
```
#### Cancel Order
```js
spotClient.cancelOrderById({ orderId: 'orderId' });
spotClient.cancelOrderByClientOid({ clientOid: 'clientOid' });
```
#### Cancel all orders for specific symbol
```js
//cancel all orders for symbol
spotClient.cancelAllOrders({ symbol: 'XBTUSDTM' });
// cancel all orders for all symbols
spotClient.cancelAllOrders();
```
#### Fills
```js
// Get Specific Fills
spotClient.getFills({ type: 'market' });
// or search for all
spotClient.getFills();
// Recent Fills from last 24 hours
spotClient.getRecentFills();
```
### Spot HF trade
All of the examples are 99% same as regular spot, but you can follow the [official HF Trade API documentation](https://www.kucoin.com/docs/rest/spot-trading/spot-hf-trade-pro-account/place-hf-order) and list of functions in [SpotClient.ts](https://github.com/tiagosiebler/kucoin-api/blob/master/src/SpotClient.ts) to find what you need!
### Margin trade & Margin HF trade
All of the examples are 99% same as regular spot, but you can follow the [official Margin Trade API documentation](https://www.kucoin.com/docs/rest/margin-trading/market-data) and list of functions in [SpotClient.ts](https://github.com/tiagosiebler/kucoin-api/blob/master/src/SpotClient.ts) to find what you need!
---
## Websocket
For Websocket examples, please refer to these links:
- [Spot Public Websocket](https://github.com/tiagosiebler/kucoin-api/blob/master/examples/ws-spot-public.ts)
- [Spot Private Websocket](https://github.com/tiagosiebler/kucoin-api/blob/master/examples/ws-spot-private.ts)
- [Futures Public Websocket](https://github.com/tiagosiebler/kucoin-api/blob/master/examples/ws-futures-public.ts)
- [Futures Private Websocket](https://github.com/tiagosiebler/kucoin-api/blob/master/examples/ws-futures-private.ts)
## Community group
If you need help, something is wrong/missing or you have suggestions, please join our [Node.js Traders](https://t.me/nodetraders) community group on Telegram and let us know!
================
File: examples/rest-futures-orders-guide.ts
================
import { FuturesClient } from '../src/index.ts';
// import { FuturesClient } from 'kucoin-api';
// normally you should install this module via npm: `npm install kucoin-api`
⋮----
async function start()
⋮----
/**
* =======
* Credits for this guide go to user: @DKTradingClient / Code Nerd from the Kucoin API Telegram group!
* =======
/**
* Futures are contracts, not currencies. In the futures symbols list you will see a "multiplier" field for each of the symbols.
* Each contract equals to Multiplier x Size
* For example: https://api-futures.kucoin.com/api/v1/contracts/XRPUSDTM - see the "multiplier" value.
* */
⋮----
/**
* E.g. if multiplier is 10(what you can see from the endpoint), that means each SIZE is 10 XRP. So if XRP is currently at $0.5,
* then each 1 contract (size 10) is going to cost $5.00
* size = (Funds x leverage) / (price x multiplier)
*/
⋮----
/**
* The trade amount indicates the amount of contract to buy or sell, and contract uses the base currency or lot as the trading unit.
* The trade amount must be no less than 1 lot for the contract and no larger than the maxOrderQty.
* It should be a multiple number of the lot, or the system will report an error when you place the order.
* E.g. 1 lot of XBTUSDTM is 0.001 Bitcoin, while 1 lot of XBTUSDM is 1 USD.
* or check the XRPUSDTM example above.
*
* Here are function examples using the Futures Create Order endpoint:
*/
⋮----
// A MARKET SHORT of 2 contracts of XBT using leverage of 5:
⋮----
// A MARKET LONG of 2 contracts of XBT using leverage of 5:
⋮----
// A LIMIT SHORT of 2 contracts of XBT using leverage of 5:
⋮----
// A LIMIT LONG of 2 contracts of XBT using leverage of 5:
⋮----
// On any "close position" action, if you specify a SIZE=0 or leave off the SIZE parameter,
// then it will close the whole position, regardless of the size.
// If you specify a SIZE, it will close only the number of contracts you specify.
⋮----
// If closeOrder is set to TRUE,
// the system will close the position and the position size will become 0.
// Side, Size and Leverage fields can be left empty and the system will determine the side and size automatically.
⋮----
// A MARKET CLOSE POSITION example:
⋮----
// A LIMIT CLOSE of a LONG example:
⋮----
// A LIMIT CLOSE of a SHORT example:
⋮----
// A STOP LOSS example for a LONG position:
⋮----
// A STOP LOSS example for a SHORT position:
================
File: examples/rest-futures-private-trade.ts
================
import { FuturesClient } from '../src/index.ts';
// import { FuturesClient } from 'kucoin-api';
// normally you should install this module via npm: `npm install kucoin-api`
⋮----
async function start()
⋮----
/**
* The trade amount indicates the amount of contract to buy or sell, and contract uses the base currency or lot as the trading unit.
* The trade amount must be no less than 1 lot for the contract and no larger than the maxOrderQty.
* It should be a multiple number of the lot, or the system will report an error when you place the order.
* E.g. 1 lot of XBTUSDTM is 0.001 Bitcoin, while 1 lot of XBTUSDM is 1 USD.
*/
⋮----
// Submit a futures entry order for 1 lot of XBTUSDTM (0.001 bitcoin)
================
File: examples/rest-futures-public.ts
================
import { FuturesClient } from '../src/index.ts';
// import { FuturesClient } from 'kucoin-api';
// normally you should install this module via npm: `npm install kucoin-api`
⋮----
async function start()
⋮----
// Fetch all symbols
⋮----
// Fetch ticker for a specific symbol
⋮----
// Fetch klines for a specific symbol
================
File: examples/rest-spot-public.ts
================
import { SpotClient } from '../src/index.ts';
// import { SpotClient } from 'kucoin-api';
// normally you should install this module via npm: `npm install kucoin-api`
⋮----
async function start()
⋮----
// Fetch all symbols
⋮----
// Fetch ticker for a specific symbol
⋮----
// Fetch klines for a specific symbol
================
File: examples/tsconfig.examples.json
================
{
"extends": "../tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "dist/cjs",
"target": "esnext",
"rootDir": "../"
},
"include": ["../src/**/*.*", "../examples/**/*.*"]
}
================
File: examples/ws-futures-private.ts
================
/* eslint-disable @typescript-eslint/no-unused-vars */
import { DefaultLogger, WebsocketClient } from '../src/index.js';
// import { DefaultLogger, WebsocketClient } from 'kucoin-api';
// normally you should install this module via npm: `npm install kucoin-api`
⋮----
async function start()
⋮----
// Optional: inject and customise a logger for more control over internal logging
// const logger: typeof DefaultLogger = {
// ...DefaultLogger,
// trace: (...params) => {
// if (
// [
// 'Sending ping',
// // 'Sending upstream ws message: ',
// 'Received pong',
// ].includes(params[0])
// ) {
// return;
// }
// console.log('trace', JSON.stringify(params, null, 2));
// },
// };
⋮----
passphrase: process.env.API_PASSPHRASE || 'apiPassPhraseHere', // This is NOT your account password
⋮----
// logger,
⋮----
// Data received
⋮----
// Something happened, attempting to reconenct
⋮----
// Reconnect successful
⋮----
// Connection closed. If unexpected, expect reconnect -> reconnected.
⋮----
// Reply to a request, e.g. "subscribe"/"unsubscribe"/"authenticate"
⋮----
// throw new Error('res?');
⋮----
// Optional: await a connection to be ready before subscribing (this is not necessary)
// await client.connect('futuresPrivateV1');
// console.log('connected');
⋮----
/**
* For more detailed usage info, refer to the ws-spot-public.ts example.
*
* Below are some examples for subscribing to private futures websockets.
* Note: all "private" websocket topics should use the "futuresPrivateV1" wsKey.
*/
================
File: examples/ws-futures-public.ts
================
/* eslint-disable @typescript-eslint/no-unused-vars */
import { DefaultLogger, WebsocketClient } from '../src/index.js';
// import { DefaultLogger, WebsocketClient } from 'kucoin-api';
// normally you should install this module via npm: `npm install kucoin-api`
⋮----
async function start()
⋮----
// Optional: fully customise the logging experience by injecting a custom logger
// const logger: typeof DefaultLogger = {
// ...DefaultLogger,
// trace: (...params) => {
// if (
// [
// 'Sending ping',
// 'Sending upstream ws message: ',
// 'Received pong',
// ].includes(params[0])
// ) {
// return;
// }
// console.log('trace', params);
// },
// };
⋮----
// const client = new WebsocketClient({}, logger);
⋮----
// Data received
⋮----
// Something happened, attempting to reconenct
⋮----
// Reconnect successful
⋮----
// Connection closed. If unexpected, expect reconnect -> reconnected.
⋮----
// Reply to a request, e.g. "subscribe"/"unsubscribe"/"authenticate"
⋮----
// throw new Error('res?');
⋮----
// Optional: await a connection to be ready before subscribing (this is not necessary)
// await client.connect('futuresPublicV1');
⋮----
/**
* Examples for public futures websocket topics (that don't require authentication).
*
* These should all subscribe via the "futuresPublicV1" wsKey. For detailed usage, refer to the ws-spot-public.ts example.
*/
================
File: examples/ws-spot-private.ts
================
/* eslint-disable @typescript-eslint/no-unused-vars */
import { DefaultLogger, WebsocketClient } from '../src/index.js';
// import { DefaultLogger, WebsocketClient } from 'kucoin-api';
// normally you should install this module via npm: `npm install kucoin-api`
⋮----
async function start()
⋮----
// Optional: inject a custom logger to override internal logging behaviour
// const logger: typeof DefaultLogger = {
// ...DefaultLogger,
// trace: (...params) => {
// if (
// [
// 'Sending ping',
// // 'Sending upstream ws message: ',
// 'Received pong',
// ].includes(params[0])
// ) {
// return;
// }
// console.log('trace', JSON.stringify(params, null, 2));
// },
// };
⋮----
passphrase: process.env.API_PASSPHRASE || 'apiPassPhraseHere', // This is NOT your account password
⋮----
// logger,
⋮----
// Data received
⋮----
// Something happened, attempting to reconenct
⋮----
// Reconnect successful
⋮----
// Connection closed. If unexpected, expect reconnect -> reconnected.
⋮----
// Reply to a request, e.g. "subscribe"/"unsubscribe"/"authenticate"
⋮----
// throw new Error('res?');
⋮----
// Optional: await a connection to be ready before subscribing (this is not necessary)
// await client.connect('spotPrivateV1');
// console.log('connected');
⋮----
/**
* For more detailed usage info, refer to the ws-spot-public.ts example.
*
* Below are some examples for subscribing to private spot & margin websockets.
* Note: all "private" websocket topics should use the "spotPrivateV1" wsKey.
*/
⋮----
/**
* Other margin websocket topics, which also use the "spotPrivateV1" WsKey:
*/
================
File: examples/ws-spot-public.ts
================
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
DefaultLogger,
WebsocketClient,
WsTopicRequest,
} from '../src/index.js';
// import { DefaultLogger, WebsocketClient, WsTopicRequest } from 'kucoin-api';
// normally you should install this module via npm: `npm install kucoin-api`
⋮----
async function start()
⋮----
// Optional: fully customise the logging experience by injecting a custom logger
// const logger: typeof DefaultLogger = {
// ...DefaultLogger,
// trace: (...params) => {
// if (
// [
// 'Sending ping',
// 'Sending upstream ws message: ',
// 'Received pong',
// ].includes(params[0])
// ) {
// return;
// }
// console.log('trace', params);
// },
// };
⋮----
// const client = new WebsocketClient({}, logger);
⋮----
// Data received
⋮----
// Something happened, attempting to reconenct
⋮----
// Reconnect successful
⋮----
// Connection closed. If unexpected, expect reconnect -> reconnected.
⋮----
// Reply to a request, e.g. "subscribe"/"unsubscribe"/"authenticate"
⋮----
// throw new Error('res?');
⋮----
// Optional: await a connection to be ready before subscribing (this is not necessary)
// await client.connect('spotPublicV1');
⋮----
/**
* Use the client subscribe(topic, market) pattern to subscribe to any websocket topic.
*
* You can subscribe to topics one at a time or many one one request. Topics can be sent as simple strings:
*
*/
⋮----
/**
* Or, as an array of simple strings
*
*/
⋮----
/**
* Or send a more structured object with parameters
*
*/
⋮----
/** Anything in the payload will be merged into the subscribe "request", allowing you to send misc parameters supported by the exchange.
* For more info on parameters, see: https://www.kucoin.com/docs/websocket/basic-info/subscribe/introduction
*/
⋮----
/**
* Or, send an array of structured objects with parameters, if you wanted to send multiple in one request
*
*/
// client.subscribe([subRequest1, subRequest2, etc], 'spotPublicV1');
⋮----
/**
* Other spot websocket topics:
*/
⋮----
/**
* Other margin websocket topics, which also use the "spotPublicV1" WsKey:
*/
================
File: src/lib/websocket/logger.ts
================
export type LogParams = null | any;
⋮----
// eslint-disable-next-line @typescript-eslint/no-unused-vars
⋮----
// console.log(_params);
================
File: src/lib/websocket/WsStore.types.ts
================
import WebSocket from 'isomorphic-ws';
⋮----
export enum WsConnectionStateEnum {
INITIAL = 0,
CONNECTING = 1,
CONNECTED = 2,
CLOSING = 3,
RECONNECTING = 4,
ERROR_RECONNECTING = 5,
// ERROR = 5,
}
⋮----
// ERROR = 5,
⋮----
export interface DeferredPromise {
resolve?: (value: TSuccess) => TSuccess;
reject?: (value: TError) => TError;
promise?: Promise;
}
⋮----
export interface WSConnectedResult {
wsKey: string;
}
⋮----
export interface WsStoredState {
/** The currently active websocket connection */
ws?: WebSocket;
/** The current lifecycle state of the connection (enum) */
connectionState?: WsConnectionStateEnum;
/** A timer that will send an upstream heartbeat (ping) when it expires */
activePingTimer?: ReturnType | undefined;
/** A timer tracking that an upstream heartbeat was sent, expecting a reply before it expires */
activePongTimer?: ReturnType | undefined;
/** If a reconnection is in progress, this will have the timer for the delayed reconnect */
activeReconnectTimer?: ReturnType | undefined;
/**
* When a connection attempt is in progress (even for reconnect), a promise is stored here.
*
* This promise will resolve once connected (and will then get removed);
*/
// connectionInProgressPromise?: DeferredPromise | undefined;
deferredPromiseStore: Record;
/**
* All the topics we are expected to be subscribed to on this connection (and we automatically resubscribe to if the connection drops)
*
* A "Set" and a deep-object-match are used to ensure we only subscribe to a topic once (tracking a list of unique topics we're expected to be connected to)
*/
subscribedTopics: Set;
/** Whether this connection is ready for events (welcome message received after connection) */
isReadyForEvents?: boolean;
/** Whether this connection has completed authentication (only applies to private connections) */
isAuthenticated?: boolean;
/** Whether this connection has completed authentication before for the Websocket API, so it knows to automatically reauth if reconnected */
didAuthWSAPI?: boolean;
/** To reauthenticate on the WS API, which channel do we send to? */
WSAPIAuthChannel?: string;
}
⋮----
/** The currently active websocket connection */
⋮----
/** The current lifecycle state of the connection (enum) */
⋮----
/** A timer that will send an upstream heartbeat (ping) when it expires */
⋮----
/** A timer tracking that an upstream heartbeat was sent, expecting a reply before it expires */
⋮----
/** If a reconnection is in progress, this will have the timer for the delayed reconnect */
⋮----
/**
* When a connection attempt is in progress (even for reconnect), a promise is stored here.
*
* This promise will resolve once connected (and will then get removed);
*/
// connectionInProgressPromise?: DeferredPromise | undefined;
⋮----
/**
* All the topics we are expected to be subscribed to on this connection (and we automatically resubscribe to if the connection drops)
*
* A "Set" and a deep-object-match are used to ensure we only subscribe to a topic once (tracking a list of unique topics we're expected to be connected to)
*/
⋮----
/** Whether this connection is ready for events (welcome message received after connection) */
⋮----
/** Whether this connection has completed authentication (only applies to private connections) */
⋮----
/** Whether this connection has completed authentication before for the Websocket API, so it knows to automatically reauth if reconnected */
⋮----
/** To reauthenticate on the WS API, which channel do we send to? */
================
File: src/lib/misc-util.ts
================
export function neverGuard(x: never, msg: string): Error
================
File: src/lib/webCryptoAPI.ts
================
import { neverGuard } from './misc-util.js';
⋮----
function bufferToB64(buffer: ArrayBuffer): string
⋮----
export type SignEncodeMethod = 'hex' | 'base64';
export type SignAlgorithm = 'SHA-256' | 'SHA-512';
⋮----
/**
* Similar to node crypto's `createHash()` function
*/
export async function hashMessage(
message: string,
method: SignEncodeMethod,
algorithm: SignAlgorithm,
): Promise
⋮----
/**
* Sign a message, with a secret, using the Web Crypto API
*/
export async function signMessage(
message: string,
secret: string,
method: SignEncodeMethod,
algorithm: SignAlgorithm,
): Promise
⋮----
export function checkWebCryptoAPISupported()
================
File: src/types/request/spot-margin-trading.ts
================
/**
*
***********
* Margin Trading
***********
*
*/
⋮----
/**
*
* Margin HF trade
*
*/
⋮----
export interface SubmitHFMarginOrderRequest {
clientOid: string;
side: 'buy' | 'sell';
symbol: string;
type?: 'limit' | 'market';
stp?: 'CN' | 'CO' | 'CB' | 'DC';
isIsolated?: boolean;
autoBorrow?: boolean;
autoRepay?: boolean;
price?: string;
size?: string;
timeInForce?: 'GTC' | 'GTT' | 'IOC' | 'FOK';
cancelAfter?: number;
postOnly?: boolean;
hidden?: boolean;
iceberg?: boolean;
visibleSize?: string;
funds?: string;
}
⋮----
export interface HFMarginRequestOrder {
symbol: string;
tradeType: 'MARGIN_TRADE' | 'MARGIN_ISOLATED_TRADE';
}
⋮----
export interface GetHFMarginFilledRequest {
symbol: string;
tradeType: 'MARGIN_TRADE' | 'MARGIN_ISOLATED_TRADE';
side?: 'buy' | 'sell';
type?: 'limit' | 'market';
startAt?: number;
endAt?: number;
lastId?: number;
limit?: number;
}
⋮----
export interface getHFMarginFillsRequest {
orderId?: string;
symbol: string;
tradeType: 'MARGIN_TRADE' | 'MARGIN_ISOLATED_TRADE';
side?: 'buy' | 'sell';
type?: 'limit' | 'market';
startAt?: number;
endAt?: number;
lastId?: number;
limit?: number;
}
⋮----
/**
*
* Orders
*
*/
⋮----
export interface SubmitMarginOrderRequest {
clientOid: string;
side: 'buy' | 'sell';
symbol: string;
type?: 'limit' | 'market';
remark?: string;
stp?: 'CN' | 'CO' | 'CB' | 'DC';
marginModel?: 'cross' | 'isolated';
autoBorrow?: boolean;
autoRepay?: boolean;
price: string;
size?: string;
timeInForce?: 'GTC' | 'GTT' | 'IOC' | 'FOK';
cancelAfter?: number;
postOnly?: boolean;
hidden?: boolean;
iceberg?: boolean;
visibleSize?: string;
funds?: string;
}
⋮----
/**
*
* Margin info
*
*/
⋮----
export interface MarginRiskLimitRequest {
isIsolated: boolean;
symbol?: string;
currency?: string;
}
⋮----
/**
*
* Isolated Margin
*
*/
⋮----
/**
*
* Margin trading(v3)
*
*/
⋮----
export interface MarginBorrowV3Request {
isIsolated?: boolean;
symbol?: string;
currency: string;
size: number;
timeInForce: 'IOC' | 'FOK';
isHf: boolean;
}
⋮----
export interface MarginRepayV3Request {
isIsolated?: boolean;
symbol?: string;
currency: string;
size: number;
isHf: boolean;
}
⋮----
export interface MarginHistoryV3Request {
currency: string;
isIsolated?: boolean;
symbol?: string;
orderNo?: string;
startTime?: number;
endTime?: number;
currentPage?: number;
pageSize?: number;
}
⋮----
export interface MarginInterestRecordsRequest {
isIsolated?: boolean;
symbol?: string;
currency?: string;
startTime?: number;
endTime?: number;
currentPage?: number;
pageSize?: number;
}
⋮----
/**
*
* Lending market(v3)
*
*/
⋮----
export interface InitiateLendingSubscriptionV3Request {
currency: string;
size: string;
interestRate: string;
}
⋮----
export interface InitiateLendingRedemptionV3Request {
currency: string;
size: string;
purchaseOrderNo: string;
}
⋮----
export interface ModifyLendingSubscriptionOrdersV3Request {
currency: string;
purchaseOrderNo: string;
interestRate: string;
}
⋮----
export interface GetLendingRedemptionOrdersV3Request {
currency: string;
redeemOrderNo?: string;
status: 'DONE' | 'PENDING';
currentPage?: number;
pageSize?: number;
}
⋮----
export interface GetLendingSubscriptionOrdersV3Request {
currency: string;
purchaseOrderNo?: string;
status: 'DONE' | 'PENDING';
currentPage?: number;
pageSize?: number;
}
================
File: src/types/request/spot-misc.ts
================
export interface GetAnnouncementsRequest {
currentPage?: number;
pageSize?: number;
annType?: string;
lang?: string;
startTime?: number;
endTime?: number;
}
================
File: src/types/response/shared.types.ts
================
export interface APISuccessResponse {
code: '200000';
data: TData;
}
⋮----
export interface APIErrorResponse {
msg: string;
code: string;
}
⋮----
export type APIResponse = APISuccessResponse | APIErrorResponse;
⋮----
export interface ServiceStatus {
msg: string;
status: 'cancelonly' | 'close' | 'open';
}
================
File: src/types/response/ws.ts
================
export interface WsServerInfo {
endpoint: string;
encrypt: boolean;
protocol: string;
pingInterval: number;
pingTimeout: number;
}
⋮----
export interface WsConnectionInfo {
token: string;
instanceServers: WsServerInfo[];
}
================
File: src/types/websockets/events.ts
================
export interface WsDataEvent {
data: TData;
table: string;
wsKey: TWSKey;
}
================
File: src/types/websockets/requests.ts
================
export type WsOperation =
| 'subscribe'
| 'unsubscribe'
| 'login'
| 'access'
| 'request';
⋮----
export interface WsRequestOperation {
id: number;
type: WsOperation;
topic: TWSTopic;
privateChannel: boolean;
response: boolean;
}
================
File: src/types/websockets/wsAPI.ts
================
export interface WsAPIWsKeyTopicMap {
[k: string]: never;
}
⋮----
export interface WsAPITopicRequestParamMap {
[k: string]: never;
}
⋮----
export interface WsAPITopicResponseMap {
[k: string]: never;
}
================
File: .prettierrc
================
{
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "all"
}
================
File: jest.config.ts
================
/**
* For a detailed explanation regarding each configuration property, visit:
* https://jestjs.io/docs/configuration
*/
⋮----
import type { Config } from 'jest';
⋮----
// All imported modules in your tests should be mocked automatically
// automock: false,
⋮----
// Stop running tests after `n` failures
// bail: 0,
bail: false, // enable to stop test when an error occur,
⋮----
// The directory where Jest should store its cached dependency information
// cacheDirectory: "/private/var/folders/kf/2k3sz4px6c9cbyzj1h_b192h0000gn/T/jest_dx",
⋮----
// Automatically clear mock calls, instances, contexts and results before every test
⋮----
// Indicates whether the coverage information should be collected while executing the test
⋮----
// An array of glob patterns indicating a set of files for which coverage information should be collected
⋮----
// The directory where Jest should output its coverage files
⋮----
// An array of regexp pattern strings used to skip coverage collection
// coveragePathIgnorePatterns: [
// "/node_modules/"
// ],
⋮----
// Indicates which provider should be used to instrument code for coverage
⋮----
// A list of reporter names that Jest uses when writing coverage reports
// coverageReporters: [
// "json",
// "text",
// "lcov",
// "clover"
// ],
⋮----
// An object that configures minimum threshold enforcement for coverage results
// coverageThreshold: undefined,
⋮----
// A path to a custom dependency extractor
// dependencyExtractor: undefined,
⋮----
// Make calling deprecated APIs throw helpful error messages
// errorOnDeprecated: false,
⋮----
// The default configuration for fake timers
// fakeTimers: {
// "enableGlobally": false
// },
⋮----
// Force coverage collection from ignored files using an array of glob patterns
// forceCoverageMatch: [],
⋮----
// A path to a module which exports an async function that is triggered once before all test suites
// globalSetup: undefined,
⋮----
// A path to a module which exports an async function that is triggered once after all test suites
// globalTeardown: undefined,
⋮----
// A set of global variables that need to be available in all test environments
// globals: {},
⋮----
// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
// maxWorkers: "50%",
⋮----
// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
// "node_modules"
// ],
⋮----
// An array of file extensions your modules use
⋮----
// modulePaths: ['src'],
⋮----
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
// moduleNameMapper: {},
⋮----
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],
⋮----
// Activates notifications for test results
// notify: false,
⋮----
// An enum that specifies notification mode. Requires { notify: true }
// notifyMode: "failure-change",
⋮----
// A preset that is used as a base for Jest's configuration
// preset: undefined,
⋮----
// Run tests from one or more projects
// projects: undefined,
⋮----
// Use this configuration option to add custom reporters to Jest
// reporters: undefined,
⋮----
// Automatically reset mock state before every test
// resetMocks: false,
⋮----
// Reset the module registry before running each individual test
// resetModules: false,
⋮----
// A path to a custom resolver
// resolver: undefined,
⋮----
// Automatically restore mock state and implementation before every test
// restoreMocks: false,
⋮----
// The root directory that Jest should scan for tests and modules within
// rootDir: undefined,
⋮----
// A list of paths to directories that Jest should use to search for files in
// roots: [
// ""
// ],
⋮----
// Allows you to use a custom runner instead of Jest's default test runner
// runner: "jest-runner",
⋮----
// The paths to modules that run some code to configure or set up the testing environment before each test
// setupFiles: [],
⋮----
// A list of paths to modules that run some code to configure or set up the testing framework before each test
// setupFilesAfterEnv: [],
⋮----
// The number of seconds after which a test is considered as slow and reported as such in the results.
// slowTestThreshold: 5,
⋮----
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
// snapshotSerializers: [],
⋮----
// The test environment that will be used for testing
// testEnvironment: "jest-environment-node",
⋮----
// Options that will be passed to the testEnvironment
// testEnvironmentOptions: {},
⋮----
// Adds a location field to test results
// testLocationInResults: false,
⋮----
// The glob patterns Jest uses to detect test files
⋮----
// "**/__tests__/**/*.[jt]s?(x)",
⋮----
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
// testPathIgnorePatterns: [
// "/node_modules/"
// ],
⋮----
// The regexp pattern or array of patterns that Jest uses to detect test files
// testRegex: [],
⋮----
// This option allows the use of a custom results processor
// testResultsProcessor: undefined,
⋮----
// This option allows use of a custom test runner
// testRunner: "jest-circus/runner",
⋮----
// A map from regular expressions to paths to transformers
// transform: undefined,
⋮----
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
// transformIgnorePatterns: [
// "/node_modules/",
// "\\.pnp\\.[^\\/]+$"
// ],
⋮----
// Prevents import esm module error from v1 axios release, issue #5026
⋮----
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined,
⋮----
// Indicates whether each individual test should be reported during the run
// verbose: undefined,
verbose: true, // report individual test
⋮----
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
// watchPathIgnorePatterns: [],
⋮----
// Whether to use watchman for file crawling
// watchman: true,
================
File: postBuild.sh
================
#!/bin/bash
#
# Add package.json files to cjs/mjs subtrees
#
cat >dist/cjs/package.json <dist/mjs/package.json < {
topic: TWSTopic;
payload?: TWSPayload;
}
⋮----
/**
* Conveniently allow users to request a topic either as string topics or objects (containing string topic + params)
*/
export type WsTopicRequestOrStringTopic<
TWSTopic extends string,
TWSPayload = any,
> = WsTopicRequest | string;
⋮----
export interface MessageEventLike {
target: WebSocket;
type: 'message';
data: string;
}
⋮----
export function isMessageEvent(msg: unknown): msg is MessageEventLike
⋮----
/**
* #305: ws.terminate() is undefined in browsers.
* This only works in node.js, not in browsers.
* Does nothing if `ws` is undefined. Does nothing in browsers.
*/
export function safeTerminateWs(
ws?: WebSocket | any,
fallbackToClose?: boolean,
): boolean
================
File: src/lib/websocket/WsStore.ts
================
import WebSocket from 'isomorphic-ws';
⋮----
import { DefaultLogger } from './logger.js';
import {
DeferredPromise,
WSConnectedResult,
WsConnectionStateEnum,
WsStoredState,
} from './WsStore.types.js';
⋮----
/**
* Simple comparison of two objects, only checks 1-level deep (nested objects won't match)
*/
export function isDeepObjectMatch(object1: unknown, object2: unknown): boolean
⋮----
type DeferredPromiseRef =
(typeof DEFERRED_PROMISE_REF)[keyof typeof DEFERRED_PROMISE_REF];
⋮----
export class WsStore<
WsKey extends string,
⋮----
constructor(logger: typeof DefaultLogger)
⋮----
/** 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
⋮----
getKeys(): WsKey[]
⋮----
create(key: WsKey): WsStoredState | undefined
⋮----
delete(key: WsKey): void
⋮----
// TODO: should we allow this at all? Perhaps block this from happening...
⋮----
/* connection websocket */
⋮----
hasExistingActiveConnection(key: WsKey): boolean
⋮----
getWs(key: WsKey): WebSocket | undefined
⋮----
setWs(key: WsKey, wsConnection: WebSocket): WebSocket
⋮----
getDeferredPromise(
wsKey: WsKey,
promiseRef: string | DeferredPromiseRef,
): DeferredPromise | undefined
⋮----
createDeferredPromise(
wsKey: WsKey,
promiseRef: string | DeferredPromiseRef,
throwIfExists: boolean,
): DeferredPromise
⋮----
// console.log('existing promise');
⋮----
// console.log('create promise');
⋮----
// TODO: Once stable, use Promise.withResolvers in future
⋮----
resolveDeferredPromise(
wsKey: WsKey,
promiseRef: string | DeferredPromiseRef,
value: unknown,
removeAfter: boolean,
): void
⋮----
rejectDeferredPromise(
wsKey: WsKey,
promiseRef: string | DeferredPromiseRef,
value: unknown,
removeAfter: boolean,
): void
⋮----
removeDeferredPromise(
wsKey: WsKey,
promiseRef: string | DeferredPromiseRef,
): void
⋮----
// Just in case it's pending
⋮----
rejectAllDeferredPromises(wsKey: WsKey, reason: string): void
⋮----
// Skip reserved keys, such as the connection promise
⋮----
/** Get promise designed to track a connection attempt in progress. Resolves once connected. */
getConnectionInProgressPromise(
wsKey: WsKey,
): DeferredPromise | undefined
⋮----
/**
* Create a deferred promise designed to track a connection attempt in progress.
*
* Will throw if existing promise is found.
*/
createConnectionInProgressPromise(
wsKey: WsKey,
throwIfExists: boolean,
): DeferredPromise
⋮----
/** Remove promise designed to track a connection attempt in progress */
removeConnectingInProgressPromise(wsKey: WsKey): void
⋮----
/* connection state */
⋮----
isWsOpen(key: WsKey): boolean
⋮----
getConnectionState(key: WsKey): WsConnectionStateEnum
⋮----
setConnectionState(key: WsKey, state: WsConnectionStateEnum)
⋮----
// console.log(new Date(), `setConnectionState(${key}, ${state})`);
⋮----
isConnectionState(key: WsKey, state: WsConnectionStateEnum): boolean
⋮----
/**
* Check if we're currently in the process of opening a connection for any reason. Safer than only checking "CONNECTING" as the state
* @param key
* @returns
*/
isConnectionAttemptInProgress(key: WsKey): boolean
⋮----
/* subscribed topics */
⋮----
getTopics(key: WsKey): Set
⋮----
getTopicsByKey(): Record>
⋮----
// Since topics are objects we can't rely on the set to detect duplicates
/**
* Find matching "topic" request from the store
* @param key
* @param topic
* @returns
*/
getMatchingTopic(key: WsKey, topic: TWSTopicSubscribeEventArgs)
⋮----
// if (typeof topic === 'string') {
// return this.getMatchingTopic(key, { channel: topic });
// }
⋮----
addTopic(key: WsKey, topic: TWSTopicSubscribeEventArgs)
⋮----
// console.log(`wsStore.addTopic(${key}, ${topic})`);
// Check for duplicate topic. If already tracked, don't store this one
⋮----
deleteTopic(key: WsKey, topic: TWSTopicSubscribeEventArgs)
⋮----
// Check if we're subscribed to a topic like this
================
File: src/types/request/broker.types.ts
================
export interface GetBrokerInfoRequest {
begin: string;
end: string;
tradeType: '1' | '2';
}
⋮----
export interface GetBrokerSubAccountsRequest {
uid: string;
currentPage?: number;
pageSize?: number;
}
⋮----
export type BrokerSubAccountPermission = 'general' | 'spot' | 'futures';
⋮----
export interface CreateBrokerSubAccountApiRequest {
uid: string;
passphrase: string;
ipWhitelist: string[];
permissions: BrokerSubAccountPermission[];
label: string;
}
⋮----
export interface GetBrokerSubAccountApisRequest {
uid: string;
apiKey?: string;
}
⋮----
export interface UpdateBrokerSubAccountApiRequest {
uid: string;
apiKey: string;
ipWhitelist: string[];
permissions: BrokerSubAccountPermission[];
label: string;
}
⋮----
export interface DeleteBrokerSubAccountApiRequest {
uid: string;
apiKey: string;
}
⋮----
export type BrokerTransferDirection = 'OUT' | 'IN';
export type BrokerAccountType = 'MAIN' | 'TRADE';
⋮----
export interface BrokerTransferRequest {
currency: string;
amount: string;
clientOid: string;
direction: BrokerTransferDirection;
accountType: BrokerAccountType;
specialUid: string;
specialAccountType: BrokerAccountType;
}
⋮----
export interface GetBrokerDepositListRequest {
currency?: string;
status?: 'PROCESSING' | 'SUCCESS' | 'FAILURE';
hash?: string;
startTimestamp?: number;
endTimestamp?: number;
limit?: number;
}
================
File: src/types/request/spot-affiliate.ts
================
export interface GetAffiliateTradeHistoryRequest {
uid: string; // required - Invitee's UID
tradeType?: 'SPOT' | 'FEATURE'; // optional - Trading type
tradeStartAt?: number; // optional - Trade start time (13-digit timestamp)
tradeEndAt?: number; // optional - Trade end time (13-digit timestamp)
page?: number; // optional - Page number >= 1, default: 1
pageSize?: number; // optional - Page size >= 1, <= 500, default: 10
}
⋮----
uid: string; // required - Invitee's UID
tradeType?: 'SPOT' | 'FEATURE'; // optional - Trading type
tradeStartAt?: number; // optional - Trade start time (13-digit timestamp)
tradeEndAt?: number; // optional - Trade end time (13-digit timestamp)
page?: number; // optional - Page number >= 1, default: 1
pageSize?: number; // optional - Page size >= 1, <= 500, default: 10
⋮----
export interface GetAffiliateCommissionRequest {
siteType?: 'all'; // optional - The source site of the commission, default: "all"
rebateType?: 0 | 1 | 2; // optional - Rebate type, default: 0
rebateStartAt?: number; // optional - Start time for commission issuance (13-digit timestamp)
rebateEndAt?: number; // optional - End time for commission issuance (13-digit timestamp)
page?: number; // optional - Page number >= 1, default: 1
pageSize?: number; // optional - Page size >= 1, <= 500, default: 10
}
⋮----
siteType?: 'all'; // optional - The source site of the commission, default: "all"
rebateType?: 0 | 1 | 2; // optional - Rebate type, default: 0
rebateStartAt?: number; // optional - Start time for commission issuance (13-digit timestamp)
rebateEndAt?: number; // optional - End time for commission issuance (13-digit timestamp)
page?: number; // optional - Page number >= 1, default: 1
pageSize?: number; // optional - Page size >= 1, <= 500, default: 10
⋮----
export interface GetAffiliateInviteesRequest {
userType?: '1' | '2' | '3'; // optional - User Type
referralCode?: string; // optional - Which referral code the user registered with
uid?: string; // optional - UID(s) of the users, can pass multiple separated by commas
registrationStartAt?: number; // optional - Registration start timestamp
registrationEndAt?: number; // optional - Registration end timestamp
page?: number; // optional - Page number >= 1, default: 1
pageSize?: number; // optional - Max number of records per page >= 1, <= 500, default: 10
}
⋮----
userType?: '1' | '2' | '3'; // optional - User Type
referralCode?: string; // optional - Which referral code the user registered with
uid?: string; // optional - UID(s) of the users, can pass multiple separated by commas
registrationStartAt?: number; // optional - Registration start timestamp
registrationEndAt?: number; // optional - Registration end timestamp
page?: number; // optional - Page number >= 1, default: 1
pageSize?: number; // optional - Max number of records per page >= 1, <= 500, default: 10
================
File: src/types/request/spot-convert.ts
================
/**
*
***********
* Spot Convert
***********
*
*/
⋮----
/**
* Get Convert Symbol
*/
export interface GetConvertSymbolRequest {
fromCurrency: string;
toCurrency: string;
orderType?: 'MARKET' | 'LIMIT';
}
⋮----
/**
* Add Convert Order
*/
export interface AddConvertOrderRequest {
clientOrderId: string;
quoteId: string;
accountType?: 'BOTH' | 'FUNDING' | 'TRADING';
}
⋮----
/**
* Get Convert Quote
*/
export interface GetConvertQuoteRequest {
fromCurrency: string;
toCurrency: string;
fromCurrencySize?: number;
toCurrencySize?: number;
}
⋮----
/**
* Get Convert Order Detail
*/
export interface GetConvertOrderDetailRequest {
clientOrderId?: string;
orderId?: string;
}
⋮----
/**
* Get Convert Order History
*/
export interface GetConvertOrderHistoryRequest {
startAt?: number;
endAt?: number;
page?: number;
pageSize?: number;
status?: 'OPEN' | 'SUCCESS' | 'FAIL';
}
⋮----
/**
* Add Convert Limit Order
*/
export interface AddConvertLimitOrderRequest {
clientOrderId: string;
fromCurrency: string;
toCurrency: string;
fromCurrencySize: number;
toCurrencySize: number;
accountType?: 'BOTH' | 'FUNDING' | 'TRADING';
}
⋮----
/**
* Get Convert Limit Quote
*/
export interface GetConvertLimitQuoteRequest {
fromCurrency: string;
toCurrency: string;
fromCurrencySize?: number;
toCurrencySize?: number;
}
⋮----
/**
* Get Convert Limit Order Detail
*/
export interface GetConvertLimitOrderDetailRequest {
clientOrderId?: string;
orderId?: string;
}
⋮----
/**
* Get Convert Limit Orders
*/
export interface GetConvertLimitOrdersRequest {
startAt?: number;
endAt?: number;
page?: number;
pageSize?: number;
status?: 'OPEN' | 'SUCCESS' | 'FAIL' | 'CANCELLED';
}
⋮----
/**
* Cancel Convert Limit Order
*/
export interface CancelConvertLimitOrderRequest {
clientOrderId?: string;
orderId?: string;
}
================
File: src/types/request/spot-earn.ts
================
/**
*
* EARN
*
*/
⋮----
export interface SubscribeEarnFixedIncomeRequest {
productId: string;
amount: string;
accountType: 'MAIN' | 'TRADE';
}
⋮----
export interface InitiateRedemptionRequest {
orderId: string;
amount: string;
fromAccountType?: 'MAIN' | 'TRADE';
confirmPunishRedeem?: '1';
}
⋮----
export interface GetEarnRedeemPreviewRequest {
orderId: string;
fromAccountType?: 'MAIN' | 'TRADE';
}
⋮----
export interface GetEarnFixedIncomeHoldAssetsRequest {
currentPage?: number;
pageSize?: number;
productId?: string;
productCategory?: string;
currency?: string;
}
⋮----
/**
*
* STRUCTURED EARN - DUAL
*
*/
⋮----
export interface StructuredProductPurchaseRequest {
productId: string; // required - Product ID
investCurrency: string; // required - Investment currency
investAmount: string; // required - Subscription amount
accountType: 'MAIN' | 'TRADE'; // required - MAIN (funding account), TRADE (spot trading account)
}
⋮----
productId: string; // required - Product ID
investCurrency: string; // required - Investment currency
investAmount: string; // required - Subscription amount
accountType: 'MAIN' | 'TRADE'; // required - MAIN (funding account), TRADE (spot trading account)
⋮----
export interface GetDualInvestmentProductsRequest {
category: 'DUAL_CLASSIC' | 'DUAL_BOOSTER' | 'DUAL_EXTRA'; // required - Product category
strikeCurrency?: string; // optional - Strike Currency
investCurrency?: string; // optional - Investment Currency
side?: 'CALL' | 'PUT'; // optional - Direction
}
⋮----
category: 'DUAL_CLASSIC' | 'DUAL_BOOSTER' | 'DUAL_EXTRA'; // required - Product category
strikeCurrency?: string; // optional - Strike Currency
investCurrency?: string; // optional - Investment Currency
side?: 'CALL' | 'PUT'; // optional - Direction
⋮----
export interface GetStructuredProductOrdersRequest {
categories: string; // required - Product categories, multiple categories are supported, e.g. DUAL_CLASSIC, DUAL_BOOSTER, DUAL_EXTRA
orderId?: string; // optional - Order Id
investCurrency?: string; // optional - Investment Currency
currentPage?: number; // optional - Current Page, default: 1
pageSize?: number; // optional - Page Size >= 10, <= 500, default: 15
}
⋮----
categories: string; // required - Product categories, multiple categories are supported, e.g. DUAL_CLASSIC, DUAL_BOOSTER, DUAL_EXTRA
orderId?: string; // optional - Order Id
investCurrency?: string; // optional - Investment Currency
currentPage?: number; // optional - Current Page, default: 1
pageSize?: number; // optional - Page Size >= 10, <= 500, default: 15
================
File: src/types/response/broker.types.ts
================
export interface BrokerInfo {
accountSize: number;
maxAccountSize: number | null;
level: number;
}
⋮----
export interface CreateBrokerSubAccountResponse {
accountName: string;
uid: string;
createdAt: number;
level: number;
}
⋮----
export interface BrokerSubAccount {
accountName: string;
uid: string;
createdAt: number;
level: number;
}
⋮----
export interface GetBrokerSubAccountsResponse {
currentPage: number;
pageSize: number;
totalNum: number;
totalPage: number;
items: BrokerSubAccount[];
}
⋮----
export interface CreateBrokerSubAccountApiResponse {
uid: string;
label: string;
apiKey: string;
secretKey: string;
apiVersion: number;
permissions: string[];
ipWhitelist: string[];
createdAt: number;
}
⋮----
export interface BrokerSubAccountApi {
uid: string;
label: string;
apiKey: string;
apiVersion: number;
permissions: ('General' | 'Spot' | 'Futures')[];
ipWhitelist: string[];
createdAt: number;
}
⋮----
export type BrokerTransferAccountType =
| 'MAIN'
| 'TRADE'
| 'CONTRACT'
| 'MARGIN'
| 'ISOLATED';
export type BrokerTransferStatus = 'PROCESSING' | 'SUCCESS' | 'FAILURE';
⋮----
export interface BrokerTransferHistory {
orderId: string;
currency: string;
amount: string;
fromUid: number;
fromAccountType: BrokerTransferAccountType;
fromAccountTag: string;
toUid: number;
toAccountType: BrokerTransferAccountType;
toAccountTag: string;
status: BrokerTransferStatus;
reason: string | null;
createdAt: number;
}
⋮----
export interface BrokerDepositRecord {
uid: number;
hash: string;
address: string;
memo: string;
amount: string;
fee: string;
currency: string;
isInner: boolean;
walletTxId: string;
status: BrokerTransferStatus;
remark: string;
chain: string;
createdAt: number;
updatedAt: number;
}
⋮----
export type BrokerWithdrawalStatus =
| 'PROCESSING'
| 'WALLET_PROCESSING'
| 'REVIEW'
| 'SUCCESS'
| 'FAILURE';
⋮----
export interface BrokerWithdrawalRecord {
id: string;
chain: string;
walletTxId: string;
uid: number;
amount: string;
memo: string;
fee: string;
address: string;
remark: string;
isInner: boolean;
currency: string;
status: BrokerWithdrawalStatus;
createdAt: number;
updatedAt: number;
}
================
File: src/types/response/spot-affiliate.ts
================
export interface AffiliateTradeHistoryItem {
tradeTime: number; // Trade time (13-digit timestamp)
tradeType: string; // Trading type (e.g., "SPOT")
tradeCurrency: string; // Trade currency
tradeAmount: string; // Trade amount
tradeAmountU: string; // Trade amount in USDT
feeU: string; // Fee in USDT
commission: string; // Commission
currency: string; // Currency (e.g., "USDT")
}
⋮----
tradeTime: number; // Trade time (13-digit timestamp)
tradeType: string; // Trading type (e.g., "SPOT")
tradeCurrency: string; // Trade currency
tradeAmount: string; // Trade amount
tradeAmountU: string; // Trade amount in USDT
feeU: string; // Fee in USDT
commission: string; // Commission
currency: string; // Currency (e.g., "USDT")
⋮----
export interface AffiliateTradeHistory {
currentPage: number; // Current page number
pageSize: number; // Page size
totalNum: number; // Total number of records
totalPage: number; // Total number of pages
items: AffiliateTradeHistoryItem[]; // Array of trade history items
}
⋮----
currentPage: number; // Current page number
pageSize: number; // Page size
totalNum: number; // Total number of records
totalPage: number; // Total number of pages
items: AffiliateTradeHistoryItem[]; // Array of trade history items
⋮----
export interface AffiliateCommissionItem {
siteType: string; // Source site of the commission
rebateType: 1 | 2; // Rebate type
payoutTime: number; // Commission payout time (T+1 settlement), 13-digit timestamp (UTC+8)
periodStartTime: number; // Start time of commission calculation period, 13-digit timestamp
periodEndTime: number; // End time of commission calculation period, 13-digit timestamp
status: 1 | 2 | 3 | 4; // Payout status
takerVolume: string; // Invitee's taker trading volume
makerVolume: string; // Invitee's maker trading volume
commission: string; // Total rebate contributed by the invitee
currency: string; // Denomination unit for trading volume/amount (USDT or USDC)
}
⋮----
siteType: string; // Source site of the commission
rebateType: 1 | 2; // Rebate type
payoutTime: number; // Commission payout time (T+1 settlement), 13-digit timestamp (UTC+8)
periodStartTime: number; // Start time of commission calculation period, 13-digit timestamp
periodEndTime: number; // End time of commission calculation period, 13-digit timestamp
status: 1 | 2 | 3 | 4; // Payout status
takerVolume: string; // Invitee's taker trading volume
makerVolume: string; // Invitee's maker trading volume
commission: string; // Total rebate contributed by the invitee
currency: string; // Denomination unit for trading volume/amount (USDT or USDC)
⋮----
export interface AffiliateInviteeItem {
uid: string; // UID of the invitee
nickName: string; // Nickname (partially hidden)
referralCode: string; // Referral code used for registration
country: string; // Country
registrationTime: number; // Registration time (13-digit timestamp)
completedKyc: boolean; // Whether KYC is completed
completedFirstDeposit: boolean; // Whether first deposit is completed
completedFirstTrade: boolean; // Whether first trade is completed
past7dFees: string; // Fees in the past 7 days
past7dCommission: string; // Commission in the past 7 days
totalCommission: string; // Total commission
myCommissionRate: string; // My commission rate (percentage)
cashbackRate: string; // Cashback rate (percentage)
currency: string; // Currency (e.g., "USDT")
}
⋮----
uid: string; // UID of the invitee
nickName: string; // Nickname (partially hidden)
referralCode: string; // Referral code used for registration
country: string; // Country
registrationTime: number; // Registration time (13-digit timestamp)
completedKyc: boolean; // Whether KYC is completed
completedFirstDeposit: boolean; // Whether first deposit is completed
completedFirstTrade: boolean; // Whether first trade is completed
past7dFees: string; // Fees in the past 7 days
past7dCommission: string; // Commission in the past 7 days
totalCommission: string; // Total commission
myCommissionRate: string; // My commission rate (percentage)
cashbackRate: string; // Cashback rate (percentage)
currency: string; // Currency (e.g., "USDT")
⋮----
export interface AffiliateInvitees {
currentPage: number; // Current page number
pageSize: number; // Page size
totalNum: number; // Total number of records
totalPage: number; // Total number of pages
items: AffiliateInviteeItem[]; // Array of invited user items
}
⋮----
currentPage: number; // Current page number
pageSize: number; // Page size
totalNum: number; // Total number of records
totalPage: number; // Total number of pages
items: AffiliateInviteeItem[]; // Array of invited user items
================
File: src/types/response/spot-convert.ts
================
/**
*
***********
* Spot Convert
***********
*
*/
⋮----
/**
* Get Convert Symbol Response
*/
export interface ConvertSymbol {
fromCurrency: string;
toCurrency: string;
fromCurrencyMaxSize: string;
fromCurrencyMinSize: string;
fromCurrencyStep: string;
toCurrencyMaxSize: string;
toCurrencyMinSize: string;
toCurrencyStep: string;
}
⋮----
/**
* Convert Currency Info
*/
export interface ConvertCurrency {
currency: string;
maxSize: string;
minSize: string;
step: string;
tradeDirection: string;
}
⋮----
/**
* USDT Currency Limit Info
*/
export interface UsdtCurrencyLimit {
currency: string;
maxSize: string;
minSize: string;
step: string;
}
⋮----
/**
* Get Convert Currencies Response
*/
export interface ConvertCurrencies {
currencies: ConvertCurrency[];
usdtCurrencyLimit: UsdtCurrencyLimit[];
}
⋮----
/**
* Add Convert Order Response
*/
export interface SubmitConvertOrderResponse {
orderId: string;
clientOrderId: string;
}
⋮----
/**
* Get Convert Quote Response
*/
export interface ConvertQuote {
quoteId: string;
price: string;
fromCurrencySize: string;
toCurrencySize: string;
validUntill: number;
}
⋮----
/**
* Convert Order Detail
*/
export interface ConvertOrder {
orderId: number;
clientOrderId: string;
status: 'OPEN' | 'SUCCESS' | 'FAIL';
fromCurrency: string;
toCurrency: string;
fromCurrencySize: string;
toCurrencySize: string;
accountType: 'BOTH' | 'FUNDING' | 'TRADING';
price: string;
orderTime: number;
}
⋮----
/**
* Get Convert Order History Response
*/
export interface ConvertOrderHistory {
currentPage: number;
pageSize: number;
totalNum: number;
totalPage: number;
items: ConvertOrder[];
}
⋮----
/**
* Add Convert Limit Order Response
*/
export interface SumbitConvertLimitResp {
orderId: string;
clientOrderId: string;
}
⋮----
/**
* Get Convert Limit Quote Response
*/
export interface ConvertLimitQuote {
price: string;
validUntill: number;
}
⋮----
/**
* Convert Limit Order Detail
*/
export interface ConvertLimitOrder {
orderId: string;
clientOrderId: string;
status: 'OPEN' | 'SUCCESS' | 'FAIL' | 'CANCELLED';
fromCurrency: string;
toCurrency: string;
fromCurrencySize: string;
toCurrencySize: string;
accountType: string;
price: string;
orderTime: number;
expiryTime: number;
cancelTime?: number;
filledTime?: number;
cancelType?: number;
}
⋮----
/**
* Get Convert Limit Orders Response
*/
export interface ConvertLimitOrdersList {
currentPage: number;
pageSize: number;
totalNum: number;
totalPage: number;
items: ConvertLimitOrder[];
}
================
File: src/types/response/spot-earn.ts
================
/**
*
* EARN
*
*/
⋮----
export interface SubscribeEarnFixedIncomeResponse {
orderId: string;
orderTxId: string;
}
⋮----
export interface InitiateRedemptionResponse {
orderTxId: string;
deliverTime: number;
status: 'SUCCESS' | 'PENDING';
amount: string;
}
⋮----
export interface GetEarnRedeemPreviewResponse {
currency: string;
redeemAmount: string;
penaltyInterestAmount: string;
redeemPeriod: number;
deliverTime: number;
manualRedeemable: boolean;
redeemAll: boolean;
}
⋮----
export interface EarnFixedIncomeHoldAsset {
orderId: string;
productId: string;
productCategory: string;
productType: string;
currency: string;
incomeCurrency: string;
returnRate: string;
holdAmount: string;
redeemedAmount: string;
redeemingAmount: string;
lockStartTime: number;
lockEndTime: number | null;
purchaseTime: number;
redeemPeriod: number;
status: 'LOCKED' | 'REDEEMING';
earlyRedeemSupported: 0 | 1;
}
⋮----
export interface EarnFixedIncomeHoldAssets {
totalNum: number;
items: EarnFixedIncomeHoldAsset[];
currentPage: number;
pageSize: number;
totalPage: number;
}
⋮----
export interface EarnProduct {
id: string;
currency: string;
category: 'DEMAND' | 'ACTIVITY' | 'KCS_STAKING' | 'STAKING' | 'ETH2';
type: 'TIME' | 'DEMAND';
precision: number;
productUpperLimit: string;
userUpperLimit: string;
userLowerLimit: string;
redeemPeriod: number;
lockStartTime: number;
lockEndTime: number | null;
applyStartTime: number;
applyEndTime: number | null;
returnRate: string;
incomeCurrency: string;
earlyRedeemSupported: 0 | 1;
productRemainAmount: string;
status: 'ONGOING' | 'PENDING' | 'FULL' | 'INTERESTING';
redeemType: 'MANUAL' | 'TRANS_DEMAND' | 'AUTO';
incomeReleaseType: 'DAILY' | 'AFTER';
interestDate: number;
duration: number;
newUserOnly: 0 | 1;
}
⋮----
/**
*
* STRUCTURED EARN - DUAL
*
*/
⋮----
export interface StructuredProductPurchaseResponse {
orderId: string; // Holding ID
}
⋮----
orderId: string; // Holding ID
⋮----
export interface DualInvestmentProduct {
category: 'DUAL_CLASSIC' | 'DUAL_BOOSTER' | 'DUAL_EXTRA'; // Product category
productId: string; // Product ID
targetCurrency: string; // Underlying currency of the product
quoteCurrency: string; // Currency used for pricing/quoting the product
investCurrency: string; // Currency used for investment
strikeCurrency: string; // Currency used for settlement if strike price is met
strikePrice: string; // Linked price (strike price) for settlement determination
protectPrice?: string; // Protection price for risk management (if applicable)
annualRate: string; // Annualized rate of return (e.g., 0.05 equals 5%)
expirationTime: number; // Product maturity time, in milliseconds
side: 'CALL' | 'PUT'; // Direction of the product: CALL (bullish), PUT (bearish)
expectSettleTime: number; // Expected settlement time, in milliseconds
duration: string; // Product duration (days)
lowerLimit: string; // Minimum investment amount per order
upperLimit: string; // Maximum investment amount per order
availableScale: string; // Total available subscription amount for the product
soldStatus: 'SOLD_OUT' | 'AVAILABLE'; // Product availability status
increment: string; // Investment step size (amount must be a multiple of this value, within lowerLimit and upperLimit)
}
⋮----
category: 'DUAL_CLASSIC' | 'DUAL_BOOSTER' | 'DUAL_EXTRA'; // Product category
productId: string; // Product ID
targetCurrency: string; // Underlying currency of the product
quoteCurrency: string; // Currency used for pricing/quoting the product
investCurrency: string; // Currency used for investment
strikeCurrency: string; // Currency used for settlement if strike price is met
strikePrice: string; // Linked price (strike price) for settlement determination
protectPrice?: string; // Protection price for risk management (if applicable)
annualRate: string; // Annualized rate of return (e.g., 0.05 equals 5%)
expirationTime: number; // Product maturity time, in milliseconds
side: 'CALL' | 'PUT'; // Direction of the product: CALL (bullish), PUT (bearish)
expectSettleTime: number; // Expected settlement time, in milliseconds
duration: string; // Product duration (days)
lowerLimit: string; // Minimum investment amount per order
upperLimit: string; // Maximum investment amount per order
availableScale: string; // Total available subscription amount for the product
soldStatus: 'SOLD_OUT' | 'AVAILABLE'; // Product availability status
increment: string; // Investment step size (amount must be a multiple of this value, within lowerLimit and upperLimit)
⋮----
export interface StructuredProductOrder {
category: string; // Product category
side: string; // Direction
duration: string; // Duration
apr: string; // Annual percentage rate
investCurrency: string; // Investment currency
strikeCurrency: string; // Strike currency
investAmount: string; // Investment amount
settleAmount: string; // Settlement amount
settleCurrency: string | null; // Settlement currency
targetPrice: string; // Target price
settlePrice: string; // Settlement price
expirationTime: number; // Expiration time in milliseconds
orderId: string; // Order ID
status: string; // Order status
}
⋮----
category: string; // Product category
side: string; // Direction
duration: string; // Duration
apr: string; // Annual percentage rate
investCurrency: string; // Investment currency
strikeCurrency: string; // Strike currency
investAmount: string; // Investment amount
settleAmount: string; // Settlement amount
settleCurrency: string | null; // Settlement currency
targetPrice: string; // Target price
settlePrice: string; // Settlement price
expirationTime: number; // Expiration time in milliseconds
orderId: string; // Order ID
status: string; // Order status
⋮----
export interface StructuredProductOrders {
currentPage: number; // Current page number
pageSize: number; // Number of records per page
totalNum: number; // Total number of records
totalPage: number; // Total number of pages
items: StructuredProductOrder[]; // List of structured product holdings
}
⋮----
currentPage: number; // Current page number
pageSize: number; // Number of records per page
totalNum: number; // Total number of records
totalPage: number; // Total number of pages
items: StructuredProductOrder[]; // List of structured product holdings
================
File: src/types/response/spot-misc.ts
================
export interface Announcement {
annId: number;
annTitle: string;
annType: string[];
annDesc: string;
cTime: number;
language: string;
annUrl: string;
}
⋮----
export interface Announcements {
totalNum: number;
currentPage: number;
pageSize: number;
totalPage: number;
items: Announcement[];
}
================
File: src/types/response/spot-vip.ts
================
/**
*
***********
* VIP LENDING
***********
*
*/
⋮----
export interface DiscountRateConfig {
currency: string;
usdtLevels: {
left: number;
right: number;
discountRate: string;
}[];
}
⋮----
export interface OtcLoan {
parentUid: string;
orders: {
orderId: string;
currency: string;
principal: string;
interest: string;
}[];
ltv: {
transferLtv: string;
onlyClosePosLtv: string;
delayedLiquidationLtv: string;
instantLiquidationLtv: string;
currentLtv: string;
};
totalMarginAmount: string;
transferMarginAmount: string;
margins: {
marginCcy: string;
marginQty: string;
marginFactor: string;
}[];
}
⋮----
export interface OtcLoanAccount {
uid: string;
marginCcy: string;
marginQty: string;
marginFactor: string;
accountType: 'TRADE' | 'TRADE_HF' | 'CONTRACT';
isParent: boolean;
}
================
File: .gitignore
================
examples/futures-private-test.ts
examples/spot-private-test.ts
node_modules
rest-spot-private-ts-test.ts
localtest.sh
testfile.ts
dist
repomix.sh
coverage
privaterepotracker
restClientRegex.ts
================
File: .nvmrc
================
v22.13.0
================
File: tsconfig.json
================
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"noEmitOnError": true,
"declaration": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": false,
"inlineSourceMap": false,
"lib": ["esnext"],
"listEmittedFiles": false,
"listFiles": false,
"moduleResolution": "node",
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noUnusedParameters": true,
"pretty": true,
"removeComments": false,
"resolveJsonModule": true,
"skipLibCheck": false,
"sourceMap": true,
"strict": true,
"strictNullChecks": true,
"types": ["node", "jest"],
"module": "commonjs",
"outDir": "dist/cjs",
"target": "esnext"
},
"compileOnSave": true,
"exclude": ["node_modules", "dist"],
"include": ["src/**/*.*", "test/**/*.*", ".eslintrc.cjs"]
}
================
File: src/lib/BaseWSClient.ts
================
import EventEmitter from 'events';
import WebSocket from 'isomorphic-ws';
⋮----
import {
WebsocketClientOptions,
WSClientConfigurableOptions,
} from '../types/websockets/client.js';
import { WsOperation } from '../types/websockets/requests.js';
import { WS_LOGGER_CATEGORY } from '../WebsocketClient.js';
import { checkWebCryptoAPISupported } from './webCryptoAPI.js';
import { DefaultLogger } from './websocket/logger.js';
import {
isMessageEvent,
MessageEventLike,
safeTerminateWs,
WsTopicRequest,
WsTopicRequestOrStringTopic,
} from './websocket/websocket-util.js';
import { WsStore } from './websocket/WsStore.js';
import {
WSConnectedResult,
WsConnectionStateEnum,
} from './websocket/WsStore.types.js';
⋮----
interface WSClientEventMap {
/** Connection opened. If this connection was previously opened and reconnected, expect the reconnected event instead */
open: (evt: { wsKey: WsKey; event: any }) => void;
/** Reconnecting a dropped connection */
reconnect: (evt: { wsKey: WsKey; event: any }) => void;
/** Successfully reconnected a connection that dropped */
reconnected: (evt: { wsKey: WsKey; event: any }) => void;
/** Connection closed */
close: (evt: { wsKey: WsKey; event: any }) => void;
/** Received reply to websocket command (e.g. after subscribing to topics) */
response: (response: any & { wsKey: WsKey }) => void;
/** Received data for topic */
update: (response: any & { wsKey: WsKey }) => void;
/** Exception from ws client OR custom listeners (e.g. if you throw inside your event handler) */
exception: (response: any & { wsKey: WsKey }) => void;
error: (response: any & { wsKey: WsKey }) => void;
/** Confirmation that a connection successfully authenticated */
authenticated: (event: { wsKey: WsKey; event: any }) => void;
}
⋮----
/** Connection opened. If this connection was previously opened and reconnected, expect the reconnected event instead */
⋮----
/** Reconnecting a dropped connection */
⋮----
/** Successfully reconnected a connection that dropped */
⋮----
/** Connection closed */
⋮----
/** Received reply to websocket command (e.g. after subscribing to topics) */
⋮----
/** Received data for topic */
⋮----
/** Exception from ws client OR custom listeners (e.g. if you throw inside your event handler) */
⋮----
/** Confirmation that a connection successfully authenticated */
⋮----
export interface EmittableEvent {
eventType:
| 'response'
| 'update'
| 'exception'
| 'authenticated'
| 'connectionReady'; // tied to "requireConnectionReadyConfirmation"
event: TEvent;
}
⋮----
| 'connectionReady'; // tied to "requireConnectionReadyConfirmation"
⋮----
// Type safety for on and emit handlers: https://stackoverflow.com/a/61609010/880837
export interface BaseWebsocketClient {
on>(
event: U,
listener: WSClientEventMap[U],
): this;
emit>(
event: U,
...args: Parameters[U]>
): boolean;
}
⋮----
on>(
event: U,
listener: WSClientEventMap[U],
): this;
⋮----
emit>(
event: U,
...args: Parameters[U]>
): boolean;
⋮----
/**
* Users can conveniently pass topics as strings or objects (object has topic name + optional params).
*
* This method normalises topics into objects (object has topic name + optional params).
*/
function getNormalisedTopicRequests(
wsTopicRequests: WsTopicRequestOrStringTopic[],
): WsTopicRequest[]
⋮----
// passed as string, convert to object
⋮----
// already a normalised object, thanks to user
⋮----
type WSTopic = string;
⋮----
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
export abstract class BaseWebsocketClient<
TWSKey extends string,
⋮----
constructor(
options?: WSClientConfigurableOptions,
logger?: typeof DefaultLogger,
)
⋮----
// Requires a confirmation "response" from the ws connection before assuming it is ready
⋮----
// Automatically auth after opening a connection?
⋮----
// Automatically include auth/sign with every WS request
⋮----
// Automatically re-auth WS API, if we were auth'd before and get reconnected
⋮----
// Check Web Crypto API support when credentials are provided and no custom sign function is used
⋮----
protected abstract sendPingEvent(wsKey: TWSKey, ws: WebSocket): void;
⋮----
protected abstract sendPongEvent(wsKey: TWSKey, ws: WebSocket): void;
⋮----
protected abstract isWsPong(data: any): boolean;
⋮----
protected abstract isWsPing(data: any): boolean;
⋮----
protected abstract getWsAuthRequestEvent(wsKey: TWSKey): Promise