{"version":3,"sources":["../src/configuration.ts","../src/constants.ts","../src/errors.ts","../src/logger.ts","../src/utils.ts","../src/websocket.ts"],"sourcesContent":["import { Agent } from 'https';\nimport type { TimeUnit } from './constants';\n\nexport class ConfigurationRestAPI {\n    /**\n     * The API key used for authentication.\n     * @memberof ConfigurationRestAPI\n     */\n    apiKey: string;\n    /**\n     * The API secret used for authentication.\n     * @memberof ConfigurationRestAPI\n     */\n    apiSecret?: string;\n    /**\n     * override base path\n     * @type {string}\n     * @memberof ConfigurationRestAPI\n     */\n    basePath?: string;\n    /**\n     * set a timeout (in milliseconds) for the request\n     * @default 1000\n     * @type {number}\n     * @memberof ConfigurationRestAPI\n     */\n    timeout?: number;\n    /**\n     * HTTP/HTTPS proxy configuration\n     * @default false\n     * @type {object}\n     * @property {string} host - Proxy server hostname\n     * @property {number} port - Proxy server port number\n     * @property {string} protocol - Proxy server protocol\n     * @property {object} [auth] - Proxy authentication credentials\n     * @property {string} auth.username - Proxy authentication username\n     * @property {string} auth.password - Proxy authentication password\n     * @memberof ConfigurationRestAPI\n     */\n    proxy?: {\n        host: string;\n        port: number;\n        protocol?: string;\n        auth?: { username: string; password: string };\n    };\n    /**\n     * enables keep-alive functionality for the connection (if httpsAgent is set then we use httpsAgent.keepAlive instead)\n     * @default true\n     * @type {boolean}\n     * @memberof ConfigurationRestAPI\n     */\n    keepAlive?: boolean;\n    /**\n     * enables response compression\n     * @default true\n     * @type {boolean}\n     * @memberof ConfigurationRestAPI\n     */\n    compression?: boolean;\n    /**\n     * number of retry attempts for failed requests\n     * @default 3\n     * @type {number}\n     * @memberof ConfigurationRestAPI\n     */\n    retries?: number;\n    /**\n     * delay between retry attempts in milliseconds\n     * @default 1000\n     * @type {number}\n     * @memberof ConfigurationRestAPI\n     */\n    backoff?: number;\n    /**\n     * https agent\n     * @default false\n     * @type {boolean | Agent}\n     * @memberof ConfigurationRestAPI\n     */\n    httpsAgent?: boolean | Agent;\n    /**\n     * private key\n     * @type {Buffer}\n     * @memberof ConfigurationRestAPI\n     */\n    privateKey?: Buffer;\n    /**\n     * private key passphrase\n     * @type {string}\n     * @memberof ConfigurationRestAPI\n     */\n    privateKeyPassphrase?: string;\n    /**\n     * timeUnit (used only on SPOT API)\n     * @type {TimeUnit}\n     * @memberof ConfigurationRestAPI\n     */\n    timeUnit?: TimeUnit;\n    /**\n     * base options for axios calls\n     * @type {Record<string, unknown>}\n     * @memberof ConfigurationRestAPI\n     * @internal\n     */\n    baseOptions?: Record<string, unknown>;\n\n    constructor(param: ConfigurationRestAPI = { apiKey: '' }) {\n        this.apiKey = param.apiKey;\n        this.apiSecret = param.apiSecret;\n        this.basePath = param.basePath;\n        this.keepAlive = param.keepAlive ?? true;\n        this.compression = param.compression ?? true;\n        this.retries = param.retries ?? 3;\n        this.backoff = param.backoff ?? 1000;\n        this.privateKey = param.privateKey;\n        this.privateKeyPassphrase = param.privateKeyPassphrase;\n        this.timeUnit = param.timeUnit;\n        this.baseOptions = {\n            timeout: param.timeout ?? 1000,\n            proxy: param.proxy && {\n                host: param.proxy.host,\n                port: param.proxy.port,\n                auth: param.proxy.auth,\n            },\n            httpsAgent: param.httpsAgent ?? false,\n            headers: {\n                'Content-Type': 'application/json',\n                'X-MBX-APIKEY': param.apiKey,\n            },\n        };\n    }\n}\n\nexport class ConfigurationWebsocketAPI {\n    /**\n     * The API key used for authentication.\n     * @memberof ConfigurationWebsocketAPI\n     */\n    apiKey: string;\n    /**\n     * The API secret used for authentication.\n     * @memberof ConfigurationWebsocketAPI\n     */\n    apiSecret?: string;\n    /**\n     * override websocket url\n     * @type {string}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    wsURL?: string;\n    /**\n     * set a timeout (in milliseconds) for the request\n     * @default 5000\n     * @type {number}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    timeout?: number;\n    /**\n     * reconnction delay\n     * @default 5000\n     * @type {number}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    reconnectDelay?: number;\n    /**\n     * use compression for websocket messages\n     * @default true\n     * @type {boolean}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    compression?: boolean;\n    /**\n     * websocket agent\n     * @default false\n     * @type {boolean | Agent}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    agent?: boolean | Agent;\n    /**\n     * the mode of the connection, either 'single' or 'pool'.\n     * @default 'single'\n     * @type {'single' | 'pool'}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    mode?: 'single' | 'pool';\n    /**\n     * the size of the connection pool, if the mode is set to 'pool'.\n     * @default 1\n     * @type {number}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    poolSize?: number;\n    /**\n     * private key\n     * @type {Buffer}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    privateKey?: Buffer;\n    /**\n     * private key passphrase\n     * @type {string}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    privateKeyPassphrase?: string;\n    /**\n     * timeUnit (used only on SPOT API)\n     * @type {TimeUnit}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    timeUnit?: TimeUnit;\n    /**\n     * Optional user agent string for identifying the client\n     * @type {string}\n     * @memberof ConfigurationWebsocketStreams\n     * @internal\n     */\n    userAgent?: string;\n\n    constructor(param: ConfigurationWebsocketAPI = { apiKey: '' }) {\n        this.apiKey = param.apiKey;\n        this.apiSecret = param.apiSecret;\n        this.wsURL = param.wsURL;\n        this.timeout = param.timeout ?? 5000;\n        this.reconnectDelay = param.reconnectDelay ?? 5000;\n        this.compression = param.compression ?? true;\n        this.agent = param.agent ?? false;\n        this.mode = param.mode ?? 'single';\n        this.poolSize = param.poolSize ?? 1;\n        this.privateKey = param.privateKey;\n        this.privateKeyPassphrase = param.privateKeyPassphrase;\n        this.timeUnit = param.timeUnit;\n    }\n}\n\nexport class ConfigurationWebsocketStreams {\n    /**\n     * override websocket url\n     * @type {string}\n     * @memberof ConfigurationWebsocketStreams\n     */\n    wsURL?: string;\n    /**\n     * reconnction delay\n     * @default 5000\n     * @type {number}\n     * @memberof ConfigurationWebsocketStreams\n     */\n    reconnectDelay?: number;\n    /**\n     * use compression for websocket messages\n     * @default true\n     * @type {boolean}\n     * @memberof ConfigurationWebsocketAPI\n     */\n    compression?: boolean;\n    /**\n     * websocket agent\n     * @default false\n     * @type {boolean | Agent}\n     * @memberof ConfigurationWebsocketStreams\n     */\n    agent?: boolean | Agent;\n    /**\n     * the mode of the connection, either 'single' or 'pool'.\n     * @default single\n     * @type {'single' | 'pool'}\n     * @memberof ConfigurationWebsocketStreams\n     */\n    mode?: 'single' | 'pool';\n    /**\n     * the size of the connection pool, if the mode is set to 'pool'.\n     * @default 1\n     * @type {number}\n     * @memberof ConfigurationWebsocketStreams\n     */\n    poolSize?: number;\n    /**\n     * timeUnit (used only on SPOT API)\n     * @type {TimeUnit}\n     * @memberof ConfigurationWebsocketStreams\n     */\n    timeUnit?: TimeUnit;\n    /**\n     * Optional user agent string for identifying the client\n     * @type {string}\n     * @memberof ConfigurationWebsocketStreams\n     * @internal\n     */\n    userAgent?: string;\n\n    constructor(param: ConfigurationWebsocketStreams = {}) {\n        this.wsURL = param.wsURL;\n        this.reconnectDelay = param.reconnectDelay ?? 5000;\n        this.compression = param.compression ?? true;\n        this.agent = param.agent ?? false;\n        this.mode = param.mode ?? 'single';\n        this.poolSize = param.poolSize ?? 1;\n        this.timeUnit = param.timeUnit;\n    }\n}\n","export const TimeUnit = {\n    MILLISECOND: 'MILLISECOND',\n    millisecond: 'millisecond',\n    MICROSECOND: 'MICROSECOND',\n    microsecond: 'microsecond',\n} as const;\nexport type TimeUnit = (typeof TimeUnit)[keyof typeof TimeUnit];\n\n// Algo constants\nexport const ALGO_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Auto Invest constants\nexport const AUTO_INVEST_REST_API_PROD_URL = 'https://api.binance.com';\n\n// C2C constants\nexport const C2C_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Convert constants\nexport const CONVERT_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Copy Trading constants\nexport const COPY_TRADING_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Crypto Loan constants\nexport const CRYPTO_LOAN_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Derivatives Trading (COIN-M Futures) constants\nexport const DERIVATIVES_TRADING_COIN_FUTURES_REST_API_PROD_URL = 'https://dapi.binance.com';\nexport const DERIVATIVES_TRADING_COIN_FUTURES_REST_API_TESTNET_URL =\n    'https://testnet.binancefuture.com';\nexport const DERIVATIVES_TRADING_COIN_FUTURES_WS_API_PROD_URL =\n    'wss://ws-dapi.binance.com/ws-dapi/v1';\nexport const DERIVATIVES_TRADING_COIN_FUTURES_WS_API_TESTNET_URL =\n    'wss://testnet.binancefuture.com/ws-dapi/v1';\nexport const DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_PROD_URL = 'wss://dstream.binance.com';\nexport const DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_TESTNET_URL =\n    'wss://dstream.binancefuture.com';\n\n// Derivatives Trading (USDS Futures) constants\nexport const DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL = 'https://fapi.binance.com';\nexport const DERIVATIVES_TRADING_USDS_FUTURES_REST_API_TESTNET_URL =\n    'https://testnet.binancefuture.com';\nexport const DERIVATIVES_TRADING_USDS_FUTURES_WS_API_PROD_URL =\n    'wss://ws-fapi.binance.com/ws-fapi/v1';\nexport const DERIVATIVES_TRADING_USDS_FUTURES_WS_API_TESTNET_URL =\n    'wss://testnet.binancefuture.com/ws-fapi/v1';\nexport const DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_PROD_URL = 'wss://fstream.binance.com';\nexport const DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_TESTNET_URL =\n    'wss://stream.binancefuture.com';\n\n// Derivatives Trading (Options) constants\nexport const DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL = 'https://eapi.binance.com';\nexport const DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL =\n    'wss://nbstream.binance.com/eoptions';\n\n// Derivatives Trading (Portfolio Margin) constants\nexport const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL = 'https://papi.binance.com';\nexport const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL =\n    'https://testnet.binancefuture.com';\n\n// Derivatives Trading (Portfolio Margin Pro) constants\nexport const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Dual Investment constants\nexport const DUAL_INVESTMENT_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Fiat constants\nexport const FIAT_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Gift Card constants\nexport const GIFT_CARD_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Margin Trading constants\nexport const MARGIN_TRADING_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Mining constants\nexport const MINING_REST_API_PROD_URL = 'https://api.binance.com';\n\n// NFT constants\nexport const NFT_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Pay constants\nexport const PAY_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Rebate constants\nexport const REBATE_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Simple Earn constants\nexport const SIMPLE_EARN_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Spot constants\nexport const SPOT_REST_API_PROD_URL = 'https://api.binance.com';\nexport const SPOT_REST_API_TESTNET_URL = 'https://testnet.binance.vision';\nexport const SPOT_WS_API_PROD_URL = 'wss://ws-api.binance.com:443/ws-api/v3';\nexport const SPOT_WS_API_TESTNET_URL = 'wss://ws-api.testnet.binance.vision/ws-api/v3';\nexport const SPOT_WS_STREAMS_PROD_URL = 'wss://stream.binance.com:9443';\nexport const SPOT_WS_STREAMS_TESTNET_URL = 'wss://stream.testnet.binance.vision';\nexport const SPOT_REST_API_MARKET_URL = 'https://data-api.binance.vision';\nexport const SPOT_WS_STREAMS_MARKET_URL = 'wss://data-stream.binance.vision';\n\n// Staking constants\nexport const STAKING_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Sub Account constants\nexport const SUB_ACCOUNT_REST_API_PROD_URL = 'https://api.binance.com';\n\n// VIP Loan constants\nexport const VIP_LOAN_REST_API_PROD_URL = 'https://api.binance.com';\n\n// Wallet constants\nexport const WALLET_REST_API_PROD_URL = 'https://api.binance.com';\n","/**\n * Represents an error that occurred in the Connector client.\n * @param msg - An optional error message.\n */\nexport class ConnectorClientError extends Error {\n    constructor(msg?: string) {\n        super(msg || 'An unexpected error occurred.');\n        Object.setPrototypeOf(this, ConnectorClientError.prototype);\n        this.name = 'ConnectorClientError';\n    }\n}\n\n/**\n * Represents an error that occurs when a required parameter is missing or undefined.\n * @param field - The name of the missing parameter.\n * @param msg - An optional error message.\n */\nexport class RequiredError extends Error {\n    constructor(\n        public field: string,\n        msg?: string\n    ) {\n        super(msg || `Required parameter ${field} was null or undefined.`);\n        Object.setPrototypeOf(this, RequiredError.prototype);\n        this.name = 'RequiredError';\n    }\n}\n\n/**\n * Represents an error that occurs when a client is unauthorized to access a resource.\n * @param msg - An optional error message.\n */\nexport class UnauthorizedError extends Error {\n    constructor(msg?: string) {\n        super(msg || 'Unauthorized access. Authentication required.');\n        Object.setPrototypeOf(this, UnauthorizedError.prototype);\n        this.name = 'UnauthorizedError';\n    }\n}\n\n/**\n * Represents an error that occurs when a resource is forbidden to the client.\n * @param msg - An optional error message.\n */\nexport class ForbiddenError extends Error {\n    constructor(msg?: string) {\n        super(msg || 'Access to the requested resource is forbidden.');\n        Object.setPrototypeOf(this, ForbiddenError.prototype);\n        this.name = 'ForbiddenError';\n    }\n}\n\n/**\n * Represents an error that occurs when client is doing too many requests.\n * @param msg - An optional error message.\n */\nexport class TooManyRequestsError extends Error {\n    constructor(msg?: string) {\n        super(msg || 'Too many requests. You are being rate-limited.');\n        Object.setPrototypeOf(this, TooManyRequestsError.prototype);\n        this.name = 'TooManyRequestsError';\n    }\n}\n\n/**\n * Represents an error that occurs when client's IP has been banned.\n * @param msg - An optional error message.\n */\nexport class RateLimitBanError extends Error {\n    constructor(msg?: string) {\n        super(msg || 'The IP address has been banned for exceeding rate limits.');\n        Object.setPrototypeOf(this, RateLimitBanError.prototype);\n        this.name = 'RateLimitBanError';\n    }\n}\n\n/**\n * Represents an error that occurs when there is an internal server error.\n * @param msg - An optional error message.\n * @param statusCode - An optional HTTP status code associated with the error.\n */\nexport class ServerError extends Error {\n    constructor(\n        msg?: string,\n        public statusCode?: number\n    ) {\n        super(msg || 'An internal server error occurred.');\n        Object.setPrototypeOf(this, ServerError.prototype);\n        this.name = 'ServerError';\n    }\n}\n\n/**\n * Represents an error that occurs when a network error occurs.\n * @param msg - An optional error message.\n */\nexport class NetworkError extends Error {\n    constructor(msg?: string) {\n        super(msg || 'A network error occurred.');\n        Object.setPrototypeOf(this, NetworkError.prototype);\n        this.name = 'NetworkError';\n    }\n}\n\n/**\n * Represents an error that occurs when the requested resource was not found.\n * @param msg - An optional error message.\n */\nexport class NotFoundError extends Error {\n    constructor(msg?: string) {\n        super(msg || 'The requested resource was not found.');\n        Object.setPrototypeOf(this, NotFoundError.prototype);\n        this.name = 'NotFoundError';\n    }\n}\n\n/**\n * Represents an error that occurs when a request is invalid or cannot be otherwise served.\n * @param msg - An optional error message.\n */\nexport class BadRequestError extends Error {\n    constructor(msg?: string) {\n        super(msg || 'The request was invalid or cannot be otherwise served.');\n        Object.setPrototypeOf(this, BadRequestError.prototype);\n        this.name = 'BadRequestError';\n    }\n}\n","export enum LogLevel {\n    NONE = '',\n    DEBUG = 'debug',\n    INFO = 'info',\n    WARN = 'warn',\n    ERROR = 'error',\n}\n\nexport class Logger {\n    private static instance: Logger;\n    private minLogLevel: LogLevel = LogLevel.INFO;\n    private readonly levelsOrder: LogLevel[] = [\n        LogLevel.NONE,\n        LogLevel.DEBUG,\n        LogLevel.INFO,\n        LogLevel.WARN,\n        LogLevel.ERROR,\n    ];\n\n    constructor() {}\n\n    public static getInstance(): Logger {\n        if (!Logger.instance) {\n            Logger.instance = new Logger();\n        }\n        return Logger.instance;\n    }\n\n    public setMinLogLevel(level: LogLevel): void {\n        if (!this.isValidLogLevel(level)) {\n            throw new Error(`Invalid log level: ${level}`);\n        }\n        this.minLogLevel = level;\n    }\n\n    private isValidLogLevel(level: LogLevel): boolean {\n        return this.levelsOrder.includes(level);\n    }\n\n    private log(level: LogLevel, ...message: unknown[]): void {\n        if (level === LogLevel.NONE || !this.allowLevelLog(level)) {\n            return;\n        }\n\n        const timestamp = new Date().toISOString();\n        console[level](`[${timestamp}] [${level.toLowerCase()}]`, ...message);\n    }\n\n    private allowLevelLog(level: LogLevel): boolean {\n        if (!this.isValidLogLevel(level)) {\n            throw new Error(`Invalid log level: ${level}`);\n        }\n\n        const currentLevelIndex = this.levelsOrder.indexOf(level);\n        const minLevelIndex = this.levelsOrder.indexOf(this.minLogLevel);\n        return currentLevelIndex >= minLevelIndex;\n    }\n\n    public debug(...message: unknown[]): void {\n        this.log(LogLevel.DEBUG, ...message);\n    }\n\n    public info(...message: unknown[]): void {\n        this.log(LogLevel.INFO, ...message);\n    }\n\n    public warn(...message: unknown[]): void {\n        this.log(LogLevel.WARN, ...message);\n    }\n\n    public error(...message: unknown[]): void {\n        this.log(LogLevel.ERROR, ...message);\n    }\n}\n","import crypto from 'crypto';\nimport fs from 'fs';\nimport https from 'https';\nimport { platform, arch } from 'os';\nimport {\n    AxiosResponseHeaders,\n    RawAxiosResponseHeaders,\n    AxiosResponse,\n    AxiosError,\n    RawAxiosRequestConfig,\n} from 'axios';\nimport globalAxios from 'axios';\nimport {\n    type ConfigurationRestAPI,\n    type RestApiRateLimit,\n    type RestApiResponse,\n    TimeUnit,\n    RequiredError,\n    BadRequestError,\n    ConnectorClientError,\n    ForbiddenError,\n    NetworkError,\n    NotFoundError,\n    RateLimitBanError,\n    ServerError,\n    TooManyRequestsError,\n    UnauthorizedError,\n    AxiosRequestArgs,\n    SendMessageOptions,\n    ObjectType,\n} from '.';\n\n/**\n * A weak cache for storing RequestSigner instances based on configuration parameters.\n *\n * @remarks\n * Uses a WeakMap to cache and reuse RequestSigner instances for configurations with\n * apiSecret, privateKey, and privateKeyPassphrase, allowing efficient memory management.\n */\nlet signerCache = new WeakMap<\n    {\n        apiSecret?: string;\n        privateKey?: string | Buffer;\n        privateKeyPassphrase?: string;\n    },\n    RequestSigner\n>();\n\n/**\n * Represents a request signer for generating signatures using HMAC-SHA256 or asymmetric key signing.\n *\n * Supports two signing methods:\n * 1. HMAC-SHA256 using an API secret\n * 2. Asymmetric signing using RSA or ED25519 private keys\n *\n * @throws {Error} If neither API secret nor private key is provided, or if the private key is invalid\n */\nclass RequestSigner {\n    private apiSecret?: string;\n    private keyObject?: crypto.KeyObject;\n    private keyType?: string;\n\n    constructor(configuration: {\n        apiSecret?: string;\n        privateKey?: string | Buffer;\n        privateKeyPassphrase?: string;\n    }) {\n        // HMAC-SHA256 path\n        if (configuration.apiSecret && !configuration.privateKey) {\n            this.apiSecret = configuration.apiSecret;\n            return;\n        }\n\n        // Asymmetric path\n        if (configuration.privateKey) {\n            let privateKey: string | Buffer = configuration.privateKey;\n\n            // If path, read file once\n            if (typeof privateKey === 'string' && fs.existsSync(privateKey)) {\n                privateKey = fs.readFileSync(privateKey, 'utf-8');\n            }\n\n            // Build KeyObject once\n            const keyInput: crypto.PrivateKeyInput = { key: privateKey };\n            if (\n                configuration.privateKeyPassphrase &&\n                typeof configuration.privateKeyPassphrase === 'string'\n            ) {\n                keyInput.passphrase = configuration.privateKeyPassphrase;\n            }\n\n            try {\n                this.keyObject = crypto.createPrivateKey(keyInput);\n                this.keyType = this.keyObject.asymmetricKeyType;\n            } catch {\n                throw new Error(\n                    'Invalid private key. Please provide a valid RSA or ED25519 private key.'\n                );\n            }\n\n            return;\n        }\n\n        throw new Error('Either \\'apiSecret\\' or \\'privateKey\\' must be provided for signed requests.');\n    }\n\n    sign(queryParams: object): string {\n        const params = buildQueryString(queryParams);\n\n        // HMAC-SHA256 signing\n        if (this.apiSecret)\n            return crypto.createHmac('sha256', this.apiSecret).update(params).digest('hex');\n\n        // Asymmetric signing\n        if (this.keyObject && this.keyType) {\n            const data = Buffer.from(params);\n\n            if (this.keyType === 'rsa')\n                return crypto.sign('RSA-SHA256', data, this.keyObject).toString('base64');\n            if (this.keyType === 'ed25519')\n                return crypto.sign(null, data, this.keyObject).toString('base64');\n\n            throw new Error('Unsupported private key type. Must be RSA or ED25519.');\n        }\n\n        throw new Error('Signer is not properly initialized.');\n    }\n}\n\n/**\n * Resets the signer cache to a new empty WeakMap.\n *\n * This function clears the existing signer cache, creating a fresh WeakMap\n * to store RequestSigner instances associated with configuration objects.\n */\nexport const clearSignerCache = function (): void {\n    signerCache = new WeakMap<\n        {\n            apiSecret?: string;\n            privateKey?: string | Buffer;\n            privateKeyPassphrase?: string;\n        },\n        RequestSigner\n    >();\n};\n\n/**\n * Generates a query string from an object of parameters.\n *\n * @param params - An object containing the query parameters.\n * @returns The generated query string.\n */\nexport function buildQueryString(params: object): string {\n    if (!params) return '';\n    return Object.entries(params).map(stringifyKeyValuePair).join('&');\n}\n\n/**\n * Converts a key-value pair into a URL-encoded query parameter string.\n *\n * @param [key, value] - The key-value pair to be converted.\n * @returns The URL-encoded query parameter string.\n */\nfunction stringifyKeyValuePair([key, value]: [string, string]) {\n    const valueString = Array.isArray(value) ? `[\"${value.join('\",\"')}\"]` : value;\n    return `${key}=${encodeURIComponent(valueString)}`;\n}\n\n/**\n * Generates a random string of 16 hexadecimal characters.\n *\n * @returns A random string of 16 hexadecimal characters.\n */\nexport function randomString() {\n    return crypto.randomBytes(16).toString('hex');\n}\n\n/**\n * Validates the provided time unit string and returns it if it is either 'MILLISECOND' or 'MICROSECOND'.\n *\n * @param timeUnit - The time unit string to be validated.\n * @returns The validated time unit string, or `undefined` if the input is falsy.\n * @throws {Error} If the time unit is not 'MILLISECOND' or 'MICROSECOND'.\n */\nexport function validateTimeUnit(timeUnit: string): string | undefined {\n    if (!timeUnit) {\n        return;\n    } else if (\n        timeUnit !== TimeUnit.MILLISECOND &&\n        timeUnit !== TimeUnit.MICROSECOND &&\n        timeUnit !== TimeUnit.millisecond &&\n        timeUnit !== TimeUnit.microsecond\n    ) {\n        throw new Error('timeUnit must be either \\'MILLISECOND\\' or \\'MICROSECOND\\'');\n    }\n\n    return timeUnit;\n}\n\n/**\n * Delays the execution of the current function for the specified number of milliseconds.\n *\n * @param ms - The number of milliseconds to delay the function.\n * @returns A Promise that resolves after the specified delay.\n */\nexport async function delay(ms: number): Promise<void> {\n    return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Generates the current timestamp in milliseconds.\n *\n * @returns The current timestamp in milliseconds.\n */\nexport function getTimestamp(): number {\n    return Date.now();\n}\n\n/**\n * Generates a signature for the given configuration and query parameters using a cached request signer.\n *\n * @param configuration - Configuration object containing API secret, private key, and optional passphrase.\n * @param queryParams - The query parameters to be signed.\n * @returns A string representing the generated signature.\n */\nexport const getSignature = function (\n    configuration: {\n        apiSecret?: string;\n        privateKey?: string | Buffer;\n        privateKeyPassphrase?: string;\n    },\n    queryParams: object\n): string {\n    let signer = signerCache.get(configuration);\n    if (!signer) {\n        signer = new RequestSigner(configuration);\n        signerCache.set(configuration, signer);\n    }\n    return signer.sign(queryParams);\n};\n\n/**\n * Asserts that a function parameter exists and is not null or undefined.\n *\n * @param functionName - The name of the function that the parameter belongs to.\n * @param paramName - The name of the parameter to check.\n * @param paramValue - The value of the parameter to check.\n * @throws {RequiredError} If the parameter is null or undefined.\n */\nexport const assertParamExists = function (\n    functionName: string,\n    paramName: string,\n    paramValue: unknown\n) {\n    if (paramValue === null || paramValue === undefined) {\n        throw new RequiredError(\n            paramName,\n            `Required parameter ${paramName} was null or undefined when calling ${functionName}.`\n        );\n    }\n};\n\n/**\n * Recursively flattens an object or array into URL search parameters.\n *\n * This function handles nested objects and arrays by converting them into dot-notation query parameters.\n * It supports different types of parameters:\n * - Arrays can be stringified or recursively added\n * - Objects are flattened with dot notation keys\n * - Primitive values are converted to strings\n *\n * @param urlSearchParams The URLSearchParams object to modify\n * @param parameter The parameter to flatten (can be an object, array, or primitive)\n * @param key Optional key for nested parameters, used for creating dot-notation keys\n */\nexport function setFlattenedQueryParams(\n    urlSearchParams: URLSearchParams,\n    parameter: unknown,\n    key: string = ''\n): void {\n    if (parameter == null) return;\n\n    // Array handling\n    if (Array.isArray(parameter)) {\n        if (key)\n            // non-empty key: stringify the entire array\n            urlSearchParams.set(key, JSON.stringify(parameter));\n        else\n            // empty key: recurse into each item without using an empty key\n            for (const item of parameter) {\n                setFlattenedQueryParams(urlSearchParams, item, '');\n            }\n        return;\n    }\n\n    // Object handling\n    if (typeof parameter === 'object') {\n        for (const subKey of Object.keys(parameter as Record<string, unknown>)) {\n            const subVal = (parameter as Record<string, unknown>)[subKey];\n            const newKey = key ? `${key}.${subKey}` : subKey;\n            setFlattenedQueryParams(urlSearchParams, subVal, newKey);\n        }\n        return;\n    }\n\n    // Primitive handling\n    const str = String(parameter);\n    if (urlSearchParams.has(key)) urlSearchParams.append(key, str);\n    else urlSearchParams.set(key, str);\n}\n\n/**\n * Sets the search parameters of the provided URL by flattening the given objects into the URL's search parameters.\n *\n * This function takes a URL and one or more objects, and updates the URL's search parameters by flattening the objects into key-value pairs. It uses the `setFlattenedQueryParams` function to recursively flatten the objects.\n *\n * @param url - The URL to update the search parameters for.\n * @param objects - One or more objects to flatten into the URL's search parameters.\n */\nexport const setSearchParams = function (url: URL, ...objects: Record<string, unknown>[]) {\n    const searchParams = new URLSearchParams(url.search);\n    setFlattenedQueryParams(searchParams, objects);\n    url.search = searchParams.toString();\n};\n\nexport const toPathString = function (url: URL) {\n    return url.pathname + url.search + url.hash;\n};\n\n/**\n * Determines whether a request should be retried based on the provided error.\n *\n * This function checks the HTTP method, response status, and number of retries left to determine if a request should be retried.\n *\n * @param error The error object to check.\n * @param method The HTTP method of the request (optional).\n * @param retriesLeft The number of retries left (optional).\n * @returns `true` if the request should be retried, `false` otherwise.\n */\nexport const shouldRetryRequest = function (\n    error: AxiosError | object,\n    method?: string,\n    retriesLeft?: number\n): boolean {\n    const isRetriableMethod = ['GET', 'DELETE'].includes(method ?? '');\n    const isRetriableStatus = [500, 502, 503, 504].includes(\n        (error as AxiosError)?.response?.status ?? 0\n    );\n    return (\n        (retriesLeft ?? 0) > 0 &&\n        isRetriableMethod &&\n        (isRetriableStatus || !(error as AxiosError)?.response)\n    );\n};\n\n/**\n * Performs an HTTP request using the provided Axios instance and configuration.\n *\n * This function handles retries, rate limit handling, and error handling for the HTTP request.\n *\n * @param axiosArgs The request arguments to be passed to Axios.\n * @param axios The Axios instance to use for the request.\n * @param configuration The configuration options for the request.\n * @returns A Promise that resolves to the API response, including the data and rate limit headers.\n */\nexport const httpRequestFunction = async function <T>(\n    axiosArgs: AxiosRequestArgs,\n    configuration?: ConfigurationRestAPI\n): Promise<RestApiResponse<T>> {\n    const axiosRequestArgs = {\n        ...axiosArgs.options,\n        url: (globalAxios.defaults?.baseURL ? '' : (configuration?.basePath ?? '')) + axiosArgs.url,\n    };\n\n    if (configuration?.keepAlive && !configuration?.baseOptions?.httpsAgent)\n        axiosRequestArgs.httpsAgent = new https.Agent({ keepAlive: true });\n\n    if (configuration?.compression)\n        axiosRequestArgs.headers = {\n            ...axiosRequestArgs.headers,\n            'Accept-Encoding': 'gzip, deflate, br',\n        };\n\n    const retries = configuration?.retries ?? 0;\n    const backoff = configuration?.backoff ?? 0;\n    let attempt = 0;\n    let lastError;\n\n    while (attempt <= retries) {\n        try {\n            const response: AxiosResponse = await globalAxios.request({\n                ...axiosRequestArgs,\n                responseType: 'text',\n            });\n            const rateLimits: RestApiRateLimit[] = parseRateLimitHeaders(response.headers);\n            return {\n                data: async (): Promise<T> => {\n                    try {\n                        return JSON.parse(response.data) as T;\n                    } catch (err) {\n                        throw new Error(`Failed to parse JSON response: ${err}`);\n                    }\n                },\n                status: response.status,\n                headers: response.headers as Record<string, string>,\n                rateLimits,\n            };\n        } catch (error) {\n            attempt++;\n            const axiosError = error as AxiosError;\n\n            if (\n                shouldRetryRequest(\n                    axiosError,\n                    axiosRequestArgs?.method?.toUpperCase(),\n                    retries - attempt\n                )\n            ) {\n                await delay(backoff * attempt);\n            } else {\n                if (axiosError.response && axiosError.response.status) {\n                    const status = axiosError.response?.status;\n                    const responseData = axiosError.response.data;\n\n                    let data: Record<string, unknown> = {};\n                    if (responseData && responseData !== null) {\n                        if (typeof responseData === 'string' && responseData !== '')\n                            try {\n                                data = JSON.parse(responseData);\n                            } catch {\n                                data = {};\n                            }\n                        else if (typeof responseData === 'object')\n                            data = responseData as Record<string, unknown>;\n                    }\n\n                    const errorMsg = (data as { msg?: string }).msg;\n\n                    switch (status) {\n                    case 400:\n                        throw new BadRequestError(errorMsg);\n                    case 401:\n                        throw new UnauthorizedError(errorMsg);\n                    case 403:\n                        throw new ForbiddenError(errorMsg);\n                    case 404:\n                        throw new NotFoundError(errorMsg);\n                    case 418:\n                        throw new RateLimitBanError(errorMsg);\n                    case 429:\n                        throw new TooManyRequestsError(errorMsg);\n                    default:\n                        if (status >= 500 && status < 600)\n                            throw new ServerError(`Server error: ${status}`, status);\n                        throw new ConnectorClientError(errorMsg);\n                    }\n                } else {\n                    if (retries > 0 && attempt >= retries)\n                        lastError = new Error(`Request failed after ${retries} retries`);\n                    else lastError = new NetworkError('Network error or request timeout.');\n\n                    break;\n                }\n            }\n        }\n    }\n\n    throw lastError;\n};\n\n/**\n * Parses the rate limit headers from the Axios response headers and returns an array of `RestApiRateLimit` objects.\n *\n * @param headers - The Axios response headers.\n * @returns An array of `RestApiRateLimit` objects containing the parsed rate limit information.\n */\nexport const parseRateLimitHeaders = function (\n    headers: RawAxiosResponseHeaders | AxiosResponseHeaders\n): RestApiRateLimit[] {\n    const rateLimits: RestApiRateLimit[] = [];\n\n    const parseIntervalDetails = (\n        key: string\n    ): { interval: 'SECOND' | 'MINUTE' | 'HOUR' | 'DAY'; intervalNum: number } | null => {\n        const match = key.match(/x-mbx-used-weight-(\\d+)([smhd])|x-mbx-order-count-(\\d+)([smhd])/i);\n        if (!match) return null;\n\n        const intervalNum = parseInt(match[1] || match[3], 10);\n        const intervalLetter = (match[2] || match[4])?.toUpperCase();\n\n        let interval: 'SECOND' | 'MINUTE' | 'HOUR' | 'DAY';\n        switch (intervalLetter) {\n        case 'S':\n            interval = 'SECOND';\n            break;\n        case 'M':\n            interval = 'MINUTE';\n            break;\n        case 'H':\n            interval = 'HOUR';\n            break;\n        case 'D':\n            interval = 'DAY';\n            break;\n        default:\n            return null;\n        }\n\n        return { interval, intervalNum };\n    };\n\n    for (const [key, value] of Object.entries(headers)) {\n        const normalizedKey = key.toLowerCase();\n        if (value === undefined) continue;\n\n        if (normalizedKey.startsWith('x-mbx-used-weight-')) {\n            const details = parseIntervalDetails(normalizedKey);\n            if (details) {\n                rateLimits.push({\n                    rateLimitType: 'REQUEST_WEIGHT',\n                    interval: details.interval,\n                    intervalNum: details.intervalNum,\n                    count: parseInt(value, 10),\n                });\n            }\n        } else if (normalizedKey.startsWith('x-mbx-order-count-')) {\n            const details = parseIntervalDetails(normalizedKey);\n            if (details) {\n                rateLimits.push({\n                    rateLimitType: 'ORDERS',\n                    interval: details.interval,\n                    intervalNum: details.intervalNum,\n                    count: parseInt(value, 10),\n                });\n            }\n        }\n    }\n\n    if (headers['retry-after']) {\n        const retryAfter = parseInt(headers['retry-after'], 10);\n        for (const limit of rateLimits) {\n            limit.retryAfter = retryAfter;\n        }\n    }\n\n    return rateLimits;\n};\n\n/**\n * Generic function to send a request with optional API key and signature.\n * @param endpoint - The API endpoint to call.\n * @param method - HTTP method to use (GET, POST, DELETE, etc.).\n * @param params - Query parameters for the request.\n * @param timeUnit - The time unit for the request.\n * @param options - Additional request options (isSigned).\n * @returns A promise resolving to the response data object.\n */\nexport const sendRequest = function <T>(\n    configuration: ConfigurationRestAPI,\n    endpoint: string,\n    method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH',\n    params: Record<string, unknown> = {},\n    timeUnit?: TimeUnit,\n    options: { isSigned?: boolean } = {}\n): Promise<RestApiResponse<T>> {\n    const localVarUrlObj = new URL(endpoint, configuration?.basePath);\n    const localVarRequestOptions: RawAxiosRequestConfig = {\n        method,\n        ...configuration?.baseOptions,\n    };\n    const localVarQueryParameter = { ...params };\n\n    if (options.isSigned) {\n        const timestamp = getTimestamp();\n        localVarQueryParameter['timestamp'] = timestamp;\n        const signature = getSignature(configuration!, localVarQueryParameter);\n        if (signature) {\n            localVarQueryParameter['signature'] = signature;\n        }\n    }\n\n    setSearchParams(localVarUrlObj, localVarQueryParameter);\n\n    if (timeUnit && localVarRequestOptions.headers) {\n        const _timeUnit = validateTimeUnit(timeUnit);\n        localVarRequestOptions.headers = {\n            ...localVarRequestOptions.headers,\n            'X-MBX-TIME-UNIT': _timeUnit,\n        };\n    }\n\n    return httpRequestFunction<T>(\n        {\n            url: toPathString(localVarUrlObj),\n            options: localVarRequestOptions,\n        },\n        configuration\n    );\n};\n\n/**\n * Removes any null, undefined, or empty string values from the provided object.\n *\n * @param obj - The object to remove empty values from.\n * @returns A new object with empty values removed.\n */\nexport function removeEmptyValue(obj: object): SendMessageOptions {\n    if (!(obj instanceof Object)) return {};\n    return Object.fromEntries(\n        Object.entries(obj).filter(\n            ([, value]) => value !== null && value !== undefined && value !== ''\n        )\n    );\n}\n\n/**\n * Sorts the properties of the provided object in alphabetical order and returns a new object with the sorted properties.\n *\n * @param obj - The object to be sorted.\n * @returns A new object with the properties sorted in alphabetical order.\n */\nexport function sortObject(obj: ObjectType) {\n    return Object.keys(obj)\n        .sort()\n        .reduce((res: ObjectType, key: string) => {\n            res[key] = obj[key] as string | number | boolean | object;\n            return res;\n        }, {});\n}\n\n/**\n * Replaces placeholders in the format <field> with corresponding values from the provided variables object.\n *\n * @param {string} str - The input string containing placeholders.\n * @param {Object} variables - An object where keys correspond to placeholder names and values are the replacements.\n * @returns {string} - The resulting string with placeholders replaced by their corresponding values.\n */\nexport function replaceWebsocketStreamsPlaceholders(\n    str: string,\n    variables: Record<string, unknown>\n): string {\n    const normalizedVariables = Object.keys(variables).reduce(\n        (acc, key) => {\n            const normalizedKey = key.toLowerCase().replace(/[-_]/g, '');\n            acc[normalizedKey] = variables[key];\n            return acc;\n        },\n        {} as Record<string, unknown>\n    );\n\n    return str.replace(/(@)?<([^>]+)>/g, (match, precedingAt, fieldName) => {\n        const normalizedFieldName = fieldName.toLowerCase().replace(/[-_]/g, '');\n\n        if (\n            Object.prototype.hasOwnProperty.call(normalizedVariables, normalizedFieldName) &&\n            normalizedVariables[normalizedFieldName] != null\n        ) {\n            const value = normalizedVariables[normalizedFieldName];\n\n            switch (normalizedFieldName) {\n            case 'symbol':\n            case 'windowsize':\n                return (value as string).toLowerCase();\n            case 'updatespeed':\n                return `@${value}`;\n            default:\n                return (precedingAt || '') + (value as string);\n            }\n        }\n\n        return '';\n    });\n}\n\n/**\n * Generates a standardized user agent string for the application.\n *\n * @param {string} packageName - The name of the package/application.\n * @param {string} packageVersion - The version of the package/application.\n * @returns {string} A formatted user agent string including package details, Node.js version, platform, and architecture.\n */\nexport function buildUserAgent(packageName: string, packageVersion: string): string {\n    return `${packageName}/${packageVersion} (Node.js/${process.version}; ${platform()}; ${arch()})`;\n}\n","import { EventEmitter } from 'events';\nimport WebSocketClient from 'ws';\nimport { ClientRequestArgs } from 'http';\nimport {\n    type ConfigurationWebsocketAPI,\n    type ConfigurationWebsocketStreams,\n    WebsocketApiResponse,\n    Logger,\n    delay,\n    randomString,\n    getTimestamp,\n    getSignature,\n    validateTimeUnit,\n    removeEmptyValue,\n    sortObject,\n    ObjectType,\n} from '.';\n\nexport class WebsocketEventEmitter {\n    private eventEmitter: EventEmitter;\n\n    constructor() {\n        this.eventEmitter = new EventEmitter();\n    }\n\n    /* eslint-disable @typescript-eslint/no-explicit-any */\n    on(\n        event: 'open' | 'message' | 'error' | 'close' | 'ping' | 'pong',\n        listener: (...args: any[]) => void\n    ): void {\n        this.eventEmitter.on(event, listener);\n    }\n\n    /* eslint-disable @typescript-eslint/no-explicit-any */\n    off(\n        event: 'open' | 'message' | 'error' | 'close' | 'ping' | 'pong',\n        listener: (...args: any[]) => void\n    ): void {\n        this.eventEmitter.off(event, listener);\n    }\n\n    /* eslint-disable @typescript-eslint/no-explicit-any */\n    protected emit(\n        event: 'open' | 'message' | 'error' | 'close' | 'ping' | 'pong',\n        ...args: any[]\n    ): void {\n        this.eventEmitter.emit(event, ...args);\n    }\n}\n\nexport interface WebsocketConnection {\n    id: string;\n    reconnectionPending: boolean;\n    renewalPending: boolean;\n    closeInitiated: boolean;\n    pendingRequests: Map<\n        string,\n        { resolve: (value: any) => void; reject: (reason?: unknown) => void }\n    >;\n    pendingSubscriptions?: string[];\n    ws?: WebSocketClient;\n}\n\nexport class WebsocketCommon extends WebsocketEventEmitter {\n    private static readonly MAX_CONNECTION_DURATION = 23 * 60 * 60 * 1000;\n    private readonly connectionQueue: Array<{\n        connection: WebsocketConnection;\n        url: string;\n        isRenewal: boolean;\n    }> = [];\n    private queueProcessing: boolean = false;\n    private connectionTimers: Map<\n        WebSocketClient,\n        Set<{ timer: NodeJS.Timeout; type: 'timeout' | 'interval' }>\n    > = new Map();\n    private mode: 'single' | 'pool';\n    private poolSize: number;\n    private roundRobinIndex = 0;\n    connectionPool: WebsocketConnection[];\n    logger: Logger = Logger.getInstance();\n\n    constructor(\n        protected configuration: ConfigurationWebsocketAPI | ConfigurationWebsocketStreams,\n        connectionPool: WebsocketConnection[] = []\n    ) {\n        super();\n        this.connectionPool = connectionPool;\n        this.mode = this.configuration?.mode ?? 'single';\n        this.poolSize =\n            this.mode === 'pool' && this.configuration?.poolSize ? this.configuration.poolSize : 1;\n        if (!connectionPool || connectionPool.length === 0) this.initializePool(this.poolSize);\n    }\n\n    /**\n     * Initializes the WebSocket connection pool by creating a specified number of connection objects\n     * and adding them to the `connectionPool` array. Each connection object has the following properties:\n     * - `closeInitiated`: a boolean indicating whether the connection has been closed\n     * - `reconnectionPending`: a boolean indicating whether a reconnection is pending\n     * - `pendingRequests`: a Map that tracks pending requests for the connection\n     * @param size - The number of connection objects to create and add to the pool.\n     * @returns void\n     */\n    private initializePool(size: number): void {\n        for (let i = 0; i < size; i++) {\n            this.connectionPool.push({\n                id: randomString(),\n                closeInitiated: false,\n                reconnectionPending: false,\n                renewalPending: false,\n                pendingRequests: new Map(),\n                pendingSubscriptions: [],\n            });\n        }\n    }\n\n    /**\n     * Gets a WebSocket connection from the pool or single connection.\n     * If the connection mode is 'single', it returns the first connection in the pool.\n     * If the connection mode is 'pool', it returns an available connection from the pool,\n     * using a round-robin selection strategy. If no available connections are found, it throws an error.\n     * @param allowNonEstablishedWebsockets - A boolean indicating whether to allow connections that are not established.\n     * @returns {WebsocketConnection} The selected WebSocket connection.\n     */\n    protected getConnection(allowNonEstablishedWebsockets: boolean = false): WebsocketConnection {\n        if (this.mode === 'single') return this.connectionPool[0];\n\n        // Filter connections based on readiness and pending reconnection status\n        const availableConnections = this.connectionPool.filter((connection) =>\n            this.isConnectionReady(connection, allowNonEstablishedWebsockets)\n        );\n\n        if (availableConnections.length === 0) {\n            throw new Error('No available Websocket connections are ready.');\n        }\n\n        // Select a connection using round-robin algorithm\n        const selectedConnection =\n            availableConnections[this.roundRobinIndex % availableConnections.length];\n        this.roundRobinIndex = (this.roundRobinIndex + 1) % availableConnections.length;\n        return selectedConnection!;\n    }\n\n    /**\n     * Checks if the provided WebSocket connection is ready for use.\n     * A connection is considered ready if it is open, has no pending reconnection, and has not been closed.\n     * @param connection - The WebSocket connection to check.\n     * @param allowNonEstablishedWebsockets - An optional flag to allow non-established WebSocket connections.\n     * @returns `true` if the connection is ready, `false` otherwise.\n     */\n    protected isConnectionReady(\n        connection: WebsocketConnection,\n        allowNonEstablishedWebsockets: boolean = false\n    ): boolean {\n        return (\n            (allowNonEstablishedWebsockets || connection.ws?.readyState === WebSocketClient.OPEN) &&\n            !connection.reconnectionPending &&\n            !connection.closeInitiated\n        );\n    }\n\n    /**\n     * Schedules a timer for a WebSocket connection and tracks it\n     * @param connection WebSocket client instance\n     * @param callback Function to execute when timer triggers\n     * @param delay Time in milliseconds before callback execution\n     * @param type Timer type ('timeout' or 'interval')\n     * @returns Timer handle\n     */\n    private scheduleTimer(\n        connection: WebSocketClient,\n        callback: () => void,\n        delay: number,\n        type: 'timeout' | 'interval' = 'timeout'\n    ): NodeJS.Timeout {\n        const timer =\n            type === 'timeout' ? setTimeout(callback, delay) : setInterval(callback, delay);\n        if (!this.connectionTimers.has(connection))\n            this.connectionTimers.set(connection, new Set());\n        this.connectionTimers.get(connection)?.add({ timer, type });\n        return timer;\n    }\n\n    /**\n     * Clears all timers associated with a WebSocket connection.\n     * @param connection - The WebSocket client instance to clear timers for.\n     * @returns void\n     */\n    private clearTimers(connection: WebSocketClient): void {\n        const timers = this.connectionTimers.get(connection);\n        if (timers) {\n            timers.forEach(({ timer, type }) => {\n                if (type === 'timeout') clearTimeout(timer);\n                else if (type === 'interval') clearInterval(timer);\n            });\n\n            this.connectionTimers.delete(connection);\n        }\n    }\n\n    /**\n     * Processes the connection queue, reconnecting or renewing connections as needed.\n     * This method is responsible for iterating through the connection queue and initiating\n     * the reconnection or renewal process for each connection in the queue. It throttles\n     * the queue processing to avoid overwhelming the server with too many connection\n     * requests at once.\n     * @param throttleRate - The time in milliseconds to wait between processing each\n     * connection in the queue.\n     * @returns A Promise that resolves when the queue has been fully processed.\n     */\n    private async processQueue(throttleRate: number = 1000): Promise<void> {\n        if (this.queueProcessing) return;\n        this.queueProcessing = true;\n\n        while (this.connectionQueue.length > 0) {\n            const { connection, url, isRenewal } = this.connectionQueue.shift()!;\n            this.initConnect(url, isRenewal, connection);\n            await delay(throttleRate);\n        }\n\n        this.queueProcessing = false;\n    }\n\n    /**\n     * Enqueues a reconnection or renewal for a WebSocket connection.\n     * This method adds the connection, URL, and renewal flag to the connection queue,\n     * and then calls the `processQueue` method to initiate the reconnection or renewal\n     * process.\n     * @param connection - The WebSocket connection to reconnect or renew.\n     * @param url - The URL to use for the reconnection or renewal.\n     * @param isRenewal - A flag indicating whether this is a renewal (true) or a reconnection (false).\n     */\n    private enqueueReconnection(\n        connection: WebsocketConnection,\n        url: string,\n        isRenewal: boolean\n    ): void {\n        this.connectionQueue.push({ connection, url, isRenewal });\n        this.processQueue();\n    }\n\n    /**\n     * Gracefully closes a WebSocket connection after pending requests complete.\n     * This method waits for any pending requests to complete before closing the connection.\n     * It sets up a timeout to force-close the connection after 30 seconds if the pending requests\n     * do not complete. Once all pending requests are completed, the connection is closed.\n     * @param connectionToClose - The WebSocket client instance to close.\n     * @param WebsocketConnectionToClose - The WebSocket connection to close.\n     * @param connection - The WebSocket connection to close.\n     * @returns Promise that resolves when the connection is closed.\n     */\n    private async closeConnectionGracefully(\n        WebsocketConnectionToClose: WebSocketClient,\n        connection: WebsocketConnection\n    ): Promise<void> {\n        if (!WebsocketConnectionToClose || !connection) return;\n\n        this.logger.debug('Waiting for pending requests to complete before disconnecting.');\n\n        const closePromise = new Promise<void>((resolve) => {\n            this.scheduleTimer(\n                WebsocketConnectionToClose,\n                () => {\n                    this.logger.warn('Force-closing connection after 30 seconds.');\n                    resolve();\n                },\n                30000\n            );\n\n            this.scheduleTimer(\n                WebsocketConnectionToClose,\n                () => {\n                    if (connection.pendingRequests.size === 0) {\n                        this.logger.debug('All pending requests completed, closing connection.');\n                        resolve();\n                    }\n                },\n                1000,\n                'interval'\n            );\n        });\n\n        await closePromise;\n\n        this.logger.info('Closing Websocket connection.');\n        WebsocketConnectionToClose.close();\n        this.cleanup(WebsocketConnectionToClose);\n    }\n\n    /**\n     * Cleans up WebSocket connection resources.\n     * Removes all listeners and clears any associated timers for the provided WebSocket client.\n     * @param ws - The WebSocket client to clean up.\n     * @returns void\n     */\n    protected cleanup(ws: WebSocketClient): void {\n        if (ws) {\n            ws.removeAllListeners();\n            this.clearTimers(ws);\n        }\n    }\n\n    /**\n     * Handles incoming WebSocket messages\n     * @param data Raw message data received\n     * @param connection Websocket connection\n     */\n    protected onMessage(data: string, connection: WebsocketConnection): void {\n        this.emit('message', data.toString(), connection);\n    }\n\n    /**\n     * Handles the opening of a WebSocket connection.\n     * @param url - The URL of the WebSocket server.\n     * @param targetConnection - The WebSocket connection being opened.\n     * @param oldConnection - The previous WebSocket connection, if this is a renewal.\n     * @param isRenewal - Indicates whether this is a connection renewal.\n     * @param oldWSConnection - The WebSocket client instance associated with the old connection.\n     */\n    protected onOpen(\n        url: string,\n        targetConnection: WebsocketConnection,\n        oldWSConnection: WebSocketClient\n    ): void {\n        this.logger.info(\n            `Connected to the Websocket Server with id ${targetConnection.id}: ${url}`\n        );\n        if (targetConnection.renewalPending) {\n            targetConnection.renewalPending = false;\n            this.closeConnectionGracefully(oldWSConnection, targetConnection);\n        } else if (targetConnection.closeInitiated) {\n            this.closeConnectionGracefully(targetConnection.ws!, targetConnection);\n        } else {\n            this.emit('open', this);\n        }\n    }\n\n    /**\n     * Returns the URL to use when reconnecting.\n     * Derived classes should override this to provide dynamic URLs.\n     * @param defaultURL The URL originally passed during the first connection.\n     * @param targetConnection The WebSocket connection being connected.\n     * @returns The URL to reconnect to.\n     */\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    protected getReconnectURL(defaultURL: string, targetConnection: WebsocketConnection): string {\n        return defaultURL;\n    }\n\n    /**\n     * Connects all WebSocket connections in the pool\n     * @param url - The Websocket server URL.\n     * @returns A promise that resolves when all connections are established.\n     */\n    protected async connectPool(url: string): Promise<void> {\n        const connectPromises = this.connectionPool.map(\n            (connection) =>\n                new Promise<void>((resolve, reject) => {\n                    this.initConnect(url, false, connection);\n\n                    connection.ws?.on('open', () => resolve());\n                    connection.ws?.on('error', (err) => reject(err));\n                    connection.ws?.on('close', () =>\n                        reject(new Error('Connection closed unexpectedly.'))\n                    );\n                })\n        );\n        await Promise.all(connectPromises);\n    }\n\n    /**\n     * Creates a new WebSocket client instance.\n     * @param url - The URL to connect to.\n     * @returns A new WebSocket client instance.\n     */\n    protected createWebSocket(url: string): WebSocketClient {\n        const wsClientOptions: WebSocketClient.ClientOptions | ClientRequestArgs = {\n            perMessageDeflate: this.configuration?.compression,\n            agent: this.configuration?.agent,\n        };\n        if (this.configuration.userAgent)\n            wsClientOptions.headers = { 'User-Agent': this.configuration.userAgent };\n\n        return new WebSocketClient(url, wsClientOptions);\n    }\n\n    /**\n     * Initializes a WebSocket connection.\n     * @param url - The Websocket server URL.\n     * @param isRenewal - Whether this is a connection renewal.\n     * @param connection - An optional WebSocket connection to use.\n     * @returns The WebSocket connection.\n     */\n    protected initConnect(\n        url: string,\n        isRenewal: boolean = false,\n        connection?: WebsocketConnection\n    ) {\n        const targetConnection = connection || this.getConnection();\n\n        if (targetConnection.renewalPending && isRenewal) {\n            this.logger.warn(\n                `Connection renewal with id ${targetConnection.id} is already in progress`\n            );\n            return;\n        }\n\n        if (\n            targetConnection.ws &&\n            targetConnection.ws.readyState === WebSocketClient.OPEN &&\n            !isRenewal\n        ) {\n            this.logger.warn(`Connection with id ${targetConnection.id} already exists`);\n            return;\n        }\n\n        const ws = this.createWebSocket(url);\n\n        this.logger.info(\n            `Establishing Websocket connection with id ${targetConnection.id} to: ${url}`\n        );\n\n        if (isRenewal) targetConnection.renewalPending = true;\n        else targetConnection.ws = ws;\n\n        this.scheduleTimer(\n            ws,\n            () => {\n                this.logger.info(`Renewing Websocket connection with id ${targetConnection.id}`);\n                this.enqueueReconnection(\n                    targetConnection,\n                    this.getReconnectURL(url, targetConnection),\n                    true\n                );\n            },\n            WebsocketCommon.MAX_CONNECTION_DURATION\n        );\n\n        ws.on('open', () => {\n            const oldWSConnection = targetConnection.ws;\n            if (targetConnection.renewalPending) targetConnection.ws = ws;\n            this.onOpen(url, targetConnection, oldWSConnection!);\n        });\n\n        ws.on('message', (data: WebSocketClient.Data) => {\n            this.onMessage(data.toString(), targetConnection);\n        });\n\n        ws.on('ping', () => {\n            this.logger.info('Received PING from server');\n            this.emit('ping');\n            ws.pong();\n            this.logger.info('Responded PONG to server\\'s PING message');\n        });\n\n        ws.on('pong', () => {\n            this.logger.info('Received PONG from server');\n            this.emit('pong');\n        });\n\n        ws.on('error', (err) => {\n            this.logger.error('Received error from server');\n            this.logger.error(err);\n            this.emit('error', err);\n        });\n\n        ws.on('close', (closeEventCode, reason) => {\n            this.emit('close', closeEventCode, reason);\n\n            if (!targetConnection.closeInitiated && !isRenewal) {\n                this.logger.warn(\n                    `Connection with id ${targetConnection.id} closed due to ${closeEventCode}: ${reason}`\n                );\n                this.scheduleTimer(\n                    ws,\n                    () => {\n                        this.logger.info(\n                            `Reconnecting conection with id ${targetConnection.id} to the server.`\n                        );\n                        targetConnection.reconnectionPending = true;\n                        this.enqueueReconnection(\n                            targetConnection,\n                            this.getReconnectURL(url, targetConnection),\n                            false\n                        );\n                    },\n                    this.configuration?.reconnectDelay ?? 5000\n                );\n            }\n        });\n\n        return targetConnection;\n    }\n\n    /**\n     * Checks if the WebSocket connection is currently open.\n     * @param connection - An optional WebSocket connection to check. If not provided, the entire connection pool is checked.\n     * @returns `true` if the connection is open, `false` otherwise.\n     */\n    isConnected(connection?: WebsocketConnection): boolean {\n        const connectionPool = connection ? [connection] : this.connectionPool;\n        return connectionPool.some((connection) => this.isConnectionReady(connection));\n    }\n\n    /**\n     * Disconnects from the WebSocket server.\n     * If there is no active connection, a warning is logged.\n     * Otherwise, all connections in the connection pool are closed gracefully,\n     * and a message is logged indicating that the connection has been disconnected.\n     * @returns A Promise that resolves when all connections have been closed.\n     * @throws Error if the WebSocket client is not set.\n     */\n    async disconnect(): Promise<void> {\n        if (!this.isConnected()) this.logger.warn('No connection to close.');\n        else {\n            this.connectionPool.forEach((connection) => {\n                connection.closeInitiated = true;\n            });\n\n            const disconnectPromises = this.connectionPool.map((connection: WebsocketConnection) =>\n                this.closeConnectionGracefully(connection.ws!, connection)\n            );\n\n            await Promise.all(disconnectPromises);\n            this.logger.info('Disconnected with Binance Websocket Server');\n        }\n    }\n\n    /**\n     * Sends a ping message to all connected Websocket servers in the pool.\n     * If no connections are ready, a warning is logged.\n     * For each active connection, the ping message is sent, and debug logs provide details.\n     * @throws Error if a Websocket client is not set for a connection.\n     */\n    pingServer(): void {\n        const connectedConnections = this.connectionPool.filter((connection) =>\n            this.isConnected(connection)\n        );\n\n        if (connectedConnections.length === 0) {\n            this.logger.warn('Ping only can be sent when connection is ready.');\n            return;\n        }\n\n        this.logger.info('Sending PING to all connected Websocket servers.');\n\n        connectedConnections.forEach((connection) => {\n            if (connection.ws) {\n                connection.ws.ping();\n                this.logger.debug(`PING sent to connection with id ${connection.id}`);\n            } else {\n                this.logger.error('WebSocket Client not set for a connection.');\n            }\n        });\n    }\n\n    /**\n     * Sends a payload through the WebSocket connection.\n     * @param payload - Message to send.\n     * @param id - Optional request identifier.\n     * @param promiseBased - Whether to return a promise.\n     * @param timeout - Timeout duration in milliseconds.\n     * @param connection - The WebSocket connection to use.\n     * @returns A promise if `promiseBased` is true, void otherwise.\n     * @throws Error if not connected or WebSocket client is not set.\n     */\n    protected send<T = unknown>(\n        payload: string,\n        id?: string,\n        promiseBased: boolean = true,\n        timeout: number = 5000,\n        connection?: WebsocketConnection\n    ): Promise<WebsocketApiResponse<T>> | void {\n        if (!this.isConnected(connection)) {\n            const errorMsg = 'Send can only be sent when connection is ready.';\n            this.logger.warn(errorMsg);\n            if (promiseBased) return Promise.reject(new Error(errorMsg));\n            else throw new Error(errorMsg);\n        }\n\n        const connectionToUse: WebsocketConnection = connection ?? this.getConnection();\n\n        if (!connectionToUse.ws) {\n            const errorMsg = 'Websocket Client not set';\n            this.logger.error(errorMsg);\n            if (promiseBased) return Promise.reject(new Error(errorMsg));\n            else throw new Error(errorMsg);\n        }\n\n        connectionToUse.ws.send(payload);\n\n        if (promiseBased) {\n            return new Promise<WebsocketApiResponse<T>>((resolve, reject) => {\n                if (!id) return reject(new Error('id is required for promise-based sending.'));\n\n                connectionToUse.pendingRequests.set(id, { resolve, reject });\n\n                this.scheduleTimer(\n                    connectionToUse.ws!,\n                    () => {\n                        if (connectionToUse.pendingRequests.has(id)) {\n                            connectionToUse.pendingRequests.delete(id);\n                            reject(new Error(`Request timeout for id: ${id}`));\n                        }\n                    },\n                    timeout\n                );\n            });\n        }\n    }\n}\n\nexport interface WebsocketSendMsgOptions {\n    id?: string;\n    [key: string]: string | number | boolean | object | undefined;\n}\n\nexport class WebsocketAPIBase extends WebsocketCommon {\n    private isConnecting: boolean = false;\n    streamCallbackMap: Map<string, Set<(data: unknown) => void>> = new Map();\n    configuration: ConfigurationWebsocketAPI;\n    logger: Logger = Logger.getInstance();\n\n    constructor(\n        configuration: ConfigurationWebsocketAPI,\n        connectionPool: WebsocketConnection[] = []\n    ) {\n        super(configuration, connectionPool);\n        this.configuration = configuration;\n    }\n\n    /**\n     * Prepares the WebSocket URL by adding optional timeUnit parameter\n     * @param wsUrl The base WebSocket URL\n     * @returns The formatted WebSocket URL with parameters\n     */\n    private prepareURL(wsUrl: string): string {\n        let url = wsUrl;\n        if (this?.configuration.timeUnit) {\n            try {\n                const _timeUnit = validateTimeUnit(this.configuration.timeUnit);\n                url = `${url}${url.includes('?') ? '&' : '?'}timeUnit=${_timeUnit}`;\n            } catch (err) {\n                this.logger.error(err);\n            }\n        }\n        return url;\n    }\n\n    /**\n     * Processes incoming WebSocket messages\n     * @param data The raw message data received\n     */\n    protected onMessage<T>(data: string, connection: WebsocketConnection): void {\n        try {\n            const message = JSON.parse(data);\n            const { id, status } = message;\n\n            if (id && connection.pendingRequests.has(id)) {\n                const request = connection.pendingRequests.get(id);\n                connection.pendingRequests.delete(id);\n\n                if (status && status >= 400) {\n                    request?.reject(message.error);\n                } else {\n                    const response: WebsocketApiResponse<T> = {\n                        data: message.result ?? message.response,\n                        ...(message.rateLimits && { rateLimits: message.rateLimits }),\n                    };\n                    request?.resolve(response);\n                }\n            } else if (\n                'event' in message &&\n                'e' in message['event'] &&\n                this.streamCallbackMap.size > 0\n            ) {\n                // Handle user data stream messages (currently with no ID we send the message to all registered callbacks)\n                this.streamCallbackMap.forEach((callbacks) =>\n                    callbacks.forEach((callback) => callback(message['event']))\n                );\n            } else {\n                this.logger.warn('Received response for unknown or timed-out request:', message);\n            }\n        } catch (error) {\n            this.logger.error('Failed to parse WebSocket message:', data, error);\n        }\n\n        super.onMessage(data, connection);\n    }\n\n    /**\n     * Establishes a WebSocket connection to Binance\n     * @returns Promise that resolves when connection is established\n     * @throws Error if connection times out\n     */\n    connect(): Promise<void> {\n        if (this.isConnected()) {\n            this.logger.info('WebSocket connection already established');\n            return Promise.resolve();\n        }\n\n        return new Promise((resolve, reject) => {\n            if (this.isConnecting) return;\n\n            this.isConnecting = true;\n\n            const timeout = setTimeout(() => {\n                this.isConnecting = false;\n                reject(new Error('Websocket connection timed out'));\n            }, 10000);\n\n            this.connectPool(this.prepareURL(this.configuration.wsURL as string))\n                .then(() => {\n                    clearTimeout(timeout);\n                    this.isConnecting = false;\n                    resolve();\n                })\n                .catch((error) => {\n                    clearTimeout(timeout);\n                    this.isConnecting = false;\n                    reject(error);\n                });\n        });\n    }\n\n    /**\n     * Sends a message to the WebSocket API Server.\n     * Supports both signed and unsigned messages.\n     * @param method The API method to call\n     * @param payload Message parameters and options\n     * @param options Additional requests options (withApiKey, isSigned)\n     * @returns Promise that resolves with the server response\n     * @throws Error if not connected\n     */\n    sendMessage<T = unknown>(\n        method: string,\n        payload: WebsocketSendMsgOptions = {},\n        options: { withApiKey?: boolean; isSigned?: boolean } = {}\n    ): Promise<WebsocketApiResponse<T>> {\n        if (!this.isConnected()) {\n            return Promise.reject(new Error('Not connected'));\n        }\n\n        const id = payload.id && /^[0-9a-f]{32}$/.test(payload.id) ? payload.id : randomString();\n        delete payload.id;\n\n        let params = removeEmptyValue(payload);\n\n        if (options.withApiKey || options.isSigned) {\n            params.apiKey = this.configuration.apiKey;\n        }\n\n        if (options.isSigned) {\n            params.timestamp = getTimestamp();\n            params = sortObject(params as ObjectType);\n            params.signature = getSignature(this.configuration!, params);\n        }\n\n        const data = {\n            id,\n            method,\n            params,\n        };\n\n        this.logger.debug('Send message to Binance WebSocket API Server:', data);\n        return this.send<T>(JSON.stringify(data), id, true, this.configuration?.timeout) as Promise<\n            WebsocketApiResponse<T>\n        >;\n    }\n}\n\nexport class WebsocketStreamsBase extends WebsocketCommon {\n    private streamConnectionMap: Map<string, WebsocketConnection> = new Map();\n    protected configuration: ConfigurationWebsocketStreams;\n    protected wsURL: string;\n    streamCallbackMap: Map<string, Set<(data: unknown) => void>> = new Map();\n    logger: Logger = Logger.getInstance();\n\n    constructor(\n        configuration: ConfigurationWebsocketStreams,\n        connectionPool: WebsocketConnection[] = []\n    ) {\n        super(configuration, connectionPool);\n        this.configuration = configuration;\n        this.wsURL = configuration.wsURL as string;\n    }\n\n    /**\n     * Formats the WebSocket URL for a given stream or streams.\n     * @param streams - Array of stream names to include in the URL.\n     * @returns The formatted WebSocket URL with the provided streams.\n     */\n    private prepareURL(streams: string[] = []): string {\n        let url = `${this.wsURL}/stream?streams=${streams.join('/')}`;\n\n        if (this.configuration?.timeUnit) {\n            try {\n                const _timeUnit = validateTimeUnit(this.configuration.timeUnit);\n                url = `${url}${url.includes('?') ? '&' : '?'}timeUnit=${_timeUnit}`;\n            } catch (err) {\n                this.logger.error(err);\n            }\n        }\n\n        return url;\n    }\n\n    /**\n     * Formats the WebSocket URL with stream and configuration parameters to be used for reconnection.\n     * @param url - The base WebSocket URL.\n     * @param targetConnection - The target WebSocket connection.\n     * @returns The formatted WebSocket URL with streams and optional parameters.\n     */\n    protected getReconnectURL(url: string, targetConnection: WebsocketConnection): string {\n        const streams = Array.from(this.streamConnectionMap.keys()).filter(\n            (stream) => this.streamConnectionMap.get(stream) === targetConnection\n        );\n        return this.prepareURL(streams);\n    }\n\n    /**\n     * Handles subscription to streams and assigns them to specific connections\n     * @param streams Array of stream names to subscribe to\n     * @returns Map of connections to streams\n     */\n    private handleStreamAssignment(streams: string[]): Map<WebsocketConnection, string[]> {\n        const connectionStreamMap = new Map<WebsocketConnection, string[]>();\n\n        streams.forEach((stream) => {\n            if (!this.streamCallbackMap.has(stream)) this.streamCallbackMap.set(stream, new Set());\n\n            let connection = this.streamConnectionMap.get(stream);\n\n            if (!connection || connection.closeInitiated || connection.reconnectionPending) {\n                connection = this.getConnection(true);\n                this.streamConnectionMap.set(stream, connection);\n            }\n\n            if (!connectionStreamMap.has(connection)) connectionStreamMap.set(connection, []);\n\n            connectionStreamMap.get(connection)?.push(stream);\n        });\n\n        return connectionStreamMap;\n    }\n\n    /**\n     * Sends a subscription payload for specified streams on a given connection.\n     * @param connection The WebSocket connection to use for sending the subscription.\n     * @param streams The streams to subscribe to.\n     * @param id Optional ID for the subscription.\n     */\n    private sendSubscriptionPayload(\n        connection: WebsocketConnection,\n        streams: string[],\n        id?: string\n    ): void {\n        const payload = {\n            method: 'SUBSCRIBE',\n            params: streams,\n            id: id && /^[0-9a-f]{32}$/.test(id) ? id : randomString(),\n        };\n        this.logger.info('SUBSCRIBE', payload);\n        this.send(JSON.stringify(payload), undefined, false, 0, connection);\n    }\n\n    /**\n     * Processes pending subscriptions for a given connection.\n     * Sends all queued subscriptions in a single payload.\n     * @param connection The WebSocket connection to process.\n     */\n    private processPendingSubscriptions(connection: WebsocketConnection): void {\n        if (connection.pendingSubscriptions && connection.pendingSubscriptions.length > 0) {\n            this.logger.info('Processing queued subscriptions for connection');\n            this.sendSubscriptionPayload(connection, connection.pendingSubscriptions);\n            connection.pendingSubscriptions = [];\n        }\n    }\n\n    /**\n     * Handles incoming WebSocket messages, parsing the data and invoking the appropriate callback function.\n     * If the message contains a stream name that is registered in the `streamCallbackMap`, the corresponding\n     * callback function is called with the message data.\n     * If the message cannot be parsed, an error is logged.\n     * @param data The raw WebSocket message data.\n     * @param connection The WebSocket connection that received the message.\n     */\n    protected onMessage(data: string, connection: WebsocketConnection): void {\n        try {\n            const parsedData = JSON.parse(data);\n            const streamName = parsedData?.stream;\n\n            if (streamName && this.streamCallbackMap.has(streamName))\n                this.streamCallbackMap\n                    .get(streamName)\n                    ?.forEach((callback) => callback(parsedData.data));\n        } catch (error) {\n            this.logger.error('Failed to parse WebSocket message:', data, error);\n        }\n\n        super.onMessage(data, connection);\n    }\n\n    /**\n     * Called when the WebSocket connection is opened.\n     * Processes any pending subscriptions for the target connection.\n     * @param url The URL of the WebSocket connection.\n     * @param targetConnection The WebSocket connection that was opened.\n     * @param oldConnection The previous WebSocket connection, if any.\n     * @param isRenewal Whether the connection is a renewal of an existing connection.\n     */\n    protected onOpen(\n        url: string,\n        targetConnection: WebsocketConnection,\n        oldWSConnection: WebSocketClient\n    ): void {\n        this.processPendingSubscriptions(targetConnection);\n        super.onOpen(url, targetConnection, oldWSConnection);\n    }\n\n    /**\n     * Connects to the WebSocket server and subscribes to the specified streams.\n     * This method returns a Promise that resolves when the connection is established,\n     * or rejects with an error if the connection fails to be established within 10 seconds.\n     * @param stream - A single stream name or an array of stream names to subscribe to.\n     * @returns A Promise that resolves when the connection is established.\n     */\n    connect(stream: string | string[] = []): Promise<void> {\n        const streams = Array.isArray(stream) ? stream : [stream];\n\n        return new Promise((resolve, reject) => {\n            const timeout = setTimeout(() => {\n                reject(new Error('Websocket connection timed out'));\n            }, 10000);\n\n            this.connectPool(this.prepareURL(streams))\n                .then(() => {\n                    clearTimeout(timeout);\n                    resolve();\n                })\n                .catch((error) => {\n                    clearTimeout(timeout);\n                    reject(error);\n                });\n        });\n    }\n\n    /**\n     * Disconnects the WebSocket connection and clears the stream callback map.\n     * This method is called to clean up the connection and associated resources.\n     */\n    async disconnect(): Promise<void> {\n        this.streamCallbackMap.clear();\n        this.streamConnectionMap.clear();\n        super.disconnect();\n    }\n\n    /**\n     * Subscribes to one or multiple WebSocket streams\n     * Handles both single and pool modes\n     * @param stream Single stream name or array of stream names to subscribe to\n     * @param id Optional subscription ID\n     * @returns void\n     */\n    subscribe(stream: string | string[], id?: string): void {\n        const streams = (Array.isArray(stream) ? stream : [stream]).filter(\n            (stream) => !this.streamConnectionMap.has(stream)\n        );\n        const connectionStreamMap = this.handleStreamAssignment(streams);\n\n        connectionStreamMap.forEach((streams, connection) => {\n            if (!this.isConnected(connection)) {\n                this.logger.info(\n                    `Connection is not ready. Queuing subscription for streams: ${streams}`\n                );\n                connection.pendingSubscriptions?.push(...streams);\n\n                return;\n            }\n\n            this.sendSubscriptionPayload(connection, streams, id);\n        });\n    }\n\n    /**\n     * Unsubscribes from one or multiple WebSocket streams\n     * Handles both single and pool modes\n     * @param stream Single stream name or array of stream names to unsubscribe from\n     * @param id Optional unsubscription ID\n     * @returns void\n     */\n    unsubscribe(stream: string | string[], id?: string): void {\n        const streams = Array.isArray(stream) ? stream : [stream];\n\n        streams.forEach((stream) => {\n            const connection = this.streamConnectionMap.get(stream);\n            if (!connection || !connection.ws || !this.isConnected(connection)) {\n                this.logger.warn(`Stream ${stream} not associated with an active connection.`);\n                return;\n            }\n\n            if (\n                !this.streamCallbackMap.has(stream) ||\n                this.streamCallbackMap.get(stream)?.size === 0\n            ) {\n                const payload = {\n                    method: 'UNSUBSCRIBE',\n                    params: [stream],\n                    id: id && /^[0-9a-f]{32}$/.test(id) ? id : randomString(),\n                };\n                this.logger.info('UNSUBSCRIBE', payload);\n                this.send(JSON.stringify(payload), undefined, false, 0, connection);\n\n                this.streamConnectionMap.delete(stream);\n                this.streamCallbackMap.delete(stream);\n            }\n        });\n    }\n\n    /**\n     * Checks if the specified stream is currently subscribed.\n     * @param stream - The name of the stream to check.\n     * @returns `true` if the stream is currently subscribed, `false` otherwise.\n     */\n    isSubscribed(stream: string): boolean {\n        return this.streamConnectionMap.has(stream);\n    }\n}\n\nexport interface WebsocketStream<T> {\n    /**\n     * Attach a listener for the stream.\n     * @param event - Event name (currently supports \"message\").\n     * @param callback - Callback function to handle incoming data.\n     */\n    on(event: 'message', callback: (data: T) => void | Promise<void>): void;\n\n    /**\n     * Unsubscribe from the stream and clean up resources.\n     */\n    unsubscribe(): void;\n}\n\n/**\n * Creates a WebSocket stream handler for managing stream subscriptions and callbacks.\n *\n * @template T The type of data expected in the stream messages\n * @param {WebsocketAPIBase | WebsocketStreamsBase} websocketBase The WebSocket base instance\n * @param {string} streamOrId The stream identifier\n * @param {string} [id] Optional additional identifier\n * @returns {WebsocketStream<T>} A stream handler with methods to register callbacks and unsubscribe\n */\nexport function createStreamHandler<T>(\n    websocketBase: WebsocketAPIBase | WebsocketStreamsBase,\n    streamOrId: string,\n    id?: string\n): WebsocketStream<T> {\n    if (websocketBase instanceof WebsocketStreamsBase) websocketBase.subscribe(streamOrId, id);\n\n    let registeredCallback: (data: unknown) => void;\n    return {\n        on: (event: 'message', callback: (data: T) => void | Promise<void>) => {\n            if (event === 'message') {\n                registeredCallback = (data: unknown) => {\n                    Promise.resolve(callback(data as T)).catch((err) => {\n                        websocketBase.logger.error(`Error in stream callback: ${err}`);\n                    });\n                };\n                const callbackSet = websocketBase.streamCallbackMap.get(streamOrId) ?? new Set();\n                callbackSet.add(registeredCallback);\n                websocketBase.streamCallbackMap.set(streamOrId, callbackSet);\n            }\n        },\n        unsubscribe: () => {\n            if (registeredCallback)\n                websocketBase.streamCallbackMap.get(streamOrId)?.delete(registeredCallback);\n            if (websocketBase instanceof WebsocketStreamsBase)\n                websocketBase.unsubscribe(streamOrId, id);\n        },\n    };\n}\n"],"mappings":"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","names":["LogLevel","delay","connection","stream","streams"]}