import { InfoIcon } from "lucide-react"; import { ChannelDropdownMenu } from "src/components/channels/ChannelDropdownMenu"; import { ChannelWarning } from "src/components/channels/ChannelWarning"; import { FormattedBitcoinAmount } from "src/components/FormattedBitcoinAmount"; import { Badge } from "src/components/ui/badge.tsx"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "src/components/ui/card"; import { Progress } from "src/components/ui/progress.tsx"; import { Separator } from "src/components/ui/separator"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "src/components/ui/tooltip"; import { useNodeDetails } from "src/hooks/useNodeDetails"; import { formatAmount } from "src/lib/utils.ts"; import { Channel, LongUnconfirmedZeroConfChannel } from "src/types"; type ChannelsCardsProps = { channels?: Channel[]; longUnconfirmedZeroConfChannels: LongUnconfirmedZeroConfChannel[]; }; export function ChannelsCards({ channels, longUnconfirmedZeroConfChannels, }: ChannelsCardsProps) { if (!channels?.length) { return null; } return ( Channels {channels .sort((a, b) => a.localBalanceMsat + a.remoteBalanceMsat > b.localBalanceMsat + b.remoteBalanceMsat ? -1 : 1 ) .map((channel, index) => { const unconfirmedChannel = longUnconfirmedZeroConfChannels.find( (uc) => uc.id === channel.id ); return ( 0} channel={channel} unconfirmedChannel={unconfirmedChannel} hasMultipleChannels={channels.length > 1} /> ); })} ); } type ChannelCardProps = { channel: Channel; unconfirmedChannel: LongUnconfirmedZeroConfChannel | undefined; addSeparator: boolean; hasMultipleChannels: boolean; }; function ChannelCard({ channel, unconfirmedChannel, addSeparator, hasMultipleChannels, }: ChannelCardProps) { const { data: node } = useNodeDetails(channel.remotePubkey); const alias = node?.alias || "Unknown"; const capacityMsat = channel.localBalanceMsat + channel.remoteBalanceMsat; return ( <> {addSeparator && }
{alias}

Status

{channel.status == "online" ? ( unconfirmedChannel ? ( Unconfirmed ) : ( Online ) ) : channel.status == "opening" ? ( Opening ) : ( Offline )}
Type
The type of lightning channel, By default private channel is recommended. If you a podcaster or musician and expect to receive keysend or Value4Value payments you will need a public channel.

{channel.public ? "Public" : "Private"}

Capacity
Total Spending and Receiving capacity of your lightning channel.

Reserve
Funds each participant sets aside to discourage cheating by ensuring each party has something at stake. This reserve cannot be spent during the channel's lifetime and typically amounts to 1% of the channel capacity. The reserve will automatically be filled when payments are received on the channel.

{channel.localBalanceMsat < channel.unspendablePunishmentReserveSat * 1000 && ( <> {formatAmount( Math.min( channel.localBalanceMsat, channel.unspendablePunishmentReserveSat * 1000 ) )}{" "} /{" "} )}

Spending

Receiving

); }