diff --git a/src/rest-client-v5.ts b/src/rest-client-v5.ts index 0262485..0913f3e 100644 --- a/src/rest-client-v5.ts +++ b/src/rest-client-v5.ts @@ -272,7 +272,7 @@ export class RestClientV5 extends BaseRestClient { */ getClientType() { - return REST_CLIENT_TYPE_ENUM.v3; + return REST_CLIENT_TYPE_ENUM.v5; } async fetchServerTime(): Promise { diff --git a/src/spot-client-v3.ts b/src/spot-client-v3.ts index 8c8d0f4..0ccf887 100644 --- a/src/spot-client-v3.ts +++ b/src/spot-client-v3.ts @@ -12,8 +12,8 @@ import BaseRestClient from './util/BaseRestClient'; */ export class SpotClientV3 extends BaseRestClient { getClientType() { - // Follows the same authentication mechanism as other v3 APIs (e.g. USDC) - return REST_CLIENT_TYPE_ENUM.v3; + // Doesn't really matter here, since the only remaining endpoint does not require auth. + return REST_CLIENT_TYPE_ENUM.v5; } async fetchServerTime(): Promise { diff --git a/src/util/BaseRestClient.ts b/src/util/BaseRestClient.ts index 5b43ae2..2309ec9 100644 --- a/src/util/BaseRestClient.ts +++ b/src/util/BaseRestClient.ts @@ -164,10 +164,6 @@ export default abstract class BaseRestClient { } } - private isSpotV1Client() { - return this.clientType === REST_CLIENT_TYPE_ENUM.spot; - } - get(endpoint: string, params?: any) { return this._call('GET', endpoint, params, true); } @@ -263,56 +259,34 @@ export default abstract class BaseRestClient { }; } - // USDC endpoints, unified margin and a few others use a different way of authenticating requests (headers instead of params) - if (this.clientType === REST_CLIENT_TYPE_ENUM.v3) { - const signResult = await this.prepareSignParams( - method, - 'v5auth', - params, - isPublicApi, - ); - - const headers: AxiosRequestConfig['headers'] = { - 'X-BAPI-SIGN-TYPE': 2, - 'X-BAPI-API-KEY': this.key, - 'X-BAPI-TIMESTAMP': signResult.timestamp, - 'X-BAPI-SIGN': signResult.sign, - 'X-BAPI-RECV-WINDOW': signResult.recvWindow, - ...options.headers, - }; - - if (method === 'GET') { - return { - ...options, - headers, - params: signResult.originalParams, - }; - } - - return { - ...options, - headers, - data: signResult.originalParams, - }; - } - const signResult = await this.prepareSignParams( method, - 'v2auth', + 'v5auth', params, isPublicApi, ); - if (method === 'GET' || this.isSpotV1Client()) { + const headers: AxiosRequestConfig['headers'] = { + 'X-BAPI-SIGN-TYPE': 2, + 'X-BAPI-API-KEY': this.key, + 'X-BAPI-TIMESTAMP': signResult.timestamp, + 'X-BAPI-SIGN': signResult.sign, + 'X-BAPI-RECV-WINDOW': signResult.recvWindow, + ...options.headers, + }; + + if (method === 'GET') { return { ...options, - params: signResult.paramsWithSign, + headers, + params: signResult.originalParams, }; } return { ...options, - data: signResult.paramsWithSign, + headers, + data: signResult.originalParams, }; } @@ -476,11 +450,7 @@ export default abstract class BaseRestClient { // Optional, set to 5000 by default. Increase if timestamp/recv_window errors are seen. if (recvWindow) { - if (this.isSpotV1Client()) { - res.originalParams.recvWindow = recvWindow; - } else { - res.originalParams.recv_window = recvWindow; - } + res.originalParams.recv_window = recvWindow; } const sortProperties = true; const encodeValues = false; diff --git a/src/util/requestUtils.ts b/src/util/requestUtils.ts index 492f7a5..751482b 100644 --- a/src/util/requestUtils.ts +++ b/src/util/requestUtils.ts @@ -207,39 +207,13 @@ export function isTopicSubscriptionConfirmation( return true; } -export function isWSAPIResponse( - msg: unknown, -): msg is Omit { - if (typeof msg !== 'object' || !msg) { - return false; - } - - if (typeof msg['op'] !== 'string') { - return false; - } - - return (WS_API_Operations as string[]).includes(msg['op']); -} - -export function isTopicSubscriptionSuccess( - msg: unknown, -): msg is WebsocketSucceededTopicSubscriptionConfirmationEvent { - if (!isTopicSubscriptionConfirmation(msg)) return false; - return msg.success === true; -} - export const APIID = 'bybitapinode'; /** * Used to switch how authentication/requests work under the hood (primarily for SPOT since it's different there) */ export const REST_CLIENT_TYPE_ENUM = { - accountAsset: 'accountAsset', - inverse: 'inverse', - inverseFutures: 'inverseFutures', - linear: 'linear', - spot: 'spot', - v3: 'v3', + v5: 'v5', } as const; export type RestClientType = diff --git a/src/util/typeGuards.ts b/src/util/typeGuards.ts index b391930..f4bcc67 100644 --- a/src/util/typeGuards.ts +++ b/src/util/typeGuards.ts @@ -2,12 +2,15 @@ * Use type guards to narrow down types with minimal efforts. */ +import { WebsocketSucceededTopicSubscriptionConfirmationEvent } from '../types'; +import { WSAPIResponse, WS_API_Operations } from '../types/websockets/ws-api'; import { WSAccountOrderEventV5, WSExecutionEventV5, WSOrderbookEventV5, WSPositionEventV5, } from '../types/websockets/ws-events'; +import { isTopicSubscriptionConfirmation } from './requestUtils'; /** * Type guard to detect a V5 orderbook event (delta & snapshots) @@ -92,3 +95,28 @@ export function isWsExecutionEventV5( return event['topic'] === 'execution'; } + +export function neverGuard(x: never, msg: string): Error { + return new Error(`Unhandled value exception "${x}", ${msg}`); +} + +export function isWSAPIResponse( + msg: unknown, +): msg is Omit { + if (typeof msg !== 'object' || !msg) { + return false; + } + + if (typeof msg['op'] !== 'string') { + return false; + } + + return (WS_API_Operations as string[]).includes(msg['op']); +} + +export function isTopicSubscriptionSuccess( + msg: unknown, +): msg is WebsocketSucceededTopicSubscriptionConfirmationEvent { + if (!isTopicSubscriptionConfirmation(msg)) return false; + return msg.success === true; +} diff --git a/src/util/webCryptoAPI.ts b/src/util/webCryptoAPI.ts index 2aea730..2743aac 100644 --- a/src/util/webCryptoAPI.ts +++ b/src/util/webCryptoAPI.ts @@ -1,4 +1,4 @@ -import { neverGuard } from './websockets'; +import { neverGuard } from './typeGuards'; function bufferToB64(buffer: ArrayBuffer): string { let binary = ''; diff --git a/src/util/websockets/websocket-util.ts b/src/util/websockets/websocket-util.ts index 883d14c..51c4b20 100644 --- a/src/util/websockets/websocket-util.ts +++ b/src/util/websockets/websocket-util.ts @@ -9,6 +9,7 @@ import { import { DefaultLogger } from '../logger'; import { WSAPIRequest } from '../../types/websockets/ws-api'; +import { neverGuard } from '../typeGuards'; export const WS_LOGGER_CATEGORY = { category: 'bybit-ws' }; @@ -301,10 +302,6 @@ export const WS_ERROR_ENUM = { USDC_OPTION_AUTH_FAILED: '3303006', }; -export function neverGuard(x: never, msg: string): Error { - return new Error(`Unhandled value exception "${x}", ${msg}`); -} - /** * #305: ws.terminate() is undefined in browsers. * This only works in node.js, not in browsers.