chore(release): promote develop to stable v1.2.0#162
Open
jeziellopes wants to merge 141 commits intomainfrom
Open
chore(release): promote develop to stable v1.2.0#162jeziellopes wants to merge 141 commits intomainfrom
jeziellopes wants to merge 141 commits intomainfrom
Conversation
GitHub merge commits (Merge pull request #N) have 2 parents and cannot be signed off by authors. Filter them out before checking for Signed-off-by so release PRs (develop → main) don't fail DCO. Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
Updated README to include badges for tests, code quality, and DCO with improved formatting.
- Domain ports: MarketDataSource, ConnectionStatus, OrderBook types - Domain book sync: pure bookFromSnapshot + applyDepthUpdate functions - Infrastructure: BinanceDataSource adapter with WS lifecycle, depth buffer, snapshot sequencing - Infrastructure: exponential backoff reconnect manager - Application: Zustand market-data store with RAF batching and selector hooks - Config singleton factory for dependency injection - 31 new tests, 100% coverage on domain/infra, 97.6% on stores Closes #99 Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
feat(infra): WebSocket data layer — Binance live market data
# [1.1.0-next.2](v1.1.0-next.1...v1.1.0-next.2) (2026-04-04) ### Features * **infra:** WebSocket data layer — Binance live market data ([35791df](35791df)), closes [#99](#99) Signed-off-by: semantic-release-bot <semantic-release-bot@martynus.net>
…admap Closes: companion to #100 merge Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
…ption Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
- Reorganize imports in book-sync.ts, BinanceDataSource.ts, snapshot.ts, ws-client.ts, reconnect.test.ts, config.ts, market-data.ts, market-data.test.ts - Refactor theme-dropdown.tsx migration block to store getItem result in local var instead of using non-null assertion Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
docs(readme): mark WebSocket data layer shipped, sync roadmap
# [1.1.0-next.3](v1.1.0-next.2...v1.1.0-next.3) (2026-04-04) ### Bug Fixes * **lint:** resolve Biome import-order and noNonNullAssertion violations ([03d7c04](03d7c04)) Signed-off-by: semantic-release-bot <semantic-release-bot@martynus.net>
- Add loader to /symbol/$symbol that validates ticker (uppercase normalize), throws notFound() for unknown symbols, and triggers market data init - Add validateSearch with Zod schema: tab (book|trades|depth), levels (number) with catch-based defaults (tab='book', levels=20) - Add notFoundComponent with 404 page and link back to BTCUSDT - Add beforeLoad redirect on / → /symbol/BTCUSDT (AC-8) - Wire useConnectionStatus() to LiveIndicator in __root.tsx (replaces hardcoded) - Add normalizeSymbol(), isValidSymbol() helpers to lib/symbols.ts - Add pricePrecision, qtyPrecision fields to SymbolInfo and all 18 entries - Create stores/ui.ts — Zustand slice for active tab + levels, synced from URL - Pass tab/levels as props through TerminalLayout (wired, ready for #96) Closes #98 Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
Replace 'as never' with 'as any' (matching index.tsx pattern) so TypeScript doesn't infer the entire route config as never. Add explicit type annotations on loader params and cast useLoaderData/useSearch return types to their concrete types. Fixes: Property does not exist on type 'never' errors in Vercel build. Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
…er types The redirect() call inside the loader needs both 'to' and 'params' cast as never — matching the established pattern in index.tsx. Casting only 'to' as any left params unresolved against the router's generated types, causing build failure: 'symbol does not exist in type ParamsReducerFn'. Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
TanStack Router skips beforeLoad on cached route matches, so the / -> BTCUSDT redirect was silently ignored when clicking the logo from a symbol page. Fix: link directly to /symbol/BTCUSDT instead of routing through /. The beforeLoad redirect on / remains as a fallback for direct URL access. Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
…sible The root route should show the portfolio landing page, not redirect. Removing beforeLoad redirect and restoring logo link to /. Also reverts optional search params schema (no longer needed without the redirect). Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
feat(routing): symbol route loaders with validation and error states
# [1.1.0-next.4](v1.1.0-next.3...v1.1.0-next.4) (2026-04-05) ### Bug Fixes * **routing:** cast redirect params as never to satisfy TS strict router types ([5f82204](5f82204)) * **routing:** link logo directly to /symbol/BTCUSDT ([cf730eb](cf730eb)) * **routing:** remove auto-redirect from / — landing page should be visible ([99bedf4](99bedf4)) * **routing:** remove stale biome-ignore comment on never cast ([58c9f56](58c9f56)) * **routing:** resolve TS errors from 'as never' route cast ([c1b7628](c1b7628)) ### Features * **routing:** symbol route loaders with validation and error states ([014ca0e](014ca0e)), closes [#96](#96) [#98](#98) Signed-off-by: semantic-release-bot <semantic-release-bot@martynus.net>
- Export OrderBookState from order-book.tsx for shared typing - Add useOrderBookViewState(levels) in features/order-book — transforms raw Map-based OrderBook into PriceLevel[] view model with cumulative totals and percent-width bars; three separate Zustand subscriptions avoid infinite re-renders from object-returning selectors - Add TradesFeed component consuming NormalizedTrade[] — shows time, price, qty, side with trading-bid/trading-ask colour coding; isBuyerMaker=true → sell (aggressor was seller) - Replace MOCK_ORDER_BOOK_STATE in trading layout with live useOrderBookViewState; show animated skeleton while orderBook is null - Replace MOCK_TERMINAL_TRADES in DataPanel with live useTrades() - 18 new tests (use-order-book-data.test.ts + trades-feed.test.tsx) Closes #96 Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
- Extract LiveIndicatorConnected from RootComponent so __root.tsx no longer subscribes to any Zustand store; header re-renders stop - Add OrderBookPanel + TradesFeedPanel leaf components in -trading-layout; TerminalLayout has zero high-freq selectors - Refactor DataPanel to accept TradesFeedSlot: ReactNode render prop so subscription ownership stays in the leaf, not the panel shell Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
…ertyTypes Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
feat(order-book): wire Order Book UI to live WebSocket data
# [1.1.0-next.5](v1.1.0-next.4...v1.1.0-next.5) (2026-04-05) ### Bug Fixes * **lint:** replace noNonNullAssertion violations in order-book test ([9cd395c](9cd395c)) * **live-indicator:** add undefined to className for exactOptionalPropertyTypes ([34d4f54](34d4f54)) ### Features * **order-book:** wire Order Book UI to live WebSocket data ([0549859](0549859)), closes [#96](#96) ### Performance Improvements * **root:** scope store subscriptions to leaf components — fix [#104](#104) [#105](#105) ([1404b72](1404b72)), closes [hi#freq](https://github.com/hi/issues/freq) Signed-off-by: semantic-release-bot <semantic-release-bot@martynus.net>
…fills - Add MarketTradesPanel leaf component (owns useTrades() subscription) - Split Order Book panel: 2/3 order book + 1/3 Market Trades feed - Add MarketTradesFeed component for NormalizedTrade[] display - Rename DataPanel Trades tab -> My Trades (shows user simulated fills) Closes #106 Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
…r fills - Add 'trades' grid panel (key=trades) for live exchange market trades - MarketTradesFeed + MarketTradesPanel leaf (owns useTrades() subscription) - DEFAULT_LAYOUTS v12: trades panel sits below order book in bottom row - redistributeLayout handles new 'trades' column in bottom row alignment - DataPanel Trades tab renamed to My Trades (user simulated fills) Closes #106 Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
feat(order-book): column headers + ARIA table semantics
- Add NormalizedCandle interface to domain layer - Add fetchKlines() to MarketDataSource port + BinanceDataSource impl - Add klines state, loadKlines action, useKlines selector to market-data store - Rewrite CandleChart to fetch real klines from Binance REST API - Imperative store subscription avoids React re-renders on data updates - Race-condition handled by seeding from store state at mount time - Rewrite PortfolioSummaryWidget to subscribe to portfolio store - Removed mock props; only botPnl passed from parent - Computes totalBalance/totalPnL/totalPnLPct from USDT balance - Remove MOCK_CANDLES_BY_INTERVAL and MOCK_PORTFOLIO_SUMMARY from mock-data.ts - Update market-data.test.ts: add fetchKlines mock + klines reset Closes #151 Closes #152 Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
…rtfolio feat(chart-portfolio): wire real Binance klines and portfolio store
- Add NormalizedKlineUpdate to domain (extends NormalizedCandle + isClosed) - Add onKlineUpdate() and subscribeKlineStream() to MarketDataSource port - Add KlineEventSchema to Binance schemas (discriminated union) - BinanceDataSource: subscribe @kline_<interval> stream after loadKlines; reconnects combined WS to include kline sub-stream without disrupting depth/trade/ticker streams (wsClient.connect closes old WS silently) - market-data store: register onKlineUpdate in initMarketData; live ticks update last candle (klineIsLiveTick=true); closed candles append to ring buffer (max 500, klineIsLiveTick=false); loadKlines calls subscribeKlineStream after REST fetch - CandleChart: uses series.update() for live ticks (no scroll jump) and series.setData() + fitContent() for full loads only - OrderBookRow: depth fill now spans full row via CSS background-image gradient on <tr> instead of absolute DepthBar inside first <td> - Update tests: mock source gets onKlineUpdate/subscribeKlineStream; row test checks backgroundImage instead of DepthBar DOM node Closes #154 Closes #155 Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
…-row fix(chart-order-book): real-time kline stream and full-row depth bar
Replace fitContent() with setVisibleLogicalRange() so the chart opens anchored to the most recent ~100 candles. This avoids cramming all 500 REST bars into a single tiny viewport on load. - Added VISIBLE_BARS = 100 constant - showLatestBars() helper: from=max(0,len-100), to=len+3 (right margin) - Live tick path (klineIsLiveTick) unchanged — no view jump on every tick - ResizeObserver fallback uses fitContent() only if no data yet Closes #157 Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
All core features are shipped. Update three documents to reflect reality: README.md - Status blurb: "Active development / order book wiring in progress" → "P0 + P1 complete" - What It Does: add OHLCV chart, live ticker, full-row depth bars - Roadmap table: all six rows now show ✅ Merged with PR links ROADMAP.md - P0 table: mark all three features ✅ Merged - P1 table: mark order entry + portfolio ✅ Merged; add OHLCV row docs/PRD.md - In-scope list: replace trading-engine issue link with flow PR links - All quality-criteria checkboxes flipped from [ ] to [x] (TypeScript note clarified: no :any types, a few as casts at Zod boundaries) Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
fix(chart): default to last 100 bars instead of fitContent
# [1.1.0-next.25](v1.1.0-next.24...v1.1.0-next.25) (2026-04-10) ### Bug Fixes * **chart:** default to last 100 bars instead of fitContent ([8a8ad7a](8a8ad7a)), closes [#157](#157) Signed-off-by: semantic-release-bot <semantic-release-bot@martynus.net>
docs: sync README, ROADMAP and PRD to reflect P0+P1 complete
Add Zustand persist middleware so balances and trade history survive
page reloads. Add resetPortfolio() action + confirmation button on
the /portfolio route.
Changes:
- src/stores/portfolio.ts
- Wrap store with persist() middleware (key: flow:portfolio:v1)
- partialize: only balances + openOrders + filledOrders persisted
- merge: clear openOrders on hydration — LocalFillEngine pending
queue is not restored, so stale limit orders would never fill
- INITIAL_STATE constant extracted for reuse in reset
- resetPortfolio() flushes engine pending queue + resets to
INITIAL_STATE
- filledOrders capped at MAX_FILLED_ORDERS (500) to bound storage
- MAX_FILLED_ORDERS = 500 constant
- src/routes/portfolio.tsx
- Reset button with 2-step inline confirmation (no window.confirm)
- First click: button turns destructive + shows warning text
- Second click: calls resetPortfolio() and returns to normal state
- onBlur resets confirming state if user clicks away
- src/stores/portfolio.test.ts (new file, 5 tests)
- Initial state assertions
- resetPortfolio() restores balances + clears orders
- persist middleware presence verified
Closes #133
Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
feat(portfolio): persist state to localStorage with reset button
# [1.1.0-next.26](v1.1.0-next.25...v1.1.0-next.26) (2026-04-10) ### Features * **portfolio:** persist state to localStorage with reset button ([d092d95](d092d95)), closes [#133](#133) Signed-off-by: semantic-release-bot <semantic-release-bot@martynus.net>
Mark the two 🔄 In progress rows as shipped and add two rows for work completed since the table was last written: - React composition patterns → ✅ #64 - Route component extraction → ✅ #115 - Typography overhaul (Rajdhani + Noto Sans Mono) → ✅ #122 (new row) - Tailwind className lint enforcement → ✅ #131 (new row) Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
docs(roadmap): mark all Design System Status items complete
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Semantic-release auto-committed chore(release): 1.1.0 directly to main with CHANGELOG.md and package.json updates. Merging main back into develop to unblock the develop → main promotion PR (#162). Resolution: - CHANGELOG.md: keep develop (all next.x history); semantic-release will regenerate the full file for v1.2.0 - package.json: keep develop version 1.1.0-next.26 for the same reason Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
…to flow - Remove @semantic-release/git: the plugin auto-commits CHANGELOG.md and package.json directly to main after every stable release. That commit is never in develop, causing conflicts on every subsequent develop → main PR. Removing it means semantic-release still tags, publishes GitHub releases and generates release notes — just without writing files back to the repo. - Remove @semantic-release/changelog: only relevant alongside the git plugin since nothing commits the generated file without it. - Rename package name from 'trading-engine' to 'flow' to match the repo. Signed-off-by: Jeziel Lopes <jeziellopes@gmail.com>
chore(sync): back-merge main v1.1.0 release commit into develop
# [1.2.0-next.1](v1.1.0...v1.2.0-next.1) (2026-04-10) ### Bug Fixes * **chart+order-book:** real-time kline stream and full-row depth bar ([45be9af](45be9af)), closes [#154](#154) [#155](#155) * **chart:** default to last 100 bars instead of fitContent ([8a8ad7a](8a8ad7a)), closes [#157](#157) * **data-panel:** My Trades shows user fills + Activity tab isolation ([1239dac](1239dac)), closes [#97](#97) [#108](#108) * **ds:** replace bg-ds-gray-800 with bg-muted in Badge; set DataPanel default to trades tab; rename column header to Qty ([acf005f](acf005f)), closes [#138](#138) [#139](#139) [#145](#145) * **infra:** add order book gap detection and snapshot staleness check ([7a381a5](7a381a5)), closes [#117](#117) * **landing:** mark all features done; replace inline styles with Tailwind ([074229f](074229f)), closes [#134](#134) [#137](#137) * **layout:** add sm breakpoint for market trades panel + correct DEFAULT_LAYOUTS v13 ([3815c6a](3815c6a)) * **lint:** replace noNonNullAssertion violations in order-book test ([9cd395c](9cd395c)) * **lint:** resolve Biome import-order and noNonNullAssertion violations ([03d7c04](03d7c04)) * **live-indicator:** add undefined to className for exactOptionalPropertyTypes ([34d4f54](34d4f54)) * **market-data:** align stream subscriptions with Binance spot reference ([7a9d848](7a9d848)), closes [#129](#129) * **order-book:** align row font size with market trades (text-sm → text-xs, py-px → py-0.5) ([408d228](408d228)) * **order-book:** depth bar fills right-to-left on both bid and ask sides ([2d245ba](2d245ba)) * **order-book:** fix NaN bucketing, correct grouping options, move controls out of drag area ([107d942](107d942)) * **order-book:** remove levels URL param, show 50 rows, clean tab param ([1a2beea](1a2beea)) * **order-book:** replace aria-hidden with role=presentation on SVGs, remove stale Binance reference block ([be2084f](be2084f)) * **order-book:** reverse asks display order so best ask sits nearest spread ([065d02a](065d02a)) * **panel:** conditional cursor-move, title contrast + rich empty states ([2a32aa9](2a32aa9)), closes [#141](#141) [#142](#142) [#143](#143) [#141](#141) [#142](#142) [#143](#143) * **routing:** cast redirect params as never to satisfy TS strict router types ([5f82204](5f82204)) * **routing:** link logo directly to /symbol/BTCUSDT ([cf730eb](cf730eb)) * **routing:** redirect legacy ?tab=book&levels params to clean URL ([187bad9](187bad9)) * **routing:** remove auto-redirect from / — landing page should be visible ([99bedf4](99bedf4)) * **routing:** remove stale biome-ignore comment on never cast ([58c9f56](58c9f56)) * **routing:** resolve TS errors from 'as never' route cast ([c1b7628](c1b7628)) * **routing:** use location.searchStr in beforeLoad, align typecheck with build ([6ba9652](6ba9652)) * **styles:** update body font-family to Noto Sans Mono (stale Geist Mono ref) ([2eccda9](2eccda9)) * **ui:** add font-mono tabular-nums to Input primitive for consistent number rendering ([17683dc](17683dc)) ### Features * **chart+portfolio:** wire real Binance klines and portfolio store ([ebd4b32](ebd4b32)), closes [#151](#151) [#152](#152) * **infra:** WebSocket data layer — Binance live market data ([35791df](35791df)), closes [#99](#99) * **layout:** market trades as separate grid panel, My Trades for user fills ([7b90b0f](7b90b0f)), closes [#106](#106) * **layout:** market trades under order book, My Trades tab for user fills ([ef19bda](ef19bda)), closes [#106](#106) * **layout:** trades panel below order book (2/3+1/3), Price/Amount/Time columns ([208dce8](208dce8)) * **order-book:** column headers + semantic table structure ([20633d7](20633d7)), closes [#140](#140) [#144](#144) * **order-book:** hover highlight + click to set limit price ([65a102b](65a102b)), closes [#126](#126) * **order-book:** price grouping dropdown + view mode toggle ([#109](#109)) ([0c89887](0c89887)) * **order-book:** wire Order Book UI to live WebSocket data ([0549859](0549859)), closes [#96](#96) * **order-entry:** simulated order entry with LocalFillEngine ([53ce52a](53ce52a)), closes [#97](#97) * **portfolio:** persist state to localStorage with reset button ([d092d95](d092d95)), closes [#133](#133) * **routing:** symbol route loaders with validation and error states ([014ca0e](014ca0e)), closes [#96](#96) [#98](#98) * **ticker:** wire live price, OHLV, and tick direction from [@mini](https://github.com/mini)Ticker stream; fix portfolio widget ([ac6fd2e](ac6fd2e)), closes [#135](#135) [#136](#136) * **ui:** add Dropdown primitive; refactor GroupingSelect to use it ([cc3e312](cc3e312)) ### Performance Improvements * **chart:** fix CandleChart blink via PortfolioWidget extraction + stable ref ([d6baa9a](d6baa9a)), closes [#105](#105) [#105](#105) * **order-book:** prevent CLS micro-stutters on live data updates ([475e041](475e041)), closes [#118](#118) * **root:** scope store subscriptions to leaf components — fix [#104](#104) [#105](#105) ([1404b72](1404b72)), closes [hi#freq](https://github.com/hi/issues/freq) * **tab:** fix blank screen and frozen UI on tab return ([e10f617](e10f617)), closes [#113](#113) Signed-off-by: semantic-release-bot <semantic-release-bot@martynus.net>
chore(release): remove @semantic-release/git plugin + rename package to flow
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.
Release promotion:
develop→mainMerging all P0 + P1 work shipped since v1.1.0 (Apr 4). Semantic-release will compute v1.2.0 from the
feat(commits.What's new since v1.1.0
Features
@miniTickerstream (feat(ticker): wire live price, OHLV, and tick direction from @miniTicker stream; fix portfolio widget #147)LocalFillEngine, balance management (feat(order-entry): simulated order entry with LocalFillEngine #132)src/ui/library (refactor(order-book): levels refactor post-#111 #116)Performance
<Activity>isolation (perf(tab): fix blank screen and frozen UI on tab return #114)Bug fixes
fitContent()withsetVisibleLogicalRangeanchored to last 100 barsDesign system
font-brand/font-cyphertokens (refactor(design-system): Rajdhani + Noto Sans Mono; font-brand token for Orbitron #122)eslint-plugin-better-tailwindcss(chore(lint): add eslint-plugin-better-tailwindcss for className hygiene #131)Stats