diff --git a/src/components/WalletViewer.tsx b/src/components/WalletViewer.tsx index 297532b..b678683 100644 --- a/src/components/WalletViewer.tsx +++ b/src/components/WalletViewer.tsx @@ -10,7 +10,9 @@ import { ArrowUpRight, ArrowDownLeft, Zap, + RefreshCw, } from "lucide-react"; +import { Button } from "@/components/ui/button"; import { Card, CardContent, @@ -19,7 +21,7 @@ import { CardTitle, } from "@/components/ui/card"; import { Alert, AlertDescription } from "@/components/ui/alert"; -import { useMemo, useState, useEffect } from "react"; +import { useMemo, useState, useCallback } from "react"; import accountManager from "@/services/accounts"; import { decryptWalletConfig, @@ -108,73 +110,111 @@ export function WalletViewer({ pubkey }: WalletViewerProps) { // Get active account from accountManager const activeAccount = use$(accountManager.active$); - // Decrypt wallet data when events are available (only for own wallet) - useEffect(() => { - if (!isOwnWallet || !activeAccount?.nip44) return; - if (!walletConfigEvent) return; + // Manual decrypt function + const decryptWalletData = useCallback(async () => { + if (!activeAccount?.nip44) { + setDecryptionError("No NIP-44 encryption support in active account"); + return; + } - const decryptWalletData = async () => { - setIsDecrypting(true); - setDecryptionError(null); + setIsDecrypting(true); + setDecryptionError(null); - try { - // Decrypt wallet config - if (walletConfigEvent) { - const config = await decryptWalletConfig( - walletConfigEvent, - activeAccount, - ); - if (config) { - setWalletConfig(config); - } - } + console.log("[WalletViewer] Starting decryption..."); + console.log( + "[WalletViewer] Wallet config event:", + walletConfigEvent ? "found" : "not found", + ); + console.log("[WalletViewer] Token events:", tokenEvents?.length || 0); + console.log("[WalletViewer] History events:", historyEvents?.length || 0); - // Decrypt token events - if (tokenEvents && tokenEvents.length > 0) { - const decryptedTokens: UnspentTokens[] = []; - for (const event of tokenEvents) { - const tokens = await decryptUnspentTokens(event, activeAccount); - if (tokens) { - decryptedTokens.push(tokens); - } - } - setUnspentTokens(decryptedTokens); - } - - // Decrypt history events - if (historyEvents && historyEvents.length > 0) { - const allTransactions: Transaction[] = []; - for (const event of historyEvents) { - const history = await decryptTransactionHistory( - event, - activeAccount, - ); - if (history && history.transactions) { - allTransactions.push(...history.transactions); - } - } - setTransactions(sortTransactions(allTransactions)); - } - } catch (error) { - console.error("Decryption error:", error); - setDecryptionError( - error instanceof Error - ? error.message - : "Failed to decrypt wallet data", + try { + // Decrypt wallet config + if (walletConfigEvent) { + console.log("[WalletViewer] Decrypting wallet config..."); + const config = await decryptWalletConfig( + walletConfigEvent, + activeAccount, ); - } finally { - setIsDecrypting(false); + if (config) { + console.log( + "[WalletViewer] Wallet config decrypted successfully:", + config, + ); + setWalletConfig(config); + } else { + console.warn("[WalletViewer] Wallet config decryption returned null"); + } } - }; - decryptWalletData(); - }, [ - isOwnWallet, - activeAccount, - walletConfigEvent, - tokenEvents, - historyEvents, - ]); + // Decrypt token events + if (tokenEvents && tokenEvents.length > 0) { + console.log( + `[WalletViewer] Decrypting ${tokenEvents.length} token event(s)...`, + ); + const decryptedTokens: UnspentTokens[] = []; + for (const event of tokenEvents) { + const tokens = await decryptUnspentTokens(event, activeAccount); + if (tokens) { + console.log("[WalletViewer] Token event decrypted:", tokens); + decryptedTokens.push(tokens); + } else { + console.warn( + "[WalletViewer] Token event decryption returned null:", + event.id, + ); + } + } + setUnspentTokens(decryptedTokens); + console.log( + `[WalletViewer] Total ${decryptedTokens.length} token event(s) decrypted`, + ); + } else { + console.log("[WalletViewer] No token events to decrypt"); + setUnspentTokens([]); + } + + // Decrypt history events + if (historyEvents && historyEvents.length > 0) { + console.log( + `[WalletViewer] Decrypting ${historyEvents.length} history event(s)...`, + ); + const allTransactions: Transaction[] = []; + for (const event of historyEvents) { + const history = await decryptTransactionHistory(event, activeAccount); + if (history && history.transactions) { + console.log( + `[WalletViewer] History event decrypted: ${history.transactions.length} transaction(s)`, + ); + allTransactions.push(...history.transactions); + } else { + console.warn( + "[WalletViewer] History event decryption returned null:", + event.id, + ); + } + } + setTransactions(sortTransactions(allTransactions)); + console.log( + `[WalletViewer] Total ${allTransactions.length} transaction(s) decrypted`, + ); + } else { + console.log("[WalletViewer] No history events to decrypt"); + setTransactions([]); + } + + console.log("[WalletViewer] Decryption completed successfully"); + } catch (error) { + console.error("[WalletViewer] Decryption error:", error); + setDecryptionError( + error instanceof Error + ? error.message + : "Failed to decrypt wallet data", + ); + } finally { + setIsDecrypting(false); + } + }, [activeAccount, walletConfigEvent, tokenEvents, historyEvents]); // Calculate balance const balanceByMint = useMemo(() => { @@ -292,9 +332,19 @@ export function WalletViewer({ pubkey }: WalletViewerProps) { )} Wallet Status + {isOwnWallet && + !walletConfig && + !isDecrypting && + activeAccount?.nip44 && ( + + )} {isOwnWallet && walletConfig && ( -