import { useQueryClient } from "@tanstack/react-query"; import { useEffect, useState } from "react"; import { toast } from "react-toastify"; import { erc20Abi, formatUnits, isAddress, parseUnits, type Address } from "viem"; import { useReadContract, useWaitForTransactionReceipt, useWriteContract } from "wagmi"; import type { SimpleErc20Token } from "~/types/api"; export function TokenCard({ token, address }: { token: SimpleErc20Token, address: Address }) { const [isTransferSectionOpen, setIsTransferSectionOpen] = useState(false); const [inputAddress, setInputAddress] = useState(""); const isAddressValid = isAddress(inputAddress); const [inputAmount, setInputAmount] = useState(""); const isAmountValid = inputAmount && !isNaN(Number(inputAmount)) && Number(inputAmount) > 0; const { data: balance, error: errorBalance } = useReadContract({ address: token.address, abi: erc20Abi, functionName: 'balanceOf', args: [address] }); const { data: decimals, error: errorDecimals } = useReadContract({ address: token.address, abi: erc20Abi, functionName: 'decimals' }); const { data: hash, mutate: makeTransfer, isPending: isWaitingForUser, error: userError } = useWriteContract(); const { data: receipt, isPending, isFetching, error: receiptError } = useWaitForTransactionReceipt({ hash }) const queryClient = useQueryClient(); useEffect(() => { if (hash && receipt?.status === 'success') { queryClient.invalidateQueries(); } }, [receipt, hash, queryClient]); function onSubmit(e) { e.preventDefault(); if (!isAddressValid) { toast.error('Invalid address.'); return; } if (!isAmountValid || !decimals) { toast.error('Invalid amount or decimals not loaded yet.'); return; } makeTransfer({ address: token.address, abi: erc20Abi, functionName: 'transfer', args: [inputAddress, parseUnits(inputAmount, decimals)] }) } if (errorBalance || errorDecimals) { return

Cannot read balance

; } return (

{token.name}

Identifier

{token.id}

Symbol

{token.symbol}

Contract address

{token.address}

Balance

{balance !== undefined && decimals !== undefined ? formatUnits(balance, decimals) : '...'} {token.symbol}

{isTransferSectionOpen && (

Transfer funds

setIsTransferSectionOpen(false)}>×
setInputAddress(e.target.value)} /> setInputAmount(e.target.value)} />
{isWaitingForUser &&

Waiting for user...

} {(userError || receiptError) &&

Failed to execute transfer.

} {(isPending && isFetching) &&

Waiting for receipt...

} {receipt &&

Status: {receipt.status}

}
)}
View contract
); }