Merge pull request #9 from tiagosiebler/next

Add new endpoints & request params
This commit is contained in:
Tiago
2023-03-23 10:14:10 +00:00
committed by GitHub
34 changed files with 865 additions and 315 deletions

View File

@@ -1,4 +1,5 @@
{ {
"tabWidth": 2, "tabWidth": 2,
"singleQuote": true "singleQuote": true,
"trailingComma": "all"
} }

View File

@@ -47,7 +47,7 @@ function promiseSleep(milliseconds) {
// WARNING: for sensitive math you should be using a library such as decimal.js! // WARNING: for sensitive math you should be using a library such as decimal.js!
function roundDown(value, decimals) { function roundDown(value, decimals) {
return Number( return Number(
Math.floor(parseFloat(value + 'e' + decimals)) + 'e-' + decimals Math.floor(parseFloat(value + 'e' + decimals)) + 'e-' + decimals,
); );
} }
@@ -117,7 +117,7 @@ async function handleWsUpdate(event) {
const symbolRulesResult = await client.getSymbols('umcbl'); const symbolRulesResult = await client.getSymbols('umcbl');
const bitcoinUSDFuturesRule = symbolRulesResult.data.find( const bitcoinUSDFuturesRule = symbolRulesResult.data.find(
(row) => row.symbol === symbol (row) => row.symbol === symbol,
); );
console.log('symbol rules: ', bitcoinUSDFuturesRule); console.log('symbol rules: ', bitcoinUSDFuturesRule);
@@ -142,7 +142,7 @@ async function handleWsUpdate(event) {
const positionsResult = await client.getPositions('umcbl'); const positionsResult = await client.getPositions('umcbl');
const positionsToClose = positionsResult.data.filter( const positionsToClose = positionsResult.data.filter(
(pos) => pos.total !== '0' (pos) => pos.total !== '0',
); );
console.log('open positions to close: ', positionsToClose); console.log('open positions to close: ', positionsToClose);
@@ -167,7 +167,7 @@ async function handleWsUpdate(event) {
console.log( console.log(
'positions after closing all: ', 'positions after closing all: ',
await client.getPositions('umcbl') await client.getPositions('umcbl'),
); );
} catch (e) { } catch (e) {
console.error('request failed: ', e); console.error('request failed: ', e);

View File

@@ -35,7 +35,7 @@ function promiseSleep(milliseconds) {
// WARNING: for sensitive math you should be using a library such as decimal.js! // WARNING: for sensitive math you should be using a library such as decimal.js!
function roundDown(value, decimals) { function roundDown(value, decimals) {
return Number( return Number(
Math.floor(parseFloat(value + 'e' + decimals)) + 'e-' + decimals Math.floor(parseFloat(value + 'e' + decimals)) + 'e-' + decimals,
); );
} }

View File

@@ -22,7 +22,7 @@ import { WebsocketClient, DefaultLogger } from '../src';
// optionally provide rest options, e.g. to pass through a proxy // optionally provide rest options, e.g. to pass through a proxy
// }, // },
}, },
logger logger,
); );
wsClient.on('update', (data) => { wsClient.on('update', (data) => {

View File

@@ -15,7 +15,7 @@ import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../src';
// optionally provide rest options, e.g. to pass through a proxy // optionally provide rest options, e.g. to pass through a proxy
// }, // },
}, },
logger logger,
); );
wsClient.on('update', (data) => { wsClient.on('update', (data) => {

View File

@@ -1,6 +1,6 @@
{ {
"name": "bitget-api", "name": "bitget-api",
"version": "1.0.4", "version": "1.0.5",
"description": "Node.js connector for Bitget REST APIs and WebSockets, with TypeScript & end-to-end tests.", "description": "Node.js connector for Bitget REST APIs and WebSockets, with TypeScript & end-to-end tests.",
"main": "lib/index.js", "main": "lib/index.js",
"types": "lib/index.d.ts", "types": "lib/index.d.ts",

View File

@@ -30,7 +30,7 @@ export class BrokerClient extends BaseRestClient {
/** Create Sub Account */ /** Create Sub Account */
createSubAccount( createSubAccount(
subName: string, subName: string,
remark?: string remark?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/broker/v1/account/sub-create', { return this.postPrivate('/api/broker/v1/account/sub-create', {
subName, subName,
@@ -47,7 +47,7 @@ export class BrokerClient extends BaseRestClient {
modifySubAccount( modifySubAccount(
subUid: string, subUid: string,
perm: string, perm: string,
status: 'normal' | 'freeze' | 'del' status: 'normal' | 'freeze' | 'del',
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/broker/v1/account/sub-modify', { return this.postPrivate('/api/broker/v1/account/sub-modify', {
subUid, subUid,
@@ -79,7 +79,7 @@ export class BrokerClient extends BaseRestClient {
/** Get Sub Future Assets */ /** Get Sub Future Assets */
getSubFutureAssets( getSubFutureAssets(
subUid: string, subUid: string,
productType: BrokerProductType productType: BrokerProductType,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/broker/v1/account/sub-future-assets', { return this.getPrivate('/api/broker/v1/account/sub-future-assets', {
subUid, subUid,
@@ -91,7 +91,7 @@ export class BrokerClient extends BaseRestClient {
getSubDepositAddress( getSubDepositAddress(
subUid: string, subUid: string,
coin: string, coin: string,
chain?: string chain?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/broker/v1/account/sub-address', { return this.postPrivate('/api/broker/v1/account/sub-address', {
subUid, subUid,
@@ -109,7 +109,7 @@ export class BrokerClient extends BaseRestClient {
setSubDepositAutoTransfer( setSubDepositAutoTransfer(
subUid: string, subUid: string,
coin: string, coin: string,
toAccountType: 'spot' | 'mix_usdt' | 'mix_usd' | 'mix_usdc' toAccountType: 'spot' | 'mix_usdt' | 'mix_usd' | 'mix_usdc',
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/broker/v1/account/sub-auto-transfer', { return this.postPrivate('/api/broker/v1/account/sub-auto-transfer', {
subUid, subUid,
@@ -130,7 +130,7 @@ export class BrokerClient extends BaseRestClient {
passphrase: string, passphrase: string,
remark: string, remark: string,
ip: string, ip: string,
perm?: string perm?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/broker/v1/manage/sub-api-create', { return this.postPrivate('/api/broker/v1/manage/sub-api-create', {
subUid, subUid,
@@ -148,7 +148,7 @@ export class BrokerClient extends BaseRestClient {
/** Modify Sub ApiKey (Only Broker) */ /** Modify Sub ApiKey (Only Broker) */
modifySubAPIKey( modifySubAPIKey(
params: BrokerSubAPIKeyModifyRequest params: BrokerSubAPIKeyModifyRequest,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/broker/v1/manage/sub-api-modify', params); return this.postPrivate('/api/broker/v1/manage/sub-api-modify', params);
} }

View File

@@ -20,6 +20,10 @@ import {
FuturesMarginMode, FuturesMarginMode,
FuturesPosition, FuturesPosition,
NewFuturesPlanTrailingStopOrder, NewFuturesPlanTrailingStopOrder,
VIPFeeRate,
GetHistoricTradesParams,
FuturesMarketTrade,
FuturesPlanType,
} from './types'; } from './types';
import { REST_CLIENT_TYPE_ENUM } from './util'; import { REST_CLIENT_TYPE_ENUM } from './util';
import BaseRestClient from './util/BaseRestClient'; import BaseRestClient from './util/BaseRestClient';
@@ -40,7 +44,7 @@ export class FuturesClient extends BaseRestClient {
/** Get Symbols : Get basic configuration information of all trading pairs (including rules) */ /** Get Symbols : Get basic configuration information of all trading pairs (including rules) */
getSymbols( getSymbols(
productType: FuturesProductType productType: FuturesProductType,
): Promise<APIResponse<FuturesSymbolRule[]>> { ): Promise<APIResponse<FuturesSymbolRule[]>> {
return this.get('/api/mix/v1/market/contracts', { productType }); return this.get('/api/mix/v1/market/contracts', { productType });
} }
@@ -60,8 +64,33 @@ export class FuturesClient extends BaseRestClient {
return this.get('/api/mix/v1/market/tickers', { productType }); return this.get('/api/mix/v1/market/tickers', { productType });
} }
/** Get Market Trades */ /** Get VIP fee rates */
getMarketTrades(symbol: string, limit?: string): Promise<APIResponse<any>> { getVIPFeeRates(): Promise<APIResponse<VIPFeeRate[]>> {
return this.get('/api/mix/v1/market/contract-vip-level');
}
/** Get most recent trades (up to 500, 100 by default) */
getRecentTrades(
symbol: string,
limit?: string,
): Promise<APIResponse<FuturesMarketTrade[]>> {
return this.get('/api/mix/v1/market/fills', { symbol, limit });
}
/** Get historic trades, up to 30 days at a time. Same-parameter responses are cached for 10 minutes. */
getHistoricTrades(
params: GetHistoricTradesParams,
): Promise<APIResponse<FuturesMarketTrade[]>> {
return this.get('/api/mix/v1/market/fills-history', params);
}
/**
* @deprecated use getRecentTrades() instead. This method will be removed soon.
*/
getMarketTrades(
symbol: string,
limit?: string,
): Promise<APIResponse<FuturesMarketTrade[]>> {
return this.get('/api/mix/v1/market/fills', { symbol, limit }); return this.get('/api/mix/v1/market/fills', { symbol, limit });
} }
@@ -70,13 +99,15 @@ export class FuturesClient extends BaseRestClient {
symbol: string, symbol: string,
granularity: KlineInterval, granularity: KlineInterval,
startTime: string, startTime: string,
endTime: string endTime: string,
limit?: string,
): Promise<any> { ): Promise<any> {
return this.get('/api/mix/v1/market/candles', { return this.get('/api/mix/v1/market/candles', {
symbol, symbol,
granularity, granularity,
startTime, startTime,
endTime, endTime,
limit,
}); });
} }
@@ -95,7 +126,7 @@ export class FuturesClient extends BaseRestClient {
symbol: string, symbol: string,
pageSize?: string, pageSize?: string,
pageNo?: string, pageNo?: string,
nextPage?: boolean nextPage?: boolean,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.get('/api/mix/v1/market/history-fundRate', { return this.get('/api/mix/v1/market/history-fundRate', {
symbol, symbol,
@@ -134,7 +165,7 @@ export class FuturesClient extends BaseRestClient {
/** Get Single Account */ /** Get Single Account */
getAccount( getAccount(
symbol: string, symbol: string,
marginCoin: string marginCoin: string,
): Promise<APIResponse<FuturesAccount>> { ): Promise<APIResponse<FuturesAccount>> {
return this.getPrivate('/api/mix/v1/account/account', { return this.getPrivate('/api/mix/v1/account/account', {
symbol, symbol,
@@ -147,6 +178,15 @@ export class FuturesClient extends BaseRestClient {
return this.getPrivate('/api/mix/v1/account/accounts', { productType }); return this.getPrivate('/api/mix/v1/account/accounts', { productType });
} }
/** Get Sub Account Contract Assets */
getSubAccountContractAssets(
productType: FuturesProductType,
): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/account/sub-account-contract-assets', {
productType,
});
}
/** /**
* This interface is only used to calculate the maximum number of positions that can be opened when the user does not hold a position by default. * This interface is only used to calculate the maximum number of positions that can be opened when the user does not hold a position by default.
* The result does not represent the actual number of positions opened. * The result does not represent the actual number of positions opened.
@@ -156,7 +196,7 @@ export class FuturesClient extends BaseRestClient {
marginCoin: string, marginCoin: string,
openPrice: number, openPrice: number,
openAmount: number, openAmount: number,
leverage?: number leverage?: number,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/account/open-count', { return this.postPrivate('/api/mix/v1/account/open-count', {
symbol, symbol,
@@ -172,7 +212,7 @@ export class FuturesClient extends BaseRestClient {
symbol: string, symbol: string,
marginCoin: string, marginCoin: string,
leverage: string, leverage: string,
holdSide?: string holdSide?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/account/setLeverage', { return this.postPrivate('/api/mix/v1/account/setLeverage', {
symbol, symbol,
@@ -187,7 +227,7 @@ export class FuturesClient extends BaseRestClient {
symbol: string, symbol: string,
marginCoin: string, marginCoin: string,
amount: string, amount: string,
holdSide?: string holdSide?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/account/setMargin', { return this.postPrivate('/api/mix/v1/account/setMargin', {
symbol, symbol,
@@ -201,7 +241,7 @@ export class FuturesClient extends BaseRestClient {
setMarginMode( setMarginMode(
symbol: string, symbol: string,
marginCoin: string, marginCoin: string,
marginMode: FuturesMarginMode marginMode: FuturesMarginMode,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/account/setMarginMode', { return this.postPrivate('/api/mix/v1/account/setMarginMode', {
symbol, symbol,
@@ -210,10 +250,21 @@ export class FuturesClient extends BaseRestClient {
}); });
} }
/** Change Hold Mode */
setHoldMode(
productType: FuturesProductType,
holdMode: 'single_hold' | 'double_hold',
): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/account/setPositionMode', {
productType,
holdMode,
});
}
/** Get Symbol Position */ /** Get Symbol Position */
getPosition( getPosition(
symbol: string, symbol: string,
marginCoin?: string marginCoin?: string,
): Promise<APIResponse<FuturesPosition[]>> { ): Promise<APIResponse<FuturesPosition[]>> {
return this.getPrivate('/api/mix/v1/position/singlePosition', { return this.getPrivate('/api/mix/v1/position/singlePosition', {
symbol, symbol,
@@ -224,7 +275,7 @@ export class FuturesClient extends BaseRestClient {
/** Get All Position */ /** Get All Position */
getPositions( getPositions(
productType: FuturesProductType, productType: FuturesProductType,
marginCoin?: string marginCoin?: string,
): Promise<APIResponse<FuturesPosition[]>> { ): Promise<APIResponse<FuturesPosition[]>> {
return this.getPrivate('/api/mix/v1/position/allPosition', { return this.getPrivate('/api/mix/v1/position/allPosition', {
productType, productType,
@@ -239,7 +290,7 @@ export class FuturesClient extends BaseRestClient {
/** Get Business Account Bill */ /** Get Business Account Bill */
getBusinessBill( getBusinessBill(
params: FuturesBusinessBillRequest params: FuturesBusinessBillRequest,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/account/accountBusinessBill', params); return this.getPrivate('/api/mix/v1/account/accountBusinessBill', params);
} }
@@ -259,7 +310,7 @@ export class FuturesClient extends BaseRestClient {
batchSubmitOrder( batchSubmitOrder(
symbol: string, symbol: string,
marginCoin: string, marginCoin: string,
orders: NewBatchFuturesOrder[] orders: NewBatchFuturesOrder[],
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/order/batch-orders', { return this.postPrivate('/api/mix/v1/order/batch-orders', {
symbol, symbol,
@@ -272,12 +323,14 @@ export class FuturesClient extends BaseRestClient {
cancelOrder( cancelOrder(
symbol: string, symbol: string,
marginCoin: string, marginCoin: string,
orderId: string orderId?: string,
clientOid?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/order/cancel-order', { return this.postPrivate('/api/mix/v1/order/cancel-order', {
symbol, symbol,
marginCoin, marginCoin,
orderId, orderId,
clientOid,
}); });
} }
@@ -285,7 +338,7 @@ export class FuturesClient extends BaseRestClient {
batchCancelOrder( batchCancelOrder(
symbol: string, symbol: string,
marginCoin: string, marginCoin: string,
orderIds: string[] orderIds: string[],
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/order/cancel-batch-orders', { return this.postPrivate('/api/mix/v1/order/cancel-batch-orders', {
symbol, symbol,
@@ -294,10 +347,23 @@ export class FuturesClient extends BaseRestClient {
}); });
} }
/**
* Cancel all futures orders for a symbol
*/
cancelSymbolOrders(
symbol: string,
marginCoin: string,
): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/order/cancel-symbol-orders', {
symbol,
marginCoin,
});
}
/** Cancel All Order */ /** Cancel All Order */
cancelAllOrders( cancelAllOrders(
productType: FuturesProductType, productType: FuturesProductType,
marginCoin: string marginCoin: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/order/cancel-all-orders', { return this.postPrivate('/api/mix/v1/order/cancel-all-orders', {
productType, productType,
@@ -313,7 +379,7 @@ export class FuturesClient extends BaseRestClient {
/** Get All Open Order */ /** Get All Open Order */
getOpenOrders( getOpenOrders(
productType: FuturesProductType, productType: FuturesProductType,
marginCoin: string marginCoin: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/order/marginCoinCurrent', { return this.getPrivate('/api/mix/v1/order/marginCoinCurrent', {
productType, productType,
@@ -328,7 +394,8 @@ export class FuturesClient extends BaseRestClient {
endTime: string, endTime: string,
pageSize: string, pageSize: string,
lastEndId?: string, lastEndId?: string,
isPre?: boolean isPre?: boolean,
clientOid?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/order/history', { return this.getPrivate('/api/mix/v1/order/history', {
symbol, symbol,
@@ -337,6 +404,7 @@ export class FuturesClient extends BaseRestClient {
pageSize, pageSize,
lastEndId, lastEndId,
isPre, isPre,
clientOid,
}); });
} }
@@ -347,7 +415,8 @@ export class FuturesClient extends BaseRestClient {
endTime: string, endTime: string,
pageSize: string, pageSize: string,
lastEndId?: string, lastEndId?: string,
isPre?: boolean isPre?: boolean,
clientOid?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/order/historyProductType', { return this.getPrivate('/api/mix/v1/order/historyProductType', {
productType, productType,
@@ -356,6 +425,7 @@ export class FuturesClient extends BaseRestClient {
pageSize, pageSize,
lastEndId, lastEndId,
isPre, isPre,
clientOid,
}); });
} }
@@ -363,7 +433,7 @@ export class FuturesClient extends BaseRestClient {
getOrder( getOrder(
symbol: string, symbol: string,
orderId?: string, orderId?: string,
clientOid?: string clientOid?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/order/detail', { return this.getPrivate('/api/mix/v1/order/detail', {
symbol, symbol,
@@ -376,7 +446,7 @@ export class FuturesClient extends BaseRestClient {
getOrderFills( getOrderFills(
symbol: string, symbol: string,
orderId?: string, orderId?: string,
pagination?: FuturesPagination pagination?: FuturesPagination,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/order/fills', { return this.getPrivate('/api/mix/v1/order/fills', {
symbol, symbol,
@@ -388,7 +458,7 @@ export class FuturesClient extends BaseRestClient {
/** Get ProductType Order fill detail */ /** Get ProductType Order fill detail */
getProductTypeOrderFills( getProductTypeOrderFills(
productType: FuturesProductType, productType: FuturesProductType,
pagination?: FuturesPagination pagination?: FuturesPagination,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/order/allFills', { return this.getPrivate('/api/mix/v1/order/allFills', {
productType: productType.toUpperCase(), productType: productType.toUpperCase(),
@@ -408,7 +478,7 @@ export class FuturesClient extends BaseRestClient {
/** Modify Plan Order TPSL */ /** Modify Plan Order TPSL */
modifyPlanOrderTPSL( modifyPlanOrderTPSL(
params: ModifyFuturesPlanOrderTPSL params: ModifyFuturesPlanOrderTPSL,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/plan/modifyPlanPreset', params); return this.postPrivate('/api/mix/v1/plan/modifyPlanPreset', params);
} }
@@ -420,37 +490,48 @@ export class FuturesClient extends BaseRestClient {
/** Place Trailing Stop order */ /** Place Trailing Stop order */
submitTrailingStopOrder( submitTrailingStopOrder(
params: NewFuturesPlanTrailingStopOrder params: NewFuturesPlanTrailingStopOrder,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/plan/placeTrailStop', params); return this.postPrivate('/api/mix/v1/plan/placeTrailStop', params);
} }
/** Place Position TPSL */ /** Place Position TPSL */
submitPositionTPSL( submitPositionTPSL(
params: NewFuturesPlanPositionTPSL params: NewFuturesPlanPositionTPSL,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/plan/placePositionsTPSL', params); return this.postPrivate('/api/mix/v1/plan/placePositionsTPSL', params);
} }
/** Modify Stop Order */ /** Modify Stop Order */
modifyStopOrder( modifyStopOrder(
params: ModifyFuturesPlanStopOrder params: ModifyFuturesPlanStopOrder,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/plan/modifyTPSLPlan', params); return this.postPrivate('/api/mix/v1/plan/modifyTPSLPlan', params);
} }
/** Cancel Plan Order TPSL */ /** Cancel Plan Order TPSL */
cancelPlanOrderTPSL( cancelPlanOrderTPSL(
params: CancelFuturesPlanTPSL params: CancelFuturesPlanTPSL,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/plan/cancelPlan', params); return this.postPrivate('/api/mix/v1/plan/cancelPlan', params);
} }
/** Cancel All Trigger Order (TPSL) */
cancelAllPlanOrders(
productType: FuturesProductType,
planType: FuturesPlanType,
): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/plan/cancelAllPlan', {
productType,
planType,
});
}
/** Get Plan Order (TPSL) List */ /** Get Plan Order (TPSL) List */
getPlanOrderTPSLs( getPlanOrderTPSLs(
symbol: string, symbol: string,
isPlan?: string, isPlan?: string,
productType?: FuturesProductType productType?: FuturesProductType,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/plan/currentPlan', { return this.getPrivate('/api/mix/v1/plan/currentPlan', {
symbol, symbol,
@@ -461,14 +542,14 @@ export class FuturesClient extends BaseRestClient {
/** Get History Plan Orders (TPSL) */ /** Get History Plan Orders (TPSL) */
getHistoricPlanOrdersTPSL( getHistoricPlanOrdersTPSL(
params: HistoricPlanOrderTPSLRequest params: HistoricPlanOrderTPSLRequest,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/plan/historyPlan', params); return this.getPrivate('/api/mix/v1/plan/historyPlan', params);
} }
/** /**
* *
* Trade Endpoints * Copy Trade Endpoints
* *
*/ */
@@ -477,7 +558,7 @@ export class FuturesClient extends BaseRestClient {
symbol: string, symbol: string,
productType: FuturesProductType, productType: FuturesProductType,
pageSize: number, pageSize: number,
pageNo: number pageNo: number,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/trace/currentTrack', { return this.getPrivate('/api/mix/v1/trace/currentTrack', {
symbol, symbol,
@@ -492,7 +573,7 @@ export class FuturesClient extends BaseRestClient {
symbol: string, symbol: string,
productType: FuturesProductType, productType: FuturesProductType,
pageSize: number, pageSize: number,
pageNo: number pageNo: number,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/trace/followerOrder', { return this.getPrivate('/api/mix/v1/trace/followerOrder', {
symbol, symbol,
@@ -505,7 +586,7 @@ export class FuturesClient extends BaseRestClient {
/** Trader Close Position */ /** Trader Close Position */
closeCopyTraderPosition( closeCopyTraderPosition(
symbol: string, symbol: string,
trackingNo: string trackingNo: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/trace/closeTrackOrder', { return this.postPrivate('/api/mix/v1/trace/closeTrackOrder', {
symbol, symbol,
@@ -520,7 +601,7 @@ export class FuturesClient extends BaseRestClient {
changes?: { changes?: {
stopProfitPrice?: number; stopProfitPrice?: number;
stopLossPrice?: number; stopLossPrice?: number;
} },
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/trace/modifyTPSL', { return this.postPrivate('/api/mix/v1/trace/modifyTPSL', {
symbol, symbol,
@@ -534,7 +615,7 @@ export class FuturesClient extends BaseRestClient {
startTime: string, startTime: string,
endTime: string, endTime: string,
pageSize: number, pageSize: number,
pageNo: number pageNo: number,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/trace/historyTrack', { return this.getPrivate('/api/mix/v1/trace/historyTrack', {
startTime, startTime,
@@ -559,7 +640,7 @@ export class FuturesClient extends BaseRestClient {
marginCoin: string, marginCoin: string,
dateMs: string, dateMs: string,
pageSize: number, pageSize: number,
pageNo: number pageNo: number,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/trace/profitDateGroupList', { return this.getPrivate('/api/mix/v1/trace/profitDateGroupList', {
marginCoin, marginCoin,
@@ -574,7 +655,7 @@ export class FuturesClient extends BaseRestClient {
marginCoin: string, marginCoin: string,
dateMs: string, dateMs: string,
pageSize: number, pageSize: number,
pageNo: number pageNo: number,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/trace/profitDateList', { return this.getPrivate('/api/mix/v1/trace/profitDateList', {
marginCoin, marginCoin,
@@ -587,7 +668,7 @@ export class FuturesClient extends BaseRestClient {
/** Get Trader Profits Details */ /** Get Trader Profits Details */
getCopyTraderProfitDetails( getCopyTraderProfitDetails(
pageSize: number, pageSize: number,
pageNo: number pageNo: number,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/mix/v1/trace/waitProfitDateList', { return this.getPrivate('/api/mix/v1/trace/waitProfitDateList', {
pageSize, pageSize,
@@ -603,7 +684,7 @@ export class FuturesClient extends BaseRestClient {
/** Trader Change CopyTrade symbol */ /** Trader Change CopyTrade symbol */
setCopyTraderSymbols( setCopyTraderSymbols(
symbol: string, symbol: string,
operation: 'add' | 'delete' operation: 'add' | 'delete',
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/mix/v1/trace/setUpCopySymbols', { return this.postPrivate('/api/mix/v1/trace/setUpCopySymbols', {
symbol, symbol,

View File

@@ -7,6 +7,20 @@ import {
KlineInterval, KlineInterval,
CoinBalance, CoinBalance,
SymbolRules, SymbolRules,
NewSpotSubTransfer,
NewSpotWithdraw,
CancelSpotOrderV2,
BatchCancelSpotOrderV2,
SpotOrderResult,
NewSpotPlanOrder,
ModifySpotPlanOrder,
CancelSpotPlanOrderParams,
GetSpotPlanOrdersParams,
SpotPlanOrder,
GetHistoricPlanOrdersParams,
SpotMarketTrade,
GetHistoricTradesParams,
VIPFeeRate,
} from './types'; } from './types';
import { REST_CLIENT_TYPE_ENUM } from './util'; import { REST_CLIENT_TYPE_ENUM } from './util';
import BaseRestClient from './util/BaseRestClient'; import BaseRestClient from './util/BaseRestClient';
@@ -66,8 +80,28 @@ export class SpotClient extends BaseRestClient {
return this.get('/api/spot/v1/market/tickers'); return this.get('/api/spot/v1/market/tickers');
} }
/** Get Market Trades */ /** Get most recent trades (up to 500, 100 by default) */
getMarketTrades(symbol: string, limit?: string): Promise<APIResponse<any>> { getRecentTrades(
symbol: string,
limit?: string,
): Promise<APIResponse<SpotMarketTrade[]>> {
return this.get('/api/spot/v1/market/fills', { symbol, limit });
}
/** Get historic trades, up to 30 days at a time. Same-parameter responses are cached for 10 minutes. */
getHistoricTrades(
params: GetHistoricTradesParams,
): Promise<APIResponse<SpotMarketTrade[]>> {
return this.get('/api/spot/v1/market/fills-history', params);
}
/**
* @deprecated use getRecentTrades() instead. This method will be removed soon.
*/
getMarketTrades(
symbol: string,
limit?: string,
): Promise<APIResponse<SpotMarketTrade[]>> {
return this.get('/api/spot/v1/market/fills', { symbol, limit }); return this.get('/api/spot/v1/market/fills', { symbol, limit });
} }
@@ -75,7 +109,7 @@ export class SpotClient extends BaseRestClient {
getCandles( getCandles(
symbol: string, symbol: string,
period: KlineInterval, period: KlineInterval,
pagination?: Pagination pagination?: Pagination,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.get('/api/spot/v1/market/candles', { return this.get('/api/spot/v1/market/candles', {
symbol, symbol,
@@ -88,11 +122,16 @@ export class SpotClient extends BaseRestClient {
getDepth( getDepth(
symbol: string, symbol: string,
type: 'step0' | 'step1' | 'step2' | 'step3' | 'step4' | 'step5', type: 'step0' | 'step1' | 'step2' | 'step3' | 'step4' | 'step5',
limit?: string limit?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.get('/api/spot/v1/market/depth', { symbol, type, limit }); return this.get('/api/spot/v1/market/depth', { symbol, type, limit });
} }
/** Get VIP fee rates */
getVIPFeeRates(): Promise<APIResponse<VIPFeeRate[]>> {
return this.get('/api/spot/v1/market/spot-vip-level');
}
/** /**
* *
* Wallet Endpoints * Wallet Endpoints
@@ -104,6 +143,18 @@ export class SpotClient extends BaseRestClient {
return this.postPrivate('/api/spot/v1/wallet/transfer', params); return this.postPrivate('/api/spot/v1/wallet/transfer', params);
} }
/** Initiate wallet transfer (v2 endpoint) */
transferV2(params: NewWalletTransfer): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/wallet/transfer-v2', params);
}
/**
* Transfer main-sub, sub-sub or sub-main
*/
subTransfer(params: NewSpotSubTransfer): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/wallet/subTransfer', params);
}
/** Get Coin Address */ /** Get Coin Address */
getDepositAddress(coin: string, chain?: string): Promise<APIResponse<any>> { getDepositAddress(coin: string, chain?: string): Promise<APIResponse<any>> {
return this.getPrivate('/api/spot/v1/wallet/deposit-address', { return this.getPrivate('/api/spot/v1/wallet/deposit-address', {
@@ -112,25 +163,22 @@ export class SpotClient extends BaseRestClient {
}); });
} }
/** Withdraw Coins On Chain*/ /** Withdraw Coins On Chain */
withdraw(params: { withdraw(params: NewSpotWithdraw): Promise<APIResponse<any>> {
coin: string;
address: string;
chain: string;
tag?: string;
amount: string;
remark?: string;
clientOid?: string;
}): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/wallet/withdrawal', params); return this.postPrivate('/api/spot/v1/wallet/withdrawal', params);
} }
/** Withdraw Coins On Chain (v2 endpoint) */
withdrawV2(params: NewSpotWithdraw): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/wallet/withdrawal-v2', params);
}
/** Inner Withdraw : Internal withdrawal means that both users are on the Bitget platform */ /** Inner Withdraw : Internal withdrawal means that both users are on the Bitget platform */
innerWithdraw( innerWithdraw(
coin: string, coin: string,
toUid: string, toUid: string,
amount: string, amount: string,
clientOid?: string clientOid?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/wallet/withdrawal-inner', { return this.postPrivate('/api/spot/v1/wallet/withdrawal-inner', {
coin, coin,
@@ -140,13 +188,29 @@ export class SpotClient extends BaseRestClient {
}); });
} }
/** Inner Withdraw (v2 endpoint) : Internal withdrawal means that both users are on the Bitget platform */
innerWithdrawV2(
coin: string,
toUid: string,
amount: string,
clientOid?: string,
): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/wallet/withdrawal-inner-v2', {
coin,
toUid,
amount,
clientOid,
});
}
/** Get Withdraw List */ /** Get Withdraw List */
getWithdrawals( getWithdrawals(
coin: string, coin: string,
startTime: string, startTime: string,
endTime: string, endTime: string,
pageSize?: string, pageSize?: string,
pageNo?: string pageNo?: string,
clientOid?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/spot/v1/wallet/withdrawal-list', { return this.getPrivate('/api/spot/v1/wallet/withdrawal-list', {
coin, coin,
@@ -154,6 +218,7 @@ export class SpotClient extends BaseRestClient {
endTime, endTime,
pageSize, pageSize,
pageNo, pageNo,
clientOid,
}); });
} }
@@ -163,7 +228,7 @@ export class SpotClient extends BaseRestClient {
startTime: string, startTime: string,
endTime: string, endTime: string,
pageSize?: string, pageSize?: string,
pageNo?: string pageNo?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.getPrivate('/api/spot/v1/wallet/deposit-list', { return this.getPrivate('/api/spot/v1/wallet/deposit-list', {
coin, coin,
@@ -190,6 +255,11 @@ export class SpotClient extends BaseRestClient {
return this.getPrivate('/api/spot/v1/account/assets', { coin }); return this.getPrivate('/api/spot/v1/account/assets', { coin });
} }
/** Get sub Account Spot Asset */
getSubAccountSpotAssets(): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/account/sub-account-spot-assets');
}
/** Get Bills : get transaction detail flow */ /** Get Bills : get transaction detail flow */
getTransactionHistory(params?: { getTransactionHistory(params?: {
coinId?: number; coinId?: number;
@@ -209,6 +279,7 @@ export class SpotClient extends BaseRestClient {
after?: string; after?: string;
before?: string; before?: string;
limit?: number; limit?: number;
clientOid?: string;
}): Promise<APIResponse<any>> { }): Promise<APIResponse<any>> {
return this.getPrivate('/api/spot/v1/account/transferRecords', params); return this.getPrivate('/api/spot/v1/account/transferRecords', params);
} }
@@ -220,14 +291,14 @@ export class SpotClient extends BaseRestClient {
*/ */
/** Place order */ /** Place order */
submitOrder(params: NewSpotOrder): Promise<APIResponse<any>> { submitOrder(params: NewSpotOrder): Promise<APIResponse<SpotOrderResult>> {
return this.postPrivate('/api/spot/v1/trade/orders', params); return this.postPrivate('/api/spot/v1/trade/orders', params);
} }
/** Place orders in batches, up to 50 at a time */ /** Place orders in batches, up to 50 at a time */
batchSubmitOrder( batchSubmitOrder(
symbol: string, symbol: string,
orderList: NewBatchSpotOrder[] orderList: NewBatchSpotOrder[],
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/trade/batch-orders', { return this.postPrivate('/api/spot/v1/trade/batch-orders', {
symbol, symbol,
@@ -243,10 +314,24 @@ export class SpotClient extends BaseRestClient {
}); });
} }
/** Cancel order (v2 endpoint - supports orderId or clientOid) */
cancelOrderV2(params?: CancelSpotOrderV2): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/trade/cancel-order-v2', params);
}
/**
* Cancel all spot orders for a symbol
*/
cancelSymbolOrders(symbol: string): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/trade/cancel-symbol-order', {
symbol,
});
}
/** Cancel order in batch (per symbol) */ /** Cancel order in batch (per symbol) */
batchCancelOrder( batchCancelOrder(
symbol: string, symbol: string,
orderIds: string[] orderIds: string[],
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/trade/cancel-batch-orders', { return this.postPrivate('/api/spot/v1/trade/cancel-batch-orders', {
symbol, symbol,
@@ -254,11 +339,21 @@ export class SpotClient extends BaseRestClient {
}); });
} }
/** Cancel order in batch (per symbol). V2 endpoint, supports orderIds or clientOids. */
batchCancelOrderV2(
params: BatchCancelSpotOrderV2,
): Promise<APIResponse<any>> {
return this.postPrivate(
'/api/spot/v1/trade/cancel-batch-orders-v2',
params,
);
}
/** Get order details */ /** Get order details */
getOrder( getOrder(
symbol: string, symbol: string,
orderId: string, orderId: string,
clientOrderId?: string clientOrderId?: string,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/trade/orderInfo', { return this.postPrivate('/api/spot/v1/trade/orderInfo', {
symbol, symbol,
@@ -275,7 +370,7 @@ export class SpotClient extends BaseRestClient {
/** Get order history for a symbol */ /** Get order history for a symbol */
getOrderHistory( getOrderHistory(
symbol: string, symbol: string,
pagination?: Pagination pagination?: Pagination,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/trade/history', { return this.postPrivate('/api/spot/v1/trade/history', {
symbol, symbol,
@@ -287,7 +382,7 @@ export class SpotClient extends BaseRestClient {
getOrderFills( getOrderFills(
symbol: string, symbol: string,
orderId: string, orderId: string,
pagination?: Pagination pagination?: Pagination,
): Promise<APIResponse<any>> { ): Promise<APIResponse<any>> {
return this.postPrivate('/api/spot/v1/trade/fills', { return this.postPrivate('/api/spot/v1/trade/fills', {
symbol, symbol,
@@ -295,4 +390,47 @@ export class SpotClient extends BaseRestClient {
...pagination, ...pagination,
}); });
} }
/** Place plan order */
submitPlanOrder(
params: NewSpotPlanOrder,
): Promise<APIResponse<SpotOrderResult>> {
return this.postPrivate('/api/spot/v1/plan/placePlan', params);
}
/** Modify plan order */
modifyPlanOrder(
params: ModifySpotPlanOrder,
): Promise<APIResponse<SpotOrderResult>> {
return this.postPrivate('/api/spot/v1/plan/modifyPlan', params);
}
/** Cancel plan order */
cancelPlanOrder(
params: CancelSpotPlanOrderParams,
): Promise<APIResponse<string>> {
return this.postPrivate('/api/spot/v1/plan/cancelPlan', params);
}
/** Get current plan orders */
getCurrentPlanOrders(params: GetSpotPlanOrdersParams): Promise<
APIResponse<{
nextFlag: boolean;
endId: number;
orderList: SpotPlanOrder[];
}>
> {
return this.postPrivate('/api/spot/v1/plan/currentPlan', params);
}
/** Get history plan orders */
getHistoricPlanOrders(params: GetHistoricPlanOrdersParams): Promise<
APIResponse<{
nextFlag: boolean;
endId: number;
orderList: SpotPlanOrder[];
}>
> {
return this.postPrivate('/api/spot/v1/plan/historyPlan', params);
}
} }

View File

@@ -51,6 +51,8 @@ export interface NewFuturesOrder {
orderType: FuturesOrderType; orderType: FuturesOrderType;
timeInForceValue?: OrderTimeInForce; timeInForceValue?: OrderTimeInForce;
clientOid?: string; clientOid?: string;
reduceOnly?: boolean;
reverse?: boolean;
presetTakeProfitPrice?: string; presetTakeProfitPrice?: string;
presetStopLossPrice?: string; presetStopLossPrice?: string;
} }
@@ -82,6 +84,7 @@ export interface NewFuturesPlanOrder {
clientOid?: string; clientOid?: string;
presetTakeProfitPrice?: string; presetTakeProfitPrice?: string;
presetStopLossPrice?: string; presetStopLossPrice?: string;
reduceOnly?: string;
} }
export interface ModifyFuturesPlanOrder { export interface ModifyFuturesPlanOrder {
@@ -90,12 +93,13 @@ export interface ModifyFuturesPlanOrder {
symbol: string; symbol: string;
executePrice?: string; executePrice?: string;
triggerPrice: string; triggerPrice: string;
triggerType: string; triggerType: 'fill_price' | 'market_price';
orderType: FuturesOrderType; orderType: FuturesOrderType;
} }
export interface ModifyFuturesPlanOrderTPSL { export interface ModifyFuturesPlanOrderTPSL {
orderId: string; orderId?: string;
clientOid?: string;
marginCoin: string; marginCoin: string;
symbol: string; symbol: string;
presetTakeProfitPrice?: string; presetTakeProfitPrice?: string;
@@ -113,6 +117,7 @@ export interface NewFuturesPlanStopOrder {
holdSide: FuturesHoldSide; holdSide: FuturesHoldSide;
size?: string; size?: string;
rangeRate?: string; rangeRate?: string;
clientOid?: string;
} }
export interface NewFuturesPlanTrailingStopOrder { export interface NewFuturesPlanTrailingStopOrder {
@@ -123,6 +128,7 @@ export interface NewFuturesPlanTrailingStopOrder {
size?: string; size?: string;
side: FuturesOrderSide; side: FuturesOrderSide;
rangeRate?: string; rangeRate?: string;
clientOid?: string;
} }
export interface NewFuturesPlanPositionTPSL { export interface NewFuturesPlanPositionTPSL {
@@ -130,18 +136,23 @@ export interface NewFuturesPlanPositionTPSL {
marginCoin: string; marginCoin: string;
planType: FuturesPlanType; planType: FuturesPlanType;
triggerPrice: string; triggerPrice: string;
triggerType?: 'fill_price' | 'market_price';
holdSide: FuturesHoldSide; holdSide: FuturesHoldSide;
clientOid?: string;
} }
export interface ModifyFuturesPlanStopOrder { export interface ModifyFuturesPlanStopOrder {
orderId: string; orderId?: string;
clientOid?: string;
marginCoin: string; marginCoin: string;
symbol: string; symbol: string;
triggerPrice?: string; triggerPrice?: string;
planType: FuturesPlanType;
} }
export interface CancelFuturesPlanTPSL { export interface CancelFuturesPlanTPSL {
orderId: string; orderId?: string;
clientOid?: string;
symbol: string; symbol: string;
marginCoin: string; marginCoin: string;
planType: FuturesPlanType; planType: FuturesPlanType;

View File

@@ -9,3 +9,11 @@ export interface Pagination {
} }
export type OrderTimeInForce = 'normal' | 'post_only' | 'fok' | 'ioc'; export type OrderTimeInForce = 'normal' | 'post_only' | 'fok' | 'ioc';
export interface GetHistoricTradesParams {
symbol: string;
limit?: string;
tradeId?: string;
startTime?: string;
endTime?: string;
}

View File

@@ -10,6 +10,26 @@ export interface NewWalletTransfer {
clientOid?: string; clientOid?: string;
} }
export interface NewSpotSubTransfer {
fromType: WalletType;
toType: WalletType;
amount: string;
coin: string;
clientOid: string;
fromUserId: string;
toUserId: string;
}
export interface NewSpotWithdraw {
coin: string;
address: string;
chain: string;
tag?: string;
amount: string;
remark?: string;
clientOid?: string;
}
export interface NewSpotOrder { export interface NewSpotOrder {
symbol: string; symbol: string;
side: 'buy' | 'sell'; side: 'buy' | 'sell';
@@ -21,3 +41,67 @@ export interface NewSpotOrder {
} }
export type NewBatchSpotOrder = Omit<NewSpotOrder, 'symbol'>; export type NewBatchSpotOrder = Omit<NewSpotOrder, 'symbol'>;
export interface CancelSpotOrderV2 {
symbol: string;
orderId?: string;
clientOid?: string;
}
export interface BatchCancelSpotOrderV2 {
symbol: string;
orderIds?: string[];
clientOids?: string[];
}
export interface NewSpotPlanOrder {
symbol: string;
side: 'buy' | 'sell';
triggerPrice: number;
executePrice?: number;
size: number;
triggerType: 'fill_price' | 'market_price';
orderType: 'limit' | 'market';
clientOid?: string;
timeInForceValue?: string;
}
export interface NewSpotPlanOrder {
symbol: string;
side: 'buy' | 'sell';
triggerPrice: number;
executePrice?: number;
size: number;
triggerType: 'fill_price' | 'market_price';
orderType: 'limit' | 'market';
clientOid?: string;
timeInForceValue?: string;
}
export interface ModifySpotPlanOrder {
orderId?: string;
clientOid?: string;
triggerPrice: number;
executePrice?: number;
size?: string;
orderType: 'limit' | 'market';
}
export interface CancelSpotPlanOrderParams {
orderId?: string;
clientOid?: string;
}
export interface GetSpotPlanOrdersParams {
symbol: string;
pageSize: string;
lastEndId?: string;
}
export interface GetHistoricPlanOrdersParams {
symbol: string;
pageSize: string;
lastEndId?: string;
startTime: string;
endTime: string;
}

View File

@@ -4,6 +4,15 @@ import {
FuturesMarginMode, FuturesMarginMode,
} from '../request'; } from '../request';
export interface FuturesMarketTrade {
tradeId: string;
price: string;
size: string;
side: 'buy' | 'sell';
timestamp: string;
symbol: string;
}
export interface FuturesAccount { export interface FuturesAccount {
marginCoin: string; marginCoin: string;
locked: number; locked: number;

View File

@@ -4,3 +4,13 @@ export interface APIResponse<T> {
msg: 'success' | string; msg: 'success' | string;
requestTime: number; requestTime: number;
} }
export interface VIPFeeRate {
level: number;
dealAmount: string;
assetAmount: string;
takerFeeRate?: string;
makerFeeRate?: number;
withdrawAmount: string;
withdrawAmountUSDT: string;
}

View File

@@ -20,3 +20,31 @@ export interface SymbolRules {
quantityScale: string; quantityScale: string;
status: string; status: string;
} }
export interface SpotOrderResult {
orderId: string;
clientOrderId: string;
}
export interface SpotPlanOrder {
orderId: string;
clientOid: string;
symbol: string;
size: string;
executePrice: string;
triggerPrice: string;
status: string;
orderType: string;
side: string;
triggerType: string;
enterPointSource: string;
cTime: number;
}
export interface SpotMarketTrade {
symbol: string;
tradeId: string;
side: 'buy' | 'sell';
fillPrice: string;
fillQuantity: string;
fillTime: string;
}

View File

@@ -44,7 +44,7 @@ export default abstract class BaseRestClient {
*/ */
constructor( constructor(
restOptions: RestClientOptions = {}, restOptions: RestClientOptions = {},
networkOptions: AxiosRequestConfig = {} networkOptions: AxiosRequestConfig = {},
) { ) {
this.options = { this.options = {
recvWindow: 5000, recvWindow: 5000,
@@ -77,7 +77,7 @@ export default abstract class BaseRestClient {
credentials.some((v) => typeof v === 'string') credentials.some((v) => typeof v === 'string')
) { ) {
throw new Error( throw new Error(
'API Key, Secret & Passphrase are ALL required to use the authenticated REST client' 'API Key, Secret & Passphrase are ALL required to use the authenticated REST client',
); );
} }
} }
@@ -109,11 +109,11 @@ export default abstract class BaseRestClient {
method: Method, method: Method,
endpoint: string, endpoint: string,
params?: any, params?: any,
isPublicApi?: boolean isPublicApi?: boolean,
): Promise<any> { ): Promise<any> {
// Sanity check to make sure it's only ever prefixed by one forward slash // Sanity check to make sure it's only ever prefixed by one forward slash
const requestUrl = [this.baseUrl, endpoint].join( const requestUrl = [this.baseUrl, endpoint].join(
endpoint.startsWith('/') ? '' : '/' endpoint.startsWith('/') ? '' : '/',
); );
// Build a request and handle signature process // Build a request and handle signature process
@@ -122,7 +122,7 @@ export default abstract class BaseRestClient {
endpoint, endpoint,
requestUrl, requestUrl,
params, params,
isPublicApi isPublicApi,
); );
// console.log('full request: ', options); // console.log('full request: ', options);
@@ -188,7 +188,7 @@ export default abstract class BaseRestClient {
data: T, data: T,
endpoint: string, endpoint: string,
method: Method, method: Method,
signMethod: SignMethod signMethod: SignMethod,
): Promise<SignedRequest<T>> { ): Promise<SignedRequest<T>> {
const timestamp = Date.now(); const timestamp = Date.now();
@@ -228,7 +228,7 @@ export default abstract class BaseRestClient {
console.error( console.error(
new Date(), new Date(),
neverGuard(signMethod, `Unhandled sign method: "${signMessage}"`) neverGuard(signMethod, `Unhandled sign method: "${signMessage}"`),
); );
return res; return res;
@@ -239,21 +239,21 @@ export default abstract class BaseRestClient {
endpoint: string, endpoint: string,
signMethod: SignMethod, signMethod: SignMethod,
params?: TParams, params?: TParams,
isPublicApi?: true isPublicApi?: true,
): Promise<UnsignedRequest<TParams>>; ): Promise<UnsignedRequest<TParams>>;
private async prepareSignParams<TParams extends object | undefined>( private async prepareSignParams<TParams extends object | undefined>(
method: Method, method: Method,
endpoint: string, endpoint: string,
signMethod: SignMethod, signMethod: SignMethod,
params?: TParams, params?: TParams,
isPublicApi?: false | undefined isPublicApi?: false | undefined,
): Promise<SignedRequest<TParams>>; ): Promise<SignedRequest<TParams>>;
private async prepareSignParams<TParams extends object | undefined>( private async prepareSignParams<TParams extends object | undefined>(
method: Method, method: Method,
endpoint: string, endpoint: string,
signMethod: SignMethod, signMethod: SignMethod,
params?: TParams, params?: TParams,
isPublicApi?: boolean isPublicApi?: boolean,
) { ) {
if (isPublicApi) { if (isPublicApi) {
return { return {
@@ -275,7 +275,7 @@ export default abstract class BaseRestClient {
endpoint: string, endpoint: string,
url: string, url: string,
params?: any, params?: any,
isPublicApi?: boolean isPublicApi?: boolean,
): Promise<AxiosRequestConfig> { ): Promise<AxiosRequestConfig> {
const options: AxiosRequestConfig = { const options: AxiosRequestConfig = {
...this.globalRequestOptions, ...this.globalRequestOptions,
@@ -301,27 +301,33 @@ export default abstract class BaseRestClient {
endpoint, endpoint,
'bitget', 'bitget',
params, params,
isPublicApi isPublicApi,
); );
if (!options.headers) { const authHeaders = {
options.headers = {}; 'ACCESS-KEY': this.apiKey,
} 'ACCESS-PASSPHRASE': this.apiPass,
options.headers['ACCESS-KEY'] = this.apiKey; 'ACCESS-TIMESTAMP': signResult.timestamp,
options.headers['ACCESS-PASSPHRASE'] = this.apiPass; 'ACCESS-SIGN': signResult.sign,
options.headers['ACCESS-TIMESTAMP'] = signResult.timestamp; };
options.headers['ACCESS-SIGN'] = signResult.sign;
options.headers['Content-Type'] = 'application/json';
if (method === 'GET') { if (method === 'GET') {
return { return {
...options, ...options,
headers: {
...authHeaders,
...options.headers,
},
url: options.url + signResult.queryParamsWithSign, url: options.url + signResult.queryParamsWithSign,
}; };
} }
return { return {
...options, ...options,
headers: {
...authHeaders,
...options.headers,
},
data: params, data: params,
}; };
} }

View File

@@ -82,7 +82,7 @@ export default class WsStore<WsKey extends string> {
if (this.hasExistingActiveConnection(key)) { if (this.hasExistingActiveConnection(key)) {
this.logger.warning( this.logger.warning(
'WsStore setConnection() overwriting existing open connection: ', 'WsStore setConnection() overwriting existing open connection: ',
this.getWs(key) this.getWs(key),
); );
} }
this.wsState[key] = { this.wsState[key] = {
@@ -98,7 +98,7 @@ export default class WsStore<WsKey extends string> {
const ws = this.getWs(key); const ws = this.getWs(key);
this.logger.warning( this.logger.warning(
'WsStore deleting state for connection still open: ', 'WsStore deleting state for connection still open: ',
ws ws,
); );
ws?.close(); ws?.close();
} }
@@ -119,7 +119,7 @@ export default class WsStore<WsKey extends string> {
if (this.isWsOpen(key)) { if (this.isWsOpen(key)) {
this.logger.warning( this.logger.warning(
'WsStore setConnection() overwriting existing open connection: ', 'WsStore setConnection() overwriting existing open connection: ',
this.getWs(key) this.getWs(key),
); );
} }

View File

@@ -11,7 +11,7 @@ function _arrayBufferToBase64(buffer: ArrayBuffer) {
export async function signMessage( export async function signMessage(
message: string, message: string,
secret: string, secret: string,
method: 'hex' | 'base64' method: 'hex' | 'base64',
): Promise<string> { ): Promise<string> {
const encoder = new TextEncoder(); const encoder = new TextEncoder();
const key = await window.crypto.subtle.importKey( const key = await window.crypto.subtle.importKey(
@@ -19,20 +19,20 @@ export async function signMessage(
encoder.encode(secret), encoder.encode(secret),
{ name: 'HMAC', hash: { name: 'SHA-256' } }, { name: 'HMAC', hash: { name: 'SHA-256' } },
false, false,
['sign'] ['sign'],
); );
const signature = await window.crypto.subtle.sign( const signature = await window.crypto.subtle.sign(
'HMAC', 'HMAC',
key, key,
encoder.encode(message) encoder.encode(message),
); );
switch (method) { switch (method) {
case 'hex': { case 'hex': {
return Array.prototype.map return Array.prototype.map
.call(new Uint8Array(signature), (x: any) => .call(new Uint8Array(signature), (x: any) =>
('00' + x.toString(16)).slice(-2) ('00' + x.toString(16)).slice(-2),
) )
.join(''); .join('');
} }

View File

@@ -4,7 +4,7 @@ import { createHmac } from 'crypto';
export async function signMessage( export async function signMessage(
message: string, message: string,
secret: string, secret: string,
method: 'hex' | 'base64' method: 'hex' | 'base64',
): Promise<string> { ): Promise<string> {
const hmac = createHmac('sha256', secret).update(message); const hmac = createHmac('sha256', secret).update(message);

View File

@@ -30,7 +30,7 @@ export interface RestClientOptions {
export function serializeParams<T extends object | undefined = {}>( export function serializeParams<T extends object | undefined = {}>(
params: T, params: T,
strict_validation = false, strict_validation = false,
prefixWith: string = '' prefixWith: string = '',
): string { ): string {
if (!params) { if (!params) {
return ''; return '';
@@ -42,7 +42,7 @@ export function serializeParams<T extends object | undefined = {}>(
const value = params[key]; const value = params[key];
if (strict_validation === true && typeof value === 'undefined') { if (strict_validation === true && typeof value === 'undefined') {
throw new Error( throw new Error(
'Failed to sign API request due to undefined parameter' 'Failed to sign API request due to undefined parameter',
); );
} }
return `${key}=${value}`; return `${key}=${value}`;
@@ -55,7 +55,7 @@ export function serializeParams<T extends object | undefined = {}>(
export function getRestBaseUrl( export function getRestBaseUrl(
useTestnet: boolean, useTestnet: boolean,
restInverseOptions: RestClientOptions restInverseOptions: RestClientOptions,
): string { ): string {
const exchangeBaseUrls = { const exchangeBaseUrls = {
livenet: 'https://api.bitget.com', livenet: 'https://api.bitget.com',

View File

@@ -36,7 +36,7 @@ function isWsChannelEvent(event: WsBaseEvent): event is WsSnapshotChannelEvent {
/** TypeGuard: event is an account update (balance) */ /** TypeGuard: event is an account update (balance) */
export function isWsAccountSnapshotEvent( export function isWsAccountSnapshotEvent(
event: unknown event: unknown,
): event is WsSnapshotAccountEvent { ): event is WsSnapshotAccountEvent {
return ( return (
isWsSnapshotEvent(event) && isWsSnapshotEvent(event) &&
@@ -48,7 +48,7 @@ export function isWsAccountSnapshotEvent(
/** TypeGuard: event is a positions update */ /** TypeGuard: event is a positions update */
export function isWsPositionsSnapshotEvent( export function isWsPositionsSnapshotEvent(
event: unknown event: unknown,
): event is WsSnapshotPositionsEvent { ): event is WsSnapshotPositionsEvent {
return ( return (
isWsSnapshotEvent(event) && isWsSnapshotEvent(event) &&
@@ -60,14 +60,14 @@ export function isWsPositionsSnapshotEvent(
/** TypeGuard: event is a UMCBL account update (balance) */ /** TypeGuard: event is a UMCBL account update (balance) */
export function isWsFuturesAccountSnapshotEvent( export function isWsFuturesAccountSnapshotEvent(
event: unknown event: unknown,
): event is WsAccountSnapshotUMCBL { ): event is WsAccountSnapshotUMCBL {
return isWsAccountSnapshotEvent(event) && event.arg.instType === 'umcbl'; return isWsAccountSnapshotEvent(event) && event.arg.instType === 'umcbl';
} }
/** TypeGuard: event is a UMCBL positions update */ /** TypeGuard: event is a UMCBL positions update */
export function isWsFuturesPositionsSnapshotEvent( export function isWsFuturesPositionsSnapshotEvent(
event: unknown event: unknown,
): event is WSPositionSnapshotUMCBL { ): event is WSPositionSnapshotUMCBL {
return isWsPositionsSnapshotEvent(event) && event.arg.instType === 'umcbl'; return isWsPositionsSnapshotEvent(event) && event.arg.instType === 'umcbl';
} }

View File

@@ -11,7 +11,7 @@ import { BitgetInstType, WsTopicSubscribeEventArgs } from './WsStore';
*/ */
type NetworkMap< type NetworkMap<
TRequiredKeys extends string, TRequiredKeys extends string,
TOptionalKeys extends string | undefined = undefined TOptionalKeys extends string | undefined = undefined,
> = Record<TRequiredKeys, string> & > = Record<TRequiredKeys, string> &
(TOptionalKeys extends string (TOptionalKeys extends string
? Record<TOptionalKeys, string | undefined> ? Record<TOptionalKeys, string | undefined>
@@ -55,14 +55,14 @@ export const PUBLIC_WS_KEYS = [] as WsKey[];
export const PRIVATE_TOPICS = ['account', 'orders', 'positions', 'ordersAlgo']; export const PRIVATE_TOPICS = ['account', 'orders', 'positions', 'ordersAlgo'];
export function isPrivateChannel<TChannel extends string>( export function isPrivateChannel<TChannel extends string>(
channel: TChannel channel: TChannel,
): boolean { ): boolean {
return PRIVATE_TOPICS.includes(channel); return PRIVATE_TOPICS.includes(channel);
} }
export function getWsKeyForTopic( export function getWsKeyForTopic(
subscribeEvent: WsTopicSubscribeEventArgs, subscribeEvent: WsTopicSubscribeEventArgs,
isPrivate?: boolean isPrivate?: boolean,
): WsKey { ): WsKey {
const instType = subscribeEvent.instType.toUpperCase() as BitgetInstType; const instType = subscribeEvent.instType.toUpperCase() as BitgetInstType;
switch (instType) { switch (instType) {
@@ -78,7 +78,7 @@ export function getWsKeyForTopic(
default: { default: {
throw neverGuard( throw neverGuard(
instType, instType,
`getWsKeyForTopic(): Unhandled market ${'instrumentId'}` `getWsKeyForTopic(): Unhandled market ${'instrumentId'}`,
); );
} }
} }
@@ -110,14 +110,14 @@ export async function getWsAuthSignature(
apiKey: string | undefined, apiKey: string | undefined,
apiSecret: string | undefined, apiSecret: string | undefined,
apiPass: string | undefined, apiPass: string | undefined,
recvWindow: number = 0 recvWindow: number = 0,
): Promise<{ ): Promise<{
expiresAt: number; expiresAt: number;
signature: string; signature: string;
}> { }> {
if (!apiKey || !apiSecret || !apiPass) { if (!apiKey || !apiSecret || !apiPass) {
throw new Error( throw new Error(
`Cannot auth - missing api key, secret or passcode in config` `Cannot auth - missing api key, secret or passcode in config`,
); );
} }
const signatureExpiresAt = ((Date.now() + recvWindow) / 1000).toFixed(0); const signatureExpiresAt = ((Date.now() + recvWindow) / 1000).toFixed(0);
@@ -125,7 +125,7 @@ export async function getWsAuthSignature(
const signature = await signMessage( const signature = await signMessage(
signatureExpiresAt + 'GET' + '/user/verify', signatureExpiresAt + 'GET' + '/user/verify',
apiSecret, apiSecret,
'base64' 'base64',
); );
return { return {

View File

@@ -61,7 +61,7 @@ interface WebsocketClientEvents {
export declare interface WebsocketClient { export declare interface WebsocketClient {
on<U extends keyof WebsocketClientEvents>( on<U extends keyof WebsocketClientEvents>(
event: U, event: U,
listener: WebsocketClientEvents[U] listener: WebsocketClientEvents[U],
): this; ): this;
emit<U extends keyof WebsocketClientEvents>( emit<U extends keyof WebsocketClientEvents>(
@@ -77,7 +77,7 @@ export class WebsocketClient extends EventEmitter {
constructor( constructor(
options: WSClientConfigurableOptions, options: WSClientConfigurableOptions,
logger?: typeof DefaultLogger logger?: typeof DefaultLogger,
) { ) {
super(); super();
@@ -100,7 +100,7 @@ export class WebsocketClient extends EventEmitter {
*/ */
public subscribe( public subscribe(
wsTopics: WsTopicSubscribeEventArgs[] | WsTopicSubscribeEventArgs, wsTopics: WsTopicSubscribeEventArgs[] | WsTopicSubscribeEventArgs,
isPrivateTopic?: boolean isPrivateTopic?: boolean,
) { ) {
const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics]; const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
@@ -122,7 +122,7 @@ export class WebsocketClient extends EventEmitter {
if (!isAuthenticated) { if (!isAuthenticated) {
return this.requestSubscribeTopics( return this.requestSubscribeTopics(
wsKey, wsKey,
topics.filter((topic) => !isPrivateChannel(topic.channel)) topics.filter((topic) => !isPrivateChannel(topic.channel)),
); );
} }
return this.requestSubscribeTopics(wsKey, topics); return this.requestSubscribeTopics(wsKey, topics);
@@ -132,11 +132,11 @@ export class WebsocketClient extends EventEmitter {
if ( if (
!this.wsStore.isConnectionState( !this.wsStore.isConnectionState(
wsKey, wsKey,
WsConnectionStateEnum.CONNECTING WsConnectionStateEnum.CONNECTING,
) && ) &&
!this.wsStore.isConnectionState( !this.wsStore.isConnectionState(
wsKey, wsKey,
WsConnectionStateEnum.RECONNECTING WsConnectionStateEnum.RECONNECTING,
) )
) { ) {
return this.connect(wsKey); return this.connect(wsKey);
@@ -151,11 +151,11 @@ export class WebsocketClient extends EventEmitter {
*/ */
public unsubscribe( public unsubscribe(
wsTopics: WsTopicSubscribeEventArgs[] | WsTopicSubscribeEventArgs, wsTopics: WsTopicSubscribeEventArgs[] | WsTopicSubscribeEventArgs,
isPrivateTopic?: boolean isPrivateTopic?: boolean,
) { ) {
const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics]; const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics];
topics.forEach((topic) => topics.forEach((topic) =>
this.wsStore.deleteTopic(getWsKeyForTopic(topic, isPrivateTopic), topic) this.wsStore.deleteTopic(getWsKeyForTopic(topic, isPrivateTopic), topic),
); );
// TODO: should this really happen on each wsKey?? seems weird // TODO: should this really happen on each wsKey?? seems weird
@@ -207,7 +207,7 @@ export class WebsocketClient extends EventEmitter {
if (this.wsStore.isWsOpen(wsKey)) { if (this.wsStore.isWsOpen(wsKey)) {
this.logger.error( this.logger.error(
'Refused to connect to ws with existing active connection', 'Refused to connect to ws with existing active connection',
{ ...LOGGER_CATEGORY, wsKey } { ...LOGGER_CATEGORY, wsKey },
); );
return this.wsStore.getWs(wsKey); return this.wsStore.getWs(wsKey);
} }
@@ -217,7 +217,7 @@ export class WebsocketClient extends EventEmitter {
) { ) {
this.logger.error( this.logger.error(
'Refused to connect to ws, connection attempt already active', 'Refused to connect to ws, connection attempt already active',
{ ...LOGGER_CATEGORY, wsKey } { ...LOGGER_CATEGORY, wsKey },
); );
return; return;
} }
@@ -260,7 +260,7 @@ export class WebsocketClient extends EventEmitter {
`${context} due to unexpected response error: "${ `${context} due to unexpected response error: "${
error?.msg || error?.message || error error?.msg || error?.message || error
}"`, }"`,
{ ...LOGGER_CATEGORY, wsKey, error } { ...LOGGER_CATEGORY, wsKey, error },
); );
break; break;
} }
@@ -278,7 +278,7 @@ export class WebsocketClient extends EventEmitter {
apiKey, apiKey,
apiSecret, apiSecret,
apiPass, apiPass,
recvWindow recvWindow,
); );
this.logger.info(`Sending auth request...`, { this.logger.info(`Sending auth request...`, {
@@ -375,7 +375,7 @@ export class WebsocketClient extends EventEmitter {
*/ */
private requestSubscribeTopics( private requestSubscribeTopics(
wsKey: WsKey, wsKey: WsKey,
topics: WsTopicSubscribeEventArgs[] topics: WsTopicSubscribeEventArgs[],
) { ) {
if (!topics.length) { if (!topics.length) {
return; return;
@@ -384,7 +384,7 @@ export class WebsocketClient extends EventEmitter {
const maxTopicsPerEvent = getMaxTopicsPerSubscribeEvent(wsKey); const maxTopicsPerEvent = getMaxTopicsPerSubscribeEvent(wsKey);
if (maxTopicsPerEvent && topics.length > maxTopicsPerEvent) { if (maxTopicsPerEvent && topics.length > maxTopicsPerEvent) {
this.logger.silly( this.logger.silly(
`Subscribing to topics in batches of ${maxTopicsPerEvent}` `Subscribing to topics in batches of ${maxTopicsPerEvent}`,
); );
for (var i = 0; i < topics.length; i += maxTopicsPerEvent) { for (var i = 0; i < topics.length; i += maxTopicsPerEvent) {
const batch = topics.slice(i, i + maxTopicsPerEvent); const batch = topics.slice(i, i + maxTopicsPerEvent);
@@ -392,7 +392,7 @@ export class WebsocketClient extends EventEmitter {
this.requestSubscribeTopics(wsKey, batch); this.requestSubscribeTopics(wsKey, batch);
} }
this.logger.silly( this.logger.silly(
`Finished batch subscribing to ${topics.length} topics` `Finished batch subscribing to ${topics.length} topics`,
); );
return; return;
} }
@@ -410,7 +410,7 @@ export class WebsocketClient extends EventEmitter {
*/ */
private requestUnsubscribeTopics( private requestUnsubscribeTopics(
wsKey: WsKey, wsKey: WsKey,
topics: WsTopicSubscribeEventArgs[] topics: WsTopicSubscribeEventArgs[],
) { ) {
if (!topics.length) { if (!topics.length) {
return; return;
@@ -419,7 +419,7 @@ export class WebsocketClient extends EventEmitter {
const maxTopicsPerEvent = getMaxTopicsPerSubscribeEvent(wsKey); const maxTopicsPerEvent = getMaxTopicsPerSubscribeEvent(wsKey);
if (maxTopicsPerEvent && topics.length > maxTopicsPerEvent) { if (maxTopicsPerEvent && topics.length > maxTopicsPerEvent) {
this.logger.silly( this.logger.silly(
`Unsubscribing to topics in batches of ${maxTopicsPerEvent}` `Unsubscribing to topics in batches of ${maxTopicsPerEvent}`,
); );
for (var i = 0; i < topics.length; i += maxTopicsPerEvent) { for (var i = 0; i < topics.length; i += maxTopicsPerEvent) {
const batch = topics.slice(i, i + maxTopicsPerEvent); const batch = topics.slice(i, i + maxTopicsPerEvent);
@@ -427,7 +427,7 @@ export class WebsocketClient extends EventEmitter {
this.requestUnsubscribeTopics(wsKey, batch); this.requestUnsubscribeTopics(wsKey, batch);
} }
this.logger.silly( this.logger.silly(
`Finished batch unsubscribing to ${topics.length} topics` `Finished batch unsubscribing to ${topics.length} topics`,
); );
return; return;
} }
@@ -449,13 +449,13 @@ export class WebsocketClient extends EventEmitter {
}); });
if (!wsKey) { if (!wsKey) {
throw new Error( throw new Error(
'Cannot send message due to no known websocket for this wsKey' 'Cannot send message due to no known websocket for this wsKey',
); );
} }
const ws = this.getWs(wsKey); const ws = this.getWs(wsKey);
if (!ws) { if (!ws) {
throw new Error( throw new Error(
`${wsKey} socket not connected yet, call "connectAll()" first then try again when the "open" event arrives` `${wsKey} socket not connected yet, call "connectAll()" first then try again when the "open" event arrives`,
); );
} }
ws.send(wsMessage); ws.send(wsMessage);
@@ -512,13 +512,13 @@ export class WebsocketClient extends EventEmitter {
// Private topics will be resubscribed to once reconnected // Private topics will be resubscribed to once reconnected
const topics = [...this.wsStore.getTopics(wsKey)]; const topics = [...this.wsStore.getTopics(wsKey)];
const publicTopics = topics.filter( const publicTopics = topics.filter(
(topic) => !isPrivateChannel(topic.channel) (topic) => !isPrivateChannel(topic.channel),
); );
this.requestSubscribeTopics(wsKey, publicTopics); this.requestSubscribeTopics(wsKey, publicTopics);
this.wsStore.get(wsKey, true)!.activePingTimer = setInterval( this.wsStore.get(wsKey, true)!.activePingTimer = setInterval(
() => this.ping(wsKey), () => this.ping(wsKey),
this.options.pingInterval this.options.pingInterval,
); );
} }
@@ -529,7 +529,7 @@ export class WebsocketClient extends EventEmitter {
const topics = [...this.wsStore.getTopics(wsKey)]; const topics = [...this.wsStore.getTopics(wsKey)];
const privateTopics = topics.filter((topic) => const privateTopics = topics.filter((topic) =>
isPrivateChannel(topic.channel) isPrivateChannel(topic.channel),
); );
if (privateTopics.length) { if (privateTopics.length) {
@@ -665,7 +665,7 @@ export class WebsocketClient extends EventEmitter {
public subscribeTopic( public subscribeTopic(
instType: BitgetInstType, instType: BitgetInstType,
topic: WsTopic, topic: WsTopic,
instId: string = 'default' instId: string = 'default',
) { ) {
return this.subscribe({ return this.subscribe({
instType, instType,
@@ -683,7 +683,7 @@ export class WebsocketClient extends EventEmitter {
public unsubscribeTopic( public unsubscribeTopic(
instType: BitgetInstType, instType: BitgetInstType,
topic: WsTopic, topic: WsTopic,
instId: string = 'default' instId: string = 'default',
) { ) {
return this.unsubscribe({ return this.unsubscribe({
instType, instType,

View File

@@ -27,7 +27,7 @@ describe('Private Broker REST API GET Endpoints', () => {
it('getBrokerInfo()', async () => { it('getBrokerInfo()', async () => {
try { try {
expect(await api.getBrokerInfo()).toMatchObject( expect(await api.getBrokerInfo()).toMatchObject(
sucessEmptyResponseObject() sucessEmptyResponseObject(),
); );
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -39,7 +39,7 @@ describe('Private Broker REST API GET Endpoints', () => {
it('getSubAccounts()', async () => { it('getSubAccounts()', async () => {
try { try {
expect(await api.getSubAccounts()).toMatchObject( expect(await api.getSubAccounts()).toMatchObject(
sucessEmptyResponseObject() sucessEmptyResponseObject(),
); );
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -51,7 +51,7 @@ describe('Private Broker REST API GET Endpoints', () => {
it('getSubEmail()', async () => { it('getSubEmail()', async () => {
try { try {
expect(await api.getSubEmail(subUid)).toMatchObject( expect(await api.getSubEmail(subUid)).toMatchObject(
sucessEmptyResponseObject() sucessEmptyResponseObject(),
); );
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -63,7 +63,7 @@ describe('Private Broker REST API GET Endpoints', () => {
it('getSubSpotAssets()', async () => { it('getSubSpotAssets()', async () => {
try { try {
expect(await api.getSubSpotAssets(subUid)).toMatchObject( expect(await api.getSubSpotAssets(subUid)).toMatchObject(
sucessEmptyResponseObject() sucessEmptyResponseObject(),
); );
} catch (e) { } catch (e) {
// expect(e.body).toBeNull(); // expect(e.body).toBeNull();
@@ -76,7 +76,7 @@ describe('Private Broker REST API GET Endpoints', () => {
it('getSubFutureAssets()', async () => { it('getSubFutureAssets()', async () => {
try { try {
expect(await api.getSubFutureAssets(subUid, 'usdt')).toMatchObject( expect(await api.getSubFutureAssets(subUid, 'usdt')).toMatchObject(
sucessEmptyResponseObject() sucessEmptyResponseObject(),
); );
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -88,7 +88,7 @@ describe('Private Broker REST API GET Endpoints', () => {
it('getSubDepositAddress()', async () => { it('getSubDepositAddress()', async () => {
try { try {
expect(await api.getSubDepositAddress(subUid, coin)).toMatchObject( expect(await api.getSubDepositAddress(subUid, coin)).toMatchObject(
sucessEmptyResponseObject() sucessEmptyResponseObject(),
); );
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -100,7 +100,7 @@ describe('Private Broker REST API GET Endpoints', () => {
it('getSubAPIKeys()', async () => { it('getSubAPIKeys()', async () => {
try { try {
expect(await api.getSubAPIKeys(subUid)).toMatchObject( expect(await api.getSubAPIKeys(subUid)).toMatchObject(
sucessEmptyResponseObject() sucessEmptyResponseObject(),
); );
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({

View File

@@ -27,7 +27,7 @@ describe('Private Broker REST API POST Endpoints', () => {
it('createSubAccount()', async () => { it('createSubAccount()', async () => {
try { try {
expect(await api.createSubAccount('test1')).toMatchObject( expect(await api.createSubAccount('test1')).toMatchObject(
sucessEmptyResponseObject() sucessEmptyResponseObject(),
); );
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -39,7 +39,7 @@ describe('Private Broker REST API POST Endpoints', () => {
it('modifySubAccount()', async () => { it('modifySubAccount()', async () => {
try { try {
expect( expect(
await api.modifySubAccount('test1', 'spot_trade,transfer', 'normal') await api.modifySubAccount('test1', 'spot_trade,transfer', 'normal'),
).toMatchObject(sucessEmptyResponseObject()); ).toMatchObject(sucessEmptyResponseObject());
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -51,7 +51,7 @@ describe('Private Broker REST API POST Endpoints', () => {
it('modifySubEmail()', async () => { it('modifySubEmail()', async () => {
try { try {
expect( expect(
await api.modifySubEmail('test1', 'ASDFASDF@LKMASDF.COM') await api.modifySubEmail('test1', 'ASDFASDF@LKMASDF.COM'),
).toMatchObject(sucessEmptyResponseObject()); ).toMatchObject(sucessEmptyResponseObject());
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -69,7 +69,7 @@ describe('Private Broker REST API POST Endpoints', () => {
chain: 'TRC20', chain: 'TRC20',
coin: 'USDT', coin: 'USDT',
subUid, subUid,
}) }),
).toMatchObject(sucessEmptyResponseObject()); ).toMatchObject(sucessEmptyResponseObject());
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -81,7 +81,7 @@ describe('Private Broker REST API POST Endpoints', () => {
it('setSubDepositAutoTransfer()', async () => { it('setSubDepositAutoTransfer()', async () => {
try { try {
expect( expect(
await api.setSubDepositAutoTransfer(subUid, 'USDT', 'spot') await api.setSubDepositAutoTransfer(subUid, 'USDT', 'spot'),
).toMatchObject(sucessEmptyResponseObject()); ).toMatchObject(sucessEmptyResponseObject());
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -97,8 +97,8 @@ describe('Private Broker REST API POST Endpoints', () => {
subUid, subUid,
'passphrase12345', 'passphrase12345',
'remark', 'remark',
'10.0.0.1' '10.0.0.1',
) ),
).toMatchObject(sucessEmptyResponseObject()); ).toMatchObject(sucessEmptyResponseObject());
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -114,7 +114,7 @@ describe('Private Broker REST API POST Endpoints', () => {
apikey: '12345', apikey: '12345',
subUid, subUid,
remark: 'test', remark: 'test',
}) }),
).toMatchObject(sucessEmptyResponseObject()); ).toMatchObject(sucessEmptyResponseObject());
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({

View File

@@ -57,7 +57,7 @@ describe('Private Futures REST API GET Endpoints', () => {
it('getOpenCount()', async () => { it('getOpenCount()', async () => {
try { try {
expect( expect(
await api.getOpenCount(symbol, marginCoin, 20000, 1) await api.getOpenCount(symbol, marginCoin, 20000, 1),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: { data: {
@@ -102,7 +102,7 @@ describe('Private Futures REST API GET Endpoints', () => {
endTime: to, endTime: to,
marginCoin, marginCoin,
symbol, symbol,
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: { data: {
@@ -125,7 +125,7 @@ describe('Private Futures REST API GET Endpoints', () => {
startTime: from, startTime: from,
endTime: to, endTime: to,
productType: 'umcbl', productType: 'umcbl',
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: { data: {
@@ -180,7 +180,7 @@ describe('Private Futures REST API GET Endpoints', () => {
it('getProductTypeOrderHistory()', async () => { it('getProductTypeOrderHistory()', async () => {
try { try {
expect( expect(
await api.getProductTypeOrderHistory('umcbl', from, to, '10') await api.getProductTypeOrderHistory('umcbl', from, to, '10'),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: expect.any(Object), data: expect.any(Object),
@@ -223,7 +223,7 @@ describe('Private Futures REST API GET Endpoints', () => {
await api.getProductTypeOrderFills('umcbl', { await api.getProductTypeOrderFills('umcbl', {
startTime: from, startTime: from,
endTime: to, endTime: to,
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: expect.any(Object), data: expect.any(Object),
@@ -253,7 +253,7 @@ describe('Private Futures REST API GET Endpoints', () => {
startTime: from, startTime: from,
endTime: to, endTime: to,
symbol, symbol,
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: expect.any(Object), data: expect.any(Object),
@@ -267,7 +267,7 @@ describe('Private Futures REST API GET Endpoints', () => {
it('getCopyTraderOpenOrder()', async () => { it('getCopyTraderOpenOrder()', async () => {
try { try {
expect( expect(
await api.getCopyTraderOpenOrder(symbol, 'umcbl', 1, 0) await api.getCopyTraderOpenOrder(symbol, 'umcbl', 1, 0),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: expect.any(Object), data: expect.any(Object),
@@ -282,7 +282,7 @@ describe('Private Futures REST API GET Endpoints', () => {
it('getCopyFollowersOpenOrder()', async () => { it('getCopyFollowersOpenOrder()', async () => {
try { try {
expect( expect(
await api.getCopyFollowersOpenOrder(symbol, 'umcbl', 1, 0) await api.getCopyFollowersOpenOrder(symbol, 'umcbl', 1, 0),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: expect.any(Object), data: expect.any(Object),
@@ -300,7 +300,7 @@ describe('Private Futures REST API GET Endpoints', () => {
{ {
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: expect.any(Object), data: expect.any(Object),
} },
); );
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -342,8 +342,8 @@ describe('Private Futures REST API GET Endpoints', () => {
marginCoin, marginCoin,
from, from,
1, 1,
1 1,
) ),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: expect.any(Object), data: expect.any(Object),
@@ -358,7 +358,7 @@ describe('Private Futures REST API GET Endpoints', () => {
it('getCopyTraderHistoricProfitDetail()', async () => { it('getCopyTraderHistoricProfitDetail()', async () => {
try { try {
expect( expect(
await api.getCopyTraderHistoricProfitDetail(marginCoin, from, 1, 1) await api.getCopyTraderHistoricProfitDetail(marginCoin, from, 1, 1),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: expect.any(Object), data: expect.any(Object),

View File

@@ -53,7 +53,7 @@ describe('Private Futures REST API POST Endpoints', () => {
it('setMarginMode()', async () => { it('setMarginMode()', async () => {
try { try {
expect( expect(
await api.setMarginMode(symbol, marginCoin, 'crossed') await api.setMarginMode(symbol, marginCoin, 'crossed'),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -76,7 +76,7 @@ describe('Private Futures REST API POST Endpoints', () => {
symbol, symbol,
size: '1', size: '1',
side: 'open_long', side: 'open_long',
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -100,7 +100,7 @@ describe('Private Futures REST API POST Endpoints', () => {
size: '1', size: '1',
side: 'open_long', side: 'open_long',
}, },
]) ]),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -115,7 +115,7 @@ describe('Private Futures REST API POST Endpoints', () => {
it('cancelOrder()', async () => { it('cancelOrder()', async () => {
try { try {
expect( expect(
await api.cancelOrder(symbol, marginCoin, '1234656') await api.cancelOrder(symbol, marginCoin, '1234656'),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -130,7 +130,7 @@ describe('Private Futures REST API POST Endpoints', () => {
it('batchCancelOrder()', async () => { it('batchCancelOrder()', async () => {
try { try {
expect( expect(
await api.batchCancelOrder(symbol, marginCoin, ['1234656']) await api.batchCancelOrder(symbol, marginCoin, ['1234656']),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -164,7 +164,7 @@ describe('Private Futures REST API POST Endpoints', () => {
symbol, symbol,
triggerPrice: '1000', triggerPrice: '1000',
triggerType: 'market_price', triggerType: 'market_price',
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -187,7 +187,7 @@ describe('Private Futures REST API POST Endpoints', () => {
symbol, symbol,
triggerPrice: '100', triggerPrice: '100',
triggerType: 'market_price', triggerType: 'market_price',
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -207,7 +207,7 @@ describe('Private Futures REST API POST Endpoints', () => {
marginCoin, marginCoin,
symbol, symbol,
presetTakeProfitPrice: '100', presetTakeProfitPrice: '100',
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -229,7 +229,7 @@ describe('Private Futures REST API POST Endpoints', () => {
planType: 'profit_plan', planType: 'profit_plan',
holdSide: 'long', holdSide: 'long',
triggerPrice: '100', triggerPrice: '100',
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -251,7 +251,7 @@ describe('Private Futures REST API POST Endpoints', () => {
holdSide: 'long', holdSide: 'long',
planType: 'profit_plan', planType: 'profit_plan',
triggerPrice: '50', triggerPrice: '50',
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -270,7 +270,8 @@ describe('Private Futures REST API POST Endpoints', () => {
marginCoin, marginCoin,
symbol, symbol,
orderId: '123456', orderId: '123456',
}) planType: 'profit_plan',
}),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -278,8 +279,7 @@ describe('Private Futures REST API POST Endpoints', () => {
} catch (e) { } catch (e) {
// expect(e).toBeNull(); // expect(e).toBeNull();
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
// code: API_ERROR_CODE.FUTURES_ORDER_TPSL_NOT_FOUND, code: API_ERROR_CODE.FUTURES_ORDER_TPSL_NOT_FOUND,
code: API_ERROR_CODE.FUTURES_POSITION_DIRECTION_EMPTY,
}); });
} }
}); });
@@ -292,7 +292,7 @@ describe('Private Futures REST API POST Endpoints', () => {
symbol, symbol,
orderId: '123456', orderId: '123456',
planType: 'profit_plan', planType: 'profit_plan',
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
@@ -310,7 +310,7 @@ describe('Private Futures REST API POST Endpoints', () => {
{ {
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},
} },
); );
} catch (e) { } catch (e) {
expect(e.body).toMatchObject({ expect(e.body).toMatchObject({
@@ -324,7 +324,7 @@ describe('Private Futures REST API POST Endpoints', () => {
expect( expect(
await api.modifyCopyTraderTPSL(symbol, '123456', { await api.modifyCopyTraderTPSL(symbol, '123456', {
stopLossPrice: 1234, stopLossPrice: 1234,
}) }),
).toMatchObject({ ).toMatchObject({
...sucessEmptyResponseObject(), ...sucessEmptyResponseObject(),
data: {}, data: {},

View File

@@ -70,7 +70,7 @@ describe('Public Spot REST API Endpoints', () => {
it('getCandles()', async () => { it('getCandles()', async () => {
expect( expect(
await api.getCandles(symbol, '1min', `${from}`, `${to}`) await api.getCandles(symbol, '1min', `${from}`, `${to}`),
).toMatchObject(expect.any(Array)); ).toMatchObject(expect.any(Array));
}); });

View File

@@ -19,7 +19,7 @@ export function sucessEmptyResponseObject() {
export function errorResponseObject( export function errorResponseObject(
result: null | any = null, result: null | any = null,
ret_code: number, ret_code: number,
ret_msg: string ret_msg: string,
) { ) {
return { return {
result, result,
@@ -30,7 +30,7 @@ export function errorResponseObject(
export function errorResponseObjectV3( export function errorResponseObjectV3(
result: null | any = null, result: null | any = null,
retCode: number retCode: number,
) { ) {
return { return {
result, result,

View File

@@ -159,4 +159,44 @@ describe('Private Spot REST API GET Endpoints', () => {
expect(e).toBeNull(); expect(e).toBeNull();
} }
}); });
it('getCurrentPlanOrders()', async () => {
try {
expect(
await api.getCurrentPlanOrders({ symbol, pageSize: '20' }),
).toMatchObject({
...sucessEmptyResponseObject(),
data: {
nextFlag: false,
orderList: expect.any(Array),
},
});
} catch (e) {
console.error('getCurrentPlanOrders: ', e);
expect(e).toBeNull();
}
});
it('getHistoricPlanOrders()', async () => {
try {
expect(
await api.getHistoricPlanOrders({
symbol,
pageSize: '20',
startTime: '1667889483000',
endTime: '1668134732000',
}),
).toMatchObject({
...sucessEmptyResponseObject(),
data: {
endId: null,
nextFlag: false,
orderList: expect.any(Array),
},
});
} catch (e) {
console.error('getHistoricPlanOrders: ', e);
expect(e).toBeNull();
}
});
}); });

View File

@@ -20,129 +20,263 @@ describe('Private Spot REST API POST Endpoints', () => {
const symbol = 'BTCUSDT_SPBL'; const symbol = 'BTCUSDT_SPBL';
const coin = 'USDT'; const coin = 'USDT';
const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60;
const from = timestampOneHourAgo.toFixed(0);
const to = String(Number(from) + 1000 * 60 * 30); // 30 minutes
it('transfer()', async () => { describe('transfers', () => {
try { it('transfer()', async () => {
expect( try {
await api.transfer({ expect(
amount: '100', await api.transfer({
coin, amount: '100',
fromType: 'spot', coin,
toType: 'mix_usdt', fromType: 'spot',
}) toType: 'mix_usdt',
).toStrictEqual(''); }),
} catch (e) { ).toStrictEqual('');
// console.error('transfer: ', e); } catch (e) {
expect(e.body).toMatchObject({ // console.error('transfer: ', e);
// not sure what this error means, probably no balance. Seems to change? expect(e.body).toMatchObject({
code: expect.stringMatching(/42013|43117/gim), // not sure what this error means, probably no balance. Seems to change?
}); code: expect.stringMatching(/42013|43117/gim),
} });
}
});
it('transferV2()', async () => {
try {
expect(
await api.transferV2({
amount: '100',
coin,
fromType: 'spot',
toType: 'mix_usdt',
}),
).toStrictEqual('');
} catch (e) {
// console.error('transferV2: ', e);
expect(e.body).toMatchObject({
// not sure what this error means, probably no balance. Seems to change?
code: expect.stringMatching(/42013|43117/gim),
});
}
});
it('subTransfer()', async () => {
try {
expect(
await api.subTransfer({
fromUserId: '123',
toUserId: '456',
amount: '100',
clientOid: '123456',
coin,
fromType: 'spot',
toType: 'mix_usdt',
}),
).toStrictEqual('');
} catch (e) {
// console.error('transferV2: ', e);
expect(e.body).toMatchObject({
// not sure what this error means, probably no balance. Seems to change?
code: expect.stringMatching(/42013|43117|40018/gim),
});
}
});
it('withdraw()', async () => {
try {
expect(
await api.withdraw({
amount: '100',
coin,
chain: 'TRC20',
address: `123456`,
}),
).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.INCORRECT_PERMISSIONS,
});
}
});
it('withdrawV2()', async () => {
try {
expect(
await api.withdrawV2({
amount: '100',
coin,
chain: 'TRC20',
address: `123456`,
}),
).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.INCORRECT_PERMISSIONS,
});
}
});
it('innerWithdraw()', async () => {
try {
expect(await api.innerWithdraw(coin, '12345', '1')).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.INCORRECT_PERMISSIONS,
});
}
});
it('innerWithdrawV2()', async () => {
try {
expect(await api.innerWithdrawV2(coin, '12345', '1')).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.INCORRECT_PERMISSIONS,
});
}
});
}); });
describe('orders', () => {
it('withdraw()', async () => { it('submitOrder()', async () => {
try { try {
expect( expect(
await api.withdraw({ await api.submitOrder({
amount: '100', symbol,
coin,
chain: 'TRC20',
address: `123456`,
})
).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.INCORRECT_PERMISSIONS,
});
}
});
it('innerWithdraw()', async () => {
try {
expect(await api.innerWithdraw(coin, '12345', '1')).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.INCORRECT_PERMISSIONS,
});
}
});
it('submitOrder()', async () => {
try {
expect(
await api.submitOrder({
symbol,
side: 'buy',
orderType: 'market',
quantity: '1',
force: 'normal',
})
).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.QTY_LESS_THAN_MINIMUM,
});
}
});
it('batchSubmitOrder()', async () => {
try {
expect(
await api.batchSubmitOrder(symbol, [
{
side: 'buy', side: 'buy',
orderType: 'market', orderType: 'market',
quantity: '1', quantity: '1',
force: 'normal', force: 'normal',
}),
).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.QTY_LESS_THAN_MINIMUM,
});
}
});
it('batchSubmitOrder()', async () => {
try {
expect(
await api.batchSubmitOrder(symbol, [
{
side: 'buy',
orderType: 'market',
quantity: '1',
force: 'normal',
},
]),
).toMatchObject({
...sucessEmptyResponseObject(),
data: {
resultList: expect.any(Array),
failure: [{ errorCode: API_ERROR_CODE.QTY_LESS_THAN_MINIMUM }],
}, },
]) });
).toMatchObject({ } catch (e) {
...sucessEmptyResponseObject(), expect(e).toBeNull();
data: { }
resultList: expect.any(Array), });
failure: [{ errorCode: API_ERROR_CODE.QTY_LESS_THAN_MINIMUM }],
}, it('cancelOrder()', async () => {
}); try {
} catch (e) { expect(await api.cancelOrder(symbol, '123456')).toMatchObject({
expect(e).toBeNull(); ...sucessEmptyResponseObject(),
} data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.ORDER_NOT_FOUND,
});
}
});
it('batchCancelOrder()', async () => {
try {
expect(await api.batchCancelOrder(symbol, ['123456'])).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.ORDER_NOT_FOUND,
});
}
});
}); });
it('cancelOrder()', async () => { describe('plan orders', () => {
try { let planOrderId: string;
expect(await api.cancelOrder(symbol, '123456')).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.ORDER_NOT_FOUND,
});
}
});
it('batchCancelOrder()', async () => { it('submitPlanOrder()', async () => {
try { try {
expect(await api.batchCancelOrder(symbol, ['123456'])).toMatchObject({ const result = await api.submitPlanOrder({
...sucessEmptyResponseObject(), symbol,
data: expect.any(Array), side: 'buy',
}); orderType: 'market',
} catch (e) { size: 100,
expect(e.body).toMatchObject({ triggerPrice: 100,
code: API_ERROR_CODE.ORDER_NOT_FOUND, triggerType: 'fill_price',
}); });
}
planOrderId = result.data.orderId;
expect(result).toMatchObject({
...sucessEmptyResponseObject(),
});
} catch (e) {
console.error('submitPlanOrder(): ', e);
expect(e).toBeNull();
}
});
it('modifyPlanOrder()', async () => {
try {
expect(
await api.modifyPlanOrder({
orderType: 'market',
triggerPrice: 100,
orderId: '123456',
}),
).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(Array),
});
} catch (e) {
expect(e.body).toMatchObject({
code: API_ERROR_CODE.PLAN_ORDER_NOT_FOUND,
});
}
});
it('cancelPlanOrder()', async () => {
try {
expect(
await api.cancelPlanOrder({
orderId: planOrderId || '123456',
}),
).toMatchObject({
...sucessEmptyResponseObject(),
data: expect.any(String),
});
} catch (e) {
console.error('cancelPlanOrder(): ', e);
expect(e).toBeNull();
}
});
}); });
}); });

View File

@@ -26,7 +26,7 @@ describe('Private Spot Websocket Client', () => {
apiSecret: 'bad', apiSecret: 'bad',
apiPass: 'bad', apiPass: 'bad',
}, },
getSilentLogger('expect401') getSilentLogger('expect401'),
); );
// const wsOpenPromise = waitForSocketEvent(badClient, 'open'); // const wsOpenPromise = waitForSocketEvent(badClient, 'open');
@@ -62,7 +62,7 @@ describe('Private Spot Websocket Client', () => {
beforeAll(() => { beforeAll(() => {
wsClient = new WebsocketClient( wsClient = new WebsocketClient(
wsClientOptions, wsClientOptions,
getSilentLogger('expectSuccess') getSilentLogger('expectSuccess'),
); );
wsClient.connectAll(); wsClient.connectAll();
// logAllEvents(wsClient); // logAllEvents(wsClient);

View File

@@ -13,7 +13,7 @@ describe('Public Spot Websocket Client', () => {
beforeAll(() => { beforeAll(() => {
wsClient = new WebsocketClient( wsClient = new WebsocketClient(
wsClientOptions, wsClientOptions,
getSilentLogger('expectSuccess') getSilentLogger('expectSuccess'),
); );
wsClient.connectAll(); wsClient.connectAll();
logAllEvents(wsClient); logAllEvents(wsClient);

View File

@@ -24,12 +24,12 @@ export const fullLogger = {
export function waitForSocketEvent( export function waitForSocketEvent(
wsClient: WebsocketClient, wsClient: WebsocketClient,
event: WsClientEvent, event: WsClientEvent,
timeoutMs: number = 4.5 * 1000 timeoutMs: number = 4.5 * 1000,
) { ) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
reject( reject(
`Failed to receive "${event}" event before timeout. Check that these are correct: topic, api keys (if private), signature process (if private)` `Failed to receive "${event}" event before timeout. Check that these are correct: topic, api keys (if private), signature process (if private)`,
); );
}, timeoutMs); }, timeoutMs);