Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions packages/tw-blocks-shared/src/wallet-kit/WalletButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ import { useWalletContext } from "./WalletProvider";
import { Popover, PopoverContent, PopoverTrigger } from "@tokenization/ui/popover";
import { Check, Copy, LogOut, ChevronRight, Wallet } from "lucide-react";

type WalletButtonProps = {
/** Use "sidebar" for lighter styling inside a sidebar (no dark/black background) */
variant?: "default" | "sidebar";
};

/**
* Wallet connection/disconnection button component
* Shows different states based on wallet connection status
*/
export const WalletButton = () => {
export const WalletButton = ({ variant = "default" }: WalletButtonProps) => {
const { handleConnect, handleDisconnect } = useWallet();
const { walletAddress, walletName } = useWalletContext();
const [copied, setCopied] = React.useState(false);
Expand All @@ -37,12 +42,17 @@ export const WalletButton = () => {
}
};

if (!mounted) {
const connectButtonClass =
variant === "sidebar"
? "flex w-full items-center gap-2 rounded-xl px-3 h-12 border border-border bg-sidebar-accent text-sidebar-accent-foreground hover:bg-sidebar-accent/80 transition-colors font-medium text-sm cursor-pointer"
: "flex w-full items-center gap-2 rounded-xl px-3 h-12 bg-primary text-primary-foreground hover:bg-primary/90 transition-colors font-medium text-sm cursor-pointer";

if (!mounted || !walletAddress) {
return (
<button
type="button"
onClick={mounted ? handleConnect : undefined}
className="flex w-full items-center gap-2 rounded-xl px-3 h-12 bg-primary text-primary-foreground hover:bg-brand-primary-hover transition-colors font-medium text-sm cursor-pointer"
onClick={handleConnect}
className={connectButtonClass}
Comment on lines +50 to +55
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C3 'useState<string \| null>\(null\)|localStorage.getItem|handleConnect|openModal' \
  packages/tw-blocks-shared/src/wallet-kit/WalletProvider.tsx \
  packages/tw-blocks-shared/src/wallet-kit/useWallet.ts

Repository: Trustless-Work/tokenization-private-credit

Length of output: 3254


🏁 Script executed:

cat -n packages/tw-blocks-shared/src/wallet-kit/WalletButtons.tsx | head -70

Repository: Trustless-Work/tokenization-private-credit

Length of output: 3097


🏁 Script executed:

cat -n packages/tw-blocks-shared/src/wallet-kit/WalletProvider.tsx

Repository: Trustless-Work/tokenization-private-credit

Length of output: 3634


🏁 Script executed:

cat -n packages/tw-blocks-shared/src/wallet-kit/useWalletContext.ts

Repository: Trustless-Work/tokenization-private-credit

Length of output: 178


Expose a hydration flag from WalletProvider to prevent showing the connect CTA during the hydration window.

The current code initializes walletAddress as null and restores persisted wallet data in a useEffect. Line 50 treats falsy walletAddress as "disconnected", but the local mounted flag only tracks component mount, not provider hydration. This creates a race condition: already-connected users briefly see the connect button after the component mounts but before the localStorage restore effect completes, and handleConnect() can be invoked during this transient state.

Add a hydrated boolean to the context. Update WalletProvider to track when the localStorage restore effect completes and expose that in the context value. Then change the check in WalletButtons.tsx line 50 to gate on hydration first:

-  const { walletAddress, walletName } = useWalletContext();
+  const { walletAddress, walletName, hydrated } = useWalletContext();

-  if (!mounted || !walletAddress) {
+  if (!hydrated) {
+    return null;
+  }
+
+  if (!walletAddress) {
     return (

This removes the need for the local mounted gate in WalletButtons.tsx.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/tw-blocks-shared/src/wallet-kit/WalletButtons.tsx` around lines 50 -
55, Add a hydrated boolean to the WalletProvider context and set it true when
the localStorage restore effect completes, then include hydrated in the provider
value; in WalletButtons.tsx stop relying on the local mounted flag and change
the early-return guard from "if (!mounted || !walletAddress)" to "if (!hydrated
|| !walletAddress)" (keeping handleConnect and connectButtonClass usage
unchanged) so the connect CTA is hidden until provider hydration finishes and
prevents invoking handleConnect during the restore window.

>
<Wallet className="size-5 shrink-0" />
<span>Conectar Billetera</span>
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/sidebar-wallet-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function SidebarWalletButton() {
isCollapsed && "justify-center"
)}
>
<WalletButton />
<WalletButton variant="sidebar" />
</div>
)
}
Loading