getting contracts integrated
parent
86d37ab5dc
commit
525ee783d8
@ -0,0 +1,297 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { ethers, BigNumber } from 'ethers';
|
||||||
|
import { useAccount, useContractReads, useContractRead, usePrepareContractWrite, useContractWrite, useWaitForTransaction, erc721ABI } from 'wagmi';
|
||||||
|
import { NotificationContainer, NotificationManager } from 'react-notifications';
|
||||||
|
import debounce from 'lodash';
|
||||||
|
|
||||||
|
import MainABI from '../abi/main.json';
|
||||||
|
import '../styles/hero.css';
|
||||||
|
import Unaboomer from '../img/unaboomer.png';
|
||||||
|
import Mailbomb from '../img/mailbomb.png';
|
||||||
|
import Explosion from '../img/explosion.png';
|
||||||
|
import Arrow from '../img/arrow_right.png';
|
||||||
|
|
||||||
|
export function Hero(props) {
|
||||||
|
const contractAddress = props.contractAddress;
|
||||||
|
const [tokensMinted, setTokensMinted] = useState(() => {
|
||||||
|
const saved = localStorage.getItem('tokensMinted-v1');
|
||||||
|
return saved || JSON.stringify([])
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
localStorage.setItem('tokensMinted-v1', tokensMinted);
|
||||||
|
}, [tokensMinted]);
|
||||||
|
|
||||||
|
const [options, setOptions] = useState({
|
||||||
|
unaboomerAmount: 1,
|
||||||
|
bombAmount: 1,
|
||||||
|
sendBombAmount: 1,
|
||||||
|
unaboomerPreviewAmount: 1,
|
||||||
|
bombPreviewAmount: 1,
|
||||||
|
sendBombPreviewAmount: 1,
|
||||||
|
unaboomerPrice: 0,
|
||||||
|
bombPrice: ethers.utils.parseEther('.01'),
|
||||||
|
unaboomersMinted: 0,
|
||||||
|
unaboomerBalance: 0,
|
||||||
|
bombBalance: 0,
|
||||||
|
unaboomersRadicalized: 0,
|
||||||
|
bombsAssembled: 0,
|
||||||
|
bombsExploded: 0,
|
||||||
|
unaboomersKilled: 0,
|
||||||
|
leaderboardPointer: 0,
|
||||||
|
leaderAddress: '',
|
||||||
|
leaderKillCount: 0,
|
||||||
|
unaboomerMaxSupply: 0,
|
||||||
|
unaboomerMaxSurvivorCount: 0,
|
||||||
|
unaboomerMaxMintPerWallet: 0,
|
||||||
|
readWTF: false,
|
||||||
|
balancesFetched: false,
|
||||||
|
unaboomersByAddress: []
|
||||||
|
});
|
||||||
|
function handleStateChange(obj) {
|
||||||
|
setOptions(preState => ({...preState , ...obj}));
|
||||||
|
}
|
||||||
|
const { isConnected, address } = useAccount();
|
||||||
|
const defOpt = {
|
||||||
|
address: contractAddress,
|
||||||
|
abi: MainABI,
|
||||||
|
enabled: isConnected
|
||||||
|
}
|
||||||
|
// Fetch this stuff and cache aggressively since it doesn't change
|
||||||
|
useContractReads({
|
||||||
|
contracts: [
|
||||||
|
{...defOpt, functionName: 'unaboomerPrice'},
|
||||||
|
{...defOpt, functionName: 'bombPrice'},
|
||||||
|
{...defOpt, functionName: 'unaboomerMaxSupply'},
|
||||||
|
{...defOpt, functionName: 'unaboomerMaxSurvivorCount'},
|
||||||
|
{...defOpt, functionName: 'unaboomerMaxMintPerWallet'}
|
||||||
|
],
|
||||||
|
watch: true,
|
||||||
|
cacheTime: 30_000,
|
||||||
|
onSuccess(data) {
|
||||||
|
handleStateChange({
|
||||||
|
unaboomerPrice: data[0].toString(),
|
||||||
|
bombPrice: data[1].toString(),
|
||||||
|
unaboomerMaxSupply: Number(data[2]),
|
||||||
|
unaboomerMaxSurvivorCount: Number(data[3]),
|
||||||
|
unaboomerMaxMintPerWallet: Number(data[4])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Fetch this stuff more frequently as it updates constantly
|
||||||
|
useContractReads({
|
||||||
|
contracts: [
|
||||||
|
{...defOpt, functionName: 'unaboomersMinted', args: [address]},
|
||||||
|
{...defOpt, functionName: 'bombBalance', args: [address]},
|
||||||
|
{...defOpt, functionName: 'unaboomersRadicalized'},
|
||||||
|
{...defOpt, functionName: 'bombsAssembled'},
|
||||||
|
{...defOpt, functionName: 'bombsExploded'},
|
||||||
|
{...defOpt, functionName: 'unaboomersKilled'},
|
||||||
|
{...defOpt, functionName: 'leaderboardPointer'},
|
||||||
|
{...defOpt, functionName: 'unaboomerBalance', args: [address]}
|
||||||
|
],
|
||||||
|
watch: true,
|
||||||
|
cacheTime: 6_000,
|
||||||
|
onSuccess(data) {
|
||||||
|
handleStateChange({
|
||||||
|
unaboomersMinted: Number(data[0]),
|
||||||
|
bombBalance: Number(data[1]),
|
||||||
|
unaboomersRadicalized: Number(data[2]),
|
||||||
|
bombsAssembled: Number(data[3]),
|
||||||
|
bombsExploded: Number(data[4]),
|
||||||
|
unaboomersKilled: Number(data[5]),
|
||||||
|
leaderboardPointer: Number(data[6]),
|
||||||
|
balancesFetched: true,
|
||||||
|
unaboomerBalance: Number(data[7])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
useContractRead({
|
||||||
|
address: contractAddress,
|
||||||
|
abi: MainABI,
|
||||||
|
enabled: options.leaderboardPointer > 0,
|
||||||
|
functionName: 'leaderboard',
|
||||||
|
args: [options.leaderboardPointer],
|
||||||
|
watch: true,
|
||||||
|
cacheTime: 8_000,
|
||||||
|
onSuccess: async (data) => {
|
||||||
|
handleStateChange({
|
||||||
|
leaderAddress: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
useContractRead({
|
||||||
|
address: contractAddress,
|
||||||
|
abi: MainABI,
|
||||||
|
enabled: options.leaderAddress.length > 0,
|
||||||
|
functionName: 'killCount',
|
||||||
|
args: [options.leaderAddress],
|
||||||
|
watch: true,
|
||||||
|
cacheTime: 8_000,
|
||||||
|
onSuccess(data) {
|
||||||
|
handleStateChange({
|
||||||
|
leaderKillCount: Number(data),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const radicalizeBoomersPrepare = usePrepareContractWrite({
|
||||||
|
address: contractAddress,
|
||||||
|
abi: MainABI,
|
||||||
|
enabled: isConnected && options.unaboomersMinted < options.unaboomerMaxMintPerWallet && options.unaboomerAmount > 0 && options.balancesFetched,
|
||||||
|
functionName: 'radicalizeBoomers',
|
||||||
|
args: [options.unaboomerAmount],
|
||||||
|
overrides: {
|
||||||
|
from: address,
|
||||||
|
value: BigNumber.from((options.unaboomerPrice * options.unaboomerAmount).toString())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const radicalizeBoomersWrite = useContractWrite({
|
||||||
|
...radicalizeBoomersPrepare.config,
|
||||||
|
onError(data) {
|
||||||
|
if (data.message.startsWith('user rejected transaction')) NotificationManager.info(`tx cancelled`, 'ok', 4000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const assembleBombsPrepare = usePrepareContractWrite({
|
||||||
|
address: contractAddress,
|
||||||
|
abi: MainABI,
|
||||||
|
enabled: isConnected && options.bombAmount > 0,
|
||||||
|
functionName: 'assembleBombs',
|
||||||
|
args: [options.bombAmount],
|
||||||
|
overrides: {
|
||||||
|
from: address,
|
||||||
|
value: BigNumber.from((options.bombPrice * options.bombAmount).toString())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const assembleBombsWrite = useContractWrite({
|
||||||
|
...assembleBombsPrepare.config,
|
||||||
|
onError(data) {
|
||||||
|
if (data.message.startsWith('user rejected transaction')) NotificationManager.info(`tx cancelled`, 'ok', 4000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const sendBombsPrepare = usePrepareContractWrite({
|
||||||
|
address: contractAddress,
|
||||||
|
abi: MainABI,
|
||||||
|
enabled: isConnected && options.bombBalance > 0,
|
||||||
|
functionName: 'sendBombs',
|
||||||
|
cacheTime: 0,
|
||||||
|
staleTime: 400,
|
||||||
|
args: [options.sendBombAmount]
|
||||||
|
});
|
||||||
|
const sendBombsWrite = useContractWrite({
|
||||||
|
...sendBombsPrepare.config,
|
||||||
|
onError(data) {
|
||||||
|
if (data.message.startsWith('user rejected transaction')) NotificationManager.info(`tx cancelled`, 'ok', 4000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
useWaitForTransaction({
|
||||||
|
hash: radicalizeBoomersWrite.data?.hash,
|
||||||
|
enabled: radicalizeBoomersWrite.status === 'success',
|
||||||
|
onSuccess(data) {
|
||||||
|
let tm = JSON.parse(tokensMinted);
|
||||||
|
const iface = new ethers.utils.Interface(erc721ABI);
|
||||||
|
data.logs.filter(log =>
|
||||||
|
log.topics[0] === '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
|
||||||
|
).map((log) => {
|
||||||
|
const res = iface.decodeEventLog("Transfer", log.data, log.topics);
|
||||||
|
NotificationManager.success(`You radicalized Unaboomer #${res.tokenId.toString()}`, '', 4000);
|
||||||
|
tm.push(Number(res.tokenId));
|
||||||
|
});
|
||||||
|
setTokensMinted(JSON.stringify(tm));
|
||||||
|
console.log(tm);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
useWaitForTransaction({
|
||||||
|
hash: sendBombsWrite.data?.hash,
|
||||||
|
enabled: sendBombsWrite.status === 'success',
|
||||||
|
onSuccess(data) {
|
||||||
|
const iface = new ethers.utils.Interface(MainABI);
|
||||||
|
data.logs.filter(log =>
|
||||||
|
log.topics[0] === '0x38c7e2e8001cefb27535bd6bcc6363c6d6a6a83dbb77f092b78956334596f9ed'
|
||||||
|
).map((log) => {
|
||||||
|
const res = iface.decodeEventLog("SentBomb", log.data, log.topics);
|
||||||
|
if (res.hit) {
|
||||||
|
if (res.owned) {
|
||||||
|
NotificationManager.error(`Your bomb exploded during assembly and killed your Unaboomer ${res.tokenId.toString()}`, '', 8000);
|
||||||
|
} else {
|
||||||
|
NotificationManager.success(`Your bomb killed Unaboomer ${res.tokenId.toString()}`, '', 8000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NotificationManager.warning(`Your bomb for Unaboomer ${res.tokenId.toString()} was a dud`, '', 8000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id='hero'>
|
||||||
|
<h1>the web3 revolution & its consequences have been a disaster for the human race.</h1>
|
||||||
|
<p>
|
||||||
|
Technology is advancing at an exponential rate and boomers are being left behind. A.I., Bitcoin,
|
||||||
|
and expensive JPEGs have made them angry. <br /><br />
|
||||||
|
They've begun to radicalize. {options.unaboomerMaxSupply > 0 ? '35,000': options.unaboomerMaxSupply} Boomers have joined forces
|
||||||
|
to lash out at the system.<br /><br />
|
||||||
|
</p>
|
||||||
|
<div id='heroFlex'>
|
||||||
|
<div className='heroFlexItem'>
|
||||||
|
<img src={Unaboomer} width='280px' alt='Pixelated Unaboomer profile picture - a hooded man with dark sunglasses.' />
|
||||||
|
|
||||||
|
{options.unaboomersMinted > 0 && (
|
||||||
|
<p>
|
||||||
|
You have minted {options.unaboomersMinted} Unaboomers.
|
||||||
|
{options.unaboomersKilled > 0 && <>{options.unaboomersKilled} are dead.</>}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<br />
|
||||||
|
{isConnected
|
||||||
|
&& options.unaboomersMinted < options.unaboomerMaxMintPerWallet
|
||||||
|
&& options.unaboomersKilled + options.unaboomersRadicalized < options.unaboomerMaxSupply
|
||||||
|
&& (
|
||||||
|
<>
|
||||||
|
<input type='number' step='1' name='bombAmountPreview' defaultValue={1} min={1} max={options.unaboomerMaxMintPerWallet - options.unaboomersMinted} onChange={(v) => {
|
||||||
|
handleStateChange({unaboomerAmount: v.target.value});
|
||||||
|
radicalizeBoomersWrite.reset()
|
||||||
|
}}></input>
|
||||||
|
<button className='doThing' disabled={radicalizeBoomersPrepare.status == 'error'} onClick={() => radicalizeBoomersWrite.write?.()}>
|
||||||
|
{radicalizeBoomersWrite.isLoading && <>minting {options.unaboomerAmount}</>}
|
||||||
|
{radicalizeBoomersWrite.isIdle && <>Radicalize {options.unaboomerAmount == 1 ? 'a Unaboomer': <>{options.unaboomerAmount} Unaboomers</>}</>}
|
||||||
|
{radicalizeBoomersWrite.isSuccess && <>sent</>}
|
||||||
|
{radicalizeBoomersWrite.isError && <>error</>}
|
||||||
|
</button>
|
||||||
|
<p>({ethers.utils.formatEther((options.unaboomerPrice * options.unaboomerAmount).toString())} ETH)</p>
|
||||||
|
</>
|
||||||
|
) || options.unaboomersMinted == options.unaboomerMaxMintPerWallet && options.unaboomersKilled + options.unaboomersRadicalized < options.unaboomerMaxSupply && (
|
||||||
|
<h2>max per wallet reached</h2>
|
||||||
|
) || options.unaboomersRadicalized == options.unaboomerMaxSupply && options.unaboomerMaxSupply > 0 && (
|
||||||
|
<h2>max supply reached</h2>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className='heroFlexArrow'>
|
||||||
|
<img src={Arrow} width='100px' alt='Arrow pointing to the next step.' />
|
||||||
|
</div>
|
||||||
|
<div className='heroFlexItem'>
|
||||||
|
<img src={Mailbomb} width='280px' alt='Pixelated Mailbomb image - handle with caution.' />
|
||||||
|
<p>
|
||||||
|
Don't let the Boomers win, fight back! Assemble a mailbomb and blow 'em to smithereens. <br /><br />
|
||||||
|
(Warning: Some bombs are duds!)
|
||||||
|
</p>
|
||||||
|
<button className='doThing buttom'>assemble mailbomb</button>
|
||||||
|
<p>(.01 ETH)</p>
|
||||||
|
</div>
|
||||||
|
<div className='heroFlexArrow'>
|
||||||
|
<img src={Arrow} width='100px' alt='Arrow pointing to the next step.' />
|
||||||
|
</div>
|
||||||
|
<div className='heroFlexItem'>
|
||||||
|
<img src={Explosion} width='280px' alt='Pixelated explosion image.' />
|
||||||
|
<p>
|
||||||
|
Ready for mayhem? Burn your mailrooms to blow up a random boomer. <br /><br />
|
||||||
|
If your bomb is live it will destroy a Boomer PFP forever. <br /><br />
|
||||||
|
(Warning: Your Boomer might explode!)
|
||||||
|
</p>
|
||||||
|
<button className='doThing buttom'>mail a bomb</button>
|
||||||
|
<p>(0 ETH)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -1,55 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
import '../styles/hero.css';
|
|
||||||
import Unaboomer from '../img/unaboomer.png';
|
|
||||||
import Mailbomb from '../img/mailbomb.png';
|
|
||||||
import Explosion from '../img/explosion.png';
|
|
||||||
import Arrow from '../img/arrow_right.png';
|
|
||||||
|
|
||||||
export class Hero extends React.Component {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div id='hero'>
|
|
||||||
<h1>the web3 revolution & its consequences have been a disaster for the human race.</h1>
|
|
||||||
<div id='heroFlex'>
|
|
||||||
<div className='heroFlexItem'>
|
|
||||||
<img src={Unaboomer} width='280px' alt='Pixelated Unaboomer profile picture - a hooded man with dark sunglasses.' />
|
|
||||||
<p>
|
|
||||||
Technology is advancing at an exponential rate and boomers are being left behind. A.I., Bitcoin,
|
|
||||||
and expensive JPEGs have made them angry. <br /><br />
|
|
||||||
They've begun to radicalize. 35,000 Boomers have joined forces
|
|
||||||
to lash out at the system.
|
|
||||||
</p>
|
|
||||||
<button className='doThing buttom'>Radicalize boomer</button>
|
|
||||||
<p>(0 ETH)</p>
|
|
||||||
</div>
|
|
||||||
<div className='heroFlexArrow'>
|
|
||||||
<img src={Arrow} width='100px' alt='Arrow pointing to the next step.' />
|
|
||||||
</div>
|
|
||||||
<div className='heroFlexItem'>
|
|
||||||
<img src={Mailbomb} width='280px' alt='Pixelated Mailbomb image - handle with caution.' />
|
|
||||||
<p>
|
|
||||||
Don't let the Boomers win, fight back! Assemble a mailbomb and blow 'em to smithereens. <br /><br />
|
|
||||||
(Warning: Some bombs are duds!)
|
|
||||||
</p>
|
|
||||||
<button className='doThing buttom'>assemble mailbomb</button>
|
|
||||||
<p>(.01 ETH)</p>
|
|
||||||
</div>
|
|
||||||
<div className='heroFlexArrow'>
|
|
||||||
<img src={Arrow} width='100px' alt='Arrow pointing to the next step.' />
|
|
||||||
</div>
|
|
||||||
<div className='heroFlexItem'>
|
|
||||||
<img src={Explosion} width='280px' alt='Pixelated explosion image.' />
|
|
||||||
<p>
|
|
||||||
Ready for mayhem? Burn your mailrooms to blow up a random boomer. <br /><br />
|
|
||||||
If your bomb is live it will destroy a Boomer PFP forever. <br /><br />
|
|
||||||
(Warning: Your Boomer might explode!)
|
|
||||||
</p>
|
|
||||||
<button className='doThing buttom'>mail a bomb</button>
|
|
||||||
<p>(0 ETH)</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue