|
|
@ -1,9 +1,14 @@
|
|
|
|
import { useState } from 'react';
|
|
|
|
import { useState } from 'react';
|
|
|
|
import { WagmiConfig, createClient, useAccount, useConnect, useDisconnect, useContractReads, configureChains } from 'wagmi';
|
|
|
|
import {
|
|
|
|
|
|
|
|
WagmiConfig, createClient, useAccount,
|
|
|
|
|
|
|
|
useConnect, useDisconnect, useContractReads,
|
|
|
|
|
|
|
|
configureChains, useContractWrite, usePrepareContractWrite,
|
|
|
|
|
|
|
|
useWaitForTransaction
|
|
|
|
|
|
|
|
} from 'wagmi';
|
|
|
|
import { localhost, goerli } from 'wagmi/chains';
|
|
|
|
import { localhost, goerli } from 'wagmi/chains';
|
|
|
|
import { publicProvider } from 'wagmi/providers/public';
|
|
|
|
import { publicProvider } from 'wagmi/providers/public';
|
|
|
|
import { InjectedConnector } from 'wagmi/connectors/injected';
|
|
|
|
import { InjectedConnector } from 'wagmi/connectors/injected';
|
|
|
|
import { ethers, getDefaultProvider } from 'ethers';
|
|
|
|
import { ethers, BigNumber } from 'ethers';
|
|
|
|
import ABI from './abi.json';
|
|
|
|
import ABI from './abi.json';
|
|
|
|
import 'bulma/css/bulma.min.css';
|
|
|
|
import 'bulma/css/bulma.min.css';
|
|
|
|
|
|
|
|
|
|
|
@ -36,12 +41,13 @@ function Contract() {
|
|
|
|
phraseSet: false,
|
|
|
|
phraseSet: false,
|
|
|
|
mintAmount: 1,
|
|
|
|
mintAmount: 1,
|
|
|
|
balance: 0,
|
|
|
|
balance: 0,
|
|
|
|
hash: ''
|
|
|
|
hash: '',
|
|
|
|
|
|
|
|
txPending: false
|
|
|
|
});
|
|
|
|
});
|
|
|
|
function handleStateChange(obj) {
|
|
|
|
function handleStateChange(obj) {
|
|
|
|
setOptions(preState => ({...preState , ...obj}));
|
|
|
|
setOptions(preState => ({...preState , ...obj}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const { data, isError, isLoading } = useContractReads({
|
|
|
|
useContractReads({
|
|
|
|
contracts: [
|
|
|
|
contracts: [
|
|
|
|
{..._contract, functionName: 'totalSupply'},
|
|
|
|
{..._contract, functionName: 'totalSupply'},
|
|
|
|
{..._contract, functionName: 'max'},
|
|
|
|
{..._contract, functionName: 'max'},
|
|
|
@ -49,7 +55,7 @@ function Contract() {
|
|
|
|
{..._contract, functionName: 'winners'},
|
|
|
|
{..._contract, functionName: 'winners'},
|
|
|
|
{..._contract, functionName: 'winningAmount'},
|
|
|
|
{..._contract, functionName: 'winningAmount'},
|
|
|
|
{..._contract, functionName: 'phraseSet'},
|
|
|
|
{..._contract, functionName: 'phraseSet'},
|
|
|
|
{..._contract, functionName: 'balanceOf'},
|
|
|
|
{..._contract, functionName: 'balanceOf', args: [address]},
|
|
|
|
{..._contract, functionName: 'winningPhraseHash'},
|
|
|
|
{..._contract, functionName: 'winningPhraseHash'},
|
|
|
|
],
|
|
|
|
],
|
|
|
|
watch: true,
|
|
|
|
watch: true,
|
|
|
@ -61,27 +67,55 @@ function Contract() {
|
|
|
|
price: Number(data[2]),
|
|
|
|
price: Number(data[2]),
|
|
|
|
winners: Number(data[3]),
|
|
|
|
winners: Number(data[3]),
|
|
|
|
winningAmount: Number(data[4]),
|
|
|
|
winningAmount: Number(data[4]),
|
|
|
|
phraseSet: Number(data[5]),
|
|
|
|
phraseSet: data[5],
|
|
|
|
balance: Number(data[6]),
|
|
|
|
balance: Number(data[6]),
|
|
|
|
hash: data[7].toString()
|
|
|
|
hash: data[7].toString()
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
const mintPrepare = usePrepareContractWrite({
|
|
|
|
if (isConnected)
|
|
|
|
address: contractAddress,
|
|
|
|
|
|
|
|
abi: ABI,
|
|
|
|
|
|
|
|
enabled: isConnected && options.mintAmount > 0,
|
|
|
|
|
|
|
|
functionName: 'mint',
|
|
|
|
|
|
|
|
args: [options.mintAmount],
|
|
|
|
|
|
|
|
overrides: {
|
|
|
|
|
|
|
|
from: address,
|
|
|
|
|
|
|
|
value: BigNumber.from((options.price * options.mintAmount).toString())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
const mintWrite = useContractWrite({
|
|
|
|
|
|
|
|
...mintPrepare.config,
|
|
|
|
|
|
|
|
onError(data) {
|
|
|
|
|
|
|
|
// if (data.message.startsWith('user rejected transaction')) NotificationManager.info(`tx cancelled`, 'ok', 4000);
|
|
|
|
|
|
|
|
mintWrite.reset();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
useWaitForTransaction({
|
|
|
|
|
|
|
|
hash: mintWrite.data?.hash,
|
|
|
|
|
|
|
|
enabled: mintWrite.status === 'success',
|
|
|
|
|
|
|
|
onSuccess() {
|
|
|
|
|
|
|
|
handleStateChange({txPending: false});
|
|
|
|
|
|
|
|
mintWrite.reset();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
if (isConnected && options.phraseSet)
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<>
|
|
|
|
<button className="button" style={{marginBottom: '1em'}} onClick={() => disconnect()}>Disconnect Wallet</button>
|
|
|
|
<button className="button" style={{marginBottom: '1em'}} onClick={() => disconnect()}>Disconnect Wallet</button>
|
|
|
|
<div className="block">
|
|
|
|
<div className="block">
|
|
|
|
<h1 className="heading">Price: {ethers.utils.formatEther((options.price * options.mintAmount).toString())} ETH</h1>
|
|
|
|
<h1 className="heading">Price: {ethers.utils.formatEther((options.price * options.mintAmount).toString())} ETH</h1>
|
|
|
|
<div class="field has-addons">
|
|
|
|
<div className="field has-addons">
|
|
|
|
<div class="control">
|
|
|
|
<div className="control">
|
|
|
|
<input class="input" type="text" placeholder="Mint amount" value={options.mintAmount} onChange={(v) => {
|
|
|
|
<input className="input" type="text" placeholder="Mint amount" value={options.mintAmount} onChange={(v) => {
|
|
|
|
if (v.target.value >= 0) handleStateChange({mintAmount: Number(v.target.value)})}
|
|
|
|
if (v.target.value >= 0) handleStateChange({mintAmount: Number(v.target.value)})}
|
|
|
|
}></input>
|
|
|
|
}></input>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="control">
|
|
|
|
<div className="control">
|
|
|
|
<a class="button is-info">
|
|
|
|
<a className={"button is-info " + ((options.txPending) && "is-loading")} disabled={mintPrepare.status == 'error'} onClick={() => {
|
|
|
|
|
|
|
|
mintWrite.write?.();
|
|
|
|
|
|
|
|
handleStateChange({txPending: true});
|
|
|
|
|
|
|
|
}}>
|
|
|
|
Mint
|
|
|
|
Mint
|
|
|
|
</a>
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
@ -93,11 +127,17 @@ function Contract() {
|
|
|
|
<h1 className="heading">Minted {options.totalSupply} / {options.max}</h1>
|
|
|
|
<h1 className="heading">Minted {options.totalSupply} / {options.max}</h1>
|
|
|
|
<progress className="progress is-primary" value={options.totalSupply} max={options.max}></progress>
|
|
|
|
<progress className="progress is-primary" value={options.totalSupply} max={options.max}></progress>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="notification is-info" style={{marginTop: '2em'}}>
|
|
|
|
<div className="notification is-info" style={{marginTop: '2em'}}>
|
|
|
|
The secret phrase containing the pre-determined winners is: <strong>{options.hash}</strong>
|
|
|
|
The secret phrase containing the pre-determined winners is: <strong>{options.hash}</strong>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
if (isConnected && !options.phraseSet)
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
|
|
<>
|
|
|
|
|
|
|
|
<h3 style={{fontSize: '2em'}}>Not minting yet. Come back later.</h3>
|
|
|
|
|
|
|
|
</>
|
|
|
|
|
|
|
|
)
|
|
|
|
return <button className="button is-dark" onClick={() => connect()}>Connect Wallet</button>
|
|
|
|
return <button className="button is-dark" onClick={() => connect()}>Connect Wallet</button>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -111,7 +151,8 @@ function App() {
|
|
|
|
A Few Of Us Are Going To Make It.
|
|
|
|
A Few Of Us Are Going To Make It.
|
|
|
|
</p>
|
|
|
|
</p>
|
|
|
|
<p className="subtitle">
|
|
|
|
<p className="subtitle">
|
|
|
|
An NFT Lottery. Mint a token for your chance to win 1 ETH. 10 tokens are pre-determined to win.
|
|
|
|
An NFT Lottery. 10 tokens are pre-determined to win.<br />
|
|
|
|
|
|
|
|
Mint one for your chance to win 1 ETH!
|
|
|
|
</p>
|
|
|
|
</p>
|
|
|
|
<Contract />
|
|
|
|
<Contract />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|