import toast from "react-hot-toast"; import { useSnapshot } from "valtio"; import { ArrowSquareOut, Copy, Trash, Wallet, X } from "phosphor-react"; import React, { useEffect, useState, FC } from "react"; import Dinero from "dinero.js"; import Button from "./Button"; import { addFaucetAccount, importAccount } from "../state/actions"; import state from "../state"; import Box from "./Box"; import { Container, Heading, Stack, Text, Flex } from "."; import { Dialog, DialogContent, DialogTitle, DialogDescription, DialogClose, DialogTrigger, } from "./Dialog"; import { css } from "../stitches.config"; import { Input, Label } from "./Input"; import truncate from "../utils/truncate"; const labelStyle = css({ color: "$mauve10", textTransform: "uppercase", fontSize: "10px", mb: "$0.5", }); import transactionsData from "../content/transactions.json"; import { SetHookDialog } from "./SetHookDialog"; import { addFunds } from "../state/actions/addFaucetAccount"; import { deleteHook } from "../state/actions/deployHook"; export const AccountDialog = ({ activeAccountAddress, setActiveAccountAddress, }: { activeAccountAddress: string | null; setActiveAccountAddress: React.Dispatch>; }) => { const snap = useSnapshot(state); const [showSecret, setShowSecret] = useState(false); const activeAccount = snap.accounts.find( (account) => account.address === activeAccountAddress ); return ( { setShowSecret(false); !open && setActiveAccountAddress(null); }} > {activeAccount?.name} Account Address {activeAccount?.address} Secret {showSecret ? activeAccount?.secret : "•".repeat(activeAccount?.secret.length || 16)}{" "} Balances & Objects {Dinero({ amount: Number(activeAccount?.xrp || "0"), precision: 6, }) .toUnit() .toLocaleString(undefined, { style: "currency", currency: "XRP", currencyDisplay: "name", })} Installed Hooks {activeAccount && activeAccount.hooks.length > 0 ? activeAccount.hooks.map((i) => truncate(i, 12)).join(",") : "–"} {activeAccount && activeAccount?.hooks?.length > 0 && ( )} ); }; interface AccountProps { card?: boolean; hideDeployBtn?: boolean; showHookStats?: boolean; } const Accounts: FC = (props) => { const snap = useSnapshot(state); const [activeAccountAddress, setActiveAccountAddress] = useState< string | null >(null); useEffect(() => { const fetchAccInfo = async () => { if (snap.clientStatus === "online") { const requests = snap.accounts.map((acc) => snap.client?.send({ id: `hooks-builder-req-info-${acc.address}`, command: "account_info", account: acc.address, }) ); const responses = await Promise.all(requests); responses.forEach((res: any) => { const address = res?.account_data?.Account as string; const balance = res?.account_data?.Balance as string; const sequence = res?.account_data?.Sequence as number; const accountToUpdate = state.accounts.find( (acc) => acc.address === address ); if (accountToUpdate) { accountToUpdate.xrp = balance; accountToUpdate.sequence = sequence; accountToUpdate.error = null; } else { const oldAccount = state.accounts.find( (acc) => acc.address === res?.account ); if (oldAccount) { oldAccount.xrp = "0"; oldAccount.error = { code: res?.error, message: res?.error_message, }; } } }); const objectRequests = snap.accounts.map((acc) => { return snap.client?.send({ id: `hooks-builder-req-objects-${acc.address}`, command: "account_objects", account: acc.address, }); }); const objectResponses = await Promise.all(objectRequests); objectResponses.forEach((res: any) => { const address = res?.account as string; const accountToUpdate = state.accounts.find( (acc) => acc.address === address ); if (accountToUpdate) { accountToUpdate.hooks = res.account_objects .find((ac: any) => ac?.LedgerEntryType === "Hook") ?.Hooks?.map((oo: any) => oo.Hook.HookHash) || []; } }); } }; let fetchAccountInfoInterval: NodeJS.Timer; if (snap.clientStatus === "online") { fetchAccInfo(); fetchAccountInfoInterval = setInterval(() => fetchAccInfo(), 10000); } return () => { if (snap.accounts.length > 0) { if (fetchAccountInfoInterval) { clearInterval(fetchAccountInfoInterval); } } }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [snap.accounts.length, snap.clientStatus]); return ( Accounts {snap.accounts.map((account) => ( setActiveAccountAddress(account.address)} css={{ px: "$3", py: props.card ? "$3" : "$2", cursor: "pointer", borderBottom: props.card ? "1px solid $mauve6" : undefined, "@hover": { "&:hover": { background: "$backgroundAlt", }, }, }} > {account.name} {account.address}{" "} {!account?.error ? ( `(${Dinero({ amount: Number(account?.xrp || "0"), precision: 6, }) .toUnit() .toLocaleString(undefined, { style: "currency", currency: "XRP", currencyDisplay: "name", })})` ) : ( (Account not found, request funds to activate account) )} {!props.hideDeployBtn && (
{ e.stopPropagation(); }} >
)}
{props.showHookStats && ( {account.hooks.length} hook {account.hooks.length === 1 ? "" : "s"} installed )}
))}
); }; export const transactionsOptions = transactionsData.map((tx) => ({ value: tx.TransactionType, label: tx.TransactionType, })); const ImportAccountDialog = () => { const [value, setValue] = useState(""); return ( Import account setValue(e.target.value)} /> ); }; export default Accounts;