188 lines
7.2 KiB
TypeScript
188 lines
7.2 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { AddressInput } from "@scaffold-ui/components";
|
|
import { IntegerInput } from "@scaffold-ui/debug-contracts";
|
|
import { useWatchBalance } from "@scaffold-ui/hooks";
|
|
import type { NextPage } from "next";
|
|
import { formatEther } from "viem";
|
|
import { useAccount } from "wagmi";
|
|
import { useDeployedContractInfo, useScaffoldReadContract, useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
|
|
import { getTokenPrice, multiplyTo1e18 } from "~~/utils/scaffold-eth/priceInWei";
|
|
|
|
const TokenVendor: NextPage = () => {
|
|
const [toAddress, setToAddress] = useState("");
|
|
const [tokensToSend, setTokensToSend] = useState("");
|
|
const [tokensToBuy, setTokensToBuy] = useState<string | bigint>("");
|
|
const [isApproved, setIsApproved] = useState(false);
|
|
const [tokensToSell, setTokensToSell] = useState<string>("");
|
|
|
|
const { address } = useAccount();
|
|
const { data: yourTokenSymbol } = useScaffoldReadContract({
|
|
contractName: "YourToken",
|
|
functionName: "symbol",
|
|
});
|
|
|
|
const { data: yourTokenBalance } = useScaffoldReadContract({
|
|
contractName: "YourToken",
|
|
functionName: "balanceOf",
|
|
args: [address],
|
|
});
|
|
|
|
const { data: vendorContractData } = useDeployedContractInfo({ contractName: "Vendor" });
|
|
const { writeContractAsync: writeVendorAsync } = useScaffoldWriteContract({ contractName: "Vendor" });
|
|
const { writeContractAsync: writeYourTokenAsync } = useScaffoldWriteContract({ contractName: "YourToken" });
|
|
|
|
const { data: vendorTokenBalance } = useScaffoldReadContract({
|
|
contractName: "YourToken",
|
|
functionName: "balanceOf",
|
|
args: [vendorContractData?.address],
|
|
});
|
|
|
|
const { data: vendorEthBalance } = useWatchBalance({ address: vendorContractData?.address });
|
|
|
|
const { data: tokensPerEth } = useScaffoldReadContract({
|
|
contractName: "Vendor",
|
|
functionName: "tokensPerEth",
|
|
});
|
|
|
|
return (
|
|
<>
|
|
<div className="flex items-center flex-col flex-grow pt-10">
|
|
<div className="flex flex-col items-center bg-base-100 shadow-lg shadow-secondary border-8 border-secondary rounded-xl p-6 mt-24 w-full max-w-lg">
|
|
<div className="text-xl">
|
|
Your token balance:{" "}
|
|
<div className="inline-flex items-center justify-center">
|
|
{parseFloat(formatEther(yourTokenBalance || 0n)).toFixed(4)}
|
|
<span className="font-bold ml-1">{yourTokenSymbol}</span>
|
|
</div>
|
|
</div>
|
|
<hr className="w-full border-secondary my-3" />
|
|
<div>
|
|
Vendor token balance:{" "}
|
|
<div className="inline-flex items-center justify-center">
|
|
{Number(formatEther(vendorTokenBalance || 0n)).toFixed(4)}
|
|
<span className="font-bold ml-1">{yourTokenSymbol}</span>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
Vendor eth balance: {Number(formatEther(vendorEthBalance?.value || 0n)).toFixed(4)}
|
|
<span className="font-bold ml-1">ETH</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex flex-col items-center space-y-4 bg-base-100 shadow-lg shadow-secondary border-8 border-secondary rounded-xl p-6 mt-8 w-full max-w-lg">
|
|
<div className="text-xl">Buy tokens</div>
|
|
<div>{tokensPerEth?.toString() || 0} tokens per ETH</div>
|
|
|
|
<div className="w-full flex flex-col space-y-2">
|
|
<IntegerInput
|
|
placeholder="amount of tokens to buy"
|
|
value={tokensToBuy.toString()}
|
|
onChange={value => setTokensToBuy(value)}
|
|
disableMultiplyBy1e18
|
|
/>
|
|
</div>
|
|
|
|
<button
|
|
className="btn btn-secondary mt-2"
|
|
onClick={async () => {
|
|
try {
|
|
await writeVendorAsync({ functionName: "buyTokens", value: getTokenPrice(tokensToBuy, tokensPerEth) });
|
|
} catch (err) {
|
|
console.error("Error calling buyTokens function", err);
|
|
}
|
|
}}
|
|
>
|
|
Buy Tokens
|
|
</button>
|
|
</div>
|
|
|
|
{!!yourTokenBalance && (
|
|
<div className="flex flex-col items-center space-y-4 bg-base-100 shadow-lg shadow-secondary border-8 border-secondary rounded-xl p-6 mt-8 w-full max-w-lg">
|
|
<div className="text-xl">Transfer tokens</div>
|
|
<div className="w-full flex flex-col space-y-2">
|
|
<AddressInput placeholder="to address" value={toAddress} onChange={value => setToAddress(value)} />
|
|
<IntegerInput
|
|
placeholder="amount of tokens to send"
|
|
value={tokensToSend}
|
|
onChange={value => setTokensToSend(value as string)}
|
|
disableMultiplyBy1e18
|
|
/>
|
|
</div>
|
|
|
|
<button
|
|
className="btn btn-secondary"
|
|
onClick={async () => {
|
|
try {
|
|
await writeYourTokenAsync({
|
|
functionName: "transfer",
|
|
args: [toAddress, multiplyTo1e18(tokensToSend)],
|
|
});
|
|
} catch (err) {
|
|
console.error("Error calling transfer function", err);
|
|
}
|
|
}}
|
|
>
|
|
Send Tokens
|
|
</button>
|
|
</div>
|
|
)}
|
|
|
|
{/* Sell Tokens */}
|
|
{!!yourTokenBalance && (
|
|
<div className="flex flex-col items-center space-y-4 bg-base-100 shadow-lg shadow-secondary border-8 border-secondary rounded-xl p-6 mt-8 w-full max-w-lg">
|
|
<div className="text-xl">Sell tokens</div>
|
|
<div>{tokensPerEth?.toString() || 0} tokens per ETH</div>
|
|
|
|
<div className="w-full flex flex-col space-y-2">
|
|
<IntegerInput
|
|
placeholder="amount of tokens to sell"
|
|
value={tokensToSell}
|
|
onChange={value => setTokensToSell(value as string)}
|
|
disabled={isApproved}
|
|
disableMultiplyBy1e18
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex gap-4">
|
|
<button
|
|
className={`btn ${isApproved ? "btn-disabled" : "btn-secondary"}`}
|
|
onClick={async () => {
|
|
try {
|
|
await writeYourTokenAsync({
|
|
functionName: "approve",
|
|
args: [vendorContractData?.address, multiplyTo1e18(tokensToSell)],
|
|
});
|
|
setIsApproved(true);
|
|
} catch (err) {
|
|
console.error("Error calling approve function", err);
|
|
}
|
|
}}
|
|
>
|
|
Approve Tokens
|
|
</button>
|
|
|
|
<button
|
|
className={`btn ${isApproved ? "btn-secondary" : "btn-disabled"}`}
|
|
onClick={async () => {
|
|
try {
|
|
await writeVendorAsync({ functionName: "sellTokens", args: [multiplyTo1e18(tokensToSell)] });
|
|
setIsApproved(false);
|
|
} catch (err) {
|
|
console.error("Error calling sellTokens function", err);
|
|
}
|
|
}}
|
|
>
|
|
Sell Tokens
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default TokenVendor;
|