mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-06-17 01:58:33 +02:00
refactor: production-readiness improvements for WalletViewer
Critical fixes: - Wrap loadWalletInfo and loadInitialTransactions in useCallback to prevent infinite loops - Fix dependency arrays in useEffect hooks - Fix early return bug in handleConfirmSend that left sending state stuck - Add async/await error handling to handleCopyInvoice - Change throw new Error instead of early return in Lightning address resolution Performance optimizations: - Removed duplicate function definitions (moved to useCallback hooks) - Proper memoization of wallet loading functions Code quality: - All functions properly handle errors with try/catch - Loading states properly reset in finally blocks - No memory leaks from useEffect dependencies
This commit is contained in:
@@ -234,20 +234,46 @@ export default function WalletViewer() {
|
||||
const [detailDialogOpen, setDetailDialogOpen] = useState(false);
|
||||
|
||||
// Load wallet info on mount
|
||||
const loadWalletInfo = useCallback(async () => {
|
||||
try {
|
||||
const info = await getInfo();
|
||||
setWalletInfo(info);
|
||||
} catch (error) {
|
||||
console.error("Failed to load wallet info:", error);
|
||||
toast.error("Failed to load wallet info");
|
||||
}
|
||||
}, [getInfo]);
|
||||
|
||||
const loadInitialTransactions = useCallback(async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const result = await listTransactions({
|
||||
limit: BATCH_SIZE,
|
||||
offset: 0,
|
||||
});
|
||||
const txs = result.transactions || [];
|
||||
setTransactions(txs);
|
||||
setHasMore(txs.length === BATCH_SIZE);
|
||||
} catch (error) {
|
||||
console.error("Failed to load transactions:", error);
|
||||
toast.error("Failed to load transactions");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [listTransactions]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isConnected) {
|
||||
loadWalletInfo();
|
||||
}
|
||||
}, [isConnected]);
|
||||
}, [isConnected, loadWalletInfo]);
|
||||
|
||||
// Load transactions when wallet info is available
|
||||
useEffect(() => {
|
||||
if (walletInfo?.methods.includes("list_transactions")) {
|
||||
loadInitialTransactions();
|
||||
}
|
||||
}, [walletInfo]);
|
||||
|
||||
// Check for incoming payment when invoice is generated
|
||||
}, [walletInfo, loadInitialTransactions]);
|
||||
useEffect(() => {
|
||||
if (!generatedPaymentHash || !receiveDialogOpen) return;
|
||||
|
||||
@@ -281,34 +307,6 @@ export default function WalletViewer() {
|
||||
loadInitialTransactions,
|
||||
]);
|
||||
|
||||
async function loadWalletInfo() {
|
||||
try {
|
||||
const info = await getInfo();
|
||||
setWalletInfo(info);
|
||||
} catch (error) {
|
||||
console.error("Failed to load wallet info:", error);
|
||||
toast.error("Failed to load wallet info");
|
||||
}
|
||||
}
|
||||
|
||||
async function loadInitialTransactions() {
|
||||
setLoading(true);
|
||||
try {
|
||||
const result = await listTransactions({
|
||||
limit: BATCH_SIZE,
|
||||
offset: 0,
|
||||
});
|
||||
const txs = result.transactions || [];
|
||||
setTransactions(txs);
|
||||
setHasMore(txs.length === BATCH_SIZE);
|
||||
} catch (error) {
|
||||
console.error("Failed to load transactions:", error);
|
||||
toast.error("Failed to load transactions");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
const loadMoreTransactions = useCallback(async () => {
|
||||
if (
|
||||
!walletInfo?.methods.includes("list_transactions") ||
|
||||
@@ -364,8 +362,8 @@ export default function WalletViewer() {
|
||||
return;
|
||||
}
|
||||
|
||||
setSending(true);
|
||||
try {
|
||||
setSending(true);
|
||||
const amountSats = parseInt(sendAmount); // Amount is in sats
|
||||
const invoice = await resolveLightningAddress(input, amountSats);
|
||||
|
||||
@@ -375,8 +373,7 @@ export default function WalletViewer() {
|
||||
// Parse the resolved invoice
|
||||
const details = parseInvoice(invoice);
|
||||
if (!details) {
|
||||
toast.error("Failed to parse resolved invoice");
|
||||
return;
|
||||
throw new Error("Failed to parse resolved invoice");
|
||||
}
|
||||
|
||||
setInvoiceDetails(details);
|
||||
@@ -558,11 +555,16 @@ export default function WalletViewer() {
|
||||
}
|
||||
}
|
||||
|
||||
function handleCopyInvoice() {
|
||||
navigator.clipboard.writeText(generatedInvoice);
|
||||
setCopied(true);
|
||||
toast.success("Invoice copied to clipboard");
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
async function handleCopyInvoice() {
|
||||
try {
|
||||
await navigator.clipboard.writeText(generatedInvoice);
|
||||
setCopied(true);
|
||||
toast.success("Invoice copied to clipboard");
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
} catch (error) {
|
||||
console.error("Failed to copy invoice:", error);
|
||||
toast.error("Failed to copy to clipboard");
|
||||
}
|
||||
}
|
||||
|
||||
function resetReceiveDialog() {
|
||||
|
||||
Reference in New Issue
Block a user