Skip to content

Chore/project completion cleanup - #1

Open
nelly439 wants to merge 114 commits into
Husten150:mainfrom
nelly439:chore/project-completion-cleanup
Open

Chore/project completion cleanup#1
nelly439 wants to merge 114 commits into
Husten150:mainfrom
nelly439:chore/project-completion-cleanup

Conversation

@nelly439

Copy link
Copy Markdown

closes #303

  • Fixed React testing act() warnings in test files
  • Added test-results/ to .gitignore
  • All 207 tests now pass without warnings
  • Project ready for deployment

Husten150 and others added 30 commits June 16, 2026 20:05
…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.
JerryIdoko and others added 30 commits June 23, 2026 22:01
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
…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
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.