Skip to content

Chore: polishing and fixes#20

Merged
Philippoes merged 16 commits intomainfrom
chore/polishing
Apr 2, 2026
Merged

Chore: polishing and fixes#20
Philippoes merged 16 commits intomainfrom
chore/polishing

Conversation

@petar-omni
Copy link
Copy Markdown
Collaborator

@petar-omni petar-omni commented Apr 2, 2026

Summary by CodeRabbit

  • New Features

    • Live mid-price streaming with market/position mid-price updates
    • Candle/chart data and detailed market endpoint
    • Price flash animations to highlight price moves
    • Sortable columns in the market selector
  • Improvements

    • Funding rate shown in market info; revised fees display
    • TP/SL shown as distinct values (better formatting)
    • Refined leverage dialog interactions and responsive layout tweaks
  • Chores

    • Dependency updates and adjusted market refresh cadence (1m)

@petar-omni petar-omni requested a review from Philippoes April 2, 2026 13:41
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
perps-dashboard Ready Ready Preview, Comment Apr 2, 2026 4:10pm
perps-widget Ready Ready Preview, Comment Apr 2, 2026 4:10pm

Request Review

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 2, 2026

@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 2, 2026

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn Medium
Low adoption: npm @tanstack/router-generator

Location: Package overview

From: pnpm-lock.yamlnpm/@tanstack/router-plugin@1.159.5npm/@tanstack/router-generator@1.159.4

ℹ Read more on: This package | This alert | What are unpopular packages?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Unpopular packages may have less maintenance and contain other problems.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@tanstack/router-generator@1.159.4. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

Introduces a Hyperliquid real-time data service, adds mid-price streaming atoms and UI price-flash, expands API schemas (markets, candles, actions, transactions), refactors atom patterns to use AtomRefs/Atom.make and field atom APIs, updates wallet/signer typings, and tweaks build/config and various UI components.

Changes

Cohort / File(s) Summary
Build & CI
package.json, pnpm-workspace.yaml, .github/workflows/ci.yml, packages/*/package.json, packages/*/vite.config.ts
Simplified dev script (removed turbo filters), migrated several deps to catalog:, removed testing-library dev deps, replaced static Vite config with factory createCommonViteConfig(), bumped workspace catalog entries, updated Playwright install command.
Hyperliquid Service & Runtime
packages/common/src/services/hyperliquid/index.ts, packages/common/src/services/index.ts, packages/common/src/services/runtime.ts
Added HyperliquidService (WS + HTTP snapshot), broadcasted mid-price stream, exported service types/schemas, registered service in runtime layer, and exported managedRuntime.
Atoms: mid-price, markets, portfolio, actions
packages/common/src/atoms/hyperliquid-atoms.ts, packages/common/src/atoms/markets-atoms.ts, packages/common/src/atoms/portfolio-atoms.ts, packages/common/src/atoms/actions-atoms.ts, packages/common/src/atoms/index.ts
Added midPriceAtom; increased markets refresh interval to 1m; added marketsBySymbolAtom, updateMarketsMidPriceAtom, updatePositionsMidPriceAtom; changed positionsAtom to Record of AtomRefs; simplified some writable atoms to Atom.make; re-exported hyperliquid atoms.
API client & schemas
packages/common/src/services/api-client/api-schemas.ts, packages/common/src/services/api-client/client-factory.ts
Expanded API surface: candles/endpoints, MarketDetailDto, new types (PerpActionTypes, ActionStatus, PerpTransactionType/Status, PositionSide, MarginMode, FundingMethod), added client methods (getCandles, getMarketById, getActions), updated related DTO fields.
Hooks & utilities
packages/common/src/hooks/*, packages/common/src/lib/formatting.ts, packages/common/src/hooks/use-optional-atom-ref.ts
Added useOptionalAtomRef, useHandleLeverageChange; refactored hooks/forms to use getFieldAtoms pattern; formatTPOrSLSettings now returns { tp, sl } and removed side-based sign logic.
Wallet & signer
packages/common/src/domain/signer.ts, packages/common/src/domain/wallet.ts, packages/common/src/services/wallet/browser-signer.ts
Added WalletAccountAddress branded schema; widened signTransaction error to include SwitchChainError; improved error wrapping and cached EIP712 check; exported WalletAccount as value.
UI components & styles
packages/common/src/components/..., packages/common/src/styles/base.css
Added PriceFlash component and CSS keyframes; minor dialog layout/padding changes; added nativeButton prop to leverage dialog; refactored limit-price setter usage.
Dashboard: market UI, selector, order form, positions
packages/dashboard/src/components/..., packages/dashboard/src/atoms/selected-market-atom.ts, packages/dashboard/src/components/modules/root/Preload.tsx
Wrapped price in PriceFlash, swapped fee displays (funding rate), added sortable market selector headers, updated open interest calc, replaced TP/SL rendering, mounted mid-price update atoms in preload, refactored selected-market init to generator Effect.
Widget: positions, order, position-details, layout
packages/widget/src/**, packages/widget/index.html, packages/widget/src/main.css
Switched positions to Record<AtomRef> flow and updated PositionCard/PositionDetails to accept positionRef; changed market/order side types to PositionSide; responsive width for widget container, mobile web-app meta tags, adjusted padding.
Misc / small changes
packages/common/src/vite.config.ts, packages/common/src/components/index.ts, various UI files
Replaced commonViteConfig export with factory, added price-flash barrel export, multiple small refactors (atom initializations, prop typings, styling tweaks).

Sequence Diagram

sequenceDiagram
    participant App as App / Preload
    participant Preload as PreloadAtoms
    participant MidAtom as midPriceAtom
    participant HL as HyperliquidService
    participant WS as WebSocketTransport
    participant UpdateMk as updateMarketsMidPriceAtom
    participant Markets as marketsAtom
    participant UI as Market UI

    App->>Preload: useAtomMount(midPriceAtom)
    Preload->>MidAtom: subscribe (runtimeAtom -> HyperliquidService)
    MidAtom->>HL: use HyperliquidService.subscribeMidPrice()
    HL->>WS: open WebSocket
    WS-->>HL: stream AllMidsWsEvent
    HL-->>MidAtom: emit stream (broadcastDynamic)
    App->>Preload: useAtomMount(updateMarketsMidPriceAtom)
    UpdateMk->>MidAtom: read mids
    MidAtom-->>UpdateMk: price events
    UpdateMk->>Markets: lookup market AtomRefs via marketsBySymbolAtom
    Markets-->>UpdateMk: return AtomRefs
    UpdateMk->>Markets: set markPrice on market AtomRefs
    Markets->>UI: notify subscribers
    UI->>UI: render PriceFlash animation
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🐰 Hooray, I hop and code with care,
Mid-prices streaming through the air,
Atoms rebounded, UI glowing bright,
Prices flash green, then red at night,
A tiny rabbit cheers—deploy it right!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Chore: polishing and fixes' uses vague terms ('polishing and fixes') that don't convey specific information about the extensive changes across atoms, API schemas, services, components, and styling throughout the codebase. Consider a more specific title that highlights the primary changes, such as 'Add HyperliquidService and refactor atom structure for mid-price updates' or 'Refactor atoms to Record-based positions and integrate Hyperliquid service'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/polishing

Comment @coderabbitai help to get the list of available commands and usage tips.

Philippoes
Philippoes previously approved these changes Apr 2, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 20

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/common/src/services/wallet/browser-signer.ts (1)

118-120: ⚠️ Potential issue | 🟠 Major

Do not convert chain-switch failures into defects in signTransaction.

Line 119 uses Effect.orDie, so SwitchChainError becomes uncatchable and bypasses the typed error channel/UI recovery path.

Suggested fix
-    if (chainId !== wagmiAdapter.wagmiConfig.state.chainId) {
-      yield* switchChain(chainId).pipe(Effect.orDie);
-    }
+    if (chainId !== wagmiAdapter.wagmiConfig.state.chainId) {
+      yield* switchChain(chainId);
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/services/wallet/browser-signer.ts` around lines 118 -
120, The current signTransaction flow converts chain-switch failures into
defects by using Effect.orDie on the switchChain call; update signTransaction so
switchChain(chainId) is not wrapped with orDie and instead propagates typed
SwitchChainError through the effect error channel (e.g., remove Effect.orDie and
use the effect's normal error propagation or map/catch to a typed error),
ensuring errors from switchChain (referenced in switchChain and
wagmiAdapter.wagmiConfig.state.chainId) are returnable/handleable by callers/UI
rather than becoming uncatchable defects.
packages/dashboard/src/components/modules/trade/order-form/index.tsx (1)

404-417: ⚠️ Potential issue | 🟡 Minor

Only the final detail row should pass isLast.

Fees, Taker Fee, and Maker Fee are all marked as last rows now, so this section renders stacked bottom borders between rows. Leave isLast on the actual final row only.

Suggested fix
         <OrderDetailRow
           label="Fees"
           value={formatAmount(calculations.fees)}
-          isLast
         />
         <OrderDetailRow
           label="Taker Fee"
           value={market.takerFee ? formatRate(market.takerFee) : "-"}
-          isLast
         />
         <OrderDetailRow
           label="Maker Fee"
           value={market.makerFee ? formatRate(market.makerFee) : "-"}
           isLast
         />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/dashboard/src/components/modules/trade/order-form/index.tsx` around
lines 404 - 417, The three OrderDetailRow instances for "Fees", "Taker Fee", and
"Maker Fee" all wrongly pass isLast; only the true final row should set isLast.
Update the OrderDetailRow calls in order-form/index.tsx so that only the "Maker
Fee" row keeps isLast, and remove the isLast prop from the "Fees" and "Taker
Fee" rows (locate the OrderDetailRow components that use label="Fees",
label="Taker Fee", and label="Maker Fee").
🧹 Nitpick comments (1)
packages/dashboard/src/components/molecules/positions/positions-tab.tsx (1)

151-153: Pre-group orders by marketId before mapping rows.

Line 153 filters the full orders array for every position, so render cost grows with positions × orders. Building a lookup once above the map keeps each row O(1).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/dashboard/src/components/molecules/positions/positions-tab.tsx`
around lines 151 - 153, The render is repeatedly filtering orders inside
positions.map (see positions.map with positionRef -> marketId and computing
marketOrders), causing O(positions × orders) cost; instead build a lookup (e.g.,
a Map keyed by order.marketId) once before the positions.map and then inside
positions.map replace the filter with a constant-time lookup (use marketId from
positionRef to fetch the orders array from that Map); update any references to
marketOrders accordingly so each row lookup is O(1).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/common/src/atoms/markets-atoms.ts`:
- Around line 124-140: The updateMarketsMidPriceAtom handler is currently
writing a new market object for every symbol on each midPriceAtom emission and
allows malformed prices; change the loop in updateMarketsMidPriceAtom (which
reads midPriceAtom and marketsBySymbolAtom and uses marketRef.update) to: 1)
parse the incoming price safely (e.g., const parsed = Number(price)) and skip if
parsed is not a finite number, 2) read the current market.markPrice from
marketRef.value and compare to parsed, and only call marketRef.update(...) when
parsed differs from the existing markPrice (no-op skip), and 3) preserve
existing market object shape when updating (only replace markPrice) so
unnecessary rerenders are avoided. Ensure these checks happen before calling
marketRef.update in the same loop that iterates Record.toEntries(mids).

In `@packages/common/src/atoms/portfolio-atoms.ts`:
- Around line 116-135: The updatePositionsMidPriceAtom handler mutates
PositionDto only by setting markPrice, leaving server-derived fields
(unrealizedPnl, liquidationPrice, etc.) stale; change the
positionRef.value.update callback used in updatePositionsMidPriceAtom to compute
and set all dependent fields atomically (e.g., call or implement a helper like
computeDerivedPositionFields(position, newMarkPrice) that returns updated
unrealizedPnl, liquidationPrice, marginUsed, etc.) and merge that full derived
object into the position update so the ref remains internally consistent after
mark price changes.

In `@packages/common/src/components/molecules/price-flash.tsx`:
- Line 11: The ref is currently typed as useRef<HTMLElement>(null) but is
attached to a <span>, so update the ref declaration in price-flash.tsx to use
useRef<HTMLSpanElement>(null) (the symbol to change is the ref constant created
via useRef) so the ref type matches the DOM element and satisfies stricter
React/TypeScript typings.

In `@packages/common/src/hooks/use-order-form.ts`:
- Around line 164-180: handleLeverageChange sets leverage via setLeverage which
stores a clamped value in leverageAtom, but the subsequent positionSize
calculation still uses the raw incoming value; change the handler to compute and
use the same clamped leverage when calling calculateOrderPositionSize (either by
deriving clampedLeverage with the same clamp/validation logic used by
leverageAtom or by reading the updated leverage from the atom synchronously) so
that calculateOrderPercentage/calculateOrderPositionSize use the stored/clamped
leverage; update references in handleLeverageChange to use clampedLeverage when
computing percentage and positionSize (functions: handleLeverageChange,
setLeverage, leverageAtom, calculateOrderPercentage,
calculateOrderPositionSize).
- Around line 88-95: The code snapshots an AtomRef by mapping ref => ref.value
in currentPosition which breaks subscriptions; instead keep the AtomRef itself
when extracting from the record (stop dereferencing ref.value in the
Option.map/Option.getOrNull flow). Concretely, change the Record.get(...)
pipeline so it returns the AtomRef (or null) rather than its .value, and defer
calling useAtomValue/useAtom or subscribing to that AtomRef at the consumer site
where a live position value is needed; update references to currentPosition
accordingly so they call useAtomValue(currentPosition) (or handle a nullable
AtomRef) rather than relying on a stale snapshot.

In `@packages/common/src/lib/formatting.ts`:
- Around line 142-158: The comment/docs for formatTPOrSLSettings are stale: the
function now returns an object { tp, sl } (strings like "TP 1.23%" or "TP Off")
rather than a combined long/short string; update the documentation/comments that
describe formatTPOrSLSettings/TPOrSLSettings to state the new return contract
(object with tp and sl properties), show example return values, and remove any
wording about a single combined string so consumers are not misled.

In `@packages/common/src/services/api-client/api-schemas.ts`:
- Around line 960-969: The matchStatus branches for MarketsControllerGetCandles
and MarketsControllerGetMarket currently map 400/404 to Effect.void, which lets
undefined flow on the success path; update the
withResponse(HttpClientResponse.matchStatus({...})) handlers in
MarketsControllerGetCandles and MarketsControllerGetMarket to treat 400 and 404
as error cases (e.g., use decodeError with the appropriate error schema names or
call unexpectedStatus) instead of returning Effect.void so the methods only
succeed with CandlesResponseDto / MarketDetailDto and surface errors correctly.
Ensure you remove the Effect.void mappings and replace them with
decodeError("MarketsControllerGetCandles400", ...) /
decodeError("MarketsControllerGetMarket404", ...) or unexpectedStatus as
appropriate.
- Around line 789-799: The schema for signedMetadata (used in ActionDto) no
longer matches the docblock: the comment documents a TLV hex string but the
schema was changed to Record<string, unknown>, causing decoding errors when the
backend sends the hex string. Fix by making signedMetadata's schema reflect the
documented wire format (e.g., change the schema for signedMetadata back to a
nullable/optional string using S.String/S.optionalWith(S.String, { nullable:
true }) or the project's nullable helper), or if the backend truly now sends a
parsed object, update the docblock to describe the Record shape and update any
consumers of ActionDto; ensure you update the symbol signedMetadata in
api-schemas.ts and any ActionDto usages/tests to match the chosen
representation.
- Around line 46-47: The type for supportedActions was changed to a single
PerpActionTypes literal but the API returns an array; update the schema so
supportedActions is an array of PerpActionTypes (e.g., PerpActionTypes[]) in
packages/common/src/services/api-client/api-schemas.ts and ensure the mirrored
type in packages/common/src/services/api-client/client-factory.ts matches the
same array type; verify any decoding/validation logic that consumes
supportedActions still treats it as an array of action strings.

In `@packages/common/src/services/hyperliquid/index.ts`:
- Around line 28-30: The current Effect.catchAll usage is wrong because the
handler returns a plain GetCandleSnapshotError instance instead of an Effect;
replace the catchAll with Effect.mapError to remap the failure into a new
GetCandleSnapshotError. Locate the Effect.tryPromise(() =>
infoClient.candleSnapshot(params)) expression and change the chained
Effect.catchAll((cause) => new GetCandleSnapshotError({ cause })) to
Effect.mapError((cause) => new GetCandleSnapshotError({ cause })), ensuring the
error is transformed correctly by the Effect pipeline.
- Around line 50-62: The current subscribeMidPrice stream uses
Stream.broadcastDynamic({ capacity: "unbounded" }) for the high-frequency
allMids websocket, which can cause unbounded memory growth; change it to use a
bounded buffer or a sliding/dropping policy instead — replace
Stream.broadcastDynamic({ capacity: "unbounded" }) with a bounded numeric
capacity (e.g., capacity: N) or switch to Stream.share({ connector:
PubSub.sliding({ capacity: N }) }) or PubSub.dropping({ capacity: N }) so
subscribeMidPrice/backpressure is bounded and old or new messages are evicted as
appropriate.

In `@packages/common/src/services/wallet/browser-signer.ts`:
- Around line 93-96: Record.get(chainsMap, chainId.toString()) returns an
Option, so convert it to an Effect before mapping errors: wrap the Record.get
call with Effect.fromOption (or use Effect.fromOptionWith) and then apply
Effect.mapError to transform None into new SwitchChainError({ cause: new
ChainNotFoundError() }); update the code around the chain variable assignment
(where Record.get, chainsMap, chainId are used) to use Effect.fromOption +
Effect.mapError instead of calling Effect.mapError directly on Record.get's
result.

In `@packages/common/src/vite.config.ts`:
- Around line 29-30: createCommonViteConfig currently reuses module-scoped
plugin instances via commonPlugins, which causes shared state across configs;
change it to instantiate fresh plugins inside createCommonViteConfig by
replacing plugins: Object.values(commonPlugins) with a new array of plugin
factory calls (e.g., tanstackRouter({ target: "react", autoCodeSplitting: true
}), viteReact({ babel: { plugins: ["babel-plugin-react-compiler"] }}),
tailwindcss(), nodePolyfills({ include: ["buffer"] }), etc.), ensuring each call
returns a new plugin instance for createCommonViteConfig so widget and dashboard
get isolated plugin objects.

In `@packages/dashboard/src/atoms/selected-market-atom.ts`:
- Line 8: The init currently uses ctx.result(marketsAtom) which creates a
reactive dependency and causes the initializer to re-run whenever marketsAtom
updates, forcing the selected market back to the default (e.g., BTC/head);
change the initializer to use ctx.resultOnce(marketsAtom) (or guard the logic so
it only sets a value if selectedMarketAtom is unset) so the markets list is read
once for one-shot initialization and user selections are not overwritten on
subsequent marketsAtom updates.

In `@packages/dashboard/src/components/modules/trade/chart-v2.tsx`:
- Around line 33-99: The createStubDatafeed currently returns no usable data:
resolveSymbol hardcodes symbol metadata, getBars always calls onResult([],
{noData:true}), and subscribeBars/unsubscribeBars are no-ops, causing the chart
to show an empty state; update createStubDatafeed so resolveSymbol derives
metadata from the passed symbolName (or looks up a market config), implement
getBars to fetch historical candle data (or generate realistic stub candles) and
call onResult with a non-empty bars array and meta.noData=false, and implement
subscribeBars/unsubscribeBars to provide live updates (or simulate them) by
calling the provided realtime callback—target the resolveSymbol, getBars,
subscribeBars and unsubscribeBars handlers in createStubDatafeed to locate and
change the behavior.
- Around line 109-115: The component currently assumes TradingView assets are
present and returns null from createChartWidget when window.TradingView is
missing, which leaves users with a blank chart and clears loading state; update
the component to explicitly load the charting_library script (referencing
LIBRARY_PATH) before calling createChartWidget, add robust error handling when
window.TradingView or TV.widget is unavailable (surface a user-facing error
state and keep/retry loading instead of setting isLoading(false) silently), and
add a simple retry/backoff mechanism so createChartWidget/TradingViewWidget
initialization is retried on transient failures; also fix the comment near
isLoading to reflect the intended behavior (keep loading state when assets are
missing).

In
`@packages/dashboard/src/components/modules/trade/market-info/market-selector-popover.tsx`:
- Around line 172-187: The sort toggle button currently only changes icon/color,
so add ARIA attributes to expose state: update the button in
market-selector-popover.tsx (the button that calls onToggle(column) and uses
isActive/direction) to include an aria-pressed={isActive} and a descriptive
aria-label that combines the visible label and the sort state (e.g., "Name,
sorted ascending"/"Name, sorted descending"/"Name, not sorted") so screen
readers announce the current sort; ensure the aria-label uses the same label
variable and the direction variable to produce the correct phrase.

In `@packages/dashboard/src/components/modules/trade/order-form/index.tsx`:
- Around line 409-417: The Taker/Maker fee checks treat 0 as missing; change the
truthy checks to nullish checks so zero fees render correctly: where
OrderDetailRow uses market.takerFee and market.makerFee, replace the current
truthy condition with a null/undefined check (e.g., use != null or !== null &&
!== undefined) and call formatRate(...) when the fee is not null/undefined,
otherwise render "-". Ensure you update both uses (market.takerFee and
market.makerFee) near the OrderDetailRow components and keep formatRate for
actual values.

In `@packages/widget/index.html`:
- Around line 8-9: The document only sets mobile-web-app-capable (Android) but
not apple-mobile-web-app-capable, so the existing
apple-mobile-web-app-status-bar-style won't take effect on iOS; add a meta tag
with name="apple-mobile-web-app-capable" and content="yes" alongside the
existing meta tags (ensure the new tag appears before or near
apple-mobile-web-app-status-bar-style) so iOS Safari can enter standalone mode
and apply the status bar style.

In `@pnpm-workspace.yaml`:
- Around line 25-29: Update the `@tanstack/router-cli` entry in
pnpm-workspace.yaml from 1.159.4 to 1.159.5 so the CLI matches
`@tanstack/react-router` and `@tanstack/router-plugin`; locate the
'@tanstack/router-cli' line and change its version string to ^1.159.5 and then
run your lockfile install (pnpm install) to regenerate the lockfile.

---

Outside diff comments:
In `@packages/common/src/services/wallet/browser-signer.ts`:
- Around line 118-120: The current signTransaction flow converts chain-switch
failures into defects by using Effect.orDie on the switchChain call; update
signTransaction so switchChain(chainId) is not wrapped with orDie and instead
propagates typed SwitchChainError through the effect error channel (e.g., remove
Effect.orDie and use the effect's normal error propagation or map/catch to a
typed error), ensuring errors from switchChain (referenced in switchChain and
wagmiAdapter.wagmiConfig.state.chainId) are returnable/handleable by callers/UI
rather than becoming uncatchable defects.

In `@packages/dashboard/src/components/modules/trade/order-form/index.tsx`:
- Around line 404-417: The three OrderDetailRow instances for "Fees", "Taker
Fee", and "Maker Fee" all wrongly pass isLast; only the true final row should
set isLast. Update the OrderDetailRow calls in order-form/index.tsx so that only
the "Maker Fee" row keeps isLast, and remove the isLast prop from the "Fees" and
"Taker Fee" rows (locate the OrderDetailRow components that use label="Fees",
label="Taker Fee", and label="Maker Fee").

---

Nitpick comments:
In `@packages/dashboard/src/components/molecules/positions/positions-tab.tsx`:
- Around line 151-153: The render is repeatedly filtering orders inside
positions.map (see positions.map with positionRef -> marketId and computing
marketOrders), causing O(positions × orders) cost; instead build a lookup (e.g.,
a Map keyed by order.marketId) once before the positions.map and then inside
positions.map replace the filter with a constant-time lookup (use marketId from
positionRef to fetch the orders array from that Map); update any references to
marketOrders accordingly so each row lookup is O(1).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 334ef86d-0bea-4ee1-8b37-9bddc8fe1d66

📥 Commits

Reviewing files that changed from the base of the PR and between eba747c and 636d935.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (56)
  • package.json
  • packages/common/package.json
  • packages/common/src/atoms/actions-atoms.ts
  • packages/common/src/atoms/hyperliquid-atoms.ts
  • packages/common/src/atoms/index.ts
  • packages/common/src/atoms/markets-atoms.ts
  • packages/common/src/atoms/order-form-atoms.ts
  • packages/common/src/atoms/portfolio-atoms.ts
  • packages/common/src/components/index.ts
  • packages/common/src/components/molecules/leverage-dialog.tsx
  • packages/common/src/components/molecules/limit-price-dialog.tsx
  • packages/common/src/components/molecules/order-type-dialog.tsx
  • packages/common/src/components/molecules/price-flash.tsx
  • packages/common/src/components/ui/dialog.tsx
  • packages/common/src/domain/signer.ts
  • packages/common/src/domain/wallet.ts
  • packages/common/src/hooks/use-deposit-form.ts
  • packages/common/src/hooks/use-order-form.ts
  • packages/common/src/hooks/use-withdraw-form.ts
  • packages/common/src/lib/formatting.ts
  • packages/common/src/services/api-client/api-schemas.ts
  • packages/common/src/services/api-client/client-factory.ts
  • packages/common/src/services/hyperliquid/index.ts
  • packages/common/src/services/index.ts
  • packages/common/src/services/runtime.ts
  • packages/common/src/services/wallet/browser-signer.ts
  • packages/common/src/styles/base.css
  • packages/common/src/vite.config.ts
  • packages/common/vite.config.ts
  • packages/dashboard/package.json
  • packages/dashboard/src/atoms/selected-market-atom.ts
  • packages/dashboard/src/components/modules/root/Preload.tsx
  • packages/dashboard/src/components/modules/trade/chart-v2.tsx
  • packages/dashboard/src/components/modules/trade/market-info/index.tsx
  • packages/dashboard/src/components/modules/trade/market-info/market-selector-popover.tsx
  • packages/dashboard/src/components/modules/trade/order-form/index.tsx
  • packages/dashboard/src/components/molecules/header/deposit/state.tsx
  • packages/dashboard/src/components/molecules/header/withdraw/state.tsx
  • packages/dashboard/src/components/molecules/positions/index.tsx
  • packages/dashboard/src/components/molecules/positions/positions-tab.tsx
  • packages/dashboard/vite.config.ts
  • packages/widget/index.html
  • packages/widget/package.json
  • packages/widget/src/app.tsx
  • packages/widget/src/components/modules/Home/Positions/index.tsx
  • packages/widget/src/components/modules/Home/Positions/position-card.tsx
  • packages/widget/src/components/modules/Home/index.tsx
  • packages/widget/src/components/modules/Order/Overview/index.tsx
  • packages/widget/src/components/modules/PositionDetails/Close/state.tsx
  • packages/widget/src/components/modules/PositionDetails/Overview/Position/index.tsx
  • packages/widget/src/components/modules/PositionDetails/Overview/index.tsx
  • packages/widget/src/components/modules/PositionDetails/Overview/modify-dialog.tsx
  • packages/widget/src/components/modules/Root/PreloadAtoms.tsx
  • packages/widget/src/main.css
  • packages/widget/vite.config.ts
  • pnpm-workspace.yaml

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/ci.yml:
- Line 25: Replace the transient CLI invocation in the CI step that runs
Playwright; the line using "pnpm dlx playwright install --with-deps" should be
changed to use the project-pinned binary via "pnpm exec" so the installed
Playwright version from the lockfile (e.g., 1.58.0) is used and browser binaries
stay deterministic; update the run step to call the project-local Playwright CLI
with the same args (install --with-deps) using pnpm exec instead of pnpm dlx.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 47aa355f-3511-4b78-aa9e-55675ed61a1f

📥 Commits

Reviewing files that changed from the base of the PR and between 636d935 and 9d6deaa.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (3)
packages/common/src/services/hyperliquid/index.ts (1)

50-62: ⚠️ Potential issue | 🟠 Major

Use bounded capacity or sliding strategy for high-frequency mid-price stream.

allMids is a high-frequency WebSocket feed. With Stream.broadcastDynamic({ capacity: "unbounded" }), slow subscribers can accumulate an ever-growing backlog, causing memory growth and potential OOM.

Consider using a bounded capacity or a sliding/dropping strategy:

     ).pipe(Stream.broadcastDynamic({ capacity: "unbounded" }));
+    // Bounded alternative:
+    // ).pipe(Stream.broadcastDynamic({ capacity: 100 }));

Or for sliding behavior (evict oldest when full), use PubSub.sliding:

import { PubSub } from "effect";

// Replace broadcastDynamic with:
.pipe(Stream.share({ connector: () => PubSub.sliding<AllMidsWsEvent>({ capacity: 100 }) }))

Since mid-price data is time-sensitive, newer values are more useful than stale backlog—sliding semantics fit well here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/services/hyperliquid/index.ts` around lines 50 - 62, The
current subscribeMidPrice stream uses Stream.broadcastDynamic({ capacity:
"unbounded" }) which can cause unbounded backlog for the high-frequency allMids
feed; replace the broadcastDynamic connector with a bounded or sliding connector
(e.g., use Stream.share with a connector created via PubSub.sliding or a bounded
PubSub) so slow subscribers drop/evict old mid-price events instead of growing
memory; update the pipe on subscribeMidPrice to use Stream.share({ connector: ()
=> PubSub.sliding<AllMidsWsEvent>({ capacity: 100 }) }) or an equivalent bounded
strategy and ensure PubSub is imported.
packages/common/src/atoms/portfolio-atoms.ts (1)

117-139: ⚠️ Potential issue | 🟠 Major

Don't leave PositionDto internally inconsistent.

This still patches only markPrice, so unrealizedPnl, liquidationPrice, and the other server-derived fields become stale inside the same ref. The TODO documents it, but consumers can still render mixed-time data from one object. Either recompute the dependent fields atomically here or keep the live mark price separate from the server snapshot.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/atoms/portfolio-atoms.ts` around lines 117 - 139,
updatePositionsMidPriceAtom currently only updates markPrice on the PositionDto
inside positionRef, leaving unrealizedPnl, liquidationPrice and other derived
fields stale; either compute and set those dependent fields atomically when
updating the ref or separate live mark prices from the server snapshot. Fix by,
inside updatePositionsMidPriceAtom where positionRef.value.update is called,
derive the new unrealizedPnl and liquidationPrice using the existing position
and market data (use the market from marketsBySymbolAtom and the current
position from positionsAtom) and update the position object with markPrice plus
the recomputed derived fields in a single update, or instead introduce a new
liveMarkPrice atom keyed by walletAddress+marketId and stop mutating PositionDto
here so PositionDto remains consistent.
packages/common/src/hooks/use-order-form.ts (1)

168-182: ⚠️ Potential issue | 🟡 Minor

Use the clamped leverage for the amount recompute.

setLeverage(value) normalizes the input through leverageAtom, but calculateOrderPositionSize still uses raw value. Any out-of-range input leaves the amount field inconsistent with the leverage that was actually stored.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/hooks/use-order-form.ts` around lines 168 - 182, The
recompute after setLeverage uses the raw input `value` but the app stores a
normalized/clamped leverage via `setLeverage`/`leverageAtom`, causing
inconsistencies; update handleLeverageChange to use the clamped/normalized
leverage when recalculating amount and position size (either read the normalized
leverage from the atom/state after calling setLeverage or explicitly clamp
`value` the same way the atom does) and then pass that clamped value into
`calculateOrderPercentage` and `calculateOrderPositionSize` instead of the raw
`value`.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/common/src/atoms/portfolio-atoms.ts`:
- Around line 129-139: When processing Record.toEntries(mids) in this block,
coerce price into a numeric value once (e.g. const newMark = Number(price)) and
skip the update if Number produced NaN/Infinity or if newMark ===
position.markPrice; locate the lookup/update flow using Record.toEntries,
Record.get(markets), Record.get(positions), positionRef and its update method,
and change the update call to only run when the parsed numeric mark is valid
(isFinite) and different from the current position.markPrice to avoid
unnecessary writes and rerenders.

In `@packages/common/src/hooks/use-optional-atom-ref.ts`:
- Around line 7-19: Replace the useState/useEffect subscription with
React.useSyncExternalStore to avoid the race and remove unused state: call
useSyncExternalStore with a subscribe function that, when ref is truthy, returns
ref.subscribe (so the hook gets the unsubscribe) and otherwise returns a no-op,
and with a getSnapshot function that returns ref?.value ?? null; ensure the hook
returns that snapshot directly instead of ref?.value. Reference symbols:
useSyncExternalStore, ref.subscribe, ref?.value.

---

Duplicate comments:
In `@packages/common/src/atoms/portfolio-atoms.ts`:
- Around line 117-139: updatePositionsMidPriceAtom currently only updates
markPrice on the PositionDto inside positionRef, leaving unrealizedPnl,
liquidationPrice and other derived fields stale; either compute and set those
dependent fields atomically when updating the ref or separate live mark prices
from the server snapshot. Fix by, inside updatePositionsMidPriceAtom where
positionRef.value.update is called, derive the new unrealizedPnl and
liquidationPrice using the existing position and market data (use the market
from marketsBySymbolAtom and the current position from positionsAtom) and update
the position object with markPrice plus the recomputed derived fields in a
single update, or instead introduce a new liveMarkPrice atom keyed by
walletAddress+marketId and stop mutating PositionDto here so PositionDto remains
consistent.

In `@packages/common/src/hooks/use-order-form.ts`:
- Around line 168-182: The recompute after setLeverage uses the raw input
`value` but the app stores a normalized/clamped leverage via
`setLeverage`/`leverageAtom`, causing inconsistencies; update
handleLeverageChange to use the clamped/normalized leverage when recalculating
amount and position size (either read the normalized leverage from the
atom/state after calling setLeverage or explicitly clamp `value` the same way
the atom does) and then pass that clamped value into `calculateOrderPercentage`
and `calculateOrderPositionSize` instead of the raw `value`.

In `@packages/common/src/services/hyperliquid/index.ts`:
- Around line 50-62: The current subscribeMidPrice stream uses
Stream.broadcastDynamic({ capacity: "unbounded" }) which can cause unbounded
backlog for the high-frequency allMids feed; replace the broadcastDynamic
connector with a bounded or sliding connector (e.g., use Stream.share with a
connector created via PubSub.sliding or a bounded PubSub) so slow subscribers
drop/evict old mid-price events instead of growing memory; update the pipe on
subscribeMidPrice to use Stream.share({ connector: () =>
PubSub.sliding<AllMidsWsEvent>({ capacity: 100 }) }) or an equivalent bounded
strategy and ensure PubSub is imported.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 835e62b1-d3b3-42a6-984d-536132074c1b

📥 Commits

Reviewing files that changed from the base of the PR and between 9d6deaa and 357f6ad.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (13)
  • .github/workflows/ci.yml
  • packages/common/src/atoms/markets-atoms.ts
  • packages/common/src/atoms/portfolio-atoms.ts
  • packages/common/src/components/molecules/price-flash.tsx
  • packages/common/src/domain/signer.ts
  • packages/common/src/domain/wallet.ts
  • packages/common/src/hooks/use-optional-atom-ref.ts
  • packages/common/src/hooks/use-order-form.ts
  • packages/common/src/lib/formatting.ts
  • packages/common/src/services/hyperliquid/index.ts
  • packages/common/src/vite.config.ts
  • packages/widget/index.html
  • pnpm-workspace.yaml
✅ Files skipped from review due to trivial changes (3)
  • .github/workflows/ci.yml
  • packages/widget/index.html
  • packages/common/src/components/molecules/price-flash.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/common/src/vite.config.ts
  • packages/common/src/domain/signer.ts
  • packages/common/src/lib/formatting.ts
  • pnpm-workspace.yaml
  • packages/common/src/domain/wallet.ts

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
packages/common/src/services/api-client/api-schemas.ts (3)

1058-1065: ⚠️ Potential issue | 🟠 Major

Don't return void on DTO-returning 400/404 responses.

These methods are typed to succeed with CandlesResponseDto / MarketDetailDto only, but Lines 1064 and 1073 turn 400/404 into a successful undefined. Drop those branches so unexpectedStatus fails instead, or add explicit error DTOs if the API documents them.

Suggested fix
   "MarketsControllerGetCandles": (marketId, options) => HttpClientRequest.get(`/v1/markets/${marketId}/candles`).pipe(
     HttpClientRequest.setUrlParams({ "interval": options?.["interval"] as any, "from": options?.["from"] as any, "to": options?.["to"] as any }),
     withResponse(HttpClientResponse.matchStatus({
       "2xx": decodeSuccess(CandlesResponseDto),
       "401": decodeError("MarketsControllerGetCandles401", MarketsControllerGetCandles401),
       "429": decodeError("MarketsControllerGetCandles429", MarketsControllerGetCandles429),
-      "400": () => Effect.void,
       orElse: unexpectedStatus
     }))
   ),
   "MarketsControllerGetMarketById": (marketId) => HttpClientRequest.get(`/v1/markets/${marketId}`).pipe(
     withResponse(HttpClientResponse.matchStatus({
       "2xx": decodeSuccess(MarketDetailDto),
       "401": decodeError("MarketsControllerGetMarketById401", MarketsControllerGetMarketById401),
       "429": decodeError("MarketsControllerGetMarketById429", MarketsControllerGetMarketById429),
-      "404": () => Effect.void,
       orElse: unexpectedStatus
     }))
   ),

Also applies to: 1068-1074

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/services/api-client/api-schemas.ts` around lines 1058 -
1065, The generated client currently treats 400/404 as successful no-op by
returning Effect.void in the MarketsControllerGetCandles (and the similar Market
detail call) response mapping; remove the 400/404 branches that return void so
those statuses fall through to unexpectedStatus, or replace them with proper
decodeError calls using the correct error DTOs if the API documents error
bodies; locate the withResponse(HttpClientResponse.matchStatus(...)) block for
MarketsControllerGetCandles and the corresponding MarketDetail mapping and
delete the "() => Effect.void" entries for 400/404 (or swap them for
decodeError("MarketsControllerGetCandles400", SomeErrorDto) /
decodeError("MarketsControllerGetCandles404", SomeErrorDto)) so the method no
longer silently returns undefined for DTO-returning endpoints.

47-47: ⚠️ Potential issue | 🟠 Major

Keep supportedActions as an array.

The field name and surrounding docs describe multiple actions, but this now accepts a single PerpActionTypes. If the API still returns ["open", "close", ...], ProviderDto decoding breaks. Please mirror the same array type in packages/common/src/services/api-client/client-factory.ts.

Suggested fix
-  "supportedActions": PerpActionTypes,
+  "supportedActions": S.Array(PerpActionTypes),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/services/api-client/api-schemas.ts` at line 47, The
ProviderDto schema's supportedActions property was changed from an array to a
single PerpActionTypes, causing decoding to fail when the API returns an array;
update the type back to an array (e.g., PerpActionTypes[]) in
packages/common/src/services/api-client/api-schemas.ts and make the
corresponding change in
packages/common/src/services/api-client/client-factory.ts so both schema and
client factory expect an array for supportedActions and decoding succeeds
consistently.

838-844: ⚠️ Potential issue | 🟠 Major

signedMetadata no longer matches the documented wire format.

The docblock describes a TLV hex string, but this schema expects an object. If the backend still sends the documented string, ActionDto decoding fails when metadata is populated. Please keep the mirror in packages/common/src/services/api-client/client-factory.ts aligned with whichever representation is actually on the wire.

Suggested fix if the wire format is still the documented TLV string
-  "signedMetadata": S.optionalWith(S.Record({ key: S.String, value: S.Unknown }), { nullable: true }),
+  "signedMetadata": S.optionalWith(S.String, { nullable: true }),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/services/api-client/api-schemas.ts` around lines 838 -
844, The schema for signedMetadata no longer matches the docblock TLV hex-string
wire format and causes ActionDto decoding to fail; update the mirror so both
sides agree: if the backend sends the TLV hex string, change the schema symbol
"signedMetadata" in packages/common/src/services/api-client/api-schemas.ts to
accept a string (e.g., S.optionalWith(S.String, { nullable: true })), and ensure
the corresponding handling/mapping in
packages/common/src/services/api-client/client-factory.ts still parses that hex
TLV into the desired runtime object (or vice‑versa—if the backend sends an
object, change the client-factory to emit the object); keep ActionDto decoding
and "signedMetadata" types consistent across both files.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/common/src/services/api-client/api-schemas.ts`:
- Around line 816-819: The schema entry for "explorerUrl" in TransactionDto is
typed as an object but documented as a URL string; update the schema to accept a
nullable string (replace the current S.Record(...) usage with a string schema
allowing null/undefined) and then mirror that change in the client factory
decoding/encoding logic in client-factory (ensure places that read/write
explorerUrl expect a string | null). Also update the docblock only if you
instead decide the API truly returns an object; keep schema and client-factory
in sync with the chosen wire format.

---

Duplicate comments:
In `@packages/common/src/services/api-client/api-schemas.ts`:
- Around line 1058-1065: The generated client currently treats 400/404 as
successful no-op by returning Effect.void in the MarketsControllerGetCandles
(and the similar Market detail call) response mapping; remove the 400/404
branches that return void so those statuses fall through to unexpectedStatus, or
replace them with proper decodeError calls using the correct error DTOs if the
API documents error bodies; locate the
withResponse(HttpClientResponse.matchStatus(...)) block for
MarketsControllerGetCandles and the corresponding MarketDetail mapping and
delete the "() => Effect.void" entries for 400/404 (or swap them for
decodeError("MarketsControllerGetCandles400", SomeErrorDto) /
decodeError("MarketsControllerGetCandles404", SomeErrorDto)) so the method no
longer silently returns undefined for DTO-returning endpoints.
- Line 47: The ProviderDto schema's supportedActions property was changed from
an array to a single PerpActionTypes, causing decoding to fail when the API
returns an array; update the type back to an array (e.g., PerpActionTypes[]) in
packages/common/src/services/api-client/api-schemas.ts and make the
corresponding change in
packages/common/src/services/api-client/client-factory.ts so both schema and
client factory expect an array for supportedActions and decoding succeeds
consistently.
- Around line 838-844: The schema for signedMetadata no longer matches the
docblock TLV hex-string wire format and causes ActionDto decoding to fail;
update the mirror so both sides agree: if the backend sends the TLV hex string,
change the schema symbol "signedMetadata" in
packages/common/src/services/api-client/api-schemas.ts to accept a string (e.g.,
S.optionalWith(S.String, { nullable: true })), and ensure the corresponding
handling/mapping in packages/common/src/services/api-client/client-factory.ts
still parses that hex TLV into the desired runtime object (or vice‑versa—if the
backend sends an object, change the client-factory to emit the object); keep
ActionDto decoding and "signedMetadata" types consistent across both files.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6179a21e-9130-48b0-b74b-d170fae1844c

📥 Commits

Reviewing files that changed from the base of the PR and between 357f6ad and b2526ba.

📒 Files selected for processing (6)
  • packages/common/src/atoms/actions-atoms.ts
  • packages/common/src/domain/wallet.ts
  • packages/common/src/hooks/use-optional-atom-ref.ts
  • packages/common/src/services/api-client/api-schemas.ts
  • packages/common/src/services/api-client/client-factory.ts
  • packages/common/src/services/wallet/wallet-service.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/common/src/services/wallet/wallet-service.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/common/src/hooks/use-optional-atom-ref.ts
  • packages/common/src/domain/wallet.ts
  • packages/common/src/atoms/actions-atoms.ts

@petar-omni petar-omni requested review from 0xYoki and Philippoes April 2, 2026 16:49
@Philippoes Philippoes merged commit 3d9e5de into main Apr 2, 2026
10 checks passed
@Philippoes Philippoes deleted the chore/polishing branch April 2, 2026 18:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants