Skip to content

Dynamic Wallet-State Binding by adding hook dependency#55

Open
aniket866 wants to merge 6 commits into
DjedAlliance:mainfrom
aniket866:added-wallet-change-in-useEffect-dependency-array
Open

Dynamic Wallet-State Binding by adding hook dependency#55
aniket866 wants to merge 6 commits into
DjedAlliance:mainfrom
aniket866:added-wallet-change-in-useEffect-dependency-array

Conversation

@aniket866
Copy link
Copy Markdown
Contributor

@aniket866 aniket866 commented Jan 31, 2026

Changes made:

Added walletAddress to the dependency array of the useEffect hook to ensure it re-runs when the wallet address changes.

@DengreSarthak Please check it out , Closes #40

Summary by CodeRabbit

  • New Features

    • Per-wallet transactions: each connected wallet now has its own cached transaction history and isolated state.
  • Bug Fixes / Reliability

    • State now resets and cached data reloads correctly when switching wallets to prevent cross-wallet data leakage.
    • Fetches avoid applying results for a different wallet if the active wallet changes mid-request, and cache expiry prevents showing stale data.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 31, 2026

Review Change Stack

Warning

Review limit reached

@aniket866, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 55 minutes and 9 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cdbd8f9f-b4d9-4be0-b4e1-e7cad04bc72d

📥 Commits

Reviewing files that changed from the base of the PR and between 28a4be9 and 269e932.

📒 Files selected for processing (1)
  • dashboard/hooks/use-transactions.ts
📝 Walkthrough

Walkthrough

The transactions hook now reads walletAddress from useWallet, resets local state when the wallet changes, uses a per-wallet localStorage cache with expiry (restoring blockNumber strings to BigInt), avoids cross-wallet race updates during fetch, and only clears the active wallet’s cache.

Changes

Hook & Wallet-aware Caching

Layer / File(s) Summary
Wallet import and hook wiring
dashboard/hooks/use-transactions.ts
Imports useWallet and exposes walletAddress to the hook.
Wallet-change state reset and per-wallet cache load
dashboard/hooks/use-transactions.ts
Tracks latest wallet in a ref; effect on [walletAddress] clears transactions, hasFetched, error, loading; loads per-wallet cache if present and not expired; restores cached blockNumber strings to BigInt.
Fetch safety across wallet switches
dashboard/hooks/use-transactions.ts
Captures the wallet being fetched and aborts applying results if the wallet changes during the async fetch.
Per-wallet caching and clearCache update
dashboard/hooks/use-transactions.ts
Serializes blockNumber to strings for storage under stablepay_transactions_<walletAddress> and updates clearCache to remove only the current wallet’s cache entry.
Trivial formatting/closure change
dashboard/hooks/use-transactions.ts
Minor closing-brace placement change; no behavior change.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I sniff the address, hop to a new trail,
Per-wallet crumbs I follow, fresh cache or stale,
I turn block strings back to BigInt with a grin,
I wipe my paws, reset — let the sync begin! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding wallet state binding through hook dependency array modifications to enable wallet-aware state management.
Linked Issues check ✅ Passed The PR successfully addresses issue #40 by making useTransactions wallet-aware through dependency array changes, per-wallet caching, and state reset on wallet changes.
Out of Scope Changes check ✅ Passed All changes are within scope: wallet-awareness implementation, per-wallet caching strategy, and state reset logic directly support the linked issue requirement.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

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: 0

Caution

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

⚠️ Outside diff range comments (2)
dashboard/hooks/use-transactions.ts (2)

22-42: ⚠️ Potential issue | 🟠 Major

Cache is not isolated per wallet—transactions may leak between accounts.

Adding walletAddress to the dependency array correctly triggers a re-run when the wallet changes, but the cache key (CACHE_KEY) is static. This means:

  1. When user switches wallets, the effect loads cached transactions that may belong to a different wallet.
  2. If the cache is empty/expired, previously loaded transactions remain in state until a new fetch completes.

Consider making the cache wallet-specific and clearing state on wallet change:

🔧 Proposed fix
+    // Clear state when wallet changes
     useEffect(() => {
+        // Reset state for new wallet context
+        setTransactions([]);
+        setHasFetched(false);
+        setError(null);
+        
+        if (!walletAddress) return;
+        
+        const cacheKey = `${CACHE_KEY}_${walletAddress}`;
-        const cached = localStorage.getItem(CACHE_KEY);
+        const cached = localStorage.getItem(cacheKey);
         if (cached) {
             try {
                 const { transactions: cachedTransactions, timestamp }: CachedData = JSON.parse(cached);
                 const isExpired = Date.now() - timestamp > CACHE_EXPIRY;

                 if (!isExpired && cachedTransactions.length > 0) {
                     // Convert string blockNumber back to BigInt
                     const restoredTransactions = cachedTransactions.map(event => ({
                         ...event,
                         blockNumber: BigInt(event.blockNumber)
                     }));
                     setTransactions(restoredTransactions);
                     setHasFetched(true);
                 }
             } catch (err) {
                 console.warn('Failed to parse cached transactions:', err);
             }
         }
     }, [walletAddress]);

You'll also need to update fetchTransactions and clearCache to use the wallet-specific cache key (or pass it via closure/ref).


48-50: ⚠️ Potential issue | 🟠 Major

Empty merchantAddress causes unfiltered data fetch—should use walletAddress instead

The merchantAddress is hardcoded to an empty string, which causes the filter condition on line 103 of transaction-service.ts (args: merchantAddress ? { receiver: merchantAddress }) to fail. This means all BoughtStableCoins events across all networks are fetched instead of filtering for a specific merchant, even though the comment suggests filtering intent. Since walletAddress is available from the useWallet() hook, it should likely be passed here to retrieve only relevant transactions.

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

🤖 Fix all issues with AI agents
In `@dashboard/hooks/use-transactions.ts`:
- Around line 21-31: The cache key is inconsistent: useEffect reads
localStorage.getItem(cacheKey) where cacheKey = `${CACHE_KEY}_${walletAddress}`
but other reads/writes/clears use plain CACHE_KEY; update all localStorage
interactions (reads, writes, and removes) to use the same per-wallet key pattern
`${CACHE_KEY}_${walletAddress}` and ensure you skip any caching operations when
walletAddress is falsy (e.g., in useEffect and in the functions that
persist/clear transactions). Locate occurrences by the symbols CACHE_KEY,
cacheKey, walletAddress, localStorage.getItem/setItem/removeItem and make them
consistent across useEffect and the transaction fetch/persist/clear logic.

Comment thread dashboard/hooks/use-transactions.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: 0

Caution

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

⚠️ Outside diff range comments (1)
dashboard/hooks/use-transactions.ts (1)

52-75: ⚠️ Potential issue | 🟡 Minor

Prevent stale async fetches from overwriting a new wallet's state.
If the wallet switches while fetchTransactions is in flight, the resolved data can overwrite the freshly reset state for the new wallet. The useEffect on line 22 resets state when walletAddress changes, but any pending fetchTransactions call (initiated before the switch) will execute its state updates afterward, causing cross-wallet data contamination in the cache (line 72-73). Consider tracking the active wallet/request and ignoring stale results.

🛠️ Suggested guard against stale results
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useRef } from 'react';

 export function useTransactions() {
     const { walletAddress } = useWallet();
+    const latestWalletRef = useRef<string | null>(walletAddress);
     const [transactions, setTransactions] = useState<TransactionEvent[]>([]);
@@
     useEffect(() => {
+        latestWalletRef.current = walletAddress;
         // Reset state for new wallet context
         setTransactions([]);
@@
-    const fetchTransactions = async () => {
+    const fetchTransactions = async () => {
+        const requestWallet = latestWalletRef.current;
         try {
             setLoading(true);
             setError(null);
             // Filter for specific merchant address: 
             const merchantAddress = '';
             const events = await transactionService.fetchStableCoinPurchases(merchantAddress);
+            if (latestWalletRef.current !== requestWallet) return;
             setTransactions(events);
             setHasFetched(true);
@@
-                if (walletAddress) {
-                    const cacheKey = `${CACHE_KEY}_${walletAddress}`;
+                if (requestWallet) {
+                    const cacheKey = `${CACHE_KEY}_${requestWallet}`;
                     localStorage.setItem(cacheKey, JSON.stringify(cacheData));
                }

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the useTransactions hook to react to wallet changes and isolate cached transaction state per connected wallet, addressing issue #40 (transactions not refreshing when switching wallets).

Changes:

  • Adds walletAddress-driven useEffect to reset local state and load a per-wallet localStorage cache on wallet changes.
  • Introduces per-wallet cache keys (stablepay_transactions_<walletAddress>) and guards against stale async updates via a ref.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread dashboard/hooks/use-transactions.ts Outdated
Comment thread dashboard/hooks/use-transactions.ts Outdated
aniket866 and others added 2 commits June 2, 2026 15:10
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@aniket866 aniket866 requested a review from DeveloperAmrit June 2, 2026 09:43
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.

Caution

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

⚠️ Outside diff range comments (3)
dashboard/hooks/use-transactions.ts (3)

54-84: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard stale catch and finally paths too.

The wallet check on Line 62 only protects the success path. If wallet A's request rejects after the user switches to wallet B, Lines 81-84 will still surface A's error and clear B's loading state. Use the same staleness gate for catch/finally, or switch to a request id so only the newest invocation can commit any state.

Proposed fix
         } catch (err) {
+            if (latestWalletRef.current !== requestWallet) return;
             console.error('Error fetching transactions:', err);
             setError(err instanceof Error ? err.message : 'Failed to fetch transactions');
         } finally {
-            setLoading(false);
+            if (latestWalletRef.current === requestWallet) {
+                setLoading(false);
+            }
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dashboard/hooks/use-transactions.ts` around lines 54 - 84, The
fetchTransactions function currently only checks staleness on the success path
using requestWallet vs latestWalletRef.current; extend that same staleness guard
to the catch and finally blocks (or implement a monotonically increasing
requestId checked at start/end) so that if latestWalletRef.current !==
requestWallet the catch should not call setError and the finally should not call
setLoading or other state setters; update references to setError, setLoading,
setTransactions, and setHasFetched so they only run when the invocation is still
fresh (use the same requestWallet or requestId guard).

72-79: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep cache persistence out of the fetch failure path.

localStorage.setItem can throw quota or storage-access errors. Right now that happens inside the main try, so a cache-write failure on Lines 76-78 falls into the fetch catch and reports a failed fetch even after setTransactions(events) already succeeded. Cache writes should be best-effort.

Proposed fix
             const cacheData: CachedData = {
                 transactions: serializableEvents as any,
                 timestamp: Date.now()
             };
                if (requestWallet) {
-                    const cacheKey = `${CACHE_KEY}_${requestWallet}`;
-                    localStorage.setItem(cacheKey, JSON.stringify(cacheData));
+                    try {
+                        const cacheKey = `${CACHE_KEY}_${requestWallet}`;
+                        localStorage.setItem(cacheKey, JSON.stringify(cacheData));
+                    } catch (storageError) {
+                        console.warn('Failed to cache transactions:', storageError);
+                    }
                }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dashboard/hooks/use-transactions.ts` around lines 72 - 79, The cache write to
localStorage (creating cacheKey with CACHE_KEY and requestWallet and calling
localStorage.setItem with cacheData) runs inside the main fetch try block and
can throw, causing successful setTransactions(events) to be treated as a fetch
failure; make cache persistence best-effort by moving the
JSON.stringify/localStorage.setItem call out of the fetch try/catch or wrapping
only the setItem call in its own try/catch that swallows/storage-quotas errors
(log them optionally) so setTransactions(events) success does not trigger the
fetch failure path.

39-47: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Treat a fresh empty cache as a real cache hit.

Line 39 only restores cached state when cachedTransactions.length > 0. That means a wallet with zero transactions will refetch every time you switch back to it within CACHE_EXPIRY, which defeats the per-wallet cache for that case. Set hasFetched for any non-expired cache entry, even when the cached array is empty.

Proposed fix
-                if (!isExpired && cachedTransactions.length > 0) {
+                if (!isExpired) {
                     // Convert string blockNumber back to BigInt
                     const restoredTransactions = cachedTransactions.map(event => ({
                         ...event,
                         blockNumber: BigInt(event.blockNumber)
                     }));
                     setTransactions(restoredTransactions);
                     setHasFetched(true);
                 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dashboard/hooks/use-transactions.ts` around lines 39 - 47, The code in
use-transactions.ts only treats non-empty cachedTransactions as a cache hit;
remove the length check so any non-expired cache entry (even an empty array) is
considered a hit. In the block guarded by !isExpired, map cachedTransactions
(which may be empty) to restore blockNumber to BigInt as you already do
(restoredTransactions) and call setTransactions(restoredTransactions) and
setHasFetched(true) for all non-expired cached entries; keep the existing BigInt
conversion logic and references to cachedTransactions, restoredTransactions,
setTransactions, setHasFetched, and isExpired.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@dashboard/hooks/use-transactions.ts`:
- Around line 54-84: The fetchTransactions function currently only checks
staleness on the success path using requestWallet vs latestWalletRef.current;
extend that same staleness guard to the catch and finally blocks (or implement a
monotonically increasing requestId checked at start/end) so that if
latestWalletRef.current !== requestWallet the catch should not call setError and
the finally should not call setLoading or other state setters; update references
to setError, setLoading, setTransactions, and setHasFetched so they only run
when the invocation is still fresh (use the same requestWallet or requestId
guard).
- Around line 72-79: The cache write to localStorage (creating cacheKey with
CACHE_KEY and requestWallet and calling localStorage.setItem with cacheData)
runs inside the main fetch try block and can throw, causing successful
setTransactions(events) to be treated as a fetch failure; make cache persistence
best-effort by moving the JSON.stringify/localStorage.setItem call out of the
fetch try/catch or wrapping only the setItem call in its own try/catch that
swallows/storage-quotas errors (log them optionally) so setTransactions(events)
success does not trigger the fetch failure path.
- Around line 39-47: The code in use-transactions.ts only treats non-empty
cachedTransactions as a cache hit; remove the length check so any non-expired
cache entry (even an empty array) is considered a hit. In the block guarded by
!isExpired, map cachedTransactions (which may be empty) to restore blockNumber
to BigInt as you already do (restoredTransactions) and call
setTransactions(restoredTransactions) and setHasFetched(true) for all
non-expired cached entries; keep the existing BigInt conversion logic and
references to cachedTransactions, restoredTransactions, setTransactions,
setHasFetched, and isExpired.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b7831fe0-8b32-4f84-8c9c-f1bb2e2019b4

📥 Commits

Reviewing files that changed from the base of the PR and between 72d8c49 and 28a4be9.

📒 Files selected for processing (1)
  • dashboard/hooks/use-transactions.ts

Copy link
Copy Markdown
Member

@DeveloperAmrit DeveloperAmrit left a comment

Choose a reason for hiding this comment

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

Thanks for the changes, approved from my side.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment thread dashboard/hooks/use-transactions.ts
Comment thread dashboard/hooks/use-transactions.ts
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.

Issue: useEffect in useTransactions has an empty dependency array, so it won't refresh if the user changes wallets.

3 participants