PendingClosedChannelsAlert.tsx raw
1 import { ExternalLinkIcon, HourglassIcon } from "lucide-react";
2 import ExternalLink from "src/components/ExternalLink";
3 import { FormattedBitcoinAmount } from "src/components/FormattedBitcoinAmount";
4 import { Alert, AlertDescription, AlertTitle } from "src/components/ui/alert";
5 import { useInfo } from "src/hooks/useInfo";
6 import { useNodeDetails } from "src/hooks/useNodeDetails";
7 import { OnchainBalanceResponse, PendingBalancesDetails } from "src/types";
8
9 type PendingClosedChannelsAlertProps = {
10 balance: OnchainBalanceResponse;
11 };
12
13 export function PendingClosedChannelsAlert({
14 balance,
15 }: PendingClosedChannelsAlertProps) {
16 if (balance.pendingBalancesFromChannelClosuresSat <= 0) {
17 return null;
18 }
19
20 const pendingDetails = [
21 ...balance.pendingBalancesDetails,
22 ...balance.pendingSweepBalancesDetails,
23 ];
24
25 return (
26 <Alert>
27 <HourglassIcon />
28 <AlertTitle>Pending Closed Channels</AlertTitle>
29 <AlertDescription className="block">
30 You have{" "}
31 <FormattedBitcoinAmount
32 amountMsat={balance.pendingBalancesFromChannelClosuresSat * 1000}
33 />{" "}
34 pending from closed channels
35 {pendingDetails.length > 0 && (
36 <>
37 {" "}
38 with
39 {pendingDetails.map((details, index) => (
40 <PendingBalancesDetailsItem
41 key={`${details.fundingTxId}:${details.fundingTxVout}`}
42 details={details}
43 showSeparator={index < pendingDetails.length - 1}
44 />
45 ))}
46 </>
47 )}
48 . Once spendable again these will become available in your on-chain
49 balance. Funds from channels that were force closed may take up to 2
50 weeks to become available.{" "}
51 <ExternalLink
52 to="https://guides.getalby.com/user-guide/alby-hub/faq/why-was-my-lightning-channel-closed-and-what-to-do-next"
53 className="underline"
54 >
55 Learn more
56 </ExternalLink>
57 </AlertDescription>
58 </Alert>
59 );
60 }
61
62 type PendingBalancesDetailsItemProps = {
63 details: PendingBalancesDetails;
64 showSeparator: boolean;
65 };
66
67 function PendingBalancesDetailsItem({
68 details,
69 showSeparator,
70 }: PendingBalancesDetailsItemProps) {
71 const { data: info } = useInfo();
72 const { data: nodeDetails } = useNodeDetails(details.nodeId);
73
74 return (
75 <span className="inline">
76
77 <ExternalLink
78 to={`https://amboss.space/node/${details.nodeId}`}
79 className="underline"
80 >
81 {nodeDetails?.alias || "Unknown"}
82 <ExternalLinkIcon className="ml-1 inline h-4 w-4" />
83 </ExternalLink>{" "}
84 (<FormattedBitcoinAmount amountMsat={details.amountSat * 1000} />
85 )
86 <ExternalLink
87 to={`${info?.mempoolUrl}/tx/${details.fundingTxId}#flow=&vout=${details.fundingTxVout}`}
88 className="underline"
89 >
90 funding tx
91 <ExternalLinkIcon className="ml-1 inline h-4 w-4" />
92 </ExternalLink>
93 {showSeparator && ","}
94 </span>
95 );
96 }
97