import { useMegaStore } from "~/state/megaStore"; import { Card, Hr, SmallHeader, Button, InnerCard, VStack } from "~/components/layout"; import PeerConnectModal from "~/components/PeerConnectModal"; import { For, Show, Suspense, createEffect, createResource, createSignal, onCleanup } from "solid-js"; import { MutinyChannel, MutinyPeer } from "@mutinywallet/mutiny-wasm"; import { Collapsible, TextField } from "@kobalte/core"; import mempoolTxUrl from "~/utils/mempoolTxUrl"; import eify from "~/utils/eify"; import { ConfirmDialog } from "./Dialog"; import { showToast } from "./Toaster"; // TODO: hopefully I don't have to maintain this type forever but I don't know how to pass it around otherwise type RefetchPeersType = (info?: unknown) => MutinyPeer[] | Promise | null | undefined function PeerItem(props: { peer: MutinyPeer }) { const [state, _] = useMegaStore() const handleDisconnectPeer = async () => { const nodes = await state.node_manager?.list_nodes(); const firstNode = nodes[0] as string || "" if (props.peer.is_connected) { await state.node_manager?.disconnect_peer(firstNode, props.peer.pubkey); } else { await state.node_manager?.delete_peer(firstNode, props.peer.pubkey); } }; return (

{">"} {props.peer.alias ? props.peer.alias : props.peer.pubkey}

                        {JSON.stringify(props.peer, null, 2)}
                    
) } function PeersList() { const [state, _] = useMegaStore() const getPeers = async () => { return await state.node_manager?.list_peers() as Promise }; const [peers, { refetch }] = createResource(getPeers); createEffect(() => { // refetch peers every 5 seconds const interval = setTimeout(() => { refetch(); }, 5000); onCleanup(() => { clearInterval(interval); }); }) return ( <> Peers {/* By wrapping this in a suspense I don't cause the page to jump to the top */} No peers}> {(peer) => ( )} ) } function ConnectPeer(props: { refetchPeers: RefetchPeersType }) { const [state, _] = useMegaStore() const [value, setValue] = createSignal(""); const onSubmit = async (e: SubmitEvent) => { e.preventDefault(); const peerConnectString = value().trim(); const nodes = await state.node_manager?.list_nodes(); const firstNode = nodes[0] as string || "" await state.node_manager?.connect_to_peer(firstNode, peerConnectString) await props.refetchPeers() setValue(""); }; return (
Connect Peer Expecting something like mutiny:abc123...
) } type RefetchChannelsListType = (info?: unknown) => MutinyChannel[] | Promise | null | undefined function ChannelItem(props: { channel: MutinyChannel, network?: string }) { const [state, _] = useMegaStore() const [confirmOpen, setConfirmOpen] = createSignal(false); const [confirmLoading, setConfirmLoading] = createSignal(false); function handleCloseChannel() { setConfirmOpen(true); } async function confirmCloseChannel() { setConfirmLoading(true); try { await state.node_manager?.close_channel(props.channel.outpoint as string) } catch (e) { console.error(e); showToast(eify(e)); } setConfirmLoading(false); setConfirmOpen(false); } return (

{">"} {props.channel.peer}

                        {JSON.stringify(props.channel, null, 2)}
                    
Mempool Link
setConfirmOpen(false)} loading={confirmLoading()}>

Are you sure you want to close this channel?

) } function ChannelsList() { const [state, _] = useMegaStore() const getChannels = async () => { return await state.node_manager?.list_channels() as Promise }; const [channels, { refetch }] = createResource(getChannels); createEffect(() => { // refetch channels every 5 seconds const interval = setTimeout(() => { refetch(); }, 5000); onCleanup(() => { clearInterval(interval); }); }) const network = state.node_manager?.get_network(); return ( <> Channels {/* By wrapping this in a suspense I don't cause the page to jump to the top */} No channels}> {(channel) => ( )} ) } function OpenChannel(props: { refetchChannels: RefetchChannelsListType }) { const [state, _] = useMegaStore() const [creationError, setCreationError] = createSignal(); const [amount, setAmount] = createSignal(""); const [peerPubkey, setPeerPubkey] = createSignal(""); const [newChannel, setNewChannel] = createSignal(); const onSubmit = async (e: SubmitEvent) => { e.preventDefault(); // TODO: figure out why this doesn't catch the rust error // src/logging.rs:29 // ERROR: Could not create a signed transaction to open channel with: The invoice or address is on a different network. try { const pubkey = peerPubkey().trim(); const bigAmount = BigInt(amount()); const nodes = await state.node_manager?.list_nodes(); const firstNode = nodes[0] as string || "" const new_channel = await state.node_manager?.open_channel(firstNode, pubkey, bigAmount) setNewChannel(new_channel) await props.refetchChannels() setAmount(""); setPeerPubkey(""); } catch (e) { setCreationError(eify(e)) } }; return ( <>
Pubkey Amount
                    {JSON.stringify(newChannel()?.outpoint, null, 2)}
                
{newChannel()?.outpoint}
Mempool Link
{creationError()?.message}
) } function LnUrlAuth() { const [state, _] = useMegaStore() const [value, setValue] = createSignal(""); const onSubmit = async (e: SubmitEvent) => { e.preventDefault(); const lnurl = value().trim(); await state.node_manager?.lnurl_auth(0, lnurl) setValue(""); }; return (
LNURL Auth Expecting something like LNURL...
) } export default function KitchenSink() { return (


) }