Scaling Hyperliquid Wallet Activity with the GoldRush Streaming API

Harish RaisinghaniHarish Raisinghani5 min read
How GoldRush scaled Hyperliquid wallet activity streaming to 200K+ monitored wallets with one GraphQL-over-WebSocket subscription.

GoldRush recently pushed the Hyperliquid walletTxs stream through a controlled load test: one client, one WebSocket, one GraphQL subscription, and over 200,000 monitored wallets.

That number is useful, but only if we are precise about what it means. This was not a claim about a maximum wallet limit. It was a benchmark for how far a single decoded wallet activity stream could stretch under test conditions while still delivering events and keeping client memory stable.

The reason we cared about this test is simple: Hyperliquid wallet activity is not just an address-history problem. The problem is not just the volume. It is the shape.

On many EVM chains, wallet activity starts with a familiar model: transactions, logs, token transfers, traces, and contract calls. Hyperliquid activity is different. It is closer to an exchange state. A product does not only need to know that an account has activity. It needs to know whether that activity was a fill, funding payment, ledger update, deposit, withdrawal, delegation, liquidation, vault movement, staking action, reward claim, or borrow/lend update.

It also moves fast. Hyperliquid block times are on the order of 70 ms. A polling loop that runs every few seconds is not even close to live, and trying to poll faster turns wallet monitoring into a high-frequency request scheduler across every watched address.

That is why this work started with streaming. The client should subscribe once. GoldRush should watch the account set and push decoded activity as it arrives.

What "decoded" means on Hyperliquid

Decoded activity is the difference between "something happened" and "the product knows what happened."

For Hyperliquid, the GoldRush walletTxs stream does more than tell you that an account changed. It returns decoded activity in product-ready shapes: fills, funding, deposits, withdrawals, liquidations, vault activity, staking, rewards, borrow/lend updates, and ledger movements.

That matters because each of those events means something different to the product consuming it. A wallet wants to show the user what happened. A tax or accounting system needs to classify the movement. An analytics product may want to filter for fills, liquidations, or vault activity. The point is not that every team gets a bigger blob of data. It is that they do not have to rebuild Hyperliquid semantics before they can use it.

walletTxs moves that interpretation layer into the stream: subscribe once, receive decoded activity, and build the product on top.

Why GraphQL-over-WebSocket made sense

GoldRush already had a Streaming API built around GraphQL-over-WebSocket. A plain WebSocket can push messages, but the client still has to know somewhere else what those messages look like. With a GraphQL subscription, the client can ask for the fields it needs across a typed Hyperliquid union: fill fields, funding fields, ledger delta fields, liquidation fields, vault fields, staking fields, and so on.

WebSocket gives us the long-lived push channel. GraphQL gives the stream a typed shape.

A simplified subscription looks like this:

subscription { walletTxs( wallet_addresses: ["0x8e80c4b533dd977cf716b5c24fd9223129272804"] chain_name: HYPERCORE_MAINNET ) { tx_hash block_signed_at decoded_type decoded_details { ... on HypercoreFillTransaction { coin side price size fee closed_pnl } ... on HypercoreLedgerEvent { ledger_type time } } } }

This is separate from GoldRush's native Hyperliquid /ws compatibility work. Native /ws matters for builders already wired into Hyperliquid market data patterns. GraphQL-over-WebSocket makes sense here because wallet activity is decoded, typed, and product-facing.

What had to change for Hyperliquid

The Streaming API already had the right transport: GraphQL-over-WebSocket subscriptions. The Hyperliquid work was mostly about the layer behind that transport.

GoldRush had to take exchange-native activity and turn it into wallet-centered events. That meant mapping fills, funding, ledger movements, vault activity, liquidations, and other account updates into a consistent stream without flattening away the meaning of each event.

The hard part was doing that while scaling the watchlist. It is one thing to decode activity for a few wallets. It is another to do it across a large monitored set, keep the stream stable, and avoid forcing customers to poll behind it as a backup.

That is the actual point: the work was not "add Hyperliquid to an existing socket." It was "extend the decoding layer and prove it can hold up at wallet-monitoring scale."

The 200K monitored wallets benchmark

We built a staged load-test harness for the GoldRush walletTxs streaming subscription against HYPERCORE_MAINNET, using @covalenthq/client-sdk and the StreamingService.rawQuery method. 

The rules were: one client, one WebSocket, one subscription. The test ramped through 11 stages, from a 1-wallet smoke test to a 200,000-wallet stretch run. Each stage included three known-active canary addresses so we could verify event flow even if the random wallets were quiet during the test window.

PASS means the subscription connected, delivered events, closed cleanly, and kept client RSS under budget.

StageWalletsPayloadDurationFirst ResponseEventsMax RSSResultNotes
S012.8 KB30 s1,065 ms48102 MBPASS-
S11007.3 KB60 s464 ms113101 MBPASS-
S21,00047.7 KB120 s1,145 ms416104 MBPASS-
S35,000227.4 KB180 s869 ms1,057104 MBPASS-
S410,000452.0 KB300 s1,056 ms3,527105 MBPASS-
S515,000676.6 KB300 s1,113 ms3,29884 MBPASS-
S620,000901.2 KB300 s1,442 ms4,989108 MBPASS-
S730,0001,350 KB300 s-072 MBFAILThe WS repeatedly connected and closed for 300 seconds with no events. Root cause was the server-side WS frame cap.
S730,0001,350 KB300 s1,466 ms44,045241 MBPASSPassed after backend raised WS frame cap from ~1 MB to 16 MB.
S840,0001,800 KB600 s1,765 ms23,794113 MBPASS-
S9100,0004,397 KB600 s5,624 ms21,838158 MBPASS-
S10200,0008,791 KB900 s3,193 ms76,342162 MBPASS-

Stage 7 found the first real edge. At roughly a 1.35 MB payload, the stream hit a server-side WebSocket frame cap and fell into a silent reconnect loop. The connection kept cycling through connecting, established, and closed for the full 300 seconds. From the SDK consumer's point of view, no events arrived and no error callback explained why.

Raising the backend frame cap from ~1 MB to 16 MB fixed that edge. The retry passed at 30,000 wallets, and the later stages passed through 200,000 monitored wallets on one client, one WebSocket, and one subscription.

Event counts should not be read as linear with wallet count. Activity depends on what the watched wallets happened to do during each test window. The healthier signal was that canary events kept flowing, the stream stayed open, events arrived, and the subscription closed cleanly.

What this unlocks

  • For wallets, Hyperliquid activity becomes a live account feed. Fills, fees, realized PnL, deposits, withdrawals, funding, and liquidations can appear without the app constantly asking whether anything changed.

  • For tax and accounting products, the useful part is classification. A ledger event is not just a blob of account movement. It can carry the subtype and fields needed to separate a withdrawal from a vault deposit, a spot transfer, a liquidation, a staking movement, or a borrow/lend update.

  • For analytics teams, the decoded stream makes narrower products easier to build: liquidation tapes, vault leaderboards, funding monitors, whale alerts, copy-trading feeds, and live cohort views. The team can filter the event types it cares about instead of rebuilding the Hyperliquid decoder first.

  • For portfolio products, the stream reduces the amount of hidden infrastructure behind the UI. Instead of polling every connected account to keep balances and activity fresh, the product can subscribe to account activity and spend more time on the user experience around it.

Decoded activity becomes something the product can subscribe to, not something every team has to reconstruct.

Next in the series: how GoldRush approached native Hyperliquid /info compatibility, and why builders needed drop-in behavior rather than another abstraction.

Enjoyed this post?

Get more Web3 insights and updates delivered weekly. Join thousands of developers staying ahead in blockchain.

Get Started

Get started with GoldRush API in minutes. Sign up for a free API key and start building.

Support

Explore multiple support options! From FAQs for self-help to real-time interactions on Discord.

Contact Sales

Interested in our professional or enterprise plans? Contact our sales team to learn more.