merge develop

This commit is contained in:
Todd Baur 2017-03-22 14:02:10 +09:00
commit ed7de6af93
41 changed files with 1594 additions and 1234 deletions

92
CONTRIBUTING.md Normal file
View File

@ -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/

View File

@ -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 [![Build
Status](https://travis-ci.org/iurimatias/embark-framework.svg?branch=develop)](https://travis-ci.org/iurimatias/embark-framework) 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) [![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) * [Dashboard](#dashboard)
* [Creating a new DApp](#creating-a-new-dapp) * [Creating a new DApp](#creating-a-new-dapp)
* [Libraries and APIs available](#libraries-and-languages-available) * [Libraries and APIs available](#libraries-and-languages-available)
* [Using and Configuring Contracts](#dapp-structure) * [Using and Configuring Contracts](#using-contracts)
* [EmbarkJS](#embarkjs) * [EmbarkJS](#embarkjs)
* [EmbarkJS - Storage (IPFS)](#embarkjs---storage) * [EmbarkJS - Storage (IPFS)](#embarkjs---storage)
* [EmbarkJS - Communication (Whisper/Orbit)](#embarkjs---communication) * [EmbarkJS - Communication (Whisper/Orbit)](#embarkjs---communication)
* [Testing Contracts](#tests) * [Testing Contracts](#tests)
* [Working with different chains](#working-with-different-chains) * [Working with different chains](#working-with-different-chains)
* [Custom Application Structure](#structuring-application) * [Custom Application Structure](#structuring-application)
* [Deploying to IPFS](#deploying-to-ipfs) * [Deploying to IPFS](#deploying-to-ipfs-and-swarm)
* [Extending Functionality with Plugins](#plugins) * [Extending Functionality with Plugins](#plugins)
* [Donations](#donations) * [Donations](#donations)
@ -144,8 +145,11 @@ DApp Structure
|___ css/ |___ css/
|___ js/ |___ js/
config/ config/
|___ blockchain.json #environments configuration |___ blockchain.json #rpc and blockchain configuration
|___ contracts.json #contracts configuration |___ contracts.json #ethereum contracts configuration
|___ storage.json #ipfs configuration
|___ communication.json #whisper/orbit configuration
|___ webserver.json #dev webserver configuration
test/ test/
|___ #contracts tests |___ #contracts tests
``` ```
@ -223,7 +227,7 @@ If you are using multiple contracts, you can pass a reference to another contrac
"SimpleStorage": { "SimpleStorage": {
"args": [ "args": [
100, 100,
$MyStorage "$MyStorage"
] ]
}, },
"MyStorage": { "MyStorage": {
@ -233,7 +237,7 @@ If you are using multiple contracts, you can pass a reference to another contrac
}, },
"MyMainContract": { "MyMainContract": {
"args": [ "args": [
$SimpleStorage "$SimpleStorage"
] ]
} }
} }
@ -322,14 +326,20 @@ events:
Client side deployment will be automatically available in Embark for existing contracts: Client side deployment will be automatically available in Embark for existing contracts:
```Javascript ```Javascript
SimpleStorage.deploy().then(function(anotherSimpleStorage) {}); SimpleStorage.deploy([args], {options}).then(function(anotherSimpleStorage) {});
``` ```
or it can be manually definied as or it can be manually definied as
```Javascript ```Javascript
var myContract = new EmbarkJS.Contract({abi: abiObject, code: code}); 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 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 # test/simple_storage_spec.js
var assert = require('assert'); var assert = require('assert');
var Embark = require('embark'); var EmbarkSpec = require('embark/lib/core/test.js');
var EmbarkSpec = Embark.initTests();
var web3 = EmbarkSpec.web3;
describe("SimpleStorage", function() { describe("SimpleStorage", function() {
before(function(done) { before(function(done) {
this.timeout(0);
var contractsConfig = { var contractsConfig = {
"SimpleStorage": { "SimpleStorage": {
args: [100] 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. Embark uses [Mocha](http://mochajs.org/) by default, but you can use any testing framework you want.

View File

@ -1,4 +1,4 @@
#!/usr/bin/env node #!/usr/bin/env node
var Cmd = require('../lib/cmd');
var Embark = require('..'); var cli = new Cmd();
Embark.process(process.argv); cli.process(process.argv);

View File

@ -6,6 +6,6 @@
</head> </head>
<body> <body>
<h3>Welcome to Embark!</h3> <h3>Welcome to Embark!</h3>
<p>See the <a href="https://github.com/iurimatias/embark-framework/wiki">Wiki</a> to see what you can do with Embark!</p> <p>See the <a href="http://embark.readthedocs.io/en/latest/index.html" target="_blank">Embark's documentation</a> to see what you can do with Embark!</p>
</body> </body>
</html> </html>

View File

@ -1,9 +1,8 @@
var assert = require('assert'); var assert = require('assert');
var Embark = require('embark'); var EmbarkSpec = require('embark/lib/core/test.js');
var EmbarkSpec = Embark.initTests();
var web3 = EmbarkSpec.web3;
//describe("SimpleStorage", function() {
// describe("SimpleStorage", function() {
// before(function(done) { // before(function(done) {
// this.timeout(0); // this.timeout(0);
// var contractsConfig = { // var contractsConfig = {
@ -30,4 +29,4 @@ var web3 = EmbarkSpec.web3;
// }); // });
// }); // });
// //
//}); // });

View File

@ -32,35 +32,55 @@ $(document).ready(function() {
//EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'}); //EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'});
$("#storage .error").hide(); $("#storage .error").hide();
EmbarkJS.Storage.ipfsConnection.ping() EmbarkJS.Storage.setProvider('ipfs')
.then(function(){ .then(function(){
$("#status-storage").addClass('status-online'); console.log('Provider set to IPFS');
$("#storage-controls").show(); 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) { .catch(function(err){
if(err){ console.log('Failed to set IPFS as Provider:', err.message);
console.log("IPFS Connection Error => " + err.message); $("#storage .error").show();
$("#storage .error").show(); $("#status-storage").addClass('status-offline');
$("#status-storage").addClass('status-offline'); $("#storage-controls").hide();
$("#storage-controls").hide(); });
}
});
$("#storage button.setIpfsText").click(function() { $("#storage button.setIpfsText").click(function() {
var value = $("#storage input.ipfsText").val(); var value = $("#storage input.ipfsText").val();
EmbarkJS.Storage.saveText(value).then(function(hash) { EmbarkJS.Storage.saveText(value).then(function(hash) {
$("span.textHash").html(hash); $("span.textHash").html(hash);
$("input.textHash").val(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() { $("#storage button.loadIpfsHash").click(function() {
var value = $("#storage input.textHash").val(); var value = $("#storage input.textHash").val();
EmbarkJS.Storage.get(value).then(function(content) { EmbarkJS.Storage.get(value).then(function(content) {
$("span.ipfsText").html(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() { $("#storage button.uploadFile").click(function() {
@ -68,8 +88,13 @@ $(document).ready(function() {
EmbarkJS.Storage.uploadFile(input).then(function(hash) { EmbarkJS.Storage.uploadFile(input).then(function(hash) {
$("span.fileIpfsHash").html(hash); $("span.fileIpfsHash").html(hash);
$("input.fileIpfsHash").val(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() { $("#storage button.loadIpfsFile").click(function() {

View File

@ -10,7 +10,7 @@
"license": "ISC", "license": "ISC",
"homepage": "", "homepage": "",
"devDependencies": { "devDependencies": {
"embark": "^2.4.0", "embark": "^2.4.1",
"mocha": "^2.2.5" "mocha": "^2.2.5"
} }
} }

View File

@ -13,13 +13,25 @@ The current available storage is IPFS. it can be initialized as
.. code:: javascript .. 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** **Retrieving Data/Text**
.. code:: javascript .. 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** **Uploading a file**
@ -30,7 +42,13 @@ The current available storage is IPFS. it can be initialized as
.. code:: javascript .. code:: javascript
var input = $("input[type=file"]); 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** **Generate URL to file**

View File

@ -20,11 +20,17 @@ existing contracts:
.. code:: javascript .. code:: javascript
SimpleStorage.deploy().then(function(anotherSimpleStorage) {}); SimpleStorage.deploy([args], {options}).then(function(anotherSimpleStorage) {});
or it can be manually definied as or it can be manually definied as
.. code:: javascript .. code:: javascript
var myContract = new EmbarkJS.Contract({abi: abiObject, code: code}); 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) {});

View File

@ -64,7 +64,7 @@ with the correct address for the contract.
"SimpleStorage": { "SimpleStorage": {
"args": [ "args": [
100, 100,
$MyStorage "$MyStorage"
] ]
}, },
"MyStorage": { "MyStorage": {
@ -74,7 +74,7 @@ with the correct address for the contract.
}, },
"MyMainContract": { "MyMainContract": {
"args": [ "args": [
$SimpleStorage "$SimpleStorage"
] ]
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,446 +1,501 @@
/*jshint esversion: 6 */ /*jshint esversion: 6 */
//var Ipfs = require('./ipfs.js'); //var Ipfs = require('./ipfs.js');
var EmbarkJS = { //=========================================================
}; // Embark Smart Contracts
//=========================================================
var EmbarkJS = {};
EmbarkJS.Contract = function(options) { EmbarkJS.Contract = function(options) {
var self = this; var self = this;
var i, abiElement; var i, abiElement;
this.abi = options.abi; this.abi = options.abi;
this.address = options.address; this.address = options.address;
this.code = '0x' + options.code; this.code = '0x' + options.code;
this.web3 = options.web3 || web3; 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) { if (this.abi) {
for (i = 0; i < this.abi.length; i++) { for (i = 0; i < this.abi.length; i++) {
abiElement = this.abi[i]; abiElement = this.abi[i];
if (abiElement.type === 'event') { if (abiElement.type === 'event') {
this.eventList.push(abiElement.name); 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() { var messageEvents = function() {
self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) { this.cb = function() {};
if (err) { };
return reject(err);
}
if (receipt !== null) { messageEvents.prototype.then = function(cb) {
return resolve(receipt); 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) { var promise = new Promise(function(resolve, reject) {
resolve(transaction); args.push(function(err, transaction) {
} else { promise.tx = transaction;
getConfirmation(); 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; if (receipt !== null) {
}; return resolve(receipt);
return true; }
}
return false; 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) { EmbarkJS.Contract.prototype.deploy = function(args, _options) {
var self = this; var self = this;
var contractParams; var contractParams;
var options = _options || {}; var options = _options || {};
contractParams = args || []; contractParams = args || [];
contractParams.push({ contractParams.push({
from: this.web3.eth.accounts[0], from: this.web3.eth.accounts[0],
data: this.code, data: this.code,
gas: options.gas || 800000 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 var contractObject = this.web3.eth.contract(this.abi);
// deploys contract
// wraps it around EmbarkJS.Contract
contractObject["new"].apply(contractObject, contractParams);
});
var promise = new Promise(function(resolve, reject) {
return promise; 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) { EmbarkJS.Storage.IPFS = {};
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) { EmbarkJS.Storage.saveText = function(text) {
var self = this; return this.currentStorage.saveText(text);
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) { EmbarkJS.Storage.get = function(hash) {
var self = this; return this.currentStorage.get(hash);
// 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) { EmbarkJS.Storage.uploadFile = function(inputSelector) {
self.ipfsConnection.object.get([hash]).then(function(node) { return this.currentStorage.uploadFile(inputSelector);
resolve(node.data);
});
});
return promise;
}; };
EmbarkJS.Storage.getUrl = function(hash) { EmbarkJS.Storage.getUrl = function(hash) {
//var ipfsHash = web3.toAscii(hash); return this.currentStorage.getUrl(hash);
return 'http://localhost:8080/ipfs/' + 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) { EmbarkJS.Messages.setProvider = function(provider, options) {
var self = this; var self = this;
var ipfs; var ipfs;
if (provider === 'whisper') { if (provider === 'whisper') {
this.currentMessages = EmbarkJS.Messages.Whisper; this.currentMessages = EmbarkJS.Messages.Whisper;
if (typeof variable === 'undefined') { if (typeof variable === 'undefined') {
if (options === undefined) { if (options === undefined) {
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
} else { } else {
web3 = new Web3(new Web3.providers.HttpProvider("http://" + options.server + ':' + options.port)); web3 = new Web3(new Web3.providers.HttpProvider("http://" + options.server + ':' + options.port));
} }
} }
web3.version.getWhisper(function(err, res) { web3.version.getWhisper(function(err, res) {
if (err) { if (err) {
console.log("whisper not available"); console.log("whisper not available");
} else { } else {
self.currentMessages.identity = web3.shh.newIdentity(); self.currentMessages.identity = web3.shh.newIdentity();
} }
}); });
} else if (provider === 'orbit') { } else if (provider === 'orbit') {
this.currentMessages = EmbarkJS.Messages.Orbit; this.currentMessages = EmbarkJS.Messages.Orbit;
if (options === undefined) { if (options === undefined) {
ipfs = HaadIpfsApi('localhost', '5001'); 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 { } 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) { EmbarkJS.Messages.sendMessage = function(options) {
return this.currentMessages.sendMessage(options); return this.currentMessages.sendMessage(options);
}; };
EmbarkJS.Messages.listenTo = function(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) { EmbarkJS.Messages.Whisper.sendMessage = function(options) {
var topics = options.topic || options.topics; var topics = options.topic || options.topics;
var data = options.data || options.payload; var data = options.data || options.payload;
var identity = options.identity || this.identity || web3.shh.newIdentity(); var identity = options.identity || this.identity || web3.shh.newIdentity();
var ttl = options.ttl || 100; var ttl = options.ttl || 100;
var priority = options.priority || 1000; var priority = options.priority || 1000;
var _topics; var _topics;
if (topics === undefined) { if (topics === undefined) {
throw new Error("missing option: topic"); 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); if (data === undefined) {
throw new Error("missing option: data");
}
var message = { // do fromAscii to each topics unless it's already a string
from: identity, if (typeof topics === 'string') {
topics: topics, _topics = [web3.fromAscii(topics)];
payload: web3.fromAscii(payload), } else {
ttl: ttl, // TODO: replace with es6 + babel;
priority: priority 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) { EmbarkJS.Messages.Whisper.listenTo = function(options) {
var topics = options.topic || options.topics; var topics = options.topic || options.topics;
var _topics = []; var _topics = [];
if (typeof topics === 'string') { if (typeof topics === 'string') {
_topics = [topics]; _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 { } else {
data = { // TODO: replace with es6 + babel;
topic: topics, for (var i = 0; i < topics.length; i++) {
data: payload, _topics.push(topics[i]);
from: result.from, }
time: (new Date(result.sent * 1000))
};
promise.cb(payload, data, result);
} }
}); 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) { EmbarkJS.Messages.Orbit.sendMessage = function(options) {
var topics = options.topic || options.topics; var topics = options.topic || options.topics;
var data = options.data || options.payload; var data = options.data || options.payload;
if (topics === undefined) { if (topics === undefined) {
throw new Error("missing option: topic"); throw new Error("missing option: topic");
} }
if (data === undefined) { if (data === undefined) {
throw new Error("missing option: data"); throw new Error("missing option: data");
} }
if (typeof topics === 'string') { if (typeof topics === 'string') {
topics = topics; topics = topics;
} else { } else {
// TODO: better to just send to different channels instead // TODO: better to just send to different channels instead
topics = topics.join(','); 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) { EmbarkJS.Messages.Orbit.listenTo = function(options) {
var self = this; var self = this;
var topics = options.topic || options.topics; var topics = options.topic || options.topics;
if (typeof topics === 'string') { if (typeof topics === 'string') {
topics = topics; topics = topics;
} else { } else {
topics = topics.join(','); topics = topics.join(',');
} }
this.orbit.join(topics); this.orbit.join(topics);
var messageEvents = function() { var messageEvents = function() {
this.cb = function() {}; this.cb = function() {};
}; };
messageEvents.prototype.then = function(cb) { messageEvents.prototype.then = function(cb) {
this.cb = cb; this.cb = cb;
}; };
messageEvents.prototype.error = function(err) { messageEvents.prototype.error = function(err) {
return err; return err;
}; };
var promise = new messageEvents(); var promise = new messageEvents();
this.orbit.events.on('message', (channel, message) => { this.orbit.events.on('message', (channel, message) => {
// TODO: looks like sometimes it's receving messages from all topics // TODO: looks like sometimes it's receving messages from all topics
if (topics !== channel) return; if (topics !== channel) return;
self.orbit.getPost(message.payload.value, true).then((post) => { self.orbit.getPost(message.payload.value, true).then((post) => {
var data = { var data = {
topic: channel, topic: channel,
data: post.content, data: post.content,
from: post.meta.from.name, from: post.meta.from.name,
time: (new Date(post.meta.ts)) time: (new Date(post.meta.ts))
}; };
promise.cb(post.content, data, post); promise.cb(post.content, data, post);
});
}); });
});
return promise; return promise;
}; };
module.exports = EmbarkJS; module.exports = EmbarkJS;

View File

@ -1,15 +1,12 @@
var program = require('commander'); var program = require('commander');
var colors = require('colors'); var colors = require('colors');
var shelljs = require('shelljs'); var shelljs = require('shelljs');
var promptly = require('promptly'); var Embark = require('../lib/index');
var path = require('path');
var Cmd = function(Embark) { var Cmd = function() {
this.Embark = Embark;
program.version(Embark.version); program.version(Embark.version);
}; };
Cmd.prototype.process = function(args) { Cmd.prototype.process = function(args) {
this.newApp(); this.newApp();
this.demo(); this.demo();
@ -30,64 +27,40 @@ Cmd.prototype.process = function(args) {
}; };
Cmd.prototype.newApp = function() { 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 program
.command('new [name]') .command('new [name]')
.description('new application') .description('new application')
.action(function (name, options) { .action(function(name, options) {
var parentDirectory = path.dirname(__dirname).split("/").pop(); if (name === undefined) {
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);
}
});
}
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() { Cmd.prototype.demo = function() {
var self = this;
program program
.command('demo') .command('demo')
.description('create a working dapp with a SimpleStorage contract') .description('create a working dapp with a SimpleStorage contract')
.action(function() { .action(function() {
self.Embark.generateTemplate('demo', './', 'embark_demo'); Embark.generateTemplate('demo', './', 'embark_demo');
}); });
}; };
Cmd.prototype.build = function() { Cmd.prototype.build = function() {
var self = this;
program program
.command('build [environment]') .command('build [environment]')
.description('deploy and build dapp at dist/ (default: development)') .description('deploy and build dapp at dist/ (default: development)')
.action(function(env, options) { .action(function(env, options) {
self.Embark.build({env: env || 'development'}); Embark.build({env: env || 'development'});
}); });
}; };
Cmd.prototype.run = function() { Cmd.prototype.run = function() {
var self = this;
program program
.command('run [environment]') .command('run [environment]')
.option('-p, --port [port]', 'port to run the dev webserver (default: 8000)') .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') .option('--no-color', 'no colors in case it\'s needed for compatbility purposes')
.description('run dapp (default: development)') .description('run dapp (default: development)')
.action(function(env, options) { .action(function(env, options) {
self.Embark.run({ Embark.run({
env: env || 'development', env: env || 'development',
serverPort: options.port, serverPort: options.port,
serverHost: options.host, serverHost: options.host,
@ -108,22 +81,20 @@ Cmd.prototype.run = function() {
}; };
Cmd.prototype.blockchain = function() { Cmd.prototype.blockchain = function() {
var self = this;
program program
.command('blockchain [environment]') .command('blockchain [environment]')
.option('-c, --client [client]', 'Use a specific ethereum client or simulator (supported: geth, parity, ethersim, testrpc') .option('-c, --client [client]', 'Use a specific ethereum client or simulator (supported: geth, parity, ethersim, testrpc')
.description('run blockchain server (default: development)') .description('run blockchain server (default: development)')
.action(function(env ,options) { .action(function(env ,options) {
self.Embark.initConfig(env || 'development', { Embark.initConfig(env || 'development', {
embarkConfig: 'embark.json', embarkConfig: 'embark.json',
interceptLogs: false interceptLogs: false
}); });
self.Embark.blockchain(env || 'development', options.client || 'geth'); Embark.blockchain(env || 'development', options.client || 'geth');
}); });
}; };
Cmd.prototype.simulator = function() { Cmd.prototype.simulator = function() {
var self = this;
program program
.command('simulator [environment]') .command('simulator [environment]')
.description('run a fast ethereum rpc simulator') .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('-p, --port [port]', 'port to run the rpc simulator (default: 8000)')
.option('-h, --host [host]', 'host to run the rpc simulator (default: localhost)') .option('-h, --host [host]', 'host to run the rpc simulator (default: localhost)')
.action(function(env, options) { .action(function(env, options) {
self.Embark.initConfig(env || 'development', { Embark.initConfig(env || 'development', {
embarkConfig: 'embark.json', embarkConfig: 'embark.json',
interceptLogs: false 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() { Cmd.prototype.upload = function() {
var self = this;
program program
.command('upload [platform] [environment]') .command('upload [platform] [environment]')
.description('upload your dapp to a decentralized storage. possible options: ipfs, swarm (e.g embark upload swarm)') .description('upload your dapp to a decentralized storage. possible options: ipfs, swarm (e.g embark upload swarm)')
.action(function(platform, env, options) { .action(function(platform, env, options) {
// TODO: get env in cmd line as well // TODO: get env in cmd line as well
self.Embark.initConfig(env || 'development', { Embark.initConfig(env || 'development', {
embarkConfig: 'embark.json', interceptLogs: false embarkConfig: 'embark.json', interceptLogs: false
}); });
self.Embark.upload(platform); Embark.upload(platform);
}); });
}; };

View File

@ -1,5 +1,5 @@
var fs = require('../core/fs.js'); var fs = require('../core/fs.js');
var utils = require('../core/utils.js'); var utils = require('../utils/utils.js');
var TemplateGenerator = function(templateName) { var TemplateGenerator = function(templateName) {
this.templateName = templateName; this.templateName = templateName;

View File

@ -1,18 +1,7 @@
/*jshint esversion: 6, loopfunc: true */ /*jshint esversion: 6, loopfunc: true */
var async = require('async'); var async = require('../utils/async_extend.js');
var SolcW = require('./solcW.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) { var Compiler = function(options) {
this.plugins = options.plugins; this.plugins = options.plugins;
this.logger = options.logger; this.logger = options.logger;

View File

@ -1,5 +1,4 @@
var async = require('async'); var async = require('async');
var Web3 = require('web3');
var Deploy = require('./deploy.js'); var Deploy = require('./deploy.js');
var ContractsManager = require('./contracts.js'); var ContractsManager = require('./contracts.js');
@ -33,21 +32,25 @@ DeployManager.prototype.deployContracts = function(done) {
}); });
contractsManager.build(callback); contractsManager.build(callback);
}, },
function connectWithWeb3(contractsManager, callback) { function checkWeb3IsConnected(contractsManager, callback) {
var web3; if (!self.web3) {
if (self.web3) { return callback(Error("no web3 instance found"));
web3 = self.web3; }
} else { if (self.web3.currentProvider.isConnected !== undefined && !self.web3.isConnected()) {
web3 = new Web3(); self.logger.error(("Couldn't connect to an Ethereum node are you sure it's on?").red);
var web3Endpoint = 'http://' + self.config.blockchainConfig.rpcHost + ':' + self.config.blockchainConfig.rpcPort; self.logger.info("make sure you have an Ethereum node or simulator running. e.g 'embark blockchain'".magenta);
web3.setProvider(new web3.providers.HttpProvider(web3Endpoint)); return callback(Error("error connecting to blockchain node"));
if (!web3.isConnected()) { }
self.logger.error(("Couldn't connect to " + web3Endpoint.underline + " are you sure it's on?").red); if (self.web3.currentProvider.isConnected === undefined) {
self.logger.info("make sure you have an ethereum node or simulator running. e.g 'embark blockchain'".magenta); self.web3.version.getNode(function(err, version) {
return callback(Error("error connecting to blockchain node")); 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) { function setDefaultAccount(contractsManager, web3, callback) {
web3.eth.getAccounts(function(err, accounts) { web3.eth.getAccounts(function(err, accounts) {

View File

@ -1,4 +1,4 @@
var utils = require('../core/utils.js'); var utils = require('../utils/utils.js');
var solcProcess; var solcProcess;
var compilerLoaded = false; var compilerLoaded = false;

View File

@ -1,6 +1,6 @@
var fs = require('./fs.js'); var fs = require('./fs.js');
var Plugins = require('./plugins.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 // TODO: add wrapper for fs so it can also work in the browser
// can work with both read and save // can work with both read and save

View File

@ -1,11 +1,14 @@
var http = require('http');
var Web3 = require('web3');
var utils = require('../utils/utils.js');
var Events = require('./events.js'); var Events = require('./events.js');
var Logger = require('./logger.js'); var Logger = require('./logger.js');
var Config = require('./config.js'); var Config = require('./config.js');
var DeployManager = require('../contracts/deploy_manager.js'); var DeployManager = require('../contracts/deploy_manager.js');
var ABIGenerator = require('../contracts/abi.js'); var ABIGenerator = require('../contracts/abi.js');
var Dashboard = require('../dashboard/dashboard.js'); var ServicesMonitor = require('./services_monitor.js');
var ServicesMonitor = require('./services.js');
var Pipeline = require('../pipeline/pipeline.js'); var Pipeline = require('../pipeline/pipeline.js');
var Server = require('../pipeline/server.js'); var Server = require('../pipeline/server.js');
var Watch = require('../pipeline/watch.js'); var Watch = require('../pipeline/watch.js');
@ -19,24 +22,44 @@ var Engine = function(options) {
}; };
Engine.prototype.init = function(_options) { Engine.prototype.init = function(_options) {
var self = this;
var options = _options || {}; var options = _options || {};
this.events = new Events(); this.events = new Events();
this.logger = options.logger || new Logger({logLevel: 'debug'}); this.logger = options.logger || new Logger({logLevel: 'debug'});
this.config = new Config({env: this.env, logger: this.logger, events: this.events}); this.config = new Config({env: this.env, logger: this.logger, events: this.events});
this.config.loadConfigFiles({embarkConfig: this.embarkConfig, interceptLogs: this.interceptLogs}); this.config.loadConfigFiles({embarkConfig: this.embarkConfig, interceptLogs: this.interceptLogs});
this.plugins = this.config.plugins; 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) { Engine.prototype.startService = function(serviceName, _options) {
var options = _options || {}; var options = _options || {};
var services = { var services = {
"monitor": this.monitorService,
"pipeline": this.pipelineService, "pipeline": this.pipelineService,
"abi": this.abiService, "abi": this.abiService,
"deployment": this.deploymentService, "deployment": this.deploymentService,
"fileWatcher": this.fileWatchService, "fileWatcher": this.fileWatchService,
"webServer": this.webServerService "webServer": this.webServerService,
"ipfs": this.ipfsService,
"web3": this.web3Service
}; };
var service = services[serviceName]; var service = services[serviceName];
@ -50,18 +73,6 @@ Engine.prototype.startService = function(serviceName, _options) {
return service.apply(this, [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) { Engine.prototype.pipelineService = function(options) {
var self = this; var self = this;
this.logger.setStatus("Building Assets"); this.logger.setStatus("Building Assets");
@ -77,13 +88,15 @@ Engine.prototype.pipelineService = function(options) {
pipeline.build(abi); pipeline.build(abi);
self.events.emit('outputDone'); self.events.emit('outputDone');
}); });
this.events.on('file-event', function(fileType, path) { // TODO: still need to redeploy contracts because the original contracts
if (fileType === 'asset') { // config is being corrupted
self.config.reloadConfig(); //this.events.on('file-event', function(fileType, path) {
pipeline.build(self.abi, path); // if (fileType === 'asset') {
self.events.emit('outputDone'); // self.config.reloadConfig();
} // pipeline.build(self.abi, path);
}); // self.events.emit('outputDone');
// }
//});
}; };
Engine.prototype.abiService = function(options) { Engine.prototype.abiService = function(options) {
@ -111,7 +124,7 @@ Engine.prototype.abiService = function(options) {
Engine.prototype.deploymentService = function(options) { Engine.prototype.deploymentService = function(options) {
var self = this; var self = this;
this.deployManager = new DeployManager({ this.deployManager = new DeployManager({
web3: options.web3, web3: options.web3 || self.web3,
trackContracts: options.trackContracts, trackContracts: options.trackContracts,
config: this.config, config: this.config,
logger: this.logger, logger: this.logger,
@ -120,10 +133,12 @@ Engine.prototype.deploymentService = function(options) {
}); });
this.events.on('file-event', function(fileType, path) { 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.config.reloadConfig();
self.deployManager.deployContracts(function() {}); self.deployManager.deployContracts(function() {});
} //}
}); });
}; };
@ -134,15 +149,96 @@ Engine.prototype.fileWatchService = function(options) {
}; };
Engine.prototype.webServerService = function(options) { Engine.prototype.webServerService = function(options) {
var self = this;
var webServerConfig = this.config.webServerConfig; var webServerConfig = this.config.webServerConfig;
if (!webServerConfig.enabled) { return; } if (!webServerConfig.enabled) { return; }
var host = options.host || webServerConfig.host;
var port = options.port || webServerConfig.port;
this.logger.setStatus("Starting Server"); this.logger.setStatus("Starting Server");
var server = new Server({ var server = new Server({
logger: this.logger, logger: this.logger,
host: options.host || webServerConfig.host, host: host,
port: options.port || webServerConfig.port 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; module.exports = Engine;

View File

@ -1,5 +1,5 @@
var fs = require('fs-extra'); var fs = require('fs-extra');
var utils = require('./utils.js'); var utils = require('../utils/utils.js');
function mkdirpSync() { function mkdirpSync() {
return fs.mkdirpSync.apply(fs.mkdirpSync, arguments); return fs.mkdirpSync.apply(fs.mkdirpSync, arguments);

View File

@ -5,7 +5,6 @@ var Logger = function(options) {
this.logLevel = options.logLevel || 'info'; this.logLevel = options.logLevel || 'info';
this.logFunction = options.logFunction || console.log; this.logFunction = options.logFunction || console.log;
this.contractsState = options.contractsState || function() {}; this.contractsState = options.contractsState || function() {};
this.availableServices = options.availableServices || function() {};
this.setStatus = options.setStatus || console.log; this.setStatus = options.setStatus || console.log;
}; };

View File

@ -1,6 +1,6 @@
/*jshint esversion: 6, loopfunc: true */ /*jshint esversion: 6, loopfunc: true */
var fs = require('./fs.js'); 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.. // TODO: pass other params like blockchainConfig, contract files, etc..
var Plugin = function(options) { var Plugin = function(options) {
@ -17,6 +17,7 @@ var Plugin = function(options) {
this.contractsConfigs = []; this.contractsConfigs = [];
this.contractsFiles = []; this.contractsFiles = [];
this.compilers = []; this.compilers = [];
this.serviceChecks = [];
this.pluginTypes = []; this.pluginTypes = [];
this.logger = options.logger; this.logger = options.logger;
this.events = options.events; this.events = options.events;
@ -98,6 +99,11 @@ Plugin.prototype.registerConsoleCommand = function(cb) {
this.pluginTypes.push('console'); 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) { Plugin.prototype.has = function(pluginType) {
return this.pluginTypes.indexOf(pluginType) >= 0; return this.pluginTypes.indexOf(pluginType) >= 0;
}; };

View File

@ -1,5 +1,5 @@
var Plugin = require('./plugin.js'); var Plugin = require('./plugin.js');
var utils = require('./utils.js'); var utils = require('../utils/utils.js');
var Plugins = function(options) { var Plugins = function(options) {
this.pluginList = options.plugins || []; this.pluginList = options.plugins || [];

View File

@ -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;

View File

@ -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;

View File

@ -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() { var getSimulator = function() {
try { try {
var sim = require('ethereumjs-testrpc'); return require('ethereumjs-testrpc');
return sim;
} catch (e) { } catch (e) {
if (e.code === 'MODULE_NOT_FOUND') { if (e.code === 'MODULE_NOT_FOUND') {
console.log('Simulator not found; Please install it with "npm install ethereumjs-testrpc --save"'); 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) { var Test;
this.options = options || {}; Test = (function (options) {
var simOptions = this.options.simulatorOptions || {}; 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({ function newWebThree() {
env: this.options.env || 'test', try {
// TODO: confi will need to detect if this is a obj var Web3 = require('web3');
embarkConfig: this.options.embarkConfig || 'embark.json', var web3 = new Web3();
interceptLogs: false web3.setProvider(sim.provider(opts.simulatorOptions));
}); return web3;
} catch (e) {
throw new Error(e);
}
}
this.engine.init({ function deployAll(contractsConfig, cb) {
logger: new TestLogger({logLevel: this.options.logLevel || 'debug'}) var RunCode = require('./runCode.js');
}); var self = this;
this.sim = getSimulator(); function newEngine () {
this.web3 = new Web3(); var Engine = require('./engine.js');
this.web3.setProvider(this.sim.provider(simOptions)); 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) { self.web3 = newWebThree();
var self = this; self.engine = newEngine();
self.engine.init();
async.waterfall([ async.waterfall([
function getConfig(callback) { function getConfig(callback) {
self.engine.config.contractsConfig = {contracts: contractsConfig}; self.engine.config.contractsConfig = {contracts: contractsConfig};
callback(); callback();
@ -71,32 +69,39 @@ Test.prototype.deployAll = function(contractsConfig, cb) {
callback(); callback();
}, },
function deploy(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); callback(null, vanillaABI);
}); });
self.engine.deployManager.deployContracts(function(err, result) { self.engine.deployManager.deployContracts(function (err, result) {
if (err) { if (err) {
console.log(err); console.log(err);
callback(err); callback(err);
} }
}); });
} }
], function(err, result) { ], 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) {
if (err) { if (err) {
throw new Error(err); console.log("got error");
process.exit();
} }
self.web3.eth.defaultAccount = accounts[0]; // this should be part of the waterfall and not just something done at the
RunCode.doEval(result, self.web3); // jshint ignore:line // end
cb(); 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; module.exports = Test;

View File

@ -1,4 +1,4 @@
var utils = require('../core/utils.js'); var utils = require('../utils/utils.js');
var RunCode = require('../core/runCode.js'); var RunCode = require('../core/runCode.js');
var Console = function(options) { var Console = function(options) {

View File

@ -23,7 +23,6 @@ Dashboard.prototype.start = function(done) {
monitor = new Monitor({env: self.env, console: console}); monitor = new Monitor({env: self.env, console: console});
self.logger.logFunction = monitor.logEntry; self.logger.logFunction = monitor.logEntry;
self.logger.contractsState = monitor.setContracts; self.logger.contractsState = monitor.setContracts;
self.logger.availableServices = monitor.availableServices;
self.logger.setStatus = monitor.setStatus.bind(monitor); self.logger.setStatus = monitor.setStatus.bind(monitor);
self.logger.info('========================'.bold.green); self.logger.info('========================'.bold.green);

View File

@ -40,7 +40,13 @@ function Dashboard(options) {
this.input.focus(); 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.progress.setContent(services.join('\n'));
this.screen.render(); this.screen.render();
}; };

View File

@ -1,64 +1,49 @@
/*jshint esversion: 6 */ /*jshint esversion: 6 */
var async = require('async'); 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 colors = require('colors');
var Engine = require('./core/engine.js'); 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 IPFS = require('./upload/ipfs.js');
var Swarm = require('./upload/swarm.js'); var Swarm = require('./upload/swarm.js');
var Cmd = require('./cmd.js');
var version = require('../package.json').version; 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.events = new Events();
this.logger = new Logger({logLevel: 'debug'}); this.logger = new Logger({logLevel: 'debug'});
this.config = new Config({env: env, logger: this.logger, events: this.events}); this.config = new Config({env: env, logger: this.logger, events: this.events});
this.config.loadConfigFiles(options); this.config.loadConfigFiles(options);
this.plugins = this.config.plugins; this.plugins = this.config.plugins;
}, }
blockchain: function(env, client) { function blockchain (env, client) {
var blockchain = Blockchain(this.config.blockchainConfig, client, env); return require('./cmds/blockchain/blockchain.js')(this.config.blockchainConfig, client, env).run();
blockchain.run(); }
},
simulator: function(options) { function simulator (options) {
var Simulator = require('./cmds/simulator.js');
var simulator = new Simulator({blockchainConfig: this.config.blockchainConfig}); var simulator = new Simulator({blockchainConfig: this.config.blockchainConfig});
simulator.run(options); 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); var templateGenerator = new TemplateGenerator(templateName);
templateGenerator.generate(destinationFolder, name); templateGenerator.generate(destinationFolder, name);
}, }
function run (options) {
var Dashboard = require('./dashboard/dashboard.js');
run: function(options) {
var self = this;
var env = options.env; var env = options.env;
var engine = new Engine({ var engine = new Engine({
@ -90,6 +75,11 @@ var Embark = {
dashboard.console.runCode(abi); dashboard.console.runCode(abi);
}); });
engine.logger.info('dashboard start');
engine.events.on('servicesState', function(servicesState) {
dashboard.monitor.availableServices(servicesState);
});
callback(); callback();
}); });
}, },
@ -99,16 +89,20 @@ var Embark = {
engine.logger.info("loaded plugins: " + pluginList.join(", ")); engine.logger.info("loaded plugins: " + pluginList.join(", "));
} }
if (options.useDashboard) { engine.startMonitor();
engine.startService("monitor", { engine.startService("web3");
serverHost: options.serverHost,
serverPort: options.serverPort,
runWebserver: options.runWebserver
});
}
engine.startService("pipeline"); engine.startService("pipeline");
engine.startService("abi"); engine.startService("abi");
engine.startService("deployment"); 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.deployManager.deployContracts(function() {
engine.startService("fileWatcher"); engine.startService("fileWatcher");
@ -131,10 +125,9 @@ var Embark = {
engine.events.emit('firstDeploymentDone'); engine.events.emit('firstDeploymentDone');
} }
}); });
}, }
build: function(options) { function build (options) {
var self = this;
var engine = new Engine({ var engine = new Engine({
env: options.env, env: options.env,
@ -169,14 +162,15 @@ var Embark = {
// needed due to child processes // needed due to child processes
process.exit(); process.exit();
}); });
}, }
initTests: function(options) { function initTests (options) {
var Test = require('./core/test.js');
return new Test(options); return new Test(options);
}, }
// TODO: should deploy if it hasn't already // TODO: should deploy if it hasn't already
upload: function(platform) { function upload (platform) {
if (platform === 'ipfs') { if (platform === 'ipfs') {
var ipfs = new IPFS({buildDir: 'dist/', plugins: this.plugins, storageConfig: this.config.storageConfig}); var ipfs = new IPFS({buildDir: 'dist/', plugins: this.plugins, storageConfig: this.config.storageConfig});
ipfs.deploy(); 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; module.exports = Embark;

14
lib/utils/async_extend.js Normal file
View File

@ -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;

View File

@ -1,42 +1,41 @@
var Embark = require('../lib/index'); var Embark = require('../lib/index');
var Cmd = require('../lib/cmd'); 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 () { describe('embark.Cmd', function () {
this.timeout(0);
var cmd = new Cmd(Embark); var cmd = new Cmd(Embark);
var pl = passingLines();
var appname = 'deleteapp';
describe('#new', function () { describe('#new', function () {
this.timeout(0); it('it should not create an app without a name', function (done) {
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) {
cmd.newApp(undefined, function (output) { cmd.newApp(undefined, function (output) {
var lines = output.split('\n'); var lines = output.split('\n');
console.log(lines); assert.equal(lines[0], 'please specify your app Name');
process.stdin.write(appname + '\n'); assert.equal(lines[1], 'e.g embark new MyApp');
assert.equal(lines[0], pl[0]); assert.equal(lines[2], 'e.g embark new --help for more information');
done();
}); });
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();
// });
// })
// })
}); });

View File

@ -14,6 +14,7 @@
"buildDir": "dist/", "buildDir": "dist/",
"config": "config/", "config": "config/",
"plugins": { "plugins": {
"embark-babel": {"files": ["**/*.js", "**/*.jsx", "!**/_vendor/*.js"]} "embark-babel": {"files": ["**/*.js", "**/*.jsx", "!**/_vendor/*.js"]},
"embark-service": {}
} }
} }

View File

@ -0,0 +1,5 @@
module.exports = function(embark) {
embark.registerServiceCheck('PluginService', function(cb) {
cb({name: "ServiceName", status: "green"});
});
};

View File

@ -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"
}

View File

@ -10,11 +10,12 @@
"license": "ISC", "license": "ISC",
"homepage": "", "homepage": "",
"devDependencies": { "devDependencies": {
"embark": "../", "embark": "file:../",
"mocha": "^2.2.5" "mocha": "^2.2.5"
}, },
"dependencies": { "dependencies": {
"embark-babel": "^1.0.0", "embark-babel": "^1.0.0",
"embark-service": "./extensions/embark-service",
"ethereumjs-testrpc": "^3.0.3" "ethereumjs-testrpc": "^3.0.3"
} }
} }

View File

@ -1,10 +1,9 @@
var assert = require('assert'); var assert = require('assert');
var Embark = require('embark'); var EmbarkSpec = require('embark/lib/core/test.js');
var EmbarkSpec = Embark.initTests();
var web3 = EmbarkSpec.web3;
describe("AnotherStorage", function() { describe("AnotherStorage", function() {
before(function(done) { before(function(done) {
this.timeout(0);
var contractsConfig = { var contractsConfig = {
"SimpleStorage": { "SimpleStorage": {
args: [100] args: [100]

View File

@ -1,10 +1,9 @@
var assert = require('assert'); var assert = require('assert');
var Embark = require('embark'); var EmbarkSpec = require('embark/lib/core/test.js');
var EmbarkSpec = Embark.initTests();
var web3 = EmbarkSpec.web3;
describe("SimpleStorage", function() { describe("SimpleStorage", function() {
before(function(done) { before(function(done) {
this.timeout(0);
var contractsConfig = { var contractsConfig = {
"SimpleStorage": { "SimpleStorage": {
args: [100] args: [100]

View File

@ -1,10 +1,9 @@
var assert = require('assert'); var assert = require('assert');
var Embark = require('embark'); var EmbarkSpec = require('embark/lib/core/test.js');
var EmbarkSpec = Embark.initTests();
var web3 = EmbarkSpec.web3;
describe("Token", function() { describe("Token", function() {
before(function(done) { before(function(done) {
this.timeout(0);
var contractsConfig = { var contractsConfig = {
"SimpleStorage": { "SimpleStorage": {
args: [100] args: [100]