Conversation
Show open interest in USD by applying mark price and remove the redundant USDC suffix.
Use Effect Order module with tri-state cycling (desc → asc → none) for all market table columns via sortable headers with direction icons.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR adds Hyperliquid WebSocket-based streaming to drive real-time market/portfolio price updates, refactors markets/positions to Record<id, AtomRef<...>> for faster lookups and reactive updates, and introduces a PriceFlash UI helper for animating price changes.
Changes:
- Add
HyperliquidService+ atoms for streaming mid prices and candles; wire streaming into market/position state updates. - Refactor portfolio/market atoms and multiple UI callsites to use
Record+AtomRefinstead of arrays. - Add
PriceFlashcomponent + CSS animation, update UI to use it, and adjust tooling/dependency configuration (Vite config factory, package deps, scripts).
Reviewed changes
Copilot reviewed 36 out of 37 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-workspace.yaml | Adds Hyperliquid client to the shared catalog; removes testing-library entries. |
| pnpm-lock.yaml | Lockfile updates for new deps and removed testing libs. |
| package.json | Simplifies dev script and normalizes build script placement. |
| packages/common/package.json | Adds Hyperliquid dependency and switches @effect/experimental to catalog spec. |
| packages/common/vite.config.ts | Updates to use the new createCommonViteConfig() factory. |
| packages/common/src/vite.config.ts | Refactors shared Vite config into a factory function. |
| packages/widget/vite.config.ts | Switches to createCommonViteConfig() usage. |
| packages/dashboard/vite.config.ts | Switches to createCommonViteConfig() usage. |
| packages/widget/package.json | Dependency spec changes (notably devDependency removals). |
| packages/dashboard/package.json | Switches @effect/experimental to catalog spec and removes testing-library dev deps. |
| packages/common/src/styles/base.css | Adds keyframes/classes for price flash animations. |
| packages/common/src/components/molecules/price-flash.tsx | New component to animate price changes by toggling CSS classes. |
| packages/common/src/components/index.ts | Exports the new PriceFlash component. |
| packages/common/src/services/runtime.ts | Registers HyperliquidService in the runtime layer. |
| packages/common/src/services/index.ts | Re-exports Hyperliquid service module. |
| packages/common/src/services/hyperliquid/index.ts | New Hyperliquid WS/HTTP service wrapper (subscriptions + snapshot). |
| packages/common/src/atoms/hyperliquid-atoms.ts | Introduces midPriceAtom stream source. |
| packages/common/src/atoms/candle-atoms.ts | Introduces candleStreamAtom family for candle subscriptions. |
| packages/common/src/atoms/index.ts | Exports candle atoms from the common atoms entrypoint. |
| packages/common/src/atoms/markets-atoms.ts | Adds marketsBySymbolAtom, increases refresh interval, adds mid-price market updates. |
| packages/common/src/atoms/portfolio-atoms.ts | Refactors positionsAtom to a Record of AtomRefs; adds mid-price position updates. |
| packages/common/src/lib/formatting.ts | Changes formatTPOrSLSettings to return structured { tp, sl }. |
| packages/common/src/hooks/use-order-form.ts | Updates position lookup logic to use Record.get instead of array search. |
| packages/dashboard/src/components/modules/root/Preload.tsx | Mounts live mid-price update atoms for markets/positions. |
| packages/widget/src/components/modules/Root/PreloadAtoms.tsx | Mounts live mid-price updates for positions when wallet is connected. |
| packages/dashboard/src/components/modules/trade/market-info/index.tsx | Uses PriceFlash, adjusts display fields (incl. OI/funding). |
| packages/dashboard/src/components/modules/trade/market-info/market-selector-popover.tsx | Adds sortable headers and adjusts displayed metrics (incl. OI). |
| packages/dashboard/src/components/modules/trade/order-form/index.tsx | Updates advanced order display; adds maker/taker fee rows. |
| packages/dashboard/src/components/molecules/positions/index.tsx | Enhances tab labels to show counts for positions/orders when connected. |
| packages/dashboard/src/components/molecules/positions/positions-tab.tsx | Refactors to AtomRef-based data flow and adds market selection interaction. |
| packages/widget/src/components/modules/Home/index.tsx | Updates positions count logic for Record-based positions. |
| packages/widget/src/components/modules/Home/Positions/index.tsx | Refactors positions aggregation/rendering for Record of AtomRefs. |
| packages/widget/src/components/modules/Home/Positions/position-card.tsx | Refactors to accept positionRef and read via useAtomRef. |
| packages/widget/src/components/modules/PositionDetails/Overview/index.tsx | Refactors position lookup from array .find to Record.get. |
| packages/widget/src/components/modules/PositionDetails/Overview/Position/index.tsx | Refactors to pass positionRef and read reactively via useAtomRef. |
| packages/widget/src/components/modules/PositionDetails/Close/state.tsx | Refactors close flow to fetch position via Record.get. |
| packages/widget/src/components/modules/Order/Overview/index.tsx | Updates TP/SL settings display to use new structured formatter output. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| volume: Order.mapInput(Order.number, (ref: MarketRef) => ref.value.volume24h), | ||
| oi: Order.mapInput( | ||
| Order.number, | ||
| (ref: MarketRef) => ref.value.openInterest * ref.value.markPrice, |
There was a problem hiding this comment.
openInterest is already documented/typed as “total notional value of all open positions” (i.e., already in quote/USD). Multiplying it by markPrice here will inflate the value and break the OI sort. Use openInterest directly for both sorting and display unless the API field semantics have changed (in which case the API schema/docs should be updated too).
| (ref: MarketRef) => ref.value.openInterest * ref.value.markPrice, | |
| (ref: MarketRef) => ref.value.openInterest, |
There was a problem hiding this comment.
hm, from what i see in API responses, it returns openInterest in baseAsset size, while swagger comment says this as total notional value of all open positions - @Philippoes is comment wrong or this in fact should be in notional value?
| </Text> | ||
| <Text variant="labelSmWhiteNeg" className="font-medium"> | ||
| {market.makerFee ? formatRate(market.makerFee) : "-"} | ||
| {formatCompactUsdAmount(market.openInterest * market.markPrice)} |
There was a problem hiding this comment.
Open interest is displayed as market.openInterest * market.markPrice, but openInterest is already a notional value per the API schema. This will overstate OI; use market.openInterest directly (or update the API schema/docs if the backend now returns contracts instead of notional).
| {formatCompactUsdAmount(market.openInterest * market.markPrice)} | |
| {formatCompactUsdAmount(market.openInterest)} |
| {/* Open Interest */} | ||
| <Text variant="labelSmWhiteNeg" className="font-medium"> | ||
| {formatCompactUsdAmount(market.openInterest)} | ||
| {formatCompactUsdAmount(market.openInterest * market.markPrice)} |
There was a problem hiding this comment.
Open interest display is being computed as market.openInterest * market.markPrice, but openInterest is already a notional value per the API schema. This will show an incorrect (overstated) OI number; display market.openInterest directly unless the backend field meaning has changed.
| {formatCompactUsdAmount(market.openInterest * market.markPrice)} | |
| {formatCompactUsdAmount(market.openInterest)} |
This pull request introduces real-time price streaming and integration with Hyperliquid WebSocket APIs, enabling live updates for market and portfolio data. It also adds a new UI component for animated price changes and refactors the codebase to support these enhancements. The most important changes are grouped below:
Hyperliquid WebSocket integration and streaming:
HyperliquidServicetopackages/common/src/services/hyperliquid/index.tsfor real-time candle and mid-price subscriptions using WebSocket APIs.midPriceAtomandcandleStreamAtomfor subscribing to live market data, and exposed these atoms for use throughout the application. [1] [2] [3] [4] [5] [6]Live market and portfolio updates:
marketsBySymbolAtomandupdateMarketsMidPriceAtomto update market prices in real time based on mid-price streams. [1] [2]updatePositionsMidPriceAtomto update portfolio positions with live mark prices, improving accuracy of displayed data. [1] [2] [3]UI enhancements:
PriceFlashcomponent to animate price changes, and corresponding CSS for up/down flashes. [1] [2] [3]Codebase and dependency improvements:
Formatting and utility changes:
formatTPOrSLSettingsto return structured objects instead of strings for easier UI rendering.These changes collectively enable robust real-time market and portfolio updates, improve UI responsiveness, and streamline the codebase for future enhancements.