86 lines
2.7 KiB
TypeScript
86 lines
2.7 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { useNavigate } from "react-router";
|
|
import { toast } from "react-toastify";
|
|
import { isAddress, parseEther } from "viem";
|
|
import { useConnection, useSendTransaction, useWaitForTransactionReceipt } from "wagmi";
|
|
|
|
|
|
export function TransferPage() {
|
|
const { isConnected } = useConnection();
|
|
const navigate = useNavigate();
|
|
|
|
const [inputAddress, setInputAddress] = useState('');
|
|
const [inputValue, setInputValue] = useState('');
|
|
|
|
const { data: transactionHash, isPending: isSendingTransaction, error, mutate: sendTransaction } = useSendTransaction();
|
|
const { data: receipt, isPending, isFetching } = useWaitForTransactionReceipt({
|
|
hash: transactionHash,
|
|
query: {
|
|
// not stricly needed, because if transactionHash is not defined,
|
|
// in current versions of wagmi it defaults to disabled
|
|
// (but, it's good to know so you can control dependent queries)
|
|
enabled: !!transactionHash
|
|
}
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (!isConnected) {
|
|
navigate('/status');
|
|
}
|
|
}, [isConnected, navigate]);
|
|
|
|
function onSubmit(e) {
|
|
e.preventDefault();
|
|
|
|
if (!isAddress(inputAddress)) {
|
|
return toast.error('Invalid address.');
|
|
}
|
|
|
|
if (!inputValue || isNaN(Number(inputValue)) || Number(inputValue) <= 0) {
|
|
return toast.error('Invalid value.');
|
|
}
|
|
|
|
sendTransaction({
|
|
to: inputAddress,
|
|
value: parseEther(inputValue)
|
|
})
|
|
}
|
|
|
|
return (
|
|
<div className="bg-white border border-slate-200 rounded-xl p-5 flex flex-col gap-6 shadow-sm">
|
|
<h1 className="text-lg font-bold">Transfer ETH</h1>
|
|
|
|
<form onSubmit={onSubmit} className="flex flex-col gap-6">
|
|
<input
|
|
type="text"
|
|
className="border border-gray-300 p-2 rounded-lg"
|
|
placeholder="Enter address."
|
|
value={inputAddress}
|
|
onChange={e => setInputAddress(e.target.value)}
|
|
/>
|
|
<input
|
|
type="text"
|
|
className="border border-gray-300 p-2 rounded-lg"
|
|
placeholder="Enter value."
|
|
value={inputValue}
|
|
onChange={e => setInputValue(e.target.value)}
|
|
/>
|
|
|
|
<div className="flex flex-row">
|
|
<button
|
|
type="submit"
|
|
disabled={!inputAddress || !inputValue}
|
|
className="bg-black text-white px-5 py-2 cursor-pointer rounded-xl disabled:opacity-50"
|
|
>
|
|
{isSendingTransaction ? 'Sending...' : 'Send'}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
{error && <p>An error occurred. Please check the address and the value.</p>}
|
|
{(isPending && isFetching) && <p>Confirming...</p>}
|
|
{receipt && <p>Status: {receipt.status}</p>}
|
|
</div>
|
|
);
|
|
}
|