Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Step 3: Two way communication with Metamask #3

Merged
merged 1 commit into from
Oct 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 56 additions & 5 deletions components/Wallet.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Image from "next/future/image";
import Link from "next/link";
import { useMetamask } from "../hooks/useMetamask";
import { Loading } from "./Loading";
Expand All @@ -14,6 +13,8 @@ export default function Wallet() {
const showConnectButton =
status !== "pageNotLoaded" && isMetamaskInstalled && !wallet;

const showAddToken = status !== "pageNotLoaded" && typeof wallet === "string";

const handleConnect = async () => {
dispatch({ type: "loading" });
const accounts = await window.ethereum.request({
Expand All @@ -25,11 +26,48 @@ export default function Wallet() {
method: "eth_getBalance",
params: [accounts[0], "latest"],
});

dispatch({ type: "connect", wallet: accounts[0], balance });

// we can register an event listener for changes to the users wallet
window.ethereum.on("accountsChanged", async (newAccounts: string[]) => {
if (newAccounts.length > 0) {
// uppon receiving a new wallet, we'll request again the balance to synchronize the UI.
const newBalance = await window.ethereum!.request({
method: "eth_getBalance",
params: [newAccounts[0], "latest"],
});

dispatch({
type: "connect",
wallet: newAccounts[0],
balance: newBalance,
});
} else {
// if the length is 0, then the user has disconnected from the wallet UI
dispatch({ type: "disconnect" });
}
});
}
};

const handleAddUsdc = async () => {
dispatch({ type: "loading" });

await window.ethereum.request({
method: "wallet_watchAsset",
params: {
type: "ERC20",
options: {
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
symbol: "USDC",
decimals: 18,
image: "https://cryptologos.cc/logos/usd-coin-usdc-logo.svg?v=023",
},
},
});
dispatch({ type: "idle" });
};

return (
<div className="bg-truffle">
<div className="mx-auto max-w-2xl py-16 px-4 text-center sm:py-20 sm:px-6 lg:px-8">
Expand All @@ -47,7 +85,7 @@ export default function Wallet() {
in order to learn how to use the Metamask API.
</p>

{wallet && (
{wallet && balance && (
<div className=" px-4 py-5 sm:px-6">
<div className="-ml-4 -mt-4 flex flex-wrap items-center justify-between sm:flex-nowrap">
<div className="ml-4 mt-4">
Expand All @@ -57,7 +95,11 @@ export default function Wallet() {
Address: <span>{wallet}</span>
</h3>
<p className="text-sm text-white">
Balance: <span>{balance}</span>
Balance:{" "}
<span>
{(parseInt(balance) / 1000000000000000000).toFixed(4)}{" "}
ETH
</span>
</p>
</div>
</div>
Expand All @@ -78,10 +120,19 @@ export default function Wallet() {
{showInstallMetamask && (
<Link href="https://metamask.io/" target="_blank">
<a className="mt-8 inline-flex w-full items-center justify-center rounded-md border border-transparent bg-ganache text-white px-5 py-3 text-base font-medium sm:w-auto">
Connect Wallet
Install Metamask
</a>
</Link>
)}

{showAddToken && (
<button
onClick={handleAddUsdc}
className="mt-8 inline-flex w-full items-center justify-center rounded-md border border-transparent bg-ganache text-white px-5 py-3 text-base font-medium sm:w-auto"
>
{status === "loading" ? <Loading /> : "Add Token"}
</button>
)}
</div>
</div>
);
Expand Down
9 changes: 7 additions & 2 deletions hooks/useMetamask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ type ConnectAction = { type: "connect"; wallet: string; balance: string };
type DisconnectAction = { type: "disconnect" };
type PageLoadedAction = { type: "pageLoaded"; isMetamaskInstalled: boolean };
type LoadingAction = { type: "loading" };
type IdleAction = { type: "idle" };

type Action =
| ConnectAction
| DisconnectAction
| PageLoadedAction
| LoadingAction;
| LoadingAction
| IdleAction;

type Dispatch = (action: Action) => void;

Expand All @@ -36,7 +38,7 @@ function metamaskReducer(state: State, action: Action): State {
return { ...state, wallet, balance, status: "idle" };
}
case "disconnect": {
return { ...state, wallet: null };
return { ...state, wallet: null, balance: null };
}
case "pageLoaded": {
const { isMetamaskInstalled } = action;
Expand All @@ -45,6 +47,9 @@ function metamaskReducer(state: State, action: Action): State {
case "loading": {
return { ...state, status: "loading" };
}
case "idle": {
return { ...state, status: "idle" };
}
default: {
throw new Error("Unhandled action type");
}
Expand Down