/ lib / modules / ens / ENSFunctions.js
ENSFunctions.js
  1  /*global web3*/
  2  const namehash = require('eth-ens-namehash');
  3  // Price of ENS registration contract functions
  4  const ENS_GAS_PRICE = 700000;
  5  
  6  const reverseAddressSuffix = '.addr.reverse';
  7  const voidAddr = '0x0000000000000000000000000000000000000000';
  8  const NoDecodeAddrErr = 'Error: Couldn\'t decode address from ABI: 0x';
  9  const NoDecodeStringErr = 'ERROR: The returned value is not a convertible string: 0x0';
 10  
 11  function registerSubDomain(ens, registrar, resolver, defaultAccount, subdomain, rootDomain, reverseNode, address, logger, secureSend, callback) {
 12    const subnode = namehash.hash(subdomain);
 13    const rootNode = namehash.hash(rootDomain);
 14    const node = namehash.hash(`${subdomain}.${rootDomain}`);
 15    // FIXME Registrar calls a function in ENS and in privatenet it doesn't work for soem reason
 16    // const toSend = registrar.methods.register(subnode, defaultAccount);
 17    const toSend = ens.methods.setSubnodeOwner(rootNode, subnode, defaultAccount);
 18    let transaction;
 19  
 20    secureSend(web3, toSend, {from: defaultAccount, gas: ENS_GAS_PRICE}, false)
 21    // Set resolver for the node
 22      .then(transac => {
 23        if (transac.status !== "0x1" && transac.status !== "0x01" && transac.status !== true) {
 24          logger.warn('Failed transaction', transac);
 25          return callback('Failed to register. Check gas cost.');
 26        }
 27        transaction = transac;
 28        return secureSend(web3, ens.methods.setResolver(node, resolver.options.address), {from: defaultAccount, gas: ENS_GAS_PRICE}, false);
 29      })
 30      // Set address for node
 31      .then(_result => {
 32        return secureSend(web3, resolver.methods.setAddr(node, address), {from: defaultAccount, gas: ENS_GAS_PRICE}, false);
 33      })
 34      // Set resolver for the reverse node
 35      .then(_result => {
 36        return secureSend(web3, ens.methods.setResolver(reverseNode, resolver.options.address), {from: defaultAccount, gas: ENS_GAS_PRICE}, false);
 37      })
 38      // Set name for reverse node
 39      .then(_result => {
 40        return secureSend(web3, resolver.methods.setName(reverseNode, `${subdomain}.${rootDomain}`), {from: defaultAccount, gas: ENS_GAS_PRICE}, false);
 41      })
 42      .then(_result => {
 43        callback(null, transaction);
 44      })
 45      .catch(err => {
 46        logger.error(err.message || err);
 47        callback('Failed to register with error: ' + (err.message || err));
 48      });
 49  }
 50  
 51  function lookupAddress(address, ens, utils, createResolverContract, callback) {
 52    if (address.startsWith("0x")) {
 53      address = address.slice(2);
 54    }
 55  
 56    let node = utils.soliditySha3(address.toLowerCase() + reverseAddressSuffix);
 57  
 58    function cb(err, name) {
 59      if (err === NoDecodeStringErr || err === NoDecodeAddrErr) {
 60        return callback('Address does not resolve to name. Try syncing chain.');
 61      }
 62      return callback(err, name);
 63    }
 64  
 65    return ens.methods.resolver(node).call((err, resolverAddress) => {
 66      if (err) {
 67        return cb(err);
 68      }
 69      if (resolverAddress === voidAddr) {
 70        return cb('Address not associated to a resolver');
 71      }
 72      createResolverContract(resolverAddress, (_, resolverContract) => {
 73        resolverContract.methods.name(node).call(cb);
 74      });
 75  
 76    });
 77  }
 78  
 79  function resolveName(name, ens, createResolverContract, callback) {
 80    let node = namehash.hash(name);
 81  
 82    function cb(err, addr) {
 83      if (err === NoDecodeAddrErr) {
 84        return callback(name + " is not registered", "0x");
 85      }
 86      callback(err, addr);
 87    }
 88  
 89    return ens.methods.resolver(node).call((err, resolverAddress) => {
 90      if (err) {
 91        return cb(err);
 92      }
 93      if (resolverAddress === voidAddr) {
 94        return cb('Name not yet registered');
 95      }
 96      createResolverContract(resolverAddress, (_, resolverContract) => {
 97        resolverContract.methods.addr(node).call(cb);
 98      });
 99    });
100  }
101  
102  if (typeof module !== 'undefined' && module.exports) {
103    module.exports = {
104      registerSubDomain,
105      resolveName,
106      lookupAddress
107    };
108  }