mirror of
https://github.com/aljazceru/mutiny-web.git
synced 2025-12-23 17:14:23 +01:00
pending nwc approve / deny
This commit is contained in:
187
src/components/PendingNwc.tsx
Normal file
187
src/components/PendingNwc.tsx
Normal file
@@ -0,0 +1,187 @@
|
||||
import { NwcProfile } from "@mutinywallet/mutiny-wasm";
|
||||
import { timeAgo } from "~/utils/prettyPrintTime";
|
||||
import { Card, LoadingSpinner, VStack } from "./layout";
|
||||
import bolt from "~/assets/icons/bolt.svg";
|
||||
import {
|
||||
For,
|
||||
Match,
|
||||
Show,
|
||||
Suspense,
|
||||
Switch,
|
||||
createEffect,
|
||||
createResource,
|
||||
createSignal
|
||||
} from "solid-js";
|
||||
import { useMegaStore } from "~/state/megaStore";
|
||||
|
||||
import greenCheck from "~/assets/icons/green-check.svg";
|
||||
import redClose from "~/assets/icons/red-close.svg";
|
||||
import { ActivityAmount } from "./ActivityItem";
|
||||
import { InfoBox } from "./InfoBox";
|
||||
import eify from "~/utils/eify";
|
||||
import { A } from "solid-start";
|
||||
|
||||
type PendingItem = {
|
||||
id: string;
|
||||
name_of_connection: string;
|
||||
date?: bigint;
|
||||
amount_sats?: bigint;
|
||||
};
|
||||
|
||||
export function PendingNwc() {
|
||||
const [state, _actions] = useMegaStore();
|
||||
|
||||
const [error, setError] = createSignal<Error>();
|
||||
|
||||
const [pendingRequests, { refetch }] = createResource(async () => {
|
||||
const profiles: NwcProfile[] =
|
||||
await state.mutiny_wallet?.get_nwc_profiles();
|
||||
|
||||
const pending = await state.mutiny_wallet?.get_pending_nwc_invoices();
|
||||
|
||||
const pendingItems: PendingItem[] = [];
|
||||
|
||||
for (const p of pending) {
|
||||
const profile = profiles.find((pro) => pro.index === p.index);
|
||||
|
||||
if (profile) {
|
||||
pendingItems.push({
|
||||
id: p.id,
|
||||
name_of_connection: profile.name,
|
||||
date: p.expiry,
|
||||
amount_sats: p.amount_sats
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log(pendingItems);
|
||||
|
||||
return pendingItems;
|
||||
});
|
||||
|
||||
const [paying, setPaying] = createSignal<string>("");
|
||||
|
||||
async function payItem(item: PendingItem) {
|
||||
try {
|
||||
setPaying(item.id);
|
||||
const nodes = await state.mutiny_wallet?.list_nodes();
|
||||
await state.mutiny_wallet?.approve_invoice(item.id, nodes[0]);
|
||||
} catch (e) {
|
||||
setError(eify(e));
|
||||
console.error(e);
|
||||
} finally {
|
||||
setPaying("");
|
||||
refetch();
|
||||
}
|
||||
}
|
||||
|
||||
async function rejectItem(item: PendingItem) {
|
||||
try {
|
||||
setPaying(item.id);
|
||||
await state.mutiny_wallet?.deny_invoice(item.id);
|
||||
} catch (e) {
|
||||
setError(eify(e));
|
||||
console.error(e);
|
||||
} finally {
|
||||
setPaying("");
|
||||
refetch();
|
||||
}
|
||||
}
|
||||
|
||||
createEffect(() => {
|
||||
// When there's an error wait five seconds and then clear it
|
||||
if (error()) {
|
||||
setTimeout(() => {
|
||||
setError(undefined);
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Suspense>
|
||||
<Show when={pendingRequests() && pendingRequests()!.length > 0}>
|
||||
<Card title="Pending Requests">
|
||||
<div class="p-1" />
|
||||
<VStack>
|
||||
<Show when={error()}>
|
||||
<InfoBox accent="red">{error()?.message}</InfoBox>
|
||||
</Show>
|
||||
<For each={pendingRequests()}>
|
||||
{(pendingItem) => (
|
||||
<div class="grid grid-cols-[auto_minmax(0,_1fr)_minmax(0,_max-content)_auto] items-center pb-4 gap-4 border-b border-neutral-800 last:border-b-0">
|
||||
<img
|
||||
class="w-[1rem]"
|
||||
src={bolt}
|
||||
alt="onchain"
|
||||
/>
|
||||
<div class="flex flex-col">
|
||||
<span class="text-base font-semibold truncate">
|
||||
{pendingItem.name_of_connection}
|
||||
</span>
|
||||
<time class="text-sm text-neutral-500">
|
||||
Expires {timeAgo(pendingItem.date)}
|
||||
</time>
|
||||
</div>
|
||||
<div>
|
||||
<ActivityAmount
|
||||
amount={
|
||||
pendingItem.amount_sats?.toString() ||
|
||||
"0"
|
||||
}
|
||||
price={state.price}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex gap-2 w-[5rem]">
|
||||
<Switch>
|
||||
<Match
|
||||
when={
|
||||
paying() !== pendingItem.id
|
||||
}
|
||||
>
|
||||
<button
|
||||
onClick={() =>
|
||||
payItem(pendingItem)
|
||||
}
|
||||
>
|
||||
<img
|
||||
class="h-[2.5rem] w-[2.5rem]"
|
||||
src={greenCheck}
|
||||
alt="Approve"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
onClick={() =>
|
||||
rejectItem(pendingItem)
|
||||
}
|
||||
>
|
||||
<img
|
||||
class="h-[2rem] w-[2rem]"
|
||||
src={redClose}
|
||||
alt="Reject"
|
||||
/>
|
||||
</button>
|
||||
</Match>
|
||||
<Match
|
||||
when={
|
||||
paying() === pendingItem.id
|
||||
}
|
||||
>
|
||||
<LoadingSpinner wide />
|
||||
</Match>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</For>
|
||||
</VStack>
|
||||
<A
|
||||
href="/settings/connections"
|
||||
class="text-m-red active:text-m-red/80 font-semibold no-underline self-center"
|
||||
>
|
||||
Configure
|
||||
</A>
|
||||
</Card>
|
||||
</Show>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user