diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..0af79571 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,92 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish to make via issue, +email, or any other method with the owners of this repository before making a change. + +Please note we have a code of conduct, please follow it in all your interactions with the project. + +## Pull Request Process + +1. Ensure any install or build dependencies are removed before the end of the layer when doing a + build. +2. Update the README.md with details of changes to the interface, this includes new environment + variables, exposed ports, useful file locations and container parameters. +3. Increase the version numbers in any examples files and the README.md to the new version that this + Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). +4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you + do not have permission to do that, you may request the second reviewer to merge it for you. + +## Code of Conduct + +### Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +### Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +### Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +### Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [INSERT EMAIL ADDRESS]. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file diff --git a/README.md b/README.md index ac3cab76..361aa454 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![Join the chat at https://gitter.im/iurimatias/embark-framework](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iurimatias/embark-framework?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![npm](https://img.shields.io/npm/dm/embark.svg)]() +[![Gitter](https://img.shields.io/gitter/room/iurimatias/embark-framework.svg)]() [![Build Status](https://travis-ci.org/iurimatias/embark-framework.svg?branch=develop)](https://travis-ci.org/iurimatias/embark-framework) [![Code Climate](https://codeclimate.com/github/iurimatias/embark-framework/badges/gpa.svg)](https://codeclimate.com/github/iurimatias/embark-framework) @@ -41,14 +42,14 @@ Table of Contents * [Dashboard](#dashboard) * [Creating a new DApp](#creating-a-new-dapp) * [Libraries and APIs available](#libraries-and-languages-available) -* [Using and Configuring Contracts](#dapp-structure) +* [Using and Configuring Contracts](#using-contracts) * [EmbarkJS](#embarkjs) * [EmbarkJS - Storage (IPFS)](#embarkjs---storage) * [EmbarkJS - Communication (Whisper/Orbit)](#embarkjs---communication) * [Testing Contracts](#tests) * [Working with different chains](#working-with-different-chains) * [Custom Application Structure](#structuring-application) -* [Deploying to IPFS](#deploying-to-ipfs) +* [Deploying to IPFS](#deploying-to-ipfs-and-swarm) * [Extending Functionality with Plugins](#plugins) * [Donations](#donations) @@ -144,8 +145,11 @@ DApp Structure |___ css/ |___ js/ config/ - |___ blockchain.json #environments configuration - |___ contracts.json #contracts configuration + |___ blockchain.json #rpc and blockchain configuration + |___ contracts.json #ethereum contracts configuration + |___ storage.json #ipfs configuration + |___ communication.json #whisper/orbit configuration + |___ webserver.json #dev webserver configuration test/ |___ #contracts tests ``` @@ -223,7 +227,7 @@ If you are using multiple contracts, you can pass a reference to another contrac "SimpleStorage": { "args": [ 100, - $MyStorage + "$MyStorage" ] }, "MyStorage": { @@ -233,7 +237,7 @@ If you are using multiple contracts, you can pass a reference to another contrac }, "MyMainContract": { "args": [ - $SimpleStorage + "$SimpleStorage" ] } } @@ -322,14 +326,20 @@ events: Client side deployment will be automatically available in Embark for existing contracts: ```Javascript - SimpleStorage.deploy().then(function(anotherSimpleStorage) {}); + SimpleStorage.deploy([args], {options}).then(function(anotherSimpleStorage) {}); ``` or it can be manually definied as ```Javascript var myContract = new EmbarkJS.Contract({abi: abiObject, code: code}); - myContract.deploy().then(function(anotherMyContractObject) {}); + myContract.deploy([args], {options}).then(function(anotherMyContractObject) {}); +``` + +so you can define your gas as + +```Javascript + myContract.deploy([100, "seconde argument"], {gas: 800000}).then(function(anotherMyContractObject) {}); ``` EmbarkJS - Storage @@ -428,12 +438,11 @@ Embark includes a testing lib to fastly run & test your contracts in a EVM. # test/simple_storage_spec.js var assert = require('assert'); -var Embark = require('embark'); -var EmbarkSpec = Embark.initTests(); -var web3 = EmbarkSpec.web3; +var EmbarkSpec = require('embark/lib/core/test.js'); describe("SimpleStorage", function() { before(function(done) { + this.timeout(0); var contractsConfig = { "SimpleStorage": { args: [100] @@ -459,6 +468,7 @@ describe("SimpleStorage", function() { }); }); + ``` Embark uses [Mocha](http://mochajs.org/) by default, but you can use any testing framework you want. diff --git a/bin/embark b/bin/embark index eb0b4d55..c9173a48 100755 --- a/bin/embark +++ b/bin/embark @@ -1,4 +1,4 @@ #!/usr/bin/env node - -var Embark = require('..'); -Embark.process(process.argv); +var Cmd = require('../lib/cmd'); +var cli = new Cmd(); +cli.process(process.argv); diff --git a/boilerplate/app/index.html b/boilerplate/app/index.html index 3585f080..8068e7c7 100644 --- a/boilerplate/app/index.html +++ b/boilerplate/app/index.html @@ -6,6 +6,6 @@

Welcome to Embark!

-

See the Wiki to see what you can do with Embark!

+

See the Embark's documentation to see what you can do with Embark!

diff --git a/boilerplate/test/contract_spec.js b/boilerplate/test/contract_spec.js index e732155d..e0a6a9dc 100644 --- a/boilerplate/test/contract_spec.js +++ b/boilerplate/test/contract_spec.js @@ -1,9 +1,8 @@ var assert = require('assert'); -var Embark = require('embark'); -var EmbarkSpec = Embark.initTests(); -var web3 = EmbarkSpec.web3; +var EmbarkSpec = require('embark/lib/core/test.js'); -//describe("SimpleStorage", function() { + +// describe("SimpleStorage", function() { // before(function(done) { // this.timeout(0); // var contractsConfig = { @@ -30,4 +29,4 @@ var web3 = EmbarkSpec.web3; // }); // }); // -//}); +// }); \ No newline at end of file diff --git a/demo/app/js/index.js b/demo/app/js/index.js index 8b3f1bb3..2db14830 100644 --- a/demo/app/js/index.js +++ b/demo/app/js/index.js @@ -32,35 +32,55 @@ $(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() { var value = $("#storage input.ipfsText").val(); EmbarkJS.Storage.saveText(value).then(function(hash) { $("span.textHash").html(hash); $("input.textHash").val(hash); + addToLog("#storage", "EmbarkJS.Storage.saveText('" + value + "').then(function(hash) { })"); + }) + .catch(function(err) { + if(err){ + console.log("IPFS saveText Error => " + err.message); + } }); - addToLog("#storage", "EmbarkJS.Storage.saveText('" + value + "').then(function(hash) { })"); }); $("#storage button.loadIpfsHash").click(function() { var value = $("#storage input.textHash").val(); EmbarkJS.Storage.get(value).then(function(content) { $("span.ipfsText").html(content); + addToLog("#storage", "EmbarkJS.Storage.get('" + value + "').then(function(content) { })"); + }) + .catch(function(err) { + if(err){ + console.log("IPFS get Error => " + err.message); + } }); - addToLog("#storage", "EmbarkJS.Storage.get('" + value + "').then(function(content) { })"); }); $("#storage button.uploadFile").click(function() { @@ -68,8 +88,13 @@ $(document).ready(function() { EmbarkJS.Storage.uploadFile(input).then(function(hash) { $("span.fileIpfsHash").html(hash); $("input.fileIpfsHash").val(hash); + addToLog("#storage", "EmbarkJS.Storage.uploadFile($('input[type=file]')).then(function(hash) { })"); + }) + .catch(function(err) { + if(err){ + console.log("IPFS uploadFile Error => " + err.message); + } }); - addToLog("#storage", "EmbarkJS.Storage.uploadFile($('input[type=file]')).then(function(hash) { })"); }); $("#storage button.loadIpfsFile").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/docs/embarkjs-storage.rst b/docs/embarkjs-storage.rst index a4641792..c8b9f2a4 100644 --- a/docs/embarkjs-storage.rst +++ b/docs/embarkjs-storage.rst @@ -13,13 +13,25 @@ The current available storage is IPFS. it can be initialized as .. code:: javascript - EmbarkJS.Storage.saveText("hello world").then(function(hash) {}); + EmbarkJS.Storage.saveText("hello world") + .then(function(hash) {}) + .catch(function(err) { + if(err){ + console.log("IPFS saveText Error => " + err.message); + } + }); **Retrieving Data/Text** .. code:: javascript - EmbarkJS.Storage.get(hash).then(function(content) {}); + EmbarkJS.Storage.get(hash) + .then(function(content) {}) + .catch(function(err) { + if(err){ + console.log("IPFS get Error => " + err.message); + } + }); **Uploading a file** @@ -30,7 +42,13 @@ The current available storage is IPFS. it can be initialized as .. code:: javascript var input = $("input[type=file"]); - EmbarkJS.Storage.uploadFile(input).then(function(hash) {}); + EmbarkJS.Storage.uploadFile(input) + .then(function(hash) {}) + .catch(function(err) { + if(err){ + console.log("IPFS uploadFile Error => " + err.message); + } + }); **Generate URL to file** diff --git a/docs/embarkjs.rst b/docs/embarkjs.rst index 50c0e747..dd6a39fc 100644 --- a/docs/embarkjs.rst +++ b/docs/embarkjs.rst @@ -20,11 +20,17 @@ existing contracts: .. code:: javascript - SimpleStorage.deploy().then(function(anotherSimpleStorage) {}); + SimpleStorage.deploy([args], {options}).then(function(anotherSimpleStorage) {}); or it can be manually definied as .. code:: javascript var myContract = new EmbarkJS.Contract({abi: abiObject, code: code}); - myContract.deploy().then(function(anotherMyContractObject) {}); + myContract.deploy([args], {options}).then(function(anotherMyContractObject) {}); + +so you can define your gas as + +.. code:: javascript + + myContract.deploy([100, "seconde argument"], {gas: 800000}).then(function(anotherMyContractObject) {}); diff --git a/docs/using-contracts.rst b/docs/using-contracts.rst index 7c68a287..d3cbe86a 100644 --- a/docs/using-contracts.rst +++ b/docs/using-contracts.rst @@ -64,7 +64,7 @@ with the correct address for the contract. "SimpleStorage": { "args": [ 100, - $MyStorage + "$MyStorage" ] }, "MyStorage": { @@ -74,7 +74,7 @@ with the correct address for the contract. }, "MyMainContract": { "args": [ - $SimpleStorage + "$SimpleStorage" ] } } diff --git a/js/build/embark.bundle.js b/js/build/embark.bundle.js index eed9d3d4..7a237acb 100644 --- a/js/build/embark.bundle.js +++ b/js/build/embark.bundle.js @@ -2,496 +2,577 @@ var EmbarkJS = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; - +/******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { - +/******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; - +/******/ /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} /******/ }; - +/******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - +/******/ /******/ // Flag the module as loaded -/******/ module.loaded = true; - +/******/ module.l = true; +/******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } - - +/******/ +/******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; - +/******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; - +/******/ +/******/ // identity function for calling harmony imports with the correct context +/******/ __webpack_require__.i = function(value) { return value; }; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; - +/******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(0); +/******/ return __webpack_require__(__webpack_require__.s = 0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ -/***/ function(module, exports) { - - /*jshint esversion: 6 */ - //var Ipfs = require('./ipfs.js'); - - var EmbarkJS = { - }; - - EmbarkJS.Contract = function(options) { - var self = this; - var i, abiElement; - - 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); - - 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); - } - - var getConfirmation = function() { - self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) { - if (err) { - return reject(err); - } - - 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 || {}; - - 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})); - } - }); - - // returns promise - // deploys contract - // wraps it around EmbarkJS.Contract - contractObject["new"].apply(contractObject, contractParams); - }); - - - return promise; - }; - - EmbarkJS.IPFS = 'ipfs'; - - EmbarkJS.Storage = { - }; - - EmbarkJS.Storage.setProvider = function(provider, options) { - if (provider === 'ipfs') { - 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 provider'); - } - }; - - 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; - }; - - 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); - }); - }); - - return promise; - }; - - EmbarkJS.Storage.getUrl = function(hash) { - //var ipfsHash = web3.toAscii(hash); - - return 'http://localhost:8080/ipfs/' + hash; - }; - - 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'); - } else { - ipfs = HaadIpfsApi(options.server, options.port); - } - 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); - }; - - EmbarkJS.Messages.listenTo = function(options) { - return this.currentMessages.listenTo(options); - }; - - 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; - - 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])); - } - } - topics = _topics; - - 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 = []; - - 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); - } 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; - }; - - module.exports = EmbarkJS; - - -/***/ } +/***/ (function(module, exports) { + +/*jshint esversion: 6 */ +//var Ipfs = require('./ipfs.js'); + +//========================================================= +// Embark Smart Contracts +//========================================================= + +var EmbarkJS = {}; + +EmbarkJS.Contract = function(options) { + var self = this; + var i, abiElement; + + 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); + + 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); + } + + var getConfirmation = function() { + self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) { + if (err) { + return reject(err); + } + + 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 || {}; + + 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 + })); + } + }); + + // returns promise + // deploys contract + // wraps it around EmbarkJS.Contract + contractObject["new"].apply(contractObject, contractParams); + }); + + + return promise; +}; + +//========================================================= +// Embark Storage +//========================================================= + +EmbarkJS.Storage = {}; + +EmbarkJS.Storage.Providers = { + IPFS: 'ipfs', + SWARM: 'swarm' +}; + +EmbarkJS.Storage.IPFS = {}; + +EmbarkJS.Storage.saveText = function(text) { + return this.currentStorage.saveText(text); +}; + +EmbarkJS.Storage.get = function(hash) { + return this.currentStorage.get(hash); +}; + +EmbarkJS.Storage.uploadFile = function(inputSelector) { + return this.currentStorage.uploadFile(inputSelector); +} + +EmbarkJS.Storage.getUrl = function(hash) { + return this.currentStorage.getUrl(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.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'); + } else { + ipfs = HaadIpfsApi(options.server, options.port); + } + this.currentMessages.orbit = new Orbit(ipfs); + this.currentMessages.orbit.connect(web3.eth.accounts[0]); + } else { + throw Error('Unknown message provider'); + } +}; + +EmbarkJS.Messages.sendMessage = function(options) { + return this.currentMessages.sendMessage(options); +}; + +EmbarkJS.Messages.listenTo = function(options) { + return this.currentMessages.listenTo(options); +}; + +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; + + 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])); + } + } + topics = _topics; + + 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 = []; + + 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); + } 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; +}; + +module.exports = EmbarkJS; + + +/***/ }) /******/ ]); \ No newline at end of file diff --git a/js/embark.js b/js/embark.js index 93b7e39f..8f31e9ac 100644 --- a/js/embark.js +++ b/js/embark.js @@ -1,446 +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); - - return promise; + 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; }; -EmbarkJS.IPFS = 'ipfs'; +//========================================================= +// Embark Storage +//========================================================= -EmbarkJS.Storage = { +EmbarkJS.Storage = {}; + +EmbarkJS.Storage.Providers = { + IPFS: 'ipfs', + SWARM: 'swarm' }; -EmbarkJS.Storage.setProvider = function(provider, options) { - if (provider === 'ipfs') { - 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 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); - }); - }); - - 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; diff --git a/lib/cmd.js b/lib/cmd.js index e529ff7d..4c774b03 100644 --- a/lib/cmd.js +++ b/lib/cmd.js @@ -1,15 +1,12 @@ var program = require('commander'); var colors = require('colors'); var shelljs = require('shelljs'); -var promptly = require('promptly'); -var path = require('path'); +var Embark = require('../lib/index'); -var Cmd = function(Embark) { - this.Embark = Embark; +var Cmd = function() { program.version(Embark.version); }; - Cmd.prototype.process = function(args) { this.newApp(); this.demo(); @@ -30,64 +27,40 @@ Cmd.prototype.process = function(args) { }; Cmd.prototype.newApp = function() { - var self = this; - - var validateName = function (value) { - try { - if(value.match(/^[a-zA-Z\s\-]+$/)) return value; - } catch (e) { - throw new Error('Name must be only letters, spaces, or dashes'); - } - }; - program - .command('new [name]') - .description('new application') - .action(function (name, options) { - var parentDirectory = path.dirname(__dirname).split("/").pop(); - if (name === undefined) { - return promptly.prompt("Name your app: (default: " + parentDirectory + ")", { - default: parentDirectory, - validator: validateName - }, function (err, inputvalue) { - if (err) { - console.error('Invalid name:', err.message); - // Manually call retry - // The passed error has a retry method to easily prompt again. - err.retry(); - } else { - //slightly different assignment of name since it comes from child prompt - self.Embark.generateTemplate('boilerplate', parentDirectory, inputvalue); - } - }); - } + .command('new [name]') + .description('new application') + .action(function(name, options) { + if (name === undefined) { - self.Embark.generateTemplate('boilerplate', './', name); - }); + console.log("please specify your app Name".red); + console.log("e.g embark new MyApp".green); + console.log("e.g embark new --help for more information".green); + process.exit(9); + } + Embark.generateTemplate('boilerplate', './', name); + }); }; Cmd.prototype.demo = function() { - var self = this; program .command('demo') .description('create a working dapp with a SimpleStorage contract') .action(function() { - self.Embark.generateTemplate('demo', './', 'embark_demo'); + Embark.generateTemplate('demo', './', 'embark_demo'); }); }; Cmd.prototype.build = function() { - var self = this; program .command('build [environment]') .description('deploy and build dapp at dist/ (default: development)') .action(function(env, options) { - self.Embark.build({env: env || 'development'}); + Embark.build({env: env || 'development'}); }); }; Cmd.prototype.run = function() { - var self = this; program .command('run [environment]') .option('-p, --port [port]', 'port to run the dev webserver (default: 8000)') @@ -97,7 +70,7 @@ Cmd.prototype.run = function() { .option('--no-color', 'no colors in case it\'s needed for compatbility purposes') .description('run dapp (default: development)') .action(function(env, options) { - self.Embark.run({ + Embark.run({ env: env || 'development', serverPort: options.port, serverHost: options.host, @@ -108,22 +81,20 @@ Cmd.prototype.run = function() { }; Cmd.prototype.blockchain = function() { - var self = this; program .command('blockchain [environment]') .option('-c, --client [client]', 'Use a specific ethereum client or simulator (supported: geth, parity, ethersim, testrpc') .description('run blockchain server (default: development)') .action(function(env ,options) { - self.Embark.initConfig(env || 'development', { + Embark.initConfig(env || 'development', { embarkConfig: 'embark.json', interceptLogs: false }); - self.Embark.blockchain(env || 'development', options.client || 'geth'); + Embark.blockchain(env || 'development', options.client || 'geth'); }); }; Cmd.prototype.simulator = function() { - var self = this; program .command('simulator [environment]') .description('run a fast ethereum rpc simulator') @@ -131,11 +102,11 @@ Cmd.prototype.simulator = function() { .option('-p, --port [port]', 'port to run the rpc simulator (default: 8000)') .option('-h, --host [host]', 'host to run the rpc simulator (default: localhost)') .action(function(env, options) { - self.Embark.initConfig(env || 'development', { + Embark.initConfig(env || 'development', { embarkConfig: 'embark.json', interceptLogs: false }); - self.Embark.simulator({port: options.port, host: options.host}); + Embark.simulator({port: options.port, host: options.host}); }); }; @@ -149,16 +120,15 @@ Cmd.prototype.test = function() { }; Cmd.prototype.upload = function() { - var self = this; program .command('upload [platform] [environment]') .description('upload your dapp to a decentralized storage. possible options: ipfs, swarm (e.g embark upload swarm)') .action(function(platform, env, options) { // TODO: get env in cmd line as well - self.Embark.initConfig(env || 'development', { + Embark.initConfig(env || 'development', { embarkConfig: 'embark.json', interceptLogs: false }); - self.Embark.upload(platform); + Embark.upload(platform); }); }; diff --git a/lib/cmds/template_generator.js b/lib/cmds/template_generator.js index a0aa482f..42c63288 100644 --- a/lib/cmds/template_generator.js +++ b/lib/cmds/template_generator.js @@ -1,5 +1,5 @@ var fs = require('../core/fs.js'); -var utils = require('../core/utils.js'); +var utils = require('../utils/utils.js'); var TemplateGenerator = function(templateName) { this.templateName = templateName; diff --git a/lib/contracts/compiler.js b/lib/contracts/compiler.js index f7a7c70e..3c258294 100644 --- a/lib/contracts/compiler.js +++ b/lib/contracts/compiler.js @@ -1,18 +1,7 @@ /*jshint esversion: 6, loopfunc: true */ -var async = require('async'); +var async = require('../utils/async_extend.js'); var SolcW = require('./solcW.js'); -function asyncEachObject(object, iterator, callback) { - async.each( - Object.keys(object || {}), - function(key, next){ - iterator(key, object[key], next); - }, - callback - ); -} -async.eachObject = asyncEachObject; - var Compiler = function(options) { this.plugins = options.plugins; this.logger = options.logger; diff --git a/lib/contracts/deploy_manager.js b/lib/contracts/deploy_manager.js index 0293b97c..ebbe5d08 100644 --- a/lib/contracts/deploy_manager.js +++ b/lib/contracts/deploy_manager.js @@ -1,5 +1,4 @@ var async = require('async'); -var Web3 = require('web3'); var Deploy = require('./deploy.js'); var ContractsManager = require('./contracts.js'); @@ -33,21 +32,25 @@ DeployManager.prototype.deployContracts = function(done) { }); contractsManager.build(callback); }, - function connectWithWeb3(contractsManager, callback) { - var web3; - if (self.web3) { - web3 = self.web3; - } else { - web3 = new Web3(); - var web3Endpoint = 'http://' + self.config.blockchainConfig.rpcHost + ':' + self.config.blockchainConfig.rpcPort; - web3.setProvider(new web3.providers.HttpProvider(web3Endpoint)); - if (!web3.isConnected()) { - self.logger.error(("Couldn't connect to " + web3Endpoint.underline + " are you sure it's on?").red); - self.logger.info("make sure you have an ethereum node or simulator running. e.g 'embark blockchain'".magenta); - return callback(Error("error connecting to blockchain node")); - } + function checkWeb3IsConnected(contractsManager, callback) { + if (!self.web3) { + return callback(Error("no web3 instance found")); + } + if (self.web3.currentProvider.isConnected !== undefined && !self.web3.isConnected()) { + self.logger.error(("Couldn't connect to an Ethereum node are you sure it's on?").red); + self.logger.info("make sure you have an Ethereum node or simulator running. e.g 'embark blockchain'".magenta); + return callback(Error("error connecting to blockchain node")); + } + if (self.web3.currentProvider.isConnected === undefined) { + self.web3.version.getNode(function(err, version) { + if (err) { + return callback(Error("error connecting to blockchain node")); + } + return callback(null, contractsManager, self.web3); + }); + } else { + return callback(null, contractsManager, self.web3); } - callback(null, contractsManager, web3); }, function setDefaultAccount(contractsManager, web3, callback) { web3.eth.getAccounts(function(err, accounts) { diff --git a/lib/contracts/solcW.js b/lib/contracts/solcW.js index eec22b10..e9a0f9ad 100644 --- a/lib/contracts/solcW.js +++ b/lib/contracts/solcW.js @@ -1,4 +1,4 @@ -var utils = require('../core/utils.js'); +var utils = require('../utils/utils.js'); var solcProcess; var compilerLoaded = false; diff --git a/lib/core/config.js b/lib/core/config.js index 3db31a9a..c87b6761 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -1,6 +1,6 @@ var fs = require('./fs.js'); var Plugins = require('./plugins.js'); -var utils = require('./utils.js'); +var utils = require('../utils/utils.js'); // TODO: add wrapper for fs so it can also work in the browser // can work with both read and save diff --git a/lib/core/engine.js b/lib/core/engine.js index ad248a7c..9f7a8736 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -1,11 +1,14 @@ +var http = require('http'); +var Web3 = require('web3'); +var utils = require('../utils/utils.js'); + var Events = require('./events.js'); var Logger = require('./logger.js'); var Config = require('./config.js'); var DeployManager = require('../contracts/deploy_manager.js'); var ABIGenerator = require('../contracts/abi.js'); -var Dashboard = require('../dashboard/dashboard.js'); -var ServicesMonitor = require('./services.js'); +var ServicesMonitor = require('./services_monitor.js'); var Pipeline = require('../pipeline/pipeline.js'); var Server = require('../pipeline/server.js'); var Watch = require('../pipeline/watch.js'); @@ -19,24 +22,44 @@ var Engine = function(options) { }; Engine.prototype.init = function(_options) { + var self = this; var options = _options || {}; this.events = new Events(); this.logger = options.logger || new Logger({logLevel: 'debug'}); this.config = new Config({env: this.env, logger: this.logger, events: this.events}); this.config.loadConfigFiles({embarkConfig: this.embarkConfig, interceptLogs: this.interceptLogs}); this.plugins = this.config.plugins; + + this.servicesMonitor = new ServicesMonitor({events: this.events, logger: this.logger}); + this.servicesMonitor.addCheck('embarkVersion', function(cb) { + return cb({name: 'Embark ' + self.version, status: 'green'}); + }, 0); +}; + +Engine.prototype.startMonitor = function() { + var self = this; + if (this.plugins) { + var servicePlugins = this.plugins.getPluginsFor('serviceChecks'); + servicePlugins.forEach(function(plugin) { + plugin.serviceChecks.forEach(function(pluginCheck) { + self.servicesMonitor.addCheck(pluginCheck.checkName, pluginCheck.checkFn, pluginCheck.time); + }); + }); + } + this.servicesMonitor.startMonitor(); }; Engine.prototype.startService = function(serviceName, _options) { var options = _options || {}; var services = { - "monitor": this.monitorService, "pipeline": this.pipelineService, "abi": this.abiService, "deployment": this.deploymentService, "fileWatcher": this.fileWatchService, - "webServer": this.webServerService + "webServer": this.webServerService, + "ipfs": this.ipfsService, + "web3": this.web3Service }; var service = services[serviceName]; @@ -50,18 +73,6 @@ Engine.prototype.startService = function(serviceName, _options) { return service.apply(this, [options]); }; -Engine.prototype.monitorService = function(options) { - var servicesMonitor = new ServicesMonitor({ - logger: this.logger, - config: this.config, - serverHost: options.serverHost, - serverPort: options.serverPort, - runWebserver: options.runWebserver, - version: this.version - }); - servicesMonitor.startMonitor(); -}; - Engine.prototype.pipelineService = function(options) { var self = this; this.logger.setStatus("Building Assets"); @@ -77,13 +88,15 @@ Engine.prototype.pipelineService = function(options) { pipeline.build(abi); self.events.emit('outputDone'); }); - this.events.on('file-event', function(fileType, path) { - if (fileType === 'asset') { - self.config.reloadConfig(); - pipeline.build(self.abi, path); - self.events.emit('outputDone'); - } - }); + // TODO: still need to redeploy contracts because the original contracts + // config is being corrupted + //this.events.on('file-event', function(fileType, path) { + // if (fileType === 'asset') { + // self.config.reloadConfig(); + // pipeline.build(self.abi, path); + // self.events.emit('outputDone'); + // } + //}); }; Engine.prototype.abiService = function(options) { @@ -111,7 +124,7 @@ Engine.prototype.abiService = function(options) { Engine.prototype.deploymentService = function(options) { var self = this; this.deployManager = new DeployManager({ - web3: options.web3, + web3: options.web3 || self.web3, trackContracts: options.trackContracts, config: this.config, logger: this.logger, @@ -120,10 +133,12 @@ Engine.prototype.deploymentService = function(options) { }); this.events.on('file-event', function(fileType, path) { - if (fileType === 'contract' || fileType === 'config') { + // TODO: for now need to deploy on asset chanes as well + // because the contractsManager config is corrupted after a deploy + //if (fileType === 'contract' || fileType === 'config') { self.config.reloadConfig(); self.deployManager.deployContracts(function() {}); - } + //} }); }; @@ -134,15 +149,96 @@ Engine.prototype.fileWatchService = function(options) { }; Engine.prototype.webServerService = function(options) { + var self = this; var webServerConfig = this.config.webServerConfig; if (!webServerConfig.enabled) { return; } + + var host = options.host || webServerConfig.host; + var port = options.port || webServerConfig.port; + this.logger.setStatus("Starting Server"); var server = new Server({ logger: this.logger, - host: options.host || webServerConfig.host, - port: options.port || webServerConfig.port + host: host, + port: port + }); + + self.servicesMonitor.addCheck('Webserver', function(cb) { + var devServer = 'Webserver (http://' + host + ':' + port + ')'; + return cb({name: devServer, status: 'green'}); + }); + + server.start(function(){ }); - server.start(function(){}); }; +Engine.prototype.ipfsService = function(options) { + var self = this; + self.servicesMonitor.addCheck('IPFS', function(cb) { + utils.checkIsAvailable('http://localhost:5001', function(available) { + if (available) { + //Ideally this method should be in an IPFS API JSONRPC wrapper + //The URL should also be flexible to accept non-default IPFS url + self.logger.trace("Checking IPFS version..."); + http.get('http://localhost:5001/api/v0/version', function(res) { + var body = ''; + res.on('data', function(d) { + body += d; + }); + res.on('end', function() { + try{ + var parsed = JSON.parse(body); + if(parsed.Version){ + return cb({name: ("IPFS " + parsed.Version), status: 'green'}); + } + else{ + return cb({name: "IPFS ", status: 'green'}); + } + } + catch (e){ + return cb({name: "IPFS ", status: 'red'}); + } + }); + res.on('error', function(err) { + self.logger.trace("Check IPFS version error: " + err); + return cb({name: "IPFS ", status: 'red'}); + }); + }); + } + else { + return cb({name: "IPFS ", status: 'red'}); + } + }); + }); +}; + +Engine.prototype.web3Service = function(options) { + var self = this; + this.web3 = options.web3; + if (this.web3 === undefined) { + this.web3 = new Web3(); + var web3Endpoint = 'http://' + this.config.blockchainConfig.rpcHost + ':' + this.config.blockchainConfig.rpcPort; + this.web3.setProvider(new this.web3.providers.HttpProvider(web3Endpoint)); + } + + self.servicesMonitor.addCheck('Ethereum', function(cb) { + if (self.web3.isConnected()) { + return cb({name: (self.web3.version.node.split("/")[0] + " " + self.web3.version.node.split("/")[1].split("-")[0] + " (Ethereum)"), status: 'green'}); + } else { + return cb({name: "No Blockchain node found", status: 'red'}); + } + }); + + self.servicesMonitor.addCheck('Whisper', function(cb) { + self.web3.version.getWhisper(function(err, res) { + if (err) { + return cb({name: 'Whisper', status: 'red'}); + } else { + return cb({name: 'Whisper', status: 'green'}); + } + }); + }); +}; + + module.exports = Engine; diff --git a/lib/core/fs.js b/lib/core/fs.js index dbbf7480..a88816e4 100644 --- a/lib/core/fs.js +++ b/lib/core/fs.js @@ -1,5 +1,5 @@ var fs = require('fs-extra'); -var utils = require('./utils.js'); +var utils = require('../utils/utils.js'); function mkdirpSync() { return fs.mkdirpSync.apply(fs.mkdirpSync, arguments); diff --git a/lib/core/logger.js b/lib/core/logger.js index 5007977c..442544a7 100644 --- a/lib/core/logger.js +++ b/lib/core/logger.js @@ -5,7 +5,6 @@ var Logger = function(options) { this.logLevel = options.logLevel || 'info'; this.logFunction = options.logFunction || console.log; this.contractsState = options.contractsState || function() {}; - this.availableServices = options.availableServices || function() {}; this.setStatus = options.setStatus || console.log; }; diff --git a/lib/core/plugin.js b/lib/core/plugin.js index 32765ea3..45a498f0 100644 --- a/lib/core/plugin.js +++ b/lib/core/plugin.js @@ -1,6 +1,6 @@ /*jshint esversion: 6, loopfunc: true */ var fs = require('./fs.js'); -var utils = require('./utils.js'); +var utils = require('../utils/utils.js'); // TODO: pass other params like blockchainConfig, contract files, etc.. var Plugin = function(options) { @@ -17,6 +17,7 @@ var Plugin = function(options) { this.contractsConfigs = []; this.contractsFiles = []; this.compilers = []; + this.serviceChecks = []; this.pluginTypes = []; this.logger = options.logger; this.events = options.events; @@ -98,6 +99,11 @@ Plugin.prototype.registerConsoleCommand = function(cb) { this.pluginTypes.push('console'); }; +Plugin.prototype.registerServiceCheck = function(checkName, checkFn, time) { + this.serviceChecks.push({checkName: checkName, checkFn: checkFn, time: time}); + this.pluginTypes.push('serviceChecks'); +}; + Plugin.prototype.has = function(pluginType) { return this.pluginTypes.indexOf(pluginType) >= 0; }; diff --git a/lib/core/plugins.js b/lib/core/plugins.js index 4132a280..c3319183 100644 --- a/lib/core/plugins.js +++ b/lib/core/plugins.js @@ -1,5 +1,5 @@ var Plugin = require('./plugin.js'); -var utils = require('./utils.js'); +var utils = require('../utils/utils.js'); var Plugins = function(options) { this.pluginList = options.plugins || []; diff --git a/lib/core/services.js b/lib/core/services.js deleted file mode 100644 index a04f672e..00000000 --- a/lib/core/services.js +++ /dev/null @@ -1,113 +0,0 @@ -var Web3 = require('web3'); -var async = require('async'); -var http = require('http'); -var utils = require('./utils.js'); - -// TODO: needs a refactor and be done in a different way -var ServicesMonitor = function(options) { - this.logger = options.logger; - this.interval = options.interval || 5000; - this.config = options.config; - this.serverHost = options.serverHost || 'localhost'; - this.serverPort = options.serverPort || 8000; - this.runWebserver = options.runWebserver; - this.version = options.version; -}; - -ServicesMonitor.prototype.startMonitor = function() { - this.check(); - this.monitor = setInterval(this.check.bind(this), this.interval); -}; - -ServicesMonitor.prototype.stopMonitor = function() { -}; - -ServicesMonitor.prototype.check = function() { - var self = this; - async.waterfall([ - function connectWeb3(callback) { - self.logger.trace('connectWeb3'); - var web3 = new Web3(); - var web3Endpoint = 'http://' + self.config.blockchainConfig.rpcHost + ':' + self.config.blockchainConfig.rpcPort; - web3.setProvider(new web3.providers.HttpProvider(web3Endpoint)); - callback(null, web3, []); - }, - function addEmbarkVersion(web3, result, callback) { - self.logger.trace('addEmbarkVersion'); - result.push(('Embark ' + self.version).green); - callback(null, web3, result); - }, - function checkEthereum(web3, result, callback) { - self.logger.trace('checkEthereum'); - var service; - if (web3.isConnected()) { - service = (web3.version.node.split("/")[0] + " " + web3.version.node.split("/")[1].split("-")[0] + " (Ethereum)").green; - } else { - service = "No Blockchain node found".red; - } - result.push(service); - callback(null, web3, result); - }, - function checkWhisper(web3, result, callback) { - self.logger.trace('checkWhisper'); - web3.version.getWhisper(function(err, res) { - var service = 'Whisper'; - result.push(err ? service.red : service.green); - callback(null, result); - }); - }, - function checkIPFS(result, callback) { - self.logger.trace('checkIPFS'); - - utils.checkIsAvailable('http://localhost:5001', function(available) { - if (available) { - //Ideally this method should be in an IPFS API JSONRPC wrapper - //The URL should also be flexible to accept non-default IPFS url - self.logger.trace("Checking IPFS version..."); - http.get('http://localhost:5001/api/v0/version', function(res) { - var body = ''; - res.on('data', function(d) { - body += d; - }); - res.on('end', function() { - var parsed = JSON.parse(body); - if(parsed.Version){ - result.push(("IPFS " + parsed.Version).green); - } - else{ - result.push("IPFS".green); - } - callback(null, result); - }); - res.on('error', function(err) { - self.logger.trace("Check IPFS version error: " + err); - result.push("IPFS".green); - callback(null, result); - }); - }); - } - else { - result.push('IPFS'.red); - return callback(null, result); - } - }); - }, - function checkDevServer(result, callback) { - var host = self.serverHost || self.config.webServerConfig.host; - var port = self.serverPort || self.config.webServerConfig.port; - self.logger.trace('checkDevServer'); - var devServer = 'Webserver (http://' + host + ':' + port + ')'; - devServer = (self.runWebserver) ? devServer.green : devServer.red; - result.push(devServer); - callback(null, result); - } - ], function(err, result) { - if (err) { - self.logger.error(err.message); - } else { - self.logger.availableServices(result); - } - }); -}; - -module.exports = ServicesMonitor; diff --git a/lib/core/services_monitor.js b/lib/core/services_monitor.js new file mode 100644 index 00000000..2685c5c2 --- /dev/null +++ b/lib/core/services_monitor.js @@ -0,0 +1,80 @@ +var async = require('../utils/async_extend.js'); + +// TODO: need to separate colors from states +// i.e use status: /on|off|warn/ not /red|green/ +// it's up to the logger or console to determine the color +var ServicesMonitor = function(options) { + this.events = options.events; + this.logger = options.logger; + this.checkList = {}; + this.checkTimers = {}; + this.checkState = {}; + this.working = false; +}; + +ServicesMonitor.prototype.initCheck = function(checkName) { + var self = this; + var check = this.checkList[checkName]; + + if (!check) { return false; } + + self.events.on('check:' + checkName, function(obj) { + // TODO: see todo above + if (check && check.status === 'red' && obj.status === 'green') { + self.events.emit('check:backOnline:' + checkName); + } + if (check && check.status === 'green' && obj.status === 'red') { + self.events.emit('check:wentOffline:' + checkName); + } + self.checkState[checkName] = obj.name[obj.status]; + check.status = obj.status; + self.events.emit("servicesState", self.checkState); + }); + + if (check.interval !== 0) { + self.checkTimers[checkName] = setInterval(function() { + check.fn.call(check.fn, function(obj) { + self.events.emit('check:' + checkName, obj); + }); + }, check.interval); + } + + check.fn.call(check.fn, function(obj) { + self.events.emit('check:' + checkName, obj); + }); +}; + +ServicesMonitor.prototype.addCheck = function(checkName, checkFn, time) { + var self = this; + this.logger.trace('add check: ' + checkName); + this.checkList[checkName] = {fn: checkFn, interval: time || 5000}; + + if (this.working) { + this.initCheck(checkName); + } +}; + +ServicesMonitor.prototype.stopCheck = function(name) { + clearInterval(this.checkTimers[name]); + delete this.checkTimers[name]; + delete this.checkList[name]; + delete this.checkState[name]; +}; + +ServicesMonitor.prototype.startMonitor = function() { + var self = this; + this.working = true; + this.logger.trace('startMonitor'); + + async.eachObject(this.checkList, function(checkName, check, callback) { + self.initCheck(checkName); + callback(); + }, function(err) { + if (err) { + self.logger.error("error running service check"); + self.logger.error(err.message); + } + }); +}; + +module.exports = ServicesMonitor; diff --git a/lib/core/test.js b/lib/core/test.js index ac1b5e37..d4b216e4 100644 --- a/lib/core/test.js +++ b/lib/core/test.js @@ -1,22 +1,6 @@ -var async = require('async'); -var Web3 = require('web3'); - -var Embark = require('../index.js'); - -var Engine = require('./engine.js'); - -var ABIGenerator = require('../contracts/abi.js'); -var ContractsManager = require('../contracts/contracts.js'); -var Deploy = require('../contracts/deploy.js'); - -var Config = require('./config.js'); -var RunCode = require('./runCode.js'); -var TestLogger = require('./test_logger.js'); - var getSimulator = function() { try { - var sim = require('ethereumjs-testrpc'); - return sim; + return require('ethereumjs-testrpc'); } catch (e) { if (e.code === 'MODULE_NOT_FOUND') { console.log('Simulator not found; Please install it with "npm install ethereumjs-testrpc --save"'); @@ -33,30 +17,44 @@ var getSimulator = function() { } }; -var Test = function(options) { - this.options = options || {}; - var simOptions = this.options.simulatorOptions || {}; +var Test; +Test = (function (options) { + var async = require('async'); + var opts = options === undefined ? {} : options; + opts.logLevel = opts.hasOwnProperty('logLevel') ? opts.logLevel : 'debug'; + opts.simulatorOptions = opts.hasOwnProperty('simulatorOptions') ? opts.simulatorOptions : {}; + var sim = getSimulator(); - this.engine = new Engine({ - env: this.options.env || 'test', - // TODO: confi will need to detect if this is a obj - embarkConfig: this.options.embarkConfig || 'embark.json', - interceptLogs: false - }); + function newWebThree() { + try { + var Web3 = require('web3'); + var web3 = new Web3(); + web3.setProvider(sim.provider(opts.simulatorOptions)); + return web3; + } catch (e) { + throw new Error(e); + } + } - this.engine.init({ - logger: new TestLogger({logLevel: this.options.logLevel || 'debug'}) - }); + function deployAll(contractsConfig, cb) { + var RunCode = require('./runCode.js'); + var self = this; - this.sim = getSimulator(); - this.web3 = new Web3(); - this.web3.setProvider(this.sim.provider(simOptions)); -}; + function newEngine () { + var Engine = require('./engine.js'); + return new Engine({ + env: opts.env || 'test', + // TODO: confi will need to detect if this is a obj + embarkConfig: opts.embarkConfig || 'embark.json', + interceptLogs: false + }); + } -Test.prototype.deployAll = function(contractsConfig, cb) { - var self = this; + self.web3 = newWebThree(); + self.engine = newEngine(); + self.engine.init(); - async.waterfall([ + async.waterfall([ function getConfig(callback) { self.engine.config.contractsConfig = {contracts: contractsConfig}; callback(); @@ -71,32 +69,39 @@ Test.prototype.deployAll = function(contractsConfig, cb) { callback(); }, function deploy(callback) { - self.engine.events.on('abi-contracts-vanila', function(vanillaABI) { + self.engine.events.on('abi-contracts-vanila', function (vanillaABI) { callback(null, vanillaABI); }); - self.engine.deployManager.deployContracts(function(err, result) { + self.engine.deployManager.deployContracts(function (err, result) { if (err) { console.log(err); callback(err); } }); } - ], function(err, result) { - if (err) { - console.log("got error"); - process.exit(); - } - // this should be part of the waterfall and not just something done at the - // end - self.web3.eth.getAccounts(function(err, accounts) { + ], function (err, result) { if (err) { - throw new Error(err); + console.log("got error"); + process.exit(); } - self.web3.eth.defaultAccount = accounts[0]; - RunCode.doEval(result, self.web3); // jshint ignore:line - cb(); + // this should be part of the waterfall and not just something done at the + // end + self.web3.eth.getAccounts(function (err, accounts) { + if (err) { + throw new Error(err); + } + self.web3.eth.defaultAccount = accounts[0]; + RunCode.doEval(result, self.web3); // jshint ignore:line + cb(); + }); }); - }); -}; + } + + + return { + deployAll: deployAll, + sim: sim + }; +}()); module.exports = Test; diff --git a/lib/dashboard/console.js b/lib/dashboard/console.js index c510f204..51ed85f8 100644 --- a/lib/dashboard/console.js +++ b/lib/dashboard/console.js @@ -1,4 +1,4 @@ -var utils = require('../core/utils.js'); +var utils = require('../utils/utils.js'); var RunCode = require('../core/runCode.js'); var Console = function(options) { diff --git a/lib/dashboard/dashboard.js b/lib/dashboard/dashboard.js index d67b142d..367b77b8 100644 --- a/lib/dashboard/dashboard.js +++ b/lib/dashboard/dashboard.js @@ -23,7 +23,6 @@ Dashboard.prototype.start = function(done) { monitor = new Monitor({env: self.env, console: console}); self.logger.logFunction = monitor.logEntry; self.logger.contractsState = monitor.setContracts; - self.logger.availableServices = monitor.availableServices; self.logger.setStatus = monitor.setStatus.bind(monitor); self.logger.info('========================'.bold.green); diff --git a/lib/dashboard/monitor.js b/lib/dashboard/monitor.js index 210fa7ce..b1a243c4 100644 --- a/lib/dashboard/monitor.js +++ b/lib/dashboard/monitor.js @@ -40,7 +40,13 @@ function Dashboard(options) { this.input.focus(); } -Dashboard.prototype.availableServices = function(services) { +Dashboard.prototype.availableServices = function(_services) { + var services = []; + var checkName; + for (checkName in _services) { + services.push(_services[checkName]); + } + this.progress.setContent(services.join('\n')); this.screen.render(); }; diff --git a/lib/index.js b/lib/index.js index 6b358d23..7037f224 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,64 +1,49 @@ /*jshint esversion: 6 */ var async = require('async'); -//require("./core/debug_util.js")(__filename, async); +// require("./utils/debug_util.js")(__filename, async); -var Web3 = require('web3'); var colors = require('colors'); var Engine = require('./core/engine.js'); -var Blockchain = require('./cmds/blockchain/blockchain.js'); -var Simulator = require('./cmds/simulator.js'); -var TemplateGenerator = require('./cmds/template_generator.js'); - -var Test = require('./core/test.js'); -var Logger = require('./core/logger.js'); -var Config = require('./core/config.js'); -var Events = require('./core/events.js'); - -var Dashboard = require('./dashboard/dashboard.js'); - var IPFS = require('./upload/ipfs.js'); var Swarm = require('./upload/swarm.js'); -var Cmd = require('./cmd.js'); var version = require('../package.json').version; -var Embark = { +var Embark = (function () { + function initConfig (env, options) { + var Events = require('./core/events.js'); + var Logger = require('./core/logger.js'); + var Config = require('./core/config.js'); - version: version, - - process: function(args) { - var cmd = new Cmd(Embark); - cmd.process(args); - }, - - initConfig: function(env, options) { this.events = new Events(); this.logger = new Logger({logLevel: 'debug'}); this.config = new Config({env: env, logger: this.logger, events: this.events}); this.config.loadConfigFiles(options); this.plugins = this.config.plugins; - }, + } - blockchain: function(env, client) { - var blockchain = Blockchain(this.config.blockchainConfig, client, env); - blockchain.run(); - }, + function blockchain (env, client) { + return require('./cmds/blockchain/blockchain.js')(this.config.blockchainConfig, client, env).run(); + } - simulator: function(options) { + function simulator (options) { + var Simulator = require('./cmds/simulator.js'); var simulator = new Simulator({blockchainConfig: this.config.blockchainConfig}); simulator.run(options); - }, + } - generateTemplate: function(templateName, destinationFolder, name) { + function generateTemplate (templateName, destinationFolder, name) { + var TemplateGenerator = require('./cmds/template_generator.js'); var templateGenerator = new TemplateGenerator(templateName); templateGenerator.generate(destinationFolder, name); - }, + } + + function run (options) { + var Dashboard = require('./dashboard/dashboard.js'); - run: function(options) { - var self = this; var env = options.env; var engine = new Engine({ @@ -90,6 +75,11 @@ var Embark = { dashboard.console.runCode(abi); }); + engine.logger.info('dashboard start'); + engine.events.on('servicesState', function(servicesState) { + dashboard.monitor.availableServices(servicesState); + }); + callback(); }); }, @@ -99,16 +89,20 @@ var Embark = { engine.logger.info("loaded plugins: " + pluginList.join(", ")); } - if (options.useDashboard) { - engine.startService("monitor", { - serverHost: options.serverHost, - serverPort: options.serverPort, - runWebserver: options.runWebserver - }); - } + engine.startMonitor(); + engine.startService("web3"); engine.startService("pipeline"); engine.startService("abi"); engine.startService("deployment"); + engine.startService("ipfs"); + + engine.events.on('check:backOnline:Ethereum', function() { + engine.logger.info('Ethereum node detected..'); + engine.config.reloadConfig(); + engine.deployManager.deployContracts(function() { + engine.logger.info('Deployment Done'); + }); + }); engine.deployManager.deployContracts(function() { engine.startService("fileWatcher"); @@ -131,10 +125,9 @@ var Embark = { engine.events.emit('firstDeploymentDone'); } }); - }, + } - build: function(options) { - var self = this; + function build (options) { var engine = new Engine({ env: options.env, @@ -169,14 +162,15 @@ var Embark = { // needed due to child processes process.exit(); }); - }, + } - initTests: function(options) { + function initTests (options) { + var Test = require('./core/test.js'); return new Test(options); - }, + } // TODO: should deploy if it hasn't already - upload: function(platform) { + function upload (platform) { if (platform === 'ipfs') { var ipfs = new IPFS({buildDir: 'dist/', plugins: this.plugins, storageConfig: this.config.storageConfig}); ipfs.deploy(); @@ -189,7 +183,19 @@ var Embark = { } } -}; + return { + version: version, + initConfig: initConfig, + blockchain: blockchain, + simulator: simulator, + generateTemplate: generateTemplate, + run: run, + build: build, + initTests: initTests, + upload: upload + }; + +})(); module.exports = Embark; diff --git a/lib/utils/async_extend.js b/lib/utils/async_extend.js new file mode 100644 index 00000000..1c6db4f5 --- /dev/null +++ b/lib/utils/async_extend.js @@ -0,0 +1,14 @@ +var async = require('async'); + +function asyncEachObject(object, iterator, callback) { + async.each( + Object.keys(object || {}), + function(key, next){ + iterator(key, object[key], next); + }, + callback + ); +} +async.eachObject = asyncEachObject; + +module.exports = async; diff --git a/lib/core/debug_util.js b/lib/utils/debug_util.js similarity index 100% rename from lib/core/debug_util.js rename to lib/utils/debug_util.js diff --git a/lib/core/utils.js b/lib/utils/utils.js similarity index 100% rename from lib/core/utils.js rename to lib/utils/utils.js diff --git a/test/cmd.js b/test/cmd.js index d5853dea..8565ab3d 100644 --- a/test/cmd.js +++ b/test/cmd.js @@ -1,42 +1,41 @@ var Embark = require('../lib/index'); var Cmd = require('../lib/cmd'); -var passingLines = function () { - var lines = []; - lines.push('Initializing Embark Template....'); - lines.push('Installing packages.. this can take a few seconds'); - lines.push('Init complete'); - return lines; -}; - describe('embark.Cmd', function () { + this.timeout(0); var cmd = new Cmd(Embark); - var pl = passingLines(); - var appname = 'deleteapp'; - describe('#new', function () { - this.timeout(0); - it('it should create an app with a `name` argument set', function (done) { - cmd.newApp(appname, function (output) { - var lines = output.split('\n'); - console.log(lines); - assert.equal(lines[0], pl[0]); - assert.equal(lines[1], pl[1]); - assert.equal(lines[2], pl[2]); - assert.equal(lines[3], 'App ready at ./' + appname); - done(); - }); - }); - - it('it should prompt when given an empty app name', function (done) { + it('it should not create an app without a name', function (done) { cmd.newApp(undefined, function (output) { var lines = output.split('\n'); - console.log(lines); - process.stdin.write(appname + '\n'); - assert.equal(lines[0], pl[0]); - done(); + assert.equal(lines[0], 'please specify your app Name'); + assert.equal(lines[1], 'e.g embark new MyApp'); + assert.equal(lines[2], 'e.g embark new --help for more information'); }); + done(); }); + it('it should create an app with a name', function (done) { + var appname = 'deleteapp'; + cmd.newApp(appname, function (output) { + var lines = output.split('\n'); + assert.equal(lines[0], 'Initializing Embark Template....'); + assert.equal(lines[1], 'Installing packages.. this can take a few seconds'); + assert.equal(lines[2], 'Init complete'); + assert.equal(lines[3], 'App ready at ./' + appname); + }); + done(); + }); }); + + // describe("#help", function () { + // it('it should spit out helpful text if no arguments are supplied', function (done) { + // cmd.process([], function (output) { + // var lines = output.split('\n'); + // assert.equal(lines[0], '\n'); + // assert.equal(lines[1], 'Usage:'); + // done(); + // }); + // }) + // }) }); \ No newline at end of file diff --git a/test_app/embark.json b/test_app/embark.json index 5cdaae97..0dd46dd1 100644 --- a/test_app/embark.json +++ b/test_app/embark.json @@ -14,6 +14,7 @@ "buildDir": "dist/", "config": "config/", "plugins": { - "embark-babel": {"files": ["**/*.js", "**/*.jsx", "!**/_vendor/*.js"]} + "embark-babel": {"files": ["**/*.js", "**/*.jsx", "!**/_vendor/*.js"]}, + "embark-service": {} } } diff --git a/test_app/extensions/embark-service/index.js b/test_app/extensions/embark-service/index.js new file mode 100644 index 00000000..27f58c84 --- /dev/null +++ b/test_app/extensions/embark-service/index.js @@ -0,0 +1,5 @@ +module.exports = function(embark) { + embark.registerServiceCheck('PluginService', function(cb) { + cb({name: "ServiceName", status: "green"}); + }); +}; diff --git a/test_app/extensions/embark-service/package.json b/test_app/extensions/embark-service/package.json new file mode 100644 index 00000000..b20033a1 --- /dev/null +++ b/test_app/extensions/embark-service/package.json @@ -0,0 +1,11 @@ +{ + "name": "embark-service", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} diff --git a/test_app/package.json b/test_app/package.json index 29cd34ff..d1ea282a 100644 --- a/test_app/package.json +++ b/test_app/package.json @@ -10,11 +10,12 @@ "license": "ISC", "homepage": "", "devDependencies": { - "embark": "../", + "embark": "file:../", "mocha": "^2.2.5" }, "dependencies": { "embark-babel": "^1.0.0", + "embark-service": "./extensions/embark-service", "ethereumjs-testrpc": "^3.0.3" } } diff --git a/test_app/test/another_storage_spec.js b/test_app/test/another_storage_spec.js index e06e11bb..b60297b5 100644 --- a/test_app/test/another_storage_spec.js +++ b/test_app/test/another_storage_spec.js @@ -1,10 +1,9 @@ var assert = require('assert'); -var Embark = require('embark'); -var EmbarkSpec = Embark.initTests(); -var web3 = EmbarkSpec.web3; +var EmbarkSpec = require('embark/lib/core/test.js'); describe("AnotherStorage", function() { before(function(done) { + this.timeout(0); var contractsConfig = { "SimpleStorage": { args: [100] diff --git a/test_app/test/simple_storage_spec.js b/test_app/test/simple_storage_spec.js index 83ad1610..b330ced6 100644 --- a/test_app/test/simple_storage_spec.js +++ b/test_app/test/simple_storage_spec.js @@ -1,10 +1,9 @@ var assert = require('assert'); -var Embark = require('embark'); -var EmbarkSpec = Embark.initTests(); -var web3 = EmbarkSpec.web3; +var EmbarkSpec = require('embark/lib/core/test.js'); describe("SimpleStorage", function() { before(function(done) { + this.timeout(0); var contractsConfig = { "SimpleStorage": { args: [100] diff --git a/test_app/test/token_spec.js b/test_app/test/token_spec.js index 3ed82f67..93eb28b5 100644 --- a/test_app/test/token_spec.js +++ b/test_app/test/token_spec.js @@ -1,10 +1,9 @@ var assert = require('assert'); -var Embark = require('embark'); -var EmbarkSpec = Embark.initTests(); -var web3 = EmbarkSpec.web3; +var EmbarkSpec = require('embark/lib/core/test.js'); describe("Token", function() { before(function(done) { + this.timeout(0); var contractsConfig = { "SimpleStorage": { args: [100]