diff --git a/lib/modules/ens/ENSFunctions.js b/lib/modules/ens/ENSFunctions.js new file mode 100644 index 00000000..a73de580 --- /dev/null +++ b/lib/modules/ens/ENSFunctions.js @@ -0,0 +1,107 @@ +const namehash = require('eth-ens-namehash'); + +const reverseAddrSuffix = '.addr.reverse'; +const voidAddress = '0x0000000000000000000000000000000000000000'; +const NoDecodeAddrError = 'Error: Couldn\'t decode address from ABI: 0x'; +const NoDecodeStringError = 'ERROR: The returned value is not a convertible string: 0x0'; + +function registerSubDomain(ens, registrar, resolver, defaultAccount, subdomain, rootDomain, reverseNode, address, logger, callback) { + const subnode = namehash.hash(subdomain); + const node = namehash.hash(`${subdomain}.${rootDomain}`); + const toSend = registrar.methods.register(subnode, defaultAccount); + let transaction; + + toSend.estimateGas() + // Register domain + .then(gasEstimated => { + return toSend.send({gas: gasEstimated + 1000, from: defaultAccount}); + }) + // Set resolver for the node + .then(transac => { + if (transac.status !== "0x1" && transac.status !== "0x01" && transac.status !== true) { + logger.warn('Failed transaction', transac); + return callback('Failed to register. Check gas cost.'); + } + transaction = transac; + return ens.methods.setResolver(node, resolver.options.address).send({from: defaultAccount}); + }) + // Set address for node + .then(_result => { + return resolver.methods.setAddr(node, address).send({from: defaultAccount}); + }) + // Set resolver for the reverse node + .then(_result => { + return ens.methods.setResolver(reverseNode, resolver.options.address).send({from: defaultAccount}); + }) + // Set name for reverse node + .then(_result => { + return resolver.methods.setName(reverseNode, subdomain + '.embark.eth').send({from: defaultAccount}); + }) + .then(_result => { + callback(null, transaction); + }) + .catch(err => { + logger.error(err); + callback('Failed to register with error: ' + (err.message || err)); + }); +} + +function lookupAddress(address, ens, utils, createResolverContract, callback) { + if (address.startsWith("0x")) { + address = address.slice(2); + } + + let node = utils.soliditySha3(address.toLowerCase() + reverseAddrSuffix); + + function cb(err, name) { + if (err === NoDecodeStringError || err === NoDecodeAddrError) { + return callback('Address does not resolve to name. Try syncing chain.'); + } + return callback(err, name); + } + + return ens.methods.resolver(node).call((err, resolverAddress) => { + if (err) { + return cb(err); + } + if (resolverAddress === voidAddress) { + return cb('Address not associated to a resolver'); + } + createResolverContract(resolverAddress, (_, resolverContract) => { + resolverContract.methods.name(node).call(cb); + }); + + }); +} + +function resolveName(name, ens, createResolverContract, callback) { + let node = namehash.hash(name); + + function cb(err, addr) { + if (err === NoDecodeAddrError) { + return callback(name + " is not registered", "0x"); + } + callback(err, addr); + } + + return ens.methods.resolver(node).call((err, resolverAddress) => { + if (err) { + return cb(err); + } + if (resolverAddress === voidAddress) { + return cb('Name not yet registered'); + } + createResolverContract(resolverAddress, (_, resolverContract) => { + resolverContract.methods.addr(node).call(cb); + }); + }); +} + +if (typeof module !== 'undefined' && module.exports) { + module.exports = { + registerSubDomain, + resolveName, + lookupAddress + }; +} +; diff --git a/lib/modules/ens/embarkjs.js b/lib/modules/ens/embarkjs.js index eed0258e..16b45d00 100644 --- a/lib/modules/ens/embarkjs.js +++ b/lib/modules/ens/embarkjs.js @@ -1,4 +1,4 @@ -/*global EmbarkJS, web3, registerSubDomain, namehash*/ +/*global EmbarkJS, web3, ENSFunctions, namehash*/ let __embarkENS = {}; @@ -132,10 +132,7 @@ __embarkENS.resolverInterface = [ ]; const providerNotSetError = 'ENS provider not set'; -const NoDecodeAddrError = 'Error: Couldn\'t decode address from ABI: 0x'; -const NoDecodeStringError = 'ERROR: The returned value is not a convertible string: 0x0'; const reverseAddrSuffix = '.addr.reverse'; -const voidAddress = '0x0000000000000000000000000000000000000000'; __embarkENS.registryAddresses = { // Mainnet @@ -171,30 +168,17 @@ __embarkENS.setProvider = function (config) { }); }; +const createResolverContract = function (address, callback) { + callback(null, new EmbarkJS.Contract({abi: this.resolverInterface, address})); +}; + __embarkENS.resolve = function (name, callback) { callback = callback || function () {}; if (!this.ens) { return callback(providerNotSetError); } - let node = namehash.hash(name); - function cb(err, addr) { - if (err === NoDecodeAddrError) { - return callback(name + " is not registered", "0x"); - } - callback(err, addr); - } - - return this.ens.methods.resolver(node).call((err, resolverAddress) => { - if (err) { - return cb(err); - } - if (resolverAddress === voidAddress) { - return cb('Name not yet registered'); - } - let resolverContract = new EmbarkJS.Contract({abi: this.resolverInterface, address: resolverAddress}); - resolverContract.methods.addr(node).call(cb); - }); + ENSFunctions.resolveName(name, this.ens, createResolverContract, callback); }; __embarkENS.lookup = function (address, callback) { @@ -202,28 +186,8 @@ __embarkENS.lookup = function (address, callback) { if (!this.ens) { return callback(providerNotSetError); } - if (address.startsWith("0x")) { - address = address.slice(2); - } - let node = web3.utils.soliditySha3(address.toLowerCase() + reverseAddrSuffix); - function cb(err, name) { - if (err === NoDecodeStringError || err === NoDecodeAddrError) { - return callback('Address does not resolve to name. Try syncing chain.'); - } - return callback(err, name); - } - - return this.ens.methods.resolver(node).call((err, resolverAddress) => { - if (err) { - return cb(err); - } - if (resolverAddress === voidAddress) { - return cb('Address not associated to a resolver'); - } - let resolverContract = new EmbarkJS.Contract({abi: this.resolverInterface, address: resolverAddress}); - resolverContract.methods.name(node).call(cb); - }); + return ENSFunctions.lookupAddress(address, this.ens, web3.utils, createResolverContract.bind(this), callback); }; __embarkENS.registerSubDomain = function (name, address, callback) { @@ -240,8 +204,9 @@ __embarkENS.registerSubDomain = function (name, address, callback) { } // Register function generated by the index - registerSubDomain(this.ens, this.registrar, this.resolver, web3.eth.defaultAccount, name, this.registration.rootDomain, - web3.utils.soliditySha3(address.toLowerCase().substr(2) + reverseAddrSuffix), address, console, callback); + ENSFunctions.registerSubDomain(this.ens, this.registrar, this.resolver, web3.eth.defaultAccount, + name, this.registration.rootDomain, web3.utils.soliditySha3(address.toLowerCase().substr(2) + reverseAddrSuffix), + address, console, callback); }; __embarkENS.isAvailable = function () { diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index 878c6682..8e42515b 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -2,6 +2,7 @@ const fs = require('../../core/fs.js'); const utils = require('../../utils/utils.js'); const namehash = require('eth-ens-namehash'); const async = require('async'); +const ENSFunctions = require('./ENSFunctions'); const reverseAddrSuffix = '.addr.reverse'; @@ -51,12 +52,12 @@ class ENS { resolverAddress: results[2].deployedAddress }; self.addSetProvider(config); + self.registerAPI(config); if (!self.env === 'development' || !self.registration || !self.registration.subdomains || !Object.keys(self.registration.subdomains).length) { return cb(); } - self.registerAPI(config); self.registerConfigSubdomains(config, cb); }); }); @@ -64,11 +65,21 @@ class ENS { registerAPI(config) { let self = this; + + const createInternalResolverContract = function(resolverAddress, callback) { + this.createResolverContract({resolverAbi: config.resolverAbi, resolverAddress}, callback) + }; + self.embark.registerAPICall( 'get', '/embark-api/ens/resolve', (req, res) => { - self.resolveSubdomain(req.query.subdomain, config, (error, address) => { + async.waterfall([ + self.createRegistryContract.bind(this, config), + function(ens, callback) { + ENSFunctions.resolveName(req.query.name, ens, createInternalResolverContract.bind(self), callback); + } + ], function(error, address) { if (error) { return res.send({error: error.message}); } @@ -81,12 +92,16 @@ class ENS { 'get', '/embark-api/ens/lookup', (req, res) => { - self.lookupAddress(req.query.address, config, (error, name) => { + async.waterfall([ + self.createRegistryContract.bind(this, config), + function(ens, callback) { + ENSFunctions.lookupAddress(req.query.address, ens, utils, createInternalResolverContract.bind(self), callback); + } + ], function(error, name) { if (error) { return res.send({error: error.message}); } - const subdomain = name.replace(new RegExp(self.registration.rootDomain + '$'), ''); - res.send({subdomain}); + res.send({name}); }); } ); @@ -109,36 +124,8 @@ class ENS { this.registerSubdomains(this.registration.subdomains, config, callback); } - lookupAddress(address, config, callback) { - let self = this; - self.createResolverContract(config, (err, resolver) => { - if (err) { - return callback(err); - } - - if (address.startsWith("0x")) { - address = address.slice(2); - } - let node = utils.soliditySha3(address.toLowerCase() + reverseAddrSuffix); - resolver.methods.name(node).call(callback); - }); - } - - resolveSubdomain(subdomain, config, callback) { - let self = this; - self.createResolverContract(config, (err, resolver) => { - if (err) { - return callback(err); - } - - const node = namehash.hash(`${subdomain}.${self.registration.rootDomain}`); - resolver.methods.addr(node).call(callback); - }); - } - registerSubdomains(subdomains, config, callback) { const self = this; - const register = require('./register'); self.events.request("blockchain:defaultAccount:get", (defaultAccount) => { async.parallel({ @@ -154,8 +141,8 @@ class ENS { async.each(Object.keys(subdomains), (subdomainName, eachCb) => { const address = subdomains[subdomainName]; const reverseNode = utils.soliditySha3(address.toLowerCase().substr(2) + reverseAddrSuffix); - register(ens, registrar, resolver, defaultAccount, subdomainName, self.registration.rootDomain, - reverseNode, address, self.logger, eachCb); + ENSFunctions.registerSubDomain(ens, registrar, resolver, defaultAccount, subdomainName, + self.registration.rootDomain, reverseNode, address, self.logger, eachCb); }, callback); }); }); @@ -209,7 +196,7 @@ class ENS { } }); - let code = fs.readFileSync(utils.joinPath(__dirname, 'register.js')).toString(); + let code = fs.readFileSync(utils.joinPath(__dirname, 'ENSFunctions.js')).toString(); code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString(); code += "\nEmbarkJS.Names.registerProvider('ens', __embarkENS);"; diff --git a/lib/modules/ens/register.js b/lib/modules/ens/register.js deleted file mode 100644 index cfed7218..00000000 --- a/lib/modules/ens/register.js +++ /dev/null @@ -1,46 +0,0 @@ -const namehash = require('eth-ens-namehash'); - -function registerSubDomain(ens, registrar, resolver, defaultAccount, subdomain, rootDomain, reverseNode, address, logger, callback) { - const subnode = namehash.hash(subdomain); - const node = namehash.hash(`${subdomain}.${rootDomain}`); - const toSend = registrar.methods.register(subnode, defaultAccount); - let transaction; - - toSend.estimateGas() - // Register domain - .then(gasEstimated => { - return toSend.send({gas: gasEstimated + 1000, from: defaultAccount}); - }) - // Set resolver for the node - .then(transac => { - if (transac.status !== "0x1" && transac.status !== "0x01" && transac.status !== true) { - logger.warn('Failed transaction', transac); - return callback('Failed to register. Check gas cost.'); - } - transaction = transac; - return ens.methods.setResolver(node, resolver.options.address).send({from: defaultAccount}); - }) - // Set address for node - .then(_result => { - return resolver.methods.setAddr(node, address).send({from: defaultAccount}); - }) - // Set resolver for the reverse node - .then(_result => { - return ens.methods.setResolver(reverseNode, resolver.options.address).send({from: defaultAccount}); - }) - // Set name for reverse node - .then(_result => { - return resolver.methods.setName(reverseNode, subdomain + '.embark.eth').send({from: defaultAccount}); - }) - .then(_result => { - callback(null, transaction); - }) - .catch(err => { - logger.error(err); - callback('Failed to register with error: ' + (err.message || err)); - }); -} - -if (typeof module !== 'undefined' && module.exports) { - module.exports = registerSubDomain; -}