dummy redshift report

This commit is contained in:
Paul Miller
2023-04-30 12:19:23 -05:00
parent 2c6b94835c
commit 01df1dda24
3 changed files with 213 additions and 40 deletions

18
src/assets/icons/coin.svg Normal file
View File

@@ -0,0 +1,18 @@
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#a)">
<mask id="b" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<path fill-rule="evenodd" clip-rule="evenodd" d="M.667 8A7.333 7.333 0 0 1 8 .667c.368 0 .667.298.667.666v13.334a.667.667 0 0 1-.667.666A7.333 7.333 0 0 1 .667 8Zm6.666-5.963a6 6 0 0 0 0 11.926V2.037Z" fill="#fff"/>
<path d="M8 1.333a6.667 6.667 0 1 1 0 13.334V1.333Z" fill="#fff"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.333 1.333c0-.368.299-.666.667-.666a7.333 7.333 0 1 1 0 14.666.667.667 0 0 1-.667-.666V1.333Zm1.334.704v11.926a6 6 0 0 0 0-11.926Z" fill="#fff"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.333 4c0-.368.299-.667.667-.667h5a.667.667 0 0 1 0 1.334H3A.667.667 0 0 1 2.333 4ZM1 6.667C1 6.299 1.298 6 1.667 6H8a.667.667 0 0 1 0 1.333H1.667A.667.667 0 0 1 1 6.667Zm0 2.666c0-.368.298-.666.667-.666H8A.667.667 0 1 1 8 10H1.667A.667.667 0 0 1 1 9.333ZM2.333 12c0-.368.299-.667.667-.667h5a.667.667 0 0 1 0 1.334H3A.667.667 0 0 1 2.333 12Z" fill="#fff"/>
</mask>
<g mask="url(#b)">
<path d="M0 0h16v16H0V0Z" fill="#fff"/>
</g>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h16v16H0z"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -265,7 +265,7 @@ export default function Receive() {
<Match when={receiveState() === "paid" && paidState() === "lightning_paid"}>
<FullscreenModal title="Payment Received" open={!!paidState()} setOpen={(open: boolean) => { if (!open) clearAll() }}>
<div class="flex flex-col items-center gap-8">
<img src={party} alt="party" class="w-1/2 mx-auto max-w-[50vh] aspect-square" />
<img src={party} alt="party" class="w-1/2 mx-auto max-w-[50vh]" />
<Amount amountSats={paymentInvoice()?.amount_sats} showFiat />
</div>
</FullscreenModal>

View File

@@ -1,4 +1,4 @@
import { createEffect, createMemo, createResource, createSignal, For, Match, onMount, Suspense, Switch } from "solid-js";
import { Component, createEffect, createMemo, createResource, createSignal, For, Match, onMount, ParentComponent, Show, Suspense, Switch } from "solid-js";
import { CENTER_COLUMN, MISSING_LABEL, REDSHIFT_LABEL, RIGHT_COLUMN, THREE_COLUMNS, UtxoItem } from "~/components/Activity";
import { Card, DefaultMain, LargeHeader, LoadingSpinner, NiceP, NodeManagerGuard, SafeArea, SmallAmount, SmallHeader, VStack } from "~/components/layout";
import { BackLink } from "~/components/layout/BackLink";
@@ -6,37 +6,164 @@ import { StyledRadioGroup } from "~/components/layout/Radio";
import NavBar from "~/components/NavBar";
import { useMegaStore } from "~/state/megaStore";
import wave from "~/assets/wave.gif"
import utxoIcon from '~/assets/icons/coin.svg';
import { Button } from "~/components/layout/Button";
import { ProgressBar } from "~/components/layout/ProgressBar";
import { MutinyChannel } from "@mutinywallet/mutiny-wasm";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import { Amount } from "~/components/Amount";
type ShiftOption = "utxo" | "lightning"
type ShiftStage = "choose" | "observe" | "success" | "failure"
const SHIFT_OPTIONS = [{ value: "utxo", label: "UTXO", caption: "Trade your UTXO for a fresh UTXO" }, { value: "lightning", label: "Lightning", caption: "Convert your UTXO into Lightning" }]
type OutPoint = string; // Replace with the actual TypeScript type for OutPoint
type RedshiftStatus = any; // Replace with the actual TypeScript type for RedshiftStatus
type RedshiftRecipient = any; // Replace with the actual TypeScript type for RedshiftRecipient
type PublicKey = any; // Replace with the actual TypeScript type for PublicKey
import receive from '~/assets/icons/receive.svg';
import { Button } from "~/components/layout/Button";
import { ProgressBar } from "~/components/layout/ProgressBar";
interface RedshiftResult {
id: bigint;
input_utxo: OutPoint;
status: RedshiftStatus;
recipient: RedshiftRecipient;
output_utxo?: OutPoint;
introduction_channel?: OutPoint;
output_channel?: OutPoint;
introduction_node: PublicKey;
amount_sats: bigint;
change_amt?: bigint;
fees_paid: bigint;
}
const dummyRedshift: RedshiftResult = {
id: BigInt(1),
input_utxo: "44036599c37d590899e8d5d92086028695d2c2966fdc354ce1da9a9eac610a53:1",
status: {}, // Replace with a dummy value for RedshiftStatus
recipient: {}, // Replace with a dummy value for RedshiftRecipient
output_utxo: "44036599c37d590899e8d5d92086028695d2c2966fdc354ce1da9a9eac610a53:1",
introduction_channel: "a7773e57f8595848a635e9af105927cac9ecaf292d71a76456ae0455bd3c9c64:0",
output_channel: "a7773e57f8595848a635e9af105927cac9ecaf292d71a76456ae0455bd3c9c64:0",
introduction_node: {}, // Replace with a dummy value for PublicKey
amount_sats: BigInt(1000000),
change_amt: BigInt(12345),
fees_paid: BigInt(2500),
};
function RedshiftReport(props: { redshift: RedshiftResult }) {
const [state, _actions] = useMegaStore();
const getUtXos = async () => {
console.log("Getting utxos");
return await state.node_manager?.list_utxos() as UtxoItem[];
}
function findUtxoByOutpoint(outpoint?: string, utxos: UtxoItem[] = []): UtxoItem | undefined {
if (!outpoint) return undefined;
return utxos.find((utxo) => utxo.outpoint === outpoint);
}
const [utxos, { refetch: _refetchUtxos }] = createResource(getUtXos);
// <VStack>
// {/* {JSON.stringify(props.channel, null, 2)} */}
// <Amount amountSats={props.channel.size} />
// <KV key={"Peer"} value={props.channel.peer} />
// <KV key={"Outpoint"} value={props.channel.outpoint} />
// {/* TODO: don't hardcode this */}
// <a class="" href={mempoolTxUrl(props.channel.outpoint?.split(":")[0], "signet")} target="_blank" rel="noreferrer">
// View on mempool
// </a>
// </VStack>
const inputUtxo = createMemo(() => {
console.log(utxos())
const foundUtxo = findUtxoByOutpoint(props.redshift.input_utxo, utxos())
console.log("Found utxo:", foundUtxo)
return foundUtxo
})
const outputUtxo = createMemo(() => {
return findUtxoByOutpoint(props.redshift.output_utxo, utxos())
})
return (
<VStack biggap>
<VStack>
<NiceP>We did it. Here's your new UTXO:</NiceP>
<Show when={utxos() && outputUtxo()}>
<Card>
<Utxo item={outputUtxo()!} redshifted />
</Card>
</Show>
</VStack>
<VStack>
<NiceP>What happened?</NiceP>
<Card>
<VStack biggap>
<KV key="Input utxo">
<Show when={utxos() && inputUtxo()}>
<Utxo item={inputUtxo()!} />
</Show>
</KV>
<KV key="Starting amount">
<Amount amountSats={props.redshift.amount_sats} />
</KV>
<KV key="Fees paid">
<Amount amountSats={props.redshift.fees_paid} />
</KV>
<KV key="Change">
<Amount amountSats={props.redshift.change_amt} />
</KV>
<KV key="Outbound channel">
<VStack>
<pre class="whitespace-pre-wrap break-all">{props.redshift.introduction_channel}</pre>
<a class="" href={mempoolTxUrl(props.redshift.introduction_channel?.split(":")[0], "signet")} target="_blank" rel="noreferrer">
View on mempool
</a>
</VStack>
</KV>
<KV key="Return channel">
<VStack>
<pre class="whitespace-pre-wrap break-all">{props.redshift.output_channel}</pre>
<a class="" href={mempoolTxUrl(props.redshift.output_channel?.split(":")[0], "signet")} target="_blank" rel="noreferrer">
View on mempool
</a>
</VStack>
</KV>
</VStack>
</Card>
<SmallHeader></SmallHeader>
</VStack>
</VStack>
)
}
const SHIFT_OPTIONS = [{ value: "utxo", label: "UTXO", caption: "Trade your UTXO for a fresh UTXO" }, { value: "lightning", label: "Lightning", caption: "Convert your UTXO into Lightning" }]
export function Utxo(props: { item: UtxoItem, onClick?: () => void, redshifted?: boolean }) {
const spent = createMemo(() => props.item.is_spent);
return (
<>
<div class={`${THREE_COLUMNS} ${props.redshifted && "bg-gradient-to-t from-m-red/10 to-transparent rounded-lg"}`} onClick={props.onClick}>
<img src={receive} alt="receive arrow" />
<div class={THREE_COLUMNS} onClick={props.onClick}>
<div class="flex items-center">
<img src={utxoIcon} alt="coin" />
</div>
<div class={CENTER_COLUMN}>
<div class="flex gap-2">
{props.redshifted && <h2 class={REDSHIFT_LABEL}>RS</h2>}
{!props.item.redshifted && <h2 class={MISSING_LABEL}>Unknown</h2>}
<Show when={props.redshifted} fallback={<h2 class={MISSING_LABEL}>Unknown</h2>}>
<h2 class={REDSHIFT_LABEL}>Redshift</h2>
</Show>
</div>
<SmallAmount amount={props.item.txout.value} />
</div>
<div class={RIGHT_COLUMN}>
<SmallHeader class={props.item?.is_spent ? "text-m-red" : "text-m-green"}>
{props.item?.is_spent ? "SPENT" : "UNSPENT"}
{/* {props.item?.is_spent ? "SPENT" : "UNSPENT"} */}
</SmallHeader>
</div>
</div>
@@ -49,28 +176,14 @@ const FAKE_STATES = ["Creating a new node", "Opening a channel", "Sending funds
function ShiftObserver(props: { setShiftStage: (stage: ShiftStage) => void }, utxo: UtxoItem) {
const [fakeStage, setFakeStage] = createSignal(2);
// onMount(() => {
// const interval = setInterval(() => {
// console.log("intervaling")
// if (fakeStage() === FAKE_STATES.length - 1) {
// clearInterval(interval)
// props.setShiftStage("success");
// } else {
// setFakeStage((fakeStage() + 1))
// }
// // cont()
// }, 1000)
// // return () => clearInterval(interval);
// })
const [sentAmount, setSentAmount] = createSignal(0);
onMount(() => {
const interval = setInterval(() => {
if (sentAmount() === 200000) {
// clearInterval(interval)
// props.setShiftStage("success");
setSentAmount((0))
clearInterval(interval)
props.setShiftStage("success");
// setSentAmount((0))
} else {
setSentAmount((sentAmount() + 50000))
@@ -92,22 +205,67 @@ function ShiftObserver(props: { setShiftStage: (stage: ShiftStage) => void }, ut
)
}
const KV: ParentComponent<{ key: string }> = (props) => {
return (
<div class="flex flex-col gap-2">
<p class="text-sm font-semibold uppercase">{props.key}</p>
{props.children}
</div>
)
}
const KVPre: ParentComponent<{ key: string }> = (props) => {
return (
<div class="flex flex-col gap-2">
<p class="text-sm font-semibold uppercase">{props.key}</p>
<pre class="whitespace-pre-wrap break-all">
{props.children}
</pre>
</div>
)
}
function SingleChannel(props: { channel: MutinyChannel }) {
return (
<VStack>
{/* {JSON.stringify(props.channel, null, 2)} */}
<Amount amountSats={props.channel.size} />
<KV key={"Peer"}>{props.channel.peer}</KV>
<KV key={"Outpoint"}>{props.channel.outpoint}</KV>
{/* TODO: don't hardcode this */}
<a class="" href={mempoolTxUrl(props.channel.outpoint?.split(":")[0], "signet")} target="_blank" rel="noreferrer">
View on mempool
</a>
</VStack>
)
}
export default function Redshift() {
const [state, _actions] = useMegaStore();
const [shiftStage, setShiftStage] = createSignal<ShiftStage>("observe");
const [shiftStage, setShiftStage] = createSignal<ShiftStage>("choose");
const [shiftType, setShiftType] = createSignal<ShiftOption>("utxo");
const [chosenUtxo, setChosenUtxo] = createSignal<UtxoItem>();
const getUtXos = async () => {
console.log("Getting utxos");
const utxos = await state.node_manager?.list_utxos() as UtxoItem[];
return utxos;
return await state.node_manager?.list_utxos() as UtxoItem[];
}
const getChannels = async () => {
console.log("Getting channels");
await state.node_manager?.sync()
const channels = await state.node_manager?.list_channels() as Promise<MutinyChannel[]>;
console.log(channels)
return channels
}
const [utxos, { refetch: _refetchUtxos }] = createResource(getUtXos);
const [channels, { refetch: _refetchChannels }] = createResource(getChannels);
createEffect(() => {
if (chosenUtxo()) {
@@ -167,7 +325,7 @@ export default function Redshift() {
<Match when={utxos.state === "ready" && utxos().length >= 0}>
<For each={utxos()}>
{(utxo) =>
<Utxo item={utxo} />
<Utxo redshifted item={utxo} />
}
</For>
</Match>
@@ -180,11 +338,8 @@ export default function Redshift() {
<ShiftObserver setShiftStage={setShiftStage} />
</Match>
<Match when={shiftStage() === "success"}>
<VStack>
<NiceP>We did it. Here's your new UTXO:</NiceP>
<Card>
<Utxo item={chosenUtxo() ?? chosenUtxo()!} redshifted />
</Card>
<VStack biggap>
<RedshiftReport redshift={dummyRedshift} />
<Button intent="red" onClick={resetState}>Nice</Button>
</VStack>
</Match>