diff --git a/src/components/faucet.tsx b/src/components/faucet.tsx new file mode 100644 index 0000000..9a18fe4 --- /dev/null +++ b/src/components/faucet.tsx @@ -0,0 +1,195 @@ +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; + +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; + +import { Input } from "./ui/input"; + +import { useSwitchNetwork } from "@/lib/hooks/use-switch-network"; +import { + useAppKit, + useAppKitAccount, + useAppKitProvider, +} from "@reown/appkit/react"; +import { useMutation } from "@tanstack/react-query"; +import { ethers } from "ethers"; +import { useState } from "react"; +import { toast } from "sonner"; +import { type Hex, encodeFunctionData, parseAbi, parseUnits } from "viem"; +import { Button } from "./ui/button"; + +const faucetTokens = [ + { + id: "FAU-sepolia", + name: "FAU", + symbol: "FAU", + decimals: 18, + address: "0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + network: "sepolia", + type: "ERC20", + hash: "0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + chainId: 11155111, + }, + { + id: "fUSDT-sepolia", + name: "fUSDT", + symbol: "fUSDT", + decimals: 6, + address: "0xF046b3CA5ae2879c6bAcC4D42fAF363eE8379F78", + network: "sepolia", + type: "ERC20", + hash: "0xF046b3CA5ae2879c6bAcC4D42fAF363eE8379F78", + chainId: 11155111, + }, +] as const; + +export const FaucetTokens = () => { + const { isConnected, address } = useAppKitAccount(); + const { open } = useAppKit(); + const { chainId, switchToChainId } = useSwitchNetwork(); + + const { walletProvider } = useAppKitProvider("eip155"); + const [token, setToken] = useState("FAU-sepolia"); + const [amount, setAmount] = useState(0); + + const mintHandler = useMutation({ + mutationFn: async () => { + if (!isConnected || !address) { + open(); + throw new Error("Connect Wallet to mint tokens"); + } + + const selectedToken = faucetTokens.find((t) => t.id === token); + if (!selectedToken) throw new Error("Invalid token"); + + if (chainId !== selectedToken.chainId) { + await switchToChainId(selectedToken.chainId); + } + + const ethersProvider = new ethers.providers.Web3Provider( + walletProvider as ethers.providers.ExternalProvider, + ); + const signer = ethersProvider.getSigner(); + + if (!signer) throw new Error("No signer found"); + + const parsedAmount = parseUnits( + amount.toString(), + selectedToken.decimals ?? 18, + ); + + const id = toast.loading("Minting tokens..."); + + const tx = await signer.sendTransaction({ + to: selectedToken.address, + data: encodeFunctionData({ + abi: parseAbi(["function mint(address to, uint256 amount) public"]), + functionName: "mint", + args: [address as Hex, parsedAmount], + }), + }); + + await tx.wait(); + + toast.loading("Waiting for confirmation...", { id }); + + return { + hash: tx.hash, + id, + }; + }, + onSuccess: (data) => { + toast.success("Tokens minted successfully", { id: data.id }); + }, + onError: (error) => { + toast.dismiss(); + toast.error(error.message); + }, + }); + + return ( + + + + + + + Get Faucet Tokens +
+
+
Token Name
+ +
+
+
Amount
+ { + const val = e.target.value; + const parsed = Number(val); + setAmount(Number.isNaN(parsed) ? 0 : parsed); + }} + /> +
+ + +
+
+
+
+ ); +}; diff --git a/src/components/navigation/topbar.tsx b/src/components/navigation/topbar.tsx index e4f7a51..357be7f 100644 --- a/src/components/navigation/topbar.tsx +++ b/src/components/navigation/topbar.tsx @@ -4,6 +4,8 @@ import { useAuthContext } from "@/context/auth"; import { ModeToggle } from "../mode-toggle"; import { UserMenu } from "../user-menu"; +import { FaucetTokens } from "../faucet"; + export function Topbar() { const auth = useAuthContext(); @@ -18,6 +20,7 @@ export function Topbar() { return (
+