From cde6f1b9a3008462e89865021b5d10a2e7783e22 Mon Sep 17 00:00:00 2001 From: JJ-Cro Date: Tue, 25 Mar 2025 16:52:04 +0100 Subject: [PATCH] chore(): reuploaded tests for legacy client --- test/broker/private.read.test.ts | 111 ++++++++ test/broker/private.write.test.ts | 125 +++++++++ test/futures/private.read.test.ts | 398 +++++++++++++++++++++++++++++ test/futures/private.write.test.ts | 352 +++++++++++++++++++++++++ test/futures/public.test.ts | 143 +++++++++++ test/spot/private.read.test.ts | 202 +++++++++++++++ test/spot/private.write.test.ts | 302 ++++++++++++++++++++++ test/spot/public.test.ts | 105 ++++++++ 8 files changed, 1738 insertions(+) create mode 100644 test/broker/private.read.test.ts create mode 100644 test/broker/private.write.test.ts create mode 100644 test/futures/private.read.test.ts create mode 100644 test/futures/private.write.test.ts create mode 100644 test/futures/public.test.ts create mode 100644 test/spot/private.read.test.ts create mode 100644 test/spot/private.write.test.ts create mode 100644 test/spot/public.test.ts diff --git a/test/broker/private.read.test.ts b/test/broker/private.read.test.ts new file mode 100644 index 0000000..f881293 --- /dev/null +++ b/test/broker/private.read.test.ts @@ -0,0 +1,111 @@ +import { API_ERROR_CODE, BrokerClient } from '../../src'; +import { sucessEmptyResponseObject } from '../response.util'; + +describe('Private Broker REST API GET Endpoints', () => { + const API_KEY = process.env.API_KEY_COM; + const API_SECRET = process.env.API_SECRET_COM; + const API_PASS = process.env.API_PASS_COM; + + it('should have api credentials to test with', () => { + expect(API_KEY).toStrictEqual(expect.any(String)); + expect(API_SECRET).toStrictEqual(expect.any(String)); + expect(API_PASS).toStrictEqual(expect.any(String)); + }); + + const api = new BrokerClient({ + apiKey: API_KEY, + apiSecret: API_SECRET, + apiPass: API_PASS, + }); + + const coin = 'BTC'; + const subUid = '123456'; + // const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60; + // const from = timestampOneHourAgo.toFixed(0); + // const to = String(Number(from) + 1000 * 60 * 30); // 30 minutes + + it('getBrokerInfo()', async () => { + try { + expect(await api.getBrokerInfo()).toMatchObject( + sucessEmptyResponseObject(), + ); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('getSubAccounts()', async () => { + try { + expect(await api.getSubAccounts()).toMatchObject( + sucessEmptyResponseObject(), + ); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('getSubEmail()', async () => { + try { + expect(await api.getSubEmail(subUid)).toMatchObject( + sucessEmptyResponseObject(), + ); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('getSubSpotAssets()', async () => { + try { + expect(await api.getSubSpotAssets(subUid)).toMatchObject( + sucessEmptyResponseObject(), + ); + } catch (e) { + // expect(e.body).toBeNull(); + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('getSubFutureAssets()', async () => { + try { + expect(await api.getSubFutureAssets(subUid, 'usdt')).toMatchObject( + sucessEmptyResponseObject(), + ); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('getSubDepositAddress()', async () => { + try { + expect(await api.getSubDepositAddress(subUid, coin)).toMatchObject( + sucessEmptyResponseObject(), + ); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('getSubAPIKeys()', async () => { + try { + expect(await api.getSubAPIKeys(subUid)).toMatchObject( + sucessEmptyResponseObject(), + ); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); +}); diff --git a/test/broker/private.write.test.ts b/test/broker/private.write.test.ts new file mode 100644 index 0000000..8fb7448 --- /dev/null +++ b/test/broker/private.write.test.ts @@ -0,0 +1,125 @@ +import { API_ERROR_CODE, BrokerClient } from '../../src'; +import { sucessEmptyResponseObject } from '../response.util'; + +describe('Private Broker REST API POST Endpoints', () => { + const API_KEY = process.env.API_KEY_COM; + const API_SECRET = process.env.API_SECRET_COM; + const API_PASS = process.env.API_PASS_COM; + + it('should have api credentials to test with', () => { + expect(API_KEY).toStrictEqual(expect.any(String)); + expect(API_SECRET).toStrictEqual(expect.any(String)); + expect(API_PASS).toStrictEqual(expect.any(String)); + }); + + const api = new BrokerClient({ + apiKey: API_KEY, + apiSecret: API_SECRET, + apiPass: API_PASS, + }); + + // const coin = 'BTC'; + const subUid = '123456'; + // const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60; + // const from = timestampOneHourAgo.toFixed(0); + // const to = String(Number(from) + 1000 * 60 * 30); // 30 minutes + + it('createSubAccount()', async () => { + try { + expect(await api.createSubAccount('test1')).toMatchObject( + sucessEmptyResponseObject(), + ); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('modifySubAccount()', async () => { + try { + expect( + await api.modifySubAccount('test1', 'spot_trade,transfer', 'normal'), + ).toMatchObject(sucessEmptyResponseObject()); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('modifySubEmail()', async () => { + try { + expect( + await api.modifySubEmail('test1', 'ASDFASDF@LKMASDF.COM'), + ).toMatchObject(sucessEmptyResponseObject()); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('subWithdrawal()', async () => { + try { + expect( + await api.subWithdrawal({ + address: '123455', + amount: '12345', + chain: 'TRC20', + coin: 'USDT', + subUid, + }), + ).toMatchObject(sucessEmptyResponseObject()); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('setSubDepositAutoTransfer()', async () => { + try { + expect( + await api.setSubDepositAutoTransfer(subUid, 'USDT', 'spot'), + ).toMatchObject(sucessEmptyResponseObject()); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('createSubAPIKey()', async () => { + try { + expect( + await api.createSubAPIKey( + subUid, + 'passphrase12345', + 'remark', + '10.0.0.1', + ), + ).toMatchObject(sucessEmptyResponseObject()); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_BROKER, + }); + } + }); + + it('modifySubAPIKey()', async () => { + try { + expect( + await api.modifySubAPIKey({ + apikey: '12345', + subUid, + remark: 'test', + }), + ).toMatchObject(sucessEmptyResponseObject()); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.PASSPHRASE_CANNOT_BE_EMPTY, + }); + } + }); +}); diff --git a/test/futures/private.read.test.ts b/test/futures/private.read.test.ts new file mode 100644 index 0000000..e41ea2d --- /dev/null +++ b/test/futures/private.read.test.ts @@ -0,0 +1,398 @@ +import { API_ERROR_CODE, FuturesClient } from '../../src'; +import { sucessEmptyResponseObject } from '../response.util'; + +describe('Private Futures REST API GET Endpoints', () => { + const API_KEY = process.env.API_KEY_COM; + const API_SECRET = process.env.API_SECRET_COM; + const API_PASS = process.env.API_PASS_COM; + + it('should have api credentials to test with', () => { + expect(API_KEY).toStrictEqual(expect.any(String)); + expect(API_SECRET).toStrictEqual(expect.any(String)); + expect(API_PASS).toStrictEqual(expect.any(String)); + }); + + const api = new FuturesClient({ + apiKey: API_KEY, + apiSecret: API_SECRET, + apiPass: API_PASS, + }); + + const symbol = 'BTCUSDT_UMCBL'; + const marginCoin = '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('getAccount()', async () => { + try { + expect(await api.getAccount(symbol, marginCoin)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + available: expect.any(String), + btcEquity: expect.any(String), + equity: expect.any(String), + marginCoin: expect.any(String), + marginMode: expect.any(String), + }, + }); + } catch (e) { + console.error('getAccount: ', e); + expect(e).toBeNull(); + } + }); + + it('getAccounts()', async () => { + try { + expect(await api.getAccounts('umcbl')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getAccounts: ', e); + expect(e).toBeNull(); + } + }); + + it('getOpenCount()', async () => { + try { + expect( + await api.getOpenCount(symbol, marginCoin, 20000, 1), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + openCount: expect.any(Number), + }, + }); + } catch (e) { + console.error('getOpenCount: ', e); + expect(e).toBeNull(); + } + }); + + it('getPosition()', async () => { + try { + expect(await api.getPosition(symbol, marginCoin)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getPosition: ', e); + expect(e).toBeNull(); + } + }); + + it('getPositions()', async () => { + try { + expect(await api.getPositions('umcbl')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getPosition: ', e); + expect(e).toBeNull(); + } + }); + + it('getAccountBill()', async () => { + try { + expect( + await api.getAccountBill({ + startTime: from, + endTime: to, + marginCoin, + symbol, + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + lastEndId: null, + nextFlag: false, + preFlag: false, + result: expect.any(Array), + }, + }); + } catch (e) { + console.error('getAccountBill: ', e); + expect(e).toBeNull(); + } + }); + + it('getBusinessBill()', async () => { + try { + expect( + await api.getBusinessBill({ + startTime: from, + endTime: to, + productType: 'umcbl', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + lastEndId: null, + nextFlag: false, + preFlag: false, + result: expect.any(Array), + }, + }); + } catch (e) { + console.error('getBusinessBill: ', e); + expect(e).toBeNull(); + } + }); + + it('getOpenSymbolOrders()', async () => { + try { + expect(await api.getOpenSymbolOrders(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getOpenSymbolOrders: ', e); + expect(e).toBeNull(); + } + }); + + it('getOpenOrders()', async () => { + try { + expect(await api.getOpenOrders('umcbl', marginCoin)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getOpenOrders: ', e); + expect(e).toBeNull(); + } + }); + + it('getOrderHistory()', async () => { + try { + expect(await api.getOrderHistory(symbol, from, to, '10')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + console.error('getOrderHistory: ', e); + expect(e).toBeNull(); + } + }); + + it('getProductTypeOrderHistory()', async () => { + try { + expect( + await api.getProductTypeOrderHistory('umcbl', from, to, '10'), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + console.error('getProductTypeOrderHistory: ', e); + expect(e).toBeNull(); + } + }); + + it('getOrder() should throw FUTURES_ORDER_NOT_FOUND', async () => { + try { + expect(await api.getOrder(symbol, '12345')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.FUTURES_ORDER_GET_NOT_FOUND, + }); + } + }); + + it('getOrderFills() should throw FUTURES_ORDER_NOT_FOUND', async () => { + try { + expect(await api.getOrderFills(symbol, '12345')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.FUTURES_ORDER_GET_NOT_FOUND, + }); + } + }); + + it('getProductTypeOrderFills() ', async () => { + try { + expect( + await api.getProductTypeOrderFills('umcbl', { + startTime: from, + endTime: to, + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + console.error('getProductTypeOrderFills: ', e); + expect(e).toBeNull(); + } + }); + + it('getPlanOrderTPSLs()', async () => { + try { + expect(await api.getPlanOrderTPSLs(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + console.error('getPlanOrderTPSLs: ', e); + expect(e).toBeNull(); + } + }); + + it('getHistoricPlanOrdersTPSL()', async () => { + try { + expect( + await api.getHistoricPlanOrdersTPSL({ + startTime: from, + endTime: to, + symbol, + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + console.error('getHistoricPlanOrdersTPSL: ', e); + expect(e).toBeNull(); + } + }); + + it.skip('getCopyTraderOpenOrder()', async () => { + try { + expect( + await api.getCopyTraderOpenOrder(symbol, 'umcbl', 1, 0), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); + + it('getCopyFollowersOpenOrder()', async () => { + try { + expect( + await api.getCopyFollowersOpenOrder(symbol, 'umcbl', 1, 0), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); + + it.skip('getCopyTraderOrderHistory()', async () => { + try { + expect(await api.getCopyTraderOrderHistory(from, to, 1, 0)).toMatchObject( + { + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }, + ); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); + + it('getCopyTraderProfitSummary()', async () => { + try { + expect(await api.getCopyTraderProfitSummary()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); + + it('getCopyTraderHistoricProfitSummary()', async () => { + try { + expect(await api.getCopyTraderHistoricProfitSummary()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); + + it('getCopyTraderHistoricProfitSummaryByDate()', async () => { + try { + expect( + await api.getCopyTraderHistoricProfitSummaryByDate( + marginCoin, + from, + 1, + 1, + ), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); + + it('getCopyTraderHistoricProfitDetail()', async () => { + try { + expect( + await api.getCopyTraderHistoricProfitDetail(marginCoin, from, 1, 1), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); + + it('getCopyTraderProfitDetails()', async () => { + try { + expect(await api.getCopyTraderProfitDetails(1, 1)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); + + it('getCopyTraderSymbols()', async () => { + try { + expect(await api.getCopyTraderSymbols()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Object), + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); +}); diff --git a/test/futures/private.write.test.ts b/test/futures/private.write.test.ts new file mode 100644 index 0000000..7ded747 --- /dev/null +++ b/test/futures/private.write.test.ts @@ -0,0 +1,352 @@ +import { API_ERROR_CODE, FuturesClient } from '../../src'; +import { sucessEmptyResponseObject } from '../response.util'; + +jest.setTimeout(10000); + +describe('Private Futures REST API POST Endpoints', () => { + const API_KEY = process.env.API_KEY_COM; + const API_SECRET = process.env.API_SECRET_COM; + const API_PASS = process.env.API_PASS_COM; + + it('should have api credentials to test with', () => { + expect(API_KEY).toStrictEqual(expect.any(String)); + expect(API_SECRET).toStrictEqual(expect.any(String)); + expect(API_PASS).toStrictEqual(expect.any(String)); + }); + + const api = new FuturesClient({ + apiKey: API_KEY, + apiSecret: API_SECRET, + apiPass: API_PASS, + }); + + const symbol = 'BTCUSDT_UMCBL'; + const marginCoin = '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('setLeverage()', async () => { + try { + expect(await api.setLeverage(symbol, marginCoin, '20')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + console.error('setLeverage: ', e); + expect(e).toBeNull(); + } + }); + + it('setMargin()', async () => { + try { + expect(await api.setMargin(symbol, marginCoin, '-10')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + // expect(e).toBeNull(); + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.PARAMETER_EXCEPTION, + }); + } + }); + + it('setMarginMode()', async () => { + try { + expect( + await api.setMarginMode(symbol, marginCoin, 'crossed'), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + console.error('setMarginMode: ', e); + expect(e).toBeNull(); + } + }); + + it('submitOrder()', async () => { + const symbol = 'BTCUSDT_UMCBL'; + const marginCoin = 'USDT'; + + try { + expect( + await api.submitOrder({ + marginCoin, + orderType: 'market', + symbol, + size: '1', + side: 'open_long', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED, + }); + } + }); + + it('batchSubmitOrder()', async () => { + try { + expect( + await api.batchSubmitOrder(symbol, marginCoin, [ + { + orderType: 'market', + size: '1', + side: 'open_long', + }, + ]), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED, + }); + } + }); + + it('cancelOrder()', async () => { + try { + expect( + await api.cancelOrder(symbol, marginCoin, '1234656'), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.FUTURES_ORDER_CANCEL_NOT_FOUND, + }); + } + }); + + it('batchCancelOrder()', async () => { + try { + expect( + await api.batchCancelOrder(symbol, marginCoin, ['1234656']), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + console.error('batchCancelOrder: ', e); + expect(e).toBeNull(); + } + }); + + it('cancelAllOrders()', async () => { + try { + expect(await api.cancelAllOrders('umcbl', marginCoin)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.NO_ORDER_TO_CANCEL, + }); + } + }); + + it.skip('submitPlanOrder()', async () => { + try { + expect( + await api.submitPlanOrder({ + marginCoin, + orderType: 'market', + side: 'open_long', + size: '0.1', + symbol, + triggerPrice: '1000', + triggerType: 'market_price', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + // {"code": "40889", "data": null, "msg": "The plan order of this contract has reached the upper limit" + // if the above error is seen, you need to cancel trigger orders on the test account (in futures) + console.error('submitPlanOrder: ', e); + expect(e).toBeNull(); + } + }); + + it.skip('modifyPlanOrder()', async () => { + try { + expect( + await api.modifyPlanOrder({ + orderId: '123456', + marginCoin, + orderType: 'market', + symbol, + triggerPrice: '100', + triggerType: 'market_price', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.PLAN_ORDER_NOT_FOUND, + }); + } + }); + + it('modifyPlanOrderTPSL()', async () => { + try { + expect( + await api.modifyPlanOrderTPSL({ + orderId: '123456', + marginCoin, + symbol, + presetTakeProfitPrice: '100', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + // expect(e).toBeNull(); + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.PLAN_ORDER_NOT_FOUND, + }); + } + }); + + it.skip('submitStopOrder()', async () => { + try { + expect( + await api.submitStopOrder({ + marginCoin, + symbol, + planType: 'profit_plan', + holdSide: 'long', + triggerPrice: '100', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + // console.log(e.body); + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.FUTURES_INSUFFICIENT_POSITION_NO_TPSL, + }); + } + }); + + it('submitPositionTPSL()', async () => { + try { + expect( + await api.submitPositionTPSL({ + marginCoin, + symbol, + holdSide: 'long', + planType: 'profit_plan', + triggerPrice: '50', + triggerType: 'market_price', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.FUTURES_INSUFFICIENT_POSITION_NO_TPSL, + }); + } + }); + + it('modifyStopOrder()', async () => { + try { + expect( + await api.modifyStopOrder({ + marginCoin, + symbol, + orderId: '123456', + planType: 'profit_plan', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + // expect(e).toBeNull(); + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.FUTURES_ORDER_TPSL_NOT_FOUND, + }); + } + }); + + it('cancelPlanOrderTPSL()', async () => { + try { + expect( + await api.cancelPlanOrderTPSL({ + marginCoin, + symbol, + orderId: '123456', + planType: 'profit_plan', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.FUTURES_ORDER_TPSL_NOT_FOUND, + }); + } + }); + + it.skip('closeCopyTraderPosition()', async () => { + try { + expect(await api.closeCopyTraderPosition(symbol, '123456')).toMatchObject( + { + ...sucessEmptyResponseObject(), + data: {}, + }, + ); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); + + it.skip('modifyCopyTraderTPSL()', async () => { + try { + expect( + await api.modifyCopyTraderTPSL(symbol, '123456', { + stopLossPrice: 1234, + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); + + it.skip('setCopyTraderSymbols()', async () => { + try { + expect(await api.setCopyTraderSymbols(symbol, 'delete')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: {}, + }); + } catch (e) { + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER, + }); + } + }); +}); diff --git a/test/futures/public.test.ts b/test/futures/public.test.ts new file mode 100644 index 0000000..1b497e1 --- /dev/null +++ b/test/futures/public.test.ts @@ -0,0 +1,143 @@ +import { FuturesClient } from '../../src'; +import { sucessEmptyResponseObject } from '../response.util'; + +describe('Public Spot REST API Endpoints', () => { + const api = new FuturesClient(); + + const symbol = 'BTCUSDT_UMCBL'; + const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60; + const from = Number(timestampOneHourAgo.toFixed(0)); + const to = from + 1000 * 60 * 30; // 30 minutes + + // it('should throw for unauthenticated private calls', async () => { + // expect(() => api.getOpenOrders()).rejects.toMatchObject( + // notAuthenticatedError() + // ); + // expect(() => api.getBalances()).rejects.toMatchObject( + // notAuthenticatedError() + // ); + // }); + + /** + * + * Market + * + */ + it('getSymbols()', async () => { + expect(await api.getSymbols('umcbl')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + }); + + it('getDepth()', async () => { + expect(await api.getDepth(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + bids: expect.any(Array), + asks: expect.any(Array), + }, + }); + }); + + it('getTicker()', async () => { + expect(await api.getTicker(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + bestAsk: expect.any(String), + bestBid: expect.any(String), + }, + }); + }); + + it('getAllTickers()', async () => { + expect(await api.getAllTickers('umcbl')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + }); + + it('getMarketTrades()', async () => { + expect(await api.getMarketTrades(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + }); + + it('getCandles()', async () => { + expect( + await api.getCandles(symbol, '1m', `${from}`, `${to}`), + ).toMatchObject(expect.any(Array)); + }); + + it('getIndexPrice()', async () => { + expect(await api.getIndexPrice(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + index: expect.any(String), + symbol: expect.any(String), + timestamp: expect.any(String), + }, + }); + }); + + it('getNextFundingTime()', async () => { + expect(await api.getNextFundingTime(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + fundingTime: expect.any(String), + symbol: expect.any(String), + }, + }); + }); + + it('getHistoricFundingRate()', async () => { + expect(await api.getHistoricFundingRate(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + }); + + it('getCurrentFundingRate()', async () => { + expect(await api.getCurrentFundingRate(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + fundingRate: expect.any(String), + symbol: expect.any(String), + }, + }); + }); + + it('getOpenInterest()', async () => { + expect(await api.getOpenInterest(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + amount: expect.any(String), + symbol: expect.any(String), + timestamp: expect.any(String), + }, + }); + }); + + it('getMarkPrice()', async () => { + expect(await api.getMarkPrice(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + markPrice: expect.any(String), + symbol: expect.any(String), + timestamp: expect.any(String), + }, + }); + }); + + it('getLeverageMinMax()', async () => { + expect(await api.getLeverageMinMax(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + maxLeverage: expect.any(String), + minLeverage: expect.any(String), + symbol: expect.any(String), + }, + }); + }); +}); diff --git a/test/spot/private.read.test.ts b/test/spot/private.read.test.ts new file mode 100644 index 0000000..761a4a6 --- /dev/null +++ b/test/spot/private.read.test.ts @@ -0,0 +1,202 @@ +import { SpotClient } from '../../src'; +import { sucessEmptyResponseObject } from '../response.util'; + +describe('Private Spot REST API GET Endpoints', () => { + const API_KEY = process.env.API_KEY_COM; + const API_SECRET = process.env.API_SECRET_COM; + const API_PASS = process.env.API_PASS_COM; + + it('should have api credentials to test with', () => { + expect(API_KEY).toStrictEqual(expect.any(String)); + expect(API_SECRET).toStrictEqual(expect.any(String)); + expect(API_PASS).toStrictEqual(expect.any(String)); + }); + + const api = new SpotClient({ + apiKey: API_KEY, + apiSecret: API_SECRET, + apiPass: API_PASS, + }); + + const symbol = 'BTCUSDT_SPBL'; + const coin = 'BTC'; + const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60; + const from = timestampOneHourAgo.toFixed(0); + const to = String(Number(from) + 1000 * 60 * 30); // 30 minutes + + // Seems to throw a permission error, probably because withdrawal permissions aren't set on this key (requires IP whitelist) + it.skip('getDepositAddress()', async () => { + try { + expect(await api.getDepositAddress(coin)).toStrictEqual(''); + } catch (e) { + console.error('exception: ', e); + expect(e).toBeNull(); + } + }); + + it('getWithdrawals()', async () => { + try { + expect(await api.getWithdrawals(coin, from, to)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getWithdrawals: ', e); + expect(e).toBeNull(); + } + }); + + it('getDeposits()', async () => { + try { + expect(await api.getDeposits(coin, from, to)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getDeposits: ', e); + expect(e).toBeNull(); + } + }); + + it('getApiKeyInfo()', async () => { + // No auth error == test pass + try { + expect(await api.getApiKeyInfo()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + user_id: expect.any(String), + authorities: expect.any(Array), + }, + }); + } catch (e) { + console.error('getApiKeyInfo: ', e); + expect(e).toBeNull(); + } + }); + + it('getBalance()', async () => { + try { + // expect(await api.getWithdrawals(coin, from, to)).toStrictEqual(''); + expect(await api.getBalance()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getBalance: ', e); + expect(e).toBeNull(); + } + }); + + it('getTransactionHistory()', async () => { + try { + expect(await api.getTransactionHistory()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getTransactionHistory: ', e); + expect(e).toBeNull(); + } + }); + + // Sees exception now about requiring coinId. Question sent to bitget 7th feb. + it.skip('getTransferHistory()', async () => { + try { + expect(await api.getTransferHistory()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getTransferHistory: ', e); + expect(e).toBeNull(); + } + }); + + it('getOrder()', async () => { + try { + expect(await api.getOrder(symbol, '12345')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getOrder: ', e); + expect(e).toBeNull(); + } + }); + + it('getOpenOrders()', async () => { + try { + expect(await api.getOpenOrders()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getOpenOrders: ', e); + expect(e).toBeNull(); + } + }); + + it('getOrderHistory()', async () => { + try { + expect(await api.getOrderHistory(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getOrderHistory: ', e); + expect(e).toBeNull(); + } + }); + + it('getOrderFills()', async () => { + try { + expect(await api.getOrderFills(symbol, '12345')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.error('getOrderFills: ', e); + expect(e).toBeNull(); + } + }); + + it('getCurrentPlanOrders()', async () => { + try { + expect( + await api.getCurrentPlanOrders({ symbol, pageSize: '20' }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + nextFlag: false, + orderList: expect.any(Array), + }, + }); + } catch (e) { + console.error('getCurrentPlanOrders: ', e); + expect(e).toBeNull(); + } + }); + + it('getHistoricPlanOrders()', async () => { + try { + expect( + await api.getHistoricPlanOrders({ + symbol, + pageSize: '20', + startTime: '1667889483000', + endTime: '1668134732000', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + endId: null, + nextFlag: false, + orderList: expect.any(Array), + }, + }); + } catch (e) { + console.error('getHistoricPlanOrders: ', e); + expect(e).toBeNull(); + } + }); +}); diff --git a/test/spot/private.write.test.ts b/test/spot/private.write.test.ts new file mode 100644 index 0000000..db68dc6 --- /dev/null +++ b/test/spot/private.write.test.ts @@ -0,0 +1,302 @@ +import { API_ERROR_CODE, SpotClient } from '../../src'; +import { sucessEmptyResponseObject } from '../response.util'; + +describe('Private Spot REST API POST Endpoints', () => { + const API_KEY = process.env.API_KEY_COM; + const API_SECRET = process.env.API_SECRET_COM; + const API_PASS = process.env.API_PASS_COM; + + it('should have api credentials to test with', () => { + expect(API_KEY).toStrictEqual(expect.any(String)); + expect(API_SECRET).toStrictEqual(expect.any(String)); + expect(API_PASS).toStrictEqual(expect.any(String)); + }); + + const api = new SpotClient({ + apiKey: API_KEY, + apiSecret: API_SECRET, + apiPass: API_PASS, + }); + + const symbol = 'BTCUSDT_SPBL'; + const coin = 'USDT'; + + 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 kyc. Seems to change? + code: expect.stringMatching(/42013|43117|40035/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 kyc. Seems to change? + code: expect.stringMatching(/42013|43117|40035/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.skip('withdrawV2()', async () => { + try { + expect( + await api.withdrawV2({ + amount: '100', + coin, + chain: 'TRC20', + address: '123456', + }), + ).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.log( + `"${expect.getState().currentTestName}"`, + JSON.stringify(e.body), + ); + + 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.skip('innerWithdrawV2()', async () => { + try { + expect(await api.innerWithdrawV2(coin, '12345', '1')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + } catch (e) { + console.log( + `"${expect.getState().currentTestName}"`, + JSON.stringify(e.body), + ); + + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.INCORRECT_PERMISSIONS, + }); + } + }); + }); + 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.ACCOUNT_KYC_REQUIRED, + }); + } + }); + + 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 }], + }, + }); + } catch (e) { + // console.log(`fn() exception: `, e.body); + + expect(e?.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED, + }); + } + }); + + it('cancelOrder()', async () => { + try { + expect(await api.cancelOrder(symbol, '123456')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: '123456', //expect.any(Array), + }); + } catch (e) { + console.log('cancelorder err', 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, + }); + } + }); + }); + + describe('plan orders', () => { + let planOrderId: string; + + 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({ + code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED, + }); + } catch (e) { + // console.error('submitPlanOrder(): ', e); + expect(e?.body).toMatchObject({ + code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED, + }); + } + }); + + 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(); + expect(e.body).toMatchObject({ + code: API_ERROR_CODE.PLAN_ORDER_NOT_FOUND, + }); + } + }); + }); +}); diff --git a/test/spot/public.test.ts b/test/spot/public.test.ts new file mode 100644 index 0000000..29eed0c --- /dev/null +++ b/test/spot/public.test.ts @@ -0,0 +1,105 @@ +import { SpotClient } from '../../src'; +import { + successResponseString, + sucessEmptyResponseObject, +} from '../response.util'; + +describe('Public Spot REST API Endpoints', () => { + const api = new SpotClient(); + + const symbol = 'BTCUSDT_SPBL'; + + // it('should throw for unauthenticated private calls', async () => { + // expect(() => api.getOpenOrders()).rejects.toMatchObject( + // notAuthenticatedError() + // ); + // expect(() => api.getBalances()).rejects.toMatchObject( + // notAuthenticatedError() + // ); + // }); + + /** + * + * Public + * + */ + + it('getServerTime()', async () => { + // expect(await api.getServerTime()).toStrictEqual(''); + expect(await api.getServerTime()).toMatchObject(successResponseString()); + }); + + it('fetchServertime() returns number', async () => { + expect(await api.fetchServerTime()).toStrictEqual(expect.any(Number)); + }); + + it('getCoins()', async () => { + expect(await api.getCoins()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + }); + + it('getSymbols()', async () => { + expect(await api.getSymbols()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + }); + + it('getSymbol()', async () => { + expect(await api.getSymbol(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + baseCoin: expect.any(String), + }, + }); + }); + + /** + * + * Market + * + */ + + it('getTicker()', async () => { + expect(await api.getTicker(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + askSz: expect.any(String), + baseVol: expect.any(String), + }, + }); + }); + + it('getAllTickers()', async () => { + expect(await api.getAllTickers()).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + }); + + it('getMarketTrades()', async () => { + expect(await api.getMarketTrades(symbol)).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + }); + + it('getCandles()', async () => { + expect(await api.getCandles(symbol, '1min')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: expect.any(Array), + }); + }); + + it('getDepth()', async () => { + expect(await api.getDepth(symbol, 'step0')).toMatchObject({ + ...sucessEmptyResponseObject(), + data: { + bids: expect.any(Array), + asks: expect.any(Array), + }, + }); + }); +});