getting contracts integrated

master
lza_menace 2 years ago
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>
)
}

@ -11,13 +11,13 @@ import { mainnet, goerli, localhost } from 'wagmi/chains';
import { infuraProvider } from 'wagmi/providers/infura' import { infuraProvider } from 'wagmi/providers/infura'
import { publicProvider } from 'wagmi/providers/public'; import { publicProvider } from 'wagmi/providers/public';
import { Navbar } from "./sections/Navbar"; import { Navbar } from "./components/Navbar";
import { Hero } from "./sections/Hero"; import { Hero } from "./components/Hero";
const { chains, provider, webSocketProvider } = configureChains( const { chains, provider, webSocketProvider } = configureChains(
[mainnet, goerli, localhost], [mainnet, goerli, localhost],
[ [
infuraProvider({ apiKey: 'e7674eea9d72437d9129b41ed018183d' }), // infuraProvider({ apiKey: 'e7674eea9d72437d9129b41ed018183d' }),
publicProvider() publicProvider()
] ]
); );
@ -37,10 +37,8 @@ const wagmiClient = createClient({
ReactDOM.createRoot(document.getElementById("root")).render( ReactDOM.createRoot(document.getElementById("root")).render(
<WagmiConfig client={wagmiClient}> <WagmiConfig client={wagmiClient}>
<RainbowKitProvider chains={chains} initialChain={1337}> <RainbowKitProvider chains={chains} initialChain={1337}>
<div className="scrollContainer">
<Navbar /> <Navbar />
<Hero /> <Hero contractAddress={'0x5FbDB2315678afecb367f032d93F642f64180aa3'} />
</div>
</RainbowKitProvider> </RainbowKitProvider>
</WagmiConfig> </WagmiConfig>
); );

@ -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>
)
}
}

@ -18,7 +18,6 @@
.heroFlexItem { .heroFlexItem {
flex: 0 25%; flex: 0 25%;
height: 100%; height: 100%;
width: 200px;
text-align: center; text-align: center;
} }
@ -33,4 +32,16 @@
button.doThing { button.doThing {
margin: 1em; margin: 1em;
cursor: pointer;
transition: .1s ease all;
}
button.doThing:hover {
transform: translate(4px, 10%);
box-shadow: 1px 1px 0px #f9f9f9;
transition: .1s ease all;
}
button.doThing:disabled {
background-color: grey;
} }

@ -20,8 +20,8 @@ button {
padding: 1em; padding: 1em;
border-radius: 0; border-radius: 0;
border: 0; border: 0;
box-shadow: 0 5px #f9f9f9; box-shadow: 5px 5px 0 #f9f9f9;
clip-path: polygon( /* clip-path: polygon(
0px 20px, 0px 20px,
4px 20px, 4px 20px,
4px 12px, 4px 12px,
@ -62,5 +62,5 @@ button {
4px calc(100% - 16px), 4px calc(100% - 16px),
4px calc(100% - 20px), 4px calc(100% - 20px),
0px calc(100% - 20px) 0px calc(100% - 20px)
); ); */
} }

Loading…
Cancel
Save