diff --git a/README.md b/README.md index 84a8b45..c84925f 100644 --- a/README.md +++ b/README.md @@ -305,9 +305,11 @@ See [websocket-client.ts](./src/websocket-client.ts) for further information. --- -## Customise Logging +## Logging -Pass a custom logger which supports the log methods `silly`, `debug`, `notice`, `info`, `warning` and `error`, or override methods from the default logger as desired. +### Customise logging + +Pass a custom logger (or mutate the imported DefaultLogger class) which supports the log methods `silly`, `debug`, `notice`, `info`, `warning` and `error`, or override methods from the default logger as desired, as in the example below: ```javascript const { WebsocketClient, DefaultLogger } = require('bybit-api'); @@ -321,6 +323,10 @@ const customLogger = { const ws = new WebsocketClient({ key: 'xxx', secret: 'yyy' }, customLogger); ``` +### Debug HTTP requests + +In rare situations, you may want to see the raw HTTP requets being built as well as the API response. These can be enabled by setting the `BYBITTRACE` env var to `true`. + ## Browser Usage Build a bundle using webpack: diff --git a/package.json b/package.json index cd0949e..3e949bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bybit-api", - "version": "3.5.7", + "version": "3.5.8", "description": "Complete & robust Node.js SDK for Bybit's REST APIs and WebSockets, with TypeScript & strong end to end tests.", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/src/types/request/v5-asset.ts b/src/types/request/v5-asset.ts index b97f3a7..3e15142 100644 --- a/src/types/request/v5-asset.ts +++ b/src/types/request/v5-asset.ts @@ -39,6 +39,7 @@ export interface GetAccountCoinBalanceParamsV5 { accountType: AccountTypeV5; coin: string; withBonus?: number; + withTransferSafeAmount?: 0 | 1; } export interface GetInternalTransferParamsV5 { @@ -119,6 +120,7 @@ export interface WithdrawParamsV5 { address: string; tag?: string; amount: string; + timestamp: number; forceChain?: number; accountType?: 'SPOT' | 'FUND'; } diff --git a/src/util/BaseRestClient.ts b/src/util/BaseRestClient.ts index 1514dda..d1a69b1 100644 --- a/src/util/BaseRestClient.ts +++ b/src/util/BaseRestClient.ts @@ -11,11 +11,12 @@ import { } from './requestUtils'; import { signMessage } from './node-support'; -if ( +const ENABLE_HTTP_TRACE = typeof process === 'object' && typeof process.env === 'object' && - process.env.BYBITTRACE -) { + process.env.BYBITTRACE; + +if (ENABLE_HTTP_TRACE) { // axios.interceptors.request.use((request) => { // console.log( // new Date(), @@ -209,7 +210,7 @@ export default abstract class BaseRestClient { if (this.options.syncTimeBeforePrivateRequests) { this.timeOffset = await this.fetchTimeOffset(); } - + return this.signRequest(params || {}, method, signMethod); } @@ -314,6 +315,10 @@ export default abstract class BaseRestClient { isPublicApi, ); + if (ENABLE_HTTP_TRACE) { + console.log('full request: ', options); + } + // Dispatch request return axios(options) .then((response) => { diff --git a/test/contract/private.read.test.ts b/test/contract/private.read.test.ts index c1cff4b..7fe9c6a 100644 --- a/test/contract/private.read.test.ts +++ b/test/contract/private.read.test.ts @@ -20,7 +20,7 @@ describe('Private Contract REST API GET Endpoints', () => { const symbol = 'BTCUSDT'; it('getHistoricOrders()', async () => { expect(await api.getHistoricOrders({ symbol })).toMatchObject( - successResponseObjectV3() + successResponseObjectV3(), ); }); @@ -29,7 +29,7 @@ describe('Private Contract REST API GET Endpoints', () => { 'eyJza2lwX2xvY2FsX3N5bWJvbCI6ZmFsc2UsInBhZ2VfdG9rZW4iOiJleUpOSWpwN0luQnJJanA3SWtJaU9pSktSRmt6VG1wcmVFMXFaM2xNVkUwMFQwUlpkRTVFUlRKTmFURm9UakpPYWt4WFVUSk9lbFY1VDBSU2FrMVhXVEJOZHowOUluMHNJbDl6YTE4aU9uc2lRaUk2SWtaNFltMWFZMDV6TUROek1rNTZXVFZOVkVrMFRXa3dlazlFWnpKTVZGRjRUbXBKZEZsVVpHcFplVEZyVG1wak1VMXFaekJaZWtadFRrUk5QU0o5TENKZmRYTmZJanA3SWtJaU9pSkJLMmt2WkZGRlJ5SjlmWDA9In0='; expect( - await api.getHistoricOrders({ symbol, cursor, limit: 1 }) + await api.getHistoricOrders({ symbol, cursor, limit: 1 }), ).toMatchObject({ // retCode: API_ERROR_CODE.DB_ERROR_WRONG_CURSOR, ...successResponseObjectV3(), @@ -43,7 +43,7 @@ describe('Private Contract REST API GET Endpoints', () => { const cursor = orders.result.nextPageCursor; expect( - await api.getHistoricOrders({ symbol, cursor, limit: 1 }) + await api.getHistoricOrders({ symbol, cursor, limit: 1 }), ).toMatchObject({ ...successResponseObjectV3(), retMsg: 'OK', @@ -51,26 +51,27 @@ describe('Private Contract REST API GET Endpoints', () => { }); it('getActiveOrders()', async () => { - expect(await api.getActiveOrders({ symbol })).toMatchObject( - successResponseObjectV3() - ); + expect(await api.getActiveOrders({ symbol })).toMatchObject({ + ...successResponseObjectV3(), + retMsg: 'OK', + }); }); it('getPositions()', async () => { expect(await api.getPositions({ symbol })).toMatchObject( - successResponseObjectV3() + successResponseObjectV3(), ); }); it('getUserExecutionHistory()', async () => { expect(await api.getUserExecutionHistory({ symbol })).toMatchObject( - successResponseObjectV3() + successResponseObjectV3(), ); }); it('getClosedProfitAndLoss()', async () => { expect(await api.getClosedProfitAndLoss({ symbol })).toMatchObject( - successResponseObjectV3() + successResponseObjectV3(), ); }); @@ -88,13 +89,13 @@ describe('Private Contract REST API GET Endpoints', () => { it('getTradingFeeRate()', async () => { expect(await api.getTradingFeeRate()).toMatchObject( - successResponseObjectV3() + successResponseObjectV3(), ); }); it('getWalletFundRecords()', async () => { expect(await api.getWalletFundRecords()).toMatchObject( - successResponseObjectV3() + successResponseObjectV3(), ); }); }); diff --git a/test/v5/private.write.test.ts b/test/v5/private.write.test.ts index 724f2b9..fb8d2d2 100644 --- a/test/v5/private.write.test.ts +++ b/test/v5/private.write.test.ts @@ -46,7 +46,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { side: orderSide, qty: '1', positionIdx: 1, - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -61,7 +61,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { symbol: linearSymbol, qty: '2', orderId: fakeOrderId, - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -75,7 +75,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { category: 'linear', symbol: linearSymbol, orderId: fakeOrderId, - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -88,7 +88,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { await api.cancelAllOrders({ category: 'linear', settleCoin: settleCoin, - }) + }), ).toMatchObject({ ...successResponseObjectV3(), }); @@ -122,7 +122,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { side: orderSide, symbol: optionsSymbol, }, - ]) + ]), ).toMatchObject({ ...successResponseObjectV3(), }); @@ -141,7 +141,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { qty: '4', symbol: optionsSymbol, }, - ]) + ]), ).toMatchObject({ ...successResponseObjectV3(), }); @@ -158,7 +158,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { orderLinkId: 'customOrderId2', symbol: optionsSymbol, }, - ]) + ]), ).toMatchObject({ ...successResponseObjectV3(), }); @@ -171,7 +171,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { // ...successResponseObjectV3(), // retMsg: '', retCode: API_ERROR_CODE.V5_API_KEY_PERMISSION_DENIED, - } + }, ); }); }); @@ -184,7 +184,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { buyLeverage: '5', sellLeverage: '5', symbol: linearSymbol, - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -201,7 +201,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { symbol: linearSymbol, // isolated tradeMode: 1, - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -215,7 +215,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { category: 'linear', symbol: linearSymbol, tpSlMode: 'Full', - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -230,7 +230,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { // both sides mode: 3, coin: settleCoin, - }) + }), ).toMatchObject({ ...successResponseObjectV3(), }); @@ -243,7 +243,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { positionIdx: 1, riskId: 1, symbol: linearSymbol, - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -260,7 +260,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { slSize: '100', slTriggerBy: 'LastPrice', stopLoss: '25000', - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -275,7 +275,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { autoAddMargin: 0, symbol: linearSymbol, positionIdx: 0, - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -301,7 +301,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { frozenPeriod: '1', qtyLimit: '1', window: '1', - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -326,8 +326,8 @@ describe('Private WRITE V5 REST API Endpoints', () => { settleCoin, '100', 'SPOT', - 'CONTRACT' - ) + 'CONTRACT', + ), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -351,7 +351,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { toAccountType: 'CONTRACT', toMemberId: 2, transferId: fakeTransferId, - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -366,7 +366,8 @@ describe('Private WRITE V5 REST API Endpoints', () => { amount: '100', chain: 'TRC20', coin: settleCoin, - }) + timestamp: Date.now(), + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -391,7 +392,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { username: 'sub1account', switch: 1, note: 'created via e2e test', - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), // retMsg: '', @@ -421,7 +422,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { await api.purchaseSpotLeveragedToken({ amount: '100', ltCoin: leverageToken.ltCoin, - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), retCode: API_ERROR_CODE.SPOT_LEVERAGE_QUIZ_REQUIRED, @@ -434,7 +435,7 @@ describe('Private WRITE V5 REST API Endpoints', () => { await api.redeemSpotLeveragedToken({ quantity: '100', ltCoin: leverageToken.ltCoin, - }) + }), ).toMatchObject({ // ...successResponseObjectV3(), retCode: API_ERROR_CODE.SPOT_LEVERAGE_TOKEN_INSUFFICIENT_BALANCE,