Merge branch 'develop'

This commit is contained in:
Iuri Matias 2017-06-28 06:56:51 -04:00
commit 10106067a7
81 changed files with 6676 additions and 5740 deletions

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ test_app/.embark/development/
test_app/config/production/password
test_app/node_modules/
test_app/chains.json
.idea

View File

@ -1,8 +1,7 @@
language: node_js
node_js:
- "7"
- "6"
- "5"
- "4"
addons:
code_climate:
repo_token: 7454b1a666015e244c384d19f48c34e35d1ae58c3aa428ec542f10bbcb848358

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/

29
Class Hierarchy.mmd Normal file
View File

@ -0,0 +1,29 @@
Mind Map generated by NB MindMap plugin
> __version__=`1.1`,showJumps=`true`
---
# Embark
## Config
## CLI
## Engine
> leftSide=`true`
### Plugins
#### DefaultLogger
#### DefaultPipeline
### Services
## DefaultLogger
## Utils
> leftSide=`true`
## DeployManager

View File

@ -21,8 +21,16 @@ module.exports = (grunt) ->
mochaTest:
test:
src: ['test/**/*.js']
jshint:
all: ['bin/embark', 'lib/**/*.js', 'js/mine.js', 'js/embark.js']
all: ['bin/embark', 'lib/**/*.js']
options: grunt.file.readJSON('package.json').jshintConfig
with_overrides:
options:
undef: false
esversion: 5
files:
src: ['js/mine.js', 'js/embark.js']
grunt.loadTasks "tasks"
require('matchdep').filterAll(['grunt-*','!grunt-cli']).forEach(grunt.loadNpmTasks)

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)
@ -8,9 +9,9 @@ What is Embark
Embark is a framework that allows you to easily develop and deploy Decentralized Applications (DApps).
A Decentralized Application is serverless html5 application that uses one or more decentralized technologies.
A Decentralized Application is a serverless html5 application that uses one or more decentralized technologies.
Embark currently integrates with EVM blockchains (Ethereum), Decentralized Storages (IPFS), and Decentralizaed communication platforms (Whisper and Orbit). Swarm is supported for deployment.
Embark currently integrates with EVM blockchains (Ethereum), Decentralized Storages (IPFS), and Decentralized communication platforms (Whisper and Orbit). Swarm is supported for deployment.
With Embark you can:
@ -18,12 +19,12 @@ With Embark you can:
* Automatically deploy contracts and make them available in your JS code. Embark watches for changes, and if you update a contract, Embark will automatically redeploy the contracts (if needed) and the dapp.
* Contracts are available in JS with Promises.
* Do Test Driven Development with Contracts using Javascript.
* Keep track of deployed contracts, deploy only when truly needed.
* Keep track of deployed contracts; deploy only when truly needed.
* Manage different chains (e.g testnet, private net, livenet)
* Easily manage complex systems of interdependent contracts.
**Decentralized Storage (IPFS)**
* Easily Store & Retrieve Data on the DApp through EmbarkJS. Includin uploading and retrieving files.
* Easily Store & Retrieve Data on the DApp through EmbarkJS. Including uploading and retrieving files.
* Deploy the full application to IPFS or Swarm.
@ -41,20 +42,20 @@ 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)
Installation
======
Requirements: geth (1.5.8 or higher), node (6.9.1 or higher is recommended) and npm
Requirements: geth (1.6.5 or higher), node (6.9.1 or higher is recommended) and npm
Optional: testrpc (3.0 or higher) if using the simulator or the test functionality.
Further: depending on the dapp stack you choose: [IPFS](https://ipfs.io/)
@ -68,7 +69,7 @@ $ npm -g install ethereumjs-testrpc
See [Complete Installation Instructions](https://github.com/iurimatias/embark-framework/wiki/Installation).
**updating from embark 1**
**updating from Embark 1**
Embark's npm package has changed from ```embark-framework``` to ```embark```, this sometimes can create conflicts. To update first uninstall embark-framework 1 to avoid any conflicts. ```npm uninstall -g embark-framework``` then ```npm install -g embark```
@ -96,7 +97,7 @@ Alternatively, to use an ethereum rpc simulator simply run:
$ embark simulator
```
By default embark blockchain will mine a minimum amount of ether and will only mine when new transactions come in. This is quite usefull to keep a low CPU. The option can be configured at ```config/blockchain.json```. Note that running a real node requires at least 2GB of free ram, please take this into account if running it in a VM.
By default Embark blockchain will mine a minimum amount of ether and will only mine when new transactions come in. This is quite useful to keep a low CPU. The option can be configured at ```config/blockchain.json```. Note that running a real node requires at least 2GB of free ram, please take this into account if running it in a VM.
Then, in another command line:
@ -105,7 +106,7 @@ $ embark run
```
This will automatically deploy the contracts, update their JS bindings and deploy your DApp to a local server at http://localhost:8000
Note that if you update your code it will automatically be re-deployed, contracts included. There is no need to restart embark, refreshing the page on the browser will do.
Note that if you update your code, it will automatically be re-deployed, contracts included. There is no need to restart embark, refreshing the page on the browser will do.
Dashboard
=====
@ -114,20 +115,20 @@ Embark 2 comes with a terminal dashboard.
![Dashboard](http://i.imgur.com/s4OQZpu.jpg)
The dashboard will tell you the state of your contracts, the enviroment you are using, and what embark is doing at the moment.
The dashboard will tell you the state of your contracts, the environment you are using, and what Embark is doing at the moment.
**available services**
Available Services will display the services available to your dapp in green, if one of these is down then it will be displayed in red.
Available Services will display the services available to your dapp in green. If a service is down, then it will be displayed in red.
**logs and console**
There is a console at the bottom which can be used to interact with contracts or with embark itself. type ```help``` to see a list of available commands, more commands will be added with each version of Embark.
There is a console at the bottom which can be used to interact with contracts or with Embark itself. Type ```help``` to see a list of available commands. More commands will be added with each version of Embark.
Creating a new DApp
======
If you want to create a blank new app.
If you want to create a blank new app:
```Bash
$ embark new AppName
@ -144,13 +145,16 @@ 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
```
Solidity/Serpent files in the contracts directory will automatically be deployed with embark run. Changes in any files will automatically be reflected in app, changes to contracts will result in a redeployment and update of their JS Bindings
Solidity/Serpent files in the contracts directory will automatically be deployed with Embark run. Changes in any files will automatically be reflected in app, changes to contracts will result in a redeployment and update of their JS Bindings
Libraries and languages available
======
@ -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"
]
}
}
@ -274,7 +278,7 @@ You can now deploy many instances of the same contract. e.g
...
```
Contracts addresses can be defined, If an address is defined the contract wouldn't be deployed but its defined address will be used instead.
Contracts addresses can be defined. If an address is defined, Embark uses the defined address instead of deploying the contract.
```Json
@ -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
@ -337,7 +347,7 @@ EmbarkJS - Storage
**initialization**
The current available storage is IPFS. it can be initialized as
The current available storage is IPFS. It can be initialized as
```Javascript
EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'})
@ -422,7 +432,7 @@ Tests
You can run specs with ```embark test```, it will run any test files under ```test/```.
Embark includes a testing lib to fastly run & test your contracts in a EVM.
Embark includes a testing lib to rapidly run & test your contracts in a EVM.
```Javascript
# test/simple_storage_spec.js
@ -434,6 +444,7 @@ var web3 = EmbarkSpec.web3;
describe("SimpleStorage", function() {
before(function(done) {
this.timeout(0);
var contractsConfig = {
"SimpleStorage": {
args: [100]
@ -459,6 +470,7 @@ describe("SimpleStorage", function() {
});
});
```
Embark uses [Mocha](http://mochajs.org/) by default, but you can use any testing framework you want.
@ -521,20 +533,20 @@ To deploy a dapp to SWARM, all you need to do is run a local SWARM node and then
Plugins
======
It's possible to extend Embarks functionality with plugins. For example the following is possible:
It's possible to extend Embark's functionality with plugins. For example, the following is possible:
* plugin to add support for es6, jsx, coffescript, etc (``embark.registerPipeline``)
* plugin to add standard contracts or a contract framework (``embark.registerContractConfiguration`` and ``embark.addContractFile``)
* plugin to make some contracts available in all environments for use by other contracts or the dapp itself e.g a Token, a DAO, ENS, etc.. (``embark.registerContractConfiguration`` and ``embark.addContractFile``)
* plugin to add a libraries such as react or boostrap (``embark.addFileToPipeline``)
* plugin to add a libraries such as react or bootstrap (``embark.addFileToPipeline``)
* plugin to specify a particular web3 initialization for special provider uses (``embark.registerClientWeb3Provider``)
* plugin to create a different contract wrapper (``embark.registerContractsGeneration``)
* plugin to add new console commands (``embark.registerConsoleCommand``)
* plugin to add support for another contract language such as viper, LLL, etc (``embark.registerCompiler``)
For more information on how to develop your own plugin please see the [plugin documentation](http://embark.readthedocs.io/en/latest/plugins.html)
For more information on how to develop your own plugin, please see the [plugin documentation](http://embark.readthedocs.io/en/latest/plugins.html)
Donations
======
If you like Embark please consider donating to 0x8811FdF0F988f0CD1B7E9DE252ABfA5b18c1cDb1
If you like Embark, please consider donating to 0x8811FdF0F988f0CD1B7E9DE252ABfA5b18c1cDb1

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,4 +1,5 @@
{
"config": {},
"nonce": "0x0000000000000042",
"difficulty": "0x0",
"alloc": {

View File

@ -9,7 +9,7 @@
"license": "ISC",
"homepage": "",
"devDependencies": {
"embark": "^2.4.2",
"embark": "^2.5.0",
"mocha": "^2.2.5"
}
}

View File

@ -3,8 +3,9 @@ var Embark = require('embark');
var EmbarkSpec = Embark.initTests();
var web3 = EmbarkSpec.web3;
//describe("SimpleStorage", function() {
// describe("SimpleStorage", function() {
// before(function(done) {
// this.timeout(0);
// var contractsConfig = {
// "SimpleStorage": {
// args: [100, '0x123']
@ -29,4 +30,4 @@ var web3 = EmbarkSpec.web3;
// });
// });
//
//});
// });

View File

@ -77,6 +77,7 @@
</div>
<div role="tabpanel" class="tab-pane" id="communication">
<div class="error alert alert-danger" role="alert">The node you are using does not support Whisper</div>
<div class="errorVersion alert alert-danger" role="alert">The node uses an unsupported version of Whisper</div>
<div id="communication-controls">
<h3>Listen To channel</h3>
<div class="form-group form-inline listen">

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() {
@ -89,11 +114,15 @@ $(document).ready(function() {
$(document).ready(function() {
$("#communication .error").hide();
web3.version.getWhisper(function(err, res) {
web3.version.getWhisper(function(err, version) {
if (err) {
$("#communication .error").show();
$("#communication-controls").hide();
+ $("#status-communication").addClass('status-offline');
$("#status-communication").addClass('status-offline');
} else if (version >= 5) {
$("#communication .errorVersion").show();
$("#communication-controls").hide();
$("#status-communication").addClass('status-offline');
} else {
EmbarkJS.Messages.setProvider('whisper');
$("#status-communication").addClass('status-online');

View File

@ -1,4 +1,5 @@
{
"config": {},
"nonce": "0x0000000000000042",
"difficulty": "0x0",
"alloc": {

View File

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

View File

@ -5,6 +5,7 @@ var web3 = EmbarkSpec.web3;
describe("SimpleStorage", function() {
before(function(done) {
this.timeout(0);
var contractsConfig = {
"SimpleStorage": {
args: [100]

View File

@ -58,9 +58,9 @@ author = u'Iuri Matias'
# built documents.
#
# The short X.Y version.
version = u'2.4'
version = u'2.5'
# The full version, including alpha/beta/rc tags.
release = u'2.4.2'
release = u'2.5.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

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

@ -48,446 +48,530 @@ var EmbarkJS =
/*jshint esversion: 6 */
//var Ipfs = require('./ipfs.js');
var EmbarkJS = {
};
//=========================================================
// Embark Smart Contracts
//=========================================================
var EmbarkJS = {};
EmbarkJS.Contract = function(options) {
var self = this;
var i, abiElement;
var self = this;
var i, abiElement;
this.abi = options.abi;
this.address = options.address;
this.code = '0x' + options.code;
this.web3 = options.web3 || web3;
this.abi = options.abi;
this.address = options.address;
this.code = '0x' + options.code;
this.web3 = options.web3 || web3;
var ContractClass = this.web3.eth.contract(this.abi);
var ContractClass = this.web3.eth.contract(this.abi);
this.eventList = [];
this.eventList = [];
if (this.abi) {
for (i = 0; i < this.abi.length; i++) {
abiElement = this.abi[i];
if (abiElement.type === 'event') {
this.eventList.push(abiElement.name);
}
}
}
var messageEvents = function() {
this.cb = function() {};
};
messageEvents.prototype.then = function(cb) {
this.cb = cb;
};
messageEvents.prototype.error = function(err) {
return err;
};
this._originalContractObject = ContractClass.at(this.address);
this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function (p) {
// TODO: check for forbidden properties
if (self.eventList.indexOf(p) >= 0) {
self[p] = function() {
var promise = new messageEvents();
var args = Array.prototype.slice.call(arguments);
args.push(function(err, result) {
if (err) {
promise.error(err);
} else {
promise.cb(result);
}
});
self._originalContractObject[p].apply(self._originalContractObject[p], args);
return promise;
};
return true;
} else if (typeof self._originalContractObject[p] === 'function') {
self[p] = function(_args) {
var args = Array.prototype.slice.call(arguments);
var fn = self._originalContractObject[p];
var props = self.abi.find((x) => x.name == p);
var promise = new Promise(function(resolve, reject) {
args.push(function(err, transaction) {
promise.tx = transaction;
if (err) {
return reject(err);
if (this.abi) {
for (i = 0; i < this.abi.length; i++) {
abiElement = this.abi[i];
if (abiElement.type === 'event') {
this.eventList.push(abiElement.name);
}
}
}
var getConfirmation = function() {
self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) {
if (err) {
return reject(err);
}
var messageEvents = function() {
this.cb = function() {};
};
if (receipt !== null) {
return resolve(receipt);
}
messageEvents.prototype.then = function(cb) {
this.cb = cb;
};
setTimeout(getConfirmation, 1000);
});
messageEvents.prototype.error = function(err) {
return err;
};
this._originalContractObject = ContractClass.at(this.address);
this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function(p) {
// TODO: check for forbidden properties
if (self.eventList.indexOf(p) >= 0) {
self[p] = function() {
var promise = new messageEvents();
var args = Array.prototype.slice.call(arguments);
args.push(function(err, result) {
if (err) {
promise.error(err);
} else {
promise.cb(result);
}
});
self._originalContractObject[p].apply(self._originalContractObject[p], args);
return promise;
};
return true;
} else if (typeof self._originalContractObject[p] === 'function') {
self[p] = function(_args) {
var args = Array.prototype.slice.call(arguments);
var fn = self._originalContractObject[p];
var props = self.abi.find((x) => x.name == p);
if (typeof(transaction) !== "string" || props.constant) {
resolve(transaction);
} else {
getConfirmation();
}
});
var promise = new Promise(function(resolve, reject) {
args.push(function(err, transaction) {
promise.tx = transaction;
if (err) {
return reject(err);
}
fn.apply(fn, args);
});
var getConfirmation = function() {
self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) {
if (err) {
return reject(err);
}
return promise;
};
return true;
}
return false;
});
if (receipt !== null) {
return resolve(receipt);
}
setTimeout(getConfirmation, 1000);
});
};
if (typeof(transaction) !== "string" || props.constant) {
resolve(transaction);
} else {
getConfirmation();
}
});
fn.apply(fn, args);
});
return promise;
};
return true;
}
return false;
});
};
EmbarkJS.Contract.prototype.deploy = function(args, _options) {
var self = this;
var contractParams;
var options = _options || {};
var self = this;
var contractParams;
var options = _options || {};
contractParams = args || [];
contractParams = args || [];
contractParams.push({
from: this.web3.eth.accounts[0],
data: this.code,
gas: options.gas || 800000
});
var contractObject = this.web3.eth.contract(this.abi);
var promise = new Promise(function(resolve, reject) {
contractParams.push(function(err, transaction) {
if (err) {
reject(err);
} else if (transaction.address !== undefined) {
resolve(new EmbarkJS.Contract({abi: self.abi, code: self.code, address: transaction.address}));
}
contractParams.push({
from: this.web3.eth.accounts[0],
data: this.code,
gas: options.gas || 800000
});
// returns promise
// deploys contract
// wraps it around EmbarkJS.Contract
contractObject["new"].apply(contractObject, contractParams);
});
var contractObject = this.web3.eth.contract(this.abi);
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';
EmbarkJS.Contract.prototype.new = EmbarkJS.Contract.prototype.deploy;
EmbarkJS.Storage = {
EmbarkJS.Contract.prototype.at = function(address) {
return new EmbarkJS.Contract({ abi: this.abi, code: this.code, address: address });
};
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);
}
EmbarkJS.Contract.prototype.send = function(value, unit, _options) {
var options, wei;
if (typeof unit === 'object') {
options = unit;
wei = value;
} else {
throw Error('unknown provider');
options = _options || {};
wei = this.web3.toWei(value, unit);
}
options.to = this.address;
options.value = wei;
console.log(options);
this.web3.eth.sendTransaction(options);
};
//=========================================================
// Embark Storage
//=========================================================
EmbarkJS.Storage = {};
EmbarkJS.Storage.Providers = {
IPFS: 'ipfs',
SWARM: 'swarm'
};
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' && typeof(web3) === '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' && typeof(web3) === '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 if (web3.version.whisper >= 5) {
console.log("this version of whisper is not supported yet; try a version of geth bellow 1.6.1");
} 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.host, options.port);
}
this.currentMessages.orbit = new Orbit(ipfs);
if (typeof(web3) === "undefined") {
this.currentMessages.orbit.connect(Math.random().toString(36).substring(2));
} else {
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,446 +1,530 @@
/*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';
EmbarkJS.Contract.prototype.new = EmbarkJS.Contract.prototype.deploy;
EmbarkJS.Storage = {
EmbarkJS.Contract.prototype.at = function(address) {
return new EmbarkJS.Contract({ abi: this.abi, code: this.code, address: address });
};
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);
}
EmbarkJS.Contract.prototype.send = function(value, unit, _options) {
var options, wei;
if (typeof unit === 'object') {
options = unit;
wei = value;
} else {
throw Error('unknown provider');
options = _options || {};
wei = this.web3.toWei(value, unit);
}
options.to = this.address;
options.value = wei;
console.log(options);
this.web3.eth.sendTransaction(options);
};
//=========================================================
// Embark Storage
//=========================================================
EmbarkJS.Storage = {};
EmbarkJS.Storage.Providers = {
IPFS: 'ipfs',
SWARM: 'swarm'
};
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' && typeof(web3) === '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' && typeof(web3) === '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 if (web3.version.whisper >= 5) {
console.log("this version of whisper is not supported yet; try a version of geth bellow 1.6.1");
} 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.host, options.port);
}
this.currentMessages.orbit = new Orbit(ipfs);
if (typeof(web3) === "undefined") {
this.currentMessages.orbit.connect(Math.random().toString(36).substring(2));
} else {
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;

5636
js/web3.js

File diff suppressed because it is too large Load Diff

View File

@ -1,150 +1,170 @@
var program = require('commander');
var colors = require('colors');
var shelljs = require('shelljs');
let program = require('commander');
let colors = require('colors');
let shelljs = require('shelljs');
let promptly = require('promptly');
let path = require('path');
const Embark = require('../lib/index');
let embark = new Embark;
var Cmd = function(Embark) {
this.Embark = Embark;
program.version(Embark.version);
};
Cmd.prototype.process = function(args) {
this.newApp();
this.demo();
this.build();
this.run();
this.blockchain();
this.simulator();
this.test();
this.upload();
this.otherCommands();
//If no arguments are passed display help by default
if (!process.argv.slice(2).length) {
program.help();
class Cmd {
constructor() {
program.version(embark.version);
}
program.parse(args);
};
Cmd.prototype.newApp = function() {
var self = this;
program
.command('new [name]')
.description('new application')
.action(function(name, options) {
if (name === undefined) {
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(code);
process(args) {
this.newApp();
this.demo();
this.build();
this.run();
this.blockchain();
this.simulator();
this.test();
this.upload();
this.otherCommands();
//If no arguments are passed display help by default
if (!process.argv.slice(2).length) {
program.help();
}
self.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');
});
};
program.parse(args);
}
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'});
});
};
newApp(name) {
Cmd.prototype.run = function() {
var self = this;
program
.command('run [environment]')
.option('-p, --port [port]', 'port to run the dev webserver (default: 8000)')
.option('-b, --host [host]', 'host to run the dev webserver (default: localhost)')
.option('--noserver', 'disable the development webserver')
.option('--nodashboard', 'simple mode, disables the dashboard')
.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({
env: env || 'development',
serverPort: options.port,
serverHost: options.host,
runWebserver: !options.noserver,
useDashboard: !options.nodashboard
});
});
};
let 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');
}
};
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', {
embarkConfig: 'embark.json',
interceptLogs: false
});
self.Embark.blockchain(env || 'development', options.client || 'geth');
});
};
program
.command('new [name]')
.description('new application')
.action(function (name) {
if (name === undefined) {
return promptly.prompt("Name your app (default is embarkDApp):", {
default: "embarkDApp",
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
embark.generateTemplate('boilerplate', './', inputvalue);
}
});
} else {
embark.generateTemplate('boilerplate', './', name);
}
Cmd.prototype.simulator = function() {
var self = this;
program
.command('simulator [environment]')
.description('run a fast ethereum rpc simulator')
.option('--testrpc', 'use testrpc as the rpc simulator [default]')
.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', {
embarkConfig: 'embark.json',
interceptLogs: false
});
self.Embark.simulator({port: options.port, host: options.host});
});
};
});
}
Cmd.prototype.test = function() {
program
.command('test')
.description('run tests')
.action(function() {
shelljs.exec('mocha test/ --no-timeouts');
});
};
demo() {
program
.command('demo')
.description('create a working dapp with a SimpleStorage contract')
.action(function () {
embark.generateTemplate('demo', './', 'embark_demo');
});
}
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', {
embarkConfig: 'embark.json', interceptLogs: false
});
self.Embark.upload(platform);
});
};
build() {
program
.command('build [environment]')
.description('deploy and build dapp at dist/ (default: development)')
.action(function (env, options) {
embark.build({env: env || 'development'});
});
}
Cmd.prototype.otherCommands = function() {
program
.action(function(env){
console.log('unknown command "%s"'.red, env);
console.log("type embark --help to see the available commands");
process.exit(0);
});
};
run() {
program
.command('run [environment]')
.option('-p, --port [port]', 'port to run the dev webserver (default: 8000)')
.option('-b, --host [host]', 'host to run the dev webserver (default: localhost)')
.option('--noserver', 'disable the development webserver')
.option('--nodashboard', 'simple mode, disables the dashboard')
.option('--no-color', 'no colors in case it\'s needed for compatbility purposes')
.description('run dapp (default: development)')
.action(function (env, options) {
embark.run({
env: env || 'development',
serverPort: options.port,
serverHost: options.host,
runWebserver: !options.noserver,
useDashboard: !options.nodashboard
});
});
}
blockchain() {
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) {
embark.initConfig(env || 'development', {
embarkConfig: 'embark.json',
interceptLogs: false
});
embark.blockchain(env || 'development', options.client || 'geth');
});
}
simulator() {
program
.command('simulator [environment]')
.description('run a fast ethereum rpc simulator')
.option('--testrpc', 'use testrpc as the rpc simulator [default]')
.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) {
embark.initConfig(env || 'development', {
embarkConfig: 'embark.json',
interceptLogs: false
});
embark.simulator({port: options.port, host: options.host});
});
}
test() {
program
.command('test')
.description('run tests')
.action(function () {
shelljs.exec('mocha test');
});
}
upload() {
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
embark.initConfig(env || 'development', {
embarkConfig: 'embark.json', interceptLogs: false
});
embark.upload(platform);
});
}
otherCommands() {
program
.action(function (env) {
console.log('unknown command "%s"'.red, env);
console.log("type embark --help to see the available commands");
process.exit(0);
});
}
}
module.exports = Cmd;

View File

@ -35,9 +35,9 @@ var Blockchain = function(options) {
this.client = new options.client({config: this.config, env: this.env});
};
Blockchain.prototype.runCommand = function(cmd) {
Blockchain.prototype.runCommand = function(cmd, options) {
console.log(("running: " + cmd.underline).green);
return shelljs.exec(cmd);
return shelljs.exec(cmd, options);
};
Blockchain.prototype.run = function() {
@ -49,7 +49,7 @@ Blockchain.prototype.run = function() {
console.log("===============================================================================".magenta);
var address = this.initChainAndGetAddress();
this.client.mainCommand(address, function(cmd) {
self.runCommand(cmd);
self.runCommand(cmd, {async: true});
});
};
@ -65,7 +65,7 @@ Blockchain.prototype.initChainAndGetAddress = function() {
// check if an account already exists, create one if not, return address
result = this.runCommand(this.client.listAccountsCommand());
if (result.output === undefined || result.output === '' || result.output.indexOf("Fatal") >= 0) {
if (result.output === undefined || result.output.match(/{(\w+)}/) === null || result.output.indexOf("Fatal") >= 0) {
console.log("no accounts found".green);
if (this.config.genesisBlock) {
console.log("initializing genesis block".green);

View File

@ -1,164 +1,171 @@
var async = require('async');
let async = require('async');
// TODO: make all of this async
var GethCommands = function(options) {
this.config = options.config;
this.env = options.env || 'development';
this.name = "Go-Ethereum (https://github.com/ethereum/go-ethereum)";
this.geth_bin = this.config.geth_bin || "geth";
};
GethCommands.prototype.commonOptions = function() {
var config = this.config;
var cmd = "";
cmd += this.determineNetworkType(config);
if (config.datadir) {
cmd += "--datadir=\"" + config.datadir + "\" ";
class GethCommands {
constructor(options) {
this.config = options && options.hasOwnProperty('config') ? options.config : {};
this.env = options && options.hasOwnProperty('env') ? options.env : 'development';
this.name = "Go-Ethereum (https://github.com/ethereum/go-ethereum)";
this.geth_bin = this.config.geth_bin || "geth";
}
if (config.light) {
cmd += "--light ";
commonOptions() {
let config = this.config;
let cmd = "";
cmd += this.determineNetworkType(config);
if (config.datadir) {
cmd += "--datadir=\"" + config.datadir + "\" ";
}
if (config.light) {
cmd += "--light ";
}
if (config.fast) {
cmd += "--fast ";
}
if (config.account && config.account.password) {
cmd += "--password " + config.account.password + " ";
}
return cmd;
}
if (config.fast) {
cmd += "--fast ";
determineNetworkType(config) {
let cmd = "";
if (config.networkType === 'testnet') {
cmd += "--testnet ";
} else if (config.networkType === 'olympic') {
cmd += "--olympic ";
} else if (config.networkType === 'custom') {
cmd += "--networkid " + config.networkId + " ";
}
return cmd;
}
if (config.account && config.account.password) {
cmd += "--password " + config.account.password + " ";
initGenesisCommmand() {
let config = this.config;
let cmd = this.geth_bin + " " + this.commonOptions();
if (config.genesisBlock) {
cmd += "init \"" + config.genesisBlock + "\" ";
}
return cmd;
}
return cmd;
};
GethCommands.prototype.determineNetworkType = function(config) {
var cmd = "";
if (config.networkType === 'testnet') {
cmd += "--testnet ";
} else if (config.networkType === 'olympic') {
cmd += "--olympic ";
} else if (config.networkType === 'custom') {
cmd += "--networkid " + config.networkId + " ";
}
return cmd;
};
GethCommands.prototype.initGenesisCommmand = function() {
var config = this.config;
var cmd = this.geth_bin + " " + this.commonOptions();
if (config.genesisBlock) {
cmd += "init \"" + config.genesisBlock + "\" ";
newAccountCommand() {
return this.geth_bin + " " + this.commonOptions() + "account new ";
}
return cmd;
};
listAccountsCommand() {
return this.geth_bin + " " + this.commonOptions() + "account list ";
}
GethCommands.prototype.newAccountCommand = function() {
return this.geth_bin + " " + this.commonOptions() + "account new ";
};
determineRpcOptions(config) {
let cmd = "";
GethCommands.prototype.listAccountsCommand = function() {
return this.geth_bin + " " + this.commonOptions() + "account list ";
};
GethCommands.prototype.determineRpcOptions = function(config) {
var cmd = "";
cmd += "--port " + config.port + " ";
cmd += "--rpc ";
cmd += "--rpcport " + config.rpcPort + " ";
cmd += "--rpcaddr " + config.rpcHost + " ";
if (config.rpcCorsDomain) {
if (config.rpcCorsDomain === '*') {
cmd += "--port " + config.port + " ";
cmd += "--rpc ";
cmd += "--rpcport " + config.rpcPort + " ";
cmd += "--rpcaddr " + config.rpcHost + " ";
if (config.rpcCorsDomain) {
if (config.rpcCorsDomain === '*') {
console.log('==================================');
console.log('make sure you know what you are doing');
console.log('==================================');
}
cmd += "--rpccorsdomain=\"" + config.rpcCorsDomain + "\" ";
} else {
console.log('==================================');
console.log('make sure you know what you are doing');
console.log('warning: cors is not set');
console.log('==================================');
}
cmd += "--rpccorsdomain=\"" + config.rpcCorsDomain + "\" ";
} else {
console.log('==================================');
console.log('warning: cors is not set');
console.log('==================================');
return cmd;
}
return cmd;
};
mainCommand(address, done) {
let self = this;
let config = this.config;
let rpc_api = (this.config.rpcApi || ['eth', 'web3', 'net']);
GethCommands.prototype.mainCommand = function(address, done) {
var self = this;
var config = this.config;
var rpc_api = (this.config.rpcApi || ['eth', 'web3', 'net']);
async.series([
function commonOptions(callback) {
var cmd = self.commonOptions();
callback(null, cmd);
},
function rpcOptions(callback) {
var cmd = self.determineRpcOptions(self.config);
callback(null, cmd);
},
function dontGetPeers(callback) {
if (config.nodiscover) {
return callback(null, "--nodiscover");
async.series([
function commonOptions(callback) {
let cmd = self.commonOptions();
callback(null, cmd);
},
function rpcOptions(callback) {
let cmd = self.determineRpcOptions(self.config);
callback(null, cmd);
},
function dontGetPeers(callback) {
if (config.nodiscover) {
return callback(null, "--nodiscover");
}
callback(null, "");
},
function vmDebug(callback) {
if (config.vmdebug) {
return callback(null, "--vmdebug");
}
callback(null, "");
},
function maxPeers(callback) {
let cmd = "--maxpeers " + config.maxpeers;
callback(null, cmd);
},
function mining(callback) {
if (config.mineWhenNeeded || config.mine) {
return callback(null, "--mine ");
}
callback("");
},
function bootnodes(callback) {
if (config.bootnodes && config.bootnodes !== "" && config.bootnodes !== []) {
return callback(null, "--bootnodes " + config.bootnodes);
}
callback("");
},
function whisper(callback) {
if (config.whisper) {
rpc_api.push('shh');
return callback(null, "--shh ");
}
callback("");
},
function rpcApi(callback) {
callback(null, '--rpcapi "' + rpc_api.join(',') + '"');
},
function accountToUnlock(callback) {
let accountAddress = "";
if(config.hasOwnProperty('address') && config.account.hasOwnProperty('address')) {
accountAddress = config.account.address;
} else {
accountAddress = address;
}
if (accountAddress) {
return callback(null, "--unlock=" + accountAddress);
}
callback(null, "");
},
function mineWhenNeeded(callback) {
if (config.mineWhenNeeded) {
return callback(null, "js .embark/" + self.env + "/js/mine.js");
}
callback(null, "");
}
callback(null, "");
},
function vmDebug(callback) {
if (config.vmdebug) {
return callback(null, "--vmdebug");
], function (err, results) {
if (err) {
throw new Error(err.message);
}
callback(null, "");
},
function maxPeers(callback) {
var cmd = "--maxpeers " + config.maxpeers;
callback(null, cmd);
},
function mining(callback) {
if (config.mineWhenNeeded || config.mine) {
return callback(null, "--mine ");
}
callback("");
},
function bootnodes(callback) {
if (config.bootnodes && config.bootnodes !== "" && config.bootnodes !== []) {
return callback(null, "--bootnodes " + config.bootnodes);
}
callback("");
},
function whisper(callback) {
if (config.whisper) {
rpc_api.push('shh');
return callback(null, "--shh ");
}
callback("");
},
function rpcApi(callback) {
callback(null, '--rpcapi "' + rpc_api.join(',') + '"');
},
function accountToUnlock(callback) {
var accountAddress = config.account.address || address;
if (accountAddress) {
return callback(null, "--unlock=" + accountAddress);
}
callback(null, "");
},
function mineWhenNeeded(callback) {
if (config.mineWhenNeeded) {
return callback(null, "js .embark/" + self.env + "/js/mine.js");
}
callback(null, "");
}
], function(err, results) {
if (err) {
throw new Error(err.message);
}
done(self.geth_bin + " " + results.join(" "));
});
};
done(self.geth_bin + " " + results.join(" "));
});
}
}
module.exports = GethCommands;

View File

@ -1,18 +1,20 @@
var shelljs = require('shelljs');
let shelljs = require('shelljs');
var Simulator = function(options) {
this.blockchainConfig = options.blockchainConfig;
};
class Simulator {
constructor(options) {
this.blockchainConfig = options.blockchainConfig;
}
Simulator.prototype.run = function(options) {
var cmds = [];
run(options) {
let cmds = [];
cmds.push("-p " + (this.blockchainConfig.rpcPort || options.port || 8545));
cmds.push("-h " + (this.blockchainConfig.rpcHost || options.host || 'localhost'));
cmds.push("-a " + (options.num || 10));
cmds.push("-p " + (this.blockchainConfig.rpcPort || options.port || 8545));
cmds.push("-h " + (this.blockchainConfig.rpcHost || options.host || 'localhost'));
cmds.push("-a " + (options.num || 10));
shelljs.exec('testrpc ' + cmds.join(' '));
};
shelljs.exec('testrpc ' + cmds.join(' '), {async : true});
}
}
module.exports = Simulator;

View File

@ -1,32 +1,35 @@
var fs = require('../core/fs.js');
var utils = require('../core/utils.js');
let fs = require('../core/fs.js');
let utils = require('../utils/utils.js');
var TemplateGenerator = function(templateName) {
this.templateName = templateName;
};
TemplateGenerator.prototype.generate = function(destinationFolder, name) {
var templatePath = fs.embarkPath(this.templateName);
console.log('Initializing Embark Template....'.green);
fs.copySync(templatePath, destinationFolder + name);
utils.cd(destinationFolder + name);
utils.sed('package.json', '%APP_NAME%', name);
console.log('Installing packages.. this can take a few seconds'.green);
utils.runCmd('npm install');
console.log('Init complete'.green);
console.log('\nApp ready at '.green + destinationFolder + name);
if (name === 'embark_demo') {
console.log('-------------------'.yellow);
console.log('Next steps:'.green);
console.log(('-> ' + ('cd ' + destinationFolder + name).bold.cyan).green);
console.log('-> '.green + 'embark blockchain'.bold.cyan + ' or '.green + 'embark simulator'.bold.cyan);
console.log('open another console in the same directory and run'.green);
console.log('-> '.green + 'embark run'.bold.cyan);
console.log('For more info go to http://github.com/iurimatias/embark-framework'.green);
class TemplateGenerator {
constructor(templateName) {
this.templateName = templateName;
}
};
generate(destinationFolder, name) {
let templatePath = fs.embarkPath(this.templateName);
console.log('Initializing Embark Template....'.green);
let fspath = utils.joinPath(destinationFolder, name);
fs.copySync(templatePath, fspath);
utils.cd(fspath);
utils.sed('package.json', '%APP_NAME%', name);
console.log('Installing packages.. this can take a few seconds'.green);
utils.runCmd('npm install');
console.log('Init complete'.green);
console.log('\nApp ready at '.green + fspath);
if (name === 'embark_demo') {
console.log('-------------------'.yellow);
console.log('Next steps:'.green);
console.log(('-> ' + ('cd ' + fspath).bold.cyan).green);
console.log('-> '.green + 'embark blockchain'.bold.cyan + ' or '.green + 'embark simulator'.bold.cyan);
console.log('open another console in the same directory and run'.green);
console.log('-> '.green + 'embark run'.bold.cyan);
console.log('For more info go to http://github.com/iurimatias/embark-framework'.green);
}
}
}
module.exports = TemplateGenerator;

View File

@ -1,138 +1,170 @@
var ABIGenerator = function(options) {
this.blockchainConfig = options.blockchainConfig || {};
this.storageConfig = options.storageConfig || {};
this.communicationConfig = options.communicationConfig || {};
this.contractsManager = options.contractsManager;
this.rpcHost = options.blockchainConfig && options.blockchainConfig.rpcHost;
this.rpcPort = options.blockchainConfig && options.blockchainConfig.rpcPort;
this.plugins = options.plugins;
};
ABIGenerator.prototype.generateProvider = function() {
var self = this;
var result = "";
var providerPlugins;
if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
return "";
class ABIGenerator {
constructor(options) {
this.blockchainConfig = options.blockchainConfig || {};
this.storageConfig = options.storageConfig || {};
this.communicationConfig = options.communicationConfig || {};
this.contractsManager = options.contractsManager;
this.rpcHost = options.blockchainConfig && options.blockchainConfig.rpcHost;
this.rpcPort = options.blockchainConfig && options.blockchainConfig.rpcPort;
this.plugins = options.plugins;
}
result += "\nvar whenEnvIsLoaded = function(cb) {";
result += "\n if (typeof window !== 'undefined' && window !== null) {";
result += "\n window.addEventListener('load', cb);";
result += "\n } else {";
result += "\n cb();";
result += "\n }";
result += "\n}";
generateProvider() {
let self = this;
let result = "";
let providerPlugins;
if (this.plugins) {
providerPlugins = this.plugins.getPluginsFor('clientWeb3Provider');
}
if (this.plugins && providerPlugins.length > 0) {
providerPlugins.forEach(function(plugin) {
result += plugin.generateProvider(self) + "\n";
});
} else {
result += "\nwhenEnvIsLoaded(function() {";
result += "\nif (typeof web3 !== 'undefined' && typeof Web3 !== 'undefined') {";
result += '\n\tweb3 = new Web3(web3.currentProvider);';
result += "\n} else if (typeof Web3 !== 'undefined') {";
result += '\n\tweb3 = new Web3(new Web3.providers.HttpProvider("http://' + this.rpcHost + ':' + this.rpcPort + '"));';
result += '\n}';
result += "\nweb3.eth.defaultAccount = web3.eth.accounts[0];";
result += '\n})';
}
return result;
};
ABIGenerator.prototype.generateContracts = function(useEmbarkJS) {
var self = this;
var result = "\n";
var contractsPlugins;
if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
return "";
}
if (this.plugins) {
contractsPlugins = this.plugins.getPluginsFor('contractGeneration');
}
if (this.plugins && contractsPlugins.length > 0) {
contractsPlugins.forEach(function(plugin) {
result += plugin.generateContracts({contracts: self.contractsManager.contracts});
});
} else {
for(var className in this.contractsManager.contracts) {
var contract = this.contractsManager.contracts[className];
var abi = JSON.stringify(contract.abiDefinition);
var gasEstimates = JSON.stringify(contract.gasEstimates);
// TODO: refactor this
result += "\nvar whenEnvIsLoaded = function(cb) {";
result += "\n if (typeof window !== 'undefined' && window !== null) {";
result += "\n window.addEventListener('load', cb);";
result += "\n } else {";
result += "\n cb();";
result += "\n }";
result += "\n}";
result += "\nwhenEnvIsLoaded(function() {";
if (useEmbarkJS) {
result += "\n" + className + " = new EmbarkJS.Contract({abi: " + abi + ", address: '" + contract.deployedAddress + "', code: '" + contract.code + "', gasEstimates: " + gasEstimates + "});";
} else {
result += "\n" + className + "Abi = " + abi + ";";
result += "\n" + className + "Contract = web3.eth.contract(" + className + "Abi);";
result += "\n" + className + " = " + className + "Contract.at('" + contract.deployedAddress + "');";
}
result += '\n});';
if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
return "";
}
result += "\nvar whenEnvIsLoaded = function(cb) {";
result += "\n if (typeof document !== 'undefined' && document !== null) {";
result += "\n document.addEventListener('DOMContentLoaded', cb);";
result += "\n } else {";
result += "\n cb();";
result += "\n }";
result += "\n}";
if (this.plugins) {
providerPlugins = this.plugins.getPluginsFor('clientWeb3Provider');
}
if (this.plugins && providerPlugins.length > 0) {
providerPlugins.forEach(function(plugin) {
result += plugin.generateProvider(self) + "\n";
});
} else {
result += "\nwhenEnvIsLoaded(function() {";
result += "\nif (typeof web3 !== 'undefined' && typeof Web3 !== 'undefined') {";
result += '\n\tweb3 = new Web3(web3.currentProvider);';
result += "\n} else if (typeof Web3 !== 'undefined') {";
result += '\n\tweb3 = new Web3(new Web3.providers.HttpProvider("http://' + this.rpcHost + ':' + this.rpcPort + '"));';
result += '\n}';
result += "\nweb3.eth.defaultAccount = web3.eth.accounts[0];";
result += '\n})';
}
return result;
}
return result;
};
generateContracts(useEmbarkJS) {
let self = this;
let result = "\n";
let contractsPlugins;
ABIGenerator.prototype.generateStorageInitialization = function(useEmbarkJS) {
var self = this;
var result = "\n";
if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
return "";
}
if (!useEmbarkJS || self.storageConfig === {}) return "";
if (this.plugins) {
contractsPlugins = this.plugins.getPluginsFor('contractGeneration');
}
if (self.storageConfig.provider === 'ipfs' && self.storageConfig.enabled === true) {
result += "\nEmbarkJS.Storage.setProvider('" + self.storageConfig.provider + "', {server: '" + self.storageConfig.host + "', port: '" + self.storageConfig.port + "'});";
if (this.plugins && contractsPlugins.length > 0) {
contractsPlugins.forEach(function (plugin) {
result += plugin.generateContracts({contracts: self.contractsManager.contracts});
});
} else {
for (let className in this.contractsManager.contracts) {
let contract = this.contractsManager.contracts[className];
let abi = JSON.stringify(contract.abiDefinition);
let gasEstimates = JSON.stringify(contract.gasEstimates);
// TODO: refactor this
result += "\nif (whenEnvIsLoaded === undefined) {";
result += "\n var whenEnvIsLoaded = function(cb) {";
result += "\n if (typeof document !== 'undefined' && document !== null) {";
result += "\n document.addEventListener('DOMContentLoaded', cb);";
result += "\n } else {";
result += "\n cb();";
result += "\n }";
result += "\n }";
result += "\n}";
result += "\nwhenEnvIsLoaded(function() {";
if (useEmbarkJS) {
result += "\n" + className + " = new EmbarkJS.Contract({abi: " + abi + ", address: '" + contract.deployedAddress + "', code: '" + contract.code + "', gasEstimates: " + gasEstimates + "});";
} else {
result += "\n" + className + "Abi = " + abi + ";";
result += "\n" + className + "Contract = web3.eth.contract(" + className + "Abi);";
result += "\n" + className + " = " + className + "Contract.at('" + contract.deployedAddress + "');";
}
result += '\n});';
}
}
return result;
}
return result;
};
generateStorageInitialization(useEmbarkJS) {
let self = this;
let result = "\n";
ABIGenerator.prototype.generateCommunicationInitialization = function(useEmbarkJS) {
var self = this;
var result = "\n";
if (!useEmbarkJS || self.storageConfig === {}) return "";
if (!useEmbarkJS || self.communicationConfig === {}) return "";
if (self.storageConfig.provider === 'ipfs' && self.storageConfig.enabled === true) {
result += "\nEmbarkJS.Storage.setProvider('" + self.storageConfig.provider + "', {server: '" + self.storageConfig.host + "', port: '" + self.storageConfig.port + "'});";
}
if (self.communicationConfig.provider === 'whisper' && self.communicationConfig.enabled === true) {
result += "\nEmbarkJS.Messages.setProvider('" + self.communicationConfig.provider + "');";
} else if (self.communicationConfig.provider === 'orbit' && self.communicationConfig.enabled === true) {
result += "\nEmbarkJS.Messages.setProvider('" + self.communicationConfig.provider + "', {server: '" + self.communicationConfig.host + "', port: '" + self.communicationConfig.port + "'});";
return result;
}
return result;
};
generateCommunicationInitialization(useEmbarkJS) {
let self = this;
let result = "\n";
ABIGenerator.prototype.generateABI = function(options) {
var result = "";
if (!useEmbarkJS || self.communicationConfig === {}) return "";
result += this.generateProvider();
result += this.generateContracts(options.useEmbarkJS);
result += this.generateStorageInitialization(options.useEmbarkJS);
result += this.generateCommunicationInitialization(options.useEmbarkJS);
if (self.communicationConfig.provider === 'whisper' && self.communicationConfig.enabled === true) {
result += "\nEmbarkJS.Messages.setProvider('" + self.communicationConfig.provider + "');";
} else if (self.communicationConfig.provider === 'orbit' && self.communicationConfig.enabled === true) {
if (self.communicationConfig.host === undefined && self.communicationConfig.port === undefined) {
result += "\nEmbarkJS.Messages.setProvider('" + self.communicationConfig.provider + "');";
} else {
result += "\nEmbarkJS.Messages.setProvider('" + self.communicationConfig.provider + "', {server: '" + self.communicationConfig.host + "', port: '" + self.communicationConfig.port + "'});";
}
}
return result;
};
return result;
}
generateABI(options) {
let result = "";
result += this.generateProvider();
result += this.generateContracts(options.useEmbarkJS);
result += this.generateStorageInitialization(options.useEmbarkJS);
result += this.generateCommunicationInitialization(options.useEmbarkJS);
return result;
}
generateContractsJSON() {
let contracts = {};
for (let className in this.contractsManager.contracts) {
let contract = this.contractsManager.contracts[className];
let contractJSON = {};
let abi = JSON.stringify(contract.abiDefinition);
let gasEstimates = JSON.stringify(contract.gasEstimates);
contractJSON.contract_name = className;
contractJSON.code = contract.code;
contractJSON.runtime_bytecode = contract.runtimeBytecode;
contractJSON.real_runtime_bytecode = contract.realRuntimeBytecode;
contractJSON.swarm_hash = contract.swarmHash;
contractJSON.gas_estimates = contract.gasEstimates;
contractJSON.function_hashes = contract.functionHashes;
contractJSON.abi = contract.abiDefinition;
contracts[className] = contractJSON;
}
return contracts;
}
}
module.exports = ABIGenerator;

View File

@ -1,118 +1,115 @@
/*jshint esversion: 6, loopfunc: true */
var async = require('async');
var SolcW = require('./solcW.js');
let async = require('../utils/async_extend.js');
let 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;
};
Compiler.prototype.compile_contracts = function(contractFiles, cb) {
var self = this;
var available_compilers = {
//".se": this.compile_serpent
".sol": this.compile_solidity.bind(this)
};
if (this.plugins) {
var compilerPlugins = this.plugins.getPluginsFor('compilers');
if (compilerPlugins.length > 0) {
compilerPlugins.forEach(function(plugin) {
plugin.compilers.forEach(function(compilerObject) {
available_compilers[compilerObject.extension] = compilerObject.cb;
});
});
}
class Compiler {
constructor(options) {
this.plugins = options.plugins;
this.logger = options.logger;
}
var compiledObject = {};
compile_contracts(contractFiles, cb) {
async.eachObject(available_compilers,
function(extension, compiler, callback) {
// TODO: warn about files it doesn't know how to compile
var matchingFiles = contractFiles.filter(function(file) {
return (file.filename.match(/\.[0-9a-z]+$/)[0] === extension);
});
let available_compilers = {
//".se": this.compile_serpent
".sol": this.compile_solidity.bind(this)
};
compiler.call(compiler, matchingFiles || [], function(err, compileResult) {
Object.assign(compiledObject, compileResult);
callback(err, compileResult);
});
},
function (err) {
cb(err, compiledObject);
if (this.plugins) {
let compilerPlugins = this.plugins.getPluginsFor('compilers');
if (compilerPlugins.length > 0) {
compilerPlugins.forEach(function (plugin) {
plugin.compilers.forEach(function (compilerObject) {
available_compilers[compilerObject.extension] = compilerObject.cb;
});
});
}
}
);
};
Compiler.prototype.compile_solidity = function(contractFiles, cb) {
var self = this;
var input = {};
var solcW;
async.waterfall([
function prepareInput(callback) {
for (var i = 0; i < contractFiles.length; i++){
// TODO: this depends on the config
var filename = contractFiles[i].filename.replace('app/contracts/','');
input[filename] = contractFiles[i].content.toString();
}
callback();
},
function loadCompiler(callback) {
// TODO: there ino need to load this twice
solcW = new SolcW();
if (solcW.isCompilerLoaded()) {
return callback();
}
let compiledObject = {};
self.logger.info("loading solc compiler..");
solcW.load_compiler(function(){
callback();
});
},
function compileContracts(callback) {
self.logger.info("compiling contracts...");
solcW.compile({sources: input}, 1, function(output) {
if (output.errors) {
return callback(new Error ("Solidity errors: " + output.errors).message);
async.eachObject(available_compilers,
function (extension, compiler, callback) {
// TODO: warn about files it doesn't know how to compile
let matchingFiles = contractFiles.filter(function (file) {
return (file.filename.match(/\.[0-9a-z]+$/)[0] === extension);
});
compiler.call(compiler, matchingFiles || [], function (err, compileResult) {
Object.assign(compiledObject, compileResult);
callback(err, compileResult);
});
},
function (err) {
cb(err, compiledObject);
}
);
}
compile_solidity(contractFiles, cb) {
let self = this;
let input = {};
let solcW;
async.waterfall([
function prepareInput(callback) {
for (let i = 0; i < contractFiles.length; i++) {
// TODO: this depends on the config
let filename = contractFiles[i].filename.replace('app/contracts/', '');
input[filename] = contractFiles[i].content.toString();
}
callback();
},
function loadCompiler(callback) {
// TODO: there ino need to load this twice
solcW = new SolcW();
if (solcW.isCompilerLoaded()) {
return callback();
}
callback(null, output);
});
},
function createCompiledObject(output, callback) {
var json = output.contracts;
compiled_object = {};
self.logger.info("loading solc compiler..");
solcW.load_compiler(function () {
callback();
});
},
function compileContracts(callback) {
self.logger.info("compiling contracts...");
solcW.compile({sources: input}, 1, function (output) {
if (output.errors) {
return callback(new Error("Solidity errors: " + output.errors).message);
}
callback(null, output);
});
},
function createCompiledObject(output, callback) {
let json = output.contracts;
for (var className in json) {
var contract = json[className];
let compiled_object = {};
compiled_object[className] = {};
compiled_object[className].code = contract.bytecode;
compiled_object[className].runtimeBytecode = contract.runtimeBytecode;
compiled_object[className].realRuntimeBytecode = contract.runtimeBytecode.slice(0, -68);
compiled_object[className].swarmHash = contract.runtimeBytecode.slice(-68).slice(0,64);
compiled_object[className].gasEstimates = contract.gasEstimates;
compiled_object[className].functionHashes = contract.functionHashes;
compiled_object[className].abiDefinition = JSON.parse(contract.interface);
for (let contractName in json) {
let contract = json[contractName];
// Pull out filename:classname
// [0] filename:classname
// [1] filename
// [2] classname
const regex = /(.*):(.*)/;
const className = contractName.match(regex)[2];
compiled_object[className] = {};
compiled_object[className].code = contract.bytecode;
compiled_object[className].runtimeBytecode = contract.runtimeBytecode;
compiled_object[className].realRuntimeBytecode = contract.runtimeBytecode.slice(0, -68);
compiled_object[className].swarmHash = contract.runtimeBytecode.slice(-68).slice(0, 64);
compiled_object[className].gasEstimates = contract.gasEstimates;
compiled_object[className].functionHashes = contract.functionHashes;
compiled_object[className].abiDefinition = JSON.parse(contract.interface);
}
callback(null, compiled_object);
}
callback(null, compiled_object);
}
], function(err, result) {
cb(err, result);
});
};
], function (err, result) {
cb(err, result);
});
}
}
module.exports = Compiler;

View File

@ -1,247 +1,251 @@
var toposort = require('toposort');
var async = require('async');
let toposort = require('toposort');
let async = require('async');
var Compiler = require('./compiler.js');
let Compiler = require('./compiler.js');
// TODO: create a contract object
var adjustGas = function(contract) {
var maxGas, adjustedGas;
if (contract.gas === 'auto') {
if (contract.deploy || contract.deploy === undefined) {
if (contract.gasEstimates.creation !== undefined) {
// TODO: should sum it instead
maxGas = Math.max(contract.gasEstimates.creation[0], contract.gasEstimates.creation[1], 500000);
} else {
maxGas = 500000;
}
} else {
maxGas = 500000;
}
// TODO: put a check so it doesn't go over the block limit
adjustedGas = Math.round(maxGas * 1.40);
adjustedGas += 25000;
contract.gas = adjustedGas;
class ContractsManager {
constructor(options) {
this.contractFiles = options.contractFiles;
this.contractsConfig = options.contractsConfig;
this.contracts = {};
this.logger = options.logger;
this.plugins = options.plugins;
this.contractDependencies = {};
}
};
var ContractsManager = function(options) {
this.contractFiles = options.contractFiles;
this.contractsConfig = options.contractsConfig;
this.contracts = {};
this.logger = options.logger;
this.plugins = options.plugins;
this.contractDependencies = {};
};
ContractsManager.prototype.build = function(done) {
var self = this;
async.waterfall([
function compileContracts(callback) {
var compiler = new Compiler({plugins: self.plugins, logger: self.logger});
compiler.compile_contracts(self.contractFiles, function(err, compiledObject) {
build(done) {
let self = this;
async.waterfall([
function compileContracts(callback) {
let compiler = new Compiler({plugins: self.plugins, logger: self.logger});
compiler.compile_contracts(self.contractFiles, function (err, compiledObject) {
self.compiledContracts = compiledObject;
callback(err);
});
},
function prepareContractsFromConfig(callback) {
var className, contract;
for(className in self.contractsConfig.contracts) {
contract = self.contractsConfig.contracts[className];
},
function prepareContractsFromConfig(callback) {
let className, contract;
for (className in self.contractsConfig.contracts) {
contract = self.contractsConfig.contracts[className];
contract.className = className;
contract.args = contract.args || [];
contract.className = className;
contract.args = contract.args || [];
self.contracts[className] = contract;
}
callback();
},
function setDeployIntention(callback) {
var className, contract;
for(className in self.contracts) {
contract = self.contracts[className];
contract.deploy = (contract.deploy === undefined) || contract.deploy;
}
callback();
},
function prepareContractsFromCompilation(callback) {
var className, compiledContract, contractConfig, contract;
for(className in self.compiledContracts) {
compiledContract = self.compiledContracts[className];
contractConfig = self.contractsConfig.contracts[className];
contract = self.contracts[className] || {className: className, args: []};
contract.code = compiledContract.code;
contract.runtimeBytecode = compiledContract.runtimeBytecode;
contract.realRuntimeBytecode = (contract.realRuntimeBytecode || contract.runtimeBytecode);
contract.swarmHash = compiledContract.swarmHash;
contract.gasEstimates = compiledContract.gasEstimates;
contract.functionHashes = compiledContract.functionHashes;
contract.abiDefinition = compiledContract.abiDefinition;
contract.gas = (contractConfig && contractConfig.gas) || self.contractsConfig.gas || 'auto';
adjustGas(contract);
contract.gasPrice = contract.gasPrice || self.contractsConfig.gasPrice;
contract.type = 'file';
contract.className = className;
self.contracts[className] = contract;
}
callback();
},
/*eslint complexity: ["error", 11]*/
function dealWithSpecialConfigs(callback) {
var className, contract, parentContractName, parentContract;
for(className in self.contracts) {
contract = self.contracts[className];
if (contract.instanceOf === undefined) { continue; }
parentContractName = contract.instanceOf;
parentContract = self.contracts[parentContractName];
if (parentContract === className) {
self.logger.error(className + ": instanceOf is set to itself");
continue;
self.contracts[className] = contract;
}
if (parentContract === undefined) {
self.logger.error(className + ": couldn't find instanceOf contract " + parentContractName);
continue;
callback();
},
function setDeployIntention(callback) {
let className, contract;
for (className in self.contracts) {
contract = self.contracts[className];
contract.deploy = (contract.deploy === undefined) || contract.deploy;
}
callback();
},
function prepareContractsFromCompilation(callback) {
let className, compiledContract, contractConfig, contract;
for (className in self.compiledContracts) {
compiledContract = self.compiledContracts[className];
contractConfig = self.contractsConfig.contracts[className];
if (parentContract.args && parentContract.args.length > 0 && ((contract.args && contract.args.length === 0) || contract.args === undefined)) {
contract.args = parentContract.args;
contract = self.contracts[className] || {className: className, args: []};
contract.code = compiledContract.code;
contract.runtimeBytecode = compiledContract.runtimeBytecode;
contract.realRuntimeBytecode = (contract.realRuntimeBytecode || contract.runtimeBytecode);
contract.swarmHash = compiledContract.swarmHash;
contract.gasEstimates = compiledContract.gasEstimates;
contract.functionHashes = compiledContract.functionHashes;
contract.abiDefinition = compiledContract.abiDefinition;
contract.gas = (contractConfig && contractConfig.gas) || self.contractsConfig.gas || 'auto';
self.adjustGas(contract);
contract.gasPrice = contract.gasPrice || self.contractsConfig.gasPrice;
contract.type = 'file';
contract.className = className;
self.contracts[className] = contract;
}
callback();
},
/*eslint complexity: ["error", 11]*/
function dealWithSpecialConfigs(callback) {
let className, contract, parentContractName, parentContract;
for (className in self.contracts) {
contract = self.contracts[className];
if (contract.instanceOf === undefined) {
continue;
}
parentContractName = contract.instanceOf;
parentContract = self.contracts[parentContractName];
if (parentContract === className) {
self.logger.error(className + ": instanceOf is set to itself");
continue;
}
if (parentContract === undefined) {
self.logger.error(className + ": couldn't find instanceOf contract " + parentContractName);
continue;
}
if (parentContract.args && parentContract.args.length > 0 && ((contract.args && contract.args.length === 0) || contract.args === undefined)) {
contract.args = parentContract.args;
}
if (contract.code !== undefined) {
self.logger.error(className + " has code associated to it but it's configured as an instanceOf " + parentContractName);
}
contract.code = parentContract.code;
contract.runtimeBytecode = parentContract.runtimeBytecode;
contract.gasEstimates = parentContract.gasEstimates;
contract.functionHashes = parentContract.functionHashes;
contract.abiDefinition = parentContract.abiDefinition;
contract.gas = contract.gas || parentContract.gas;
contract.gasPrice = contract.gasPrice || parentContract.gasPrice;
contract.type = 'instance';
if (contract.code !== undefined) {
self.logger.error(className + " has code associated to it but it's configured as an instanceOf " + parentContractName);
}
callback();
},
function removeContractsWithNoCode(callback) {
let className, contract;
for (className in self.contracts) {
contract = self.contracts[className];
contract.code = parentContract.code;
contract.runtimeBytecode = parentContract.runtimeBytecode;
contract.gasEstimates = parentContract.gasEstimates;
contract.functionHashes = parentContract.functionHashes;
contract.abiDefinition = parentContract.abiDefinition;
contract.gas = contract.gas || parentContract.gas;
contract.gasPrice = contract.gasPrice || parentContract.gasPrice;
contract.type = 'instance';
}
callback();
},
function removeContractsWithNoCode(callback) {
var className, contract;
for(className in self.contracts) {
contract = self.contracts[className];
if (contract.code === undefined) {
self.logger.error(className + " has no code associated");
delete self.contracts[className];
}
}
self.logger.trace(self.contracts);
callback();
},
function determineDependencies(callback) {
var className, contract;
for(className in self.contracts) {
contract = self.contracts[className];
if (contract.args === []) continue;
var ref = contract.args;
for (var j = 0; j < ref.length; j++) {
var arg = ref[j];
if (arg[0] === "$") {
self.contractDependencies[className] = self.contractDependencies[className] || [];
self.contractDependencies[className].push(arg.substr(1));
if (contract.code === undefined) {
self.logger.error(className + " has no code associated");
delete self.contracts[className];
}
}
self.logger.trace(self.contracts);
callback();
},
function determineDependencies(callback) {
let className, contract;
for (className in self.contracts) {
contract = self.contracts[className];
if (contract.args === []) continue;
let ref = contract.args;
for (let j = 0; j < ref.length; j++) {
let arg = ref[j];
if (arg[0] === "$") {
self.contractDependencies[className] = self.contractDependencies[className] || [];
self.contractDependencies[className].push(arg.substr(1));
}
}
}
callback();
}
callback();
}
], function(err, result) {
if (err) {
self.logger.error("Error Compiling/Building contracts: " + err);
}
self.logger.trace("finished".underline);
done(err, self);
});
};
ContractsManager.prototype.getContract = function(className) {
return this.contracts[className];
};
ContractsManager.prototype.sortContracts = function(contractList) {
var converted_dependencies = [], i;
for(var contract in this.contractDependencies) {
var dependencies = this.contractDependencies[contract];
for(i=0; i < dependencies.length; i++) {
converted_dependencies.push([contract, dependencies[i]]);
}
], function (err, result) {
if (err) {
self.logger.error("Error Compiling/Building contracts: " + err);
}
self.logger.trace("finished".underline);
done(err, self);
});
}
var orderedDependencies = toposort(converted_dependencies).reverse();
var newList = contractList.sort(function(a,b) {
var order_a = orderedDependencies.indexOf(a.className);
var order_b = orderedDependencies.indexOf(b.className);
return order_a - order_b;
});
return newList;
};
// TODO: should be built contracts
ContractsManager.prototype.listContracts = function() {
var contracts = [];
for(var className in this.contracts) {
var contract = this.contracts[className];
contracts.push(contract);
getContract(className) {
return this.contracts[className];
}
return this.sortContracts(contracts);
};
ContractsManager.prototype.contractsState = function() {
var data = [];
sortContracts(contractList) {
let converted_dependencies = [], i;
for(var className in this.contracts) {
var contract = this.contracts[className];
var contractData;
if (contract.deploy === false) {
contractData = [
className.green,
'Interface or set to not deploy'.green,
"\t\tn/a".green
];
} else if (contract.error) {
contractData = [
className.green,
(contract.error).red,
'\t\tError'.red
];
} else {
contractData = [
className.green,
(contract.deployedAddress || '...').green,
((contract.deployedAddress !== undefined) ? "\t\tDeployed".green : "\t\tPending".magenta)
];
for (let contract in this.contractDependencies) {
let dependencies = this.contractDependencies[contract];
for (i = 0; i < dependencies.length; i++) {
converted_dependencies.push([contract, dependencies[i]]);
}
}
data.push(contractData);
let orderedDependencies = toposort(converted_dependencies).reverse();
let newList = contractList.sort(function (a, b) {
let order_a = orderedDependencies.indexOf(a.className);
let order_b = orderedDependencies.indexOf(b.className);
return order_a - order_b;
});
return newList;
}
return data;
};
// TODO: should be built contracts
listContracts() {
let contracts = [];
for (let className in this.contracts) {
let contract = this.contracts[className];
contracts.push(contract);
}
return this.sortContracts(contracts);
}
contractsState() {
let data = [];
for (let className in this.contracts) {
let contract = this.contracts[className];
let contractData;
if (contract.deploy === false) {
contractData = [
className.green,
'Interface or set to not deploy'.green,
"\t\tn/a".green
];
} else if (contract.error) {
contractData = [
className.green,
(contract.error).red,
'\t\tError'.red
];
} else {
contractData = [
className.green,
(contract.deployedAddress || '...').green,
((contract.deployedAddress !== undefined) ? "\t\tDeployed".green : "\t\tPending".magenta)
];
}
data.push(contractData);
}
return data;
}
adjustGas(contract) {
let maxGas, adjustedGas;
if (contract.gas === 'auto') {
if (contract.deploy || contract.deploy === undefined) {
if (contract.gasEstimates.creation !== undefined) {
// TODO: should sum it instead
maxGas = Math.max(contract.gasEstimates.creation[0], contract.gasEstimates.creation[1], 500000);
} else {
maxGas = 500000;
}
} else {
maxGas = 500000;
}
// TODO: put a check so it doesn't go over the block limit
adjustedGas = Math.round(maxGas * 1.40);
adjustedGas += 25000;
contract.gas = adjustedGas;
}
}
}
module.exports = ContractsManager;

View File

@ -1,166 +1,168 @@
var async = require('async');
let async = require('async');
var RunCode = require('../core/runCode.js');
let RunCode = require('../core/runCode.js');
var DeployTracker = require('./deploy_tracker.js');
var ABIGenerator = require('./abi.js');
let DeployTracker = require('./deploy_tracker.js');
let ABIGenerator = require('./abi.js');
var Deploy = function(options) {
this.web3 = options.web3;
this.contractsManager = options.contractsManager;
this.logger = options.logger;
this.env = options.env;
class Deploy {
constructor(options) {
this.web3 = options.web3;
this.contractsManager = options.contractsManager;
this.logger = options.logger;
this.env = options.env;
this.deployTracker = new DeployTracker({
logger: options.logger, chainConfig: options.chainConfig, web3: options.web3, env: this.env
});
};
Deploy.prototype.determineArguments = function(suppliedArgs) {
var realArgs = [], l, arg, contractName, referedContract;
for (l = 0; l < suppliedArgs.length; l++) {
arg = suppliedArgs[l];
if (arg[0] === "$") {
contractName = arg.substr(1);
referedContract = this.contractsManager.getContract(contractName);
realArgs.push(referedContract.deployedAddress);
} else {
realArgs.push(arg);
}
this.deployTracker = new DeployTracker({
logger: options.logger, chainConfig: options.chainConfig, web3: options.web3, env: this.env
});
}
return realArgs;
};
determineArguments(suppliedArgs) {
let realArgs = [], l, arg, contractName, referedContract;
Deploy.prototype.checkAndDeployContract = function(contract, params, callback) {
var self = this;
var suppliedArgs;
var realArgs;
var arg;
var l;
var contractName;
var referedContract;
contract.error = false;
if (contract.deploy === false) {
self.logger.contractsState(self.contractsManager.contractsState());
return callback();
}
if (contract.address !== undefined) {
realArgs = self.determineArguments(params || contract.args);
contract.deployedAddress = contract.address;
self.deployTracker.trackContract(contract.className, contract.realRuntimeBytecode, realArgs, contract.address);
self.deployTracker.save();
self.logger.contractsState(self.contractsManager.contractsState());
return callback();
}
var trackedContract = self.deployTracker.getContract(contract.className, contract.realRuntimeBytecode, contract.args);
if (trackedContract && this.web3.eth.getCode(trackedContract.address) !== "0x") {
self.logger.info(contract.className.bold.cyan + " already deployed at ".green + trackedContract.address.bold.cyan);
contract.deployedAddress = trackedContract.address;
self.logger.contractsState(self.contractsManager.contractsState());
return callback();
} else {
realArgs = self.determineArguments(params || contract.args);
this.deployContract(contract, realArgs, function(err, address) {
if (err) {
return callback(new Error(err));
for (l = 0; l < suppliedArgs.length; l++) {
arg = suppliedArgs[l];
if (arg[0] === "$") {
contractName = arg.substr(1);
referedContract = this.contractsManager.getContract(contractName);
realArgs.push(referedContract.deployedAddress);
} else {
realArgs.push(arg);
}
self.deployTracker.trackContract(contract.className, contract.realRuntimeBytecode, realArgs, address);
}
return realArgs;
}
checkAndDeployContract(contract, params, callback) {
let self = this;
let suppliedArgs;
let realArgs;
let arg;
let l;
let contractName;
let referedContract;
contract.error = false;
if (contract.deploy === false) {
self.logger.contractsState(self.contractsManager.contractsState());
return callback();
}
if (contract.address !== undefined) {
realArgs = self.determineArguments(params || contract.args);
contract.deployedAddress = contract.address;
self.deployTracker.trackContract(contract.className, contract.realRuntimeBytecode, realArgs, contract.address);
self.deployTracker.save();
self.logger.contractsState(self.contractsManager.contractsState());
return callback();
}
if (contract.onDeploy !== undefined) {
self.logger.info('executing onDeploy commands');
var abiGenerator = new ABIGenerator({contractsManager: self.contractsManager});
var abi = abiGenerator.generateContracts(false);
var cmds = contract.onDeploy.join(';\n');
let trackedContract = self.deployTracker.getContract(contract.className, contract.realRuntimeBytecode, contract.args);
RunCode.doEval(abi + "\n" + cmds, self.web3);
if (trackedContract && this.web3.eth.getCode(trackedContract.address) !== "0x") {
self.logger.info(contract.className.bold.cyan + " already deployed at ".green + trackedContract.address.bold.cyan);
contract.deployedAddress = trackedContract.address;
self.logger.contractsState(self.contractsManager.contractsState());
return callback();
} else {
realArgs = self.determineArguments(params || contract.args);
this.deployContract(contract, realArgs, function (err, address) {
if (err) {
return callback(new Error(err));
}
self.deployTracker.trackContract(contract.className, contract.realRuntimeBytecode, realArgs, address);
self.deployTracker.save();
self.logger.contractsState(self.contractsManager.contractsState());
if (contract.onDeploy !== undefined) {
self.logger.info('executing onDeploy commands');
let abiGenerator = new ABIGenerator({contractsManager: self.contractsManager});
let abi = abiGenerator.generateContracts(false);
let cmds = contract.onDeploy.join(';\n');
RunCode.doEval(abi + "\n" + cmds, self.web3);
}
callback();
});
}
}
deployContract(contract, params, callback) {
let self = this;
let contractObject = this.web3.eth.contract(contract.abiDefinition);
let contractParams = (params || contract.args).slice();
this.web3.eth.getAccounts(function (err, accounts) {
if (err) {
return callback(new Error(err));
}
callback();
// TODO: probably needs to be defaultAccount
// TODO: it wouldn't necessary be the first address
// use defined blockchain address or first address
contractParams.push({
//from: this.web3.eth.coinbase,
from: accounts[0],
data: "0x" + contract.code,
gas: contract.gas,
gasPrice: contract.gasPrice
});
self.logger.info("deploying " + contract.className.bold.cyan + " with ".green + contract.gas + " gas".green);
contractParams.push(function (err, transaction) {
self.logger.contractsState(self.contractsManager.contractsState());
if (err) {
self.logger.error("error deploying contract: " + contract.className.cyan);
let errMsg = err.toString();
if (errMsg === 'Error: The contract code couldn\'t be stored, please check your gas amount.') {
errMsg = 'The contract code couldn\'t be stored, out of gas or constructor error';
}
self.logger.error(errMsg);
contract.error = errMsg;
return callback(new Error(err));
} else if (transaction.address !== undefined) {
self.logger.info(contract.className.bold.cyan + " deployed at ".green + transaction.address.bold.cyan);
contract.deployedAddress = transaction.address;
contract.transactionHash = transaction.transactionHash;
return callback(null, transaction.address);
}
});
contractObject["new"].apply(contractObject, contractParams);
});
}
};
deployAll(done) {
let self = this;
this.logger.info("deploying contracts");
Deploy.prototype.deployContract = function(contract, params, callback) {
var self = this;
var contractObject = this.web3.eth.contract(contract.abiDefinition);
var contractParams = (params || contract.args).slice();
this.web3.eth.getAccounts(function(err, accounts) {
if (err) {
return callback(new Error(err));
}
// TODO: probably needs to be defaultAccount
// TODO: it wouldn't necessary be the first address
// use defined blockchain address or first address
contractParams.push({
//from: this.web3.eth.coinbase,
from: accounts[0],
data: "0x" + contract.code,
gas: contract.gas,
gasPrice: contract.gasPrice
});
self.logger.info("deploying " + contract.className.bold.cyan + " with ".green + contract.gas + " gas".green);
contractParams.push(function(err, transaction) {
self.logger.contractsState(self.contractsManager.contractsState());
if (err) {
self.logger.error("error deploying contract: " + contract.className.cyan);
var errMsg = err.toString();
if (errMsg === 'Error: The contract code couldn\'t be stored, please check your gas amount.') {
errMsg = 'The contract code couldn\'t be stored, out of gas or constructor error';
async.eachOfSeries(this.contractsManager.listContracts(),
function (contract, key, callback) {
self.logger.trace(arguments);
self.checkAndDeployContract(contract, null, callback);
},
function (err, results) {
if (err) {
self.logger.error("error deploying contracts");
self.logger.error(err.message);
self.logger.debug(err.stack);
}
self.logger.error(errMsg);
contract.error = errMsg;
return callback(new Error(err));
} else if (transaction.address !== undefined) {
self.logger.info(contract.className.bold.cyan + " deployed at ".green + transaction.address.bold.cyan);
contract.deployedAddress = transaction.address;
contract.transactionHash = transaction.transactionHash;
return callback(null, transaction.address);
self.logger.info("finished deploying contracts");
self.logger.trace(arguments);
done();
}
});
);
contractObject["new"].apply(contractObject, contractParams);
});
};
Deploy.prototype.deployAll = function(done) {
var self = this;
this.logger.info("deploying contracts");
async.eachOfSeries(this.contractsManager.listContracts(),
function(contract, key, callback) {
self.logger.trace(arguments);
self.checkAndDeployContract(contract, null, callback);
},
function(err, results) {
if (err) {
self.logger.error("error deploying contracts");
self.logger.error(err.message);
self.logger.debug(err.stack);
}
self.logger.info("finished deploying contracts");
self.logger.trace(arguments);
done();
}
);
};
}
}
module.exports = Deploy;

View File

@ -1,85 +1,90 @@
var async = require('async');
var Web3 = require('web3');
let async = require('async');
let Deploy = require('./deploy.js');
let ContractsManager = require('./contracts.js');
var Deploy = require('./deploy.js');
var ContractsManager = require('./contracts.js');
var DeployManager = function(options) {
this.config = options.config;
this.logger = options.logger;
this.blockchainConfig = this.config.blockchainConfig;
this.plugins = options.plugins;
this.events = options.events;
this.web3 = options.web3;
this.chainConfig = (options.trackContracts !== false) ? this.config.chainTracker : false;
};
DeployManager.prototype.deployContracts = function(done) {
var self = this;
if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
self.logger.info("Blockchain component is disabled in the config".underline);
self.events.emit('blockchainDisabled', {});
return done();
class DeployManager {
constructor(options) {
this.config = options.config;
this.logger = options.logger;
this.blockchainConfig = this.config.blockchainConfig;
this.events = options.events;
this.plugins = options.plugins;
this.web3 = options.web3;
this.chainConfig = (options.trackContracts !== false) ? this.config.chainTracker : false;
}
async.waterfall([
function buildContracts(callback) {
var contractsManager = new ContractsManager({
contractFiles: self.config.contractsFiles,
contractsConfig: self.config.contractsConfig,
logger: self.logger,
plugins: self.plugins
});
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"));
}
deployContracts(done) {
let self = this;
if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
self.logger.info("Blockchain component is disabled in the config".underline);
this.events.emit('blockchainDisabled', {});
return done();
}
callback(null, contractsManager, web3);
},
function setDefaultAccount(contractsManager, web3, callback) {
web3.eth.getAccounts(function(err, accounts) {
async.waterfall([
function buildContracts(callback) {
let contractsManager = new ContractsManager({
contractFiles: self.config.contractsFiles,
contractsConfig: self.config.contractsConfig,
logger: self.logger,
plugins: self.plugins
});
contractsManager.build(callback);
},
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);
}
},
function setDefaultAccount(contractsManager, web3, callback) {
web3.eth.getAccounts(function (err, accounts) {
if (err) {
return callback(new Error(err));
}
let accountConfig = self.config.blockchainConfig.account;
let selectedAccount = accountConfig && accountConfig.address;
web3.eth.defaultAccount = (selectedAccount || accounts[0]);
callback(null, contractsManager, web3);
});
},
function deployAllContracts(contractsManager, web3, callback) {
let deploy = new Deploy({
web3: web3,
contractsManager: contractsManager,
logger: self.logger,
chainConfig: self.chainConfig,
env: self.config.env
});
deploy.deployAll(function () {
self.events.emit('contractsDeployed', contractsManager);
callback(null, contractsManager);
});
}
], function (err, result) {
if (err) {
return callback(new Error(err));
done(err, null);
} else {
done(null, result);
}
var accountConfig = self.config.blockchainConfig.account;
var selectedAccount = accountConfig && accountConfig.address;
web3.eth.defaultAccount = (selectedAccount || accounts[0]);
callback(null, contractsManager, web3);
});
},
function deployAllContracts(contractsManager, web3, callback) {
var deploy = new Deploy({
web3: web3,
contractsManager: contractsManager,
logger: self.logger,
chainConfig: self.chainConfig,
env: self.config.env
});
deploy.deployAll(function() {
self.events.emit('contractsDeployed', contractsManager);
callback(null, contractsManager);
});
}
], function(err, result) {
if (err) {
done(err, null);
} else {
done(null, result);
}
});
};
}
module.exports = DeployManager;

View File

@ -1,56 +1,62 @@
var fs = require('../core/fs.js');
let fs = require('../core/fs.js');
var DeployTracker = function(options) {
this.logger = options.logger;
this.env = options.env;
this.chainConfig = options.chainConfig;
this.web3 = options.web3;
class DeployTracker {
constructor(options) {
this.logger = options.logger;
this.env = options.env;
this.chainConfig = options.chainConfig;
this.web3 = options.web3;
if (this.chainConfig === false) {
this.currentChain = {contracts: []};
return;
if (this.chainConfig === false) {
this.currentChain = {contracts: []};
return;
}
// TODO: need to make this async
let block = this.web3.eth.getBlock(0);
let chainId = block.hash;
if (this.chainConfig[chainId] === undefined) {
this.chainConfig[chainId] = {contracts: {}};
}
this.currentChain = this.chainConfig[chainId];
this.currentChain.name = this.env;
// TODO: add other params
//this.currentChain.networkId = "";
//this.currentChain.networkType = "custom"
}
// TODO: need to make this async
var block = this.web3.eth.getBlock(0);
var chainId = block.hash;
if (this.chainConfig[chainId] === undefined) {
this.chainConfig[chainId] = {contracts: {}};
loadConfig(config) {
this.chainConfig = config;
return this;
}
this.currentChain = this.chainConfig[chainId];
trackContract(contractName, code, args, address) {
this.currentChain.contracts[this.web3.sha3(code + contractName + args.join(','))] = {
name: contractName,
address: address
};
}
this.currentChain.name = this.env;
// TODO: add other params
//this.currentChain.networkId = "";
//this.currentChain.networkType = "custom"
};
getContract(contractName, code, args) {
let contract = this.currentChain.contracts[this.web3.sha3(code + contractName + args.join(','))];
if (contract && contract.address === undefined) {
return false;
}
return contract;
}
DeployTracker.prototype.loadConfig = function(config) {
this.chainConfig = config;
return this;
};
DeployTracker.prototype.trackContract = function(contractName, code, args, address) {
this.currentChain.contracts[this.web3.sha3(code + contractName + args.join(','))] = {
name: contractName,
address: address
};
};
DeployTracker.prototype.getContract = function(contractName, code, args) {
var contract = this.currentChain.contracts[this.web3.sha3(code + contractName + args.join(','))];
if (contract && contract.address === undefined) { return false; }
return contract;
};
// TODO: abstract this
// chainConfig can be an abstract PersistentObject
DeployTracker.prototype.save = function() {
if (this.chainConfig === false) { return; }
fs.writeJSONSync("./chains.json", this.chainConfig);
};
// TODO: abstract this
// chainConfig can be an abstract PersistentObject
save() {
if (this.chainConfig === false) {
return;
}
fs.writeJSONSync("./chains.json", this.chainConfig, {spaces: 2});
}
}
module.exports = DeployTracker;

View File

@ -1,18 +1,18 @@
var solc;
let solc;
process.on('message', function(msg) {
process.on('message', function (msg) {
if (msg.action === 'loadCompiler') {
solc = require('solc');
process.send({result: "loadedCompiler"});
}
if (msg.action === 'compile') {
var output = solc.compile(msg.obj, msg.optimize);
let output = solc.compile(msg.obj, msg.optimize);
process.send({result: "compilation", output: output});
}
});
process.on('exit', function() {
process.on('exit', function () {
process.exit(0);
});

View File

@ -1,36 +1,38 @@
var utils = require('../core/utils.js');
var solcProcess;
var compilerLoaded = false;
let utils = require('../utils/utils.js');
let solcProcess;
let compilerLoaded = false;
var SolcW = function() {
};
class SolcW {
SolcW.prototype.load_compiler = function(done) {
if (compilerLoaded) { done(); }
solcProcess = require('child_process').fork(utils.joinPath(__dirname, '/solcP.js'));
solcProcess.once('message', function(msg) {
if (msg.result !== 'loadedCompiler') {
return;
load_compiler(done) {
if (compilerLoaded) {
done();
}
compilerLoaded = true;
done();
});
solcProcess.send({action: 'loadCompiler'});
};
solcProcess = require('child_process').fork(utils.joinPath(__dirname, '/solcP.js'));
solcProcess.once('message', function (msg) {
if (msg.result !== 'loadedCompiler') {
return;
}
compilerLoaded = true;
done();
});
solcProcess.send({action: 'loadCompiler'});
}
SolcW.prototype.isCompilerLoaded = function() {
return (compilerLoaded === true);
};
isCompilerLoaded() {
return (compilerLoaded === true);
}
SolcW.prototype.compile = function(obj, optimize, done) {
solcProcess.once('message', function(msg) {
if (msg.result !== 'compilation') {
return;
}
done(msg.output);
});
solcProcess.send({action: 'compile', obj: obj, optimize: optimize});
};
compile(obj, optimize, done) {
solcProcess.once('message', function (msg) {
if (msg.result !== 'compilation') {
return;
}
done(msg.output);
});
solcProcess.send({action: 'compile', obj: obj, optimize: optimize});
}
}
module.exports = SolcW;

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,5 +1,5 @@
class Core {
var Core = function() {};
}
module.exports = Core;

View File

@ -1,151 +1,251 @@
var Events = require('./events.js');
var Logger = require('./logger.js');
var Config = require('./config.js');
let Web3 = require('web3');
let utils = require('../utils/utils.js');
let Events = require('./events.js');
let Logger = require('./logger.js');
let Config = require('./config.js');
let DeployManager = require('../contracts/deploy_manager.js');
let ABIGenerator = require('../contracts/abi.js');
let ServicesMonitor = require('./services_monitor.js');
let Pipeline = require('../pipeline/pipeline.js');
let Server = require('../pipeline/server.js');
let Watch = require('../pipeline/watch.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 Pipeline = require('../pipeline/pipeline.js');
var Server = require('../pipeline/server.js');
var Watch = require('../pipeline/watch.js');
var Engine = function(options) {
this.env = options.env;
this.embarkConfig = options.embarkConfig;
this.interceptLogs = options.interceptLogs;
this.version = "2.4.2";
};
Engine.prototype.init = function(_options) {
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;
};
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
};
var service = services[serviceName];
if (!service) {
throw new Error("unknown service: " + serviceName);
class Engine {
constructor(options) {
this.env = options.env;
this.embarkConfig = options.embarkConfig;
this.interceptLogs = options.interceptLogs;
this.version = options.version;
}
// need to be careful with circular references due to passing the web3 object
//this.logger.trace("calling: " + serviceName + "(" + JSON.stringify(options) + ")");
return service.apply(this, [options]);
};
init(_options) {
let self = this;
let options = _options || {};
this.events = new Events();
this.logger = options.logger || new Logger({logLevel: options.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;
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();
};
this.servicesMonitor = new ServicesMonitor({events: this.events, logger: this.logger});
this.servicesMonitor.addCheck('embarkVersion', function (cb) {
return cb({name: 'Embark ' + self.version, status: 'on'});
}, 0);
}
Engine.prototype.pipelineService = function(options) {
var self = this;
this.logger.setStatus("Building Assets");
var pipeline = new Pipeline({
buildDir: this.config.buildDir,
contractsFiles: this.config.contractsFiles,
assetFiles: this.config.assetFiles,
logger: this.logger,
plugins: this.plugins
});
this.events.on('abi', function(abi) {
self.currentAbi = abi;
pipeline.build(abi);
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');
// }
//});
};
startMonitor() {
let self = this;
if (this.plugins) {
let 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.abiService = function(options) {
var self = this;
var generateABICode = function(contractsManager) {
var abiGenerator = new ABIGenerator({
blockchainConfig: self.config.blockchainConfig,
contractsManager: contractsManager,
plugins: self.plugins,
storageConfig: self.config.storageConfig,
communicationConfig: self.config.communicationConfig
startService(serviceName, _options) {
let options = _options || {};
let services = {
"pipeline": this.pipelineService,
"abi": this.abiService,
"deployment": this.deploymentService,
"fileWatcher": this.fileWatchService,
"webServer": this.webServerService,
"ipfs": this.ipfsService,
"web3": this.web3Service
};
let service = services[serviceName];
if (!service) {
throw new Error("unknown service: " + serviceName);
}
// need to be careful with circular references due to passing the web3 object
//this.logger.trace("calling: " + serviceName + "(" + JSON.stringify(options) + ")");
return service.apply(this, [options]);
}
pipelineService(options) {
let self = this;
this.logger.setStatus("Building Assets");
let pipeline = new Pipeline({
buildDir: this.config.buildDir,
contractsFiles: this.config.contractsFiles,
assetFiles: this.config.assetFiles,
logger: this.logger,
plugins: this.plugins
});
var embarkJSABI = abiGenerator.generateABI({useEmbarkJS: true});
var vanillaABI = abiGenerator.generateABI({useEmbarkJS: false});
var vanillaContractsABI = abiGenerator.generateContracts(false);
this.events.on('abi', function (abi, contractsJSON) {
self.currentAbi = abi;
self.contractsJSON = contractsJSON;
pipeline.build(abi, contractsJSON);
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, self.contractsJSON, path);
// self.events.emit('outputDone');
// }
//});
}
self.events.emit('abi-contracts-vanila', vanillaContractsABI);
self.events.emit('abi-vanila', vanillaABI);
self.events.emit('abi', embarkJSABI);
};
this.events.on('contractsDeployed', generateABICode);
this.events.on('blockchainDisabled', generateABICode);
};
abiService(options) {
let self = this;
let generateABICode = function (contractsManager) {
let abiGenerator = new ABIGenerator({
blockchainConfig: self.config.blockchainConfig,
contractsManager: contractsManager,
plugins: self.plugins,
storageConfig: self.config.storageConfig,
communicationConfig: self.config.communicationConfig
});
let embarkJSABI = abiGenerator.generateABI({useEmbarkJS: true});
let vanillaABI = abiGenerator.generateABI({useEmbarkJS: false});
let vanillaContractsABI = abiGenerator.generateContracts(false);
let contractsJSON = abiGenerator.generateContractsJSON();
Engine.prototype.deploymentService = function(options) {
var self = this;
this.deployManager = new DeployManager({
web3: options.web3,
trackContracts: options.trackContracts,
config: this.config,
logger: this.logger,
plugins: this.plugins,
events: this.events
});
self.events.emit('abi-contracts-vanila', vanillaContractsABI, contractsJSON);
self.events.emit('abi-vanila', vanillaABI, contractsJSON);
self.events.emit('abi', embarkJSABI, contractsJSON);
};
this.events.on('contractsDeployed', generateABICode);
this.events.on('blockchainDisabled', generateABICode);
}
this.events.on('file-event', function(fileType, path) {
// 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') {
deploymentService(options) {
let self = this;
this.deployManager = new DeployManager({
web3: options.web3 || self.web3,
trackContracts: options.trackContracts,
config: this.config,
logger: this.logger,
plugins: this.plugins,
events: this.events
});
this.events.on('file-event', function (fileType, path) {
// 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() {});
//}
});
};
self.deployManager.deployContracts(function () {
});
//}
});
}
Engine.prototype.fileWatchService = function(options) {
this.logger.setStatus("Watching for changes");
var watch = new Watch({logger: this.logger, events: this.events});
watch.start();
};
fileWatchService(options) {
this.logger.setStatus("Watching for changes");
let watch = new Watch({logger: this.logger, events: this.events});
watch.start();
}
Engine.prototype.webServerService = function(options) {
var webServerConfig = this.config.webServerConfig;
if (!webServerConfig.enabled) { return; }
this.logger.setStatus("Starting Server");
var server = new Server({
logger: this.logger,
host: options.host || webServerConfig.host,
port: options.port || webServerConfig.port
});
server.start(function(){});
};
webServerService(options) {
let self = this;
let webServerConfig = this.config.webServerConfig;
if (!webServerConfig.enabled) {
return;
}
let host = options.host || webServerConfig.host;
let port = options.port || webServerConfig.port;
this.logger.setStatus("Starting Server");
let server = new Server({
logger: this.logger,
host: host,
port: port
});
self.servicesMonitor.addCheck('Webserver', function (cb) {
let devServer = 'Webserver (http://' + host + ':' + port + ')';
return cb({name: devServer, status: 'on'});
});
server.start(function () {
});
}
ipfsService(options) {
let 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...");
utils.httpGet('http://localhost:5001/api/v0/version', function (res) {
let body = '';
res.on('data', function (d) {
body += d;
});
res.on('end', function () {
try {
let parsed = JSON.parse(body);
if (parsed.Version) {
return cb({name: ("IPFS " + parsed.Version), status: 'on'});
}
else {
return cb({name: "IPFS ", status: 'on'});
}
}
catch (e) {
return cb({name: "IPFS ", status: 'off'});
}
});
res.on('error', function (err) {
self.logger.trace("Check IPFS version error: " + err);
return cb({name: "IPFS ", status: 'off'});
});
});
}
else {
return cb({name: "IPFS ", status: 'off'});
}
});
});
}
web3Service(options) {
let self = this;
this.web3 = options.web3;
if (this.web3 === undefined) {
this.web3 = new Web3();
let 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: 'on'
});
} else {
return cb({name: "No Blockchain node found", status: 'off'});
}
});
self.servicesMonitor.addCheck('Whisper', function (cb) {
self.web3.version.getWhisper(function (err, version) {
if (err) {
return cb({name: 'Whisper', status: 'off'});
} else if (version >= 5) {
return cb({name: 'Whisper (version ' + version + ') - unsupported', status: 'warn'});
} else {
return cb({name: 'Whisper (version ' + version + ')', status: 'on'});
}
});
});
}
}
module.exports = Engine;

View File

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

View File

@ -1,40 +1,52 @@
var colors = require('colors');
let colors = require('colors');
var Logger = function(options) {
this.logLevels = ['error', 'warn', 'info', 'debug', 'trace'];
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;
};
class Logger {
constructor(options) {
this.logLevels = ['error', 'warn', 'info', 'debug', 'trace'];
this.logLevel = options.logLevel || 'info';
this.logFunction = options.logFunction || console.log;
this.contractsState = options.contractsState || function () {
};
this.setStatus = options.setStatus || console.log;
}
}
Logger.prototype.error = function(txt) {
if (!(this.shouldLog('error'))) { return; }
Logger.prototype.error = function (txt) {
if (!txt || !(this.shouldLog('error'))) {
return;
}
this.logFunction(txt.red);
};
Logger.prototype.warn = function(txt) {
if (!(this.shouldLog('warn'))) { return; }
Logger.prototype.warn = function (txt) {
if (!txt || !(this.shouldLog('warn'))) {
return;
}
this.logFunction(txt.yellow);
};
Logger.prototype.info = function(txt) {
if (!(this.shouldLog('info'))) { return; }
Logger.prototype.info = function (txt) {
if (!txt || !(this.shouldLog('info'))) {
return;
}
this.logFunction(txt.green);
};
Logger.prototype.debug = function(txt) {
if (!(this.shouldLog('debug'))) { return; }
Logger.prototype.debug = function (txt) {
if (!txt || !(this.shouldLog('debug'))) {
return;
}
this.logFunction(txt);
};
Logger.prototype.trace = function(txt) {
if (!(this.shouldLog('trace'))) { return; }
Logger.prototype.trace = function (txt) {
if (!txt || !(this.shouldLog('trace'))) {
return;
}
this.logFunction(txt);
};
Logger.prototype.shouldLog = function(level) {
Logger.prototype.shouldLog = function (level) {
return (this.logLevels.indexOf(level) <= this.logLevels.indexOf(this.logLevel));
};

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,5 +1,5 @@
var Web3 = require('web3');
var web3;
let Web3 = require('web3');
let web3;
// ======================
// the eval is used for evaluating some of the contact calls for different purposes

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 @@
let async = require('../utils/async_extend.js');
class ServicesMonitor {
constructor(options) {
this.events = options.events;
this.logger = options.logger;
this.checkList = {};
this.checkTimers = {};
this.checkState = {};
this.working = false;
}
}
ServicesMonitor.prototype.initCheck = function (checkName) {
let self = this;
let check = this.checkList[checkName];
if (!check) {
return false;
}
self.events.on('check:' + checkName, function (obj) {
if (check && check.status === 'off' && obj.status === 'on') {
self.events.emit('check:backOnline:' + checkName);
}
if (check && check.status === 'on' && obj.status === 'off') {
self.events.emit('check:wentOffline:' + checkName);
}
self.checkState[checkName] = {name: obj.name, status: 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) {
let 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 () {
let 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

@ -12,6 +12,7 @@ var Deploy = require('../contracts/deploy.js');
var Config = require('./config.js');
var RunCode = require('./runCode.js');
var TestLogger = require('./test_logger.js');
var web3;
var getSimulator = function() {
try {
@ -45,7 +46,7 @@ var Test = function(options) {
});
this.engine.init({
logger: new TestLogger({logLevel: this.options.logLevel || 'debug'})
logger: new TestLogger({logLevel: 'debug'})
});
this.sim = getSimulator();

View File

@ -1,52 +1,65 @@
var colors = require('colors');
let colors = require('colors');
// TODO: just logFunction changes, probably doesn't need a whole new module just
// for this
var TestLogger = function(options) {
this.logLevels = ['error', 'warn', 'info', 'debug', 'trace'];
this.logs = [];
this.logLevel = options.logLevel || 'info';
};
class TestLogger {
constructor(options) {
this.logLevels = ['error', 'warn', 'info', 'debug', 'trace'];
this.logs = [];
this.logLevel = options.logLevel || 'info';
}
TestLogger.prototype.logFunction = function() {
this.logs.push(arguments);
};
logFunction() {
this.logs.push(arguments);
}
TestLogger.prototype.contractsState = function() {
this.logs.push(arguments);
};
contractsState() {
this.logs.push(arguments);
}
TestLogger.prototype.availableServices = function() {
this.logs.push(arguments);
};
availableServices() {
this.logs.push(arguments);
}
TestLogger.prototype.error = function(txt) {
if (!(this.shouldLog('error'))) { return; }
this.logFunction(txt.red);
};
error(txt) {
if (!(this.shouldLog('error'))) {
return;
}
this.logFunction(txt.red);
}
TestLogger.prototype.warn = function(txt) {
if (!(this.shouldLog('warn'))) { return; }
this.logFunction(txt.yellow);
};
warn(txt) {
if (!(this.shouldLog('warn'))) {
return;
}
this.logFunction(txt.yellow);
}
TestLogger.prototype.info = function(txt) {
if (!(this.shouldLog('info'))) { return; }
this.logFunction(txt.green);
};
info(txt) {
if (!(this.shouldLog('info'))) {
return;
}
this.logFunction(txt.green);
}
TestLogger.prototype.debug = function(txt) {
if (!(this.shouldLog('debug'))) { return; }
this.logFunction(txt);
};
debug(txt) {
if (!(this.shouldLog('debug'))) {
return;
}
this.logFunction(txt);
}
TestLogger.prototype.trace = function(txt) {
if (!(this.shouldLog('trace'))) { return; }
this.logFunction(txt);
};
trace(txt) {
if (!(this.shouldLog('trace'))) {
return;
}
this.logFunction(txt);
}
TestLogger.prototype.shouldLog = function(level) {
return (this.logLevels.indexOf(level) <= this.logLevels.indexOf(this.logLevel));
};
shouldLog(level) {
return (this.logLevels.indexOf(level) <= this.logLevels.indexOf(this.logLevel));
}
}
module.exports = TestLogger;

View File

@ -1,28 +1,29 @@
var CommandHistory = function() {
this.history = [];
this.pointer = -1;
};
CommandHistory.prototype.addCommand = function(cmd) {
this.history.push(cmd);
this.pointer = this.history.length;
};
CommandHistory.prototype.getPreviousCommand = function(cmd) {
if (this.pointer >= 0) {
this.pointer--;
class CommandHistory {
constructor() {
this.history = [];
this.pointer = -1;
}
return this.history[this.pointer];
};
CommandHistory.prototype.getNextCommand = function(cmd) {
if (this.pointer >= this.history.length) {
this.pointer = this.history.length - 1;
return '';
addCommand(cmd) {
this.history.push(cmd);
this.pointer = this.history.length;
}
this.pointer++;
return this.history[this.pointer];
};
getPreviousCommand(cmd) {
if (this.pointer >= 0) {
this.pointer--;
}
return this.history[this.pointer];
}
getNextCommand(cmd) {
if (this.pointer >= this.history.length) {
this.pointer = this.history.length - 1;
return '';
}
this.pointer++;
return this.history[this.pointer];
}
}
module.exports = CommandHistory;

View File

@ -1,60 +1,62 @@
var utils = require('../core/utils.js');
var RunCode = require('../core/runCode.js');
let utils = require('../utils/utils.js');
let RunCode = require('../core/runCode.js');
var Console = function(options) {
this.plugins = options.plugins;
this.version = options.version;
};
Console.prototype.runCode = function(code) {
RunCode.doEval(code); // jshint ignore:line
};
Console.prototype.processEmbarkCmd = function(cmd) {
if (cmd === 'help') {
var helpText = [
'Welcome to Embark ' + this.version,
'',
'possible commands are:',
// TODO: only if the blockchain is actually active!
// will need to pass te current embark state here
'web3 - instantiated web3.js object configured to the current environment',
'quit - to immediatly exit',
'',
'The web3 object and the interfaces for the deployed contracts and their methods are also available'
];
return helpText.join('\n');
} else if (cmd === 'quit') {
utils.exit();
}
return false;
};
Console.prototype.executeCmd = function(cmd, callback) {
var plugin, pluginOutput;
var plugins = this.plugins.getPluginsFor('console');
for (var i = 0; i < plugins.length; i++) {
plugin = plugins[i];
pluginOutput = plugin.runCommands(cmd, {});
if (pluginOutput !== false && pluginOutput !== 'false') return callback(pluginOutput);
class Console {
constructor(options) {
this.plugins = options.plugins;
this.version = options.version;
}
var output = this.processEmbarkCmd(cmd);
if (output) {
return callback(output);
runCode(code) {
RunCode.doEval(code); // jshint ignore:line
}
try {
var result = RunCode.doEval(cmd);
return callback(result);
processEmbarkCmd (cmd) {
if (cmd === 'help') {
let helpText = [
'Welcome to Embark ' + this.version,
'',
'possible commands are:',
// TODO: only if the blockchain is actually active!
// will need to pass te current embark state here
'web3 - instantiated web3.js object configured to the current environment',
'quit - to immediatly exit',
'',
'The web3 object and the interfaces for the deployed contracts and their methods are also available'
];
return helpText.join('\n');
} else if (cmd === 'quit') {
utils.exit();
}
return false;
}
catch(e) {
if (e.message.indexOf('not defined') > 0) {
return callback(("error: " + e.message).red + ("\nType " + "help".bold + " to see the list of available commands").cyan);
} else {
return callback(e.message);
executeCmd(cmd, callback) {
var plugin, pluginOutput;
var plugins = this.plugins.getPluginsFor('console');
for (var i = 0; i < plugins.length; i++) {
plugin = plugins[i];
pluginOutput = plugin.runCommands(cmd, {});
if (pluginOutput !== false && pluginOutput !== 'false') return callback(pluginOutput);
}
let output = this.processEmbarkCmd(cmd);
if (output) {
return callback(output);
}
try {
let result = RunCode.doEval(cmd);
return callback(result);
}
catch (e) {
if (e.message.indexOf('not defined') > 0) {
return callback(("error: " + e.message).red + ("\nType " + "help".bold + " to see the list of available commands").cyan);
} else {
return callback(e.message);
}
}
}
};
}
module.exports = Console;

View File

@ -1,43 +1,45 @@
var async = require('async');
let async = require('async');
var Monitor = require('./monitor.js');
var Console = require('./console.js');
let Monitor = require('./monitor.js');
let Console = require('./console.js');
var Dashboard = function(options) {
this.logger = options.logger;
this.plugins = options.plugins;
this.version = options.version;
this.env = options.env;
};
class Dashboard {
constructor(options) {
this.logger = options.logger;
this.plugins = options.plugins;
this.version = options.version;
this.env = options.env;
}
Dashboard.prototype.start = function(done) {
var console, monitor;
var self = this;
start(done) {
let console, monitor;
let self = this;
async.waterfall([
function startConsole(callback) {
console = new Console({plugins: self.plugins, version: self.version});
callback();
},
function startMonitor(callback) {
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);
async.waterfall([
function startConsole(callback) {
console = new Console({plugins: self.plugins, version: self.version});
callback();
},
function startMonitor(callback) {
monitor = new Monitor({env: self.env, console: console});
self.logger.logFunction = monitor.logEntry;
self.logger.contractsState = monitor.setContracts;
self.logger.setStatus = monitor.setStatus.bind(monitor);
self.logger.info('========================'.bold.green);
self.logger.info(('Welcome to Embark ' + self.version).yellow.bold);
self.logger.info('========================'.bold.green);
self.logger.info('========================'.bold.green);
self.logger.info(('Welcome to Embark ' + self.version).yellow.bold);
self.logger.info('========================'.bold.green);
// TODO: do this after monitor is rendered
callback();
}
], function() {
self.console = console;
self.monitor = monitor;
done();
});
};
// TODO: do this after monitor is rendered
callback();
}
], function () {
self.console = console;
self.monitor = monitor;
done();
});
}
}
module.exports = Dashboard;

View File

@ -1,348 +1,365 @@
/*jshint esversion: 6 */
var blessed = require("blessed");
var CommandHistory = require('./command_history.js');
let blessed = require("blessed");
let CommandHistory = require('./command_history.js');
function Dashboard(options) {
var title = (options && options.title) || "Embark 2.4.2";
this.env = options.env;
this.console = options.console;
this.history = new CommandHistory();
class Dashboard {
constructor(options) {
let title = (options && options.title) || "Embark " + options.version;
this.env = options.env;
this.console = options.console;
this.history = new CommandHistory();
this.color = (options && options.color) || "green";
this.minimal = (options && options.minimal) || false;
this.color = (options && options.color) || "green";
this.minimal = (options && options.minimal) || false;
this.screen = blessed.screen({
smartCSR: true,
title: title,
dockBorders: false,
fullUnicode: true,
autoPadding: true
});
this.screen = blessed.screen({
smartCSR: true,
title: title,
dockBorders: false,
fullUnicode: true,
autoPadding: true
});
this.layoutLog();
this.layoutStatus();
this.layoutModules();
this.layoutCmd();
this.layoutLog();
this.layoutStatus();
this.layoutModules();
this.layoutCmd();
this.screen.key(["C-c"], function() {
process.exit(0);
});
this.screen.key(["C-c"], function () {
process.exit(0);
});
this.logEntry = this.logEntry.bind(this);
this.setContracts = this.setContracts.bind(this);
this.availableServices = this.availableServices.bind(this);
this.logEntry = this.logEntry.bind(this);
this.setContracts = this.setContracts.bind(this);
this.availableServices = this.availableServices.bind(this);
this.status.setContent(this.env.green);
this.status.setContent(this.env.green);
this.screen.render();
this.input.focus();
}
availableServices(_services) {
let services = [];
let check;
for (check in _services) {
let checkObj = _services[check];
if (checkObj.status === 'on') {
services.push(checkObj.name.green);
} else if (checkObj.status === 'off') {
services.push(checkObj.name.red);
} else if (checkObj.status === 'warn') {
services.push(checkObj.name.grey);
} else {
services.push(checkObj.name);
}
}
this.progress.setContent(services.join('\n'));
this.screen.render();
}
setStatus(status) {
this.operations.setContent(status);
this.screen.render();
}
setContracts(contracts) {
let data = [];
data.push(["Contract Name", "Address", "Status"]);
contracts.forEach(function (row) {
data.push(row);
});
this.moduleTable.setData(data);
this.screen.render();
}
logEntry(text) {
this.logText.log(text);
this.screen.render();
}
layoutLog() {
this.log = blessed.box({
label: "Logs",
padding: 1,
width: "100%",
height: "55%",
left: "0%",
top: "42%",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.logText = blessed.log({
parent: this.log,
tags: true,
width: "100%-5",
//height: '90%',
scrollable: true,
input: false,
alwaysScroll: true,
scrollbar: {
ch: " ",
inverse: true
},
keys: false,
vi: false,
mouse: true
});
this.screen.append(this.log);
}
layoutModules() {
this.modules = blessed.box({
label: "Contracts",
tags: true,
padding: 1,
width: "75%",
height: "42%",
left: "0%",
top: "0",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.moduleTable = blessed.table({
parent: this.modules,
height: "100%",
width: "100%-5",
align: "left",
pad: 1,
margin: "auto",
shrink: true,
scrollable: true,
alwaysScroll: true,
scrollbar: {
ch: " ",
inverse: true
},
keys: false,
vi: false,
mouse: true,
data: [["ContractName", "Address", "Status"]]
});
this.screen.append(this.modules);
}
layoutAssets() {
this.assets = blessed.box({
label: "Asset Pipeline",
tags: true,
padding: 1,
width: "50%",
height: "55%",
left: "50%",
top: "42%",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.assetTable = blessed.table({
parent: this.assets,
height: "100%",
width: "100%-5",
align: "left",
pad: 1,
scrollable: true,
alwaysScroll: true,
scrollbar: {
ch: " ",
inverse: true
},
keys: false,
vi: false,
mouse: true,
data: [["Name", "Size"]]
});
this.screen.append(this.assets);
}
layoutStatus() {
this.wrapper = blessed.layout({
width: "25%",
height: "42%",
top: "0%",
left: "75%",
layout: "grid"
});
this.status = blessed.box({
parent: this.wrapper,
label: "Environment",
tags: true,
padding: {
left: 1
},
width: "100%",
height: "20%",
valign: "middle",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.operations = blessed.box({
parent: this.wrapper,
label: "Status",
tags: true,
padding: {
left: 1
},
width: "100%",
height: "20%",
valign: "middle",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.progress = blessed.box({
parent: this.wrapper,
label: "Available Services",
tags: true,
padding: this.minimal ? {
left: 1
} : 1,
width: "100%",
height: "60%",
valign: "top",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.screen.append(this.wrapper);
}
layoutCmd() {
this.consoleBox = blessed.box({
label: 'Console',
tags: true,
padding: 0,
width: '100%',
height: '6%',
left: '0%',
top: '95%',
border: {
type: 'line'
},
style: {
fg: 'black',
border: {
fg: this.color
}
}
});
this.input = blessed.textbox({
parent: this.consoleBox,
name: 'input',
input: true,
keys: false,
top: 0,
left: 1,
height: '50%',
width: '100%-2',
inputOnFocus: true,
style: {
fg: 'green',
bg: 'black',
focus: {
bg: 'black',
fg: 'green'
}
}
});
let self = this;
this.input.key(["C-c"], function () {
process.exit(0);
});
this.input.key(["C-w"], function () {
self.input.clearValue();
self.input.focus();
});
this.input.key(["up"], function () {
let cmd = self.history.getPreviousCommand();
self.input.setValue(cmd);
self.input.focus();
});
this.input.key(["down"], function () {
let cmd = self.history.getNextCommand();
self.input.setValue(cmd);
self.input.focus();
});
this.input.on('submit', function (data) {
if (data !== '') {
self.history.addCommand(data);
self.logText.log('console> '.bold.green + data);
self.console.executeCmd(data, function (result) {
self.logText.log(result);
});
}
self.input.clearValue();
self.input.focus();
});
this.screen.append(this.consoleBox);
}
this.screen.render();
this.input.focus();
}
Dashboard.prototype.availableServices = function(services) {
this.progress.setContent(services.join('\n'));
this.screen.render();
};
Dashboard.prototype.setStatus = function(status) {
this.operations.setContent(status);
this.screen.render();
};
Dashboard.prototype.setContracts = function(contracts) {
var data = [];
data.push(["Contract Name", "Address", "Status"]);
contracts.forEach(function(row) {
data.push(row);
});
this.moduleTable.setData(data);
this.screen.render();
};
Dashboard.prototype.logEntry = function(text) {
this.logText.log(text);
this.screen.render();
};
Dashboard.prototype.layoutLog = function() {
this.log = blessed.box({
label: "Logs",
padding: 1,
width: "100%",
height: "55%",
left: "0%",
top: "42%",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.logText = blessed.log({
parent: this.log,
tags: true,
width: "100%-5",
//height: '90%',
scrollable: true,
input: false,
alwaysScroll: true,
scrollbar: {
ch: " ",
inverse: true
},
keys: false,
vi: false,
mouse: true
});
this.screen.append(this.log);
};
Dashboard.prototype.layoutModules = function() {
this.modules = blessed.box({
label: "Contracts",
tags: true,
padding: 1,
width: "75%",
height: "42%",
left: "0%",
top: "0",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.moduleTable = blessed.table({
parent: this.modules,
height: "100%",
width: "100%-5",
align: "left",
pad: 1,
margin: "auto",
shrink: true,
scrollable: true,
alwaysScroll: true,
scrollbar: {
ch: " ",
inverse: true
},
keys: false,
vi: false,
mouse: true,
data: [["ContractName", "Address", "Status"]]
});
this.screen.append(this.modules);
};
Dashboard.prototype.layoutAssets = function() {
this.assets = blessed.box({
label: "Asset Pipeline",
tags: true,
padding: 1,
width: "50%",
height: "55%",
left: "50%",
top: "42%",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.assetTable = blessed.table({
parent: this.assets,
height: "100%",
width: "100%-5",
align: "left",
pad: 1,
scrollable: true,
alwaysScroll: true,
scrollbar: {
ch: " ",
inverse: true
},
keys: false,
vi: false,
mouse: true,
data: [["Name", "Size"]]
});
this.screen.append(this.assets);
};
Dashboard.prototype.layoutStatus = function() {
this.wrapper = blessed.layout({
width: "25%",
height: "42%",
top: "0%",
left: "75%",
layout: "grid"
});
this.status = blessed.box({
parent: this.wrapper,
label: "Environment",
tags: true,
padding: {
left: 1
},
width: "100%",
height: "20%",
valign: "middle",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.operations = blessed.box({
parent: this.wrapper,
label: "Status",
tags: true,
padding: {
left: 1
},
width: "100%",
height: "20%",
valign: "middle",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.progress = blessed.box({
parent: this.wrapper,
label: "Available Services",
tags: true,
padding: this.minimal ? {
left: 1
} : 1,
width: "100%",
height: "60%",
valign: "top",
border: {
type: "line"
},
style: {
fg: -1,
border: {
fg: this.color
}
}
});
this.screen.append(this.wrapper);
};
Dashboard.prototype.layoutCmd = function() {
this.consoleBox = blessed.box({
label: 'Console',
tags: true,
padding: 0,
width: '100%',
height: '6%',
left: '0%',
top: '95%',
border: {
type: 'line'
},
style: {
fg: 'black',
border: {
fg: this.color
}
}
});
this.input = blessed.textbox({
parent: this.consoleBox,
name: 'input',
input: true,
keys: false,
top: 0,
left: 1,
height: '50%',
width: '100%-2',
inputOnFocus: true,
style: {
fg: 'green',
bg: 'black',
focus: {
bg: 'black',
fg: 'green'
}
}
});
var self = this;
this.input.key(["C-c"], function() {
process.exit(0);
});
this.input.key(["C-w"], function() {
self.input.clearValue();
self.input.focus();
});
this.input.key(["up"], function() {
var cmd = self.history.getPreviousCommand();
self.input.setValue(cmd);
self.input.focus();
});
this.input.key(["down"], function() {
var cmd = self.history.getNextCommand();
self.input.setValue(cmd);
self.input.focus();
});
this.input.on('submit', function(data) {
if (data !== '') {
self.history.addCommand(data);
self.logText.log('console> '.bold.green + data);
self.console.executeCmd(data, function(result) {
self.logText.log(result);
});
}
self.input.clearValue();
self.input.focus();
});
this.screen.append(this.consoleBox);
};
module.exports = Dashboard;

View File

@ -1,74 +1,68 @@
/*jshint esversion: 6 */
var async = require('async');
//require("./core/debug_util.js")(__filename, async);
let async = require('async');
// require("./utils/debug_util.js")(__filename, async);
var Web3 = require('web3');
var colors = require('colors');
let colors = require('colors');
var Engine = require('./core/engine.js');
let 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');
let IPFS = require('./upload/ipfs.js');
let Swarm = require('./upload/swarm.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');
let version = require('../package.json').version;
var Dashboard = require('./dashboard/dashboard.js');
class Embark {
var IPFS = require('./upload/ipfs.js');
var Swarm = require('./upload/swarm.js');
constructor (options) {
this.version = version;
this.options = options || {};
}
var Cmd = require('./cmd.js');
initConfig(env, options) {
let Events = require('./core/events.js');
let Logger = require('./core/logger.js');
let Config = require('./core/config.js');
var Embark = {
version: '2.4.2',
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();
},
blockchain(env, client) {
return require('./cmds/blockchain/blockchain.js')(this.config.blockchainConfig, client, env).run();
}
simulator: function(options) {
var simulator = new Simulator({blockchainConfig: this.config.blockchainConfig});
simulator(options) {
let Simulator = require('./cmds/simulator.js');
let simulator = new Simulator({blockchainConfig: this.config.blockchainConfig});
simulator.run(options);
},
}
generateTemplate: function(templateName, destinationFolder, name) {
var templateGenerator = new TemplateGenerator(templateName);
generateTemplate(templateName, destinationFolder, name) {
let TemplateGenerator = require('./cmds/template_generator.js');
let templateGenerator = new TemplateGenerator(templateName);
templateGenerator.generate(destinationFolder, name);
},
}
run: function(options) {
var self = this;
var env = options.env;
run(options) {
let self = this;
let Dashboard = require('./dashboard/dashboard.js');
var engine = new Engine({
let env = options.env;
let engine = new Engine({
env: options.env,
embarkConfig: 'embark.json'
version: this.version,
embarkConfig: options.embarkConfig || 'embark.json'
});
engine.init();
if (!options.useDashboard) {
console.log('========================'.bold.green);
console.log(('Welcome to Embark ' + Embark.version).yellow.bold);
console.log(('Welcome to Embark ' + this.version).yellow.bold);
console.log('========================'.bold.green);
}
@ -78,38 +72,47 @@ var Embark = {
return callback();
}
var dashboard = new Dashboard({
let dashboard = new Dashboard({
logger: engine.logger,
plugins: engine.plugins,
version: engine.version,
version: self.version,
env: engine.env
});
dashboard.start(function() {
engine.events.on('abi-vanila', function(abi) {
dashboard.start(function () {
engine.events.on('abi-vanila', function (abi) {
dashboard.console.runCode(abi);
});
engine.logger.info('dashboard start');
engine.events.on('servicesState', function (servicesState) {
dashboard.monitor.availableServices(servicesState);
});
callback();
});
},
function (callback) {
var pluginList = engine.plugins.listPlugins();
let pluginList = engine.plugins.listPlugins();
if (pluginList.length > 0) {
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.deployManager.deployContracts(function() {
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 (err) {
engine.startService("fileWatcher");
if (options.runWebserver) {
engine.startService("webServer", {
@ -117,12 +120,13 @@ var Embark = {
port: options.serverPort
});
}
callback();
callback(err);
});
}
], function(err, result) {
], function (err, result) {
if (err) {
engine.logger.error(err.message);
engine.logger.info(err.stack);
} else {
engine.logger.setStatus("Ready".green);
engine.logger.info("Looking for documentation? you can find it at ".cyan + "http://embark.readthedocs.io/".green.underline);
@ -130,13 +134,13 @@ var Embark = {
engine.events.emit('firstDeploymentDone');
}
});
},
}
build: function(options) {
var self = this;
build(options) {
var engine = new Engine({
let engine = new Engine({
env: options.env,
version: this.version,
embarkConfig: 'embark.json',
interceptLogs: false
});
@ -144,43 +148,46 @@ var Embark = {
async.waterfall([
function startServices(callback) {
var pluginList = engine.plugins.listPlugins();
let pluginList = engine.plugins.listPlugins();
if (pluginList.length > 0) {
engine.logger.info("loaded plugins: " + pluginList.join(", "));
}
engine.startService("web3");
engine.startService("pipeline");
engine.startService("abi");
engine.startService("deployment");
callback();
},
function deploy(callback) {
engine.deployManager.deployContracts(function() {
callback();
engine.deployManager.deployContracts(function (err) {
callback(err);
});
}
], function(err, result) {
], function (err, result) {
if (err) {
engine.logger.error(err.message);
engine.logger.debug(err.stack);
} else {
engine.logger.info("finished building".underline);
}
// needed due to child processes
process.exit();
});
},
}
initTests: function(options) {
initTests(options) {
let Test = require('./core/test.js');
return new Test(options);
},
}
// TODO: should deploy if it hasn't already
upload: function(platform) {
upload(platform) {
if (platform === 'ipfs') {
var ipfs = new IPFS({buildDir: 'dist/', plugins: this.plugins, storageConfig: this.config.storageConfig});
let ipfs = new IPFS({buildDir: 'dist/', plugins: this.plugins, storageConfig: this.config.storageConfig});
ipfs.deploy();
} else if (platform === 'swarm') {
var swarm = new Swarm({buildDir: 'dist/', plugins: this.plugins, storageConfig: this.config.storageConfig});
let swarm = new Swarm({buildDir: 'dist/', plugins: this.plugins, storageConfig: this.config.storageConfig});
swarm.deploy();
} else {
console.log(("unknown platform: " + platform).red);
@ -188,7 +195,12 @@ var Embark = {
}
}
}
// temporary until next refactor
Embark.initTests = function(options) {
let Test = require('./core/test.js');
return new Test(options);
};
module.exports = Embark;

View File

@ -1,80 +1,94 @@
/*jshint esversion: 6, loopfunc: true */
var fs = require('../core/fs.js');
let fs = require('../core/fs.js');
var Pipeline = function(options) {
this.buildDir = options.buildDir;
this.contractsFiles = options.contractsFiles;
this.assetFiles = options.assetFiles;
this.logger = options.logger;
this.plugins = options.plugins;
};
class Pipeline {
Pipeline.prototype.build = function(abi, path) {
var self = this;
for(var targetFile in this.assetFiles) {
constructor(options) {
this.buildDir = options.buildDir;
this.contractsFiles = options.contractsFiles;
this.assetFiles = options.assetFiles;
this.logger = options.logger;
this.plugins = options.plugins;
}
var contentFiles = this.assetFiles[targetFile].map(file => {
self.logger.trace("reading " + file.filename);
build(abi, contractsJSON, path) {
let self = this;
for (let targetFile in this.assetFiles) {
var pipelinePlugins = this.plugins.getPluginsFor('pipeline');
let contentFiles = this.assetFiles[targetFile].map(file => {
self.logger.trace("reading " + file.filename);
if (file.filename === 'embark.js') {
return {content: file.content + "\n" + abi, filename: file.filename, path: file.path, modified: true};
} else if (file.filename === 'abi.js') {
return {content: abi, filename: file.filename, path: file.path, modified: true};
} else if (['web3.js', 'ipfs.js', 'ipfs-api.js', 'orbit.js'].indexOf(file.filename) >= 0) {
file.modified = true;
return file;
} else {
let pipelinePlugins = this.plugins.getPluginsFor('pipeline');
if (pipelinePlugins.length > 0) {
pipelinePlugins.forEach(function(plugin) {
try {
if (file.options && file.options.skipPipeline) {
return;
if (file.filename === 'embark.js') {
return {content: file.content + "\n" + abi, filename: file.filename, path: file.path, modified: true};
} else if (file.filename === 'abi.js') {
return {content: abi, filename: file.filename, path: file.path, modified: true};
} else if (['web3.js', 'ipfs.js', 'ipfs-api.js', 'orbit.js'].indexOf(file.filename) >= 0) {
file.modified = true;
return file;
} else {
if (pipelinePlugins.length > 0) {
pipelinePlugins.forEach(function (plugin) {
try {
if (file.options && file.options.skipPipeline) {
return;
}
file.content = plugin.runPipeline({targetFile: file.filename, source: file.content});
file.modified = true;
}
file.content = plugin.runPipeline({targetFile: file.filename, source: file.content});
file.modified = true;
}
catch(err) {
self.logger.error(err.message);
}
});
catch (err) {
self.logger.error(err.message);
}
});
}
return file;
}
});
let dir = targetFile.split('/').slice(0, -1).join('/');
self.logger.trace("creating dir " + this.buildDir + dir);
fs.mkdirpSync(this.buildDir + dir);
// if it's a directory
if (targetFile.slice(-1) === '/' || targetFile.indexOf('.') === -1) {
let targetDir = targetFile;
if (targetDir.slice(-1) !== '/') {
targetDir = targetDir + '/';
}
return file;
contentFiles.map(function (file) {
let filename = file.filename.replace('app/', '');
filename = filename.replace(targetDir, '');
self.logger.info("writing file " + (self.buildDir + targetDir + filename).bold.dim);
fs.copySync(self.buildDir + targetDir + filename, file.path, {overwrite: true});
});
} else {
let content = contentFiles.map(function (file) {
return file.content;
}).join("\n");
self.logger.info("writing file " + (this.buildDir + targetFile).bold.dim);
fs.writeFileSync(this.buildDir + targetFile, content);
}
});
}
var dir = targetFile.split('/').slice(0, -1).join('/');
self.logger.trace("creating dir " + this.buildDir + dir);
fs.mkdirpSync(this.buildDir + dir);
this.buildContracts(contractsJSON);
}
// if it's a directory
if (targetFile.slice(-1) === '/' || targetFile.indexOf('.') === -1) {
var targetDir = targetFile;
buildContracts(contractsJSON) {
fs.mkdirpSync(this.buildDir + 'contracts');
if (targetDir.slice(-1) !== '/') {
targetDir = targetDir + '/';
}
contentFiles.map(function(file) {
var filename = file.filename.replace('app/', '');
filename = filename.replace(targetDir, '');
self.logger.info("writing file " + (self.buildDir + targetDir + filename).bold.dim);
fs.copySync(self.buildDir + targetDir + filename, file.path, {overwrite: true});
});
} else {
var content = contentFiles.map(function(file) {
return file.content;
}).join("\n");
self.logger.info("writing file " + (this.buildDir + targetFile).bold.dim);
fs.writeFileSync(this.buildDir + targetFile, content);
for (let className in contractsJSON) {
let contract = contractsJSON[className];
fs.writeJSONSync(this.buildDir + 'contracts/' + className + ".json", contract, {spaces: 2});
}
}
};
}
module.exports = Pipeline;

View File

@ -1,24 +1,27 @@
var finalhandler = require('finalhandler');
var http = require('http');
var serveStatic = require('serve-static');
let finalhandler = require('finalhandler');
let http = require('http');
let serveStatic = require('serve-static');
var Server = function(options) {
this.dist = options.dist || 'dist/';
this.port = options.port || 8000;
this.hostname = options.host || 'localhost';
this.logger = options.logger;
};
class Server {
constructor(options) {
this.dist = options.dist || 'dist/';
this.port = options.port || 8000;
this.hostname = options.host || 'localhost';
this.logger = options.logger;
}
Server.prototype.start = function(callback) {
var serve = serveStatic(this.dist, {'index': ['index.html', 'index.htm']});
start(callback) {
let serve = serveStatic(this.dist, {'index': ['index.html', 'index.htm']});
var server = http.createServer(function onRequest (req, res) {
serve(req, res, finalhandler(req, res));
});
let server = http.createServer(function onRequest(req, res) {
serve(req, res, finalhandler(req, res));
});
this.logger.info("webserver available at " + ("http://" + this.hostname + ":" + this.port).bold.underline.green);
server.listen(this.port, this.hostname) ;
callback();
};
this.logger.info("webserver available at " + ("http://" + this.hostname + ":" + this.port).bold.underline.green);
server.listen(this.port, this.hostname);
callback();
}
}
module.exports = Server;

View File

@ -1,101 +1,104 @@
/*jshint esversion: 6 */
var chokidar = require('chokidar');
let chokidar = require('chokidar');
var fs = require('../core/fs.js');
let fs = require('../core/fs.js');
// TODO: this should be receiving the config object not re-reading the
// embark.json file
var Watch = function(options) {
this.logger = options.logger;
this.events = options.events;
};
Watch.prototype.start = function() {
var self = this;
// TODO: should come from the config object instead of reading the file
// directly
var embarkConfig = fs.readJSONSync("embark.json");
this.watchAssets(embarkConfig, function() {
self.logger.trace('ready to watch asset changes');
});
this.watchContracts(embarkConfig, function() {
self.logger.trace('ready to watch contract changes');
});
this.watchConfigs(function() {
self.logger.trace('ready to watch config changes');
});
this.logger.info("ready to watch file changes");
};
Watch.prototype.watchAssets = function(embarkConfig, callback) {
var self = this;
var appConfig = embarkConfig.app;
var filesToWatch = [];
for(var targetFile in appConfig) {
filesToWatch.push(appConfig[targetFile]);
class Watch {
constructor(options) {
this.logger = options.logger;
this.events = options.events;
}
this.watchFiles(
filesToWatch,
function(eventName, path) {
self.logger.info(`${eventName}: ${path}`);
self.events.emit('file-' + eventName, 'asset', path);
self.events.emit('file-event', 'asset', path);
},
function() {
callback();
start() {
let self = this;
// TODO: should come from the config object instead of reading the file
// directly
let embarkConfig = fs.readJSONSync("embark.json");
this.watchAssets(embarkConfig, function () {
self.logger.trace('ready to watch asset changes');
});
this.watchContracts(embarkConfig, function () {
self.logger.trace('ready to watch contract changes');
});
this.watchConfigs(function () {
self.logger.trace('ready to watch config changes');
});
this.logger.info("ready to watch file changes");
}
watchAssets(embarkConfig, callback) {
let self = this;
let appConfig = embarkConfig.app;
let filesToWatch = [];
for (let targetFile in appConfig) {
filesToWatch.push(appConfig[targetFile]);
}
);
};
Watch.prototype.watchContracts = function(embarkConfig, callback) {
var self = this;
this.watchFiles(
[embarkConfig.contracts],
function(eventName, path) {
self.logger.info(`${eventName}: ${path}`);
self.events.emit('file-' + eventName, 'contract', path);
self.events.emit('file-event', 'contract', path);
},
function() {
callback();
}
);
};
this.watchFiles(
filesToWatch,
function (eventName, path) {
self.logger.info(`${eventName}: ${path}`);
self.events.emit('file-' + eventName, 'asset', path);
self.events.emit('file-event', 'asset', path);
},
function () {
callback();
}
);
}
Watch.prototype.watchConfigs = function(callback) {
var self = this;
this.watchFiles(
"config/**/contracts.json",
function(eventName, path) {
self.logger.info(`${eventName}: ${path}`);
self.events.emit('file-' + eventName, 'config', path);
self.events.emit('file-event', 'config', path);
},
function() {
callback();
}
);
};
watchContracts(embarkConfig, callback) {
let self = this;
this.watchFiles(
[embarkConfig.contracts],
function (eventName, path) {
self.logger.info(`${eventName}: ${path}`);
self.events.emit('file-' + eventName, 'contract', path);
self.events.emit('file-event', 'contract', path);
},
function () {
callback();
}
);
}
Watch.prototype.watchFiles = function(files, changeCallback, doneCallback) {
this.logger.trace('watchFiles');
this.logger.trace(files);
watchConfigs(callback) {
let self = this;
this.watchFiles(
"config/**/contracts.json",
function (eventName, path) {
self.logger.info(`${eventName}: ${path}`);
self.events.emit('file-' + eventName, 'config', path);
self.events.emit('file-event', 'config', path);
},
function () {
callback();
}
);
}
var configWatcher = chokidar.watch(files, {
ignored: /[\/\\]\./, persistent: true, ignoreInitial: true, followSymlinks: true
});
watchFiles(files, changeCallback, doneCallback) {
this.logger.trace('watchFiles');
this.logger.trace(files);
configWatcher
.on('add', path => changeCallback('add', path))
.on('change', path => changeCallback('change', path))
.on('unlink', path => changeCallback('remove', path))
.on('ready', doneCallback);
};
let configWatcher = chokidar.watch(files, {
ignored: /[\/\\]\./, persistent: true, ignoreInitial: true, followSymlinks: true
});
configWatcher
.on('add', path => changeCallback('add', path))
.on('change', path => changeCallback('change', path))
.on('unlink', path => changeCallback('remove', path))
.on('ready', doneCallback);
}
}
module.exports = Watch;

View File

@ -1,56 +1,60 @@
var colors = require('colors');
var async = require('async');
var shelljs = require('shelljs');
let colors = require('colors');
let async = require('async');
let shelljs = require('shelljs');
var IPFS = function(options) {
this.options = options;
this.buildDir = options.buildDir || 'dist/';
this.plugins = options.plugins;
this.storageConfig = options.storageConfig;
this.configIpfsBin = this.storageConfig.ipfs_bin || "ipfs";
};
class IPFS {
IPFS.prototype.deploy = function() {
var self = this;
async.waterfall([
function findBinary(callback) {
var ipfs_bin = shelljs.exec('which ' + self.configIpfsBin).output.split("\n")[0];
constructor(options) {
this.options = options;
this.buildDir = options.buildDir || 'dist/';
this.plugins = options.plugins;
this.storageConfig = options.storageConfig;
this.configIpfsBin = this.storageConfig.ipfs_bin || "ipfs";
}
if (ipfs_bin === 'ipfs not found' || ipfs_bin === ''){
console.log(('=== WARNING: ' + self.configIpfsBin + ' not found or not in the path. Guessing ~/go/bin/ipfs for path').yellow);
ipfs_bin = "~/go/bin/ipfs";
deploy() {
let self = this;
async.waterfall([
function findBinary(callback) {
let ipfs_bin = shelljs.exec('which ' + self.configIpfsBin).output.split("\n")[0];
if (ipfs_bin === 'ipfs not found' || ipfs_bin === '') {
console.log(('=== WARNING: ' + self.configIpfsBin + ' not found or not in the path. Guessing ~/go/bin/ipfs for path').yellow);
ipfs_bin = "~/go/bin/ipfs";
}
return callback(null, ipfs_bin);
},
function runCommand(ipfs_bin, callback) {
let cmd = ipfs_bin + " add -r " + self.buildDir;
console.log(("=== adding " + self.buildDir + " to ipfs").green);
console.log(cmd.green);
let result = shelljs.exec(cmd);
return callback(null, result);
},
function getHashFromOutput(result, callback) {
let rows = result.output.split("\n");
let dir_row = rows[rows.length - 2];
let dir_hash = dir_row.split(" ")[1];
return callback(null, dir_hash);
},
function printUrls(dir_hash, callback) {
console.log(("=== DApp available at http://localhost:8080/ipfs/" + dir_hash + "/").green);
console.log(("=== DApp available at http://gateway.ipfs.io/ipfs/" + dir_hash + "/").green);
return callback();
}
return callback(null, ipfs_bin);
},
function runCommand(ipfs_bin, callback) {
var cmd = ipfs_bin + " add -r " + self.buildDir;
console.log(("=== adding " + self.buildDir + " to ipfs").green);
console.log(cmd.green);
var result = shelljs.exec(cmd);
return callback(null, result);
},
function getHashFromOutput(result, callback) {
var rows = result.output.split("\n");
var dir_row = rows[rows.length - 2];
var dir_hash = dir_row.split(" ")[1];
return callback(null, dir_hash);
},
function printUrls(dir_hash, callback) {
console.log(("=== DApp available at http://localhost:8080/ipfs/" + dir_hash + "/").green);
console.log(("=== DApp available at http://gateway.ipfs.io/ipfs/" + dir_hash + "/").green);
return callback();
}
], function(err, result) {
], function (err, result) {
if (err) {
console.log("error uploading to ipfs".red);
console.log(err);
}
});
};
});
}
}
module.exports = IPFS;

View File

@ -1,55 +1,57 @@
var colors = require('colors');
var async = require('async');
var shelljs = require('shelljs');
let colors = require('colors');
let async = require('async');
let shelljs = require('shelljs');
var Swarm = function(options) {
this.options = options;
this.buildDir = options.buildDir || 'dist/';
};
class Swarm {
constructor(options) {
this.options = options;
this.buildDir = options.buildDir || 'dist/';
}
Swarm.prototype.deploy = function() {
var self = this;
async.waterfall([
function findBinary(callback) {
var swarm_bin = shelljs.exec('which swarm').output.split("\n")[0];
deploy() {
let self = this;
async.waterfall([
function findBinary(callback) {
let swarm_bin = shelljs.exec('which swarm').output.split("\n")[0];
if (swarm_bin==='swarm not found' || swarm_bin === ''){
console.log('=== WARNING: Swarm not in an executable path. Guessing ~/go/bin/swarm for path'.yellow);
swarm_bin = "~/go/bin/swarm";
if (swarm_bin === 'swarm not found' || swarm_bin === '') {
console.log('=== WARNING: Swarm not in an executable path. Guessing ~/go/bin/swarm for path'.yellow);
swarm_bin = "~/go/bin/swarm";
}
return callback(null, swarm_bin);
},
function runCommand(swarm_bin, callback) {
let cmd = swarm_bin + " --defaultpath " + self.buildDir + "index.html --recursive up " + self.buildDir;
console.log(("=== adding " + self.buildDir + " to swarm").green);
console.log(cmd.green);
let result = shelljs.exec(cmd);
return callback(null, result);
},
function getHashFromOutput(result, callback) {
if (result.code !== 0) {
return callback("couldn't upload, is the swarm daemon running?");
}
let rows = result.output.split("\n");
let dir_hash = rows.reverse()[1];
return callback(null, dir_hash);
},
function printUrls(dir_hash, callback) {
console.log(("=== DApp available at http://localhost:8500/bzz:/" + dir_hash + "/").green);
return callback();
}
return callback(null, swarm_bin);
},
function runCommand(swarm_bin, callback) {
var cmd = swarm_bin + " --defaultpath " + self.buildDir + "index.html --recursive up " + self.buildDir;
console.log(("=== adding " + self.buildDir + " to swarm").green);
console.log(cmd.green);
var result = shelljs.exec(cmd);
return callback(null, result);
},
function getHashFromOutput(result, callback) {
if (result.code !== 0) {
return callback("couldn't upload, is the swarm daemon running?");
}
var rows = result.output.split("\n");
var dir_hash = rows.reverse()[1];
return callback(null, dir_hash);
},
function printUrls(dir_hash, callback) {
console.log(("=== DApp available at http://localhost:8500/bzz:/" + dir_hash + "/").green);
return callback();
}
], function(err, result) {
], function (err, result) {
if (err) {
console.log("error uploading to swarm".red);
console.log(err);
}
});
};
});
}
}
module.exports = Swarm;

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

@ -0,0 +1,15 @@
let 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

@ -5,9 +5,9 @@ function extend(filename, async) {
return;
}
async._waterfall = async.waterfall;
async.waterfall = function(_tasks, callback) {
var tasks = _tasks.map(function(t) {
var fn = function() {
async.waterfall = function (_tasks, callback) {
let tasks = _tasks.map(function (t) {
let fn = function () {
console.log("async " + filename + ": " + t.name);
t.apply(t, arguments);
};

View File

@ -1,9 +1,9 @@
/*global exit */
var path = require('path');
var globule = require('globule');
var merge = require('merge');
var http = require('http');
var shelljs = require('shelljs');
let path = require('path');
let globule = require('globule');
let merge = require('merge');
let http = require('http');
let shelljs = require('shelljs');
function joinPath() {
return path.join.apply(path.join, arguments);
@ -22,15 +22,19 @@ function recursiveMerge(target, source) {
}
function checkIsAvailable(url, callback) {
http.get(url, function(res) {
http.get(url, function (res) {
callback(true);
}).on('error', function(res) {
}).on('error', function (res) {
callback(false);
});
}
function httpGet(url, callback) {
return http.get(url, callback);
}
function runCmd(cmd, options) {
var result = shelljs.exec(cmd, options || {silent: true});
let result = shelljs.exec(cmd, options || {silent: true});
if (result.code !== 0) {
console.log("error doing.. " + cmd);
console.log(result.output);
@ -53,12 +57,14 @@ function exit(code) {
process.exit(code);
}
//TODO: Maybe desired to just `module.exports = this` ?
module.exports = {
joinPath: joinPath,
filesMatchingPattern: filesMatchingPattern,
fileMatchesPattern: fileMatchesPattern,
recursiveMerge: recursiveMerge,
checkIsAvailable: checkIsAvailable,
httpGet: httpGet,
runCmd: runCmd,
cd: cd,
sed: sed,

View File

@ -1,6 +1,6 @@
{
"name": "embark",
"version": "2.4.2",
"version": "2.5.0",
"description": "Embark is a framework that allows you to easily develop and deploy DApps",
"scripts": {
"test": "grunt jshint && mocha test/ --no-timeouts"
@ -26,11 +26,14 @@
"fs-extra": "^2.0.0",
"globule": "^1.1.0",
"merge": "^1.2.0",
"promptly": "^2.1.0",
"serve-static": "^1.11.1",
"shelljs": "^0.5.0",
"solc": "0.4.8",
"solc": "0.4.11",
"toposort": "^1.0.0",
"web3": "^0.18.2"
"underscore": "^1.8.3",
"underscore.string": "^3.3.4",
"web3": "^0.19.1"
},
"author": "Iuri Matias <iuri.matias@gmail.com>",
"contributors": [],
@ -49,6 +52,8 @@
"devDependencies": {
"grunt": "^1.0.1",
"grunt-cli": "^1.2.0",
"grunt-contrib-clean": "^1.0.0",
"grunt-contrib-coffee": "^1.0.0",
"grunt-contrib-jshint": "^1.0.0",
"grunt-mocha-test": "^0.13.2",
"matchdep": "^1.0.1",
@ -56,5 +61,19 @@
"mocha-sinon": "^1.1.4",
"sinon": "^1.15.4",
"toposort": "^1.0.0"
},
"jshintConfig": {
"indent": 2,
"white": true,
"node": true,
"undef": true,
"-W058": true,
"-W014": true,
"expr": true,
"esversion": 6,
"unused": false,
"globals": {
"node": true
}
}
}

View File

@ -1,23 +1,23 @@
/*globals describe, it*/
var ABIGenerator = require('../lib/contracts/abi.js');
var assert = require('assert');
let ABIGenerator = require('../lib/contracts/abi.js');
let assert = require('assert');
// TODO: instead 'eval' the code with a fake web3 object
// and check the generate code interacts as expected
describe('embark.ABIGenerator', function() {
this.timeout(0);
describe('#generateProvider', function() {
var generator = new ABIGenerator({blockchainConfig: {rpcHost: 'somehost', rpcPort: '1234'}, contractsManager: {}});
let generator = new ABIGenerator({blockchainConfig: {rpcHost: 'somehost', rpcPort: '1234'}, contractsManager: {}});
it('should generate code to connect to a provider', function() {
var providerCode = "\nvar whenEnvIsLoaded = function(cb) {\n if (typeof window !== 'undefined' && window !== null) {\n window.addEventListener('load', cb);\n } else {\n cb();\n }\n}\nwhenEnvIsLoaded(function() {\nif (typeof web3 !== 'undefined' && typeof Web3 !== 'undefined') {\n\tweb3 = new Web3(web3.currentProvider);\n} else if (typeof Web3 !== 'undefined') {\n\tweb3 = new Web3(new Web3.providers.HttpProvider(\"http://somehost:1234\"));\n}\nweb3.eth.defaultAccount = web3.eth.accounts[0];\n})"
var providerCode = "\nvar whenEnvIsLoaded = function(cb) {\n if (typeof document !== 'undefined' && document !== null) {\n document.addEventListener('DOMContentLoaded', cb);\n } else {\n cb();\n }\n}\nwhenEnvIsLoaded(function() {\nif (typeof web3 !== 'undefined' && typeof Web3 !== 'undefined') {\n\tweb3 = new Web3(web3.currentProvider);\n} else if (typeof Web3 !== 'undefined') {\n\tweb3 = new Web3(new Web3.providers.HttpProvider(\"http://somehost:1234\"));\n}\nweb3.eth.defaultAccount = web3.eth.accounts[0];\n})"
assert.equal(generator.generateProvider(), providerCode);
});
});
describe('#generateContracts', function() {
var generator = new ABIGenerator({blockchainConfig: {}, contractsManager: {
let generator = new ABIGenerator({blockchainConfig: {}, contractsManager: {
contracts: {
SimpleStorage: {
abiDefinition: [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"type":"constructor"}],
@ -35,19 +35,19 @@ describe('embark.ABIGenerator', function() {
}});
describe('with EmbarkJS', function() {
var withEmbarkJS = true;
let withEmbarkJS = true;
it('should generate contract code', function() {
var contractCode = "\n\nwhenEnvIsLoaded(function() {\nSimpleStorage = new EmbarkJS.Contract({abi: [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}], address: '0x123', code: '12345', gasEstimates: 12000});\n});\nwhenEnvIsLoaded(function() {\nFoo = new EmbarkJS.Contract({abi: [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}], address: '0x124', code: '123456', gasEstimates: 12000});\n});";
var contractCode = "\n\nif (whenEnvIsLoaded === undefined) {\n var whenEnvIsLoaded = function(cb) {\n if (typeof document !== 'undefined' && document !== null) {\n document.addEventListener('DOMContentLoaded', cb);\n } else {\n cb();\n }\n }\n}\nwhenEnvIsLoaded(function() {\nSimpleStorage = new EmbarkJS.Contract({abi: [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}], address: '0x123', code: '12345', gasEstimates: 12000});\n});\nif (whenEnvIsLoaded === undefined) {\n var whenEnvIsLoaded = function(cb) {\n if (typeof document !== 'undefined' && document !== null) {\n document.addEventListener('DOMContentLoaded', cb);\n } else {\n cb();\n }\n }\n}\nwhenEnvIsLoaded(function() {\nFoo = new EmbarkJS.Contract({abi: [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}], address: '0x124', code: '123456', gasEstimates: 12000});\n});";
assert.equal(generator.generateContracts(withEmbarkJS), contractCode);
});
});
describe('with default interface', function() {
var withEmbarkJS = false;
let withEmbarkJS = false;
it('should generate contract code', function() {
var contractCode = "\n\nwhenEnvIsLoaded(function() {\nSimpleStorageAbi = [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}];\nSimpleStorageContract = web3.eth.contract(SimpleStorageAbi);\nSimpleStorage = SimpleStorageContract.at('0x123');\n});\nwhenEnvIsLoaded(function() {\nFooAbi = [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}];\nFooContract = web3.eth.contract(FooAbi);\nFoo = FooContract.at('0x124');\n});";
var contractCode = "\n\nif (whenEnvIsLoaded === undefined) {\n var whenEnvIsLoaded = function(cb) {\n if (typeof document !== 'undefined' && document !== null) {\n document.addEventListener('DOMContentLoaded', cb);\n } else {\n cb();\n }\n }\n}\nwhenEnvIsLoaded(function() {\nSimpleStorageAbi = [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}];\nSimpleStorageContract = web3.eth.contract(SimpleStorageAbi);\nSimpleStorage = SimpleStorageContract.at('0x123');\n});\nif (whenEnvIsLoaded === undefined) {\n var whenEnvIsLoaded = function(cb) {\n if (typeof document !== 'undefined' && document !== null) {\n document.addEventListener('DOMContentLoaded', cb);\n } else {\n cb();\n }\n }\n}\nwhenEnvIsLoaded(function() {\nFooAbi = [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}];\nFooContract = web3.eth.contract(FooAbi);\nFoo = FooContract.at('0x124');\n});";
assert.equal(generator.generateContracts(withEmbarkJS), contractCode);
});
});

View File

@ -1,17 +1,18 @@
/*globals describe, it*/
var Blockchain = require('../lib/cmds/blockchain/blockchain.js');
var assert = require('assert');
const Blockchain = require('../lib/cmds/blockchain/blockchain');
describe('embark.Blockchain', function() {
//var Client = function() {};
const assert = require('assert');
describe('embark.Blockchain', function () {
//let Client = function() {};
//Client.prototype.name = "ClientName";
describe('#initializer', function() {
//var client = new Client();
describe('#initializer', function () {
//let client = new Client();
describe('with empty config', function() {
it('should have a default config', function() {
var config = {
describe('with empty config', function () {
it('should have a default config', function (done) {
let config = {
networkType: 'custom',
genesisBlock: false,
geth_bin: 'geth',
@ -31,15 +32,16 @@ describe('embark.Blockchain', function() {
account: {},
bootnodes: ""
};
var blockchain = Blockchain(config, 'geth');
let blockchain = new Blockchain(config, 'geth');
assert.deepEqual(blockchain.config, config);
done();
});
});
describe('with config', function() {
it('should take config params', function() {
var config = {
describe('with config', function () {
it('should take config params', function (done) {
let config = {
networkType: 'livenet',
genesisBlock: 'foo/bar/genesis.json',
geth_bin: 'geth',
@ -59,9 +61,10 @@ describe('embark.Blockchain', function() {
account: {},
bootnodes: ""
};
var blockchain = Blockchain(config, 'geth');
let blockchain = new Blockchain(config, 'geth');
assert.deepEqual(blockchain.config, config);
done();
});
});

52
test/cmd.js Normal file
View File

@ -0,0 +1,52 @@
let Embark = require('../lib/index');
let Cmd = require('../lib/cmd');
// Function to send a line to stdin
function sendLine(line) {
setImmediate(function () {
process.stdin.emit('data', line + '\n');
});
}
let passingLines = function () {
let 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);
describe('#new', function () {
it('it should create an app with a name', function (done) {
let cmd = new Cmd(Embark);
let pl = passingLines();
let appname = 'deleteapp';
cmd.newApp(appname, function (output) {
let 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) {
let cmd = new Cmd(Embark);
let pl = passingLines();
let appname = 'deleteapp';
cmd.newApp(undefined, function (output) {
let lines = output.split('\n');
console.log(lines);
sendLine(appname + '\n');
assert.equal(lines[0], pl[0]);
});
done();
});
});
});

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,10 @@
/*globals describe, it*/
var Config = require('../lib/core/config.js');
var Plugins = require('../lib/core/plugins.js');
var assert = require('assert');
var fs = require('fs');
let Config = require('../lib/core/config.js');
let Plugins = require('../lib/core/plugins.js');
let assert = require('assert');
describe('embark.Config', function() {
var config = new Config({
let config = new Config({
env: 'myenv',
configDir: './test/test1/config/'
});
@ -14,7 +13,7 @@ describe('embark.Config', function() {
describe('#loadBlockchainConfigFile', function() {
it('should load blockchain config correctly', function() {
config.loadBlockchainConfigFile();
var expectedConfig = {
let expectedConfig = {
"enabled": true,
"networkType": "custom",
"genesisBlock": "config/development/genesis.json",
@ -36,7 +35,7 @@ describe('embark.Config', function() {
describe('#loadContractsConfigFile', function() {
it('should load contract config correctly', function() {
config.loadContractsConfigFile();
var expectedConfig = {
let expectedConfig = {
"gas": "auto",
"contracts": {
"SimpleStorage": {

View File

@ -1,11 +1,12 @@
/*globals describe, it*/
var Console = require('../lib/dashboard/console.js');
var Plugins = require('../lib/core/plugins.js');
var assert = require('assert');
let Console = require('../lib/dashboard/console.js');
let Plugins = require('../lib/core/plugins.js');
let assert = require('assert');
let version = require('../package.json').version;
describe('embark.Console', function() {
var plugins = new Plugins({plugins: {}});
var console = new Console({plugins: plugins, version: '2.3.1'});
let plugins = new Plugins({plugins: {}});
let console = new Console({plugins: plugins, version: version});
describe('#executeCmd', function() {
@ -13,8 +14,8 @@ describe('embark.Console', function() {
it('it should provide a help text', function(done) {
console.executeCmd('help', function(output) {
var lines = output.split('\n');
assert.equal(lines[0], 'Welcome to Embark 2.3.1');
let lines = output.split('\n');
assert.equal(lines[0], 'Welcome to Embark ' + version);
assert.equal(lines[2], 'possible commands are:');
done();
});

View File

@ -1,16 +1,17 @@
/*globals describe, it*/
var ContractsManager = require('../lib/contracts/contracts.js');
var Logger = require('../lib/core/logger.js');
var assert = require('assert');
var fs = require('fs');
let ContractsManager = require('../lib/contracts/contracts.js');
let Logger = require('../lib/core/logger.js');
let assert = require('assert');
let fs = require('fs');
var readFile = function(file) {
let readFile = function(file) {
return {filename: file, content: fs.readFileSync(file).toString()};
};
describe('embark.Contratcs', function() {
this.timeout(0);
describe('simple', function() {
var contractsManager = new ContractsManager({
let contractsManager = new ContractsManager({
contractFiles: [
readFile('test/contracts/simple_storage.sol'),
readFile('test/contracts/token.sol')
@ -40,7 +41,7 @@ describe('embark.Contratcs', function() {
throw err;
}
var contracts = contractsManager.listContracts();
let contracts = contractsManager.listContracts();
assert.equal(contracts.length, 2);
assert.equal(contracts[0].deploy, true);
@ -69,7 +70,7 @@ describe('embark.Contratcs', function() {
});
describe('config with contract instances', function() {
var contractsManager = new ContractsManager({
let contractsManager = new ContractsManager({
contractFiles: [
readFile('test/contracts/simple_storage.sol'),
readFile('test/contracts/token_storage.sol')
@ -109,7 +110,7 @@ describe('embark.Contratcs', function() {
throw err;
}
var contracts = contractsManager.listContracts();
let contracts = contractsManager.listContracts();
assert.equal(contracts.length, 4);
assert.equal(contracts[0].className, "MySimpleStorage");
@ -126,7 +127,7 @@ describe('embark.Contratcs', function() {
//assert.equal(contracts[3].code, '');
//assert.equal(contracts[3].runtimeBytecode, '');
var parentContract = contracts[2];
let parentContract = contracts[2];
//MySimpleStorage
assert.equal(contracts[0].deploy, true);

View File

@ -2,6 +2,8 @@ pragma solidity ^0.4.7;
contract SimpleStorage {
uint public storedData;
function() payable { }
function SimpleStorage(uint initialValue) {
storedData = initialValue;
}

View File

@ -24,3 +24,27 @@ div {
margin-bottom: 0;
}
.status-offline {
vertical-align: middle;
margin-left: 5px;
margin-top: 4px;
width: 12px;
height: 12px;
background: red;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
.status-online {
vertical-align: middle;
margin-left: 5px;
margin-top: 4px;
width: 12px;
height: 12px;
background: mediumseagreen;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}

View File

@ -9,8 +9,8 @@
<ul class="nav nav-tabs" role="tablist" id="myTabs">
<li role="presentation" class="active"><a href="#blockchain" aria-controls="blockchain" role="tab" data-toggle="tab">Blockchain</a></li>
<li role="presentation"><a href="#storage" aria-controls="storage" role="tab" data-toggle="tab">Decentralized Storage (IPFS)</a></li>
<li role="presentation"><a href="#communication" aria-controls="communication" role="tab" data-toggle="tab">P2P communication (whisper/orbit)</a></li>
<li role="presentation"><a href="#storage" aria-controls="storage" role="tab" data-toggle="tab">Decentralized Storage (IPFS)<span class="pull-right" id="status-storage"></a></li>
<li role="presentation"><a href="#communication" aria-controls="communication" role="tab" data-toggle="tab">P2P communication (Whisper/Orbit)<span class="pull-right" id="status-communication"></span></a></li>
</ul>
<div class="tab-content">
@ -37,7 +37,8 @@
</div>
</div>
<div role="tabpanel" class="tab-pane" id="storage">
note: You need to have an IPFS node running
<div class="error alert alert-danger" role="alert">The node you are using does not support IPFS. Please ensure <a href="https://github.com/ipfs/js-ipfs-api#cors" target="_blank">CORS</a> is setup for the IPFS node.</div>
<div id="storage-controls">
<h3>Save text to IPFS</h3>
<div class="form-group form-inline">
@ -72,11 +73,12 @@
<div class="logs">
<br> EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'})
</div>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="communication">
<span class="error">The node you are using does not support whisper</span>
<div class="error alert alert-danger" role="alert">The node you are using does not support Whisper</div>
<div class="errorVersion alert alert-danger" role="alert">The node uses an unsupported version of Whisper</div>
<div id="communication-controls">
<h3>Listen To channel</h3>
<div class="form-group form-inline listen">
<input type="text" class="channel text form-control" placeholder="channel">
@ -97,7 +99,7 @@
<div class="logs">
<br> EmbarkJS.Messages.setProvider('whisper')
</div>
</div>
</div>
</div>

View File

@ -28,23 +28,59 @@ $(document).ready(function() {
// Storage (IPFS) example
// ===========================
$(document).ready(function() {
// automatic set if config/storage.json has "enabled": true and "provider": "ipfs"
//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');
$("#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){
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() {
@ -52,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() {
@ -73,13 +114,21 @@ $(document).ready(function() {
$(document).ready(function() {
$("#communication .error").hide();
//web3.version.getWhisper(function(err, res) {
// if (err) {
// $("#communication .error").show();
// } else {
// EmbarkJS.Messages.setProvider('whisper');
// }
//});
$("#communication .errorVersion").hide();
web3.version.getWhisper(function(err, version) {
if (err) {
$("#communication .error").show();
$("#communication-controls").hide();
$("#status-communication").addClass('status-offline');
} else if (version >= 5) {
$("#communication .errorVersion").show();
$("#communication-controls").hide();
$("#status-communication").addClass('status-offline');
} else {
EmbarkJS.Messages.setProvider('whisper');
$("#status-communication").addClass('status-online');
}
});
$("#communication button.listenToChannel").click(function() {
var channel = $("#communication .listen input.channel").val();
@ -98,4 +147,3 @@ $(document).ready(function() {
});
});

View File

@ -1,4 +1,5 @@
{
"config": {},
"nonce": "0x0000000000000042",
"difficulty": "0x0",
"alloc": {

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: "on"});
});
};

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

@ -5,6 +5,7 @@ var web3 = EmbarkSpec.web3;
describe("AnotherStorage", function() {
before(function(done) {
this.timeout(0);
var contractsConfig = {
"SimpleStorage": {
args: [100]

View File

@ -5,6 +5,7 @@ var web3 = EmbarkSpec.web3;
describe("SimpleStorage", function() {
before(function(done) {
this.timeout(0);
var contractsConfig = {
"SimpleStorage": {
args: [100]

View File

@ -5,6 +5,7 @@ var web3 = EmbarkSpec.web3;
describe("Token", function() {
before(function(done) {
this.timeout(0);
var contractsConfig = {
"SimpleStorage": {
args: [100]