work-sample/src/App.tsx

189 lines
5.4 KiB
TypeScript
Raw Normal View History

2022-12-07 18:47:26 -08:00
import React, {useState} from 'react';
2022-12-07 18:34:36 -08:00
import logo from './logo.svg';
import './App.css';
2022-12-07 18:55:13 -08:00
import Web3 from 'web3';
2022-12-07 23:29:13 -08:00
import { WagmiConfig, createClient, configureChains, mainnet, useConnect, useAccount, useDisconnect } from 'wagmi'
import { MetaMaskConnector } from 'wagmi/connectors/metaMask'
import { publicProvider } from 'wagmi/providers/public'
2022-12-07 18:55:13 -08:00
2022-12-07 20:56:39 -08:00
const web3 = new Web3(Web3.givenProvider);
2022-12-07 21:31:13 -08:00
import Airdrop from "./Airdrop.json";
2022-12-08 00:11:01 -08:00
import MagnaToken from "./MagnaToken.json";
2022-12-07 20:56:39 -08:00
const airdropAddress = "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512";
2022-12-07 21:31:13 -08:00
const airdropContract = new web3.eth.Contract(Airdrop.abi as any, airdropAddress);
2022-12-07 20:56:39 -08:00
2022-12-08 00:11:01 -08:00
const magnaTokenAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3";
const magnaTokenContract = new web3.eth.Contract(MagnaToken.abi as any, magnaTokenAddress);
2022-12-07 23:29:13 -08:00
const { chains, provider, webSocketProvider } = configureChains([mainnet], [publicProvider()]);
const wagmiClient = createClient({
autoConnect: true,
connectors: [
new MetaMaskConnector({ chains }),
],
provider,
webSocketProvider,
})
function Profile() {
const { connect, connectors, error, isLoading, pendingConnector } =
useConnect()
const { address, connector, isConnected } = useAccount()
const { disconnect } = useDisconnect()
if (isConnected) {
const connectorName = connector?.name || "unknown connector";
return (
<div>
<div>Connected to {connectorName} address: {address}</div>
<button onClick={(_evt) => disconnect() }>Disconnect</button>
</div>
)
}
return (
<div>
2022-12-07 23:40:19 -08:00
<div>Connect to Airdrop App</div>
2022-12-07 23:29:13 -08:00
{connectors.map((connector) => (
<button
disabled={!connector.ready}
key={connector.id}
onClick={() => connect({ connector })}
>
{connector.name}
{!connector.ready && ' (unsupported)'}
{isLoading &&
connector.id === pendingConnector?.id &&
' (connecting)'}
</button>
))}
{error && <div>{error.message}</div>}
</div>
)
}
2022-12-07 18:47:26 -08:00
interface AddressesProps {
addressList: string[];
setAddressListFn: any;
2022-12-08 12:55:35 -08:00
numTokens: number;
setNumTokens: any;
2022-12-07 18:47:26 -08:00
}
function Addresses(props: AddressesProps) {
const [inputState, setInputState] = useState("");
2022-12-07 18:55:13 -08:00
const [errorText, setErrorText] = useState("");
2022-12-08 12:55:35 -08:00
const { setAddressListFn, addressList, numTokens, setNumTokens } = props;
2022-12-07 18:47:26 -08:00
const save = () => {
2022-12-07 20:56:39 -08:00
if (!web3.utils.isAddress(inputState)) {
2022-12-07 18:55:13 -08:00
setErrorText("Invalid ETH address");
return;
}
setErrorText("");
2022-12-07 20:56:39 -08:00
const checksumAddr = web3.utils.toChecksumAddress(inputState);
2022-12-07 18:55:13 -08:00
if (addressList.includes(checksumAddr)) {
2022-12-07 18:47:26 -08:00
//Do nothing
} else {
2022-12-07 18:55:13 -08:00
setAddressListFn([...addressList, checksumAddr]);
2022-12-07 18:47:26 -08:00
}
setInputState("");
}
2022-12-07 21:31:13 -08:00
2022-12-07 21:34:45 -08:00
var num;
2022-12-07 23:16:46 -08:00
if (isNaN(numTokens) || numTokens < 0) {
2022-12-07 21:34:45 -08:00
num = 0;
} else {
num = numTokens;
}
2022-12-07 21:31:13 -08:00
2022-12-07 18:47:26 -08:00
return (
2022-12-07 21:31:13 -08:00
<div>
<div>
2022-12-07 18:47:26 -08:00
<input id="address" value={inputState} onChange={ (evt) => setInputState(evt.target.value) } ></input>
2022-12-07 18:55:13 -08:00
<div className="addressError">{errorText}</div>
2022-12-07 18:47:26 -08:00
<button onClick={save}>Add address</button>
2022-12-07 21:31:13 -08:00
</div>
<div>
Number of tokens:
<input type="numeric" value={num} onChange={ (evt) => setNumTokens(parseInt(evt.target.value)) }></input>
</div>
</div>
);
2022-12-07 18:47:26 -08:00
}
interface AddressListProps {
addressList: string[];
};
function AddressList({addressList}: AddressListProps) {
const addresses = addressList.length == 0 ?
<p>No addresses specified yet</p> :
addressList.map((addr: string) => <div key={addr} className="addressItem">{addr}</div>);
return (
<div>
<h2>Addresses to airdrop to: </h2>
{ addresses }
</div>
)
}
2022-12-07 18:34:36 -08:00
function App() {
2022-12-07 18:47:26 -08:00
const [addressList, setAddressList] = useState([]);
2022-12-08 12:55:35 -08:00
const [numTokens, setNumTokens] = useState(0);
const { address: ownerAddress, isConnected } = useAccount()
2022-12-07 18:47:26 -08:00
2022-12-07 23:16:46 -08:00
async function performAirdrop() {
console.log("Performing airdrop");
2022-12-08 12:55:35 -08:00
const totalCoins = addressList.length * numTokens;
2022-12-07 23:48:41 -08:00
2022-12-08 12:55:35 -08:00
console.log(`Owner ${ownerAddress} Airdrop ${airdropAddress}`);
2022-12-07 23:48:41 -08:00
2022-12-08 00:11:01 -08:00
const allowance = await magnaTokenContract.methods.allowance(ownerAddress, airdropAddress).call({ from: ownerAddress });
2022-12-07 23:48:41 -08:00
console.log(`Allowance: ${allowance}`);
2022-12-08 12:55:35 -08:00
if (allowance < totalCoins) {
const output = await magnaTokenContract.methods.approve(airdropAddress, totalCoins).send({ from: ownerAddress });
console.log(output);
2022-12-08 00:11:01 -08:00
}
2022-12-08 12:55:35 -08:00
const recipients = addressList;
const amounts = addressList.map((_addr) => numTokens);
const output = await airdropContract.methods.airdropTokens(recipients, amounts).send({ from: ownerAddress });
console.log(output);
2022-12-07 23:16:46 -08:00
}
2022-12-08 12:55:35 -08:00
const airdropButtonDisabled = addressList.length == 0 || !isConnected;
2022-12-07 18:34:36 -08:00
return (
2022-12-07 23:29:13 -08:00
<WagmiConfig client={wagmiClient}>
2022-12-07 18:34:36 -08:00
<div className="App">
2022-12-07 23:29:13 -08:00
<Profile/>
2022-12-07 18:47:26 -08:00
<h1>Airdrop App</h1>
<p>Add an address to airdrop to:</p>
2022-12-08 12:55:35 -08:00
<Addresses addressList={addressList} setAddressListFn={setAddressList} numTokens={numTokens} setNumTokens={setNumTokens}/>
<button disabled={airdropButtonDisabled} onClick={performAirdrop} >Perform Airdrop!</button>
2022-12-07 18:47:26 -08:00
<AddressList addressList={addressList} />
2022-12-07 18:34:36 -08:00
</div>
2022-12-07 23:29:13 -08:00
</WagmiConfig>
2022-12-07 18:34:36 -08:00
);
}
export default App;