Repository navigation
Improve realtime correctness, cache isolation, and rendering performance - #2124
Open
antonbelous0v wants to merge 24 commits into
Open
antonbelous0v wants to merge 24 commits into
antonbelous0v wants to merge 24 commits into
Conversation
|
@antonbelous0v is attempting to deploy a commit to the dYdX Trading Team on Vercel. A member of the Team first needs to authorize it. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
d3d402c7Report the actual indexer heightuseApiStatereturned the validator height for bothvalidatorHeightandindexerHeight.The hook now reads the real indexer height, so API status, lag reporting, and related analytics no longer compare the validator against itself.
25495ddaShare locale state across output componentsOutputcomponents subscribed to Redux independently to read the selected locale, even though they were already underLocaleProvider.The selected locale now comes from the existing locale context. This removes a Redux subscription from every
Outputinstance and keeps locale formatting state behind one provider boundary.9c26bbbfAvoid copying existing BigNumber valuesMustBigNumberconstructed a newBigNumbereven when the input was already aBigNumber.It now returns existing instances directly.
BigNumberoperations are immutable, so the copy provided no isolation and only added allocations across a helper with a large number of call sites.1bcca3d7Reuse parsed values during number formattingformatNumberOutputparsed the same input up to four times to calculate its absolute value and sign.The value is now converted once and reused for all formatting decisions. Tests cover positive, negative, fiat, regular, and compact output.
200eff74Handle unavailable staking validatorsDefault-validator selection could call
reduce()on an empty array when the configured whitelist had no matches or the validator response was empty.The selection is now safe for empty responses, falls back to available bonded validators, and excludes jailed or unbonded validators from the default candidates.
6872dd13Make validator ranking deterministicValidator ranking used two consecutive sorts with comparators that returned
-1for equal values. This violated theArray.sort()comparator contract and could produce unstable ordering.Ranking now uses one deterministic comparator:
0for genuinely equal values.c2022d52Stop idle chart animation framesTimeSeriesChartkept a permanentrequestAnimationFrameloop alive after zoom animation had completed, and also while no animation was active.The animation hook now:
For an idle chart, this changes the steady-state animation workload from roughly 60 callbacks per second to zero.
2d18368dAvoid redundant orderbook redrawsuseDrawOrderbookrebuiltpriceSizeMapduring every render. Because that new object was an effect dependency, any parent render caused a complete canvas clear, row redraw, and replacement timeout even when orderbook data had not changed.The map is now stable for the lifetime of the input data, preventing unrelated renders from triggering full orderbook redraws.
7fe11635Bridge candle history to live updatesThe first WebSocket candle snapshot was treated only as an internal baseline and never sent to TradingView.
A candle arriving between the REST history response and WebSocket subscription could therefore be missed until another update arrived.
The initial WebSocket snapshot now publishes its most recent candle. Later messages continue publishing updates to the current candle and any newer candles.
db6132d6Uncross orderbook levels in linear timeOrderbook uncrossing repeatedly called
Array.shift()while removing stale crossed levels. Since every shift moves the remaining array, a large crossed section could degrade to O(n²).The implementation now advances bid and ask indices and performs one final
slice()per side.Complexity:
9d838708Find visible chart points with binary searchDuring zoom animation,
TimeSeriesChartscanned the complete historical dataset on every frame to find visible points. It then created another temporary array to calculate the Y range.Since the chart already relies on chronologically sorted data, visible boundaries are now found with binary search. The Y range is calculated directly without the intermediate
map()allocation.Complexity for selecting visible data:
kis the number of visible pointsThis matters most for long histories and animated zooming, where the calculation runs once per frame.
10bc9fdaThrottle orderbook scroll measurementsThe orderbook middle-row listener called
getBoundingClientRect()for every native scroll event. Browsers can emit multiple scroll events per rendered frame, causing repeated synchronous layout reads.Measurements are now limited to one
requestAnimationFramecallback per frame. The listener is passive, and cleanup removes it from the exact DOM node where it was registered.This also fixes a listener leak caused by reading a changed
ref.currentduring cleanup.57bd9d6dKeep chart gradient IDs stable and isolatedThreshold charts generated a new random SVG ID on every render, forcing unnecessary threshold DOM updates.
Gradient IDs were also shared globally between chart instances, so multiple charts could reference another chart's gradient definitions.
IDs are now:
9b1cd7b8Tear down replaced candle subscriptionsRegistering a TradingView candle subscription with an existing
listenerGuidoverwrote the stored teardown callback without invoking it.The old WebSocket subscriber remained active and could continue delivering duplicate candles.
Subscription replacement is now atomic: the previous subscription is torn down before the new one is registered. Invalid replacement subscriptions also remove the old listener.
2510eb21Reuse compact number formattersEvery compact-number and compact-fiat render created a new
Intl.NumberFormatinstance.ICU formatter construction is substantially more expensive than calling
format()on an existing formatter. Formatters are now cached by locale and currency mode.The cache is bounded by the supported locale set and the two compact formatting modes.
c347a24aRevalidate markets when network data changesMarket validation was memoized using only
marketIds.length.If two networks exposed the same number of markets, switching networks did not invalidate the memoized market ID. The application could keep a market or prediction-market classification from the previous network.
Validation now depends on the actual market collections, and route validation runs when the available market IDs change.
21d76562Bound WebSocket gap recovery workMissingMessageDetectorcreated one timeout for every missingmessage_id.An anomalous jump in IDs could synchronously allocate hundreds of thousands or millions of timers, freezing the tab and causing a large memory spike.
Normal small gaps are still tracked individually. Gaps above the safe bound now trigger the existing reconnect recovery path immediately instead of allocating an unbounded timer queue.
af423f19Isolate withdrawal limits by networkWithdrawal capacity and withdrawal/transfer gating status used global React Query keys.
After switching networks, the UI could reuse limits and gating state from the previous network until the cache became stale.
The keys now include:
Capacity calculation also reacts correctly when the withdrawal safety feature changes at runtime.
50379facIsolate vault queries by networkVault queries reused global cache entries across networks.
The following data is now scoped to the selected network:
This prevents mainnet and testnet TVL, balances, positions, and slippage from being mixed.
76317962Scope transfer fee simulations to the accountTransfer fee simulations were cached only by amount, recipient, and transfer type.
The same inputs after an account or network switch could reuse a fee calculated with a different wallet or chain context.
The query key now includes both the selected network and dYdX address.
4013f37aScope asset metadata cache to its endpointAsset metadata and prices used the same cache key after the metadata endpoint changed.
A network switch could therefore continue showing metadata and prices from the previous environment for up to five minutes.
The metadata endpoint is now part of the cache key.
dadfa9b1Scope deposit addresses to the indexerBridging deposit addresses were cached only by dYdX address.
The same account on another network could reuse addresses returned by the previous indexer endpoint.
The active indexer URL is now part of the query key.
c71f39beScope Turnkey sessions to the walletThe wallet-export dialog stored the Turnkey session under one global query key.
After switching embedded wallets, a cached session from the previous wallet could continue to satisfy the export UI's session check.
The session query is now keyed by the concrete Turnkey wallet ID and remains disabled until that wallet is available.
88518a2fIsolate affiliate data by indexerAffiliate queries were not scoped to their indexer, including the leaderboard query with
staleTime: Infinity.After switching networks, the application could indefinitely display affiliate data from the previous environment.
The active indexer endpoint is now included in the keys for: