Add ops-based server filtering for history API#290
Conversation
Replace useSyncExternalStore with useState + useEffect in Header so the remembered username is always null on the initial render (matching the server), then updated after hydration. Apply the same deferred pattern to useTheme, which was reading localStorage inside the useState initializer — a value the server can never produce, causing React to render different trees on server vs client.
Cross-tab sync — window.addEventListener('storage', ...) in the module init block. When another tab writes to THEME_KEY, _theme is updated and _notify() is called so all subscribers in this tab re-render.
Duplicated classList ops — both sites kept, with comments explaining why: changeTheme applies synchronously for FOUC prevention, useLayoutEffect is the safety net for mount and cross-tab updates that come through _notify().
Set mutation during iteration — all forEach calls now go through _notify(), which snapshots with Array.from(_listeners) before iterating.
cycleTheme stability — removed the theme dependency by reading _theme directly from the module store. cycleTheme is now stable (only depends on changeTheme, which is itself stable with []), so it won't invalidate memoized children if one is added later.
Replace the single shared store with a makeStore factory and create the store in Providers via a persistent useRef so each server request gets an isolated store (prevents auth state leaking) while the client keeps a single instance. Update store types to AppStore/RootState/AppDispatch. Clarify Header's useSyncExternalStore usage in a comment for SSR-safe avatar initialization. Make getCurrentTheme SSR-safe by returning the internal _theme instead of reading localStorage.
Lock in the SSR-isolation invariant introduced in this PR so a future refactor cannot quietly revert makeStore back to a module-level singleton without failing CI.
The repo's vitest config requires 80% line/statement coverage, but ui.ts and wallet.ts had no tests, dragging the global stats to 79.54% lines / 77.30% statements and failing CI. Add reducer tests for every action in both slices. After this change: - Lines: 79.54% -> 84.46% - Statements: 77.30% -> 81.91%
Introduce AUTH_KEY_FIELDS and AuthKeyField type and update serializableCheck to ignore auth key paths and the auth/setCredentials action to avoid middleware warnings for private keys. Disable Redux DevTools in production entirely, and in development add stateSanitizer and actionSanitizer to replace live private-key fields with "[REDACTED]" in the auth slice and in setCredentials actions so keys are never shown in plain text to extensions or logs.
This reverts commit 936a654.
This reverts commit 0e90fbe.
Introduce AUTH_KEY_FIELDS constant covering all five key fields in the
auth slice (ownerKey, activeKey, postingKey, memoKey, privateKey) and
apply two layers of protection:
Production:
devTools: false — the Redux DevTools extension cannot inspect the
store on a real user session under any circumstances.
Development:
stateSanitizer replaces every non-null key field with '[REDACTED]'
before the extension renders state, so a developer's own keys are
never shown in plain text in the DevTools panel or time-travel log.
actionSanitizer applies the same redaction to auth/setCredentials
payloads so keys are not captured at the moment of login either.
Also fixes the pre-existing serializableCheck config which referenced
a non-existent action ('auth/setPrivateKey') and only listed one of
the five key paths — updated to 'auth/setCredentials' and all paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduce server-side op-type filtering to /api/query/history (ops param) with batching, cursor advancement, nextFrom/exhausted pagination and Redis fallbacks. Update the client API (apiClient.getHistory) and hooks (use-batch-history, use-rewards-history, use-activity-history) to request server-filtered pages instead of doing client-side filtering; simplify hook logic to consume already-normalized SteemHistoryItem[] and track server-provided nextFrom/exhausted. Add WALLET/ACTIVITY/REWARD op constants (src/lib/steem/history-ops.ts), normalize/cache helpers, and MAX_BATCHES/BATCH_SIZE safeguards. Add devTools sanitizers to redact auth key fields in Redux DevTools and tests for the new behaviors; mark some local filtering helpers as deprecated. Also remove some UI icons from recent-activity and adjust related tests.
|
The Included operation types:
Excluded operation types (never returned):
The server scans raw Steem account history in batches and only accumulates entries where |
Architectural Conflict with Existing Lazy-Load DesignThe This PR changes it to: The Problem: Two Nested LoopsThe server-side batching in Summary
RecommendationIf server-side filtering is desired, the server should handle only one batch per request (pull The |
|
Addressing these . |
Minor:
|
|
I will Address all these Concerns and Commit |
Minor Suggestions1. Duplicated
|
Remove server-side multi-batch scanning and simplify filtered history path to make exactly one Steem RPC call per HTTP request. Key changes: - Remove MAX_BATCHES and server-side limit/loop; fetchFiltered now issues one SteemService.getAccountHistory call and returns matching ops from that batch. - Deduplicate requested ops list and adjust handler call signatures (limit removed from filtered path). - Clamp fetchLimit to BATCH_SIZE or the provided from cursor (or BATCH_SIZE when from = -1) to avoid duplicates near history start. - Compute nextFrom/exhausted using the oldest index in the whole batch (to advance correctly) and return matching history. - Update tests to reflect the new single-RPC behavior and adjusted nextFrom/exhausted semantics (remove multi-batch expectations and adjust request params and assertions accordingly). This moves pagination control to the client (one batch per request) and simplifies server logic, avoiding complex loops and potential off-by-one/duplication issues.
Add two unit tests to tests/unit/history-route-filter.test.ts: one verifies that when from is much larger than BATCH_SIZE the handler uses the full BATCH_SIZE as fetchLimit (load-more behavior), and the other verifies that an empty ops query param is treated as no filter (legacy path) so response omits nextFrom and exhausted. Tests use mockGetAccountHistory and makeTuples to simulate responses.
|
@ety001, you can review now |
Introduce server-side op-type filtering to /api/query/history (ops param) with batching, cursor advancement, nextFrom/exhausted pagination and Redis fallbacks. Update the client API (apiClient.getHistory) and hooks (use-batch-history, use-rewards-history, use-activity-history) to request server-filtered pages instead of doing client-side filtering; simplify hook logic to consume already-normalized SteemHistoryItem[] and track server-provided nextFrom/exhausted. Add WALLET/ACTIVITY/REWARD op constants (src/lib/steem/history-ops.ts), normalize/cache helpers, and MAX_BATCHES/BATCH_SIZE safeguards. Add devTools sanitizers to redact auth key fields in Redux DevTools and tests for the new behaviors; mark some local filtering helpers as deprecated. Also remove some UI icons from recent-activity and adjust related tests.