Ethereum Name Service (ENS)

The Ethereum Name Service (ENS) is analogous to the Domain Name Service. It enables users and developers to use human-friendly names in place of error-prone hexadecimal addresses, content hashes, and more.

The ens module is included with Web3.py. It provides an interface to look up domains and addresses, add resolver records, or get and set metadata.

Setup

Create an ENS object (named ns below) in one of three ways:

  1. Automatic detection

  2. Specify an instance or list of Providers

  3. From an existing web3.Web3 object

# automatic detection
from ens.auto import ns

# or, with a provider
from web3 import IPCProvider
from ens import ENS

provider = IPCProvider(...)
ns = ENS(provider)

# or, with a w3 instance
# Note: This inherits the w3 middlewares from the w3 instance and adds a stalecheck middleware to the middleware onion
from ens import ENS
w3 = Web3(...)
ns = ENS.fromWeb3(w3)

Asynchronous support is available via the AsyncENS module:

from ens import AsyncENS

ns = AsyncENS(provider)

Note that an ens module instance is also avaliable on the w3 instance. The first time it’s used, Web3.py will create the ens instance using ENS.fromWeb3(w3) or AsyncENS.fromWeb3(w3) as appropriate.

# instantiate w3 instance
from web3 import Web3, IPCProvider
w3 = Web3(IPCProvider(...))

# use the module
w3.ens.address('ethereum.eth')

Usage

Name Info

Get the Address for an ENS Name

from ens.auto import ns
eth_address = ns.address('jasoncarver.eth')
assert eth_address == '0x5B2063246F2191f18F2675ceDB8b28102e957458'

The ENS module has no opinion as to which TLD you can use, but will not infer a TLD if it is not provided with the name.

Get the ENS Name for an Address

domain = ns.name('0x5B2063246F2191f18F2675ceDB8b28102e957458')

# name() also accepts the bytes version of the address
assert ns.name(b'[ c$o!\x91\xf1\x8f&u\xce\xdb\x8b(\x10.\x95tX') == domain

# confirm that the name resolves back to the address that you looked up:
assert ns.address(domain) == '0x5B2063246F2191f18F2675ceDB8b28102e957458'

Note

For accuracy, and as a recommendation from the ENS documentation on reverse resolution, the ENS module now verifies that the forward resolution matches the address with every call to get the name() for an address. This is the only sure way to know whether the reverse resolution is correct. Anyone can claim any name, only forward resolution implies that the owner of the name gave their stamp of approval.

Get the Owner of a Name

eth_address = ns.owner('exchange.eth')

Set Up Your Name and Address


Text Records

Set Text Metadata for an ENS Record

As the owner of an ENS record, you can add text metadata. A list of supported fields can be found in the ENS documentation. You’ll need to setup the address first, and then the text can be set:

ns.setup_address('jasoncarver.eth', '0x5B2063246F2191f18F2675ceDB8b28102e957458')
ns.set_text('jasoncarver.eth', 'url', 'https://example.com')

A transaction dictionary can be passed as the last argument if desired:

transaction_dict = {'from': '0x123...'}
ns.set_text('jasoncarver.eth', 'url', 'https://example.com', transaction_dict)

If the transaction dictionary is not passed, sensible defaults will be used, and if a transaction dictionary is passed but does not have a from value, the default will be the owner.

Read Text Metadata for an ENS Record

Anyone can read the data from an ENS Record:

url = ns.get_text('jasoncarver.eth', 'url')
assert url == 'https://example.com'

Working With Resolvers

Get the Resolver for an ENS Record

You can get the resolver for an ENS name via the resolver() method.

>>> resolver = ns.resolver('jasoncarver.eth')
>>> resolver.address
'0x5FfC014343cd971B7eb70732021E26C35B744cc4'

Wildcard Resolution Support

The ENS module supports Wildcard Resolution for resolvers that implement the ExtendedResolver interface as described in ENSIP-10. Resolvers that implement the extended resolver interface should return True when calling the supportsInterface() function with the extended resolver interface id 0x9061b923 and should resolve subdomains to a unique address.

A working example of a resolver that supports wildcard resolution is the resolver for the hatch.eth record on the Ropsten testnet.

# connect to the Ropsten testnet
>>> w3 = Web3(WebsocketProvider("wss://{ropsten_provider}"))
>>> ns = ENS.fromWeb3(w3)

# get the resolver for `hatch.eth`
>>> resolver = ns.resolver('hatch.eth')
>>> resolver.address
'0x8fc4C380c5d539aE631daF3Ca9182b40FB21D1ae'

# verify extended resolver interface support
>>> resolver.caller.supportsInterface('0x9061b923')
True

>>> ns.address('random-subdomain.hatch.eth')
'0x49D4c4ff230688e4A357bc057e7E35e64d271939'
>>> ns.address('another-random-subdomain.hatch.eth')
'0xb35359B6450B0CbC9BE15A4eE6bcb8c5b0d9fC4A'