Adding ENS into your Dapp

We recently announced ENS Hackathon and we decided to use Blockaprty for registration Bloc(thanks Nick for his bravely decision to use the breeding edge Dap).

The aim is to make participants to stake small deposit to prevent no shows but this is also to filter out participants who have no clue how to interact with Dapps (you don’t know how many people have tried to register by sending ETH from exchanges).

For ENS hackathon, we can do even better. Why don’t we integrate ENS into the Dapp so that we can actually show who knows how to set their ens names into their ETH address?

In this blog post, I will show you how I implmented step by step.

NOTE: The frontend code of BlockParty is quite a mess and due for rewrite so please focus on the code snippets rather than the overall structure.

Step 1: Install ethereum-ens

There are multiple ways to interact with ENS

To interact with ENS at frontend, we recommend using ethereum-ens.

You can use normal npm command to install the library into your project.

npm install ethereum-ens --save

Once done, import the library into your js file and instantiate the ENS object by passing web3 provider, as wriiten in the library readme section.

Don’t do “window.ens”, boys and girls! 🙈🙈🙈

Resolve and Reverse

Now that you can interact with ENS, the first thing you can do is to lookup ETH address with a given ENS name like the following.

var address = ens.resolver('foo.eth').addr()

However, what I want to do is a reverse. I want to find a ENS name which is associated to an ETH address. For that purpose, you need to call reverse()

ens.reverse('0xabc...').name()

In my example, chanined the method call with catch(){} because if the reverse() function does not find any matching name, it will raise exception.

That was easy so far, isn’t it?

Making it work on your development environment

The integration works fine if you are connecting to public network, mainnet, rinkeby, and ropsten as the ethereum--ens automagically detect the network you are currently connecting and connect to the correct ENS smart contract. However ENS will have no idea what is the ENS contract address in your own test environment such as ganache.

Luckily ENS already supports non default ENS address by passing the contract address as a second argument like this.

Hold on! Where did you get ENSContract.address? Good question. This is where your rabbit hole starts.

Deploying ENS locally.

Installing the bits.

As I mentioned earlier, ENS is just another truffle project so you can deploy using truffle migrate, but you don't want to copy&paste smart contracts. Instead, you can install the smart contract using npm command.

npm install @ensdomains/ens --save-dev

What this does is to download and copy contract artifacts (JSON file including ABI) under node_modules

$ tree node_modules/@ensdomains/ens/build
node_modules/@ensdomains/ens/build
├── Dockerfile
├── README.md
└── contracts
├── DNSResolver.json
├── Deed.json
├── DefaultReverseResolver.json
├── ENS.json
├── ENS.lll.json
├── ENSRegistry.json
├── FIFSRegistrar.json
├── Migrations.json
├── PublicResolver.json
├── Registrar.json
├── Resolver.json
├── ResolverInterface.json
├── ReverseRegistrar.json
└── TestRegistrar.json

You also want to install eth-ens-namehash which we are going to use later.

npm install eth-ens-namehash --save-dev

Writing a migration file

After the basic setup is done, now you need to include ENS, PublicResolver, and ReverseRegistrar.

This will take ABI from the JSON artifacts stored under the node module (If you want to know more how this works behind the scene, you may want to check out my proud first contribution to Truffle project)

Once these contract artifacts are accessible from your migration file, then let’s deploy the contract as well as setting some ownership.

The interesting thing you notice is that reverse address is just another resolver which is pointing with special toplevel domain called .reverse (You can find out more detail on the doc).

Once you finish writing the migration file, let’s deploy with normal truffle command.

truffle migrate

Connecting to the test ENS address

Once you run the migration, the deployed contract address will be under your build/contracts/*json directory.

Go back to your front end code and add the following.

import TruffleContract from 'truffle-contract'
import ENSArtifacts from '../build/contracts/ENSRegistry.json';
var ENSContract = TruffleContract(ENSArtifacts);
var ens = new ENS(provider, ENSContract.address);

Assign domains

Now your Dapp handles ENS on any network, but wait. How do I set ens name?

One way to do so is just interact ENS contract via truffle console but you don't want to do that every time you want to test ENS integration.

To make my own life simpler, I wrote a simple truffle script to automate like this.

truffle exec scripts/ens.js -n ethlab -a 0x123'

This will create ethlab.eth and set it to 0x123 address.

Here is the full source code.

There are a few things worth your attention.

Firstly, you require the ENS contracts without @ensdomains/ens prefix.

const ENSRegistry = artifacts.require('ENSRegistry.sol');
const PublicResolver = artifacts.require('PublicResolver.sol');
const ReverseRegistrar = artifacts.require('ReverseRegistrar.sol');

Why? If you call the contract with @ensdomains/ens, Truffle tries to lookup artifacts under your node_module folder but the artifact file has no deployed ENS address. Hence you specify the contract addreses without prefix so that Truffle lookup the default location build/contracts/*json.

Secondly, there are no registrar because you are the owner of the ENS address so you can just set all the domains by yourself.

Thirdly, look out how the script is setting the name as well as searching the name.

await reverseresolver.setName(`${name}.eth`, { from: address});

Reverse resolver is just another resolver which sets a string to a ENS name. Let’s see the source code of ReverseResolver.

function setName(bytes32 node, string _name) public owner_only(node) {
name[node] = _name;
}

Once the name is set, you can resolve it by loolking up address.addr.reverse (without 0x hence .slice(2)).

let res2 = await resolver.name.call(namehash.hash(`${address.slice(2)}.addr.reverse`));

In fact, if you look into the ethereum-ens library which you used, that's exactly what the reverse() function is doing.

ENS_1.prototype.reverse = function(address, abi) {
if(address.startsWith("0x"))
address = address.slice(2);
return this.resolver(address.toLowerCase() + ".addr.reverse", abi);
};

Making it better

Now your Dapp is fully integrated into ENS for address lookup purpose. Yay!

However, it is quite hectic to set them all up. Can we automate this to make it a lot easier?

If you are interesting in helping us out, why don’t you join our ENS hackathon?