get distracted by non-essential frontend stuff
This commit is contained in:
parent
fec688478b
commit
6ccaac1195
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
contract MessageBox {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useStore } from "../store";
|
||||
import { shortenAddress, tryWithToast } from "../utils";
|
||||
import { tryWithToast } from "../utils/toast";
|
||||
import { formatPadTokenAmount, shortenAddress } from "../utils/ui";
|
||||
import { web3 } from "../web3";
|
||||
|
||||
export function ConnectMetamaskButton() {
|
||||
|
|
@ -8,6 +9,7 @@ export function ConnectMetamaskButton() {
|
|||
const unsetConnectedAccount = useStore(
|
||||
(state) => state.unsetConnectedAccount
|
||||
);
|
||||
const padTokenBalance = useStore((state) => state.padTokenBalance);
|
||||
|
||||
// https://docs.web3js.org/guides/getting_started/metamask/#react-app
|
||||
async function connectMetamask() {
|
||||
|
|
@ -35,7 +37,18 @@ export function ConnectMetamaskButton() {
|
|||
connectedAccount ? disconnectWallet() : connectMetamask()
|
||||
}
|
||||
>
|
||||
{connectedAccount ? shortenAddress(connectedAccount) : "Connect MetaMask"}
|
||||
{connectedAccount ? (
|
||||
<>
|
||||
{shortenAddress(connectedAccount)}
|
||||
{padTokenBalance !== null && (
|
||||
<div className="badge badge-secondary">
|
||||
{formatPadTokenAmount(padTokenBalance)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
"Connect MetaMask"
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import { buildMainContextValue, MainContext } from "../contexts/MainContext";
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function ContextsProvider({ children }: Props) {
|
||||
const mainContextValue = buildMainContextValue();
|
||||
|
||||
return (
|
||||
<MainContext.Provider value={mainContextValue}>
|
||||
{children}
|
||||
</MainContext.Provider>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { useStore } from "../store";
|
||||
import buildContext from "../utils/context";
|
||||
import { padToken } from "../web3";
|
||||
|
||||
interface IMainContext {
|
||||
fetchPadTokenBalance: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const [MainContext, useMainContext] = buildContext<IMainContext>();
|
||||
|
||||
export function buildMainContextValue(): IMainContext {
|
||||
const connectedAccount = useStore((state) => state.connectedAccount);
|
||||
const setPadTokenBalance = useStore((state) => state.setPadTokenBalance);
|
||||
const unsetPadTokenBalance = useStore((state) => state.unsetPadTokenBalance);
|
||||
|
||||
const fetchPadTokenBalance = async () => {
|
||||
const balance: bigint = await padToken.methods
|
||||
.balanceOf(connectedAccount)
|
||||
.call();
|
||||
if (typeof balance === "bigint") {
|
||||
setPadTokenBalance(balance);
|
||||
} else {
|
||||
unsetPadTokenBalance();
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (connectedAccount) {
|
||||
fetchPadTokenBalance();
|
||||
}
|
||||
}, [connectedAccount]);
|
||||
|
||||
return {
|
||||
fetchPadTokenBalance,
|
||||
};
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"MessageBoxModule#MessageBox": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
|
||||
"MainModule#PADToken": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9"
|
||||
"MainModule#PADToken": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
|
||||
"MessageBoxModule#MessageBox": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { RouterProvider, createRouter } from "@tanstack/react-router";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { ContextsProvider } from "./components/ContextsProvider";
|
||||
import "./index.css";
|
||||
import { routeTree } from "./routeTree.gen";
|
||||
|
||||
|
|
@ -13,6 +14,8 @@ declare module "@tanstack/react-router" {
|
|||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<RouterProvider router={router} />
|
||||
<ContextsProvider>
|
||||
<RouterProvider router={router} />
|
||||
</ContextsProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { createLazyFileRoute } from "@tanstack/react-router";
|
||||
import { useState } from "react";
|
||||
import { useStore } from "../store";
|
||||
import { toastError, tryWithToast } from "../utils";
|
||||
import { toastError, tryWithToast } from "../utils/toast";
|
||||
import { messageBox } from "../web3";
|
||||
|
||||
export const Route = createLazyFileRoute("/message-box")({
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { createLazyFileRoute } from "@tanstack/react-router";
|
||||
import { useState } from "react";
|
||||
import type { Numbers } from "web3";
|
||||
import { useStore } from "../store";
|
||||
import { getFormInputValue, toastError, tryWithToast } from "../utils";
|
||||
import { getFormInputValue } from "../utils/form";
|
||||
import { toastError, tryWithToast } from "../utils/toast";
|
||||
import { formatPadTokenAmount } from "../utils/ui";
|
||||
import { padToken, web3 } from "../web3";
|
||||
|
||||
export const Route = createLazyFileRoute("/pad-token")({
|
||||
|
|
@ -28,10 +29,8 @@ function PadTokenPage() {
|
|||
}
|
||||
|
||||
await tryWithToast("Balance Of", async () => {
|
||||
const balanceBN: Numbers = await padToken.methods
|
||||
.balanceOf(address)
|
||||
.call();
|
||||
setBalance(web3.utils.fromWei(balanceBN, "ether"));
|
||||
const _balance: bigint = await padToken.methods.balanceOf(address).call();
|
||||
setBalance(formatPadTokenAmount(_balance));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -86,7 +85,7 @@ function PadTokenPage() {
|
|||
Get
|
||||
</button>
|
||||
<div>
|
||||
<span className="font-bold">Balance:</span> {balance} PAD
|
||||
<span className="font-bold">Balance:</span> {balance}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
import { create } from "zustand";
|
||||
|
||||
interface State {
|
||||
connectedAccount: string | null;
|
||||
setConnectedAccount: (connectedAccount: string) => void;
|
||||
unsetConnectedAccount: () => void;
|
||||
padTokenBalance: bigint | null;
|
||||
setPadTokenBalance: (padTokenBalance: bigint) => void;
|
||||
unsetPadTokenBalance: () => void;
|
||||
}
|
||||
|
||||
export const useStore = create<State>()((set, get) => ({
|
||||
connectedAccount: null,
|
||||
setConnectedAccount: (connectedAccount) => set({ connectedAccount }),
|
||||
unsetConnectedAccount: () => set({ connectedAccount: null }),
|
||||
padTokenBalance: null,
|
||||
setPadTokenBalance: (padTokenBalance) => set({ padTokenBalance }),
|
||||
unsetPadTokenBalance: () => set({ padTokenBalance: null }),
|
||||
}));
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
import { create } from "zustand";
|
||||
|
||||
interface State {
|
||||
connectedAccount: string | null;
|
||||
setConnectedAccount: (newAccount: string) => void;
|
||||
unsetConnectedAccount: () => void;
|
||||
}
|
||||
|
||||
export const useStore = create<State>()((set) => ({
|
||||
connectedAccount: null,
|
||||
setConnectedAccount: (newAccount) => set({ connectedAccount: newAccount }),
|
||||
unsetConnectedAccount: () => set({ connectedAccount: null }),
|
||||
}));
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import { createContext, useContext } from "react";
|
||||
|
||||
export default function buildContext<TContext>(): [
|
||||
React.Context<TContext | null>,
|
||||
() => TContext,
|
||||
] {
|
||||
const builtContext = createContext<TContext | null>(null);
|
||||
|
||||
const builtUseContext = () => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const contextInstance = useContext(builtContext);
|
||||
if (contextInstance === null) {
|
||||
throw new Error(
|
||||
"You can use this hook only inside the context's provider."
|
||||
);
|
||||
}
|
||||
return contextInstance;
|
||||
};
|
||||
|
||||
return [builtContext, builtUseContext];
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export function getFormInputValue(form: HTMLFormElement, name: string) {
|
||||
// @ts-expect-error
|
||||
const input = form.elements[name] as HTMLInputElement;
|
||||
return input.value;
|
||||
}
|
||||
|
|
@ -29,13 +29,3 @@ export async function tryWithToast(
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function shortenAddress(address: string) {
|
||||
return address.slice(0, 6) + "..." + address.slice(-4);
|
||||
}
|
||||
|
||||
export function getFormInputValue(form: HTMLFormElement, name: string) {
|
||||
// @ts-expect-error
|
||||
const input = form.elements[name] as HTMLInputElement;
|
||||
return input.value;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { web3 } from "../web3";
|
||||
|
||||
export function shortenAddress(address: string) {
|
||||
return address.slice(0, 6) + "..." + address.slice(-4);
|
||||
}
|
||||
|
||||
export function formatPadTokenAmount(amount: bigint) {
|
||||
return `${web3.utils.fromWei(amount, "ether").replace(/\.*$/, "")} PAD`;
|
||||
}
|
||||
Loading…
Reference in New Issue