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
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.

View File

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

View File

@ -6,6 +6,6 @@
</head>
<body>
<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>
</html>

View File

@ -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;
// });
// });
//
//});
// });

View File

@ -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() {

View File

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

View File

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

View File

@ -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) {});

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@ -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) {

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

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() {
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;

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 Console = function(options) {

View File

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

View File

@ -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();
};

View File

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

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 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();
// });
// })
// })
});

View File

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

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

View File

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

View File

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

View File

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