fix a stack overflow in the wallet copy button

Mine, from the clipboard sweep. format.ts exported copyToClipboard wrapping
navigator.clipboard; the sweep replaced the body call with copyToClipboard(value),
so the function called itself. CopyField.tsx is the caller, so every copy button in
the Wallet was an infinite recursion.

Removed the wrapper rather than repointing it — helpers/clipboard already does more
(execCommand fallback on an insecure origin) and CopyField imports it directly now.

Found by finally running tsgo, in the officerdev-test tree, which has node_modules.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-13 12:33:23 +00:00
co-authored by Claude Opus 5
parent bf7e919593
commit d6f01862fe
2 changed files with 9 additions and 11 deletions
@@ -1,6 +1,6 @@
import { useState } from 'react'; import { useState } from 'react';
import { Check, Copy } from 'lucide-react'; import { Check, Copy } from 'lucide-react';
import { copyToClipboard } from './format'; import { copyToClipboard } from 'helpers/clipboard';
// A read-only value with a copy button — addresses, invoices, txids, xpubs. // A read-only value with a copy button — addresses, invoices, txids, xpubs.
// //
@@ -1,5 +1,5 @@
import type { InvoiceState, PaymentStatus } from './shared'; import type { InvoiceState, PaymentStatus } from './shared';
import { copyToClipboard } from 'helpers/clipboard';
// Display formatting for the Wallet panels. // Display formatting for the Wallet panels.
// //
@@ -142,12 +142,10 @@ export const PAYMENT_TONES: Record<PaymentStatus, string> = {
failed: 'bg-destructive/10 text-destructive', failed: 'bg-destructive/10 text-destructive',
}; };
/** Clipboard with a graceful failure — an insecure origin has no navigator.clipboard at all. */ // `copyToClipboard` used to be re-exported from here, wrapping navigator.clipboard with a try/catch. The
export async function copyToClipboard(value: string): Promise<boolean> { // helper in `helpers/clipboard` now does that and more — it falls back to execCommand on an insecure
try { // origin, where navigator.clipboard does not exist at all — so callers import it from there directly.
await copyToClipboard(value); //
return true; // Removed rather than left as a pass-through: the wrapper had become `copyToClipboard` calling
} catch { // `copyToClipboard`, which is a stack overflow on any Wallet copy button. Every re-export is a chance for
return false; // exactly that, and this file is about formatting.
}
}