c4d26d3b7f
Pending transactions that never complete now auto-cancel/expire after a configurable window (NostrConfig::expiry_secs, default 24h; lower it in nostr.toml to test). A sync-loop sweep (NostrService::expire_stale): - cancels stale outgoing sends + invoices we paid via GRIM's cancel_tx (WalletTask::Cancel), releasing the outputs they had locked; - annotates incoming payments / invoices we issued as Cancelled only (a late on-chain confirmation still wins); - marks pending incoming requests Expired. The activity feed and receipt now render "canceled" (this also fixes a latent bug where a manually-cancelled tx still showed "pending"). Receipt de-duplication: the To/From name rows are shown only when the counterparty has a real identity (petname or verified NIP-05); a bare npub now appears once, in the "nostr" row, instead of twice. 38 lib tests pass (2 new for the expiry bucket logic).