Skip to content

Commit

Permalink
feat: refactor + connect page + header
Browse files Browse the repository at this point in the history
  • Loading branch information
0xhohenheim committed Jun 12, 2024
1 parent c3a3092 commit a5a9dd5
Show file tree
Hide file tree
Showing 19 changed files with 440 additions and 244 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Create Wagmi</title>
<title>Batch Payouts</title>
</head>
<body>
<div id="root"></div>
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"@tanstack/react-query": "5.0.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-toastify": "^10.0.5",
"viem": "latest",
"wagmi": "latest"
},
Expand All @@ -23,6 +24,7 @@
"@vitejs/plugin-react": "^4.1.0",
"@wagmi/cli": "latest",
"buffer": "^6.0.3",
"sass": "^1.77.4",
"typescript": "^5.2.2",
"vite": "^4.4.9"
}
Expand Down
257 changes: 151 additions & 106 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

137 changes: 50 additions & 87 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,97 +1,60 @@
import { useAccount, useConnect, useDisconnect } from 'wagmi'
import { useAccount } from 'wagmi'
import { useWriteContracts, useCallsStatus } from 'wagmi/experimental'
import Connect from './components/Connect'
import Payout from './components/Payout'

const abi = [
{
stateMutability: 'nonpayable',
type: 'function',
inputs: [{ name: 'to', type: 'address' }],
name: 'safeMint',
outputs: [],
}
{
stateMutability: 'nonpayable',
type: 'function',
inputs: [{ name: 'to', type: 'address' }],
name: 'safeMint',
outputs: [],
}
] as const

function App() {
const account = useAccount()
const { connectors, connect, status, error } = useConnect()
const { disconnect } = useDisconnect()
const { data: id, writeContracts } = useWriteContracts()
const { data: callsStatus } = useCallsStatus({
id: id as string,
query: {
enabled: !!id,
// Poll every second until the calls are confirmed
refetchInterval: (data) =>
data.state.data?.status === "CONFIRMED" ? false : 1000,
},
});

const handleMint = () => {
writeContracts({
contracts: [
{
address: "0x119Ea671030FBf79AB93b436D2E20af6ea469a19",
abi,
functionName: "safeMint",
args: [account.address],
},
{
address: "0x119Ea671030FBf79AB93b436D2E20af6ea469a19",
abi,
functionName: "safeMint",
args: [account.address],
const account = useAccount()
const { data: id, writeContracts } = useWriteContracts()
const { data: callsStatus } = useCallsStatus({
id: id as string,
query: {
enabled: !!id,
// Poll every second until the calls are confirmed
refetchInterval: (data) =>
data.state.data?.status === "CONFIRMED" ? false : 1000,
},
{
address: "0x119Ea671030FBf79AB93b436D2E20af6ea469a19",
abi,
functionName: "safeMint",
args: [account.address],
}
],
})
}


return (
<>
<div>
<h2>Account</h2>

<div>
status: {account.status}
<br />
addresses: {JSON.stringify(account.addresses)}
<br />
chainId: {account.chainId}
</div>

{account.status === 'connected' && (
<button type="button" onClick={() => disconnect()}>
Disconnect
</button>
)}
</div>

<div>
<h2>Connect</h2>
{connectors.map((connector) => (
<button
key={connector.uid}
onClick={() => connect({ connector })}
type="button"
>
{connector.name}
</button>
))}
<div>{status}</div>
<div>{error?.message}</div>
<div>
<button onClick={handleMint}>Mint</button>
{callsStatus && <div> Status: {callsStatus.status}</div>}
</div>
</div>
</>
)
});

const handleMint = () => {
writeContracts({
contracts: [
{
address: "0x119Ea671030FBf79AB93b436D2E20af6ea469a19",
abi,
functionName: "safeMint",
args: [account.address],
},
{
address: "0x119Ea671030FBf79AB93b436D2E20af6ea469a19",
abi,
functionName: "safeMint",
args: [account.address],
},
{
address: "0x119Ea671030FBf79AB93b436D2E20af6ea469a19",
abi,
functionName: "safeMint",
args: [account.address],
}
],
})
}

if (!account.isConnected)
return (<Connect />)
else
return (<Payout />)
}

export default App
1 change: 1 addition & 0 deletions src/assets/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as logoutIcon } from "./logout.png";
Binary file added src/assets/logout.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions src/components/Connect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import styles from "../styles/Connect.module.scss";
import { useConnect } from "wagmi";

export default function Connect(): React.JSX.Element {
const { connectors, connect, error, isPending } = useConnect();

return (
<div className={styles.main}>
<h1>The Batch Payouts App</h1>
<span className={styles.subtitle}>Powered by Crypto</span>
<button
key={connectors[0].uid}
className={`${styles.connectBttn} ${isPending ? styles.shimmer : ""}`}
onClick={() => connect({ connector: connectors[0] })}
type="button"
>
{connectors[0].name}
</button>
{error && <span className={styles.errorMsg}>{error.message}</span>}
</div>
);
};
38 changes: 38 additions & 0 deletions src/components/Payout/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from "react";
import styles from "../../styles/Payout/Header.module.scss";
import { useAccount, useDisconnect } from "wagmi";
import { toast } from "react-toastify";
import { logoutIcon } from "../../assets";

export default function Header(): React.JSX.Element {
const { address, chain } = useAccount();
const { disconnect, isPending } = useDisconnect();

const copyToClipboard = () => {
try {
navigator.clipboard.writeText(address as string);
toast.success("Copied to clipboard!")
} catch (err) {
toast.error("Failed to copy!")
}
}

return (
<div className={styles.main}>
<h1>The Batch Payouts App</h1>
<div className={styles.walletContainer}>
<div
onClick={copyToClipboard}
className={`${styles.address} ${isPending ? styles.shimmer : ""}`}>
{address?.slice(0, 5) + "..." + address?.slice(-5)}
</div>
<div className={styles.details}>
<span>Network: {chain?.name}</span>
<button className={styles.logoutBttn} onClick={() => { disconnect(); }}>
<img src={logoutIcon} alt="Logout" />
</button>
</div>
</div>
</div>
);
};
13 changes: 13 additions & 0 deletions src/components/Payout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";
import styles from "../../styles/Payout/Payout.module.scss";
import Header from "./Header";

export default function Payout(): React.JSX.Element {
return (
<div className={styles.main}>
<div className={styles.inner}>
<Header />
</div>
</div>
);
};
19 changes: 19 additions & 0 deletions src/configs/wagmi.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { http, createConfig } from 'wagmi';
import { baseSepolia } from 'wagmi/chains';
import { coinbaseWallet } from 'wagmi/connectors';

export const config = createConfig({
chains: [baseSepolia],
connectors: [
coinbaseWallet({ appName: 'Batch Payouts', preference: 'smartWalletOnly' }),
],
transports: {
[baseSepolia.id]: http(),
},
});

declare module 'wagmi' {
interface Register {
config: typeof config;
}
}
21 changes: 0 additions & 21 deletions src/index.css

This file was deleted.

22 changes: 12 additions & 10 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@ import { Buffer } from 'buffer'
import React from 'react'
import ReactDOM from 'react-dom/client'
import { WagmiProvider } from 'wagmi'

import App from './App.tsx'
import { config } from './wagmi.ts'
import { config } from './configs/wagmi.config.ts'
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

import './index.css'
import './styles/global.scss'

globalThis.Buffer = Buffer

const queryClient = new QueryClient()

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</WagmiProvider>
</React.StrictMode>,
<React.StrictMode>
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</WagmiProvider>
<ToastContainer position='top-center' stacked/>
</React.StrictMode>,
)
33 changes: 33 additions & 0 deletions src/styles/Connect.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@import './_variables.scss';
@import './_animations.scss';

.main {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
text-align: center;

.subtitle {
text-transform: uppercase;
font-size: small;
margin-bottom: 20px;
}

.connectBttn {
padding: 10px 40px;
background-color: $coinbase-blue;
color: white;
border-radius: 30px;
border: none;
outline: none;
cursor: pointer;
}

.errorMsg {
color: red;
font-size: small;
}
}
Loading

0 comments on commit a5a9dd5

Please sign in to comment.