mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-04-12 05:39:18 +02:00
improve wallet receive view
This commit is contained in:
parent
458c18db08
commit
a973a6dbb1
@ -1,64 +0,0 @@
|
||||
import { useState } from "react";
|
||||
import { useActionHub } from "applesauce-react/hooks";
|
||||
import { Button, Flex, Spacer, Textarea, useToast } from "@chakra-ui/react";
|
||||
import { getDecodedToken, Token } from "@cashu/cashu-ts";
|
||||
import { ReceiveToken } from "applesauce-wallet/actions";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
import SimpleView from "../../components/layout/presets/simple-view";
|
||||
import { getCashuWallet } from "../../services/cashu-mints";
|
||||
import RouterLink from "../../components/router-link";
|
||||
import QRCodeScannerButton from "../../components/qr-code/qr-code-scanner-button";
|
||||
|
||||
export default function WalletReceiveView() {
|
||||
const location = useLocation();
|
||||
const actions = useActionHub();
|
||||
const navigate = useNavigate();
|
||||
const toast = useToast();
|
||||
|
||||
const [input, setInput] = useState(location.state?.input ?? "");
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const receive = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const decoded = getDecodedToken(input.trim());
|
||||
const originalAmount = decoded.proofs.reduce((t, p) => t + p.amount, 0);
|
||||
|
||||
// swap tokens
|
||||
const wallet = await getCashuWallet(decoded.mint);
|
||||
const proofs = await wallet.receive(decoded);
|
||||
const token: Token = { mint: decoded.mint, proofs };
|
||||
|
||||
const amount = token.proofs.reduce((t, p) => t + p.amount, 0);
|
||||
const fee = originalAmount - amount;
|
||||
|
||||
// save new tokens
|
||||
await actions.run(ReceiveToken, token, undefined, fee || undefined);
|
||||
|
||||
toast({ status: "success", description: `Received ${amount} sats` });
|
||||
|
||||
navigate("/wallet");
|
||||
} catch (error) {
|
||||
if (error instanceof Error) toast({ status: "error", description: error.message });
|
||||
console.log(error);
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<SimpleView title="Receive" maxW="2xl" center>
|
||||
<Textarea value={input} onChange={(e) => setInput(e.target.value)} placeholder="cashuB...." rows={10} />
|
||||
<Flex gap="2">
|
||||
<Button as={RouterLink} to="/wallet">
|
||||
Back
|
||||
</Button>
|
||||
<Spacer />
|
||||
<QRCodeScannerButton onResult={setInput} />
|
||||
<Button colorScheme="primary" onClick={receive} isLoading={loading}>
|
||||
Receive
|
||||
</Button>
|
||||
</Flex>
|
||||
</SimpleView>
|
||||
);
|
||||
}
|
68
src/views/wallet/receive/index.tsx
Normal file
68
src/views/wallet/receive/index.tsx
Normal file
@ -0,0 +1,68 @@
|
||||
import { useState } from "react";
|
||||
import { Button, Flex, IconButton, Spacer, Textarea, useToast } from "@chakra-ui/react";
|
||||
import { getDecodedToken, getEncodedToken } from "@cashu/cashu-ts";
|
||||
import { decodeTokenFromEmojiString } from "applesauce-wallet/helpers";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
import SimpleView from "../../../components/layout/presets/simple-view";
|
||||
import RouterLink from "../../../components/router-link";
|
||||
import QRCodeScannerButton from "../../../components/qr-code/qr-code-scanner-button";
|
||||
import Clipboard from "../../../components/icons/clipboard";
|
||||
|
||||
export default function WalletReceiveView() {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const toast = useToast();
|
||||
|
||||
const [input, setInput] = useState(location.state?.input ?? "");
|
||||
|
||||
const handleScannerResult = (result: string) => {
|
||||
try {
|
||||
const token = getDecodedToken(result.trim());
|
||||
navigate("/wallet/receive/token", { state: { token: getEncodedToken(token) }, replace: true });
|
||||
} catch (error) {
|
||||
setInput(result);
|
||||
}
|
||||
};
|
||||
|
||||
const receive = () => {
|
||||
try {
|
||||
const token = getDecodedToken(input.trim());
|
||||
navigate("/wallet/receive/token", { state: { token: getEncodedToken(token) }, replace: true });
|
||||
} catch (error) {
|
||||
if (error instanceof Error) toast({ status: "error", description: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SimpleView title="Receive" maxW="2xl" center>
|
||||
<Textarea
|
||||
value={input}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
onPaste={(e) => {
|
||||
try {
|
||||
const token = decodeTokenFromEmojiString(e.clipboardData.getData("text"));
|
||||
if (token) navigate("/wallet/receive/token", { state: { token: getEncodedToken(token) } });
|
||||
} catch (error) {}
|
||||
}}
|
||||
placeholder="cashuB...."
|
||||
rows={10}
|
||||
/>
|
||||
<Flex gap="2">
|
||||
<Button as={RouterLink} to="/wallet">
|
||||
Back
|
||||
</Button>
|
||||
<Spacer />
|
||||
<IconButton
|
||||
icon={<Clipboard boxSize={5} />}
|
||||
aria-label="Paste"
|
||||
onClick={async () => handleScannerResult(await navigator.clipboard.readText())}
|
||||
/>
|
||||
<QRCodeScannerButton onResult={handleScannerResult} />
|
||||
<Button colorScheme="primary" onClick={receive}>
|
||||
Receive
|
||||
</Button>
|
||||
</Flex>
|
||||
</SimpleView>
|
||||
);
|
||||
}
|
70
src/views/wallet/receive/token.tsx
Normal file
70
src/views/wallet/receive/token.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
import { Flex, Spacer, Button, Text, Card, CardBody, useToast, useDisclosure, ButtonGroup } from "@chakra-ui/react";
|
||||
import { useLocation, Navigate, useNavigate } from "react-router-dom";
|
||||
import { useActionHub } from "applesauce-react/hooks";
|
||||
import { getDecodedToken, Token } from "@cashu/cashu-ts";
|
||||
import { ReceiveToken } from "applesauce-wallet/actions";
|
||||
|
||||
import SimpleView from "../../../components/layout/presets/simple-view";
|
||||
import RouterLink from "../../../components/router-link";
|
||||
import CashuMintFavicon from "../../../components/cashu/cashu-mint-favicon";
|
||||
import CashuMintName from "../../../components/cashu/cashu-mint-name";
|
||||
import useAsyncErrorHandler from "../../../hooks/use-async-error-handler";
|
||||
import { getCashuWallet } from "../../../services/cashu-mints";
|
||||
|
||||
export default function WalletReceiveTokenView() {
|
||||
const navigate = useNavigate();
|
||||
const toast = useToast();
|
||||
const actions = useActionHub();
|
||||
const location = useLocation();
|
||||
const more = useDisclosure();
|
||||
|
||||
const token: string = location.state?.token;
|
||||
if (!token) return <Navigate to="/wallet" />;
|
||||
|
||||
const decoded = getDecodedToken(token);
|
||||
const originalAmount = decoded.proofs.reduce((t, p) => t + p.amount, 0);
|
||||
|
||||
const receive = useAsyncErrorHandler(async () => {
|
||||
try {
|
||||
// swap tokens
|
||||
const wallet = await getCashuWallet(decoded.mint);
|
||||
const proofs = await wallet.receive(decoded);
|
||||
const token: Token = { mint: decoded.mint, proofs };
|
||||
|
||||
const amount = token.proofs.reduce((t, p) => t + p.amount, 0);
|
||||
const fee = originalAmount - amount;
|
||||
|
||||
// save new tokens
|
||||
await actions.run(ReceiveToken, token, undefined, fee || undefined);
|
||||
|
||||
toast({ status: "success", description: `Received ${amount} sats` });
|
||||
|
||||
navigate("/wallet");
|
||||
} catch (error) {
|
||||
if (error instanceof Error) toast({ status: "error", description: error.message });
|
||||
console.log(error);
|
||||
}
|
||||
}, [decoded, originalAmount, actions, navigate, toast]);
|
||||
|
||||
const swap = useAsyncErrorHandler(async () => {}, [decoded, originalAmount, actions, navigate, toast]);
|
||||
|
||||
return (
|
||||
<SimpleView title="Receive Token" maxW="xl" center>
|
||||
<Card mb="4">
|
||||
<CardBody>
|
||||
<Text fontSize="4xl" textAlign="center">
|
||||
{originalAmount} sats
|
||||
</Text>
|
||||
<Flex alignItems="center" justifyContent="center" gap="2" mt="4">
|
||||
<CashuMintFavicon mint={decoded.mint} size="sm" />
|
||||
<CashuMintName mint={decoded.mint} fontSize="lg" />
|
||||
</Flex>
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
<Button colorScheme="primary" isLoading={receive.loading} onClick={receive.run} size="lg">
|
||||
Receive
|
||||
</Button>
|
||||
</SimpleView>
|
||||
);
|
||||
}
|
@ -3,7 +3,8 @@ import RequireActiveAccount from "../../components/router/require-active-account
|
||||
import { lazy } from "react";
|
||||
|
||||
const WalletHomeView = lazy(() => import("."));
|
||||
const WalletReceiveView = lazy(() => import("./receive"));
|
||||
const WalletReceiveView = lazy(() => import("./receive/index"));
|
||||
const WalletReceiveTokenView = lazy(() => import("./receive/token"));
|
||||
const WalletSendView = lazy(() => import("./send/index"));
|
||||
const WalletSendCashuView = lazy(() => import("./send/cashu"));
|
||||
const WalletSendTokenView = lazy(() => import("./send/token"));
|
||||
@ -17,7 +18,13 @@ export default [
|
||||
</RequireActiveAccount>
|
||||
),
|
||||
},
|
||||
{ path: "receive", Component: WalletReceiveView },
|
||||
{
|
||||
path: "receive",
|
||||
children: [
|
||||
{ index: true, Component: WalletReceiveView },
|
||||
{ path: "token", Component: WalletReceiveTokenView },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "send",
|
||||
children: [
|
||||
|
@ -20,8 +20,10 @@ export default function WalletSendCashuView() {
|
||||
const balance = useStoreQuery(WalletBalanceQuery, [account.pubkey]);
|
||||
const tokens = useStoreQuery(WalletTokensQuery, [account.pubkey, false]);
|
||||
|
||||
const defaultMint = balance && Object.keys(balance).reduce((a, b) => (balance[a] > balance[b] ? a : b));
|
||||
|
||||
const { register, getValues, watch, handleSubmit, formState } = useForm({
|
||||
defaultValues: { amount: 0, mint: "" },
|
||||
defaultValues: { amount: 0, mint: defaultMint ?? "" },
|
||||
mode: "all",
|
||||
});
|
||||
|
||||
@ -33,7 +35,9 @@ export default function WalletSendCashuView() {
|
||||
const selected = dumbTokenSelection(tokens, values.amount, values.mint);
|
||||
const wallet = await getCashuWallet(values.mint);
|
||||
|
||||
// swap
|
||||
await wallet.mint.getKeySets();
|
||||
|
||||
// swap tokens for send
|
||||
const send = await wallet.send(values.amount, selected.proofs);
|
||||
|
||||
// save the change
|
||||
|
@ -10,7 +10,7 @@ export default function WalletSendView() {
|
||||
<SimpleView title="Send" maxW="xl" center>
|
||||
<Card as={LinkBox} p="4" gap="4" display="flex" flexDirection="row" alignItems="center">
|
||||
<ECashIcon boxSize={10} />
|
||||
<HoverLinkOverlay as={RouterLink} to="/wallet/send/cashu">
|
||||
<HoverLinkOverlay as={RouterLink} to="/wallet/send/cashu" replace>
|
||||
<Text fontWeight="bold" fontSize="xl">
|
||||
ECash
|
||||
</Text>
|
||||
@ -18,7 +18,7 @@ export default function WalletSendView() {
|
||||
</Card>
|
||||
<Card as={LinkBox} p="4" gap="4" display="flex" flexDirection="row" alignItems="center">
|
||||
<LightningIcon boxSize={10} color="yellow.400" />
|
||||
<HoverLinkOverlay as={RouterLink} to="/wallet/pay/lightning">
|
||||
<HoverLinkOverlay as={RouterLink} to="/wallet/pay/lightning" replace>
|
||||
<Text fontWeight="bold" fontSize="xl">
|
||||
Lightning
|
||||
</Text>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { filter, from, Observable, switchMap, take } from "rxjs";
|
||||
import { Button, ButtonGroup, Flex, Spacer, useToast } from "@chakra-ui/react";
|
||||
import { ANIMATED_QR_INTERVAL, sendAnimated } from "applesauce-wallet/helpers";
|
||||
import { ANIMATED_QR_INTERVAL, encodeTokenToEmoji, sendAnimated } from "applesauce-wallet/helpers";
|
||||
import { getDecodedToken, Proof, ProofState } from "@cashu/cashu-ts";
|
||||
import { ReceiveToken } from "applesauce-wallet/actions";
|
||||
import { useActionHub } from "applesauce-react/hooks";
|
||||
@ -10,7 +11,6 @@ import SimpleView from "../../../components/layout/presets/simple-view";
|
||||
import RouterLink from "../../../components/router-link";
|
||||
import { CopyIconButton } from "../../../components/copy-icon-button";
|
||||
import QrCodeSvg from "../../../components/qr-code/qr-code-svg";
|
||||
import { filter, from, Observable, switchMap, take } from "rxjs";
|
||||
import { getCashuWallet } from "../../../services/cashu-mints";
|
||||
|
||||
export default function WalletSendTokenView() {
|
||||
@ -103,6 +103,7 @@ export default function WalletSendTokenView() {
|
||||
|
||||
<Flex gap="2">
|
||||
<CopyIconButton value={token} aria-label="Copy token" />
|
||||
<CopyIconButton value={encodeTokenToEmoji(token)} aria-label="Copy emoji" icon={<span>🥜</span>} />
|
||||
<Spacer />
|
||||
<Button onClick={cancel} isLoading={canceling}>
|
||||
Cancel
|
||||
|
@ -5,10 +5,12 @@ import {
|
||||
Card,
|
||||
CardBody,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
Flex,
|
||||
IconButton,
|
||||
Spacer,
|
||||
Text,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import { useActiveAccount, useEventStore, useStoreQuery } from "applesauce-react/hooks";
|
||||
import {
|
||||
@ -27,7 +29,7 @@ import ArrowBlockDown from "../../../components/icons/arrow-block-down";
|
||||
import useEventIntersectionRef from "../../../hooks/use-event-intersection-ref";
|
||||
import useAsyncErrorHandler from "../../../hooks/use-async-error-handler";
|
||||
import { useDeleteEventContext } from "../../../providers/route/delete-event-provider";
|
||||
import { TrashIcon } from "../../../components/icons";
|
||||
import { ChevronDownIcon, ChevronUpIcon, TrashIcon } from "../../../components/icons";
|
||||
import useEventUpdate from "../../../hooks/use-event-update";
|
||||
import Timestamp from "../../../components/timestamp";
|
||||
import useSingleEvents from "../../../hooks/use-single-events";
|
||||
@ -38,6 +40,7 @@ import { usePublishEvent } from "../../../providers/global/publish-provider";
|
||||
import factory from "../../../services/event-factory";
|
||||
|
||||
function HistoryEntry({ entry }: { entry: NostrEvent }) {
|
||||
const more = useDisclosure();
|
||||
const account = useActiveAccount()!;
|
||||
const eventStore = useEventStore();
|
||||
const locked = isHistoryContentLocked(entry);
|
||||
@ -57,7 +60,7 @@ function HistoryEntry({ entry }: { entry: NostrEvent }) {
|
||||
|
||||
return (
|
||||
<Card ref={ref}>
|
||||
<CardBody p="2" display="flex" flexDirection="row" gap="2">
|
||||
<CardHeader p="2" display="flex" flexDirection="row" gap="2" alignItems="center">
|
||||
{locked ? (
|
||||
<Lock01 boxSize={8} />
|
||||
) : details?.direction === "in" ? (
|
||||
@ -66,6 +69,7 @@ function HistoryEntry({ entry }: { entry: NostrEvent }) {
|
||||
<ArrowBlockUp boxSize={8} color="orange.500" />
|
||||
)}
|
||||
<Text fontSize="xl">{details?.amount}</Text>
|
||||
{details?.fee !== undefined && <Text>( fee {details.fee} )</Text>}
|
||||
<Spacer />
|
||||
<ButtonGroup size="sm" alignItems="center">
|
||||
{locked && (
|
||||
@ -74,18 +78,10 @@ function HistoryEntry({ entry }: { entry: NostrEvent }) {
|
||||
</Button>
|
||||
)}
|
||||
<Timestamp timestamp={entry.created_at} />
|
||||
<DebugEventButton variant="ghost" event={entry} />
|
||||
<IconButton
|
||||
icon={<TrashIcon boxSize={5} />}
|
||||
aria-label="Delete entry"
|
||||
onClick={() => deleteEvent(entry)}
|
||||
colorScheme="red"
|
||||
variant="ghost"
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</CardBody>
|
||||
</CardHeader>
|
||||
{details && (
|
||||
<CardFooter px="2" pt="0" pb="2">
|
||||
<CardBody px="2" pt="0" pb="2" display="flex">
|
||||
{details.mint && (
|
||||
<>
|
||||
<CashuMintFavicon mint={details.mint} size="xs" mr="2" />
|
||||
@ -102,11 +98,30 @@ function HistoryEntry({ entry }: { entry: NostrEvent }) {
|
||||
</AvatarGroup>
|
||||
</>
|
||||
)}
|
||||
{details.fee !== undefined && (
|
||||
<Text fontStyle="italic" ms="auto">
|
||||
fee: {details.fee}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<Button
|
||||
ms="auto"
|
||||
size="sm"
|
||||
variant="link"
|
||||
onClick={more.onToggle}
|
||||
rightIcon={more.isOpen ? <ChevronUpIcon boxSize={6} /> : <ChevronDownIcon boxSize={6} />}
|
||||
>
|
||||
Details
|
||||
</Button>
|
||||
</CardBody>
|
||||
)}
|
||||
{more.isOpen && (
|
||||
<CardFooter pt="0" pb="2" px="2" gap="2" display="flex">
|
||||
<ButtonGroup size="sm" ms="auto">
|
||||
<DebugEventButton variant="ghost" event={entry} />
|
||||
<IconButton
|
||||
icon={<TrashIcon boxSize={5} />}
|
||||
aria-label="Delete entry"
|
||||
onClick={() => deleteEvent(entry)}
|
||||
colorScheme="red"
|
||||
variant="ghost"
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</CardFooter>
|
||||
)}
|
||||
</Card>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Card,
|
||||
CardBody,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
Flex,
|
||||
@ -10,24 +11,37 @@ import {
|
||||
IconButton,
|
||||
Spacer,
|
||||
Text,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import { useActiveAccount, useEventStore, useStoreQuery } from "applesauce-react/hooks";
|
||||
import { WalletTokensQuery } from "applesauce-wallet/queries";
|
||||
import { getTokenContent, isTokenContentLocked, unlockTokenContent } from "applesauce-wallet/helpers";
|
||||
import { NostrEvent } from "nostr-tools";
|
||||
import { ProofState } from "@cashu/cashu-ts";
|
||||
import { getEncodedToken, ProofState } from "@cashu/cashu-ts";
|
||||
|
||||
import useAsyncErrorHandler from "../../../hooks/use-async-error-handler";
|
||||
import useEventUpdate from "../../../hooks/use-event-update";
|
||||
import useEventIntersectionRef from "../../../hooks/use-event-intersection-ref";
|
||||
import { ECashIcon, TrashIcon } from "../../../components/icons";
|
||||
import {
|
||||
ChevronDownIcon,
|
||||
ChevronUpIcon,
|
||||
ECashIcon,
|
||||
ExternalLinkIcon,
|
||||
QrCodeIcon,
|
||||
TrashIcon,
|
||||
} from "../../../components/icons";
|
||||
import DebugEventButton from "../../../components/debug-modal/debug-event-button";
|
||||
import { useDeleteEventContext } from "../../../providers/route/delete-event-provider";
|
||||
import Timestamp from "../../../components/timestamp";
|
||||
import { getCashuWallet } from "../../../services/cashu-mints";
|
||||
import ConsolidateTokensButton from "../components/consolidate-tokens-button";
|
||||
import CashuMintFavicon from "../../../components/cashu/cashu-mint-favicon";
|
||||
import CashuMintName from "../../../components/cashu/cashu-mint-name";
|
||||
import { CopyIconButton } from "../../../components/copy-icon-button";
|
||||
import RouterLink from "../../../components/router-link";
|
||||
|
||||
function TokenEvent({ token }: { token: NostrEvent }) {
|
||||
const more = useDisclosure();
|
||||
const account = useActiveAccount();
|
||||
const eventStore = useEventStore();
|
||||
useEventUpdate(token.id);
|
||||
@ -54,6 +68,8 @@ function TokenEvent({ token }: { token: NostrEvent }) {
|
||||
eventStore.update(token);
|
||||
}, [token, account, eventStore]);
|
||||
|
||||
const encoded = useMemo(() => details && getEncodedToken(details), [details]);
|
||||
|
||||
return (
|
||||
<Card ref={ref} w="full">
|
||||
<CardHeader p="2" alignItems="center" flexDirection="row" display="flex" gap="2">
|
||||
@ -66,34 +82,64 @@ function TokenEvent({ token }: { token: NostrEvent }) {
|
||||
</Button>
|
||||
)}
|
||||
<Timestamp timestamp={token.created_at} />
|
||||
<DebugEventButton variant="ghost" event={token} />
|
||||
<IconButton
|
||||
icon={<TrashIcon boxSize={5} />}
|
||||
aria-label="Delete entry"
|
||||
onClick={() => deleteEvent(token)}
|
||||
colorScheme="red"
|
||||
variant="ghost"
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</CardHeader>
|
||||
{details && (
|
||||
<CardFooter px="2" pt="0" pb="0" gap="2" display="flex">
|
||||
<Button
|
||||
variant="link"
|
||||
colorScheme={
|
||||
spentState === undefined ? undefined : spentState.some((s) => s.state === "UNSPENT") ? "green" : "red"
|
||||
}
|
||||
onClick={check}
|
||||
>
|
||||
{spentState === undefined
|
||||
? "Check"
|
||||
: (spentState.some((s) => s.state === "UNSPENT") ? "Unspent" : "Spent") +
|
||||
` ${spentState.filter((s) => s.state === "UNSPENT").length}/${spentState.length}`}
|
||||
</Button>
|
||||
<Spacer />
|
||||
<Text fontSize="sm" fontStyle="italic">
|
||||
{details.mint}
|
||||
</Text>
|
||||
<CardBody display="flex" gap="2" px="2" pt="0" pb="2">
|
||||
{details && (
|
||||
<>
|
||||
<CashuMintFavicon mint={details.mint} size="xs" />
|
||||
<CashuMintName mint={details.mint} />
|
||||
</>
|
||||
)}
|
||||
<Spacer />
|
||||
<Button
|
||||
variant="link"
|
||||
onClick={more.onToggle}
|
||||
rightIcon={more.isOpen ? <ChevronUpIcon boxSize={6} /> : <ChevronDownIcon boxSize={6} />}
|
||||
>
|
||||
Details
|
||||
</Button>
|
||||
</CardBody>
|
||||
{more.isOpen && (
|
||||
<CardFooter px="2" pt="0" pb="2" gap="2" display="flex">
|
||||
<ButtonGroup size="sm">
|
||||
<Button
|
||||
variant="ghost"
|
||||
colorScheme={
|
||||
spentState === undefined ? undefined : spentState.some((s) => s.state === "UNSPENT") ? "green" : "red"
|
||||
}
|
||||
onClick={check}
|
||||
>
|
||||
{spentState === undefined
|
||||
? "Check"
|
||||
: (spentState.some((s) => s.state === "UNSPENT") ? "Unspent" : "Spent") +
|
||||
` ${spentState.filter((s) => s.state === "UNSPENT").length}/${spentState.length}`}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
<ButtonGroup ms="auto" size="sm">
|
||||
{encoded && (
|
||||
<>
|
||||
<CopyIconButton value={encoded} aria-label="Copy token" variant="ghost" />
|
||||
<IconButton
|
||||
as={RouterLink}
|
||||
to="/wallet/send/token"
|
||||
state={{ token: encoded }}
|
||||
icon={<ExternalLinkIcon />}
|
||||
aria-label="Show token"
|
||||
variant="ghost"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<DebugEventButton variant="ghost" event={token} />
|
||||
|
||||
<IconButton
|
||||
aria-label="Delete entry"
|
||||
onClick={() => deleteEvent(token)}
|
||||
colorScheme="red"
|
||||
variant="ghost"
|
||||
icon={<TrashIcon />}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</CardFooter>
|
||||
)}
|
||||
</Card>
|
||||
|
Loading…
x
Reference in New Issue
Block a user