Conversation
…n wallet components - Added @frontend-design/, @brief.md, and .clinerules to .gitignore - Added new HomeScreen component with dashboard layout - Added AccountHeader, BalanceCard, and QuickActions components - Added useAccountBalance hook - Updated main.tsx to include new components
- Removed unused React imports from components using new JSX transform - Removed unused useEffect and Copy imports from HomeScreen - All components now build without TypeScript warnings
- Removed eslint-disable-line comment for react-hooks/exhaustive-deps rule - The rule definition was not found in ESLint configuration - This fixes the pre-push hook lint failure
- Ran pnpm format to fix code style issues - Applied consistent formatting across the entire codebase - This fixes the pre-push hook formatting check
📝 WalkthroughWalkthroughIntroduces a home dashboard screen for the extension wallet application, comprising UI components for displaying account information and balance, a custom React hook for balance management with polling, and supporting documentation and design guidelines. Changes
Sequence DiagramsequenceDiagram
participant User
participant HomeScreen
participant useAccountBalance
participant AccountHeader
participant BalanceCard
participant QuickActions
participant API as Backend API
User->>HomeScreen: Load HomeScreen
HomeScreen->>useAccountBalance: Call hook (mount)
useAccountBalance->>API: fetchBalance()
API-->>useAccountBalance: Return balance data
useAccountBalance-->>HomeScreen: Return {balance, isLoading, error, refreshBalance}
HomeScreen->>AccountHeader: Render with address & network
HomeScreen->>BalanceCard: Render with balance, loading, error states
HomeScreen->>QuickActions: Render with onSendClick, onReceiveClick callbacks
HomeScreen-->>User: Display dashboard UI
Note over useAccountBalance: 30-second polling interval starts
loop Polling
useAccountBalance->>API: fetchBalance() (background)
API-->>useAccountBalance: Return updated balance
alt Difference > threshold
useAccountBalance->>HomeScreen: Update balance state
HomeScreen->>BalanceCard: Re-render with new balance
end
end
User->>BalanceCard: Click refresh button
BalanceCard->>HomeScreen: Call onRefresh()
HomeScreen->>useAccountBalance: Call refreshBalance()
HomeScreen->>HomeScreen: Set isRefreshing=true
useAccountBalance->>API: fetchBalance()
API-->>useAccountBalance: Return balance
useAccountBalance-->>HomeScreen: Update balance
HomeScreen->>HomeScreen: Set isRefreshing=false
HomeScreen->>BalanceCard: Update with isRefreshing=false
BalanceCard-->>User: Display refreshed balance
User->>AccountHeader: Click copy address
AccountHeader->>HomeScreen: Call onCopyAddress()
HomeScreen->>HomeScreen: navigator.clipboard.writeText(address)
HomeScreen-->>User: Icon changes to indicate copy success
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (8)
apps/extension-wallet/src/components/BalanceCard.tsx (2)
29-30: Duplicate hardcoded conversion rate; use the shared utility instead.The
usdRate = 0.12is hardcoded here, butuseAccountBalance.tsalready exports aconvertToUSD(xlmAmount, rate)utility with the same default rate. If the rate needs updating, it would need to be changed in multiple places.Proposed fix: import and use the shared utility
import { RefreshCw, TrendingUp, AlertCircle, Coins } from 'lucide-react'; import { Button } from '@ancore/ui-kit'; import { Card, CardContent, CardHeader, CardTitle } from '@ancore/ui-kit'; +import { convertToUSD, formatUSD } from '../hooks/useAccountBalance'; // ... in component body: - // Calculate approximate USD value (placeholder - in real app, fetch from API) - const usdRate = 0.12; // Example rate: 1 XLM = $0.12 - const usdValue = balance * usdRate; - const formattedUsdValue = new Intl.NumberFormat('en-US', { - style: 'currency', - currency: 'USD', - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }).format(usdValue); + // Calculate approximate USD value (placeholder - in real app, fetch from API) + const usdValue = convertToUSD(balance); + const formattedUsdValue = formatUSD(usdValue);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/extension-wallet/src/components/BalanceCard.tsx` around lines 29 - 30, Replace the hardcoded usdRate/usdValue in BalanceCard.tsx by importing and using the shared convertToUSD utility from useAccountBalance.ts; remove the local usdRate constant and call convertToUSD(balance) (or convertToUSD(balance, rate) if an override is needed) to compute the USD value so the single source of truth for the conversion rate is used.
181-189: Consider moving the CSS animation to a stylesheet.Inline
<style>tags in React components can cause style recalculation on each render and make styles harder to maintain. Consider moving the@keyframes floatanimation to the global CSS file (index.css) or using a CSS-in-JS solution that handles deduplication.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/extension-wallet/src/components/BalanceCard.tsx` around lines 181 - 189, The inline <style> block defining `@keyframes` float and .animate-float inside BalanceCard.tsx should be moved to a stylesheet (e.g., index.css) or converted to a deduplicating CSS-in-JS rule; remove the inline <style> from BalanceCard.tsx, add the `@keyframes` float and .animate-float rules to your global CSS (or a styled component) and keep using the .animate-float className on the element(s) in BalanceCard so the animation behavior remains identical while avoiding per-render style injection and duplicates.apps/extension-wallet/src/main.tsx (1)
11-15: Placeholder callbacks need actual navigation/action implementation.The
onSettingsClick,onSendClick, andonReceiveClickcallbacks currently only log to console. Before this feature is complete, these should navigate to actual screens or trigger real actions. Consider adding a TODO comment or tracking this in an issue.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/extension-wallet/src/main.tsx` around lines 11 - 15, Replace the placeholder console.log callbacks passed to HomeScreen (props onSettingsClick, onSendClick, onReceiveClick) with real navigation or action invocations: call the app's navigation method (or dispatch appropriate actions) to navigate to Settings, Send, and Receive screens respectively, or wire to the real send/receive handlers; if the screens/handlers don't yet exist, add a TODO with an associated issue ID and leave a clear stub that calls a navigation helper (e.g., navigateToSettings/navigateToSend/navigateToReceive) so future work can implement them. Ensure you update the callbacks in main.tsx where HomeScreen is rendered and reference the exact prop names onSettingsClick, onSendClick, and onReceiveClick.brief.md (1)
41-43: Dependencies listed but not used in implementation.The brief lists
@ancore/core-sdkand@ancore/stellaras dependencies, but the current implementation uses stubbed/simulated data inuseAccountBalance.ts. This is fine for a demo but should be noted for future integration work.Would you like me to open an issue to track the integration of actual SDK dependencies?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@brief.md` around lines 41 - 43, The dependency list in brief.md includes `@ancore/core-sdk` and `@ancore/stellar` but the implementation in useAccountBalance.ts uses stubbed/simulated data; update brief.md to reflect that these SDKs are not yet integrated (add a short note or "Stubbed data — SDK integration pending") and add a TODO or link to a new issue tracking integration of `@ancore/core-sdk` and `@ancore/stellar` so future work knows to replace stubs in useAccountBalance.ts with real SDK calls.apps/extension-wallet/src/hooks/useAccountBalance.ts (2)
62-64: Missing dependency in useEffect will cause lint warning.The
refreshBalancecallback is called inside this effect but not listed in the dependency array. While the intent is to run once on mount, this will trigger anexhaustive-depslint warning.Proposed fix: suppress lint or restructure
Option 1 - Add eslint disable comment (if intentional):
// Initial fetch on mount useEffect(() => { refreshBalance(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []);Option 2 - Include dependency (will re-fetch if refreshBalance identity changes):
useEffect(() => { refreshBalance(); - }, []); + }, [refreshBalance]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/extension-wallet/src/hooks/useAccountBalance.ts` around lines 62 - 64, The useEffect in useAccountBalance.ts calls refreshBalance but omits it from the dependency array, triggering an exhaustive-deps lint warning; fix by either adding refreshBalance to the dependency array of the useEffect so it reruns if refreshBalance identity changes, or if the intent is truly to run only once on mount, add a one-line eslint disable comment above the effect (// eslint-disable-next-line react-hooks/exhaustive-deps) with a short justification; reference the useEffect that invokes refreshBalance and the refreshBalance callback when making the change.
67-88: Stale closure: polling interval captures outdatedbalanceanderrorvalues.The interval callback on line 72 checks
isLoadinganderror, but these values are captured when the effect runs. Since the effect re-runs when these dependencies change, this works for the guards. However, thebalancecomparison on line 76 uses the closure value which may be stale relative to whatsetBalancehas set.Additionally, line 72's
!isLoadingcheck is redundant since the effect already returns early on line 68 whenisLoadingis true.Proposed fix: use functional state update and remove redundant check
useEffect(() => { if (isLoading) return; const interval = setInterval(() => { - // Only update if not currently loading and no error - if (!isLoading && !error) { + if (!error) { fetchBalance() .then((newBalance) => { - // Only update if balance changed significantly (> 0.001 XLM) - if (Math.abs(newBalance - balance) > 0.001) { - setBalance(newBalance); - } + setBalance((prevBalance) => { + // Only update if balance changed significantly (> 0.001 XLM) + if (Math.abs(newBalance - prevBalance) > 0.001) { + return newBalance; + } + return prevBalance; + }); }) .catch((err) => { console.debug('Background balance update failed:', err); }); } }, 30000); return () => clearInterval(interval); - }, [balance, isLoading, error, fetchBalance]); + }, [isLoading, error, fetchBalance]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/extension-wallet/src/hooks/useAccountBalance.ts` around lines 67 - 88, The polling interval callback in useAccountBalance captures a stale balance and redundantly checks isLoading; update the interval handler to remove the redundant !isLoading guard and use a functional updater when updating state (call setBalance(prev => { if (Math.abs(newBalance - prev) > 0.001) return newBalance; return prev; })) so the comparison uses the latest balance; keep the existing error logging behavior on fetchBalance().catch and ensure fetchBalance, setBalance, balance, error, and isLoading are referenced to locate the change.apps/extension-wallet/src/components/QuickActions.tsx (2)
44-44: Placeholderconsole.logshould be wired to actual handlers or removed.The QR Code, More, and Buy XLM actions (lines 44, 53, 139) currently log to console. Consider either:
- Adding callback props similar to
onSendClick/onReceiveClick- Implementing the actual functionality
- Disabling these buttons until implemented
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/extension-wallet/src/components/QuickActions.tsx` at line 44, Replace the placeholder console.log handlers for the QR Code, More, and Buy XLM buttons with real callbacks or disable them: add new props (e.g., onQrClick, onMoreClick, onBuyXlmClick) to the QuickActions component prop type alongside existing onSendClick/onReceiveClick, wire the buttons' onClick to call those props, and either require callers to pass handlers or provide safe defaults (no-op) or render the buttons disabled when the prop is undefined; update any usage sites to pass the new handlers or leave them disabled until implemented.
154-160: Static placeholder values in transaction status card.The network fees (
~0.00001 XLM), speed (~3-5 seconds), and the 85% progress bar are hardcoded. These should eventually be fetched from the network or made configurable via props when real transaction handling is implemented.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/extension-wallet/src/components/QuickActions.tsx` around lines 154 - 160, The Transaction Ready card in QuickActions.tsx uses hardcoded values (network fees "~0.00001 XLM", speed "~3-5 seconds", and an 85% progress bar); update the QuickActions component to accept props like networkFee, eta, and progress (or fetch them in useEffect via a new getNetworkFeeEstimate/getTxSpeedEstimate helper) and replace the static strings and progress value with those dynamic values, providing sensible defaults if props are omitted to preserve current UI behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.gitignore:
- Around line 66-67: The .gitignore entries use an incorrect `@` prefix so they
won't match actual files; update the entries to match the real paths by
replacing `@frontend-design/` with `frontend-design/` and `@brief.md` with
`brief.md` (or remove these lines entirely if you intend to track those files)
so Git will properly ignore the intended items.
In `@apps/extension-wallet/src/components/BalanceCard.tsx`:
- Around line 45-56: The particle positions are regenerated on every render
because Math.random() is called directly inside the Array.from(...).map in the
BalanceCard component; fix by generating and memoizing a stable array of
particle position objects (left, top, animationDelay, animationDuration) once
(e.g., in a useMemo or useState initializer) and map over that memoized array
instead of calling Math.random() in the render, keeping the existing key (index)
or use an id field in the memoized objects for stable keys.
In `@apps/extension-wallet/src/screens/HomeScreen.tsx`:
- Around line 19-21: The copy flow assumes success and never updates the copied
UI: add a local copied state via useState (e.g., const [copied, setCopied] =
useState(false)), implement a robust copy handler (e.g., handleCopy) that tries
navigator.clipboard.writeText(accountAddress) with try/catch, falls back to a
document.execCommand('copy') fallback, sets setCopied(true) on success and
setCopied(false) on failure, and resets copied after a short timeout; then wire
the copied state (or setCopied) into the UI where the address/network copy
buttons are rendered (references: accountAddress, network, copied, and the copy
handler locations around the blocks you noted at lines 29-33 and 67-71).
- Around line 22-27: The handleRefresh function can leave isRefreshing true if
refreshBalance() rejects; wrap the await refreshBalance() call in a try/finally
(or try/catch/finally) so that setIsRefreshing(false) is always invoked in the
finally block (instead of only in the setTimeout after a successful await),
referencing handleRefresh, refreshBalance, and setIsRefreshing to locate the
change; keep the simulated delay by calling setTimeout inside the finally before
clearing the refreshing state.
---
Nitpick comments:
In `@apps/extension-wallet/src/components/BalanceCard.tsx`:
- Around line 29-30: Replace the hardcoded usdRate/usdValue in BalanceCard.tsx
by importing and using the shared convertToUSD utility from
useAccountBalance.ts; remove the local usdRate constant and call
convertToUSD(balance) (or convertToUSD(balance, rate) if an override is needed)
to compute the USD value so the single source of truth for the conversion rate
is used.
- Around line 181-189: The inline <style> block defining `@keyframes` float and
.animate-float inside BalanceCard.tsx should be moved to a stylesheet (e.g.,
index.css) or converted to a deduplicating CSS-in-JS rule; remove the inline
<style> from BalanceCard.tsx, add the `@keyframes` float and .animate-float rules
to your global CSS (or a styled component) and keep using the .animate-float
className on the element(s) in BalanceCard so the animation behavior remains
identical while avoiding per-render style injection and duplicates.
In `@apps/extension-wallet/src/components/QuickActions.tsx`:
- Line 44: Replace the placeholder console.log handlers for the QR Code, More,
and Buy XLM buttons with real callbacks or disable them: add new props (e.g.,
onQrClick, onMoreClick, onBuyXlmClick) to the QuickActions component prop type
alongside existing onSendClick/onReceiveClick, wire the buttons' onClick to call
those props, and either require callers to pass handlers or provide safe
defaults (no-op) or render the buttons disabled when the prop is undefined;
update any usage sites to pass the new handlers or leave them disabled until
implemented.
- Around line 154-160: The Transaction Ready card in QuickActions.tsx uses
hardcoded values (network fees "~0.00001 XLM", speed "~3-5 seconds", and an 85%
progress bar); update the QuickActions component to accept props like
networkFee, eta, and progress (or fetch them in useEffect via a new
getNetworkFeeEstimate/getTxSpeedEstimate helper) and replace the static strings
and progress value with those dynamic values, providing sensible defaults if
props are omitted to preserve current UI behavior.
In `@apps/extension-wallet/src/hooks/useAccountBalance.ts`:
- Around line 62-64: The useEffect in useAccountBalance.ts calls refreshBalance
but omits it from the dependency array, triggering an exhaustive-deps lint
warning; fix by either adding refreshBalance to the dependency array of the
useEffect so it reruns if refreshBalance identity changes, or if the intent is
truly to run only once on mount, add a one-line eslint disable comment above the
effect (// eslint-disable-next-line react-hooks/exhaustive-deps) with a short
justification; reference the useEffect that invokes refreshBalance and the
refreshBalance callback when making the change.
- Around line 67-88: The polling interval callback in useAccountBalance captures
a stale balance and redundantly checks isLoading; update the interval handler to
remove the redundant !isLoading guard and use a functional updater when updating
state (call setBalance(prev => { if (Math.abs(newBalance - prev) > 0.001) return
newBalance; return prev; })) so the comparison uses the latest balance; keep the
existing error logging behavior on fetchBalance().catch and ensure fetchBalance,
setBalance, balance, error, and isLoading are referenced to locate the change.
In `@apps/extension-wallet/src/main.tsx`:
- Around line 11-15: Replace the placeholder console.log callbacks passed to
HomeScreen (props onSettingsClick, onSendClick, onReceiveClick) with real
navigation or action invocations: call the app's navigation method (or dispatch
appropriate actions) to navigate to Settings, Send, and Receive screens
respectively, or wire to the real send/receive handlers; if the screens/handlers
don't yet exist, add a TODO with an associated issue ID and leave a clear stub
that calls a navigation helper (e.g.,
navigateToSettings/navigateToSend/navigateToReceive) so future work can
implement them. Ensure you update the callbacks in main.tsx where HomeScreen is
rendered and reference the exact prop names onSettingsClick, onSendClick, and
onReceiveClick.
In `@brief.md`:
- Around line 41-43: The dependency list in brief.md includes `@ancore/core-sdk`
and `@ancore/stellar` but the implementation in useAccountBalance.ts uses
stubbed/simulated data; update brief.md to reflect that these SDKs are not yet
integrated (add a short note or "Stubbed data — SDK integration pending") and
add a TODO or link to a new issue tracking integration of `@ancore/core-sdk` and
`@ancore/stellar` so future work knows to replace stubs in useAccountBalance.ts
with real SDK calls.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f29b6460-285d-424a-8ab5-a5d378c1b2eb
📒 Files selected for processing (10)
.gitignoreapps/extension-wallet/src/components/AccountHeader.tsxapps/extension-wallet/src/components/BalanceCard.tsxapps/extension-wallet/src/components/QuickActions.tsxapps/extension-wallet/src/hooks/useAccountBalance.tsapps/extension-wallet/src/main.tsxapps/extension-wallet/src/screens/HomeScreen.tsxbrief.mdfrontend-design/LICENSE.txtfrontend-design/SKILL.md
| @frontend-design/ | ||
| @brief.md |
There was a problem hiding this comment.
Gitignore entries don't match actual file/directory names.
The entries @frontend-design/ and @brief.md use an @ prefix, but the actual files in this PR are frontend-design/ and brief.md (without @). These gitignore rules won't match and the files will be tracked.
Either remove the @ prefix to ignore these files, or if the intent is to track them, remove these gitignore entries entirely.
Proposed fix (if intent is to ignore these paths)
# Project-specific ignores
-@frontend-design/
-@brief.md
+frontend-design/
+brief.md
.clinerules📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @frontend-design/ | |
| @brief.md | |
| frontend-design/ | |
| brief.md | |
| .clinerules |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.gitignore around lines 66 - 67, The .gitignore entries use an incorrect `@`
prefix so they won't match actual files; update the entries to match the real
paths by replacing `@frontend-design/` with `frontend-design/` and `@brief.md`
with `brief.md` (or remove these lines entirely if you intend to track those
files) so Git will properly ignore the intended items.
| {Array.from({ length: 20 }).map((_, i) => ( | ||
| <div | ||
| key={i} | ||
| className="absolute w-1 h-1 bg-primary/20 rounded-full animate-float" | ||
| style={{ | ||
| left: `${Math.random() * 100}%`, | ||
| top: `${Math.random() * 100}%`, | ||
| animationDelay: `${Math.random() * 5}s`, | ||
| animationDuration: `${3 + Math.random() * 7}s`, | ||
| }} | ||
| /> | ||
| ))} |
There was a problem hiding this comment.
Math.random() in render causes particle positions to change on every re-render.
The particle positions are computed using Math.random() directly in the render function. Each time the component re-renders (e.g., when balance updates, refresh button clicked), all particles will jump to new random positions, creating a jarring visual effect.
Proposed fix: memoize particle positions
+import { useMemo } from 'react';
import { RefreshCw, TrendingUp, AlertCircle, Coins } from 'lucide-react';
// ... other imports
export function BalanceCard({
// ... props
}: BalanceCardProps) {
+ // Memoize particle positions so they don't change on re-render
+ const particles = useMemo(
+ () =>
+ Array.from({ length: 20 }).map((_, i) => ({
+ id: i,
+ left: `${Math.random() * 100}%`,
+ top: `${Math.random() * 100}%`,
+ animationDelay: `${Math.random() * 5}s`,
+ animationDuration: `${3 + Math.random() * 7}s`,
+ })),
+ []
+ );
// ... rest of component
{/* Animated particles background */}
<div className="absolute inset-0 overflow-hidden">
- {Array.from({ length: 20 }).map((_, i) => (
+ {particles.map((particle) => (
<div
- key={i}
+ key={particle.id}
className="absolute w-1 h-1 bg-primary/20 rounded-full animate-float"
style={{
- left: `${Math.random() * 100}%`,
- top: `${Math.random() * 100}%`,
- animationDelay: `${Math.random() * 5}s`,
- animationDuration: `${3 + Math.random() * 7}s`,
+ left: particle.left,
+ top: particle.top,
+ animationDelay: particle.animationDelay,
+ animationDuration: particle.animationDuration,
}}
/>
))}
</div>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/extension-wallet/src/components/BalanceCard.tsx` around lines 45 - 56,
The particle positions are regenerated on every render because Math.random() is
called directly inside the Array.from(...).map in the BalanceCard component; fix
by generating and memoizing a stable array of particle position objects (left,
top, animationDelay, animationDuration) once (e.g., in a useMemo or useState
initializer) and map over that memoized array instead of calling Math.random()
in the render, keeping the existing key (index) or use an id field in the
memoized objects for stable keys.
| const [accountAddress] = useState('GABC...123'); | ||
| const [network] = useState('Testnet'); | ||
|
|
There was a problem hiding this comment.
Fix clipboard flow: handle failures and wire copied-state feedback.
The copy handler currently assumes success, and the success UI (copied) is never driven from HomeScreen.
✅ Proposed fix
const [isRefreshing, setIsRefreshing] = useState(false);
const [accountAddress] = useState('GABC...123');
const [network] = useState('Testnet');
+ const [copied, setCopied] = useState(false);
- const handleCopyAddress = () => {
- navigator.clipboard.writeText('GABC...123');
- // In a real app, you'd show a toast notification here
- console.log('Address copied to clipboard');
- };
+ const handleCopyAddress = async () => {
+ try {
+ await navigator.clipboard.writeText(accountAddress);
+ setCopied(true);
+ setTimeout(() => setCopied(false), 1200);
+ } catch (err) {
+ console.error('Failed to copy address', err);
+ }
+ };
<AccountHeader
address={accountAddress}
network={network}
onCopyAddress={handleCopyAddress}
+ copied={copied}
/>Also applies to: 29-33, 67-71
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/extension-wallet/src/screens/HomeScreen.tsx` around lines 19 - 21, The
copy flow assumes success and never updates the copied UI: add a local copied
state via useState (e.g., const [copied, setCopied] = useState(false)),
implement a robust copy handler (e.g., handleCopy) that tries
navigator.clipboard.writeText(accountAddress) with try/catch, falls back to a
document.execCommand('copy') fallback, sets setCopied(true) on success and
setCopied(false) on failure, and resets copied after a short timeout; then wire
the copied state (or setCopied) into the UI where the address/network copy
buttons are rendered (references: accountAddress, network, copied, and the copy
handler locations around the blocks you noted at lines 29-33 and 67-71).
| const handleRefresh = async () => { | ||
| setIsRefreshing(true); | ||
| await refreshBalance(); | ||
| // Simulate network delay for better UX | ||
| setTimeout(() => setIsRefreshing(false), 800); | ||
| }; |
There was a problem hiding this comment.
Ensure refresh state always resets on failure.
If refreshBalance() rejects, isRefreshing never resets and the UI can remain in a perpetual refreshing state.
✅ Proposed fix
const handleRefresh = async () => {
setIsRefreshing(true);
- await refreshBalance();
- // Simulate network delay for better UX
- setTimeout(() => setIsRefreshing(false), 800);
+ try {
+ await refreshBalance();
+ } finally {
+ // Simulate network delay for better UX
+ setTimeout(() => setIsRefreshing(false), 800);
+ }
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const handleRefresh = async () => { | |
| setIsRefreshing(true); | |
| await refreshBalance(); | |
| // Simulate network delay for better UX | |
| setTimeout(() => setIsRefreshing(false), 800); | |
| }; | |
| const handleRefresh = async () => { | |
| setIsRefreshing(true); | |
| try { | |
| await refreshBalance(); | |
| } finally { | |
| // Simulate network delay for better UX | |
| setTimeout(() => setIsRefreshing(false), 800); | |
| } | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/extension-wallet/src/screens/HomeScreen.tsx` around lines 22 - 27, The
handleRefresh function can leave isRefreshing true if refreshBalance() rejects;
wrap the await refreshBalance() call in a try/finally (or try/catch/finally) so
that setIsRefreshing(false) is always invoked in the finally block (instead of
only in the setTimeout after a successful await), referencing handleRefresh,
refreshBalance, and setIsRefreshing to locate the change; keep the simulated
delay by calling setTimeout inside the finally before clearing the refreshing
state.
|
@vrickish Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
|
@vrickish please resolve conflicts |
Closes #83
Description
Type of Change
Security Impact
Testing
Test Coverage
Manual Testing Steps
Breaking Changes
Checklist
For High-Security Changes
Related Issues
Closes #
Related to #
Additional Context
Reviewer Notes
Summary by CodeRabbit
Release Notes