From a568835ceb426e458734c593f561977f20ae56ef Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Wed, 27 Dec 2017 19:10:05 -0500 Subject: [PATCH] separate components; extract ipfs; add register method --- js/embark.js | 377 +------------------------------- js/embarkjs/ipfs.js | 97 ++++++++ js/embarkjs/orbit.js | 71 ++++++ js/embarkjs/whisper.js | 177 +++++++++++++++ lib/contracts/code_generator.js | 4 + 5 files changed, 361 insertions(+), 365 deletions(-) create mode 100644 js/embarkjs/ipfs.js create mode 100644 js/embarkjs/orbit.js create mode 100644 js/embarkjs/whisper.js diff --git a/js/embark.js b/js/embark.js index 97578b6ae..83c41d909 100644 --- a/js/embark.js +++ b/js/embark.js @@ -182,19 +182,12 @@ EmbarkJS.Contract.prototype.send = function(value, unit, _options) { this.web3.eth.sendTransaction(options); }; -//========================================================= -// Embark Storage -//========================================================= - EmbarkJS.Storage = {}; EmbarkJS.Storage.Providers = { - IPFS: 'ipfs', SWARM: 'swarm' }; -EmbarkJS.Storage.IPFS = {}; - EmbarkJS.Storage.saveText = function(text) { return this.currentStorage.saveText(text); }; @@ -211,119 +204,22 @@ EmbarkJS.Storage.getUrl = function(hash) { return this.currentStorage.getUrl(hash); }; +EmbarkJS.Storage.registerProvider = function(providerName, obj) { + EmbarkJS.Storage.Providers[providerName] = obj; +}; + EmbarkJS.Storage.setProvider = function(provider, options) { - var self = this; - var promise = new Promise(function(resolve, reject) { - if (provider.toLowerCase() === EmbarkJS.Storage.Providers.IPFS) { - //I don't think currentStorage is used anywhere, this might not be needed - //for now until additional storage providers are supported. But keeping it - //anyways - self.currentStorage = EmbarkJS.Storage.IPFS; + let provider = this.Providers[provider]; - try { - if (options === undefined) { - self.ipfsConnection = IpfsApi('localhost', '5001'); - self._getUrl = "http://localhost:8080/ipfs/"; - } else { - self.ipfsConnection = IpfsApi(options.server, options.port); - self._getUrl = options.getUrl || "http://localhost:8080/ipfs/"; - } - resolve(self); - } catch (err) { - console.log(err); - self.ipfsConnection = null; - reject(new Error('Failed to connect to IPFS')); - } - } else if (provider.toLowerCase() === EmbarkJS.Storage.SWARM) { - reject('Swarm not implemented'); - // TODO Implement Swarm - // this.currentStorage = EmbarkJS.Storage.SWARM; - // if (options === undefined) { - // //Connect to default Swarm node - // } else { - // //Connect using options - // } - } else { - reject('Unknown storage provider'); - } - }); - return promise; + if (!provider) { + throw new Error('Unknown storage provider'); + } + + this.currentStorage = provider; + + return provider.setProvider(options); }; -EmbarkJS.Storage.IPFS.saveText = function(text) { - var promise = new Promise(function(resolve, reject) { - if (!EmbarkJS.Storage.ipfsConnection) { - var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); - reject(connectionError); - } - EmbarkJS.Storage.ipfsConnection.add((new EmbarkJS.Storage.ipfsConnection.Buffer(text)), function(err, result) { - if (err) { - reject(err); - } else { - resolve(result[0].path); - } - }); - }); - - return promise; -}; - -EmbarkJS.Storage.IPFS.get = function(hash) { - // TODO: detect type, then convert if needed - //var ipfsHash = web3.toAscii(hash); - var promise = new Promise(function(resolve, reject) { - if (!EmbarkJS.Storage.ipfsConnection) { - var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); - reject(connectionError); - } - EmbarkJS.Storage.ipfsConnection.object.get(hash).then(function(node) { - resolve(node.data.toString()); - }).catch(function(err) { - reject(err); - }); - }); - - return promise; -}; - -EmbarkJS.Storage.IPFS.uploadFile = function(inputSelector) { - var file = inputSelector[0].files[0]; - - if (file === undefined) { - throw new Error('no file found'); - } - - var promise = new Promise(function(resolve, reject) { - if (!EmbarkJS.Storage.ipfsConnection) { - var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); - reject(connectionError); - } - var reader = new FileReader(); - reader.onloadend = function() { - var fileContent = reader.result; - var buffer = EmbarkJS.Storage.ipfsConnection.Buffer.from(fileContent); - EmbarkJS.Storage.ipfsConnection.add(buffer, function(err, result) { - if (err) { - reject(err); - } else { - resolve(result[0].path); - } - }); - }; - reader.readAsArrayBuffer(file); - }); - - return promise; -}; - -EmbarkJS.Storage.IPFS.getUrl = function(hash) { - return (self._getUrl || "http://localhost:8080/ipfs/") + hash; -}; - -//========================================================= -// Embark Messaging -//========================================================= - EmbarkJS.Messages = {}; EmbarkJS.Messages.web3CompatibleWithV5 = function() { @@ -413,255 +309,6 @@ EmbarkJS.Messages.listenTo = function(options) { return this.currentMessages.listenTo(options); }; -EmbarkJS.Messages.Whisper = {}; - -EmbarkJS.Messages.Whisper.sendMessage = function(options) { - var topics, data, ttl, priority, payload; - if (EmbarkJS.Messages.isNewWeb3()) { - topics = options.topic || options.topics; - data = options.data || options.payload; - ttl = options.ttl || 100; - priority = options.priority || 1000; - var powTime = options.powTime || 3; - var powTarget = options.powTarget || 0.5; - - if (topics === undefined) { - throw new Error("missing option: topic"); - } - - if (data === undefined) { - throw new Error("missing option: data"); - } - - topics = this.web3.utils.toHex(topics).slice(0, 10); - - payload = JSON.stringify(data); - - let message = { - symKeyID: this.symKeyID, // encrypts using the sym key ID - sig: this.sig, // signs the message using the keyPair ID - ttl: ttl, - topic: topics, - payload: EmbarkJS.Utils.fromAscii(payload), - powTime: powTime, - powTarget: powTarget - }; - - this.web3.shh.post(message, function() { }); - } else { - topics = options.topic || options.topics; - data = options.data || options.payload; - ttl = options.ttl || 100; - priority = options.priority || 1000; - var identity = options.identity || this.identity || web3.shh.newIdentity(); - var _topics; - - if (topics === undefined) { - throw new Error("missing option: topic"); - } - - if (data === undefined) { - throw new Error("missing option: data"); - } - - if (typeof topics === 'string') { - _topics = [EmbarkJS.Utils.fromAscii(topics)]; - } else { - _topics = topics.map((t) => EmbarkJS.Utils.fromAscii(t)); - } - topics = _topics; - - payload = JSON.stringify(data); - - var message; - message = { - from: identity, - topics: topics, - payload: EmbarkJS.Utils.fromAscii(payload), - ttl: ttl, - priority: priority - }; - - return EmbarkJS.Messages.currentMessages.web3.shh.post(message, function() { }); - } -}; - -EmbarkJS.Messages.Whisper.listenTo = function(options) { - var topics, _topics, messageEvents; - if (EmbarkJS.Messages.isNewWeb3()) { - messageEvents = function() { - this.cb = function() {}; - }; - - messageEvents.prototype.then = function(cb) { - this.cb = cb; - }; - - messageEvents.prototype.error = function(err) { - return err; - }; - - messageEvents.prototype.stop = function() { - this.filter.stopWatching(); - }; - - topics = options.topic || options.topics; - _topics = []; - - let promise = new messageEvents(); - - // listenTo - if (typeof topics === 'string') { - topics = [this.web3.utils.toHex(topics).slice(0, 10)]; - } else { - topics = topics.map((t) => this.web3.utils.toHex(t).slice(0, 10)); - } - - let filter = this.web3.shh.subscribe("messages", { - symKeyID: this.symKeyID, - topics: topics - }).on('data', function(result) { - var payload = JSON.parse(EmbarkJS.Utils.toAscii(result.payload)); - var data; - data = { - topic: result.topic, - data: payload, - //from: result.from, - time: result.timestamp - }; - - promise.cb(payload, data, result); - }); - - promise.filter = filter; - - return promise; - } else { - topics = options.topic || options.topics; - _topics = []; - - messageEvents = function() { - this.cb = function() {}; - }; - - messageEvents.prototype.then = function(cb) { - this.cb = cb; - }; - - messageEvents.prototype.error = function(err) { - return err; - }; - - messageEvents.prototype.stop = function() { - this.filter.stopWatching(); - }; - - if (typeof topics === 'string') { - _topics = [topics]; - } else { - _topics = topics.map((t) => EmbarkJS.Utils.fromAscii(t)); - } - topics = _topics; - - var filterOptions = { - topics: topics - }; - - let promise = new messageEvents(); - - let filter = this.web3.shh.filter(filterOptions, function(err, result) { - var payload = JSON.parse(EmbarkJS.Utils.toAscii(result.payload)); - var data; - if (err) { - promise.error(err); - } else { - data = { - topic: topics, - data: payload, - from: result.from, - time: (new Date(result.sent * 1000)) - }; - promise.cb(payload, data, result); - } - }); - - promise.filter = filter; - - return promise; - } -}; - -EmbarkJS.Messages.Orbit = {}; - -EmbarkJS.Messages.Orbit.sendMessage = function(options) { - var topics = options.topic || options.topics; - var data = options.data || options.payload; - - if (topics === undefined) { - throw new Error("missing option: topic"); - } - - if (data === undefined) { - throw new Error("missing option: data"); - } - - if (typeof topics === 'string') { - topics = topics; - } else { - // TODO: better to just send to different channels instead - topics = topics.join(','); - } - - this.orbit.join(topics); - - var payload = JSON.stringify(data); - - this.orbit.send(topics, data); -}; - -EmbarkJS.Messages.Orbit.listenTo = function(options) { - var self = this; - var topics = options.topic || options.topics; - - if (typeof topics === 'string') { - topics = topics; - } else { - topics = topics.join(','); - } - - this.orbit.join(topics); - - var messageEvents = function() { - this.cb = function() {}; - }; - - messageEvents.prototype.then = function(cb) { - this.cb = cb; - }; - - messageEvents.prototype.error = function(err) { - return err; - }; - - var promise = new messageEvents(); - - this.orbit.events.on('message', (channel, message) => { - // TODO: looks like sometimes it's receving messages from all topics - if (topics !== channel) return; - self.orbit.getPost(message.payload.value, true).then((post) => { - var data = { - topic: channel, - data: post.content, - from: post.meta.from.name, - time: (new Date(post.meta.ts)) - }; - promise.cb(post.content, data, post); - }); - }); - - return promise; -}; - EmbarkJS.Utils = { fromAscii: function(str) { var _web3 = new Web3(); diff --git a/js/embarkjs/ipfs.js b/js/embarkjs/ipfs.js new file mode 100644 index 000000000..e55850cfb --- /dev/null +++ b/js/embarkjs/ipfs.js @@ -0,0 +1,97 @@ +let __embarkIPFS = {}; + +__embarkIPFS.setProvider = function(options) { + var self = this; + var promise = new Promise(function(resolve, reject) { + self.currentStorage = EmbarkJS.Storage.IPFS; + + try { + if (options === undefined) { + self.ipfsConnection = IpfsApi('localhost', '5001'); + self._getUrl = "http://localhost:8080/ipfs/"; + } else { + self.ipfsConnection = IpfsApi(options.server, options.port); + self._getUrl = options.getUrl || "http://localhost:8080/ipfs/"; + } + resolve(self); + } catch (err) { + console.log(err); + self.ipfsConnection = null; + reject(new Error('Failed to connect to IPFS')); + } + }); + return promise; +}; + +__embarkIPFS.saveText = function(text) { + const self = this; + var promise = new Promise(function(resolve, reject) { + if (!this.ipfsConnection) { + var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); + reject(connectionError); + } + self.ipfsConnection.add((new self.ipfsConnection.Buffer(text)), function(err, result) { + if (err) { + reject(err); + } else { + resolve(result[0].path); + } + }); + }); + + return promise; +}; + +__embarkIPFS.get = function(hash) { + // TODO: detect type, then convert if needed + //var ipfsHash = web3.toAscii(hash); + var promise = new Promise(function(resolve, reject) { + if (!self.ipfsConnection) { + var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); + reject(connectionError); + } + self.ipfsConnection.object.get(hash).then(function(node) { + resolve(node.data.toString()); + }).catch(function(err) { + reject(err); + }); + }); + + return promise; +}; + +__embarkIPFS.uploadFile = function(inputSelector) { + var file = inputSelector[0].files[0]; + + if (file === undefined) { + throw new Error('no file found'); + } + + var promise = new Promise(function(resolve, reject) { + if (!self.ipfsConnection) { + var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); + reject(connectionError); + } + var reader = new FileReader(); + reader.onloadend = function() { + var fileContent = reader.result; + var buffer = self.ipfsConnection.Buffer.from(fileContent); + self.ipfsConnection.add(buffer, function(err, result) { + if (err) { + reject(err); + } else { + resolve(result[0].path); + } + }); + }; + reader.readAsArrayBuffer(file); + }); + + return promise; +}; + +__embarkIPFS.getUrl = function(hash) { + return (self._getUrl || "http://localhost:8080/ipfs/") + hash; +}; + +EmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS); diff --git a/js/embarkjs/orbit.js b/js/embarkjs/orbit.js new file mode 100644 index 000000000..15e3af062 --- /dev/null +++ b/js/embarkjs/orbit.js @@ -0,0 +1,71 @@ +EmbarkJS.Messages.Orbit = {}; + +EmbarkJS.Messages.Orbit.sendMessage = function(options) { + var topics = options.topic || options.topics; + var data = options.data || options.payload; + + if (topics === undefined) { + throw new Error("missing option: topic"); + } + + if (data === undefined) { + throw new Error("missing option: data"); + } + + if (typeof topics === 'string') { + topics = topics; + } else { + // TODO: better to just send to different channels instead + topics = topics.join(','); + } + + this.orbit.join(topics); + + var payload = JSON.stringify(data); + + this.orbit.send(topics, data); +}; + +EmbarkJS.Messages.Orbit.listenTo = function(options) { + var self = this; + var topics = options.topic || options.topics; + + if (typeof topics === 'string') { + topics = topics; + } else { + topics = topics.join(','); + } + + this.orbit.join(topics); + + var messageEvents = function() { + this.cb = function() {}; + }; + + messageEvents.prototype.then = function(cb) { + this.cb = cb; + }; + + messageEvents.prototype.error = function(err) { + return err; + }; + + var promise = new messageEvents(); + + this.orbit.events.on('message', (channel, message) => { + // TODO: looks like sometimes it's receving messages from all topics + if (topics !== channel) return; + self.orbit.getPost(message.payload.value, true).then((post) => { + var data = { + topic: channel, + data: post.content, + from: post.meta.from.name, + time: (new Date(post.meta.ts)) + }; + promise.cb(post.content, data, post); + }); + }); + + return promise; +}; + diff --git a/js/embarkjs/whisper.js b/js/embarkjs/whisper.js new file mode 100644 index 000000000..51ff36fc5 --- /dev/null +++ b/js/embarkjs/whisper.js @@ -0,0 +1,177 @@ +EmbarkJS.Messages.Whisper = {}; + +EmbarkJS.Messages.Whisper.sendMessage = function(options) { + var topics, data, ttl, priority, payload; + if (EmbarkJS.Messages.isNewWeb3()) { + topics = options.topic || options.topics; + data = options.data || options.payload; + ttl = options.ttl || 100; + priority = options.priority || 1000; + var powTime = options.powTime || 3; + var powTarget = options.powTarget || 0.5; + + if (topics === undefined) { + throw new Error("missing option: topic"); + } + + if (data === undefined) { + throw new Error("missing option: data"); + } + + topics = this.web3.utils.toHex(topics).slice(0, 10); + + payload = JSON.stringify(data); + + let message = { + symKeyID: this.symKeyID, // encrypts using the sym key ID + sig: this.sig, // signs the message using the keyPair ID + ttl: ttl, + topic: topics, + payload: EmbarkJS.Utils.fromAscii(payload), + powTime: powTime, + powTarget: powTarget + }; + + this.web3.shh.post(message, function() { }); + } else { + topics = options.topic || options.topics; + data = options.data || options.payload; + ttl = options.ttl || 100; + priority = options.priority || 1000; + var identity = options.identity || this.identity || web3.shh.newIdentity(); + var _topics; + + if (topics === undefined) { + throw new Error("missing option: topic"); + } + + if (data === undefined) { + throw new Error("missing option: data"); + } + + if (typeof topics === 'string') { + _topics = [EmbarkJS.Utils.fromAscii(topics)]; + } else { + _topics = topics.map((t) => EmbarkJS.Utils.fromAscii(t)); + } + topics = _topics; + + payload = JSON.stringify(data); + + var message; + message = { + from: identity, + topics: topics, + payload: EmbarkJS.Utils.fromAscii(payload), + ttl: ttl, + priority: priority + }; + + return EmbarkJS.Messages.currentMessages.web3.shh.post(message, function() { }); + } +}; + +EmbarkJS.Messages.Whisper.listenTo = function(options) { + var topics, _topics, messageEvents; + if (EmbarkJS.Messages.isNewWeb3()) { + messageEvents = function() { + this.cb = function() {}; + }; + + messageEvents.prototype.then = function(cb) { + this.cb = cb; + }; + + messageEvents.prototype.error = function(err) { + return err; + }; + + messageEvents.prototype.stop = function() { + this.filter.stopWatching(); + }; + + topics = options.topic || options.topics; + _topics = []; + + let promise = new messageEvents(); + + // listenTo + if (typeof topics === 'string') { + topics = [this.web3.utils.toHex(topics).slice(0, 10)]; + } else { + topics = topics.map((t) => this.web3.utils.toHex(t).slice(0, 10)); + } + + let filter = this.web3.shh.subscribe("messages", { + symKeyID: this.symKeyID, + topics: topics + }).on('data', function(result) { + var payload = JSON.parse(EmbarkJS.Utils.toAscii(result.payload)); + var data; + data = { + topic: result.topic, + data: payload, + //from: result.from, + time: result.timestamp + }; + + promise.cb(payload, data, result); + }); + + promise.filter = filter; + + return promise; + } else { + topics = options.topic || options.topics; + _topics = []; + + messageEvents = function() { + this.cb = function() {}; + }; + + messageEvents.prototype.then = function(cb) { + this.cb = cb; + }; + + messageEvents.prototype.error = function(err) { + return err; + }; + + messageEvents.prototype.stop = function() { + this.filter.stopWatching(); + }; + + if (typeof topics === 'string') { + _topics = [topics]; + } else { + _topics = topics.map((t) => EmbarkJS.Utils.fromAscii(t)); + } + topics = _topics; + + var filterOptions = { + topics: topics + }; + + let promise = new messageEvents(); + + let filter = this.web3.shh.filter(filterOptions, function(err, result) { + var payload = JSON.parse(EmbarkJS.Utils.toAscii(result.payload)); + var data; + if (err) { + promise.error(err); + } else { + data = { + topic: topics, + data: payload, + from: result.from, + time: (new Date(result.sent * 1000)) + }; + promise.cb(payload, data, result); + } + }); + + promise.filter = filter; + + return promise; + } +}; diff --git a/lib/contracts/code_generator.js b/lib/contracts/code_generator.js index 6204086ad..762fb2f0c 100644 --- a/lib/contracts/code_generator.js +++ b/lib/contracts/code_generator.js @@ -291,6 +291,10 @@ class CodeGenerator { code += "\n" + embarkjsCode + "\n"; + code += "\n" + fs.readFileSync(fs.embarkPath('js/embarkjs/ipfs.js')).toString(); + code += "\n" + fs.readFileSync(fs.embarkPath('js/embarkjs/whisper.js')).toString(); + code += "\n" + fs.readFileSync(fs.embarkPath('js/embarkjs/orbit.js')).toString(); + code += this.generateCommunicationInitialization(true); code += this.generateStorageInitialization(true);