diff --git a/demo/app/js/index.js b/demo/app/js/index.js index fe7ac8cf..2db14830 100644 --- a/demo/app/js/index.js +++ b/demo/app/js/index.js @@ -32,18 +32,28 @@ $(document).ready(function() { //EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'}); $("#storage .error").hide(); - EmbarkJS.Storage.ipfsConnection.ping() + EmbarkJS.Storage.setProvider('ipfs') .then(function(){ - $("#status-storage").addClass('status-online'); - $("#storage-controls").show(); + console.log('Provider set to IPFS'); + EmbarkJS.Storage.ipfsConnection.ping() + .then(function(){ + $("#status-storage").addClass('status-online'); + $("#storage-controls").show(); + }) + .catch(function(err) { + if(err){ + console.log("IPFS Connection Error => " + err.message); + $("#storage .error").show(); + $("#status-storage").addClass('status-offline'); + $("#storage-controls").hide(); + } + }); }) - .catch(function(err) { - if(err){ - console.log("IPFS Connection Error => " + err.message); - $("#storage .error").show(); - $("#status-storage").addClass('status-offline'); - $("#storage-controls").hide(); - } + .catch(function(err){ + console.log('Failed to set IPFS as Provider:', err.message); + $("#storage .error").show(); + $("#status-storage").addClass('status-offline'); + $("#storage-controls").hide(); }); $("#storage button.setIpfsText").click(function() { diff --git a/demo/package.json b/demo/package.json index 2d381594..d955d134 100644 --- a/demo/package.json +++ b/demo/package.json @@ -10,7 +10,7 @@ "license": "ISC", "homepage": "", "devDependencies": { - "embark": "^2.4.0", + "embark": "^2.4.1", "mocha": "^2.2.5" } } diff --git a/js/build/embark.bundle.js b/js/build/embark.bundle.js index a4ba41df..7a237acb 100644 --- a/js/build/embark.bundle.js +++ b/js/build/embark.bundle.js @@ -74,450 +74,501 @@ var EmbarkJS = /*jshint esversion: 6 */ //var Ipfs = require('./ipfs.js'); -var EmbarkJS = { -}; +//========================================================= +// Embark Smart Contracts +//========================================================= + +var EmbarkJS = {}; EmbarkJS.Contract = function(options) { - var self = this; - var i, abiElement; + var self = this; + var i, abiElement; - this.abi = options.abi; - this.address = options.address; - this.code = '0x' + options.code; - this.web3 = options.web3 || web3; + this.abi = options.abi; + this.address = options.address; + this.code = '0x' + options.code; + this.web3 = options.web3 || web3; - var ContractClass = this.web3.eth.contract(this.abi); + var ContractClass = this.web3.eth.contract(this.abi); - this.eventList = []; + this.eventList = []; - if (this.abi) { - for (i = 0; i < this.abi.length; i++) { - abiElement = this.abi[i]; - if (abiElement.type === 'event') { - this.eventList.push(abiElement.name); - } - } - } - - var messageEvents = function() { - this.cb = function() {}; - }; - - messageEvents.prototype.then = function(cb) { - this.cb = cb; - }; - - messageEvents.prototype.error = function(err) { - return err; - }; - - this._originalContractObject = ContractClass.at(this.address); - this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function (p) { - // TODO: check for forbidden properties - if (self.eventList.indexOf(p) >= 0) { - - self[p] = function() { - var promise = new messageEvents(); - var args = Array.prototype.slice.call(arguments); - args.push(function(err, result) { - if (err) { - promise.error(err); - } else { - promise.cb(result); - } - }); - - self._originalContractObject[p].apply(self._originalContractObject[p], args); - return promise; - }; - return true; - } else if (typeof self._originalContractObject[p] === 'function') { - self[p] = function(_args) { - var args = Array.prototype.slice.call(arguments); - var fn = self._originalContractObject[p]; - var props = self.abi.find((x) => x.name == p); - - var promise = new Promise(function(resolve, reject) { - args.push(function(err, transaction) { - promise.tx = transaction; - if (err) { - return reject(err); + if (this.abi) { + for (i = 0; i < this.abi.length; i++) { + abiElement = this.abi[i]; + if (abiElement.type === 'event') { + this.eventList.push(abiElement.name); } + } + } - var getConfirmation = function() { - self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) { - if (err) { - return reject(err); - } + var messageEvents = function() { + this.cb = function() {}; + }; - if (receipt !== null) { - return resolve(receipt); - } + messageEvents.prototype.then = function(cb) { + this.cb = cb; + }; - setTimeout(getConfirmation, 1000); - }); + messageEvents.prototype.error = function(err) { + return err; + }; + + this._originalContractObject = ContractClass.at(this.address); + this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function(p) { + // TODO: check for forbidden properties + if (self.eventList.indexOf(p) >= 0) { + + self[p] = function() { + var promise = new messageEvents(); + var args = Array.prototype.slice.call(arguments); + args.push(function(err, result) { + if (err) { + promise.error(err); + } else { + promise.cb(result); + } + }); + + self._originalContractObject[p].apply(self._originalContractObject[p], args); + return promise; }; + return true; + } else if (typeof self._originalContractObject[p] === 'function') { + self[p] = function(_args) { + var args = Array.prototype.slice.call(arguments); + var fn = self._originalContractObject[p]; + var props = self.abi.find((x) => x.name == p); - if (typeof(transaction) !== "string" || props.constant) { - resolve(transaction); - } else { - getConfirmation(); - } - }); + var promise = new Promise(function(resolve, reject) { + args.push(function(err, transaction) { + promise.tx = transaction; + if (err) { + return reject(err); + } - fn.apply(fn, args); - }); + var getConfirmation = function() { + self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) { + if (err) { + return reject(err); + } - return promise; - }; - return true; - } - return false; - }); + if (receipt !== null) { + return resolve(receipt); + } + + setTimeout(getConfirmation, 1000); + }); + }; + + if (typeof(transaction) !== "string" || props.constant) { + resolve(transaction); + } else { + getConfirmation(); + } + }); + + fn.apply(fn, args); + }); + + return promise; + }; + return true; + } + return false; + }); }; EmbarkJS.Contract.prototype.deploy = function(args, _options) { - var self = this; - var contractParams; - var options = _options || {}; + var self = this; + var contractParams; + var options = _options || {}; - contractParams = args || []; + contractParams = args || []; - contractParams.push({ - from: this.web3.eth.accounts[0], - data: this.code, - gas: options.gas || 800000 - }); - - var contractObject = this.web3.eth.contract(this.abi); - - var promise = new Promise(function(resolve, reject) { - contractParams.push(function(err, transaction) { - if (err) { - reject(err); - } else if (transaction.address !== undefined) { - resolve(new EmbarkJS.Contract({abi: self.abi, code: self.code, address: transaction.address})); - } + contractParams.push({ + from: this.web3.eth.accounts[0], + data: this.code, + gas: options.gas || 800000 }); - // returns promise - // deploys contract - // wraps it around EmbarkJS.Contract - contractObject["new"].apply(contractObject, contractParams); - }); + var contractObject = this.web3.eth.contract(this.abi); + + var promise = new Promise(function(resolve, reject) { + contractParams.push(function(err, transaction) { + if (err) { + reject(err); + } else if (transaction.address !== undefined) { + resolve(new EmbarkJS.Contract({ + abi: self.abi, + code: self.code, + address: transaction.address + })); + } + }); + + // returns promise + // deploys contract + // wraps it around EmbarkJS.Contract + contractObject["new"].apply(contractObject, contractParams); + }); - return promise; + return promise; }; -EmbarkJS.Storage = { - IPFS : 'ipfs' +//========================================================= +// Embark Storage +//========================================================= + +EmbarkJS.Storage = {}; + +EmbarkJS.Storage.Providers = { + IPFS: 'ipfs', + SWARM: 'swarm' }; -EmbarkJS.Storage.setProvider = function(provider, options) { - if (provider.toLowerCase() === EmbarkJS.Storage.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 - this.currentStorage = EmbarkJS.Storage.IPFS; - if (options === undefined) { - this.ipfsConnection = IpfsApi('localhost', '5001'); - } else { - this.ipfsConnection = IpfsApi(options.server, options.port); - } - } else { - throw Error('Unknown storage provider'); - } -}; +EmbarkJS.Storage.IPFS = {}; EmbarkJS.Storage.saveText = function(text) { - var self = this; - if (!this.ipfsConnection) { - this.setProvider('ipfs'); - } - var promise = new Promise(function(resolve, reject) { - self.ipfsConnection.add((new self.ipfsConnection.Buffer(text)), function(err, result) { - if (err) { - reject(err); - } else { - resolve(result[0].path); - } - }); - }); - - return promise; -}; - -EmbarkJS.Storage.uploadFile = function(inputSelector) { - var self = this; - var file = inputSelector[0].files[0]; - - if (file === undefined) { - throw new Error('no file found'); - } - - if (!this.ipfsConnection) { - this.setProvider('ipfs'); - } - - var promise = new Promise(function(resolve, reject) { - 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; + return this.currentStorage.saveText(text); }; EmbarkJS.Storage.get = function(hash) { - var self = this; - // TODO: detect type, then convert if needed - //var ipfsHash = web3.toAscii(hash); - if (!this.ipfsConnection) { - this.setProvider('ipfs'); - } - - var promise = new Promise(function(resolve, reject) { - self.ipfsConnection.object.get([hash]).then(function(node) { - resolve(node.data); - }).catch(function (err){ - reject(err); - }); - }); - - return promise; + return this.currentStorage.get(hash); }; +EmbarkJS.Storage.uploadFile = function(inputSelector) { + return this.currentStorage.uploadFile(inputSelector); +} + EmbarkJS.Storage.getUrl = function(hash) { - //var ipfsHash = web3.toAscii(hash); + return this.currentStorage.getUrl(hash); +} - return 'http://localhost:8080/ipfs/' + hash; +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; + + try { + if (options === undefined) { + self.ipfsConnection = IpfsApi('localhost', '5001'); + } else { + self.ipfsConnection = IpfsApi(options.server, options.port); + } + resolve(self); + } catch (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; }; -EmbarkJS.Messages = { +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); + }).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) { + //var ipfsHash = web3.toAscii(hash); + + return 'http://localhost:8080/ipfs/' + hash; +}; + +//========================================================= +// Embark Messaging +//========================================================= + +EmbarkJS.Messages = {}; + EmbarkJS.Messages.setProvider = function(provider, options) { - var self = this; - var ipfs; - if (provider === 'whisper') { - this.currentMessages = EmbarkJS.Messages.Whisper; - if (typeof variable === 'undefined') { - if (options === undefined) { - web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); - } else { - web3 = new Web3(new Web3.providers.HttpProvider("http://" + options.server + ':' + options.port)); - } - } - web3.version.getWhisper(function(err, res) { - if (err) { - console.log("whisper not available"); - } else { - self.currentMessages.identity = web3.shh.newIdentity(); - } - }); - } else if (provider === 'orbit') { - this.currentMessages = EmbarkJS.Messages.Orbit; - if (options === undefined) { - ipfs = HaadIpfsApi('localhost', '5001'); + var self = this; + var ipfs; + if (provider === 'whisper') { + this.currentMessages = EmbarkJS.Messages.Whisper; + if (typeof variable === 'undefined') { + if (options === undefined) { + web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); + } else { + web3 = new Web3(new Web3.providers.HttpProvider("http://" + options.server + ':' + options.port)); + } + } + web3.version.getWhisper(function(err, res) { + if (err) { + console.log("whisper not available"); + } else { + self.currentMessages.identity = web3.shh.newIdentity(); + } + }); + } else if (provider === 'orbit') { + this.currentMessages = EmbarkJS.Messages.Orbit; + if (options === undefined) { + ipfs = HaadIpfsApi('localhost', '5001'); + } else { + ipfs = HaadIpfsApi(options.server, options.port); + } + this.currentMessages.orbit = new Orbit(ipfs); + this.currentMessages.orbit.connect(web3.eth.accounts[0]); } else { - ipfs = HaadIpfsApi(options.server, options.port); + throw Error('Unknown message provider'); } - this.currentMessages.orbit = new Orbit(ipfs); - this.currentMessages.orbit.connect(web3.eth.accounts[0]); - } else { - throw Error('unknown provider'); - } }; EmbarkJS.Messages.sendMessage = function(options) { - return this.currentMessages.sendMessage(options); + return this.currentMessages.sendMessage(options); }; EmbarkJS.Messages.listenTo = function(options) { - return this.currentMessages.listenTo(options); + return this.currentMessages.listenTo(options); }; -EmbarkJS.Messages.Whisper = { -}; +EmbarkJS.Messages.Whisper = {}; EmbarkJS.Messages.Whisper.sendMessage = function(options) { - var topics = options.topic || options.topics; - var data = options.data || options.payload; - var identity = options.identity || this.identity || web3.shh.newIdentity(); - var ttl = options.ttl || 100; - var priority = options.priority || 1000; - var _topics; + var topics = options.topic || options.topics; + var data = options.data || options.payload; + var identity = options.identity || this.identity || web3.shh.newIdentity(); + var ttl = options.ttl || 100; + var priority = options.priority || 1000; + var _topics; - if (topics === undefined) { - throw new Error("missing option: topic"); - } - - if (data === undefined) { - throw new Error("missing option: data"); - } - - // do fromAscii to each topics unless it's already a string - if (typeof topics === 'string') { - _topics = [web3.fromAscii(topics)]; - } else { - // TODO: replace with es6 + babel; - for (var i = 0; i < topics.length; i++) { - _topics.push(web3.fromAscii(topics[i])); + if (topics === undefined) { + throw new Error("missing option: topic"); } - } - topics = _topics; - var payload = JSON.stringify(data); + if (data === undefined) { + throw new Error("missing option: data"); + } - var message = { - from: identity, - topics: topics, - payload: web3.fromAscii(payload), - ttl: ttl, - priority: priority - }; + // do fromAscii to each topics unless it's already a string + if (typeof topics === 'string') { + _topics = [web3.fromAscii(topics)]; + } else { + // TODO: replace with es6 + babel; + for (var i = 0; i < topics.length; i++) { + _topics.push(web3.fromAscii(topics[i])); + } + } + topics = _topics; - return web3.shh.post(message, function() {}); + var payload = JSON.stringify(data); + + var message = { + from: identity, + topics: topics, + payload: web3.fromAscii(payload), + ttl: ttl, + priority: priority + }; + + return web3.shh.post(message, function() {}); }; EmbarkJS.Messages.Whisper.listenTo = function(options) { - var topics = options.topic || options.topics; - var _topics = []; + var topics = options.topic || options.topics; + var _topics = []; - if (typeof topics === 'string') { - _topics = [topics]; - } else { - // TODO: replace with es6 + babel; - for (var i = 0; i < topics.length; i++) { - _topics.push(topics[i]); - } - } - topics = _topics; - - var filterOptions = { - topics: topics - }; - - var 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(); - }; - - var promise = new messageEvents(); - - var filter = web3.shh.filter(filterOptions, function(err, result) { - var payload = JSON.parse(web3.toAscii(result.payload)); - var data; - if (err) { - promise.error(err); + if (typeof topics === 'string') { + _topics = [topics]; } else { - data = { - topic: topics, - data: payload, - from: result.from, - time: (new Date(result.sent * 1000)) - }; - promise.cb(payload, data, result); + // TODO: replace with es6 + babel; + for (var i = 0; i < topics.length; i++) { + _topics.push(topics[i]); + } } - }); + topics = _topics; - promise.filter = filter; + var filterOptions = { + topics: topics + }; - return promise; + var 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(); + }; + + var promise = new messageEvents(); + + var filter = web3.shh.filter(filterOptions, function(err, result) { + var payload = JSON.parse(web3.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 = {}; EmbarkJS.Messages.Orbit.sendMessage = function(options) { - var topics = options.topic || options.topics; - var data = options.data || options.payload; + var topics = options.topic || options.topics; + var data = options.data || options.payload; - if (topics === undefined) { - throw new Error("missing option: topic"); - } + if (topics === undefined) { + throw new Error("missing option: topic"); + } - if (data === undefined) { - throw new Error("missing option: data"); - } + 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(','); - } + if (typeof topics === 'string') { + topics = topics; + } else { + // TODO: better to just send to different channels instead + topics = topics.join(','); + } - this.orbit.join(topics); + this.orbit.join(topics); - var payload = JSON.stringify(data); + var payload = JSON.stringify(data); - this.orbit.send(topics, data); + this.orbit.send(topics, data); }; EmbarkJS.Messages.Orbit.listenTo = function(options) { - var self = this; - var topics = options.topic || options.topics; + var self = this; + var topics = options.topic || options.topics; - if (typeof topics === 'string') { - topics = topics; - } else { - topics = topics.join(','); - } + if (typeof topics === 'string') { + topics = topics; + } else { + topics = topics.join(','); + } - this.orbit.join(topics); + this.orbit.join(topics); - var messageEvents = function() { - this.cb = function() {}; - }; + var messageEvents = function() { + this.cb = function() {}; + }; - messageEvents.prototype.then = function(cb) { - this.cb = cb; - }; + messageEvents.prototype.then = function(cb) { + this.cb = cb; + }; - messageEvents.prototype.error = function(err) { - return err; - }; + messageEvents.prototype.error = function(err) { + return err; + }; - var promise = new messageEvents(); + 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); + 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; + return promise; }; module.exports = EmbarkJS; diff --git a/js/embark.js b/js/embark.js index 646dc55f..8f31e9ac 100644 --- a/js/embark.js +++ b/js/embark.js @@ -1,450 +1,501 @@ /*jshint esversion: 6 */ //var Ipfs = require('./ipfs.js'); -var EmbarkJS = { -}; +//========================================================= +// Embark Smart Contracts +//========================================================= + +var EmbarkJS = {}; EmbarkJS.Contract = function(options) { - var self = this; - var i, abiElement; + var self = this; + var i, abiElement; - this.abi = options.abi; - this.address = options.address; - this.code = '0x' + options.code; - this.web3 = options.web3 || web3; + this.abi = options.abi; + this.address = options.address; + this.code = '0x' + options.code; + this.web3 = options.web3 || web3; - var ContractClass = this.web3.eth.contract(this.abi); + var ContractClass = this.web3.eth.contract(this.abi); - this.eventList = []; + this.eventList = []; - if (this.abi) { - for (i = 0; i < this.abi.length; i++) { - abiElement = this.abi[i]; - if (abiElement.type === 'event') { - this.eventList.push(abiElement.name); - } - } - } - - var messageEvents = function() { - this.cb = function() {}; - }; - - messageEvents.prototype.then = function(cb) { - this.cb = cb; - }; - - messageEvents.prototype.error = function(err) { - return err; - }; - - this._originalContractObject = ContractClass.at(this.address); - this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function (p) { - // TODO: check for forbidden properties - if (self.eventList.indexOf(p) >= 0) { - - self[p] = function() { - var promise = new messageEvents(); - var args = Array.prototype.slice.call(arguments); - args.push(function(err, result) { - if (err) { - promise.error(err); - } else { - promise.cb(result); - } - }); - - self._originalContractObject[p].apply(self._originalContractObject[p], args); - return promise; - }; - return true; - } else if (typeof self._originalContractObject[p] === 'function') { - self[p] = function(_args) { - var args = Array.prototype.slice.call(arguments); - var fn = self._originalContractObject[p]; - var props = self.abi.find((x) => x.name == p); - - var promise = new Promise(function(resolve, reject) { - args.push(function(err, transaction) { - promise.tx = transaction; - if (err) { - return reject(err); + if (this.abi) { + for (i = 0; i < this.abi.length; i++) { + abiElement = this.abi[i]; + if (abiElement.type === 'event') { + this.eventList.push(abiElement.name); } + } + } - var getConfirmation = function() { - self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) { - if (err) { - return reject(err); - } + var messageEvents = function() { + this.cb = function() {}; + }; - if (receipt !== null) { - return resolve(receipt); - } + messageEvents.prototype.then = function(cb) { + this.cb = cb; + }; - setTimeout(getConfirmation, 1000); - }); + messageEvents.prototype.error = function(err) { + return err; + }; + + this._originalContractObject = ContractClass.at(this.address); + this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function(p) { + // TODO: check for forbidden properties + if (self.eventList.indexOf(p) >= 0) { + + self[p] = function() { + var promise = new messageEvents(); + var args = Array.prototype.slice.call(arguments); + args.push(function(err, result) { + if (err) { + promise.error(err); + } else { + promise.cb(result); + } + }); + + self._originalContractObject[p].apply(self._originalContractObject[p], args); + return promise; }; + return true; + } else if (typeof self._originalContractObject[p] === 'function') { + self[p] = function(_args) { + var args = Array.prototype.slice.call(arguments); + var fn = self._originalContractObject[p]; + var props = self.abi.find((x) => x.name == p); - if (typeof(transaction) !== "string" || props.constant) { - resolve(transaction); - } else { - getConfirmation(); - } - }); + var promise = new Promise(function(resolve, reject) { + args.push(function(err, transaction) { + promise.tx = transaction; + if (err) { + return reject(err); + } - fn.apply(fn, args); - }); + var getConfirmation = function() { + self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) { + if (err) { + return reject(err); + } - return promise; - }; - return true; - } - return false; - }); + if (receipt !== null) { + return resolve(receipt); + } + + setTimeout(getConfirmation, 1000); + }); + }; + + if (typeof(transaction) !== "string" || props.constant) { + resolve(transaction); + } else { + getConfirmation(); + } + }); + + fn.apply(fn, args); + }); + + return promise; + }; + return true; + } + return false; + }); }; EmbarkJS.Contract.prototype.deploy = function(args, _options) { - var self = this; - var contractParams; - var options = _options || {}; + var self = this; + var contractParams; + var options = _options || {}; - contractParams = args || []; + contractParams = args || []; - contractParams.push({ - from: this.web3.eth.accounts[0], - data: this.code, - gas: options.gas || 800000 - }); - - var contractObject = this.web3.eth.contract(this.abi); - - var promise = new Promise(function(resolve, reject) { - contractParams.push(function(err, transaction) { - if (err) { - reject(err); - } else if (transaction.address !== undefined) { - resolve(new EmbarkJS.Contract({abi: self.abi, code: self.code, address: transaction.address})); - } + contractParams.push({ + from: this.web3.eth.accounts[0], + data: this.code, + gas: options.gas || 800000 }); - // returns promise - // deploys contract - // wraps it around EmbarkJS.Contract - contractObject["new"].apply(contractObject, contractParams); - }); + var contractObject = this.web3.eth.contract(this.abi); + + var promise = new Promise(function(resolve, reject) { + contractParams.push(function(err, transaction) { + if (err) { + reject(err); + } else if (transaction.address !== undefined) { + resolve(new EmbarkJS.Contract({ + abi: self.abi, + code: self.code, + address: transaction.address + })); + } + }); + + // returns promise + // deploys contract + // wraps it around EmbarkJS.Contract + contractObject["new"].apply(contractObject, contractParams); + }); - return promise; + return promise; }; -EmbarkJS.Storage = { - IPFS : 'ipfs' +//========================================================= +// Embark Storage +//========================================================= + +EmbarkJS.Storage = {}; + +EmbarkJS.Storage.Providers = { + IPFS: 'ipfs', + SWARM: 'swarm' }; -EmbarkJS.Storage.setProvider = function(provider, options) { - if (provider.toLowerCase() === EmbarkJS.Storage.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 - this.currentStorage = EmbarkJS.Storage.IPFS; - if (options === undefined) { - this.ipfsConnection = IpfsApi('localhost', '5001'); - } else { - this.ipfsConnection = IpfsApi(options.server, options.port); - } - } else { - throw Error('Unknown storage provider'); - } -}; +EmbarkJS.Storage.IPFS = {}; EmbarkJS.Storage.saveText = function(text) { - var self = this; - if (!this.ipfsConnection) { - this.setProvider('ipfs'); - } - var promise = new Promise(function(resolve, reject) { - self.ipfsConnection.add((new self.ipfsConnection.Buffer(text)), function(err, result) { - if (err) { - reject(err); - } else { - resolve(result[0].path); - } - }); - }); - - return promise; -}; - -EmbarkJS.Storage.uploadFile = function(inputSelector) { - var self = this; - var file = inputSelector[0].files[0]; - - if (file === undefined) { - throw new Error('no file found'); - } - - if (!this.ipfsConnection) { - this.setProvider('ipfs'); - } - - var promise = new Promise(function(resolve, reject) { - 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; + return this.currentStorage.saveText(text); }; EmbarkJS.Storage.get = function(hash) { - var self = this; - // TODO: detect type, then convert if needed - //var ipfsHash = web3.toAscii(hash); - if (!this.ipfsConnection) { - this.setProvider('ipfs'); - } + return this.currentStorage.get(hash); +}; - var promise = new Promise(function(resolve, reject) { - self.ipfsConnection.object.get([hash]).then(function(node) { - resolve(node.data); - }).catch(function (err){ - reject(err); - }); - }); - - return promise; +EmbarkJS.Storage.uploadFile = function(inputSelector) { + return this.currentStorage.uploadFile(inputSelector); }; EmbarkJS.Storage.getUrl = function(hash) { - //var ipfsHash = web3.toAscii(hash); - - return 'http://localhost:8080/ipfs/' + hash; + return this.currentStorage.getUrl(hash); }; -EmbarkJS.Messages = { +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; + + try { + if (options === undefined) { + self.ipfsConnection = IpfsApi('localhost', '5001'); + } else { + self.ipfsConnection = IpfsApi(options.server, options.port); + } + resolve(self); + } catch (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; }; +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); + }).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) { + //var ipfsHash = web3.toAscii(hash); + + return 'http://localhost:8080/ipfs/' + hash; +}; + +//========================================================= +// Embark Messaging +//========================================================= + +EmbarkJS.Messages = {}; + EmbarkJS.Messages.setProvider = function(provider, options) { - var self = this; - var ipfs; - if (provider === 'whisper') { - this.currentMessages = EmbarkJS.Messages.Whisper; - if (typeof variable === 'undefined') { - if (options === undefined) { - web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); - } else { - web3 = new Web3(new Web3.providers.HttpProvider("http://" + options.server + ':' + options.port)); - } - } - web3.version.getWhisper(function(err, res) { - if (err) { - console.log("whisper not available"); - } else { - self.currentMessages.identity = web3.shh.newIdentity(); - } - }); - } else if (provider === 'orbit') { - this.currentMessages = EmbarkJS.Messages.Orbit; - if (options === undefined) { - ipfs = HaadIpfsApi('localhost', '5001'); + var self = this; + var ipfs; + if (provider === 'whisper') { + this.currentMessages = EmbarkJS.Messages.Whisper; + if (typeof variable === 'undefined') { + if (options === undefined) { + web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); + } else { + web3 = new Web3(new Web3.providers.HttpProvider("http://" + options.server + ':' + options.port)); + } + } + web3.version.getWhisper(function(err, res) { + if (err) { + console.log("whisper not available"); + } else { + self.currentMessages.identity = web3.shh.newIdentity(); + } + }); + } else if (provider === 'orbit') { + this.currentMessages = EmbarkJS.Messages.Orbit; + if (options === undefined) { + ipfs = HaadIpfsApi('localhost', '5001'); + } else { + ipfs = HaadIpfsApi(options.server, options.port); + } + this.currentMessages.orbit = new Orbit(ipfs); + this.currentMessages.orbit.connect(web3.eth.accounts[0]); } else { - ipfs = HaadIpfsApi(options.server, options.port); + throw Error('Unknown message provider'); } - this.currentMessages.orbit = new Orbit(ipfs); - this.currentMessages.orbit.connect(web3.eth.accounts[0]); - } else { - throw Error('unknown provider'); - } }; EmbarkJS.Messages.sendMessage = function(options) { - return this.currentMessages.sendMessage(options); + return this.currentMessages.sendMessage(options); }; EmbarkJS.Messages.listenTo = function(options) { - return this.currentMessages.listenTo(options); + return this.currentMessages.listenTo(options); }; -EmbarkJS.Messages.Whisper = { -}; +EmbarkJS.Messages.Whisper = {}; EmbarkJS.Messages.Whisper.sendMessage = function(options) { - var topics = options.topic || options.topics; - var data = options.data || options.payload; - var identity = options.identity || this.identity || web3.shh.newIdentity(); - var ttl = options.ttl || 100; - var priority = options.priority || 1000; - var _topics; + var topics = options.topic || options.topics; + var data = options.data || options.payload; + var identity = options.identity || this.identity || web3.shh.newIdentity(); + var ttl = options.ttl || 100; + var priority = options.priority || 1000; + var _topics; - if (topics === undefined) { - throw new Error("missing option: topic"); - } - - if (data === undefined) { - throw new Error("missing option: data"); - } - - // do fromAscii to each topics unless it's already a string - if (typeof topics === 'string') { - _topics = [web3.fromAscii(topics)]; - } else { - // TODO: replace with es6 + babel; - for (var i = 0; i < topics.length; i++) { - _topics.push(web3.fromAscii(topics[i])); + if (topics === undefined) { + throw new Error("missing option: topic"); } - } - topics = _topics; - var payload = JSON.stringify(data); + if (data === undefined) { + throw new Error("missing option: data"); + } - var message = { - from: identity, - topics: topics, - payload: web3.fromAscii(payload), - ttl: ttl, - priority: priority - }; + // do fromAscii to each topics unless it's already a string + if (typeof topics === 'string') { + _topics = [web3.fromAscii(topics)]; + } else { + // TODO: replace with es6 + babel; + for (var i = 0; i < topics.length; i++) { + _topics.push(web3.fromAscii(topics[i])); + } + } + topics = _topics; - return web3.shh.post(message, function() {}); + var payload = JSON.stringify(data); + + var message = { + from: identity, + topics: topics, + payload: web3.fromAscii(payload), + ttl: ttl, + priority: priority + }; + + return web3.shh.post(message, function() {}); }; EmbarkJS.Messages.Whisper.listenTo = function(options) { - var topics = options.topic || options.topics; - var _topics = []; + var topics = options.topic || options.topics; + var _topics = []; - if (typeof topics === 'string') { - _topics = [topics]; - } else { - // TODO: replace with es6 + babel; - for (var i = 0; i < topics.length; i++) { - _topics.push(topics[i]); - } - } - topics = _topics; - - var filterOptions = { - topics: topics - }; - - var 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(); - }; - - var promise = new messageEvents(); - - var filter = web3.shh.filter(filterOptions, function(err, result) { - var payload = JSON.parse(web3.toAscii(result.payload)); - var data; - if (err) { - promise.error(err); + if (typeof topics === 'string') { + _topics = [topics]; } else { - data = { - topic: topics, - data: payload, - from: result.from, - time: (new Date(result.sent * 1000)) - }; - promise.cb(payload, data, result); + // TODO: replace with es6 + babel; + for (var i = 0; i < topics.length; i++) { + _topics.push(topics[i]); + } } - }); + topics = _topics; - promise.filter = filter; + var filterOptions = { + topics: topics + }; - return promise; + var 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(); + }; + + var promise = new messageEvents(); + + var filter = web3.shh.filter(filterOptions, function(err, result) { + var payload = JSON.parse(web3.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 = {}; EmbarkJS.Messages.Orbit.sendMessage = function(options) { - var topics = options.topic || options.topics; - var data = options.data || options.payload; + var topics = options.topic || options.topics; + var data = options.data || options.payload; - if (topics === undefined) { - throw new Error("missing option: topic"); - } + if (topics === undefined) { + throw new Error("missing option: topic"); + } - if (data === undefined) { - throw new Error("missing option: data"); - } + 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(','); - } + if (typeof topics === 'string') { + topics = topics; + } else { + // TODO: better to just send to different channels instead + topics = topics.join(','); + } - this.orbit.join(topics); + this.orbit.join(topics); - var payload = JSON.stringify(data); + var payload = JSON.stringify(data); - this.orbit.send(topics, data); + this.orbit.send(topics, data); }; EmbarkJS.Messages.Orbit.listenTo = function(options) { - var self = this; - var topics = options.topic || options.topics; + var self = this; + var topics = options.topic || options.topics; - if (typeof topics === 'string') { - topics = topics; - } else { - topics = topics.join(','); - } + if (typeof topics === 'string') { + topics = topics; + } else { + topics = topics.join(','); + } - this.orbit.join(topics); + this.orbit.join(topics); - var messageEvents = function() { - this.cb = function() {}; - }; + var messageEvents = function() { + this.cb = function() {}; + }; - messageEvents.prototype.then = function(cb) { - this.cb = cb; - }; + messageEvents.prototype.then = function(cb) { + this.cb = cb; + }; - messageEvents.prototype.error = function(err) { - return err; - }; + messageEvents.prototype.error = function(err) { + return err; + }; - var promise = new messageEvents(); + 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); + 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; + return promise; }; module.exports = EmbarkJS;