From 61c278c31886e6c47dfdde8f8340fde21e10cf8b Mon Sep 17 00:00:00 2001 From: tiagosiebler Date: Wed, 11 May 2022 18:12:44 +0100 Subject: [PATCH] expand test coverage to linear endpoints --- src/linear-client.ts | 10 +- src/util/enum.ts | 10 ++ test/linear/private.read.test.ts | 142 +++++++++--------- test/linear/private.write.test.ts | 231 ++++++++++++++++++++++++++++++ 4 files changed, 311 insertions(+), 82 deletions(-) create mode 100644 test/linear/private.write.test.ts diff --git a/src/linear-client.ts b/src/linear-client.ts index e5842fb..94d4ac3 100644 --- a/src/linear-client.ts +++ b/src/linear-client.ts @@ -386,14 +386,6 @@ export class LinearClient extends BaseRestClient { ); } - /** @deprecated use setPositionTpSlMode() instead */ - setSwitchMode(params?: { - symbol: string; - tp_sl_mode: typeof positionTpSlModeEnum[keyof typeof positionTpSlModeEnum]; - }): GenericAPIResponse { - return this.requestWrapper.post('private/linear/tpsl/switch-mode', params); - } - /** * Switch TP/SL mode between full or partial. When set to Partial, TP/SL orders may have a quantity less than the position size. * This is set with the setTradingStop() method. Use `positionTpSlModeEnum` for the tp_sl_mode parameter. @@ -477,7 +469,7 @@ export class LinearClient extends BaseRestClient { setRiskLimit(params: { symbol: string; side: string; - risk_id: string; + risk_id: number; }): GenericAPIResponse { return this.requestWrapper.post('private/linear/position/set-risk', params); } diff --git a/src/util/enum.ts b/src/util/enum.ts index 152f3d4..fb36dc5 100644 --- a/src/util/enum.ts +++ b/src/util/enum.ts @@ -1,4 +1,5 @@ export const API_ERROR_CODE = { + PARAMS_MISSING_OR_WRONG: 10001, ORDER_NOT_FOUND_OR_TOO_LATE: 20001, POSITION_STATUS_NOT_NORMAL: 30013, CANNOT_SET_TRADING_STOP_FOR_ZERO_POS: 30024, @@ -14,4 +15,13 @@ export const API_ERROR_CODE = { RISK_LIMIT_NOT_EXISTS: 30090, LEVERAGE_NOT_MODIFIED: 34036, SAME_SLTP_MODE: 37002, + ORDER_NOT_FOUND_OR_TOO_LATE_LINEAR: 130010, + ORDER_COST_NOT_AVAILABLE: 130021, + CANNOT_SET_LINEAR_TRADING_STOP_FOR_ZERO_POS: 130024, + ISOLATED_NOT_MODIFIED_LINEAR: 130056, + POSITION_SIZE_IS_ZERO: 130057, + AUTO_ADD_MARGIN_NOT_MODIFIED: 130060, + INSUFFICIENT_BALANCE_FOR_ORDER_COST_LINEAR: 130080, + SAME_SLTP_MODE_LINEAR: 130150, + RISK_ID_NOT_MODIFIED: 134026, } as const; diff --git a/test/linear/private.read.test.ts b/test/linear/private.read.test.ts index f061cf7..fea1db4 100644 --- a/test/linear/private.read.test.ts +++ b/test/linear/private.read.test.ts @@ -1,7 +1,7 @@ import { LinearClient } from '../../src/linear-client'; import { successResponseList, successResponseObject } from '../response.util'; -describe('Public Linear REST API Endpoints', () => { +describe('Public Linear REST API GET Endpoints', () => { const useLivenet = true; const API_KEY = process.env.API_KEY_COM; const API_SECRET = process.env.API_SECRET_COM; @@ -17,91 +17,87 @@ describe('Public Linear REST API Endpoints', () => { const symbol = 'BTCUSDT'; - describe('Linear only private GET endpoints', () => { - it('getApiKeyInfo()', async () => { - expect(await api.getApiKeyInfo()).toMatchObject(successResponseObject()); - }); + it('getApiKeyInfo()', async () => { + expect(await api.getApiKeyInfo()).toMatchObject(successResponseObject()); + }); - it('getWalletBalance()', async () => { - expect(await api.getWalletBalance()).toMatchObject( - successResponseObject() - ); - }); + it('getWalletBalance()', async () => { + expect(await api.getWalletBalance()).toMatchObject(successResponseObject()); + }); - it('getWalletFundRecords()', async () => { - expect(await api.getWalletFundRecords()).toMatchObject( - successResponseObject() - ); - }); + it('getWalletFundRecords()', async () => { + expect(await api.getWalletFundRecords()).toMatchObject( + successResponseObject() + ); + }); - it('getWithdrawRecords()', async () => { - expect(await api.getWithdrawRecords()).toMatchObject( - successResponseObject() - ); - }); + it('getWithdrawRecords()', async () => { + expect(await api.getWithdrawRecords()).toMatchObject( + successResponseObject() + ); + }); - it('getAssetExchangeRecords()', async () => { - expect(await api.getAssetExchangeRecords()).toMatchObject( - successResponseList() - ); - }); + it('getAssetExchangeRecords()', async () => { + expect(await api.getAssetExchangeRecords()).toMatchObject( + successResponseList() + ); + }); - it('getActiveOrderList()', async () => { - expect(await api.getActiveOrderList({ symbol: symbol })).toMatchObject( - successResponseObject() - ); - }); + it('getActiveOrderList()', async () => { + expect(await api.getActiveOrderList({ symbol: symbol })).toMatchObject( + successResponseObject() + ); + }); - it('queryActiveOrder()', async () => { - expect(await api.queryActiveOrder({ symbol: symbol })).toMatchObject( - successResponseObject() - ); - }); + it('queryActiveOrder()', async () => { + expect(await api.queryActiveOrder({ symbol: symbol })).toMatchObject( + successResponseObject() + ); + }); - it('getConditionalOrder()', async () => { - expect(await api.getConditionalOrder({ symbol: symbol })).toMatchObject( - successResponseObject() - ); - }); + it('getConditionalOrder()', async () => { + expect(await api.getConditionalOrder({ symbol: symbol })).toMatchObject( + successResponseObject() + ); + }); - it('queryConditionalOrder()', async () => { - expect(await api.queryConditionalOrder({ symbol: symbol })).toMatchObject( - successResponseObject() - ); - }); + it('queryConditionalOrder()', async () => { + expect(await api.queryConditionalOrder({ symbol: symbol })).toMatchObject( + successResponseObject() + ); + }); - it('getPosition()', async () => { - expect(await api.getPosition()).toMatchObject(successResponseObject()); - }); + it('getPosition()', async () => { + expect(await api.getPosition()).toMatchObject(successResponseObject()); + }); - it('getTradeRecords()', async () => { - expect(await api.getTradeRecords({ symbol: symbol })).toMatchObject( - successResponseObject() - ); - }); + it('getTradeRecords()', async () => { + expect(await api.getTradeRecords({ symbol: symbol })).toMatchObject( + successResponseObject() + ); + }); - it('getClosedPnl()', async () => { - expect(await api.getClosedPnl({ symbol: symbol })).toMatchObject( - successResponseObject() - ); - }); + it('getClosedPnl()', async () => { + expect(await api.getClosedPnl({ symbol: symbol })).toMatchObject( + successResponseObject() + ); + }); - it('getRiskLimitList()', async () => { - expect(await api.getRiskLimitList({ symbol: symbol })).toMatchObject( - successResponseList() - ); - }); + it('getRiskLimitList()', async () => { + expect(await api.getRiskLimitList({ symbol: symbol })).toMatchObject( + successResponseList() + ); + }); - it('getPredictedFundingFee()', async () => { - expect( - await api.getPredictedFundingFee({ symbol: symbol }) - ).toMatchObject(successResponseObject()); - }); + it('getPredictedFundingFee()', async () => { + expect(await api.getPredictedFundingFee({ symbol: symbol })).toMatchObject( + successResponseObject() + ); + }); - it('getLastFundingFee()', async () => { - expect(await api.getLastFundingFee({ symbol: symbol })).toMatchObject( - successResponseObject() - ); - }); + it('getLastFundingFee()', async () => { + expect(await api.getLastFundingFee({ symbol: symbol })).toMatchObject( + successResponseObject() + ); }); }); diff --git a/test/linear/private.write.test.ts b/test/linear/private.write.test.ts new file mode 100644 index 0000000..dec3a40 --- /dev/null +++ b/test/linear/private.write.test.ts @@ -0,0 +1,231 @@ +import { LinearClient } from '../../src'; +import { API_ERROR_CODE } from '../../src/util/enum'; +import { successResponseObject } from '../response.util'; + +describe('Private Inverse-Futures REST API POST Endpoints', () => { + const useLivenet = true; + const API_KEY = process.env.API_KEY_COM; + const API_SECRET = process.env.API_SECRET_COM; + + it('should have api credentials to test with', () => { + expect(API_KEY).toStrictEqual(expect.any(String)); + expect(API_SECRET).toStrictEqual(expect.any(String)); + }); + + const api = new LinearClient(API_KEY, API_SECRET, useLivenet, { + disable_time_sync: true, + }); + + // Warning: if some of these start to fail with 10001 params error, it's probably that this future expired and a newer one exists with a different symbol! + const symbol = 'BTCUSDT'; + + // These tests are primarily check auth is working by expecting balance or order not found style errors + + it('placeActiveOrder()', async () => { + expect( + await api.placeActiveOrder({ + side: 'Buy', + symbol, + order_type: 'Limit', + price: 20000, + qty: 1, + time_in_force: 'GoodTillCancel', + reduce_only: false, + close_on_trigger: false, + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.ORDER_COST_NOT_AVAILABLE, + }); + }); + + it('cancelActiveOrder()', async () => { + expect( + await api.cancelActiveOrder({ + symbol, + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE, + ret_msg: 'order not exists or too late to cancel', + }); + }); + + it('cancelAllActiveOrders()', async () => { + expect( + await api.cancelAllActiveOrders({ + symbol, + }) + ).toMatchObject(successResponseObject()); + }); + + it('replaceActiveOrder()', async () => { + expect( + await api.replaceActiveOrder({ + symbol, + order_id: '123123123', + p_r_qty: 1, + p_r_price: 30000, + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE, + ret_msg: 'order not exists or too late to replace', + }); + }); + + it('placeConditionalOrder()', async () => { + expect( + await api.placeConditionalOrder({ + order_type: 'Limit', + side: 'Buy', + symbol, + qty: 1, + price: 8100, + base_price: 8300, + stop_px: 8150, + time_in_force: 'GoodTillCancel', + order_link_id: 'cus_order_id_1', + reduce_only: false, + trigger_by: 'LastPrice', + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.INSUFFICIENT_BALANCE_FOR_ORDER_COST_LINEAR, + ret_msg: 'Insufficient wallet balance', + }); + }); + + it('cancelConditionalOrder()', async () => { + expect( + await api.cancelConditionalOrder({ + symbol, + order_link_id: 'lkasmdflasd', + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE_LINEAR, + ret_msg: 'order not exists or too late to cancel', + }); + }); + + it('cancelAllConditionalOrders()', async () => { + expect( + await api.cancelAllConditionalOrders({ + symbol, + }) + ).toMatchObject(successResponseObject()); + }); + + it('replaceConditionalOrder()', async () => { + expect( + await api.replaceConditionalOrder({ + symbol, + p_r_price: 50000, + p_r_qty: 1, + order_link_id: 'someorderid', + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.ORDER_NOT_FOUND_OR_TOO_LATE_LINEAR, + ret_msg: 'order not exists or too late to replace', + }); + }); + + it('setAutoAddMargin()', async () => { + expect( + await api.setAutoAddMargin({ + symbol, + side: 'Buy', + auto_add_margin: true, + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.AUTO_ADD_MARGIN_NOT_MODIFIED, + ret_msg: 'autoAddMargin not modified', + }); + }); + + it('setMarginSwitch()', async () => { + expect( + await api.setMarginSwitch({ + symbol, + is_isolated: true, + buy_leverage: 5, + sell_leverage: 5, + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.ISOLATED_NOT_MODIFIED_LINEAR, + ret_msg: 'Isolated not modified', + }); + }); + + it('setPositionMode()', async () => { + expect( + await api.setPositionMode({ + symbol, + mode: 'BothSide', + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.POSITION_MODE_NOT_MODIFIED, + ret_msg: 'position mode not modified', + }); + }); + + it('setPositionTpSlMode()', async () => { + expect( + await api.setPositionTpSlMode({ + symbol, + tp_sl_mode: 'Full', + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.SAME_SLTP_MODE_LINEAR, + ret_msg: 'same tp sl mode2', + }); + }); + + it('setAddReduceMargin()', async () => { + expect( + await api.setAddReduceMargin({ + symbol, + side: 'Buy', + margin: 5, + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.POSITION_SIZE_IS_ZERO, + ret_msg: 'position size is zero', + }); + }); + + it('setUserLeverage()', async () => { + expect( + await api.setUserLeverage({ + symbol, + buy_leverage: 5, + sell_leverage: 5, + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.LEVERAGE_NOT_MODIFIED, + ret_msg: 'leverage not modified', + }); + }); + + it('setTradingStop()', async () => { + expect( + await api.setTradingStop({ + symbol, + side: 'Buy', + take_profit: 555, + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.CANNOT_SET_LINEAR_TRADING_STOP_FOR_ZERO_POS, + ret_msg: 'can not set tp/sl/ts for zero position', + }); + }); + + it('setRiskLimit()', async () => { + expect( + await api.setRiskLimit({ + symbol, + side: 'Buy', + risk_id: 2, + }) + ).toMatchObject({ + ret_code: API_ERROR_CODE.RISK_ID_NOT_MODIFIED, + ret_msg: 'risk id not modified', + }); + }); +});