# ENS: A Practical Guide

By [The Indexing Company](https://paragraph.com/@indexingco) · 2022-09-23

---

So you’ve made it to this site and this particular blog post. Great! But do you know _how_ you actually got here?

_(For those wanting to dive in, feel free to scroll past this to “The DIY Section” below)_

The internet today (web2) works, and more importantly gained adoption, in part thanks to the magical world of the Domain Name System (DNS for short). At the highest level, DNS effectively allows users of web2 to say “I want to visit [longdogechallenge.com](https://longdogechallenge.com/)” and reliably be taken to the content (website) that lives there. Let’s break down how that works a bit:

1.  A user enters the domain name, `longdogechallenge.com`, in their browser’s address bar
    
2.  A _DNS lookup_ occurs to resolve that domain name to a server’s IP address (an Internet Protocol address is a way to uniquely identify every device on the internet)
    
3.  The browser is given the IP address for the requested domain name and asks the server behind that IP address for content
    
4.  The server returns the content and the browser renders that to the end user (aka the resulting website)
    

_(The above is admittedly a major simplification of DNS, and for those wishing to dive deeper,_ [_Cloudflare has a great technical write up_](https://www.cloudflare.com/learning/dns/what-is-dns/)_)_

For our purposes though, the general idea is that users of web2 can use DNS to get content behind an IP address while only knowing a domain name. This abstraction is enormously powerful. For starters, IP addresses are _not_ easy to remember - the “common” IPv4 format looks something like `192.168.1.1` and the newer IPv6 format, `2001:0db8:85a3:0000:0000:8a2e:0370:7334`, certainly isn’t any easier. IP addresses are designed for uniquely identifying the billions of internet devices and facilitating communication between _them_; not with humans. And of equal importance, because humans are accessing content via domain names, the server providing that content can be swapped out simply by changing which IP address a domain name points to.

### Okay, but what does this have to do with web3?

Allowing mere humans to remember just `google.com` instead of `142.250.113.102` was a massive accessibility win for web2. The Ethereum Name System, ENS, provides a similar system for the Ethereum ecosystem. And while Ethereum is of course _not_ equivalent to all of web3, it does represent a large portion of the current web3 user base in some capacity (even if you aren’t directly using Ethereum, many protocols and services are built atop the same basic technologies - more on that another time).

ENS, in short, allows a web3 user to say “I want to send funds to alice.eth” without actually knowing the wallet address behind `alice.eth`.

The DIY Section
---------------

Alright, we’ve covered what ENS is and why you should have one. Now let’s dig into how to acquire and use ENS; for both web3 users and developers.

### For Users

Go buy an ENS! Seriously, go right now and buy one if you haven’t already. Some steps to get you started:

**Setup your wallet**

If you haven’t already, make sure you have a web3 wallet. [MetaMask](https://metamask.io/) is a great place to get started if you haven’t already joined web3.

From there, make sure you have “some” Ethereum in your wallet. A quarter (0.25) ETH should be plenty to get started (unless you’re trying to get a [highly prized ENS](https://espressoinsight.com/2022/05/15/most-expensive-ens-sales-ever/)). If you don’t have any ETH yet, look towards exchanges like [Coinbase](https://www.coinbase.com/) to get you started.

**Buy an ENS**

Visit a site like [https://app.ens.domains](https://app.ens.domains/) to look up names you’re interested in. There’s no wrong answer here - it’s a lot like choosing an email or a Twitter handle. If your name is available, then great! Follow the registration process (yes, this will involve 2 transactions) and secure your shiny new ENS.

If the name you like is already registered, then you have a few options for purchasing it on the “secondary markets”. ENS, at least in part, is officially a standard NFT collection. That means you can use your favorite NFT marketplaces to trade registered ENS items. Some options in no particular order:

*   [https://opensea.io/](https://opensea.io/)
    
*   [https://nft.coinbase.com/](https://nft.coinbase.com/)
    
*   [https://www.ens.vision/](https://www.ens.vision/)
    

**Tie your ENS to your wallet address**

This is the important piece. Now that you own your ENS, you need to make sure that it’s setup to point to your wallet address. There are two different pieces to this. Go back to [https://app.ens.domains/](https://app.ens.domains/) once again and click “My Account” in the upper right-hand corner and then do the following:

**Define the ENS => wallet address lookup** -- Select the ENS you just purchased and set the “Record” for “ETH” address to your wallet address. During this step, feel free to set as many of the other text records you see there as you want - this is all part of your new web3 profile.

![Setting ENS records](https://storage.googleapis.com/papyrus_images/1296a31ccac8ba22630e647bb20507889548509ab99eaa086dc5788e722b8d8b.png)

Setting ENS records

**Define the wallet address => ENS reverse lookup** -- Go back to your “My Account” page and you’ll have an option to select your “Primary ENS Name”. Submit the corresponding transaction to make it permanent 🔥

![Setting a Primary ENS Name](https://storage.googleapis.com/papyrus_images/c97feee8e83f433e811dfac379e384724675b8536290c50c365e761a1d14439c.png)

Setting a Primary ENS Name

_NOTE: Both of the above steps will also require submitting Ethereum transactions and paying a small amount of ETH in “gas”. This is to pay the network to store the new data you just added._

And just like that, you’ll now have an official, named identity in web3 🎉 A simple way you can try it out is by looking up your name or wallet address on [Etherscan](https://etherscan.io/) and seeing that the two are linked in the results.

**BONUS: Add an NFT as your avatar**

Thanks to the wonderful world of web3, you can also link pieces of decentralized data together. Specifically in this case, you can say that the photo for your shiny new ENS name should be another NFT that you own. For instance, the avatar field for runninyeti.eth is set to `` `eip155:1/erc1155:0x495f947276749ce646f68ac8c248420045cb7b5e/87433597745683365960201176492736871205018189775129059226749288698845216112641` `` which points to this lovely image:

![](https://storage.googleapis.com/papyrus_images/a94fedabc867c82feee7e6a30302418339e2809ab3576b871433a8b7b30cf216.png)

For a good overview of how to do this, check out [this post](https://medium.com/the-ethereum-name-service/step-by-step-guide-to-setting-an-nft-as-your-ens-profile-avatar-3562d39567fc) by the ENS team.

### For Developers

Also go buy an ENS! For yourself, for your project, whatever it might be, just start participating. See the “For Users” section above and follow along.

Now that that’s done, here’s some how-to’s for adding ENS functionality to your projects. We’re going to focus on using [web3.js](https://www.npmjs.com/package/web3) since it’s usable on both frontend and backend codebases, but these same principles can be used with any language.

We’re also going to focus on some of the low-hanging fruit based on what is available to the developer community _today_, but we encourage everyone to go far beyond this (e.g. “ENS Profiles” or [deploying ENS on a private chain](https://docs.ens.domains/deploying-ens-on-a-private-chain)). There are also existing packages to obfuscate working with ENS (mainly JavaScript based, like [ensjs](https://www.npmjs.com/package/@ensdomains/ensjs)), but for this post we’ll be looking at how we can do it ourselves and handle all data directly.

**Look up the current owner of an ENS**

_tl;dr - ask the NFT contract for ENS who the current owner is_

We’ll start with an easy one. To grab the address of the current owner of a given ENS name:

1.  Define a web3.js contract instance with the `ownerOf` [ABI input](https://docs.openzeppelin.com/contracts/2.x/api/token/erc721#IERC721-ownerOf-uint256-)
    
2.  Convert the `name` to a `tokenId`
    
3.  Ask the contract who owns that `tokenId`
    

    async function getOwnerAddressForENSName(name) {
      // do a basic null check
      if (!name) {
        return null;
      }
    
      // define a new contract instance for ENS NFTs
      const nftContract = new web3.eth.Contract(
        [
          {
            inputs: [{ internalType: 'uint256', name: 'tokenId', type: 'uint256' }],
            name: 'ownerOf',
            outputs: [{ internalType: 'address', name: '', type: 'address' }],
            stateMutability: 'view',
            type: 'function',
          },
        ],
        ENS_NFT_ADDRESS
      );
    
      // convert the name to a tokenId
      const tokenId = new BigNumber(Web3.utils.sha3(name.replace(/\.eth$/, ''))).toString();
    
      // ask the contract for the current owner and return the result
      return nftContract.methods
        .ownerOf(tokenId)
        .call()
        .catch(() => null);
    }
    

**Swap ENS names for wallet addresses**

_tl;dr - ask the ENS resolver for the address of a given ENS name_

Let’s kick things up a notch. In order to get the resolved address for a given ENS name, we’ll need a few things:

1.  First we want to define a contract instance for the ENS resolver with the `addr` [method](https://docs.ens.domains/ens-improvement-proposals/ensip-9-multichain-address-resolution). The current contract address is `0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41`
    
2.  We then leverage the `namehash` [algorithm](https://docs.ens.domains/ens-improvement-proposals/ensip-1-ens#namehash-algorithm) to convert the given `name` to a sha3 `node`
    
3.  Ask the contract for the current `addr` value of the given `node`
    

    async function getAddressFromENSName(name) {
      // some basic validity checks
      // @NOTE: non .eth names are valid, but may require a different resolver contract address
      if (!name || !name.endsWith('.eth')) {
        return null;
      }
    
      // define a new contract instance for our ENS resolver
      const resolverContract = new web3.eth.Contract(
        [
          {
            constant: true,
            inputs: [{ internalType: 'bytes32', name: 'node', type: 'bytes32' }],
            name: 'addr',
            outputs: [{ internalType: 'address', name: '', type: 'address' }],
            payable: false,
            stateMutability: 'view',
            type: 'function',
          },
        ],
        ENS_RESOLVER_ADDRESS
      );
    
      // convert our name to a node hash
      const node = namehash(name);
    
      // ask the contract for the current address and return the result
      return resolverContract.methods
        .addr(node)
        .call()
        .catch(() => null);
    }
    

**Swap wallet addresses for ENS names**

_tl;dr - ask the ENS reverse resolver for the ENS name of a given address; double check against the name => address method above_

A final example here, getting the ENS name for a given wallet address is almost identical to the other two methods above:

1.  Again, start by defining a new contract instance for the ENS reverse resolver with the `getNames` [method](https://docs.ens.domains/ens-improvement-proposals/ensip-3-reverse-resolution). The current contract address is `0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C`
    
2.  Ask the contract for the name that corresponds to our given address
    
3.  Double check that the name => address mapping matches. While this step isn’t _necessary_, it’s best practice to ensure no one is manipulating the reverse resolver - more info [from ENS here](https://docs.ens.domains/dapp-developer-guide/resolving-names#reverse-resolution)
    

    async function getENSNameFromAddress(address) {
      // some basic validity checks
      if (!address || address.length !== 42) {
        return null;
      }
    
      // make sure our address is the checksum version
      address = Web3.utils.toChecksumAddress(address);
    
      // define a new contract instance for our ENS reverse resolver
      const reverseResolverContract = new web3.eth.Contract(
        [
          {
            inputs: [{ internalType: 'address[]', name: 'addresses', type: 'address[]' }],
            name: 'getNames',
            outputs: [{ internalType: 'string[]', name: 'r', type: 'string[]' }],
            stateMutability: 'view',
            type: 'function',
          },
        ],
        ENS_REVERSE_RESOLVER_ADDRESS
      );
    
      // ask the contract for the name that maps from the address
      // @NOTE: you can pass multiple addresses in a single call with this method
      const [name] = await reverseResolverContract.methods
        .getNames([address])
        .call()
        .catch(() => []);
    
      // @NOTE: ideally we double check that the reverse resolver is correct
      //        this can be done by comparing against the name => address mapping
      if (address !== (await getAddressFromENSName(name))) {
        return null;
      }
    
      return name;
    }
    

### Wrapping up

There you have it, that’s a quick run down on working with ENS! Both as a web3 user and as a developer in the space. For deeper dives, definitely check out the official [ENS documentation](https://docs.ens.domains/dapp-developer-guide/ens-enabling-your-dapp) and feel free to explore the code from this post on [Github](https://gist.github.com/brock-haugen/e2fe9920b9d2069912b77fe5f0826733). And please reach out if you find this post interesting or just want to chat more about ENS, indexing, and Data 3.0.

![](https://storage.googleapis.com/papyrus_images/5acf23ff6fc88dea5abeac034979835f6788670a26f0bbb62a72c2d665f3fede.gif)

---

*Originally published on [The Indexing Company](https://paragraph.com/@indexingco/ens-a-practical-guide)*
