Skip to content

BinanceFeed doesn't normalize symbol case — fetchTicker/watchTicker silently hang then time out for non-canonical-case symbols #2415

Description

@realfishsam

Gap

BinanceFeed never normalizes symbol case when caching tickers or matching WebSocket subscriptions, unlike ChainlinkFeed, which upper-cases consistently at every entry point. Incoming ticker events always arrive with canonical uppercase symbols (e.g. "BTC/USDT"), so a caller who passes any other case (e.g. "btc/usdt") through either SDK's fetchTicker/watchTicker never gets a subscription match — the request silently hangs until a hardcoded timeout fires with a generic, misleading error.

Core

  • core/src/feeds/binance/binance-feed.ts:102-104 (fetchTickerImpl): const cached = this.latestTickers.get(symbol); — raw symbol, not upper-cased.
  • core/src/feeds/binance/binance-feed.ts:132-134 (watchTickerImpl): const sub: Subscription = { symbol, callback }; — raw symbol, not upper-cased.
  • core/src/feeds/binance/binance-feed.ts:230-234 (handleMessage) dispatches with strict equality: if (sub.symbol === ticker.symbol) { sub.callback(ticker); }, and ticker.symbol always comes out canonical-uppercase via symbolToPair() (core/src/feeds/binance/normalizer.ts:11-22).
  • Contrast core/src/feeds/chainlink/chainlink-feed.ts:128 (fetchTickerImpl): this.latestTickers.get(symbol.toUpperCase()), and :181 (watchTickerImpl): symbol: symbol.toUpperCase() — Chainlink correctly normalizes.

TypeScript SDK

sdks/typescript/pmxt/feed-client.ts:91-93 — fetchTicker(symbol) passes the caller's symbol straight through as a query param with no case normalization.

Python SDK

sdks/python/pmxt/feed_client.py:119-121 — fetch_ticker(symbol) — same, passes through verbatim.

Evidence

Read binance-feed.ts and chainlink-feed.ts side by side: Chainlink calls .toUpperCase() at both cache-lookup and subscription-registration sites; Binance does neither. core/test/unit/dataFeeds.core.test.ts only ever exercises canonical-case symbols like 'BTC/USDT', so this path is untested.

Impact

Calling feed.fetchTicker('btc/usdt') (or any non-canonical case) through either SDK against the binance feed never matches an incoming trade event, so the internal watchTickerImpl-based wait inside fetchTickerImpl (binance-feed.ts:107-118) silently hangs until the hardcoded 10s timeout and then throws "timed out waiting for trade" — with no indication the real cause is a case mismatch.


Found by automated Core-to-SDK surface coverage audit

Activity

  1. AnuragR3k commented on Sep 22, 2026

    @AnuragR3k

    @realfishsam I’ve opened a PR for this: #2421

    It normalizes Binance ticker symbols to uppercase for both fetchTicker and watchTicker, and adds regression tests for lowercase symbols like btc/usdt.

    Tests and TypeScript build are passing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions