Chore/project completion cleanup - #1
Open
nelly439 wants to merge 114 commits into
Open
Conversation
…for field inspections - Add SVG icon assets for all required PWA sizes in /public/icons/ - Update manifest.ts with proper icon paths, screenshots array, and maskable icons - Create service worker (sw.js) with precaching, NetworkFirst API strategy, and push handling - Register service worker and add beforeinstallprompt handler via PwaInstaller component - Implement PushNotificationManager for VAPID-based push subscription - Add API routes for VAPID public key and push subscription endpoints - Update layout.tsx with apple-touch-icon meta tags and service worker registration - Configure next.config.ts with proper SW headers and caching - Add Lighthouse CI audit step to frontend CI workflow - Add generate-pwa-assets script and .env.example for VAPID configuration Closes #20
- Replace useState with useRef ring buffer (10k entries) - rAF rendering loop with differential updates - 500ms full redraw interval enforcement - Offload min/max range computation to web worker - Rate monitoring with console.warn at 3000 msg/s - LiveMetricsCanvas: ring buffer + range cache + rAF loop
…essure fix: High-Frequency WebSocket Telemetry Backpressure Management in Canvas Charts
feat: Progressive Web App Manifest Configuration for Field Inspections
- Add WatchWalletChanges from @stellar/freighter-api to detect identity changes - Use generation counter (useRef) to discard stale connect responses - Store AbortController in ref for immediate cancellation on identity change - Nullify metrics and evict React Query cache on wallet switch - Evict query cache before committing new public key in connect flow - Add generation checks after each async step in connect - Clean up disconnect to abort in-flight operations and clear cache - Replace dynamic imports with static imports for getAddress/getNetwork Closes Husten150#1
…tching fix: race conditions in async wallet switching state synchronization
…r codes, and collapsible error UI
- Refactor errorDecoder.ts into an ErrorDecoder class with a dynamic per-contract error registry via registerContractErrors()
- Add SorobanHostFuncError enum with 17 host function error codes
- Parse Soroban RPC error objects with { code, message, data } structure
- Add tryDecode() with fallback chain: Soroban -> Stellar -> RPC -> generic
- Wrap all error messages in t() for future i18n support
- Add collapsible Details section in TransactionModal showing raw error
- Add comprehensive unit tests for ErrorDecoder
Closes #10
feat: accessible error translation layer for obscure Web3 RPC rejections
…ation Implemented comprehensive transaction retry queue system to address duplicate submissions and transaction state loss on page reloads. Key Features: - IndexedDB persistence (schema v2) with pendingTransactions store - 30-second deduplication window to prevent duplicate submissions - Automatic transaction status polling (5s intervals, 10min max) - Real-time UI updates with TxStatusPill component - Transaction tracking: hash, retry count, ledger number - Auto-restore pending transactions on app mount - Clear completed transactions functionality Technical Changes: - Upgraded IndexedDB from v1 to v2 with indexes - Refactored useTxRetryQueue hook with persistence support - Created TxStatusPill and TxStatusList UI components - Added mock /api/escrow/tx-status endpoint - Integrated queue with TransactionModal Testing: - Added 27+ comprehensive tests (IndexedDB, queue logic, UI) - All tests passing (57+ total) - 0 TypeScript errors, 0 ESLint warnings - Production build verified Documentation: - QUICK_START.md - Quick reference guide - TRANSACTION_QUEUE_README.md - Complete API documentation - IMPLEMENTATION_SUMMARY.md - Technical details - FLOW_DIAGRAM.md - Visual flow diagrams - TEST_RESULTS.md - Test coverage report - COMPLETION_CHECKLIST.md - Requirements checklist - IMPLEMENTATION_COMPLETE.md - Final summary Dependencies: - Added fake-indexeddb for testing Breaking Changes: None Notes: - Mock tx-status API endpoint needs Soroban RPC integration for production - All existing tests still passing - Backward compatible implementation
Applied prettier formatting to ensure consistent code style across the project. Changes include standardized indentation, line breaks, and code formatting.
Fixed stale closure issue in startPollingTxStatus by using functional updates. The polling function was capturing stale state, preventing status updates. Changes: - Updated startPollingTxStatus to use setPendingTxs functional form - Removed pendingTxs from dependency array to avoid recreation - Modified test to check state updates instead of mock calls - All 57 tests now passing Fixes: - Transaction status now correctly updates to 'confirmed' - Polling works properly across multiple transactions - No more stale state issues in async callbacks
…eue-persistence feat: implement transaction retry queue with persistence and deduplic…
- Create GasEstimator sub-component with Inclusion Fee, Resource Fee, and Rent Refundable Fee rows, each with spinner state - Add useGasEstimate hook using @stellar/stellar-sdk Server.simulateTransaction for real-time Soroban RPC simulation - Implement 30-second in-memory cache keyed by contractId+operation+amount - Add 3-second timeout fallback with heuristic estimate - Display fees in XLM and USD (via oracle rate fetch) - Extend ErrorDecoder with simulation-specific error patterns - Update TransactionModal to integrate GasEstimator with disabled Submit on simulation failure - Update useEscrowBalance hook with simulate method - Add comprehensive tests for GasEstimator, useGasEstimate, and errorDecoder Closes #12
Deterministic Pre-Flight Gas Fee Estimation Component
… analytics (#11) - Add useChunkedHistory hook with sequential chunk fetching, Web Worker processing, AbortController cancellation, and progressive state - Support multi-device history aggregation with merged/sorted results - Add TelemetryChart progressive rendering with loading gradient overlay and animated dots - Add memory cap enforcement (MAX_MEMORY_POINTS = 200,000) with downsampling - Add new types: TelemetryHistoryPoint, ProcessedHistoryChunk, ChunkedHistoryState - Fix ring buffer to only append new data points (prevDataLenRef tracking) - Add comprehensive unit tests (13 tests covering all edge cases) Closes #11
Issue #6 - Canvas Re-rendering Profiling and Memory Leak Isolation: - Add Page Visibility API listener to pause/resume rAF loops in LiveMetricsCanvas and TelemetryChart, preventing wasted renders when the tab is hidden and forcing full redraw on resume - Add dev-mode memory measurement using performance.measureUserAgentSpecificMemory with typed interface - Improve cleanup to cancel rAF and reset refs on unmount Issue #11 - Dynamic Chunk-Loading and Pagination for IoT Analytics: - Create useChunkedHistory hook with sequential chunked fetching, AbortController cancellation, and Web Worker integration - Split time ranges into non-overlapping chunks (max 86,400 pts/chunk) - Progressive data accumulation with partial rendering support - Add pending region visualization in TelemetryChart with animated dashed border and dimmed loading overlay - Support progressive rendering via new totalTimeRange, pendingRange, and isLoading props
perf(dashboard): optimize fleet canvas grid rendering and metrics cul…
…ding fix: implement dynamic chunk-loading and pagination for year-long IoT…
Problem: The initial / route shipped 2.4 MB of JS (uncompressed) because
@stellar/stellar-sdk and @stellar/freighter-api were eagerly loaded via
WalletProvider in the root layout, causing a ~12-second TTI on 3G.
Changes:
- next.config.ts: add @next/bundle-analyzer (ANALYZE=true), enable
experimental.webpackBuildWorker, and configure webpack splitChunks
cache groups to isolate @stellar/* SDKs and bignumber.js into
dedicated chunks (stellar-sdk, bignumber).
- src/components/providers/index.tsx: strip WalletProvider and
QueryProvider from root Providers — only ThemeProvider remains,
keeping the root layout server-renderable and SDK-free.
- src/components/providers/DashboardProviders.tsx (new): client
component composing QueryProvider + WalletProvider, imported only
from wallet-connected routes.
- src/app/dashboard/layout.tsx: wrap children in DashboardProviders so
the Stellar SDK chunk is fetched only when the user navigates to
/dashboard or /escrow.
- src/app/dashboard/page.tsx: replace static TelemetryChart import with
next/dynamic({ ssr: false }) so the canvas component and its Web
Worker ship as a separate lazy chunk, not in the initial payload.
- src/app/page.tsx: dynamic-import HomeContent (ssr:false) to keep the
root page HTML lightweight; Stellar SDK loads only after hydration.
- src/components/home/HomeContent.tsx (new): extracted home page UI
wrapped in DashboardProviders for deferred wallet context.
- package.json: add analyze script (ANALYZE=true npm run build).
- .github/workflows/frontend-ci.yml: add bundle-analysis job that runs
the analyzer build, uploads the treemap report as an artifact, and
fails CI if the / route gzipped JS exceeds 200 KB.
All 72 unit tests pass. TypeScript and ESLint clean.
Fix the Lint & Format CI check that was failing because 47 files had inconsistent formatting. Ran prettier --write on the full src tree. No logic changes — purely whitespace/style normalisation.
feat(hooks): add race-safe useLatestRequest primitive; harden refresh…
Issue #59 described a Math.random/getRandomValues transaction-nonce collision. That mechanism does not exist: the only nonce in the repo is the server-side auth nonce (randomBytes(32)); GasEstimator is a display-only component and no client code builds a transaction nonce. This is defense-in-depth, NOT a fix for a reproducible bug. The submit button's existing disabled guard already prevents click-driven double-submits in React 18/19 (discrete-event state updates flush synchronously, so the button is disabled before any second click). The added submittingRef makes that protection independent of render timing and of the disabled condition staying correct, so a future refactor (button enabled during submit, a keyboard trigger, a programmatic/non-discrete invocation) cannot reintroduce a duplicate escrow submission. - TransactionModal.handleSubmit: bail if a submit is already in flight. - Test: three synchronous submit activations result in exactly one /api/escrow/deposit request and one enqueue.
…ning harden(TransactionModal): synchronous in-flight guard on submit
- canvasWorker.test.ts: type mockPostMessage with explicit fn signature to fix TS2348 (Mock<Procedure|Constructable> not callable) - transactionModalPopstate.spec.ts: add Window interface augmentation for __closeCalls, __onClose, __fireSpuriousPopstates, __fireGenuineBack to fix TS2339 property-does-not-exist errors - Add RestoreTransactionBanner component and dashboard page integration - Add TransactionModal popstate guard (replaceState-based, spurious-close fix)
Issue #55 described a stale-closure zoom-jump in LiveMetricsCanvas. That bug does not exist: there is no zoom in LiveMetricsCanvas (every ctx.scale is ctx.scale(dpr, dpr)), no computeBounds/telemetryData state, and the rAF loops already read data from refs and re-subscribe when their draw callback changes. This is a DRY refactor, NOT a bug fix. LiveMetricsCanvas and TelemetryChart had byte-identical rAF-loop boilerplate (running flag, visibility skip, hidden-tab full-redraw reset, reduced-motion interval fallback, cleanup). Extracted it into one tested hook; behavior is preserved exactly. - useRenderLoop: rAF loop + reduced-motion interval + visibility skip + resume-after-hidden callback + cleanup. draw/isVisible/onResumeAfterHidden must be stable (memoized) so the loop re-subscribes only when draw changes, matching the original effect deps. - LiveMetricsCanvas / TelemetryChart: use the hook; component-specific bits (isPageVisible ref, lastFullRedraw reset) passed in via stable callbacks. - Tests: visible-draw, hidden-skip, resume-after-hidden, unmount-cancel, and reduced-motion interval. Verified: typecheck, lint, 149 tests, prettier, and next build all pass.
- create useFormTracker zustand store to track dirty forms across the app - add AppUpdateBanner component to notify users of pending app reloads and block reload until unsaved forms are saved - update TransactionModal to track dirty state based on input amount, clean on submit and unmount - enhance PwaInstaller to show confirmation dialog for unsaved changes before reloading or installing PWA - add AGENTS.md contributor guidelines and update .gitignore to track the new file
refactor(canvas): extract shared useRenderLoop hook
- use functional state initializer to safely access localStorage only client-side - refactor auto-reload useEffect to fix timer cleanup and correct dependencies - remove redundant initial state effect since initial state is now set via useState
Issue #50 described a useSyncExternalStore stale-closure bug. That mechanism does not exist: there is no useSyncExternalStore, no deviceStore, no applyFilter anywhere, and FleetCanvasGrid had no click action at all (hover only). So there was no bug to fix — but the issue points at a real gap and a real invariant worth guaranteeing. This implements the genuine capability (click a cell to open its detail) and upholds the invariant 'the selection always matches the currently-rendered fleet' by construction, not via the blueprint ref/version hack: - Selection keyed by stable fleetId; the detail panel derives from the latest fleet list each render (resolveSelectedFleet). On a new batch it re-derives — shows the updated fleet or clears if gone. No closure or index to drift stale. - hitTestCell: pure, shared coordinate->index used by both hover and click. - Optional onSelectFleet callback; inline detail panel keeps it self-contained. - Tests cover hitTestCell and resolveSelectedFleet incl. the stale-proof property. Verified: typecheck, lint, 158 tests, prettier, next build all pass.
…ction feat(FleetCanvasGrid): clickable fleet selection (stale-proof by design)
feat: add form dirty tracking, app update banner, unsaved form checks
The src/core/blockchain/ directory (rpc_client, tx_manager, event_listener) and tests/unit/blockchain.test.ts were mistakenly added to the frontend. This is a Node.js server-side RPC client; the undici HTTP/2 session leak fix has been applied to iot-billing-backend instead (PR: fix/rpc-http2-session-leak). Also reverts the undici dependency from package.json — the frontend does not need it.
…improvements fix: format billing stream reconnect changes
Combines both sides: - Keeps worker/OffscreenCanvas path with chunked transfer (CHUNK_SIZE=4096) - Brings in main's improved fallback: decimation (MAX_POINTS_PER_METRIC=2000), rangeCache, prefersReducedMotion, visibility tracking, rate-warn threshold, viewport culling, incremental redraws (FULL_REDRAW_MS=500) - RING_CAPACITY aligned to main's 10_000 - Drops FrameBudgetMonitor/useRenderLoop (not yet in this branch)
…rLoop - Resolves MAX_POINTS_PER_METRIC conflict: keep chunkBuffer (worker path) + comment - Creates src/utils/frameBudget.ts: FrameBudgetMonitor, decimationStride - Creates src/hooks/useRenderLoop.ts: rAF/interval loop with visibility + reduced-motion - LiveMetricsCanvas now uses FrameBudgetMonitor for budget-adaptive decimation and useRenderLoop replacing the inline rAF loop
…ndition-45 Fix/device status icon race condition 45
…afelist, css validation, and tests
Device telemetry chart
…s-safelist fix(#65): guarantee status/type Tailwind classes survive the production build
- Remove duplicate MAX_POINTS_PER_METRIC constant (merge artifact) - Fix broken for-loop in LiveMetricsCanvas (missing moveTo/lineTo, first/lastPlotted updates, and closing brace — merge artifact) - Remove duplicate const stride declaration (merge artifact) - Replace setState-in-effect in RestoreTransactionBanner with lazy useState initializer to fix react-hooks/set-state-in-effect error - Run Prettier on 5 affected files
- Fix React testing act() warnings in test files - Add test-results/ to .gitignore for E2E test artifacts - All 207 tests now pass without warnings - Project ready for deployment
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.
closes #303