Originally published at www.toptal.com , written by Radek Ostrowski . In , I introduced you to smart contract development but skimmed over how to develop a distributed application (dapp, stylized ĐApp). This time, I want to focus on precisely that. However, to make our work more meaningful, let’s build a service that allows people to create free Ethereum subdomains with a single blockchain transaction. the previous article in the blockchain series Let’s start this ĐApp tutorial by explaining the Ethereum Name Service (ENS) first. The Ethereum Name Service ENS is a equivalent of the commonly used Domain Name System (DNS). Both of them could be described with a phone-book metaphor. They serve as a lookup service, translating human-readable names into their underlying representations — in the case of DNS and ENS, computer addresses instead of telephone numbers. blockchain DNS translates the domain names of website addresses into Internet Protocol (IP) addresses. They’re easily understood by computers, but not so convenient for us humans. For example, at the time of this writing, represents —which would you rather remember and type? toptal.com 35.186.228.167 $ ping toptal.com PING toptal.com (35.186.228.167): 56 data bytes ENS serves the same purpose, but instead of IP addresses, domains are mapped into Ethereum addresses, which are 42 characters long. The top-level ENS domain is . .eth Interestingly, the equivalent of DNS’ Central Registry is represented as set of . These are running on the Ethereum blockchain, in a distributed manner, “… meaning it doesn’t suffer from the insecurity of the DNS system. You can be confident names you enter work the way their owner intended,” as describes. smart contracts the ENS website Below is a high-level overview of the ENS architecture. The backbone of the service is the ENS registry smart contract, which maps representations of domain names to ENS resolvers’ smart contracts. Those, in turn, map to the target Ethereum address. Looking at the diagram, if an application wanted to resolve the ENS address , it would first query the ENS Registry for the corresponding ENS Resolver and then ask the resolver for the mapping Ethereum address which would respond with . For more information dig into the ENS Documentation . radek.freedomain.eth 0x0987... here ENS Domains .eth ENS launched on May 4th, 2017, and at the moment (phase one), its domains have to contain seven or more characters. It is not possible to use which has six characters, so we will instead use an ENS domain that I bought: . toptal.eth freedomain.eth Anyone can register a domain name by locking in some ether in a Vickrey auction process mediated by deployed smart contracts. The auction consists of two stages, and , lasting three and two days respectively. .eth bid reveal First, an auction for a domain must be started along with placing the first bid. Once it’s running, anyone can place their bids. Once the first stage completes, new bids are no longer accepted and the participants then have to reveal their bids. The winner with the highest bid only has to match the second highest bid, and the rest of the ether is refunded. All the remaining participants also get a refund. But it’s important to note that if you do not reveal your bid in time, the ether you bid is lost. Once you are confirmed the winner, you only have to the auction and set the and the address. Simple? Maybe not so much, if you are new to Ethereum. There are several tools that can help you with that—like , , and —but it’s a multistage process nonetheless. (I also just discovered , which seems a bit more user-friendly.) finalize resolver target MyCrypto MyEtherWallet ENS Manager ENSListing What about subdomains? Are they any simpler? Let’s have a look. ENS Subdomains What use is there of a subdomain in the first place? My best guess is that it’s the same as with subdomains in DNS. They can also give more of an organizational feel to users, where the domain represents the organization and the subdomain resembles the structure of email addresses: [email protected] => radek.freedomain.eth A novel use case currently being implemented by is to use your subdomain as a username/login to Ethereum ĐApps. Imagine a case where there is a ĐApp game which you’ve been playing for a while. It would be great to continue playing the game with the same login from your laptop and your mobile phone as you are on the go even though both devices use different key pairs. This is how this is achieved: Tenzorum Project Log in to the ĐApp using your subdomain, e.g., radek.tenz-id.eth The ĐApp asks you to sign a message to verify you are the holder of the corresponding private key The ĐApp checks that you are authorized to log in by asking your personal wallet smart contract. (You guessed it, the login represented by the ENS subdomain is pointing to your personal wallet’s address.) This has the added benefit of being able to continue playing even if you lose your device (and the private key on it), as you won’t lose the access to your personal wallet. Subdomains map names to addresses exactly the same way as domains do, but you don’t need to go through an auction process to create one. Luckily, there is no minimum length limit on ENS subdomains, either. To register a subdomain, you have to be the owner of the domain as a prerequisite. To create or update a subdomain, you have to call on the ENS registry smart contract. Once successful, the same logic as with domains applies: The owner has to set the and the address. setSubnodeOwner resolver target What if we could automate this and simplify the process for users? I have created [a smart contract that does exactly that — the aforementioned —allowing anyone to create a subdomain with a single blockchain call. However, as the focus of this article is on building ĐApps, I will leave it for you to examine as an exercise. EnsSubdomainFactory.sol Distributed Applications (ĐApps) A ĐApp is simply a front-end website interacting with the blockchain back end. The website must be viewed on a Ethereum-enabled browser like , , or the mobile app ; or by installing the plugin. Mist Parity Cipher MetaMask Instead of a traditional back end with a server and database, the read and write calls are made directly to the Ethereum blockchain. The calls can be done using the JSON RPC protocol, but luckily for us there is a library which wraps the calls in a developer-friendly fashion. Meet Web3. There are several versions in different programming languages, but we are going to use the JavaScript one, . Also, the instance is being injected by the browser, or in the case of our approach here, the MetaMask plugin. web3.js web3 HTML Website So now, we can get down to how to build a ĐApp. In our case, all we need is a simple form with five elements: Input field for subdomain name Dropdown with available domains Input field for the new owner of the subdomain Input field for the target address Submit button I’ve pimped it up a bit with . (Remember, in terms of UI features, a ĐApp is like any other web app, so we don’t need a ĐApp framework — regular web tech like Bootstrap does perfectly well here.) Here’s what it looks like: Bootstrap per se It’s just a regular so we will not elaborate more. All the magic happens in the JavaScript file . HTML website dapp.js JavaScript and Web3 To build any generic ĐApp, what you need is: A Web3 instance (e.g., with MetaMask provider) A way to read from the blockchain (e.g., ethereum balance) A way to write to the blockchain (e.g., send ether) A way to read from a smart contract (e.g., ENS domain owner, or ERC20 token balance) A way to write to a smart contract (e.g., create subdomain, or transfer ERC20 tokens) Additionally, for your decentralized application to interact with a smart contract you need: An Application Binary Interface (ABI) The deployed address of the smart contract I’ll cover the above in turn and show you how we apply them to our ĐApp. The most convenient way to develop ĐApps is with Firefox or Chrome with the MetaMask plugin. For instructions on how to get it installed, please revisit the . previous article As of this writing, there are two relevant versions of web3.js to consider when developing a decentralized app: The and the not-quite-released-but-already-widely-in-use . In this article we are using the latter version. 0.20 1.0.0 The check for the instance happens in the function. This will also work with upcoming MetaMask : web3 initWeb3() web3 injection changes window.addEventListener('load', () => { // If web3 is not injected if (typeof web3 === 'undefined') { // Listen for provider injection window.addEventListener('message', ({ data }) => { if (data && data.type && data.type === 'ETHEREUM_PROVIDER_SUCCESS') { // Use injected provider web3 = new Web3(ethereum); // ... } else { // No web3 instance available. Show a popup // ... } }); // Request provider window.postMessage({ type: 'ETHEREUM_PROVIDER_REQUEST' }, '*'); } // If web3 is injected, use its provider else { web3 = new Web3(web3.currentProvider); // ... } }); If no instance is found, we can display a notification to the user: web3 Interacting with the Blockchain Firstly, let’s get the current loaded Ethereum account, as done in the function: loadAccount() web3.eth.getAccounts(function(error, accounts) { if (error) { // handle error } else { DApp.currentAccount = accounts[0]; // ... } }); We can then auto-populate the input fields for the new owner and target with the address of the current account. In our application, we do not need to interact with ether balances, but for completeness, here is how to check an account balance: web3.eth.getBalance(DApp.currentAccount, function(error, ethBalance) { if (error) { // handle error } else { console.log("Eth balance", ethBalance); } }); …and here is how to send some ether: web3.eth.sendTransaction( { from: DApp.currentAccount, to: receiverAddress, value: ethValue }, function(error, txHash) { if (error) { // handle error } else { console.log("Transaction hash", txHash); } } ); Note that you have to specify the and fields as Ethereum addresses and also the of ether you want to send. This is represented in wei—e.g., is one ether. from to value 1000000000000000000 Interacting with Smart Contracts In order to interact with a smart contract, we first have to create a proxy object. To do this, we need its (ABI), which specifies the available operations. application binary interface We also need the Ethereum address where the smart contract is deployed on the blockchain. In the application, we are interacting with one smart contract, which is our : EnsSubdomainFactory factoryAbi: [...], // Local factoryAddress: "0x9fbda871d559710256a2502a2517b794b482db40", ... The contract is initiated in the function: initContracts() DApp.factoryContract = new web3.eth.Contract(DApp.factoryAbi, DApp.factoryAddress); After this setup, we are finally ready to make some calls. For our use case, we need to know who the current owner of a particular domain and subdomain is, so this is how our function looks: checkSubdomainOwner() DApp.factoryContract.methods.subdomainOwner(subdomain, domain).call() Note that this is a read-only operation: We are using function, which is free to execute—i.e., it does not consume any gas. call() This is how our ĐApp will show that a given domain is available, taken, or owned by the current user: The final blockchain call we need to make is to create or update the subdomain. We do it inside of the function: newSubdomain() DApp.factoryContract.methods.newSubdomain( subdomain, domain, owner, target).send( { gas: 150000, from: DApp.currentAccount }, function(error, txHash) { if (error) { // handle error } else { console.log("Transaction hash", txHash); } } ); This time, we are passing four parameters to the function: , , , and . They are self explanatory. subdomain domain owner target Note that we are using instead of . That’s because this is a write operation and will change the state of the blockchain, and will also cost you some ether as gas. An additional parameter that we include is which represents the gas limit for the transaction. If the transaction costs more than the limit to execute we want it to get reverted. send() call() gas Listening for Events We would like to know when our transaction completes successfully and notify the user that their subdomain is ready to use. The factory smart contract defines an event which gets emitted when the subdomain is created or updated: event SubdomainCreated(address indexed creator, address indexed owner, string domain, string subdomain); Following , we should be able to do this: the web3.js documentation DApp.factoryContract.once('SubdomainCreated', { filter: {creator: DApp.currentAccount} }, function(error, event){ if (error) { // handle error } else { // display a notification that the event happened } } ); Where we specify the event we want to listen to and pass the parameter to only listen to events where the is specified as our . Unfortunately, the current version of MetaMask , which are required by web3.js 1.0 events. This works in older version of web3.js but with a different syntax. SubdomainCreated filter creator DApp.currentAccount does not yet support web sockets As a workaround, we could poll for the transaction receipt to check if it’s been mined, but for simplicity, we will just show a link to Etherscan’s ENS lookup service with the details of our new subdomain, e.g., and the transaction status can be also found in the MetaMask window. https://etherscan.io/enslookup?q=radek.freedomain.eth And this is all we really need to complete our simple ĐApp. For the full source code, feel free to dig in . here Running Locally If you want to play with the code locally, simply check it out and make sure you have the following npm packages installed: npm i -g truffle npm i web3 lite-server eth-ens-namehash-ms You can launch the local testnet with : Truffle $ truffle develop … truffle(develop)> migrate … truffle(develop)> test Using network 'develop'. Contract: EnsSubdomainFactory ✓ creating new subdomain works (143ms) ✓ creating new subdomain fails when factory is not the owner of domain (47ms) ✓ updating subdomain works if done by current owner (215ms) ✓ creating new subdomain fails if it is already owned by someone else (197ms) ✓ transferring domain works (76ms) ✓ cannot transfer domains when locked (97ms) ✓ cannot transfer domains when not contract owner (55ms) ✓ checking for domain and subdomain owner works (138ms) 8 passing (2s) Finally, repoint the factory smart contract to your local node by uncommenting a line in : dapp.js // Local factoryAddress: "0x9fbda871d559710256a2502a2517b794b482db40", // Ropsten // factoryAddress: "0xf9fa2ff44a474b6d20500969bda61c2827fbc6b6", // Mainnet // factoryAddress: "0xbd185de5172ca64eec3d8cc763883a68f9154cd6", To start the web server, simply execute , which should launch your browser on . npm run dev localhost:3000 Note that I’ve included ENS registry and resolver mock contracts for easy local development. The Results on the Ethereum Network The contract is deployed to . 0xbd185de5172ca64eec3d8cc763883a68f9154cd6 Our production ĐApp website is available at . https://ens.startonchain.com The source code with MIT license . is available on GitHub Disclaimer: This is running on the main network, not testnet, so you are operating with real money. Use at your own risk. It’s important to note that domain owners can always change the subdomain owners — even if they are already assigned. We disabled this option in our smart contract, but you should be careful when you are using somebody else’s domain. Welcome to the World of ĐApps In this ĐApp tutorial, I’ve touched on the Ethereum Name Service (ENS), web3.js, ABI, smart contracts, MetaMask, transaction event listeners, and how to generate a Truffle project. This ĐApp does something interesting and useful, letting people create free Ethereum subdomains with a single blockchain transaction. Combined with , I’ve given you enough detail (and hopefully the inspiration) for you to create your own Ethereum-based blockchain app. Best of luck! my smart contract tutorial A smart contract is a computer program that gets executed on the blockchain’s nodes. Smart contracts can perform any calculation, persist data, define business rules, and also send and accept native currency like ether. Contracts are immutable in nature, unless programmed otherwise. The internet’s Domain Name System (DNS) is a hierarchical, decentralized service translating human-friendly domain names like `toptal.com` into numerical IP addresses like `35.186.228.167`, which are required by computers on the Internet to locate data and serve content like websites. An Ethereum Name Service (ENS) domain is equivalent to a DNS domain and offers a decentralized and secure way to translate human-memorable text into Ethereum addresses. ENS domains currently end with .eth and have seven or more characters. They can be bought in an auction and can have hierarchical subdomains. A ĐApp is simply a front-end website interacting with the blockchain back-end (usually via web3) instead of a traditional back-end with a server and a database. The website must be viewed on an Ethereum-enabled browser like Mist, Parity, or the mobile app Cipher; or by installing the MetaMask plugin. All blockchains are distributed in nature as they have separate nodes working together in a distributed manner. Not all blockchains are decentralized, though. Some are centralized if there is a company that can censor, change, or stop the operation of the blockchain. Subdomains are part of second-level domains, but are considered separate entities by search engines. They can be used to create different websites for different regions, languages, departments, user types, or device types. E.g., a dedicated mobile version of example.com might use the m.example.com subdomain. Originally published at www.toptal.com .