Skip to main content

Quick cheat sheet

Quick cheat sheet to ntegrating ENS in your dApp / Website

Starting from scratch with Create React App and Ethers.js


React Setup

Let’s build a new app using Create React App!

To start, you need:

  • Node.js and NPM. Installation instructions are here if you need them.
  • A browser with MetaMask installed

In your terminal, navigate to the folder you want to create the app in, and then type:

npx create-react-app my-app

Then navigate into the new directory that was created, and start the app:

cd my-app
npm start

The app server should be started, and you should see the default app in your browser:

http://localhost:3000

Creating a wallet connect button

Let’s say we want to connect an Ethereum wallet to the app. First, let’s add a button to the page.

Create a new Wallet.js file inside the src folder of your app:

src/
├─ Wallet.js

We’ll fill it out with some boilerplate code:

Wallet.js
import './Wallet.css';

function Wallet() {
const connect = async () => {
// TODO
};

return <button className="wallet-connect" onClick={connect}>Connect Wallet</button>;
}

export default Wallet;

You can also add some CSS styling if you want to make it look a bit nicer.

Create a Wallet.css file inside the src folder too:

src/
├─ Wallet.css
├─ Wallet.js

And add some CSS styling to it:

Wallet.css
button.wallet-connect {
height: 50px;
font-size: 30px;
border-radius: 23px;
cursor: pointer;
}

Finally, add that new Wallet component into your app by editing the App.js file:

App.js
import logo from './logo.svg';
import './App.css';
import Wallet from './Wallet';

function App() {
return (
<div className="App">
<header className="App-header">
<Wallet/>
<img src={logo} className="App-logo" alt="logo" />
...

That <Wallet/> line adds the component into your app.

At this point, after saving everything, you should see the button appear!

http://localhost:3000


Connect an Ethereum wallet with Ethers.js

First let’s install Ethers in your app:

npm i ethers

To use it in your Wallet component, include this at the top:

Wallet.js
import { useState } from 'react';
import { ethers } from 'ethers';

Now, let’s actually do something when you click on the connect button.

First off, we’ll use the useState method to store some stateful information in our Wallet component. For more information on this React feature, see here.

Wallet.js
function Wallet() {
const [provider, setProvider] = useState();
const [address, setAddress] = useState();
...

Next, we’ll connect an Ethereum wallet using Ethers.js and MetaMask in your browser:

Wallet.js
const connect = async () => {
let prov = provider;
if (!prov) {
prov = new ethers.providers.Web3Provider(window.ethereum);
setProvider(prov);
}

let address;

await prov.send("eth_requestAccounts", []);
const signer = prov.getSigner();
if (signer) {
address = await signer.getAddress();
}

setAddress(address);
};
See here for Ethers.js “Getting Started” documentation.

In the code above, we’re doing the same three steps:

  1. Connect an Ethers.js Provider using window.ethereum
  2. Request permission from MetaMask to connect the account, using eth_requestAccounts
  3. Get the Signer’s public address from the Provider

We’ll also add some extra code so the wallet can be connected and disconnected:

Wallet.js
const disconnect = () => {
setAddress('');
};

if (address) {
return <div className="wallet">
<span>{address}</span>
<button className="wallet-disconnect" onClick={disconnect}></button>
</div>;
} else {
return <button className="wallet-connect" onClick={connect}>Connect Wallet</button>;
}

And perhaps a bit more styling for the component too:

Wallet.css
button.wallet-disconnect {
border-radius: 50%;
height: 26px;
font-size: 13px;
cursor: pointer;
}

div.wallet {
display: inline-flex;
align-items: center;
height: 50px;
}

div.wallet span {
margin: -3px 7px 0px 7px;
font-size: 30px;
}

Now when you click on Connect Wallet, it should open MetaMask and request to connect an account. If you allow the connection, then the page should automatically update with your account address:

http://localhost:3000

Here is the full Wallet.js code at this point:

Wallet.js
import { useState } from 'react';
import { ethers } from 'ethers';
import './Wallet.css';

function Wallet() {
const [provider, setProvider] = useState();
const [address, setAddress] = useState();

const connect = async () => {
let prov = provider;
if (!prov) {
prov = new ethers.providers.Web3Provider(window.ethereum);
setProvider(prov);
}

let address;

await prov.send("eth_requestAccounts", []);
const signer = prov.getSigner();
if (signer) {
address = await signer.getAddress();
}

setAddress(address);
};

const disconnect = () => {
setAddress('');
};

if (address) {
return <div className="wallet">
<span>{address}</span>
<button className="wallet-disconnect" onClick={disconnect}></button>
</div>;
} else {
return <button className="wallet-connect" onClick={connect}>Connect Wallet</button>;
}
}

export default Wallet;

Resolving the ENS Primary Name

Now, instead of always showing an ugly hexadecimal address, let’s integrate with ENS!
Ethers.js makes this easy. Here’s their documentation page on it.

You just call provider.lookupAddress(address). Let’s add this to our app:

Wallet.js
function Wallet() {
const [provider, setProvider] = useState();
const [address, setAddress] = useState();
const [ensName, setEnsName] = useState();

const connect = async () => {
let prov = provider;
if (!prov) {
prov = new ethers.providers.Web3Provider(window.ethereum);
setProvider(prov);
}

let address, ensName;

await prov.send("eth_requestAccounts", []);
const signer = prov.getSigner();
if (signer) {
address = await signer.getAddress();
ensName = await prov.lookupAddress(address);
}

setAddress(address);
setEnsName(ensName);
};

const disconnect = () => {
setAddress('');
setEnsName('');
};

if (address) {
return <div className="wallet">
<span>{ensName || address}</span>
<button className="wallet-disconnect" onClick={disconnect}></button>
</div>;
} else {
return <button className="wallet-connect" onClick={connect}>Connect Wallet</button>;
}
}

Now in your app, it should display the ENS Primary Name for your connected account:

http://localhost:3000

Resolving the Avatar for an ENS name

Now we have an ENS name for the connected account! So if they have records set on their ENS name, we can resolve those and display them in the app! Let’s start with a popular one – the Avatar record.

Per the Ethers.js documentation, resolving the avatar is as simple as calling provider.getAvatar(name). Let’s add that:

Wallet.js
function Wallet() {
const [provider, setProvider] = useState();
const [address, setAddress] = useState();
const [ensName, setEnsName] = useState();
const [avatar, setAvatar] = useState();

const connect = async () => {
let prov = provider;
if (!prov) {
prov = new ethers.providers.Web3Provider(window.ethereum);
setProvider(prov);
}

let address, ensName, avatar;

await prov.send("eth_requestAccounts", []);
const signer = prov.getSigner();
if (signer) {
address = await signer.getAddress();
ensName = await prov.lookupAddress(address);
if (ensName) {
avatar = await prov.getAvatar(ensName);
}
}

setAddress(address);
setEnsName(ensName);
setAvatar(avatar);
};

const disconnect = () => {
setAddress('');
setEnsName('');
setAvatar('');
};

if (address) {
return <div className="wallet">
{avatar && (<img src={avatar} alt="avatar"></img>)}
<span>{ensName || address}</span>
<button className="wallet-disconnect" onClick={disconnect}></button>
</div>;
} else {
return <button className="wallet-connect" onClick={connect}>Connect Wallet</button>;
}
}

We can also add some more styling to make it look better:

Wallet.css
div.wallet img {
width: 50px;
height: 50px;
border-radius: 50%;
}

Now you should see both the ENS Primary Name and Avatar in the app!

http://localhost:3000

Resolving other ENS records

info

An ENS name can be used as your web3 profile too! There are many other records you can set other than the Avatar, like:

  • E-mail address
  • URL to some web2 website
  • Other social media links, like Twitter/etc
  • Decentralized website (IPFS/Arweave/Tor/etc)
  • Other coin addresses like BTC
  • And much more!

Let’s add a few of these into our app as well. In Ethers.js, you can resolve other records by:

  1. Get the resolver for the ENS name
  2. Call the appropriate method on the resolver to resolve a particular record

In code this looks like:

const resolver = await provider.getResolver('ens.eth');
const urlRecord = await resolver.getText('url');

In our app, after we get the avatar, let’s add this:

Wallet.js
const resolver = await prov.getResolver(ensName);
if (resolver) {
otherRecords.email = await resolver.getText('email');
otherRecords.url = await resolver.getText('url');
otherRecords.twitter = await resolver.getText('com.twitter');
}

Then we’ll add some <p> blocks for each record:

Wallet.js
return <div>
<div className="wallet">
{avatar && (<img src={avatar} alt="avatar"></img>)}
<span>{ensName || address}</span>
<button className="wallet-disconnect" onClick={disconnect}></button>
</div>
<div>
{otherRecords.email && (<p>Email: <a href={`mailto:${otherRecords.email}`}>{otherRecords.email}</a></p>)}
{otherRecords.url && (<p>Website: <a href={otherRecords.url}>{otherRecords.url}</a></p>)}
{otherRecords.twitter && (<p>Twitter: <a href={`https://twitter.com/${otherRecords.twitter}`}>@{otherRecords.twitter}</a></p>)}
</div>
</div>;

We’re not doing it here for this simple example, but it’s probably a good idea to keep in mind input sanitization, and assume that any returned text values are untrusted input.

Anyway, now those records will show up in the app if they’re set on the ENS name!

http://localhost:3000

Final code and live example

You can find the final code we used for this demo up on GitHub! We only needed to add our Wallet.js and Wallet.css files, and then make a couple of small changes to App.js and package.json.

And here’s a live example of the starter app!

http://localhost:3000

Using the wagmi React Hooks

Setup

This time, instead of doing everything from scratch, let’s use the wagmi React Hooks!

We’ll start out the same way as the first demo. In your terminal, navigate to the folder you want to create the app in, and then type:

npx create-react-app my-app

Then install wagmi and ethers:

cd my-app
npm i wagmi ethers

Basic Wagmi Start

The wagmi website shows a starter example, so let’s use that.

Create a new Profile.js file inside the src folder of your app.

src/
├─ App.js
├─ package.json
├─ Profile.js
├─ Wallet.css
├─ Wallet.js

We’ll fill it out with the example code:

Profile.js
import { useAccount, useConnect, useDisconnect } from 'wagmi';
import { InjectedConnector } from 'wagmi/connectors/injected';

function Profile() {
const { address, isConnected } = useAccount()
const { connect } = useConnect({
connector: new InjectedConnector(),
})
const { disconnect } = useDisconnect()

if (isConnected)
return (
<div>
Connected to {address}
<button onClick={() => disconnect()}>Disconnect</button>
</div>
)
return <button onClick={() => connect()}>Connect Wallet</button>
}

export default Profile;

Then we’ll edit App.js to include that new module:

App.js
import { WagmiConfig, createClient } from 'wagmi';
import { getDefaultProvider } from 'ethers';
import Profile from './Profile';
import logo from './logo.svg';
import './App.css';

const client = createClient({
autoConnect: true,
provider: getDefaultProvider(),
})

function App() {
return (
<div className="App">
<header className="App-header">
<WagmiConfig client={client}>
<Profile />
</WagmiConfig>
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}

export default App;

Run this in your terminal to start the web server:

npm start

The app should pop up in your browser, and you’ll see that it already has some basic Connect / Disconnect functionality!

http://localhost:3000


Adding ENS Integration with Wagmi

Wagmi also has several examples here.
In their Connect Wallet example they show how to display the ENS name and Avatar.

So let’s add that in:

Profile.js
import {
useAccount,
useConnect,
useDisconnect,
useEnsAvatar,
useEnsName,
} from 'wagmi'

function Profile() {
const { address, connector, isConnected } = useAccount()
const { data: ensAvatar } = useEnsAvatar({ address })
const { data: ensName } = useEnsName({ address })
const { connect, connectors, error, isLoading, pendingConnector } =
useConnect()
const { disconnect } = useDisconnect()

if (isConnected) {
return (
<div>
<img src={ensAvatar} alt="ENS Avatar" />
<div>{ensName ? `${ensName} (${address})` : address}</div>
<div>Connected to {connector.name}</div>
<button onClick={disconnect}>Disconnect</button>
</div>
)
}

return (
<div>
{connectors.map((connector) => (
<button
disabled={!connector.ready}
key={connector.id}
onClick={() => connect({ connector })}
>
{connector.name}
{!connector.ready && ' (unsupported)'}
{isLoading &&
connector.id === pendingConnector?.id &&
' (connecting)'}
</button>
))}

{error && <div>{error.message}</div>}
</div>
)
}

export default Profile;

Those hooks useEnsName and useEnsAvatar will automatically load the ENS primary name and avatar for you!

http://localhost:3000

Now you can get to styling and make it look however you want!

Quick Cheat Sheet

Getting started / Ethers.js setup

  1. Install Ethers in your Node project
    • npm i ethers
  2. Import Ethers in your code
    • import { ethers } from 'ethers';
  3. Connect a Provider
    • const provider = new ethers.providers.Web3Provider(window.ethereum);
    • Other methods here
  4. Get currently connected wallet
    • For MetaMask, first do this: await provider.send("eth_requestAccounts", []);
    • Then get the Signer: const signer = prov.getSigner();
    • And finally, the public address: const address = await signer.getAddress();

Get ENS Primary Name

const ensName = await provider.lookupAddress(address);

Get ENS Avatar

const avatar = await provider.getAvatar(ensName);

Get Other ENS Text Records

const resolver = await provider.getResolver(ensName);

// Text Records
const email = await resolver.getText('email');
const url = await resolver.getText('url');
const twitter = await resolver.getText('com.twitter');

// Any other text record is the same, even custom text records
const myCustomRecord = await resolver.getText('mycustomrecord');

Get Coin Addresses

// Easily get other coin types using this
import { formatsByName } from '@ensdomains/address-encoder';

const resolver = await provider.getResolver(ensName);

// ETH Address
const ethAddress = await resolver.getAddress();

// Other Coin Addresses
const btcAddress = await resolver.getAddress(formatsByName['BTC'].coinType);