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,6 +32,9 @@ $(document).ready(function() {
//EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'});
$("#storage .error").hide();
EmbarkJS.Storage.setProvider('ipfs')
.then(function(){
console.log('Provider set to IPFS');
EmbarkJS.Storage.ipfsConnection.ping()
.then(function(){
$("#status-storage").addClass('status-online');
@ -45,22 +48,39 @@ $(document).ready(function() {
$("#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);
}
});
});
$("#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);
}
});
});
$("#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);
}
});
});
$("#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"
]
}
}

View File

@ -2,56 +2,85 @@ var EmbarkJS =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports) {
/***/ (function(module, exports) {
/*jshint esversion: 6 */
//var Ipfs = require('./ipfs.js');
/*jshint esversion: 6 */
//var Ipfs = require('./ipfs.js');
var EmbarkJS = {
};
//=========================================================
// Embark Smart Contracts
//=========================================================
EmbarkJS.Contract = function(options) {
var EmbarkJS = {};
EmbarkJS.Contract = function(options) {
var self = this;
var i, abiElement;
@ -86,7 +115,7 @@ var EmbarkJS =
};
this._originalContractObject = ContractClass.at(this.address);
this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function (p) {
this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function(p) {
// TODO: check for forbidden properties
if (self.eventList.indexOf(p) >= 0) {
@ -148,9 +177,9 @@ var EmbarkJS =
}
return false;
});
};
};
EmbarkJS.Contract.prototype.deploy = function(args, _options) {
EmbarkJS.Contract.prototype.deploy = function(args, _options) {
var self = this;
var contractParams;
var options = _options || {};
@ -170,7 +199,11 @@ var EmbarkJS =
if (err) {
reject(err);
} else if (transaction.address !== undefined) {
resolve(new EmbarkJS.Contract({abi: self.abi, code: self.code, address: transaction.address}));
resolve(new EmbarkJS.Contract({
abi: self.abi,
code: self.code,
address: transaction.address
}));
}
});
@ -182,33 +215,80 @@ var EmbarkJS =
return promise;
};
};
EmbarkJS.IPFS = 'ipfs';
//=========================================================
// Embark Storage
//=========================================================
EmbarkJS.Storage = {
};
EmbarkJS.Storage = {};
EmbarkJS.Storage.setProvider = function(provider, options) {
if (provider === 'ipfs') {
this.currentStorage = EmbarkJS.Storage.IPFS;
if (options === undefined) {
this.ipfsConnection = IpfsApi('localhost', '5001');
} else {
this.ipfsConnection = IpfsApi(options.server, options.port);
}
} else {
throw Error('unknown provider');
}
};
EmbarkJS.Storage.Providers = {
IPFS: 'ipfs',
SWARM: 'swarm'
};
EmbarkJS.Storage.saveText = function(text) {
EmbarkJS.Storage.IPFS = {};
EmbarkJS.Storage.saveText = function(text) {
return this.currentStorage.saveText(text);
};
EmbarkJS.Storage.get = function(hash) {
return this.currentStorage.get(hash);
};
EmbarkJS.Storage.uploadFile = function(inputSelector) {
return this.currentStorage.uploadFile(inputSelector);
}
EmbarkJS.Storage.getUrl = function(hash) {
return this.currentStorage.getUrl(hash);
}
EmbarkJS.Storage.setProvider = function(provider, options) {
var self = this;
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 (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 {
@ -218,26 +298,43 @@ var EmbarkJS =
});
return promise;
};
};
EmbarkJS.Storage.uploadFile = function(inputSelector) {
var self = this;
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');
}
if (!this.ipfsConnection) {
this.setProvider('ipfs');
}
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 = self.ipfsConnection.Buffer.from(fileContent);
self.ipfsConnection.add(buffer, function(err, result) {
var buffer = EmbarkJS.Storage.ipfsConnection.Buffer.from(fileContent);
EmbarkJS.Storage.ipfsConnection.add(buffer, function(err, result) {
if (err) {
reject(err);
} else {
@ -249,35 +346,21 @@ var EmbarkJS =
});
return promise;
};
};
EmbarkJS.Storage.get = function(hash) {
var self = this;
// TODO: detect type, then convert if needed
//var ipfsHash = web3.toAscii(hash);
if (!this.ipfsConnection) {
this.setProvider('ipfs');
}
var promise = new Promise(function(resolve, reject) {
self.ipfsConnection.object.get([hash]).then(function(node) {
resolve(node.data);
});
});
return promise;
};
EmbarkJS.Storage.getUrl = function(hash) {
EmbarkJS.Storage.IPFS.getUrl = function(hash) {
//var ipfsHash = web3.toAscii(hash);
return 'http://localhost:8080/ipfs/' + hash;
};
};
EmbarkJS.Messages = {
};
//=========================================================
// Embark Messaging
//=========================================================
EmbarkJS.Messages.setProvider = function(provider, options) {
EmbarkJS.Messages = {};
EmbarkJS.Messages.setProvider = function(provider, options) {
var self = this;
var ipfs;
if (provider === 'whisper') {
@ -306,22 +389,21 @@ var EmbarkJS =
this.currentMessages.orbit = new Orbit(ipfs);
this.currentMessages.orbit.connect(web3.eth.accounts[0]);
} else {
throw Error('unknown provider');
throw Error('Unknown message provider');
}
};
};
EmbarkJS.Messages.sendMessage = function(options) {
EmbarkJS.Messages.sendMessage = function(options) {
return this.currentMessages.sendMessage(options);
};
};
EmbarkJS.Messages.listenTo = function(options) {
EmbarkJS.Messages.listenTo = function(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 data = options.data || options.payload;
var identity = options.identity || this.identity || web3.shh.newIdentity();
@ -359,9 +441,9 @@ var EmbarkJS =
};
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 = [];
@ -416,12 +498,11 @@ var EmbarkJS =
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 data = options.data || options.payload;
@ -445,9 +526,9 @@ var EmbarkJS =
var payload = JSON.stringify(data);
this.orbit.send(topics, data);
};
};
EmbarkJS.Messages.Orbit.listenTo = function(options) {
EmbarkJS.Messages.Orbit.listenTo = function(options) {
var self = this;
var topics = options.topic || options.topics;
@ -488,10 +569,10 @@ var EmbarkJS =
});
return promise;
};
};
module.exports = EmbarkJS;
module.exports = EmbarkJS;
/***/ }
/***/ })
/******/ ]);

View File

@ -1,8 +1,11 @@
/*jshint esversion: 6 */
//var Ipfs = require('./ipfs.js');
var EmbarkJS = {
};
//=========================================================
// Embark Smart Contracts
//=========================================================
var EmbarkJS = {};
EmbarkJS.Contract = function(options) {
var self = this;
@ -39,7 +42,7 @@ EmbarkJS.Contract = function(options) {
};
this._originalContractObject = ContractClass.at(this.address);
this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function (p) {
this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function(p) {
// TODO: check for forbidden properties
if (self.eventList.indexOf(p) >= 0) {
@ -123,7 +126,11 @@ EmbarkJS.Contract.prototype.deploy = function(args, _options) {
if (err) {
reject(err);
} else if (transaction.address !== undefined) {
resolve(new EmbarkJS.Contract({abi: self.abi, code: self.code, address: transaction.address}));
resolve(new EmbarkJS.Contract({
abi: self.abi,
code: self.code,
address: transaction.address
}));
}
});
@ -137,31 +144,78 @@ EmbarkJS.Contract.prototype.deploy = function(args, _options) {
return promise;
};
EmbarkJS.IPFS = 'ipfs';
//=========================================================
// Embark Storage
//=========================================================
EmbarkJS.Storage = {
EmbarkJS.Storage = {};
EmbarkJS.Storage.Providers = {
IPFS: 'ipfs',
SWARM: 'swarm'
};
EmbarkJS.Storage.IPFS = {};
EmbarkJS.Storage.saveText = function(text) {
return this.currentStorage.saveText(text);
};
EmbarkJS.Storage.get = function(hash) {
return this.currentStorage.get(hash);
};
EmbarkJS.Storage.uploadFile = function(inputSelector) {
return this.currentStorage.uploadFile(inputSelector);
};
EmbarkJS.Storage.getUrl = function(hash) {
return this.currentStorage.getUrl(hash);
};
EmbarkJS.Storage.setProvider = function(provider, options) {
if (provider === 'ipfs') {
this.currentStorage = EmbarkJS.Storage.IPFS;
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) {
this.ipfsConnection = IpfsApi('localhost', '5001');
self.ipfsConnection = IpfsApi('localhost', '5001');
} else {
this.ipfsConnection = IpfsApi(options.server, options.port);
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 {
throw Error('unknown provider');
reject('Unknown storage provider');
}
});
return promise;
};
EmbarkJS.Storage.saveText = function(text) {
var self = this;
if (!this.ipfsConnection) {
this.setProvider('ipfs');
}
EmbarkJS.Storage.IPFS.saveText = function(text) {
var promise = new Promise(function(resolve, reject) {
self.ipfsConnection.add((new self.ipfsConnection.Buffer(text)), function(err, result) {
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 {
@ -173,24 +227,41 @@ EmbarkJS.Storage.saveText = function(text) {
return promise;
};
EmbarkJS.Storage.uploadFile = function(inputSelector) {
var self = this;
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');
}
if (!this.ipfsConnection) {
this.setProvider('ipfs');
}
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 = self.ipfsConnection.Buffer.from(fileContent);
self.ipfsConnection.add(buffer, function(err, result) {
var buffer = EmbarkJS.Storage.ipfsConnection.Buffer.from(fileContent);
EmbarkJS.Storage.ipfsConnection.add(buffer, function(err, result) {
if (err) {
reject(err);
} else {
@ -204,31 +275,17 @@ EmbarkJS.Storage.uploadFile = function(inputSelector) {
return promise;
};
EmbarkJS.Storage.get = function(hash) {
var self = this;
// TODO: detect type, then convert if needed
//var ipfsHash = web3.toAscii(hash);
if (!this.ipfsConnection) {
this.setProvider('ipfs');
}
var promise = new Promise(function(resolve, reject) {
self.ipfsConnection.object.get([hash]).then(function(node) {
resolve(node.data);
});
});
return promise;
};
EmbarkJS.Storage.getUrl = function(hash) {
EmbarkJS.Storage.IPFS.getUrl = function(hash) {
//var ipfsHash = web3.toAscii(hash);
return 'http://localhost:8080/ipfs/' + hash;
};
EmbarkJS.Messages = {
};
//=========================================================
// Embark Messaging
//=========================================================
EmbarkJS.Messages = {};
EmbarkJS.Messages.setProvider = function(provider, options) {
var self = this;
@ -259,7 +316,7 @@ EmbarkJS.Messages.setProvider = function(provider, options) {
this.currentMessages.orbit = new Orbit(ipfs);
this.currentMessages.orbit.connect(web3.eth.accounts[0]);
} else {
throw Error('unknown provider');
throw Error('Unknown message provider');
}
};
@ -271,8 +328,7 @@ EmbarkJS.Messages.listenTo = function(options) {
return this.currentMessages.listenTo(options);
};
EmbarkJS.Messages.Whisper = {
};
EmbarkJS.Messages.Whisper = {};
EmbarkJS.Messages.Whisper.sendMessage = function(options) {
var topics = options.topic || options.topics;
@ -371,8 +427,7 @@ EmbarkJS.Messages.Whisper.listenTo = function(options) {
return promise;
};
EmbarkJS.Messages.Orbit = {
};
EmbarkJS.Messages.Orbit = {};
EmbarkJS.Messages.Orbit.sendMessage = function(options) {
var topics = options.topic || options.topics;

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();
.action(function(name, options) {
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() {
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);
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,28 +17,42 @@ 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',
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);
}
}
function deployAll(contractsConfig, cb) {
var RunCode = require('./runCode.js');
var self = this;
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: this.options.embarkConfig || 'embark.json',
embarkConfig: opts.embarkConfig || 'embark.json',
interceptLogs: false
});
}
this.engine.init({
logger: new TestLogger({logLevel: this.options.logLevel || 'debug'})
});
this.sim = getSimulator();
this.web3 = new Web3();
this.web3.setProvider(this.sim.provider(simOptions));
};
Test.prototype.deployAll = function(contractsConfig, cb) {
var self = this;
self.web3 = newWebThree();
self.engine = newEngine();
self.engine.init();
async.waterfall([
function getConfig(callback) {
@ -71,24 +69,24 @@ 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) {
], 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) {
self.web3.eth.getAccounts(function (err, accounts) {
if (err) {
throw new Error(err);
}
@ -97,6 +95,13 @@ Test.prototype.deployAll = function(contractsConfig, cb) {
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 () {
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) {
var cmd = new Cmd(Embark);
describe('#new', function () {
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]);
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]