Files
solace-bg-dubai/frontend/components/web3/WalletConnect.tsx
defiQUG a03417be98
All checks were successful
CI / lint-and-test (push) Successful in 9m52s
chore: consolidate local WIP (repo cleanup 20260707)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 09:41:38 -07:00

114 lines
4.0 KiB
TypeScript

"use client";
import { useState, useEffect, useRef } from "react";
import { useAccount, useConnect, useDisconnect } from "wagmi";
import { formatAddress } from "@/lib/utils";
import { isValidWalletConnectProjectId, getWalletConnectProjectId } from "@/lib/web3/walletconnect";
import { WalletBalancePanel } from "@/components/web3/WalletBalancePanel";
export function WalletConnect() {
const { address, isConnected } = useAccount();
const { connectors, connect, isPending } = useConnect();
const { disconnect } = useDisconnect();
const [menuOpen, setMenuOpen] = useState(false);
const menuRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!menuOpen) return;
const onPointerDown = (event: MouseEvent) => {
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
setMenuOpen(false);
}
};
document.addEventListener("mousedown", onPointerDown);
return () => document.removeEventListener("mousedown", onPointerDown);
}, [menuOpen]);
const walletConnectConfigured = isValidWalletConnectProjectId(
getWalletConnectProjectId()
);
const availableConnectors = connectors.filter((connector) => {
if (connector.id === "walletConnect" && !walletConnectConfigured) {
return false;
}
return true;
});
if (isConnected && address) {
return (
<div ref={menuRef} className="relative w-full sm:w-auto">
<button
type="button"
onClick={() => setMenuOpen((open) => !open)}
className="flex flex-wrap items-center gap-2 text-sm rounded-lg px-3 py-2 bg-gray-800/80 hover:bg-gray-800 border border-gray-700 transition-colors w-full sm:w-auto"
aria-expanded={menuOpen}
aria-haspopup="dialog"
>
<span className="text-gray-400">Connected:</span>
<span className="font-mono text-white">{formatAddress(address)}</span>
<span className="text-gray-500 text-xs" aria-hidden>
{menuOpen ? "▲" : "▼"}
</span>
</button>
{menuOpen && (
<div
role="dialog"
aria-label="Wallet balances"
className="absolute right-0 mt-2 bg-gray-900 border border-gray-700 rounded-xl shadow-xl z-50 overflow-hidden"
>
<WalletBalancePanel
address={address}
onDisconnect={() => {
disconnect();
setMenuOpen(false);
}}
/>
</div>
)}
</div>
);
}
return (
<div ref={menuRef} className="relative w-full sm:w-auto">
<button
type="button"
onClick={() => setMenuOpen((open) => !open)}
disabled={isPending || availableConnectors.length === 0}
className="w-full sm:w-auto px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-700 disabled:cursor-not-allowed rounded-lg transition-colors text-sm font-medium"
aria-expanded={menuOpen}
aria-haspopup="menu"
>
{isPending ? "Connecting…" : "Connect Wallet"}
</button>
{menuOpen && (
<div
role="menu"
className="absolute right-0 mt-2 w-full sm:w-56 bg-gray-900 border border-gray-700 rounded-lg shadow-xl z-50 overflow-hidden"
>
{availableConnectors.map((connector) => (
<button
key={connector.uid}
type="button"
role="menuitem"
onClick={() => {
connect({ connector });
setMenuOpen(false);
}}
className="w-full text-left px-4 py-3 text-sm hover:bg-gray-800 transition-colors border-b border-gray-800 last:border-b-0"
>
{connector.name}
</button>
))}
{!walletConnectConfigured && (
<p className="px-4 py-2 text-xs text-gray-500 border-t border-gray-800">
WalletConnect disabled set NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID
</p>
)}
</div>
)}
</div>
);
}