import { Collapsible, TextField } from "@kobalte/core"; import { MutinyChannel, MutinyPeer } from "@mutinywallet/mutiny-wasm"; import { createResource, createSignal, For, Match, Show, Suspense, Switch } from "solid-js"; import { Button, ConfirmDialog, ExternalLink, Hr, InnerCard, MiniStringShower, ResetRouter, Restart, ResyncOnchain, showToast, VStack } from "~/components"; import { useI18n } from "~/i18n/context"; import { Network } from "~/logic/mutinyWalletSetup"; import { useMegaStore } from "~/state/megaStore"; import { eify, mempoolTxUrl } from "~/utils"; // 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 i18n = useI18n(); const [state, _] = useMegaStore(); const handleDisconnectPeer = async () => { const nodes = await state.mutiny_wallet?.list_nodes(); const firstNode = (nodes[0] as string) || ""; if (props.peer.is_connected) { await state.mutiny_wallet?.disconnect_peer( firstNode, props.peer.pubkey ); } else { await state.mutiny_wallet?.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 i18n = useI18n(); const [state, _] = useMegaStore(); const getPeers = async () => { return (await state.mutiny_wallet?.list_peers()) as Promise< MutinyPeer[] >; }; const [peers, { refetch }] = createResource(getPeers); return ( <> {/* By wrapping this in a suspense I don't cause the page to jump to the top */} {i18n.t( "settings.admin.kitchen_sink.no_peers" )} } > {(peer) => } ); } function ConnectPeer(props: { refetchPeers: RefetchPeersType }) { const i18n = useI18n(); const [state, _] = useMegaStore(); const [value, setValue] = createSignal(""); const onSubmit = async (e: SubmitEvent) => { e.preventDefault(); const peerConnectString = value().trim(); const nodes = await state.mutiny_wallet?.list_nodes(); const firstNode = (nodes[0] as string) || ""; await state.mutiny_wallet?.connect_to_peer( firstNode, peerConnectString ); await props.refetchPeers(); setValue(""); }; return (
{i18n.t("settings.admin.kitchen_sink.connect_peer")} {i18n.t("settings.admin.kitchen_sink.expect_a_value")}
); } type RefetchChannelsListType = ( info?: unknown ) => MutinyChannel[] | Promise | null | undefined; type PendingChannelAction = "close" | "force_close" | "abandon"; function ChannelItem(props: { channel: MutinyChannel; network?: Network }) { const i18n = useI18n(); const [state, _] = useMegaStore(); const [pendingChannelAction, setPendingChannelAction] = createSignal(); const [confirmLoading, setConfirmLoading] = createSignal(false); async function confirmChannelAction() { const action = pendingChannelAction(); if (!action) return; setConfirmLoading(true); try { await state.mutiny_wallet?.close_channel( props.channel.outpoint as string, action === "force_close", action === "abandon" ); } catch (e) { console.error(e); showToast(eify(e)); } setConfirmLoading(false); setPendingChannelAction(undefined); } return (

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

                        {JSON.stringify(props.channel, null, 2)}
                    
{i18n.t("common.view_transaction")}
setPendingChannelAction(undefined)} loading={confirmLoading()} >

{i18n.t( "settings.admin.kitchen_sink.confirm_close_channel" )}

{i18n.t( "settings.admin.kitchen_sink.confirm_force_close" )}

{i18n.t( "settings.admin.kitchen_sink.confirm_abandon_channel" )}

); } function ChannelsList() { const i18n = useI18n(); const [state, _] = useMegaStore(); const getChannels = async () => { return (await state.mutiny_wallet?.list_channels()) as Promise< MutinyChannel[] >; }; const [channels, { refetch }] = createResource(getChannels); const network = state.mutiny_wallet?.get_network() as Network; return ( <> {/* By wrapping this in a suspense I don't cause the page to jump to the top */} {i18n.t( "settings.admin.kitchen_sink.no_channels" )} } > {(channel) => ( )} ); } function OpenChannel(props: { refetchChannels: RefetchChannelsListType }) { const i18n = useI18n(); 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.mutiny_wallet?.list_nodes(); const firstNode = (nodes[0] as string) || ""; const new_channel = await state.mutiny_wallet?.open_channel( firstNode, pubkey, bigAmount ); setNewChannel(new_channel); await props.refetchChannels(); setAmount(""); setPeerPubkey(""); } catch (e) { setCreationError(eify(e)); } }; const network = state.mutiny_wallet?.get_network() as Network; return ( <>
{i18n.t("settings.admin.kitchen_sink.pubkey")} {i18n.t("settings.admin.kitchen_sink.amount")}
                    {JSON.stringify(newChannel()?.outpoint, null, 2)}
                
{newChannel()?.outpoint}
{i18n.t("common.view_transaction")}
{creationError()?.message}
); } function ListNodes() { const i18n = useI18n(); const [state, _] = useMegaStore(); const getNodeIds = async () => { const nodes = await state.mutiny_wallet?.list_nodes(); return nodes as string[]; }; const [nodeIds] = createResource(getNodeIds); return ( {i18n.t("settings.admin.kitchen_sink.no_nodes")} } > {(nodeId) => } ); } export function KitchenSink() { return ( <>





); }