Onboarding New Users With Coinbase Wallet
Michael Bogan
Posted on August 1, 2022
Introduction
Web3 represents an exciting chapter in the development of the internet. The primitives that the blockchain provides will lead to an infinite number of applications and use cases. We’ve seen the explosion of ICOs, DeFi, NFTs, and peer-to-peer payment systems. However, we still have a long way to go before reaching mass adoption of this new technology. User experience is one area where things still lack.
As web3 developers, how are we supposed to onboard the next wave of users when the average person doesn’t understand concepts such as non-custodial crypto wallets or signed transactions? This article will explore the issue, and offer a solution to help create a better user experience. We’ll look at a real-world example of how we can use the Coinbase Wallet SDK to create a seamless onboarding experience for new users.
Real-World Problems
One of the concepts that’s most intriguing in web3 is the intersection of healthcare and blockchain technology. HIPAA compliance means that patient records probably shouldn’t be put on a public blockchain. However, there are hundreds of other ways we can use the blockchain to revolutionize the healthcare sector.
Healthcare Workers (HCW) have to spend in excess of six weeks being vetted and verified before working at any healthcare institution. The loss of time and income by hospital systems is huge. A trusted third party conducts certification verifications, background checks et al for weeks on end while a HCW isn’t paid and the hospital system has to find a temporary worker to fill the gap. This is a problem that the blockchain can solve. With blockchain immutability, once a certification is verified, it never has to happen again.
Web3 Solutions
To solve this problem, I want to build a Certification Verification dapp called Health Verify (HV) that mints an NFT if a HCW certificate is successfully verified. There are many different paths this solution can take: ZK proofs to guarantee anonymity, using Arweave or Ceramic as a schelling point for all verified certificates, and so on. In my view, everything rises and falls on the quality of the onboarding for first-time crypto users.
Since a user requires a wallet browser extension in order to interact with web3 applications, there should be considerations for someone unfamiliar with the technology. Just seeing a “Connect Wallet” button with little context can be an intimidating first impression so we want to make things as smooth as possible.
Coinbase wallet is one of the few wallets that offers an onboarding experience if the user doesn't already have a wallet extension installed. It makes sense to use this wallet because Coinbase is a trusted name in web3 and provides a secure on-ramp for new users, while allowing existing users to easily connect to my dapp.
For the rest of this article, we’ll focus on building the first part of the Health Verify dapp. We’ll create the onboarding page and integrate the Coinbase Wallet SDK to make it easy for users to either connect an existing wallet, or create a new one.
The Project
So let’s start pulling everything together. React is the library de jour when building dapps, my preferred libraries for Health Verify include:
- Next.js - ideal React framework for production
- Wagmi Hooks - a collection of React Hooks containing everything you need to start working with Ethereum
- Infura RPC provider - highly available Ethereum API
- Coinbase Wallet SDK - Coinbase Wallet SDK (formerly WalletLink) allows developers to connect their dapps to Coinbase Wallet on both mobile web (for iOS and Android) and desktop
- Chakra UI - a simple, modular, and accessible component library that gives you the building blocks you need to build your React application
As for features, here is the scope for this article:
- Onboarding: Allows HCW to sign up if they don’t have a wallet.
- Verification: HCW selects from a list of supported certifications, submits some information, and then sends it to a server for manual verification. After verification is complete, an NFT is issued.
For this article, we’ll just build a simple interface for the submission portion of this workflow, including the Coinbase Wallet onboarding flow.
Implementation
Note: If you want to, you can view the codebase here.
Okay, BUIDL time! Next.js has been a darling of the React ecosystem from when it came out. Personally, I enjoy not dealing with React Router, so it’s a go-to of mine when starting any React project. For Health Verify, we’ll start by installing Next.js and Chakra UI. I use Typescript in this article, but you can use Javascript and everything should be the same, sans all the typing boilerplate.
Step 1: Install Next.js
- Go to your terminal and type the following command:
npx create-next-app@latest --typescript
- Follow the prompts and enter an app name. If all goes well, then you should have a fresh Next.js install.
Step 2: Install and Configure Chakra UI
I’ve used a number of different UI libraries over the years but I haven’t found anything that is as un-opinionated about UI element design while having such an amazing developer experience. Therefore, I highly recommend the Chakra UI library.
- Navigate to your project folder that you created in Step 1 in your terminal and run the following:
yarn add @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^6
- Import the Chakra UI provider, and add it to the _app.tsx file. At this stage, the _app.tsx should look as below:
import type { AppProps } from "next/app"
import { ChakraProvider } from "@chakra-ui/react"
function MyApp({ Component, pageProps }: AppProps) {
return (
<ChakraProvider>
<Component {...pageProps} />
</ChakraProvider>
);
}
export default MyApp;
Step 3: Install Coinbase Wallet SDK and Wagmi Hooks
Install the Coinbase Wallet SDK and Wagmi Hooks by running the following command:
yarn add @coinbase/wallet-sdk wagmi ethers
Note: Ethers is a Wagmi dependency.
Step 4: Get an Infura ID
Infura’s high availability API for Ethereum will help us get started with Health Verify. We are configuring a backup provider for the Coinbase Wallet to use for requests that won’t use the Injected Provider. This step is optional. You can follow this guide to get up and running with an Infura project.
Once you have your Infura ID, edit the .env.local by adding the following key:
REACT_APP_INFURA_ID=xxxxxxIDHERE*******
Step 5: Configure Wagmi and Coinbase SDK
We can achieve the integration between Coinbase Wallet SDK and Wagmi primarily via connectors. Connectors are wrappers for providers that can either be injected or from custodial or non-custodial wallets. Wagmi has built-in support for Coinbase Wallet and that makes integration a piece of cake.
- Create a file in the root of the project and call it connectors.ts. This can be located anywhere really. I put mine in a utils folder at the root of the project.
- I choose to support Metamask as well for Health Verify as it helps with my testing and also provides an alternative for some users.
import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet'
import { MetaMaskConnector } from 'wagmi/connectors/metaMask'
import { chain } from 'wagmi'
const APP_NAME = 'Health Verify'
const APP_LOGO_URL = 'https://ethereum.org/static/a110735dade3f354a46fc2446cd52476/f3a29/eth-home-iconwebp'
export const connectors = [
new CoinbaseWalletConnector({
chains: [chain.mainnet],
options: {
appName: APP_NAME,
appLogoURL: APP_LOGO_URL,
}}),
new MetaMaskConnector({
chains: [chain.mainnet],
options: {
shimChainChangedDisconnect: false,
},
}),
]
Step 6: Configure Wagmi Hooks
I love the Wagmi Hooks library for its simplicity. All you need to do is wrap your app in the WagmiConfig component and you can use React Hooks on your dapp. That’s it. For Health Verify, I have to edit _app.tsx in the following ways:
- Import the Wagmi Hooks provider, createClient, configureChains, chain objects from the Wagmi library. You can read up on what they all do in the Wagmi documentation here.
- Initialize a variable with your Infura ID that you created in Step 4.
- Use
configureChains
to create a provider. At this stage, you can also pass an array of supported chains. I’m using mainnet and polygon. Note: You can configure supported chains in theConnector
object you created in Step 5.
At the end of this step, your _app.tsx file should look like this:
import type { AppProps } from 'next/app'
import { providers } from 'ethers'
import {ChakraProvider } from '@chakra-ui/react'
import { WagmiConfig, createClient, configureChains, chain } from 'wagmi'
import { connectors } from '../utils/connectors'
import { infuraProvider } from 'wagmi/providers/infura'
const infuraId = process.env.REACT_APP_INFURA_ID
const { provider } = configureChains(
[chain.mainnet, chain.polygon],
[infuraProvider({ infuraId })],
)
const client = createClient({
connectors,
provider,
})
function MyApp({ Component, pageProps }: AppProps) {
return (
<ChakraProvider>
<WagmiConfig client={client}>
<Component {...pageProps} />
</WagmiConfig>
</ChakraProvider>
)
}
export default MyApp
After this you could fire up your Next.js instance by running yarn dev
. However, if you do, you’ll see the boilerplate Next.js home page. Let’s fix that.
Step 7: Connect Wallet Modal
And now for the fun part. I won’t focus on the specific Chakra UI elements that I will use, but I will bring attention to several cool Wagmi hooks that we need to use in order to build a dynamic UI that responds to the wallet connection status.
-
useAccount
- used to access the connected account. We can toggle UI states based on this binary value. -
useConnect
- used to access the account using the configured connectors.
For the Connect Wallet Modal, we are loading the connectors that we configured earlier and are showing the user the supported wallet options. It’s all coming together—wax on, wax off.
import {
VStack,
HStack,
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalCloseButton,
Button,
Text,
Image,
} from '@chakra-ui/react'
import { useConnect } from 'wagmi'
export type SelectWalletModalProps = {
isOpen: boolean;
closeModal: () => coid;
}
export default function SelectWalletModal({
isopen,
closeModal,
}: SelectWalletModalProps) {
const { data } = useConnect();
const {
activeConnector,
connect,
connectors,
error,
isConnecting,
pendingConnector,
} = uesConnect();
return (
<Modal isOpen={isOpen} onClose={closeModal} isCentered>
<ModalOverlay />
<ModalContent w='300px'>
<ModalHeader>Select Wallet</ModalHeader>
<ModalCloseButton
_focus={{
boxShadow: 'none',
}}
/>
<ModalBody paddingBottom='1.5rem'>
<VStack>
{activateConnector && <div>Connected to {activeConnector.name}</div>}
{connectors.map((connector) => (
<Button
variant='outline'
key={connector.id}
disabled={!connector.ready}
onClick={() => {
connect(connector);
closeModal();
}}
w='100%'
>
<HStack w='100%' justifyContent='center'>
<Image
width={26}
height={26}
borderRadius="3px"
src={walletIcons(connector.name)}
alt={"Wallet"}
></Image>
<Text>
{connector.name}{" "}
{isConnecting &&
pendingConnector?.id === connector.id &&
" (connecting)"}
</Text>
</Button>
))}
{error && <Text>(error.message)</Text>}
</VStack>
</ModalBody>
</ModalContent>
</Modal>
);
}
Step 8: Home Page UI
For Health Verify, my desired UX is that the user visits the home page, sees some copy, and a call-to-action that prompts the user to select a wallet. If they don’t have a wallet, then they can quickly and easily create one. The best part about using the Coinbase Wallet SDK is that if the user doesn’t have a wallet, he or she still gets a seamless onboarding experience and is greenpilled. We have done a lot of the work already so let’s bring it home by putting together a nice UI.
import {
Flex,
Box,
Text,
Button,
Container,
Heading,
Stack,
ListItem,
UnorderedList,
useDisclosure, } from '@chakra-ui/react'
import type { NextPage } from 'next'
import Head from 'next/head'
import { useAccount, useConnect } from 'wagmi'
import SelectWalletModal from '../components/SelectWalletModal'
import { Certifications } from '../components/certifications'
const Home: NextPage = () => {
const { data: account } = useAccount()
const { isOpen, onOpen, onClose } = useDisclosure()
return (
<>
<Head>
<title>Health Verify</title>
<meta
name='Health Verify'
content='Health Verify remembers your certifications'
/>
<link rel='icon' href='/facivon.ico' />
</Head>
<Flex alignItems='center' justifyContent='center'>
{account ? <Certifications/> : (
<Container maxW={'3x1'}>
<Stack
as={Box}
textAlign={'center'}
spacing={{ base: 8, md: 14 }}
py={{ base: 20, md: 36 }}
>
<Heading
fontWeight={600}
fontSize={{ base: '2x1', sm: '4x1', md: '6x1' }}
lineHeight={'110%'}
>
Never verify your health certifications <br />
<Text as={'span'} color={'green.400'}>
AGAIN
</Text>
</Heading>
<Text fontSize={'2x1'}>
With Health Verify, you can easily verify your health certifications by following the steps below.
</Text>
<UnorderedList listStyleType='none'>
<ListItem>{`Click 'Start' to connect your wallet.`}</ListItem>
<ListItem>{`If you don't have a wallet, create a Coinbase Wallet by selecting Coinbase Wallet`}</ListItem>
<ListItem>Select a certification to verify</ListItem>
<ListItem>Enter your Certification ID</ListItem>
<ListItem>
Wait for our team to verify your certification
</ListItem>
</UnorderedList>
<Stack
direction={'column'}
spacing={3}
align={'center'}
position={'relative'}
>
<Button
colorScheme={'green'}
bg={'green.400'}
rounded={'full'}
onClick={onOpen}
px={6}
_hover={{
bg: 'green.500',
}}
>
Start
</Button>
</Stack>
</Stack>
</Container>
)}
</Flex>
<SelectWalletModal isopen={isOpen} closeModal={onClose} />
</>
);
}
Now, if you’re keen, you’ll notice that we only need one hook to make everything work smoothly. This is another reason why Wagmi is so awesome. We can get started with hooks really easily without writing tons of boilerplate for RPC or Contract interactions. Wagmi has many more hooks that I’d encourage anyone to check out.
So now that we have our UI, we can bring everything together. Let’s start the app and see what our rendered app looks like. If you have everything configured correctly, then your home page should look like the image below:
When you click on “Start”, the following Connect Wallet modal should pop up:
Select “Coinbase Wallet” and if you configured everything correctly, it should show the Coinbase Wallet SDK “Install” dialog that allows a user to either sign up with their mobile phone or install Coinbase Wallet.
If the user selects "Install", then they will be prompted to install the Coinbase Wallet browser extension and be guided through the final setup. This is exactly the user experience we want for users new to crypto. Now that we can onboard brand new users, we can continue to build out Health Verify.
Conclusion
Web3 introduces technology that will undoubtedly enhance many areas of our digital lives. We are only at the early stages of development, but already the use cases and applications are growing. However, in order to reach wider adoption, the user experience needs to improve.
In this article, we reviewed how to build a dapp using Next.js, Typescript, Wagmi, and the Coinbase Wallet SDK. With little configuration, we were able to deliver a great user experience to new crypto users. Now, we can build out Health Verify even further.
Posted on August 1, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.