From dfb1534d222e55aa6ddfbc112a98e34fa77efe1b Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Wed, 22 Mar 2023 09:44:40 +0000 Subject: [PATCH 01/11] fix(): fix unintentional pointer ref, fixes very rare sign issue if request is fired in parallel --- src/util/BaseRestClient.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/util/BaseRestClient.ts b/src/util/BaseRestClient.ts index 923140c..425ce96 100644 --- a/src/util/BaseRestClient.ts +++ b/src/util/BaseRestClient.ts @@ -304,24 +304,31 @@ export default abstract class BaseRestClient { isPublicApi ); - if (!options.headers) { - options.headers = {}; - } - options.headers['ACCESS-KEY'] = this.apiKey; - options.headers['ACCESS-PASSPHRASE'] = this.apiPass; - options.headers['ACCESS-TIMESTAMP'] = signResult.timestamp; - options.headers['ACCESS-SIGN'] = signResult.sign; - options.headers['Content-Type'] = 'application/json'; + const authHeaders = { + 'ACCESS-KEY': this.apiKey, + 'ACCESS-PASSPHRASE': this.apiPass, + 'ACCESS-TIMESTAMP': signResult.timestamp, + 'ACCESS-SIGN': signResult.sign, + 'Content-Type': 'application/json', + }; if (method === 'GET') { return { ...options, + headers: { + ...authHeaders, + ...options.headers, + }, url: options.url + signResult.queryParamsWithSign, }; } return { ...options, + headers: { + ...authHeaders, + ...options.headers, + }, data: params, }; } From bf2e545d09d05507f68d3567e209f717807b22d1 Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Wed, 22 Mar 2023 10:49:32 +0000 Subject: [PATCH 02/11] feat(): add new spot wallet endpoints --- src/spot-client.ts | 46 +++++++++++++++----- src/types/request/spot.ts | 20 +++++++++ test/spot/private.write.test.ts | 74 +++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 10 deletions(-) diff --git a/src/spot-client.ts b/src/spot-client.ts index b239ec3..3e06632 100644 --- a/src/spot-client.ts +++ b/src/spot-client.ts @@ -7,6 +7,8 @@ import { KlineInterval, CoinBalance, SymbolRules, + NewSpotSubTransfer, + NewSpotWithdraw, } from './types'; import { REST_CLIENT_TYPE_ENUM } from './util'; import BaseRestClient from './util/BaseRestClient'; @@ -104,6 +106,18 @@ export class SpotClient extends BaseRestClient { return this.postPrivate('/api/spot/v1/wallet/transfer', params); } + /** Initiate wallet transfer (v2 endpoint) */ + transferV2(params: NewWalletTransfer): Promise> { + return this.postPrivate('/api/spot/v1/wallet/transfer-v2', params); + } + + /** + * Transfer main-sub, sub-sub or sub-main + */ + subTransfer(params: NewSpotSubTransfer): Promise> { + return this.postPrivate('/api/spot/v1/wallet/subTransfer', params); + } + /** Get Coin Address */ getDepositAddress(coin: string, chain?: string): Promise> { return this.getPrivate('/api/spot/v1/wallet/deposit-address', { @@ -112,19 +126,16 @@ export class SpotClient extends BaseRestClient { }); } - /** Withdraw Coins On Chain*/ - withdraw(params: { - coin: string; - address: string; - chain: string; - tag?: string; - amount: string; - remark?: string; - clientOid?: string; - }): Promise> { + /** Withdraw Coins On Chain */ + withdraw(params: NewSpotWithdraw): Promise> { return this.postPrivate('/api/spot/v1/wallet/withdrawal', params); } + /** Withdraw Coins On Chain (v2 endpoint) */ + withdrawV2(params: NewSpotWithdraw): Promise> { + return this.postPrivate('/api/spot/v1/wallet/withdrawal-v2', params); + } + /** Inner Withdraw : Internal withdrawal means that both users are on the Bitget platform */ innerWithdraw( coin: string, @@ -140,6 +151,21 @@ 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> { + return this.postPrivate('/api/spot/v1/wallet/withdrawal-inner-v2', { + coin, + toUid, + amount, + clientOid, + }); + } + /** Get Withdraw List */ getWithdrawals( coin: string, diff --git a/src/types/request/spot.ts b/src/types/request/spot.ts index edc5e46..10e4fb2 100644 --- a/src/types/request/spot.ts +++ b/src/types/request/spot.ts @@ -21,3 +21,23 @@ export interface NewSpotOrder { } export type NewBatchSpotOrder = Omit; + +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; +} diff --git a/test/spot/private.write.test.ts b/test/spot/private.write.test.ts index 280a764..3ed2e8d 100644 --- a/test/spot/private.write.test.ts +++ b/test/spot/private.write.test.ts @@ -43,6 +43,47 @@ describe('Private Spot REST API POST Endpoints', () => { } }); + 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/gim), + }); + } + }); + it('withdraw()', async () => { try { expect( @@ -63,6 +104,26 @@ describe('Private Spot REST API POST Endpoints', () => { } }); + 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({ @@ -76,6 +137,19 @@ describe('Private Spot REST API POST Endpoints', () => { } }); + 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, + }); + } + }); + it('submitOrder()', async () => { try { expect( From 31aee2a0e5b106bcaa7caa923a1d2e0e71116432 Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Wed, 22 Mar 2023 15:00:40 +0000 Subject: [PATCH 03/11] feat(): add plan order endpoints --- src/spot-client.ts | 80 +++++- src/types/request/spot.ts | 88 ++++++- src/types/response/spot.ts | 20 ++ src/util/BaseRestClient.ts | 1 - test/spot/private.read.test.ts | 41 +++ test/spot/private.write.test.ts | 436 ++++++++++++++++++-------------- 6 files changed, 464 insertions(+), 202 deletions(-) diff --git a/src/spot-client.ts b/src/spot-client.ts index 3e06632..a2b7417 100644 --- a/src/spot-client.ts +++ b/src/spot-client.ts @@ -9,6 +9,15 @@ import { SymbolRules, NewSpotSubTransfer, NewSpotWithdraw, + CancelSpotOrderV2, + BatchCancelSpotOrderV2, + SpotOrderResult, + NewSpotPlanOrder, + ModifySpotPlanOrder, + CancelSpotPlanOrderParams, + GetSpotPlanOrdersParams, + SpotPlanOrder, + GetHistoricPlanOrdersParams, } from './types'; import { REST_CLIENT_TYPE_ENUM } from './util'; import BaseRestClient from './util/BaseRestClient'; @@ -246,7 +255,7 @@ export class SpotClient extends BaseRestClient { */ /** Place order */ - submitOrder(params: NewSpotOrder): Promise> { + submitOrder(params: NewSpotOrder): Promise> { return this.postPrivate('/api/spot/v1/trade/orders', params); } @@ -269,6 +278,20 @@ export class SpotClient extends BaseRestClient { }); } + /** Cancel order (v2 endpoint - supports orderId or clientOid) */ + cancelOrderV2(params?: CancelSpotOrderV2): Promise> { + return this.postPrivate('/api/spot/v1/trade/cancel-order-v2', params); + } + + /** + * Cancel all spot orders for a symbol + */ + cancelSymbolOrders(symbol: string): Promise> { + return this.postPrivate('/api/spot/v1/trade/cancel-symbol-order', { + symbol, + }); + } + /** Cancel order in batch (per symbol) */ batchCancelOrder( symbol: string, @@ -280,6 +303,16 @@ export class SpotClient extends BaseRestClient { }); } + /** Cancel order in batch (per symbol). V2 endpoint, supports orderIds or clientOids. */ + batchCancelOrderV2( + params: BatchCancelSpotOrderV2 + ): Promise> { + return this.postPrivate( + '/api/spot/v1/trade/cancel-batch-orders-v2', + params + ); + } + /** Get order details */ getOrder( symbol: string, @@ -321,4 +354,49 @@ export class SpotClient extends BaseRestClient { ...pagination, }); } + + /** Place plan order */ + submitPlanOrder( + params: NewSpotPlanOrder + ): Promise> { + return this.postPrivate('/api/spot/v1/plan/placePlan', params); + } + + /** Modify plan order */ + modifyPlanOrder( + params: ModifySpotPlanOrder + ): Promise> { + return this.postPrivate('/api/spot/v1/plan/modifyPlan', params); + } + + /** Cancel plan order */ + cancelPlanOrder( + params: CancelSpotPlanOrderParams + ): Promise> { + 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); + } + + // } diff --git a/src/types/request/spot.ts b/src/types/request/spot.ts index 10e4fb2..071f2ee 100644 --- a/src/types/request/spot.ts +++ b/src/types/request/spot.ts @@ -10,18 +10,6 @@ export interface NewWalletTransfer { clientOid?: string; } -export interface NewSpotOrder { - symbol: string; - side: 'buy' | 'sell'; - orderType: 'limit' | 'market'; - force: OrderTimeInForce; - price?: string; - quantity: string; - clientOrderId?: string; -} - -export type NewBatchSpotOrder = Omit; - export interface NewSpotSubTransfer { fromType: WalletType; toType: WalletType; @@ -41,3 +29,79 @@ export interface NewSpotWithdraw { remark?: string; clientOid?: string; } + +export interface NewSpotOrder { + symbol: string; + side: 'buy' | 'sell'; + orderType: 'limit' | 'market'; + force: OrderTimeInForce; + price?: string; + quantity: string; + clientOrderId?: string; +} + +export type NewBatchSpotOrder = Omit; + +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; +} diff --git a/src/types/response/spot.ts b/src/types/response/spot.ts index 4c6ea61..460fbcb 100644 --- a/src/types/response/spot.ts +++ b/src/types/response/spot.ts @@ -20,3 +20,23 @@ export interface SymbolRules { quantityScale: 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; +} diff --git a/src/util/BaseRestClient.ts b/src/util/BaseRestClient.ts index 425ce96..b2c8a90 100644 --- a/src/util/BaseRestClient.ts +++ b/src/util/BaseRestClient.ts @@ -309,7 +309,6 @@ export default abstract class BaseRestClient { 'ACCESS-PASSPHRASE': this.apiPass, 'ACCESS-TIMESTAMP': signResult.timestamp, 'ACCESS-SIGN': signResult.sign, - 'Content-Type': 'application/json', }; if (method === 'GET') { diff --git a/test/spot/private.read.test.ts b/test/spot/private.read.test.ts index e7ac101..784ce02 100644 --- a/test/spot/private.read.test.ts +++ b/test/spot/private.read.test.ts @@ -159,4 +159,45 @@ describe('Private Spot REST API GET Endpoints', () => { expect(e).toBeNull(); } }); + + it('getCurrentPlanOrders()', async () => { + try { + expect( + await api.getCurrentPlanOrders({ symbol, pageSize: '20' }) + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + endId: null, + 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(); + } + }); }); diff --git a/test/spot/private.write.test.ts b/test/spot/private.write.test.ts index 3ed2e8d..8be72ce 100644 --- a/test/spot/private.write.test.ts +++ b/test/spot/private.write.test.ts @@ -20,203 +20,263 @@ describe('Private Spot REST API POST Endpoints', () => { const symbol = 'BTCUSDT_SPBL'; 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 () => { - try { - expect( - await api.transfer({ - amount: '100', - coin, - fromType: 'spot', - toType: 'mix_usdt', - }) - ).toStrictEqual(''); - } catch (e) { - // console.error('transfer: ', e); - expect(e.body).toMatchObject({ - // not sure what this error means, probably no balance. Seems to change? - code: expect.stringMatching(/42013|43117/gim), - }); - } + describe('transfers', () => { + it('transfer()', async () => { + try { + expect( + await api.transfer({ + amount: '100', + coin, + fromType: 'spot', + toType: 'mix_usdt', + }) + ).toStrictEqual(''); + } catch (e) { + // console.error('transfer: ', e); + expect(e.body).toMatchObject({ + // 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, + }); + } + }); }); - - 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/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, - }); - } - }); - - 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, [ - { + describe('orders', () => { + 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', + orderType: 'market', + quantity: '1', + force: 'normal', + }, + ]) + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + resultList: expect.any(Array), + failure: [{ errorCode: API_ERROR_CODE.QTY_LESS_THAN_MINIMUM }], }, - ]) - ).toMatchObject({ - ...sucessEmptyResponseObject(), - data: { - resultList: expect.any(Array), - failure: [{ errorCode: API_ERROR_CODE.QTY_LESS_THAN_MINIMUM }], - }, - }); - } catch (e) { - expect(e).toBeNull(); - } + }); + } catch (e) { + expect(e).toBeNull(); + } + }); + + it('cancelOrder()', async () => { + try { + 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 () => { + 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 () => { - try { - 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, - }); - } - }); + describe('plan orders', () => { + let planOrderId: string; - 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('submitPlanOrder()', async () => { + try { + const result = await api.submitPlanOrder({ + symbol, + side: 'buy', + orderType: 'market', + size: 100, + triggerPrice: 100, + 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(); + } + }); }); }); From b2bbd8097cdc251569804765d44a0d6145140582 Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Wed, 22 Mar 2023 15:14:19 +0000 Subject: [PATCH 04/11] fix(): plan order test --- test/spot/private.read.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/spot/private.read.test.ts b/test/spot/private.read.test.ts index 784ce02..67798ec 100644 --- a/test/spot/private.read.test.ts +++ b/test/spot/private.read.test.ts @@ -167,7 +167,6 @@ describe('Private Spot REST API GET Endpoints', () => { ).toMatchObject({ ...sucessEmptyResponseObject(), data: { - endId: null, nextFlag: false, orderList: expect.any(Array), }, From b92739de979490fa0339cb69c8d8fca2acd0d120 Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Wed, 22 Mar 2023 15:51:19 +0000 Subject: [PATCH 05/11] feat(): add new spot market endpoints + params --- src/spot-client.ts | 42 +++++++++++++++++++++++++++++++++++--- src/types/request/spot.ts | 8 ++++++++ src/types/response/spot.ts | 19 +++++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/spot-client.ts b/src/spot-client.ts index a2b7417..a3079ec 100644 --- a/src/spot-client.ts +++ b/src/spot-client.ts @@ -18,6 +18,9 @@ import { GetSpotPlanOrdersParams, SpotPlanOrder, GetHistoricPlanOrdersParams, + SpotMarketTrade, + GetHistoricTradesParams, + SpotVIPFeeRate, } from './types'; import { REST_CLIENT_TYPE_ENUM } from './util'; import BaseRestClient from './util/BaseRestClient'; @@ -77,8 +80,28 @@ export class SpotClient extends BaseRestClient { return this.get('/api/spot/v1/market/tickers'); } - /** Get Market Trades */ - getMarketTrades(symbol: string, limit?: string): Promise> { + /** Get most recent trades (up to 500, 100 by default) */ + getRecentTrades( + symbol: string, + limit?: string + ): Promise> { + 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> { + 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> { return this.get('/api/spot/v1/market/fills', { symbol, limit }); } @@ -104,6 +127,11 @@ export class SpotClient extends BaseRestClient { return this.get('/api/spot/v1/market/depth', { symbol, type, limit }); } + /** Get VIP fee rates */ + getVIPFeeRates(): Promise> { + return this.get('/api/spot/v1/market/spot-vip-level'); + } + /** * * Wallet Endpoints @@ -181,7 +209,8 @@ export class SpotClient extends BaseRestClient { startTime: string, endTime: string, pageSize?: string, - pageNo?: string + pageNo?: string, + clientOid?: string ): Promise> { return this.getPrivate('/api/spot/v1/wallet/withdrawal-list', { coin, @@ -189,6 +218,7 @@ export class SpotClient extends BaseRestClient { endTime, pageSize, pageNo, + clientOid, }); } @@ -225,6 +255,11 @@ export class SpotClient extends BaseRestClient { return this.getPrivate('/api/spot/v1/account/assets', { coin }); } + /** Get sub Account Spot Asset */ + getSubAccountSpotAssets(): Promise> { + return this.postPrivate('/api/spot/v1/account/sub-account-spot-assets'); + } + /** Get Bills : get transaction detail flow */ getTransactionHistory(params?: { coinId?: number; @@ -244,6 +279,7 @@ export class SpotClient extends BaseRestClient { after?: string; before?: string; limit?: number; + clientOid?: string; }): Promise> { return this.getPrivate('/api/spot/v1/account/transferRecords', params); } diff --git a/src/types/request/spot.ts b/src/types/request/spot.ts index 071f2ee..3bea3ed 100644 --- a/src/types/request/spot.ts +++ b/src/types/request/spot.ts @@ -1,5 +1,13 @@ import { OrderTimeInForce } from './shared'; +export interface GetHistoricTradesParams { + symbol: string; + limit?: string; + tradeId?: string; + startTime?: string; + endTime?: string; +} + export type WalletType = 'spot' | 'mix_usdt' | 'mix_usd'; export interface NewWalletTransfer { diff --git a/src/types/response/spot.ts b/src/types/response/spot.ts index 460fbcb..dee7775 100644 --- a/src/types/response/spot.ts +++ b/src/types/response/spot.ts @@ -21,6 +21,16 @@ export interface SymbolRules { status: string; } +export interface SpotVIPFeeRate { + level: number; + dealAmount: string; + assetAmount: string; + takerFeeRate?: string; + makerFeeRate?: number; + withdrawAmount: string; + withdrawAmountUSDT: string; +} + export interface SpotOrderResult { orderId: string; clientOrderId: string; @@ -40,3 +50,12 @@ export interface SpotPlanOrder { enterPointSource: string; cTime: number; } + +export interface SpotMarketTrade { + symbol: string; + tradeId: string; + side: 'buy' | 'sell'; + fillPrice: string; + fillQuantity: string; + fillTime: string; +} From 831689e8575f9b17519f2810c3c87262da9f397b Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Wed, 22 Mar 2023 17:00:59 +0000 Subject: [PATCH 06/11] feat(): add new futures endpoints & add new req property (clientOid) --- .prettierrc | 3 +- src/futures-client.ts | 162 ++++++++++++++++++++++++-------- src/spot-client.ts | 42 ++++----- src/types/request/futures.ts | 19 +++- src/types/request/shared.ts | 8 ++ src/types/request/spot.ts | 8 -- src/types/response/futures.ts | 9 ++ src/types/response/shared.ts | 10 ++ src/types/response/spot.ts | 11 --- src/util/BaseRestClient.ts | 24 ++--- src/websocket-client.ts | 50 +++++----- test/spot/private.read.test.ts | 4 +- test/spot/private.write.test.ts | 18 ++-- 13 files changed, 235 insertions(+), 133 deletions(-) diff --git a/.prettierrc b/.prettierrc index 1fb73bc..8d6ce6a 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,5 @@ { "tabWidth": 2, - "singleQuote": true + "singleQuote": true, + "trailingComma": "all" } diff --git a/src/futures-client.ts b/src/futures-client.ts index 92444d0..9372d0a 100644 --- a/src/futures-client.ts +++ b/src/futures-client.ts @@ -20,6 +20,11 @@ import { FuturesMarginMode, FuturesPosition, NewFuturesPlanTrailingStopOrder, + VIPFeeRate, + SpotMarketTrade, + GetHistoricTradesParams, + FuturesMarketTrade, + FuturesPlanType, } from './types'; import { REST_CLIENT_TYPE_ENUM } from './util'; import BaseRestClient from './util/BaseRestClient'; @@ -40,7 +45,7 @@ export class FuturesClient extends BaseRestClient { /** Get Symbols : Get basic configuration information of all trading pairs (including rules) */ getSymbols( - productType: FuturesProductType + productType: FuturesProductType, ): Promise> { return this.get('/api/mix/v1/market/contracts', { productType }); } @@ -60,8 +65,33 @@ export class FuturesClient extends BaseRestClient { return this.get('/api/mix/v1/market/tickers', { productType }); } - /** Get Market Trades */ - getMarketTrades(symbol: string, limit?: string): Promise> { + /** Get VIP fee rates */ + getVIPFeeRates(): Promise> { + return this.get('/api/spot/v1/market/spot-vip-level'); + } + + /** Get most recent trades (up to 500, 100 by default) */ + getRecentTrades( + symbol: string, + limit?: string, + ): Promise> { + 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> { + 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> { return this.get('/api/mix/v1/market/fills', { symbol, limit }); } @@ -70,13 +100,15 @@ export class FuturesClient extends BaseRestClient { symbol: string, granularity: KlineInterval, startTime: string, - endTime: string + endTime: string, + limit?: string, ): Promise { return this.get('/api/mix/v1/market/candles', { symbol, granularity, startTime, endTime, + limit, }); } @@ -95,7 +127,7 @@ export class FuturesClient extends BaseRestClient { symbol: string, pageSize?: string, pageNo?: string, - nextPage?: boolean + nextPage?: boolean, ): Promise> { return this.get('/api/mix/v1/market/history-fundRate', { symbol, @@ -134,7 +166,7 @@ export class FuturesClient extends BaseRestClient { /** Get Single Account */ getAccount( symbol: string, - marginCoin: string + marginCoin: string, ): Promise> { return this.getPrivate('/api/mix/v1/account/account', { symbol, @@ -147,6 +179,15 @@ export class FuturesClient extends BaseRestClient { return this.getPrivate('/api/mix/v1/account/accounts', { productType }); } + /** Get Sub Account Contract Assets */ + getSubAccountContractAssets( + productType: FuturesProductType, + ): Promise> { + 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. * The result does not represent the actual number of positions opened. @@ -156,7 +197,7 @@ export class FuturesClient extends BaseRestClient { marginCoin: string, openPrice: number, openAmount: number, - leverage?: number + leverage?: number, ): Promise> { return this.postPrivate('/api/mix/v1/account/open-count', { symbol, @@ -172,7 +213,7 @@ export class FuturesClient extends BaseRestClient { symbol: string, marginCoin: string, leverage: string, - holdSide?: string + holdSide?: string, ): Promise> { return this.postPrivate('/api/mix/v1/account/setLeverage', { symbol, @@ -187,7 +228,7 @@ export class FuturesClient extends BaseRestClient { symbol: string, marginCoin: string, amount: string, - holdSide?: string + holdSide?: string, ): Promise> { return this.postPrivate('/api/mix/v1/account/setMargin', { symbol, @@ -201,7 +242,7 @@ export class FuturesClient extends BaseRestClient { setMarginMode( symbol: string, marginCoin: string, - marginMode: FuturesMarginMode + marginMode: FuturesMarginMode, ): Promise> { return this.postPrivate('/api/mix/v1/account/setMarginMode', { symbol, @@ -210,10 +251,21 @@ export class FuturesClient extends BaseRestClient { }); } + /** Change Hold Mode */ + setHoldMode( + productType: FuturesProductType, + holdMode: 'single_hold' | 'double_hold', + ): Promise> { + return this.postPrivate('/api/mix/v1/account/setPositionMode', { + productType, + holdMode, + }); + } + /** Get Symbol Position */ getPosition( symbol: string, - marginCoin?: string + marginCoin?: string, ): Promise> { return this.getPrivate('/api/mix/v1/position/singlePosition', { symbol, @@ -224,7 +276,7 @@ export class FuturesClient extends BaseRestClient { /** Get All Position */ getPositions( productType: FuturesProductType, - marginCoin?: string + marginCoin?: string, ): Promise> { return this.getPrivate('/api/mix/v1/position/allPosition', { productType, @@ -239,7 +291,7 @@ export class FuturesClient extends BaseRestClient { /** Get Business Account Bill */ getBusinessBill( - params: FuturesBusinessBillRequest + params: FuturesBusinessBillRequest, ): Promise> { return this.getPrivate('/api/mix/v1/account/accountBusinessBill', params); } @@ -259,7 +311,7 @@ export class FuturesClient extends BaseRestClient { batchSubmitOrder( symbol: string, marginCoin: string, - orders: NewBatchFuturesOrder[] + orders: NewBatchFuturesOrder[], ): Promise> { return this.postPrivate('/api/mix/v1/order/batch-orders', { symbol, @@ -272,12 +324,14 @@ export class FuturesClient extends BaseRestClient { cancelOrder( symbol: string, marginCoin: string, - orderId: string + orderId?: string, + clientOid?: string, ): Promise> { return this.postPrivate('/api/mix/v1/order/cancel-order', { symbol, marginCoin, orderId, + clientOid, }); } @@ -285,7 +339,7 @@ export class FuturesClient extends BaseRestClient { batchCancelOrder( symbol: string, marginCoin: string, - orderIds: string[] + orderIds: string[], ): Promise> { return this.postPrivate('/api/mix/v1/order/cancel-batch-orders', { symbol, @@ -294,10 +348,23 @@ export class FuturesClient extends BaseRestClient { }); } + /** + * Cancel all futures orders for a symbol + */ + cancelSymbolOrders( + symbol: string, + marginCoin: string, + ): Promise> { + return this.postPrivate('/api/mix/v1/order/cancel-symbol-orders', { + symbol, + marginCoin, + }); + } + /** Cancel All Order */ cancelAllOrders( productType: FuturesProductType, - marginCoin: string + marginCoin: string, ): Promise> { return this.postPrivate('/api/mix/v1/order/cancel-all-orders', { productType, @@ -313,7 +380,7 @@ export class FuturesClient extends BaseRestClient { /** Get All Open Order */ getOpenOrders( productType: FuturesProductType, - marginCoin: string + marginCoin: string, ): Promise> { return this.getPrivate('/api/mix/v1/order/marginCoinCurrent', { productType, @@ -328,7 +395,8 @@ export class FuturesClient extends BaseRestClient { endTime: string, pageSize: string, lastEndId?: string, - isPre?: boolean + isPre?: boolean, + clientOid?: string, ): Promise> { return this.getPrivate('/api/mix/v1/order/history', { symbol, @@ -337,6 +405,7 @@ export class FuturesClient extends BaseRestClient { pageSize, lastEndId, isPre, + clientOid, }); } @@ -347,7 +416,8 @@ export class FuturesClient extends BaseRestClient { endTime: string, pageSize: string, lastEndId?: string, - isPre?: boolean + isPre?: boolean, + clientOid?: string, ): Promise> { return this.getPrivate('/api/mix/v1/order/historyProductType', { productType, @@ -356,6 +426,7 @@ export class FuturesClient extends BaseRestClient { pageSize, lastEndId, isPre, + clientOid, }); } @@ -363,7 +434,7 @@ export class FuturesClient extends BaseRestClient { getOrder( symbol: string, orderId?: string, - clientOid?: string + clientOid?: string, ): Promise> { return this.getPrivate('/api/mix/v1/order/detail', { symbol, @@ -376,7 +447,7 @@ export class FuturesClient extends BaseRestClient { getOrderFills( symbol: string, orderId?: string, - pagination?: FuturesPagination + pagination?: FuturesPagination, ): Promise> { return this.getPrivate('/api/mix/v1/order/fills', { symbol, @@ -388,7 +459,7 @@ export class FuturesClient extends BaseRestClient { /** Get ProductType Order fill detail */ getProductTypeOrderFills( productType: FuturesProductType, - pagination?: FuturesPagination + pagination?: FuturesPagination, ): Promise> { return this.getPrivate('/api/mix/v1/order/allFills', { productType: productType.toUpperCase(), @@ -408,7 +479,7 @@ export class FuturesClient extends BaseRestClient { /** Modify Plan Order TPSL */ modifyPlanOrderTPSL( - params: ModifyFuturesPlanOrderTPSL + params: ModifyFuturesPlanOrderTPSL, ): Promise> { return this.postPrivate('/api/mix/v1/plan/modifyPlanPreset', params); } @@ -420,37 +491,48 @@ export class FuturesClient extends BaseRestClient { /** Place Trailing Stop order */ submitTrailingStopOrder( - params: NewFuturesPlanTrailingStopOrder + params: NewFuturesPlanTrailingStopOrder, ): Promise> { return this.postPrivate('/api/mix/v1/plan/placeTrailStop', params); } /** Place Position TPSL */ submitPositionTPSL( - params: NewFuturesPlanPositionTPSL + params: NewFuturesPlanPositionTPSL, ): Promise> { return this.postPrivate('/api/mix/v1/plan/placePositionsTPSL', params); } /** Modify Stop Order */ modifyStopOrder( - params: ModifyFuturesPlanStopOrder + params: ModifyFuturesPlanStopOrder, ): Promise> { return this.postPrivate('/api/mix/v1/plan/modifyTPSLPlan', params); } /** Cancel Plan Order TPSL */ cancelPlanOrderTPSL( - params: CancelFuturesPlanTPSL + params: CancelFuturesPlanTPSL, ): Promise> { return this.postPrivate('/api/mix/v1/plan/cancelPlan', params); } + /** Cancel All Trigger Order (TPSL) */ + cancelAllPlanOrders( + productType: FuturesProductType, + planType: FuturesPlanType, + ): Promise> { + return this.postPrivate('/api/mix/v1/plan/cancelAllPlan', { + productType, + planType, + }); + } + /** Get Plan Order (TPSL) List */ getPlanOrderTPSLs( symbol: string, isPlan?: string, - productType?: FuturesProductType + productType?: FuturesProductType, ): Promise> { return this.getPrivate('/api/mix/v1/plan/currentPlan', { symbol, @@ -461,14 +543,14 @@ export class FuturesClient extends BaseRestClient { /** Get History Plan Orders (TPSL) */ getHistoricPlanOrdersTPSL( - params: HistoricPlanOrderTPSLRequest + params: HistoricPlanOrderTPSLRequest, ): Promise> { return this.getPrivate('/api/mix/v1/plan/historyPlan', params); } /** * - * Trade Endpoints + * Copy Trade Endpoints * */ @@ -477,7 +559,7 @@ export class FuturesClient extends BaseRestClient { symbol: string, productType: FuturesProductType, pageSize: number, - pageNo: number + pageNo: number, ): Promise> { return this.getPrivate('/api/mix/v1/trace/currentTrack', { symbol, @@ -492,7 +574,7 @@ export class FuturesClient extends BaseRestClient { symbol: string, productType: FuturesProductType, pageSize: number, - pageNo: number + pageNo: number, ): Promise> { return this.getPrivate('/api/mix/v1/trace/followerOrder', { symbol, @@ -505,7 +587,7 @@ export class FuturesClient extends BaseRestClient { /** Trader Close Position */ closeCopyTraderPosition( symbol: string, - trackingNo: string + trackingNo: string, ): Promise> { return this.postPrivate('/api/mix/v1/trace/closeTrackOrder', { symbol, @@ -520,7 +602,7 @@ export class FuturesClient extends BaseRestClient { changes?: { stopProfitPrice?: number; stopLossPrice?: number; - } + }, ): Promise> { return this.postPrivate('/api/mix/v1/trace/modifyTPSL', { symbol, @@ -534,7 +616,7 @@ export class FuturesClient extends BaseRestClient { startTime: string, endTime: string, pageSize: number, - pageNo: number + pageNo: number, ): Promise> { return this.getPrivate('/api/mix/v1/trace/historyTrack', { startTime, @@ -559,7 +641,7 @@ export class FuturesClient extends BaseRestClient { marginCoin: string, dateMs: string, pageSize: number, - pageNo: number + pageNo: number, ): Promise> { return this.getPrivate('/api/mix/v1/trace/profitDateGroupList', { marginCoin, @@ -574,7 +656,7 @@ export class FuturesClient extends BaseRestClient { marginCoin: string, dateMs: string, pageSize: number, - pageNo: number + pageNo: number, ): Promise> { return this.getPrivate('/api/mix/v1/trace/profitDateList', { marginCoin, @@ -587,7 +669,7 @@ export class FuturesClient extends BaseRestClient { /** Get Trader Profits Details */ getCopyTraderProfitDetails( pageSize: number, - pageNo: number + pageNo: number, ): Promise> { return this.getPrivate('/api/mix/v1/trace/waitProfitDateList', { pageSize, @@ -603,7 +685,7 @@ export class FuturesClient extends BaseRestClient { /** Trader Change CopyTrade symbol */ setCopyTraderSymbols( symbol: string, - operation: 'add' | 'delete' + operation: 'add' | 'delete', ): Promise> { return this.postPrivate('/api/mix/v1/trace/setUpCopySymbols', { symbol, diff --git a/src/spot-client.ts b/src/spot-client.ts index a3079ec..1a0c6e5 100644 --- a/src/spot-client.ts +++ b/src/spot-client.ts @@ -20,7 +20,7 @@ import { GetHistoricPlanOrdersParams, SpotMarketTrade, GetHistoricTradesParams, - SpotVIPFeeRate, + VIPFeeRate, } from './types'; import { REST_CLIENT_TYPE_ENUM } from './util'; import BaseRestClient from './util/BaseRestClient'; @@ -83,14 +83,14 @@ export class SpotClient extends BaseRestClient { /** Get most recent trades (up to 500, 100 by default) */ getRecentTrades( symbol: string, - limit?: string + limit?: string, ): Promise> { 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 + params: GetHistoricTradesParams, ): Promise> { return this.get('/api/spot/v1/market/fills-history', params); } @@ -100,7 +100,7 @@ export class SpotClient extends BaseRestClient { */ getMarketTrades( symbol: string, - limit?: string + limit?: string, ): Promise> { return this.get('/api/spot/v1/market/fills', { symbol, limit }); } @@ -109,7 +109,7 @@ export class SpotClient extends BaseRestClient { getCandles( symbol: string, period: KlineInterval, - pagination?: Pagination + pagination?: Pagination, ): Promise> { return this.get('/api/spot/v1/market/candles', { symbol, @@ -122,13 +122,13 @@ export class SpotClient extends BaseRestClient { getDepth( symbol: string, type: 'step0' | 'step1' | 'step2' | 'step3' | 'step4' | 'step5', - limit?: string + limit?: string, ): Promise> { return this.get('/api/spot/v1/market/depth', { symbol, type, limit }); } /** Get VIP fee rates */ - getVIPFeeRates(): Promise> { + getVIPFeeRates(): Promise> { return this.get('/api/spot/v1/market/spot-vip-level'); } @@ -178,7 +178,7 @@ export class SpotClient extends BaseRestClient { coin: string, toUid: string, amount: string, - clientOid?: string + clientOid?: string, ): Promise> { return this.postPrivate('/api/spot/v1/wallet/withdrawal-inner', { coin, @@ -193,7 +193,7 @@ export class SpotClient extends BaseRestClient { coin: string, toUid: string, amount: string, - clientOid?: string + clientOid?: string, ): Promise> { return this.postPrivate('/api/spot/v1/wallet/withdrawal-inner-v2', { coin, @@ -210,7 +210,7 @@ export class SpotClient extends BaseRestClient { endTime: string, pageSize?: string, pageNo?: string, - clientOid?: string + clientOid?: string, ): Promise> { return this.getPrivate('/api/spot/v1/wallet/withdrawal-list', { coin, @@ -228,7 +228,7 @@ export class SpotClient extends BaseRestClient { startTime: string, endTime: string, pageSize?: string, - pageNo?: string + pageNo?: string, ): Promise> { return this.getPrivate('/api/spot/v1/wallet/deposit-list', { coin, @@ -298,7 +298,7 @@ export class SpotClient extends BaseRestClient { /** Place orders in batches, up to 50 at a time */ batchSubmitOrder( symbol: string, - orderList: NewBatchSpotOrder[] + orderList: NewBatchSpotOrder[], ): Promise> { return this.postPrivate('/api/spot/v1/trade/batch-orders', { symbol, @@ -331,7 +331,7 @@ export class SpotClient extends BaseRestClient { /** Cancel order in batch (per symbol) */ batchCancelOrder( symbol: string, - orderIds: string[] + orderIds: string[], ): Promise> { return this.postPrivate('/api/spot/v1/trade/cancel-batch-orders', { symbol, @@ -341,11 +341,11 @@ export class SpotClient extends BaseRestClient { /** Cancel order in batch (per symbol). V2 endpoint, supports orderIds or clientOids. */ batchCancelOrderV2( - params: BatchCancelSpotOrderV2 + params: BatchCancelSpotOrderV2, ): Promise> { return this.postPrivate( '/api/spot/v1/trade/cancel-batch-orders-v2', - params + params, ); } @@ -353,7 +353,7 @@ export class SpotClient extends BaseRestClient { getOrder( symbol: string, orderId: string, - clientOrderId?: string + clientOrderId?: string, ): Promise> { return this.postPrivate('/api/spot/v1/trade/orderInfo', { symbol, @@ -370,7 +370,7 @@ export class SpotClient extends BaseRestClient { /** Get order history for a symbol */ getOrderHistory( symbol: string, - pagination?: Pagination + pagination?: Pagination, ): Promise> { return this.postPrivate('/api/spot/v1/trade/history', { symbol, @@ -382,7 +382,7 @@ export class SpotClient extends BaseRestClient { getOrderFills( symbol: string, orderId: string, - pagination?: Pagination + pagination?: Pagination, ): Promise> { return this.postPrivate('/api/spot/v1/trade/fills', { symbol, @@ -393,21 +393,21 @@ export class SpotClient extends BaseRestClient { /** Place plan order */ submitPlanOrder( - params: NewSpotPlanOrder + params: NewSpotPlanOrder, ): Promise> { return this.postPrivate('/api/spot/v1/plan/placePlan', params); } /** Modify plan order */ modifyPlanOrder( - params: ModifySpotPlanOrder + params: ModifySpotPlanOrder, ): Promise> { return this.postPrivate('/api/spot/v1/plan/modifyPlan', params); } /** Cancel plan order */ cancelPlanOrder( - params: CancelSpotPlanOrderParams + params: CancelSpotPlanOrderParams, ): Promise> { return this.postPrivate('/api/spot/v1/plan/cancelPlan', params); } diff --git a/src/types/request/futures.ts b/src/types/request/futures.ts index 67dfc32..5d934a6 100644 --- a/src/types/request/futures.ts +++ b/src/types/request/futures.ts @@ -51,6 +51,8 @@ export interface NewFuturesOrder { orderType: FuturesOrderType; timeInForceValue?: OrderTimeInForce; clientOid?: string; + reduceOnly?: boolean; + reverse?: boolean; presetTakeProfitPrice?: string; presetStopLossPrice?: string; } @@ -82,6 +84,7 @@ export interface NewFuturesPlanOrder { clientOid?: string; presetTakeProfitPrice?: string; presetStopLossPrice?: string; + reduceOnly?: string; } export interface ModifyFuturesPlanOrder { @@ -90,12 +93,13 @@ export interface ModifyFuturesPlanOrder { symbol: string; executePrice?: string; triggerPrice: string; - triggerType: string; + triggerType: 'fill_price' | 'market_price'; orderType: FuturesOrderType; } export interface ModifyFuturesPlanOrderTPSL { - orderId: string; + orderId?: string; + clientOid?: string; marginCoin: string; symbol: string; presetTakeProfitPrice?: string; @@ -113,6 +117,7 @@ export interface NewFuturesPlanStopOrder { holdSide: FuturesHoldSide; size?: string; rangeRate?: string; + clientOid?: string; } export interface NewFuturesPlanTrailingStopOrder { @@ -123,6 +128,7 @@ export interface NewFuturesPlanTrailingStopOrder { size?: string; side: FuturesOrderSide; rangeRate?: string; + clientOid?: string; } export interface NewFuturesPlanPositionTPSL { @@ -130,18 +136,23 @@ export interface NewFuturesPlanPositionTPSL { marginCoin: string; planType: FuturesPlanType; triggerPrice: string; + triggerType?: 'fill_price' | 'market_price'; holdSide: FuturesHoldSide; + clientOid?: string; } export interface ModifyFuturesPlanStopOrder { - orderId: string; + orderId?: string; + clientOid?: string; marginCoin: string; symbol: string; triggerPrice?: string; + planType: FuturesPlanType; } export interface CancelFuturesPlanTPSL { - orderId: string; + orderId?: string; + clientOid?: string; symbol: string; marginCoin: string; planType: FuturesPlanType; diff --git a/src/types/request/shared.ts b/src/types/request/shared.ts index 0e9bd1e..3a63c26 100644 --- a/src/types/request/shared.ts +++ b/src/types/request/shared.ts @@ -9,3 +9,11 @@ export interface Pagination { } export type OrderTimeInForce = 'normal' | 'post_only' | 'fok' | 'ioc'; + +export interface GetHistoricTradesParams { + symbol: string; + limit?: string; + tradeId?: string; + startTime?: string; + endTime?: string; +} diff --git a/src/types/request/spot.ts b/src/types/request/spot.ts index 3bea3ed..071f2ee 100644 --- a/src/types/request/spot.ts +++ b/src/types/request/spot.ts @@ -1,13 +1,5 @@ import { OrderTimeInForce } from './shared'; -export interface GetHistoricTradesParams { - symbol: string; - limit?: string; - tradeId?: string; - startTime?: string; - endTime?: string; -} - export type WalletType = 'spot' | 'mix_usdt' | 'mix_usd'; export interface NewWalletTransfer { diff --git a/src/types/response/futures.ts b/src/types/response/futures.ts index ae4dcb7..f195bd4 100644 --- a/src/types/response/futures.ts +++ b/src/types/response/futures.ts @@ -4,6 +4,15 @@ import { FuturesMarginMode, } from '../request'; +export interface FuturesMarketTrade { + tradeId: string; + price: string; + size: string; + side: 'buy' | 'sell'; + timestamp: string; + symbol: string; +} + export interface FuturesAccount { marginCoin: string; locked: number; diff --git a/src/types/response/shared.ts b/src/types/response/shared.ts index e97e286..d99b11c 100644 --- a/src/types/response/shared.ts +++ b/src/types/response/shared.ts @@ -4,3 +4,13 @@ export interface APIResponse { msg: 'success' | string; requestTime: number; } + +export interface VIPFeeRate { + level: number; + dealAmount: string; + assetAmount: string; + takerFeeRate?: string; + makerFeeRate?: number; + withdrawAmount: string; + withdrawAmountUSDT: string; +} diff --git a/src/types/response/spot.ts b/src/types/response/spot.ts index dee7775..4cde265 100644 --- a/src/types/response/spot.ts +++ b/src/types/response/spot.ts @@ -20,17 +20,6 @@ export interface SymbolRules { quantityScale: string; status: string; } - -export interface SpotVIPFeeRate { - level: number; - dealAmount: string; - assetAmount: string; - takerFeeRate?: string; - makerFeeRate?: number; - withdrawAmount: string; - withdrawAmountUSDT: string; -} - export interface SpotOrderResult { orderId: string; clientOrderId: string; diff --git a/src/util/BaseRestClient.ts b/src/util/BaseRestClient.ts index b2c8a90..1019957 100644 --- a/src/util/BaseRestClient.ts +++ b/src/util/BaseRestClient.ts @@ -44,7 +44,7 @@ export default abstract class BaseRestClient { */ constructor( restOptions: RestClientOptions = {}, - networkOptions: AxiosRequestConfig = {} + networkOptions: AxiosRequestConfig = {}, ) { this.options = { recvWindow: 5000, @@ -77,7 +77,7 @@ export default abstract class BaseRestClient { credentials.some((v) => typeof v === 'string') ) { 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, endpoint: string, params?: any, - isPublicApi?: boolean + isPublicApi?: boolean, ): Promise { // Sanity check to make sure it's only ever prefixed by one forward slash const requestUrl = [this.baseUrl, endpoint].join( - endpoint.startsWith('/') ? '' : '/' + endpoint.startsWith('/') ? '' : '/', ); // Build a request and handle signature process @@ -122,7 +122,7 @@ export default abstract class BaseRestClient { endpoint, requestUrl, params, - isPublicApi + isPublicApi, ); // console.log('full request: ', options); @@ -188,7 +188,7 @@ export default abstract class BaseRestClient { data: T, endpoint: string, method: Method, - signMethod: SignMethod + signMethod: SignMethod, ): Promise> { const timestamp = Date.now(); @@ -228,7 +228,7 @@ export default abstract class BaseRestClient { console.error( new Date(), - neverGuard(signMethod, `Unhandled sign method: "${signMessage}"`) + neverGuard(signMethod, `Unhandled sign method: "${signMessage}"`), ); return res; @@ -239,21 +239,21 @@ export default abstract class BaseRestClient { endpoint: string, signMethod: SignMethod, params?: TParams, - isPublicApi?: true + isPublicApi?: true, ): Promise>; private async prepareSignParams( method: Method, endpoint: string, signMethod: SignMethod, params?: TParams, - isPublicApi?: false | undefined + isPublicApi?: false | undefined, ): Promise>; private async prepareSignParams( method: Method, endpoint: string, signMethod: SignMethod, params?: TParams, - isPublicApi?: boolean + isPublicApi?: boolean, ) { if (isPublicApi) { return { @@ -275,7 +275,7 @@ export default abstract class BaseRestClient { endpoint: string, url: string, params?: any, - isPublicApi?: boolean + isPublicApi?: boolean, ): Promise { const options: AxiosRequestConfig = { ...this.globalRequestOptions, @@ -301,7 +301,7 @@ export default abstract class BaseRestClient { endpoint, 'bitget', params, - isPublicApi + isPublicApi, ); const authHeaders = { diff --git a/src/websocket-client.ts b/src/websocket-client.ts index c578a2b..611dad0 100644 --- a/src/websocket-client.ts +++ b/src/websocket-client.ts @@ -61,7 +61,7 @@ interface WebsocketClientEvents { export declare interface WebsocketClient { on( event: U, - listener: WebsocketClientEvents[U] + listener: WebsocketClientEvents[U], ): this; emit( @@ -77,7 +77,7 @@ export class WebsocketClient extends EventEmitter { constructor( options: WSClientConfigurableOptions, - logger?: typeof DefaultLogger + logger?: typeof DefaultLogger, ) { super(); @@ -100,7 +100,7 @@ export class WebsocketClient extends EventEmitter { */ public subscribe( wsTopics: WsTopicSubscribeEventArgs[] | WsTopicSubscribeEventArgs, - isPrivateTopic?: boolean + isPrivateTopic?: boolean, ) { const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics]; @@ -122,7 +122,7 @@ export class WebsocketClient extends EventEmitter { if (!isAuthenticated) { return this.requestSubscribeTopics( wsKey, - topics.filter((topic) => !isPrivateChannel(topic.channel)) + topics.filter((topic) => !isPrivateChannel(topic.channel)), ); } return this.requestSubscribeTopics(wsKey, topics); @@ -132,11 +132,11 @@ export class WebsocketClient extends EventEmitter { if ( !this.wsStore.isConnectionState( wsKey, - WsConnectionStateEnum.CONNECTING + WsConnectionStateEnum.CONNECTING, ) && !this.wsStore.isConnectionState( wsKey, - WsConnectionStateEnum.RECONNECTING + WsConnectionStateEnum.RECONNECTING, ) ) { return this.connect(wsKey); @@ -151,11 +151,11 @@ export class WebsocketClient extends EventEmitter { */ public unsubscribe( wsTopics: WsTopicSubscribeEventArgs[] | WsTopicSubscribeEventArgs, - isPrivateTopic?: boolean + isPrivateTopic?: boolean, ) { const topics = Array.isArray(wsTopics) ? wsTopics : [wsTopics]; 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 @@ -207,7 +207,7 @@ export class WebsocketClient extends EventEmitter { if (this.wsStore.isWsOpen(wsKey)) { this.logger.error( 'Refused to connect to ws with existing active connection', - { ...LOGGER_CATEGORY, wsKey } + { ...LOGGER_CATEGORY, wsKey }, ); return this.wsStore.getWs(wsKey); } @@ -217,7 +217,7 @@ export class WebsocketClient extends EventEmitter { ) { this.logger.error( 'Refused to connect to ws, connection attempt already active', - { ...LOGGER_CATEGORY, wsKey } + { ...LOGGER_CATEGORY, wsKey }, ); return; } @@ -260,7 +260,7 @@ export class WebsocketClient extends EventEmitter { `${context} due to unexpected response error: "${ error?.msg || error?.message || error }"`, - { ...LOGGER_CATEGORY, wsKey, error } + { ...LOGGER_CATEGORY, wsKey, error }, ); break; } @@ -278,7 +278,7 @@ export class WebsocketClient extends EventEmitter { apiKey, apiSecret, apiPass, - recvWindow + recvWindow, ); this.logger.info(`Sending auth request...`, { @@ -375,7 +375,7 @@ export class WebsocketClient extends EventEmitter { */ private requestSubscribeTopics( wsKey: WsKey, - topics: WsTopicSubscribeEventArgs[] + topics: WsTopicSubscribeEventArgs[], ) { if (!topics.length) { return; @@ -384,7 +384,7 @@ export class WebsocketClient extends EventEmitter { const maxTopicsPerEvent = getMaxTopicsPerSubscribeEvent(wsKey); if (maxTopicsPerEvent && topics.length > maxTopicsPerEvent) { 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) { const batch = topics.slice(i, i + maxTopicsPerEvent); @@ -392,7 +392,7 @@ export class WebsocketClient extends EventEmitter { this.requestSubscribeTopics(wsKey, batch); } this.logger.silly( - `Finished batch subscribing to ${topics.length} topics` + `Finished batch subscribing to ${topics.length} topics`, ); return; } @@ -410,7 +410,7 @@ export class WebsocketClient extends EventEmitter { */ private requestUnsubscribeTopics( wsKey: WsKey, - topics: WsTopicSubscribeEventArgs[] + topics: WsTopicSubscribeEventArgs[], ) { if (!topics.length) { return; @@ -419,7 +419,7 @@ export class WebsocketClient extends EventEmitter { const maxTopicsPerEvent = getMaxTopicsPerSubscribeEvent(wsKey); if (maxTopicsPerEvent && topics.length > maxTopicsPerEvent) { 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) { const batch = topics.slice(i, i + maxTopicsPerEvent); @@ -427,7 +427,7 @@ export class WebsocketClient extends EventEmitter { this.requestUnsubscribeTopics(wsKey, batch); } this.logger.silly( - `Finished batch unsubscribing to ${topics.length} topics` + `Finished batch unsubscribing to ${topics.length} topics`, ); return; } @@ -449,13 +449,13 @@ export class WebsocketClient extends EventEmitter { }); if (!wsKey) { 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); if (!ws) { 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); @@ -512,13 +512,13 @@ export class WebsocketClient extends EventEmitter { // Private topics will be resubscribed to once reconnected const topics = [...this.wsStore.getTopics(wsKey)]; const publicTopics = topics.filter( - (topic) => !isPrivateChannel(topic.channel) + (topic) => !isPrivateChannel(topic.channel), ); this.requestSubscribeTopics(wsKey, publicTopics); this.wsStore.get(wsKey, true)!.activePingTimer = setInterval( () => 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 privateTopics = topics.filter((topic) => - isPrivateChannel(topic.channel) + isPrivateChannel(topic.channel), ); if (privateTopics.length) { @@ -665,7 +665,7 @@ export class WebsocketClient extends EventEmitter { public subscribeTopic( instType: BitgetInstType, topic: WsTopic, - instId: string = 'default' + instId: string = 'default', ) { return this.subscribe({ instType, @@ -683,7 +683,7 @@ export class WebsocketClient extends EventEmitter { public unsubscribeTopic( instType: BitgetInstType, topic: WsTopic, - instId: string = 'default' + instId: string = 'default', ) { return this.unsubscribe({ instType, diff --git a/test/spot/private.read.test.ts b/test/spot/private.read.test.ts index 67798ec..8815caa 100644 --- a/test/spot/private.read.test.ts +++ b/test/spot/private.read.test.ts @@ -163,7 +163,7 @@ describe('Private Spot REST API GET Endpoints', () => { it('getCurrentPlanOrders()', async () => { try { expect( - await api.getCurrentPlanOrders({ symbol, pageSize: '20' }) + await api.getCurrentPlanOrders({ symbol, pageSize: '20' }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: { @@ -185,7 +185,7 @@ describe('Private Spot REST API GET Endpoints', () => { pageSize: '20', startTime: '1667889483000', endTime: '1668134732000', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: { diff --git a/test/spot/private.write.test.ts b/test/spot/private.write.test.ts index 8be72ce..aa0dc91 100644 --- a/test/spot/private.write.test.ts +++ b/test/spot/private.write.test.ts @@ -30,7 +30,7 @@ describe('Private Spot REST API POST Endpoints', () => { coin, fromType: 'spot', toType: 'mix_usdt', - }) + }), ).toStrictEqual(''); } catch (e) { // console.error('transfer: ', e); @@ -49,7 +49,7 @@ describe('Private Spot REST API POST Endpoints', () => { coin, fromType: 'spot', toType: 'mix_usdt', - }) + }), ).toStrictEqual(''); } catch (e) { // console.error('transferV2: ', e); @@ -71,7 +71,7 @@ describe('Private Spot REST API POST Endpoints', () => { coin, fromType: 'spot', toType: 'mix_usdt', - }) + }), ).toStrictEqual(''); } catch (e) { // console.error('transferV2: ', e); @@ -90,7 +90,7 @@ describe('Private Spot REST API POST Endpoints', () => { coin, chain: 'TRC20', address: `123456`, - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Array), @@ -110,7 +110,7 @@ describe('Private Spot REST API POST Endpoints', () => { coin, chain: 'TRC20', address: `123456`, - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Array), @@ -158,7 +158,7 @@ describe('Private Spot REST API POST Endpoints', () => { orderType: 'market', quantity: '1', force: 'normal', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Array), @@ -180,7 +180,7 @@ describe('Private Spot REST API POST Endpoints', () => { quantity: '1', force: 'normal', }, - ]) + ]), ).toMatchObject({ ...sucessEmptyResponseObject(), data: { @@ -251,7 +251,7 @@ describe('Private Spot REST API POST Endpoints', () => { orderType: 'market', triggerPrice: 100, orderId: '123456', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Array), @@ -268,7 +268,7 @@ describe('Private Spot REST API POST Endpoints', () => { expect( await api.cancelPlanOrder({ orderId: planOrderId || '123456', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(String), From e9972ef82968dedbbb27b7e5b4562ef0c6a01ef3 Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Wed, 22 Mar 2023 17:02:12 +0000 Subject: [PATCH 07/11] chore(): lint for trailing commas, fix tests with new types --- examples/rest-trade-futures.ts | 8 ++++---- examples/rest-trade-spot.ts | 2 +- examples/ws-private.ts | 2 +- examples/ws-public.ts | 2 +- src/broker-client.ts | 14 +++++++------- src/util/WsStore.ts | 6 +++--- src/util/browser-support.ts | 8 ++++---- src/util/node-support.ts | 2 +- src/util/requestUtils.ts | 6 +++--- src/util/type-guards.ts | 8 ++++---- src/util/websocket-util.ts | 14 +++++++------- test/broker/private.read.test.ts | 14 +++++++------- test/broker/private.write.test.ts | 16 ++++++++-------- test/futures/private.read.test.ts | 24 ++++++++++++------------ test/futures/private.write.test.ts | 29 +++++++++++++++-------------- test/futures/public.test.ts | 2 +- test/response.util.ts | 4 ++-- test/ws.private.test.ts | 4 ++-- test/ws.public.test.ts | 2 +- test/ws.util.ts | 4 ++-- 20 files changed, 86 insertions(+), 85 deletions(-) diff --git a/examples/rest-trade-futures.ts b/examples/rest-trade-futures.ts index 43dc87a..58ca502 100644 --- a/examples/rest-trade-futures.ts +++ b/examples/rest-trade-futures.ts @@ -47,7 +47,7 @@ function promiseSleep(milliseconds) { // WARNING: for sensitive math you should be using a library such as decimal.js! function roundDown(value, decimals) { 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 bitcoinUSDFuturesRule = symbolRulesResult.data.find( - (row) => row.symbol === symbol + (row) => row.symbol === symbol, ); console.log('symbol rules: ', bitcoinUSDFuturesRule); @@ -142,7 +142,7 @@ async function handleWsUpdate(event) { const positionsResult = await client.getPositions('umcbl'); const positionsToClose = positionsResult.data.filter( - (pos) => pos.total !== '0' + (pos) => pos.total !== '0', ); console.log('open positions to close: ', positionsToClose); @@ -167,7 +167,7 @@ async function handleWsUpdate(event) { console.log( 'positions after closing all: ', - await client.getPositions('umcbl') + await client.getPositions('umcbl'), ); } catch (e) { console.error('request failed: ', e); diff --git a/examples/rest-trade-spot.ts b/examples/rest-trade-spot.ts index 02e3441..a990097 100644 --- a/examples/rest-trade-spot.ts +++ b/examples/rest-trade-spot.ts @@ -35,7 +35,7 @@ function promiseSleep(milliseconds) { // WARNING: for sensitive math you should be using a library such as decimal.js! function roundDown(value, decimals) { return Number( - Math.floor(parseFloat(value + 'e' + decimals)) + 'e-' + decimals + Math.floor(parseFloat(value + 'e' + decimals)) + 'e-' + decimals, ); } diff --git a/examples/ws-private.ts b/examples/ws-private.ts index a6356c5..fa74781 100644 --- a/examples/ws-private.ts +++ b/examples/ws-private.ts @@ -22,7 +22,7 @@ import { WebsocketClient, DefaultLogger } from '../src'; // optionally provide rest options, e.g. to pass through a proxy // }, }, - logger + logger, ); wsClient.on('update', (data) => { diff --git a/examples/ws-public.ts b/examples/ws-public.ts index 39c40a2..52a8701 100644 --- a/examples/ws-public.ts +++ b/examples/ws-public.ts @@ -15,7 +15,7 @@ import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../src'; // optionally provide rest options, e.g. to pass through a proxy // }, }, - logger + logger, ); wsClient.on('update', (data) => { diff --git a/src/broker-client.ts b/src/broker-client.ts index 5ca8493..d96816b 100644 --- a/src/broker-client.ts +++ b/src/broker-client.ts @@ -30,7 +30,7 @@ export class BrokerClient extends BaseRestClient { /** Create Sub Account */ createSubAccount( subName: string, - remark?: string + remark?: string, ): Promise> { return this.postPrivate('/api/broker/v1/account/sub-create', { subName, @@ -47,7 +47,7 @@ export class BrokerClient extends BaseRestClient { modifySubAccount( subUid: string, perm: string, - status: 'normal' | 'freeze' | 'del' + status: 'normal' | 'freeze' | 'del', ): Promise> { return this.postPrivate('/api/broker/v1/account/sub-modify', { subUid, @@ -79,7 +79,7 @@ export class BrokerClient extends BaseRestClient { /** Get Sub Future Assets */ getSubFutureAssets( subUid: string, - productType: BrokerProductType + productType: BrokerProductType, ): Promise> { return this.getPrivate('/api/broker/v1/account/sub-future-assets', { subUid, @@ -91,7 +91,7 @@ export class BrokerClient extends BaseRestClient { getSubDepositAddress( subUid: string, coin: string, - chain?: string + chain?: string, ): Promise> { return this.postPrivate('/api/broker/v1/account/sub-address', { subUid, @@ -109,7 +109,7 @@ export class BrokerClient extends BaseRestClient { setSubDepositAutoTransfer( subUid: string, coin: string, - toAccountType: 'spot' | 'mix_usdt' | 'mix_usd' | 'mix_usdc' + toAccountType: 'spot' | 'mix_usdt' | 'mix_usd' | 'mix_usdc', ): Promise> { return this.postPrivate('/api/broker/v1/account/sub-auto-transfer', { subUid, @@ -130,7 +130,7 @@ export class BrokerClient extends BaseRestClient { passphrase: string, remark: string, ip: string, - perm?: string + perm?: string, ): Promise> { return this.postPrivate('/api/broker/v1/manage/sub-api-create', { subUid, @@ -148,7 +148,7 @@ export class BrokerClient extends BaseRestClient { /** Modify Sub ApiKey (Only Broker) */ modifySubAPIKey( - params: BrokerSubAPIKeyModifyRequest + params: BrokerSubAPIKeyModifyRequest, ): Promise> { return this.postPrivate('/api/broker/v1/manage/sub-api-modify', params); } diff --git a/src/util/WsStore.ts b/src/util/WsStore.ts index c02e1da..1151dea 100644 --- a/src/util/WsStore.ts +++ b/src/util/WsStore.ts @@ -82,7 +82,7 @@ export default class WsStore { if (this.hasExistingActiveConnection(key)) { this.logger.warning( 'WsStore setConnection() overwriting existing open connection: ', - this.getWs(key) + this.getWs(key), ); } this.wsState[key] = { @@ -98,7 +98,7 @@ export default class WsStore { const ws = this.getWs(key); this.logger.warning( 'WsStore deleting state for connection still open: ', - ws + ws, ); ws?.close(); } @@ -119,7 +119,7 @@ export default class WsStore { if (this.isWsOpen(key)) { this.logger.warning( 'WsStore setConnection() overwriting existing open connection: ', - this.getWs(key) + this.getWs(key), ); } diff --git a/src/util/browser-support.ts b/src/util/browser-support.ts index 8098e72..3633549 100644 --- a/src/util/browser-support.ts +++ b/src/util/browser-support.ts @@ -11,7 +11,7 @@ function _arrayBufferToBase64(buffer: ArrayBuffer) { export async function signMessage( message: string, secret: string, - method: 'hex' | 'base64' + method: 'hex' | 'base64', ): Promise { const encoder = new TextEncoder(); const key = await window.crypto.subtle.importKey( @@ -19,20 +19,20 @@ export async function signMessage( encoder.encode(secret), { name: 'HMAC', hash: { name: 'SHA-256' } }, false, - ['sign'] + ['sign'], ); const signature = await window.crypto.subtle.sign( 'HMAC', key, - encoder.encode(message) + encoder.encode(message), ); switch (method) { case 'hex': { return Array.prototype.map .call(new Uint8Array(signature), (x: any) => - ('00' + x.toString(16)).slice(-2) + ('00' + x.toString(16)).slice(-2), ) .join(''); } diff --git a/src/util/node-support.ts b/src/util/node-support.ts index 3d88b55..4afe4b6 100644 --- a/src/util/node-support.ts +++ b/src/util/node-support.ts @@ -4,7 +4,7 @@ import { createHmac } from 'crypto'; export async function signMessage( message: string, secret: string, - method: 'hex' | 'base64' + method: 'hex' | 'base64', ): Promise { const hmac = createHmac('sha256', secret).update(message); diff --git a/src/util/requestUtils.ts b/src/util/requestUtils.ts index e448bdc..63cc78d 100644 --- a/src/util/requestUtils.ts +++ b/src/util/requestUtils.ts @@ -30,7 +30,7 @@ export interface RestClientOptions { export function serializeParams( params: T, strict_validation = false, - prefixWith: string = '' + prefixWith: string = '', ): string { if (!params) { return ''; @@ -42,7 +42,7 @@ export function serializeParams( const value = params[key]; if (strict_validation === true && typeof value === 'undefined') { throw new Error( - 'Failed to sign API request due to undefined parameter' + 'Failed to sign API request due to undefined parameter', ); } return `${key}=${value}`; @@ -55,7 +55,7 @@ export function serializeParams( export function getRestBaseUrl( useTestnet: boolean, - restInverseOptions: RestClientOptions + restInverseOptions: RestClientOptions, ): string { const exchangeBaseUrls = { livenet: 'https://api.bitget.com', diff --git a/src/util/type-guards.ts b/src/util/type-guards.ts index 2577367..b74709a 100644 --- a/src/util/type-guards.ts +++ b/src/util/type-guards.ts @@ -36,7 +36,7 @@ function isWsChannelEvent(event: WsBaseEvent): event is WsSnapshotChannelEvent { /** TypeGuard: event is an account update (balance) */ export function isWsAccountSnapshotEvent( - event: unknown + event: unknown, ): event is WsSnapshotAccountEvent { return ( isWsSnapshotEvent(event) && @@ -48,7 +48,7 @@ export function isWsAccountSnapshotEvent( /** TypeGuard: event is a positions update */ export function isWsPositionsSnapshotEvent( - event: unknown + event: unknown, ): event is WsSnapshotPositionsEvent { return ( isWsSnapshotEvent(event) && @@ -60,14 +60,14 @@ export function isWsPositionsSnapshotEvent( /** TypeGuard: event is a UMCBL account update (balance) */ export function isWsFuturesAccountSnapshotEvent( - event: unknown + event: unknown, ): event is WsAccountSnapshotUMCBL { return isWsAccountSnapshotEvent(event) && event.arg.instType === 'umcbl'; } /** TypeGuard: event is a UMCBL positions update */ export function isWsFuturesPositionsSnapshotEvent( - event: unknown + event: unknown, ): event is WSPositionSnapshotUMCBL { return isWsPositionsSnapshotEvent(event) && event.arg.instType === 'umcbl'; } diff --git a/src/util/websocket-util.ts b/src/util/websocket-util.ts index 844c873..6b9645b 100644 --- a/src/util/websocket-util.ts +++ b/src/util/websocket-util.ts @@ -11,7 +11,7 @@ import { BitgetInstType, WsTopicSubscribeEventArgs } from './WsStore'; */ type NetworkMap< TRequiredKeys extends string, - TOptionalKeys extends string | undefined = undefined + TOptionalKeys extends string | undefined = undefined, > = Record & (TOptionalKeys extends string ? Record @@ -55,14 +55,14 @@ export const PUBLIC_WS_KEYS = [] as WsKey[]; export const PRIVATE_TOPICS = ['account', 'orders', 'positions', 'ordersAlgo']; export function isPrivateChannel( - channel: TChannel + channel: TChannel, ): boolean { return PRIVATE_TOPICS.includes(channel); } export function getWsKeyForTopic( subscribeEvent: WsTopicSubscribeEventArgs, - isPrivate?: boolean + isPrivate?: boolean, ): WsKey { const instType = subscribeEvent.instType.toUpperCase() as BitgetInstType; switch (instType) { @@ -78,7 +78,7 @@ export function getWsKeyForTopic( default: { throw neverGuard( instType, - `getWsKeyForTopic(): Unhandled market ${'instrumentId'}` + `getWsKeyForTopic(): Unhandled market ${'instrumentId'}`, ); } } @@ -110,14 +110,14 @@ export async function getWsAuthSignature( apiKey: string | undefined, apiSecret: string | undefined, apiPass: string | undefined, - recvWindow: number = 0 + recvWindow: number = 0, ): Promise<{ expiresAt: number; signature: string; }> { if (!apiKey || !apiSecret || !apiPass) { 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); @@ -125,7 +125,7 @@ export async function getWsAuthSignature( const signature = await signMessage( signatureExpiresAt + 'GET' + '/user/verify', apiSecret, - 'base64' + 'base64', ); return { diff --git a/test/broker/private.read.test.ts b/test/broker/private.read.test.ts index 67522a9..cb92c57 100644 --- a/test/broker/private.read.test.ts +++ b/test/broker/private.read.test.ts @@ -27,7 +27,7 @@ describe('Private Broker REST API GET Endpoints', () => { it('getBrokerInfo()', async () => { try { expect(await api.getBrokerInfo()).toMatchObject( - sucessEmptyResponseObject() + sucessEmptyResponseObject(), ); } catch (e) { expect(e.body).toMatchObject({ @@ -39,7 +39,7 @@ describe('Private Broker REST API GET Endpoints', () => { it('getSubAccounts()', async () => { try { expect(await api.getSubAccounts()).toMatchObject( - sucessEmptyResponseObject() + sucessEmptyResponseObject(), ); } catch (e) { expect(e.body).toMatchObject({ @@ -51,7 +51,7 @@ describe('Private Broker REST API GET Endpoints', () => { it('getSubEmail()', async () => { try { expect(await api.getSubEmail(subUid)).toMatchObject( - sucessEmptyResponseObject() + sucessEmptyResponseObject(), ); } catch (e) { expect(e.body).toMatchObject({ @@ -63,7 +63,7 @@ describe('Private Broker REST API GET Endpoints', () => { it('getSubSpotAssets()', async () => { try { expect(await api.getSubSpotAssets(subUid)).toMatchObject( - sucessEmptyResponseObject() + sucessEmptyResponseObject(), ); } catch (e) { // expect(e.body).toBeNull(); @@ -76,7 +76,7 @@ describe('Private Broker REST API GET Endpoints', () => { it('getSubFutureAssets()', async () => { try { expect(await api.getSubFutureAssets(subUid, 'usdt')).toMatchObject( - sucessEmptyResponseObject() + sucessEmptyResponseObject(), ); } catch (e) { expect(e.body).toMatchObject({ @@ -88,7 +88,7 @@ describe('Private Broker REST API GET Endpoints', () => { it('getSubDepositAddress()', async () => { try { expect(await api.getSubDepositAddress(subUid, coin)).toMatchObject( - sucessEmptyResponseObject() + sucessEmptyResponseObject(), ); } catch (e) { expect(e.body).toMatchObject({ @@ -100,7 +100,7 @@ describe('Private Broker REST API GET Endpoints', () => { it('getSubAPIKeys()', async () => { try { expect(await api.getSubAPIKeys(subUid)).toMatchObject( - sucessEmptyResponseObject() + sucessEmptyResponseObject(), ); } catch (e) { expect(e.body).toMatchObject({ diff --git a/test/broker/private.write.test.ts b/test/broker/private.write.test.ts index a7e15ff..c9dd3ef 100644 --- a/test/broker/private.write.test.ts +++ b/test/broker/private.write.test.ts @@ -27,7 +27,7 @@ describe('Private Broker REST API POST Endpoints', () => { it('createSubAccount()', async () => { try { expect(await api.createSubAccount('test1')).toMatchObject( - sucessEmptyResponseObject() + sucessEmptyResponseObject(), ); } catch (e) { expect(e.body).toMatchObject({ @@ -39,7 +39,7 @@ describe('Private Broker REST API POST Endpoints', () => { it('modifySubAccount()', async () => { try { expect( - await api.modifySubAccount('test1', 'spot_trade,transfer', 'normal') + await api.modifySubAccount('test1', 'spot_trade,transfer', 'normal'), ).toMatchObject(sucessEmptyResponseObject()); } catch (e) { expect(e.body).toMatchObject({ @@ -51,7 +51,7 @@ describe('Private Broker REST API POST Endpoints', () => { it('modifySubEmail()', async () => { try { expect( - await api.modifySubEmail('test1', 'ASDFASDF@LKMASDF.COM') + await api.modifySubEmail('test1', 'ASDFASDF@LKMASDF.COM'), ).toMatchObject(sucessEmptyResponseObject()); } catch (e) { expect(e.body).toMatchObject({ @@ -69,7 +69,7 @@ describe('Private Broker REST API POST Endpoints', () => { chain: 'TRC20', coin: 'USDT', subUid, - }) + }), ).toMatchObject(sucessEmptyResponseObject()); } catch (e) { expect(e.body).toMatchObject({ @@ -81,7 +81,7 @@ describe('Private Broker REST API POST Endpoints', () => { it('setSubDepositAutoTransfer()', async () => { try { expect( - await api.setSubDepositAutoTransfer(subUid, 'USDT', 'spot') + await api.setSubDepositAutoTransfer(subUid, 'USDT', 'spot'), ).toMatchObject(sucessEmptyResponseObject()); } catch (e) { expect(e.body).toMatchObject({ @@ -97,8 +97,8 @@ describe('Private Broker REST API POST Endpoints', () => { subUid, 'passphrase12345', 'remark', - '10.0.0.1' - ) + '10.0.0.1', + ), ).toMatchObject(sucessEmptyResponseObject()); } catch (e) { expect(e.body).toMatchObject({ @@ -114,7 +114,7 @@ describe('Private Broker REST API POST Endpoints', () => { apikey: '12345', subUid, remark: 'test', - }) + }), ).toMatchObject(sucessEmptyResponseObject()); } catch (e) { expect(e.body).toMatchObject({ diff --git a/test/futures/private.read.test.ts b/test/futures/private.read.test.ts index 4adc392..b117c50 100644 --- a/test/futures/private.read.test.ts +++ b/test/futures/private.read.test.ts @@ -57,7 +57,7 @@ describe('Private Futures REST API GET Endpoints', () => { it('getOpenCount()', async () => { try { expect( - await api.getOpenCount(symbol, marginCoin, 20000, 1) + await api.getOpenCount(symbol, marginCoin, 20000, 1), ).toMatchObject({ ...sucessEmptyResponseObject(), data: { @@ -102,7 +102,7 @@ describe('Private Futures REST API GET Endpoints', () => { endTime: to, marginCoin, symbol, - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: { @@ -125,7 +125,7 @@ describe('Private Futures REST API GET Endpoints', () => { startTime: from, endTime: to, productType: 'umcbl', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: { @@ -180,7 +180,7 @@ describe('Private Futures REST API GET Endpoints', () => { it('getProductTypeOrderHistory()', async () => { try { expect( - await api.getProductTypeOrderHistory('umcbl', from, to, '10') + await api.getProductTypeOrderHistory('umcbl', from, to, '10'), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Object), @@ -223,7 +223,7 @@ describe('Private Futures REST API GET Endpoints', () => { await api.getProductTypeOrderFills('umcbl', { startTime: from, endTime: to, - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Object), @@ -253,7 +253,7 @@ describe('Private Futures REST API GET Endpoints', () => { startTime: from, endTime: to, symbol, - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Object), @@ -267,7 +267,7 @@ describe('Private Futures REST API GET Endpoints', () => { it('getCopyTraderOpenOrder()', async () => { try { expect( - await api.getCopyTraderOpenOrder(symbol, 'umcbl', 1, 0) + await api.getCopyTraderOpenOrder(symbol, 'umcbl', 1, 0), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Object), @@ -282,7 +282,7 @@ describe('Private Futures REST API GET Endpoints', () => { it('getCopyFollowersOpenOrder()', async () => { try { expect( - await api.getCopyFollowersOpenOrder(symbol, 'umcbl', 1, 0) + await api.getCopyFollowersOpenOrder(symbol, 'umcbl', 1, 0), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Object), @@ -300,7 +300,7 @@ describe('Private Futures REST API GET Endpoints', () => { { ...sucessEmptyResponseObject(), data: expect.any(Object), - } + }, ); } catch (e) { expect(e.body).toMatchObject({ @@ -342,8 +342,8 @@ describe('Private Futures REST API GET Endpoints', () => { marginCoin, from, 1, - 1 - ) + 1, + ), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Object), @@ -358,7 +358,7 @@ describe('Private Futures REST API GET Endpoints', () => { it('getCopyTraderHistoricProfitDetail()', async () => { try { expect( - await api.getCopyTraderHistoricProfitDetail(marginCoin, from, 1, 1) + await api.getCopyTraderHistoricProfitDetail(marginCoin, from, 1, 1), ).toMatchObject({ ...sucessEmptyResponseObject(), data: expect.any(Object), diff --git a/test/futures/private.write.test.ts b/test/futures/private.write.test.ts index d4464f4..d7d5492 100644 --- a/test/futures/private.write.test.ts +++ b/test/futures/private.write.test.ts @@ -53,7 +53,7 @@ describe('Private Futures REST API POST Endpoints', () => { it('setMarginMode()', async () => { try { expect( - await api.setMarginMode(symbol, marginCoin, 'crossed') + await api.setMarginMode(symbol, marginCoin, 'crossed'), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -76,7 +76,7 @@ describe('Private Futures REST API POST Endpoints', () => { symbol, size: '1', side: 'open_long', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -100,7 +100,7 @@ describe('Private Futures REST API POST Endpoints', () => { size: '1', side: 'open_long', }, - ]) + ]), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -115,7 +115,7 @@ describe('Private Futures REST API POST Endpoints', () => { it('cancelOrder()', async () => { try { expect( - await api.cancelOrder(symbol, marginCoin, '1234656') + await api.cancelOrder(symbol, marginCoin, '1234656'), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -130,7 +130,7 @@ describe('Private Futures REST API POST Endpoints', () => { it('batchCancelOrder()', async () => { try { expect( - await api.batchCancelOrder(symbol, marginCoin, ['1234656']) + await api.batchCancelOrder(symbol, marginCoin, ['1234656']), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -164,7 +164,7 @@ describe('Private Futures REST API POST Endpoints', () => { symbol, triggerPrice: '1000', triggerType: 'market_price', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -187,7 +187,7 @@ describe('Private Futures REST API POST Endpoints', () => { symbol, triggerPrice: '100', triggerType: 'market_price', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -207,7 +207,7 @@ describe('Private Futures REST API POST Endpoints', () => { marginCoin, symbol, presetTakeProfitPrice: '100', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -229,7 +229,7 @@ describe('Private Futures REST API POST Endpoints', () => { planType: 'profit_plan', holdSide: 'long', triggerPrice: '100', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -251,7 +251,7 @@ describe('Private Futures REST API POST Endpoints', () => { holdSide: 'long', planType: 'profit_plan', triggerPrice: '50', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -270,7 +270,8 @@ describe('Private Futures REST API POST Endpoints', () => { marginCoin, symbol, orderId: '123456', - }) + planType: 'profit_plan', + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -292,7 +293,7 @@ describe('Private Futures REST API POST Endpoints', () => { symbol, orderId: '123456', planType: 'profit_plan', - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, @@ -310,7 +311,7 @@ describe('Private Futures REST API POST Endpoints', () => { { ...sucessEmptyResponseObject(), data: {}, - } + }, ); } catch (e) { expect(e.body).toMatchObject({ @@ -324,7 +325,7 @@ describe('Private Futures REST API POST Endpoints', () => { expect( await api.modifyCopyTraderTPSL(symbol, '123456', { stopLossPrice: 1234, - }) + }), ).toMatchObject({ ...sucessEmptyResponseObject(), data: {}, diff --git a/test/futures/public.test.ts b/test/futures/public.test.ts index 804e2ae..2076fe4 100644 --- a/test/futures/public.test.ts +++ b/test/futures/public.test.ts @@ -70,7 +70,7 @@ describe('Public Spot REST API Endpoints', () => { it('getCandles()', async () => { expect( - await api.getCandles(symbol, '1min', `${from}`, `${to}`) + await api.getCandles(symbol, '1min', `${from}`, `${to}`), ).toMatchObject(expect.any(Array)); }); diff --git a/test/response.util.ts b/test/response.util.ts index 4d704ce..6679da0 100644 --- a/test/response.util.ts +++ b/test/response.util.ts @@ -19,7 +19,7 @@ export function sucessEmptyResponseObject() { export function errorResponseObject( result: null | any = null, ret_code: number, - ret_msg: string + ret_msg: string, ) { return { result, @@ -30,7 +30,7 @@ export function errorResponseObject( export function errorResponseObjectV3( result: null | any = null, - retCode: number + retCode: number, ) { return { result, diff --git a/test/ws.private.test.ts b/test/ws.private.test.ts index 3c735b5..7354069 100644 --- a/test/ws.private.test.ts +++ b/test/ws.private.test.ts @@ -26,7 +26,7 @@ describe('Private Spot Websocket Client', () => { apiSecret: 'bad', apiPass: 'bad', }, - getSilentLogger('expect401') + getSilentLogger('expect401'), ); // const wsOpenPromise = waitForSocketEvent(badClient, 'open'); @@ -62,7 +62,7 @@ describe('Private Spot Websocket Client', () => { beforeAll(() => { wsClient = new WebsocketClient( wsClientOptions, - getSilentLogger('expectSuccess') + getSilentLogger('expectSuccess'), ); wsClient.connectAll(); // logAllEvents(wsClient); diff --git a/test/ws.public.test.ts b/test/ws.public.test.ts index 815f48d..0b6539b 100644 --- a/test/ws.public.test.ts +++ b/test/ws.public.test.ts @@ -13,7 +13,7 @@ describe('Public Spot Websocket Client', () => { beforeAll(() => { wsClient = new WebsocketClient( wsClientOptions, - getSilentLogger('expectSuccess') + getSilentLogger('expectSuccess'), ); wsClient.connectAll(); logAllEvents(wsClient); diff --git a/test/ws.util.ts b/test/ws.util.ts index ad509e7..1a83175 100644 --- a/test/ws.util.ts +++ b/test/ws.util.ts @@ -24,12 +24,12 @@ export const fullLogger = { export function waitForSocketEvent( wsClient: WebsocketClient, event: WsClientEvent, - timeoutMs: number = 4.5 * 1000 + timeoutMs: number = 4.5 * 1000, ) { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { 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); From 3942f7e3f52e6f63ccab6c6f24a05002e8686158 Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Wed, 22 Mar 2023 17:04:14 +0000 Subject: [PATCH 08/11] fix(): fix broken test --- test/futures/private.write.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/futures/private.write.test.ts b/test/futures/private.write.test.ts index d7d5492..5446cca 100644 --- a/test/futures/private.write.test.ts +++ b/test/futures/private.write.test.ts @@ -279,8 +279,7 @@ describe('Private Futures REST API POST Endpoints', () => { } catch (e) { // expect(e).toBeNull(); expect(e.body).toMatchObject({ - // code: API_ERROR_CODE.FUTURES_ORDER_TPSL_NOT_FOUND, - code: API_ERROR_CODE.FUTURES_POSITION_DIRECTION_EMPTY, + code: API_ERROR_CODE.FUTURES_ORDER_TPSL_NOT_FOUND, }); } }); From a7d978834deccd3fff2102ca33bbfdb6c258c3c1 Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Wed, 22 Mar 2023 17:08:12 +0000 Subject: [PATCH 09/11] v1.0.5: add new spot & futures endpoints, add new parameters --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 53dfe5d..15aec87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "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.", "main": "lib/index.js", "types": "lib/index.d.ts", From 1d1a4b82171e147efe4cfe8f75ec1b3a465e47f3 Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Thu, 23 Mar 2023 10:09:47 +0000 Subject: [PATCH 10/11] fix(): typo in url --- src/futures-client.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/futures-client.ts b/src/futures-client.ts index 9372d0a..aef11f5 100644 --- a/src/futures-client.ts +++ b/src/futures-client.ts @@ -21,7 +21,6 @@ import { FuturesPosition, NewFuturesPlanTrailingStopOrder, VIPFeeRate, - SpotMarketTrade, GetHistoricTradesParams, FuturesMarketTrade, FuturesPlanType, @@ -67,7 +66,7 @@ export class FuturesClient extends BaseRestClient { /** Get VIP fee rates */ getVIPFeeRates(): Promise> { - return this.get('/api/spot/v1/market/spot-vip-level'); + return this.get('/api/mix/v1/market/contract-vip-level'); } /** Get most recent trades (up to 500, 100 by default) */ From e9d9b148b0b992c422373167d7eff57496262507 Mon Sep 17 00:00:00 2001 From: Tiago Siebler Date: Thu, 23 Mar 2023 10:12:21 +0000 Subject: [PATCH 11/11] chore(): clean empty comment --- src/spot-client.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/spot-client.ts b/src/spot-client.ts index 1a0c6e5..f57ed72 100644 --- a/src/spot-client.ts +++ b/src/spot-client.ts @@ -433,6 +433,4 @@ export class SpotClient extends BaseRestClient { > { return this.postPrivate('/api/spot/v1/plan/historyPlan', params); } - - // }