Repository: ccxt/ccxt
File: ts/src/pro/gate.ts (TypeScript)

Code before:
        //          "A": "0.0353"
        //        }
        //    }
        //
        this.helperForHandleTickerBidAsk ('bidask', client, message);
    }

    async helperForWatchTickersBidsAsks (symbols: Strings = undefined, methdoName: Str = undefined, params = {}): Promise<Tickers> {
        await this.loadMarkets ();
        symbols = this.marketSymbols (symbols);
        let marketType = undefined;
        [ marketType, params ] = this.handleMarketTypeAndParams (methdoName, undefined, params);
        let subType = undefined;
        [ subType, params ] = this.handleSubTypeAndParams (methdoName, undefined, params);
        if (symbols === undefined) {
            if (marketType === undefined) {
                throw new ArgumentsRequired (this.id + ' ' + methdoName + ' requires symbols or set params["defaultType"] to any from "spot|swap|future". if you do not use spot, then you also need to set params["defaultSubType"] to "linear" or "inverse"');
            }
            this.checkRequiredArgument (methdoName, marketType, 'defaultType', [ 'spot', 'swap', 'future', 'option' ]);
            const isSwapOrFuture = this.inArray (marketType, [ 'swap', 'future' ]);
            if (isSwapOrFuture) {
                this.checkRequiredArgument (methdoName, subType, 'defaultSubType', [ 'linear', 'inverse' ]);
            }
            let filteredMarkets = this.filterBy (this.markets, 'type', marketType);
            filteredMarkets = this.filterByArray (filteredMarkets, 'active', [ true ], false);
            if (isSwapOrFuture) {
                filteredMarkets = this.filterBy (filteredMarkets, 'subType', subType);
            }
            symbols = this.getArrayOfObjectsKey (filteredMarkets, 'symbol');
        }
        const market = this.market (symbols[0]);
        const messageType = this.getTypeByMarket (market);
        const marketIds = this.marketIds (symbols);
        let method = undefined;
        [ method, params ] = this.handleOptionAndParams (params, methdoName, 'method');
        const url = this.getUrlByMarket (market);
        const channel = messageType + '.' + method;
        const isWatchTickers = (methdoName === 'watchTickers');
        const prefix = isWatchTickers ? 'ticker' : 'bidask';
        const messageHashes = [];
        for (let i = 0; i < symbols.length; i++) {
            const symbol = symbols[i];
            messageHashes.push (prefix + ':' + symbol);
        }
        const tickerOrBidAsk = await this.subscribePublicMultiple (url, messageHashes, marketIds, channel, params);
        if (this.newUpdates) {
            const items = {};
            items[tickerOrBidAsk['symbol']] = tickerOrBidAsk;
            return items;
        }
        const result = isWatchTickers ? this.tickers : this.bidsasks;

Review comment (performance):
I would have to test it in this context. But when looking to implement this on binance. I needed to create an ArrayCache, as it could happen that the future is resolved several times, but the user only receives it once. Therefore losing information. I'm worndering if we would have to do the same here.
https://github.com/ccxt/ccxt/pull/20903


Code after:
        //    }
        //
        this.handleTickerAndBidAsk ('bidask', client, message);
    }

    async subscribeWatchTickersAndBidsAsks (symbols: Strings = undefined, callerMethodName: Str = undefined, params = {}): Promise<Tickers> {
        await this.loadMarkets ();
        [ callerMethodName, params ] = this.handleParamString (params, 'callerMethodName', callerMethodName);
        symbols = this.marketSymbols (symbols, undefined, false);
        const market = this.market (symbols[0]);
        const messageType = this.getTypeByMarket (market);
        const marketIds = this.marketIds (symbols);
        let channelName = undefined;
        [ channelName, params ] = this.handleOptionAndParams (params, callerMethodName, 'method');
        const url = this.getUrlByMarket (market);
        const channel = messageType + '.' + channelName;
        const isWatchTickers = callerMethodName.indexOf ('watchTicker') >= 0;
        const prefix = isWatchTickers ? 'ticker' : 'bidask';
        const messageHashes = [];
        for (let i = 0; i < symbols.length; i++) {
            const symbol = symbols[i];
            messageHashes.push (prefix + ':' + symbol);
        }
        const tickerOrBidAsk = await this.subscribePublicMultiple (url, messageHashes, marketIds, channel, params);
        if (this.newUpdates) {
            const items = {};
            items[tickerOrBidAsk['symbol']] = tickerOrBidAsk;
            return items;
        }
        const result = isWatchTickers ? this.tickers : this.bidsasks;
        return this.filterByArray (result, 'symbol', symbols, true);
    }

    handleTickerAndBidAsk (objectName: string, client: Client, message) {
        const channel = this.safeString (message, 'channel');
        const parts = channel.split ('.');
        const rawMarketType = this.safeString (parts, 0);
        const marketType = (rawMarketType === 'futures') ? 'contract' : 'spot';
        let results = [];
        if (marketType === 'contract') {
            results = this.safeList (message, 'result', []);
        } else {
            const rawTicker = this.safeDict (message, 'result', {});
            results = [ rawTicker ];
        }
        const isTicker = (objectName === 'ticker'); // whether ticker or bid-ask
        for (let i = 0; i < results.length; i++) {
            const rawTicker = results[i];
            const marketId = this.safeString (rawTicker, 's');
            const market = this.safeMarket (marketId, undefined, '_', marketType);
            const parsedItem = this.parseTicker (rawTicker, market);