From a87b543f64e7ce610d9a446b7b1a2cabb8e0e0dc Mon Sep 17 00:00:00 2001 From: Anthony Laibe Date: Tue, 14 Aug 2018 16:12:03 +0100 Subject: [PATCH] Lookup/Resolver between EmbarkJS and Embark --- lib/modules/ens/ENSFunctions.js | 107 ++++++++++++++++++++++++++++++++ lib/modules/ens/embarkjs.js | 50 +++------------ lib/modules/ens/index.js | 56 +++++++---------- 3 files changed, 135 insertions(+), 78 deletions(-) create mode 100644 lib/modules/ens/ENSFunctions.js 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 2a85d36e..3a54dac4 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 @@ -183,30 +180,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) { @@ -214,28 +198,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) { diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js index 42d8a537..98b7f508 100644 --- a/lib/modules/ens/index.js +++ b/lib/modules/ens/index.js @@ -193,11 +193,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}); } @@ -210,12 +220,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}); }); } ); @@ -238,36 +252,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({ @@ -283,8 +269,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); }); }); @@ -330,7 +316,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);";