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 2: use the Metamask API to get information about the user #2

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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Branches will be created with stages for the rest of the implementation

You are presented with a Next.js application that has a basic layout and a Context Provider. Your goal is to learn how to use the Metamask API to make this an application that users can interact with.

Few notes about the initial setup ans constraints:
Few notes about the initial setup and constraints:

- You do not need any additional dependencies.
- The context provider is already setup so that any react code under [components](./components/) and [pages](./pages/) can access the context using a hook.
Expand Down
32 changes: 29 additions & 3 deletions components/Wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import { Loading } from "./Loading";
export default function Wallet() {
const {
dispatch,
state: { status, isMetamaskInstalled },
state: { status, isMetamaskInstalled, wallet, balance },
} = useMetamask();

const showInstallMetamask =
status !== "pageNotLoaded" && !isMetamaskInstalled;
const showConnectButton = status !== "pageNotLoaded" && isMetamaskInstalled;
const showConnectButton =
status !== "pageNotLoaded" && isMetamaskInstalled && !wallet;

const handleConnect = async () => {
dispatch({ type: "loading" });
Expand All @@ -20,7 +21,12 @@ export default function Wallet() {
});

if (accounts.length > 0) {
dispatch({ type: "connect", wallet: accounts[0] });
const balance = await window.ethereum!.request({
method: "eth_getBalance",
params: [accounts[0], "latest"],
});

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

Expand All @@ -40,6 +46,26 @@ export default function Wallet() {
</Link>{" "}
in order to learn how to use the Metamask API.
</p>

{wallet && (
<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">
<div className="flex items-center">
<div className="ml-4">
<h3 className="text-lg font-medium leading-6 text-white">
Address: <span>{wallet}</span>
</h3>
<p className="text-sm text-white">
Balance: <span>{balance}</span>
</p>
</div>
</div>
</div>
</div>
</div>
)}

{showConnectButton && (
<button
onClick={handleConnect}
Expand Down
16 changes: 9 additions & 7 deletions hooks/useMetamask.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, type PropsWithChildren } from "react";

type ConnectAction = { type: "connect"; wallet: string };
type ConnectAction = { type: "connect"; wallet: string; balance: string };
type DisconnectAction = { type: "disconnect" };
type PageLoadedAction = { type: "pageLoaded"; isMetamaskInstalled: boolean };
type LoadingAction = { type: "loading" };
Expand All @@ -19,23 +19,21 @@ type State = {
wallet: string | null;
isMetamaskInstalled: boolean;
status: Status;
balance: string | null;
};

const MetamaskContext = React.createContext<
{ state: State; dispatch: Dispatch } | undefined
>(undefined);

const initialState: State = {
wallet: null,
isMetamaskInstalled: false,
status: "loading",
balance: null,
} as const;

function metamaskReducer(state: State, action: Action): State {
switch (action.type) {
case "connect": {
const { wallet } = action;
return { ...state, wallet, status: "idle" };
const { wallet, balance } = action;
return { ...state, wallet, balance, status: "idle" };
}
case "disconnect": {
return { ...state, wallet: null };
Expand All @@ -53,6 +51,10 @@ function metamaskReducer(state: State, action: Action): State {
}
}

const MetamaskContext = React.createContext<
{ state: State; dispatch: Dispatch } | undefined
>(undefined);

function MetamaskProvider({ children }: PropsWithChildren) {
const [state, dispatch] = React.useReducer(metamaskReducer, initialState);
const value = { state, dispatch };
Expand Down