Merge branch 'develop' into buildFixes

This commit is contained in:
Antonio Tenorio Fornés 2017-10-24 19:05:22 +02:00
commit 4bb77ae8d5
96 changed files with 2251 additions and 678 deletions

273
.eslintrc.json Normal file
View File

@ -0,0 +1,273 @@
{
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"parserOptions": {
"sourceType": "module"
},
"rules": {
"accessor-pairs": "error",
"array-bracket-newline": "error",
"array-bracket-spacing": [
"error",
"never"
],
"array-callback-return": "off",
"array-element-newline": "off",
"arrow-body-style": "error",
"arrow-parens": "off",
"arrow-spacing": [
"error",
{
"after": true,
"before": true
}
],
"block-scoped-var": "error",
"block-spacing": "error",
"brace-style": "off",
"callback-return": "off",
"camelcase": "off",
"capitalized-comments": "off",
"class-methods-use-this": "off",
"comma-dangle": "error",
"comma-spacing": "off",
"comma-style": [
"error",
"last"
],
"complexity": "error",
"computed-property-spacing": [
"error",
"never"
],
"consistent-return": "off",
"consistent-this": "off",
"curly": "off",
"default-case": "error",
"dot-location": [
"error",
"property"
],
"dot-notation": "off",
"eol-last": "error",
"eqeqeq": "off",
"for-direction": "error",
"func-call-spacing": "error",
"func-name-matching": "error",
"func-names": "off",
"func-style": "off",
"function-paren-newline": "off",
"generator-star-spacing": "error",
"getter-return": "error",
"global-require": "off",
"guard-for-in": "off",
"handle-callback-err": "off",
"id-blacklist": "error",
"id-length": "off",
"id-match": "error",
"indent": "off",
"indent-legacy": "off",
"init-declarations": "off",
"jsx-quotes": "error",
"key-spacing": "off",
"keyword-spacing": "off",
"line-comment-position": "off",
"linebreak-style": [
"error",
"unix"
],
"lines-around-comment": "error",
"lines-around-directive": "error",
"max-depth": "error",
"max-len": "off",
"max-lines": "off",
"max-nested-callbacks": "error",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "error",
"multiline-ternary": [
"error",
"never"
],
"new-parens": "off",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-alert": "error",
"no-array-constructor": "error",
"no-await-in-loop": "error",
"no-bitwise": "error",
"no-buffer-constructor": "error",
"no-caller": "error",
"no-catch-shadow": "error",
"no-confusing-arrow": "error",
"no-console": "off",
"no-continue": "off",
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-else-return": "off",
"no-empty-function": "off",
"no-eq-null": "error",
"no-eval": "off",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-label": "error",
"no-extra-parens": "off",
"no-floating-decimal": "error",
"no-implicit-coercion": "error",
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-inner-declarations": [
"error",
"functions"
],
"no-invalid-this": "off",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "off",
"no-loop-func": "error",
"no-magic-numbers": "off",
"no-mixed-operators": "error",
"no-mixed-requires": "error",
"no-multi-assign": "error",
"no-multi-spaces": "off",
"no-multi-str": "error",
"no-multiple-empty-lines": "error",
"no-native-reassign": "error",
"no-negated-condition": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "error",
"no-new": "error",
"no-new-func": "error",
"no-new-object": "error",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-path-concat": "error",
"no-plusplus": "off",
"no-process-env": "off",
"no-process-exit": "off",
"no-proto": "error",
"no-prototype-builtins": "off",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-modules": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": "error",
"no-return-assign": "error",
"no-return-await": "error",
"no-script-url": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "off",
"no-shadow-restricted-names": "error",
"no-spaced-func": "error",
"no-sync": "off",
"no-tabs": "error",
"no-template-curly-in-string": "error",
"no-ternary": "off",
"no-throw-literal": "error",
"no-trailing-spaces": "off",
"no-undef-init": "error",
"no-undefined": "off",
"no-underscore-dangle": "off",
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": "error",
"no-unused-expressions": "error",
"no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
"no-use-before-define": "off",
"no-useless-call": "off",
"no-useless-computed-key": "error",
"no-useless-concat": "error",
"no-useless-constructor": "error",
"no-useless-rename": "error",
"no-useless-return": "off",
"no-var": "off",
"no-void": "error",
"no-warning-comments": "off",
"no-whitespace-before-property": "error",
"no-with": "error",
"nonblock-statement-body-position": "error",
"object-curly-newline": "off",
"object-curly-spacing": [
"error",
"never"
],
"object-property-newline": "off",
"object-shorthand": "off",
"one-var": "off",
"one-var-declaration-per-line": "off",
"operator-assignment": "off",
"operator-linebreak": "error",
"padded-blocks": "off",
"padding-line-between-statements": "error",
"prefer-arrow-callback": "off",
"prefer-const": "off",
"prefer-destructuring": "off",
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "error",
"prefer-reflect": "off",
"prefer-rest-params": "off",
"prefer-spread": "off",
"prefer-template": "off",
"quote-props": "off",
"quotes": "off",
"radix": "error",
"require-await": "error",
"require-jsdoc": "off",
"rest-spread-spacing": "error",
"semi": "error",
"semi-spacing": [
"error",
{
"after": true,
"before": false
}
],
"semi-style": [
"error",
"last"
],
"sort-imports": "error",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "off",
"space-before-function-paren": "off",
"space-in-parens": [
"error",
"never"
],
"space-infix-ops": "off",
"space-unary-ops": "error",
"spaced-comment": "off",
"strict": "error",
"switch-colon-spacing": "error",
"symbol-description": "error",
"template-curly-spacing": [
"error",
"never"
],
"template-tag-spacing": "error",
"unicode-bom": [
"error",
"never"
],
"valid-jsdoc": "error",
"vars-on-top": "off",
"wrap-iife": "error",
"wrap-regex": "error",
"yield-star-spacing": "error",
"yoda": [
"error",
"never"
]
}
}

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ test_app/config/production/password
test_app/node_modules/
test_app/chains.json
.idea
.eslintrc.json

View File

@ -1,5 +1,7 @@
[![npm](https://img.shields.io/npm/dm/embark.svg)]()
[![Gitter](https://img.shields.io/gitter/room/iurimatias/embark-framework.svg)]()
![Embark](https://github.com/iurimatias/embark-framework/raw/develop/logo.png)
[![npm](https://img.shields.io/npm/dm/embark.svg)](https://npmjs.com/package/embark)
[![Gitter](https://img.shields.io/gitter/room/iurimatias/embark-framework.svg)](https://gitter.im/iurimatias/embark-framework)
[![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)
@ -55,7 +57,7 @@ Table of Contents
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 recommended, 1.6.0 or lower for whisper v1 support; whisper v5 support coming soon), 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/)
@ -389,7 +391,7 @@ EmbarkJS - Communication
**initialization**
For Whisper:
For Whisper (note: currently requires geth 1.6.0):
```Javascript
EmbarkJS.Messages.setProvider('whisper')
@ -549,4 +551,4 @@ For more information on how to develop your own plugin, please see the [plugin d
Donations
======
If you like Embark, please consider donating to 0x8811FdF0F988f0CD1B7E9DE252ABfA5b18c1cDb1
If you like Embark, please consider donating to 0xFA239D14c7117C3D2370B2a4c4238534391fadd9

View File

@ -12,7 +12,8 @@
"rpcCorsDomain": "http://localhost:8000",
"account": {
"password": "config/development/password"
}
},
"wsOrigins": "http://localhost:8000"
},
"testnet": {
"enabled": true,

View File

@ -2,6 +2,11 @@
"default": {
"enabled": true,
"provider": "whisper",
"available_providers": ["whisper", "orbit"]
"available_providers": ["whisper", "orbit"],
"connection": {
"host": "localhost",
"port": 8546,
"type": "ws"
}
}
}

View File

@ -1,5 +1,18 @@
{
"default": {
"versions": {
"web3.js": "1.0.0-beta",
"solc": "0.4.17"
},
"deployment": {
"host": "localhost",
"port": 8545,
"type": "rpc"
},
"dappConnection": [
"$WEB3",
"http://localhost:8545"
],
"gas": "auto",
"contracts": {
}

View File

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

View File

@ -11,6 +11,7 @@
"enabled": true,
"provider": "ipfs",
"host": "localhost",
"port": 5001
"port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
}
}

View File

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

View File

@ -1,7 +1,3 @@
var assert = require('assert');
var EmbarkSpec = require('embark/lib/core/test.js');
// describe("SimpleStorage", function() {
// before(function(done) {
// this.timeout(0);

View File

@ -2,15 +2,15 @@ pragma solidity ^0.4.7;
contract SimpleStorage {
uint public storedData;
function SimpleStorage(uint initialValue) {
function SimpleStorage(uint initialValue) public {
storedData = initialValue;
}
function set(uint x) {
function set(uint x) public {
storedData = x;
}
function get() constant returns (uint retVal) {
function get() public view returns (uint retVal) {
return storedData;
}

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

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

@ -12,7 +12,8 @@
"rpcCorsDomain": "http://localhost:8000",
"account": {
"password": "config/development/password"
}
},
"wsOrigins": "http://localhost:8000"
},
"testnet": {
"enabled": true,

View File

@ -2,6 +2,11 @@
"default": {
"enabled": true,
"provider": "whisper",
"available_providers": ["whisper", "orbit"]
"available_providers": ["whisper", "orbit"],
"connection": {
"host": "localhost",
"port": 8546,
"type": "ws"
}
}
}

View File

@ -1,5 +1,18 @@
{
"default": {
"versions": {
"web3.js": "1.0.0-beta",
"solc": "0.4.17"
},
"deployment": {
"host": "localhost",
"port": 8545,
"type": "rpc"
},
"dappConnection": [
"$WEB3",
"http://localhost:8545"
],
"gas": "auto",
"contracts": {
"SimpleStorage": {

View File

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

View File

@ -11,6 +11,7 @@
"enabled": true,
"provider": "ipfs",
"host": "localhost",
"port": 5001
"port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
}
}

View File

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

View File

@ -1,8 +1,3 @@
var assert = require('assert');
var Embark = require('embark');
var EmbarkSpec = Embark.initTests();
var web3 = EmbarkSpec.web3;
describe("SimpleStorage", function() {
before(function(done) {
this.timeout(0);

View File

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

View File

@ -1,4 +1,4 @@
Donations
======
If you like Embark please consider donating to 0x8811FdF0F988f0CD1B7E9DE252ABfA5b18c1cDb1
If you like Embark please consider donating to 0xFA239D14c7117C3D2370B2a4c4238534391fadd9

View File

@ -1,5 +1,4 @@
Donations
=========
If you like Embark please consider donating to
0x8811FdF0F988f0CD1B7E9DE252ABfA5b18c1cDb1
If you like Embark please consider donating to 0xFA239D14c7117C3D2370B2a4c4238534391fadd9

View File

@ -11,7 +11,7 @@ methods in EmbarkJS contracts will be converted to promises.
.. code:: javascript
var myContract = new EmbarkJS.Contract({abi: abiObject, address: "0x123"});
myContract.get().then(function(value) { console.log("value is " + value.toNumber) });
myContract.get().then(function(value) { console.log("value is " + value.toNumber()) });
**deployment**

View File

@ -1,7 +1,7 @@
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 recommended), node (6.9.1 or higher is recommended) and npm
serpent (develop) if using contracts with Serpent, 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/>`__

View File

@ -7,103 +7,122 @@
var EmbarkJS = {};
EmbarkJS.isNewWeb3 = function() {
var _web3 = new Web3();
if (typeof(_web3.version) === "string") {
return true;
}
return parseInt(_web3.version.api.split('.')[0], 10) >= 1;
};
EmbarkJS.Contract = function(options) {
var self = this;
var i, abiElement;
var ContractClass;
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);
if (EmbarkJS.isNewWeb3()) {
// TODO:
// add default **from** address
// add gasPrice
ContractClass = new this.web3.eth.Contract(this.abi, this.address);
ContractClass.setProvider(this.web3.currentProvider);
this.eventList = [];
return ContractClass;
} else {
ContractClass = this.web3.eth.contract(this.abi);
if (this.abi) {
this.eventList = [];
if (this.abi) {
for (i = 0; i < this.abi.length; i++) {
abiElement = this.abi[i];
if (abiElement.type === 'event') {
this.eventList.push(abiElement.name);
}
abiElement = this.abi[i];
if (abiElement.type === 'event') {
this.eventList.push(abiElement.name);
}
}
}
}
var messageEvents = function() {
var messageEvents = function() {
this.cb = function() {};
};
};
messageEvents.prototype.then = function(cb) {
messageEvents.prototype.then = function(cb) {
this.cb = cb;
};
};
messageEvents.prototype.error = function(err) {
messageEvents.prototype.error = function(err) {
return err;
};
};
this._originalContractObject = ContractClass.at(this.address);
this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function(p) {
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[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;
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);
self[p] = function(_args) {
var args = Array.prototype.slice.call(arguments);
var fn = self._originalContractObject[p];
var props = self.abi.find((x) => x.name == p);
var promise = new Promise(function(resolve, reject) {
args.push(function(err, transaction) {
promise.tx = transaction;
if (err) {
return reject(err);
}
var promise = new Promise(function(resolve, reject) {
args.push(function(err, transaction) {
promise.tx = transaction;
if (err) {
return reject(err);
}
var getConfirmation = function() {
self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) {
if (err) {
return reject(err);
}
var getConfirmation = function() {
self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) {
if (err) {
return reject(err);
}
if (receipt !== null) {
return resolve(receipt);
}
if (receipt !== null) {
return resolve(receipt);
}
setTimeout(getConfirmation, 1000);
});
};
setTimeout(getConfirmation, 1000);
});
};
if (typeof(transaction) !== "string" || props.constant) {
resolve(transaction);
} else {
getConfirmation();
}
});
if (typeof(transaction) !== "string" || props.constant) {
resolve(transaction);
} else {
getConfirmation();
}
});
fn.apply(fn, args);
});
fn.apply(fn, args);
});
return promise;
};
return true;
return promise;
};
return true;
}
return false;
});
});
}
};
EmbarkJS.Contract.prototype.deploy = function(args, _options) {
@ -208,8 +227,10 @@ EmbarkJS.Storage.setProvider = function(provider, options) {
try {
if (options === undefined) {
self.ipfsConnection = IpfsApi('localhost', '5001');
self.getUrl = "http://localhost:8080/ipfs/";
} else {
self.ipfsConnection = IpfsApi(options.server, options.port);
self.getUrl = options.getUrl || "http://localhost:8080/ipfs/";
}
resolve(self);
} catch (err) {
@ -299,9 +320,7 @@ EmbarkJS.Storage.IPFS.uploadFile = function(inputSelector) {
};
EmbarkJS.Storage.IPFS.getUrl = function(hash) {
//var ipfsHash = web3.toAscii(hash);
return 'http://localhost:8080/ipfs/' + hash;
return (self.getUrl || "http://localhost:8080/ipfs/") + hash;
};
//=========================================================
@ -310,34 +329,80 @@ EmbarkJS.Storage.IPFS.getUrl = function(hash) {
EmbarkJS.Messages = {};
EmbarkJS.Messages.web3CompatibleWithV5 = function() {
var _web3 = new Web3();
if (typeof(_web3.version) === "string") {
return true;
}
return parseInt(_web3.version.api.split('.')[1], 10) >= 20;
};
EmbarkJS.Messages.isNewWeb3 = function() {
var _web3 = new Web3();
if (typeof(_web3.version) === "string") {
return true;
}
return parseInt(_web3.version.api.split('.')[0], 10) >= 1;
};
EmbarkJS.Messages.getWhisperVersion = function(cb) {
if (this.isNewWeb3()) {
this.currentMessages.web3.shh.getVersion(function(err, version) {
cb(err, version);
});
} else {
this.currentMessages.web3.version.getWhisper(function(err, res) {
cb(err, web3.version.whisper);
});
}
};
EmbarkJS.Messages.setProvider = function(provider, options) {
var self = this;
var ipfs;
if (provider === 'whisper') {
this.providerName = 'whisper';
this.currentMessages = EmbarkJS.Messages.Whisper;
if (typeof variable === 'undefined') {
if (options === undefined) {
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
} else {
web3 = new Web3(new Web3.providers.HttpProvider("http://" + options.server + ':' + options.port));
}
let provider;
if (options === undefined) {
provider = "localhost:8546";
} else {
provider = options.server + ':' + options.port;
}
web3.version.getWhisper(function(err, res) {
if (this.isNewWeb3()) {
self.currentMessages.web3 = new Web3(new Web3.providers.WebsocketProvider("ws://" + provider));
} else {
self.currentMessages.web3 = new Web3(new Web3.providers.HttpProvider("http://" + provider));
}
self.getWhisperVersion(function(err, version) {
if (err) {
console.log("whisper not available");
} else if (version >= 5) {
if (self.web3CompatibleWithV5()) {
self.currentMessages.web3.shh.newSymKey().then((id) => {self.currentMessages.symKeyID = id;});
self.currentMessages.web3.shh.newKeyPair().then((id) => {self.currentMessages.sig = id;});
} else {
console.log("this version of whisper in this node");
}
} else {
self.currentMessages.identity = web3.shh.newIdentity();
self.currentMessages.identity = self.currentMessages.web3.shh.newIdentity();
}
self.currentMessages.whisperVersion = self.currentMessages.web3.version.whisper;
});
} else if (provider === 'orbit') {
this.providerName = 'orbit';
this.currentMessages = EmbarkJS.Messages.Orbit;
if (options === undefined) {
ipfs = HaadIpfsApi('localhost', '5001');
} else {
ipfs = HaadIpfsApi(options.server, options.port);
ipfs = HaadIpfsApi(options.host, options.port);
}
this.currentMessages.orbit = new Orbit(ipfs);
this.currentMessages.orbit.connect(web3.eth.accounts[0]);
if (typeof(web3) === "undefined") {
this.currentMessages.orbit.connect(Math.random().toString(36).substring(2));
} else {
this.currentMessages.orbit.connect(web3.eth.accounts[0]);
}
} else {
throw Error('Unknown message provider');
}
@ -354,100 +419,179 @@ EmbarkJS.Messages.listenTo = function(options) {
EmbarkJS.Messages.Whisper = {};
EmbarkJS.Messages.Whisper.sendMessage = function(options) {
var topics = options.topic || options.topics;
var data = options.data || options.payload;
var identity = options.identity || this.identity || web3.shh.newIdentity();
var ttl = options.ttl || 100;
var priority = options.priority || 1000;
var _topics;
var topics, data, ttl, priority, payload;
if (EmbarkJS.Messages.isNewWeb3()) {
topics = options.topic || options.topics;
data = options.data || options.payload;
ttl = options.ttl || 100;
priority = options.priority || 1000;
var powTime = options.powTime || 3;
var powTarget = options.powTarget || 0.5;
if (topics === undefined) {
throw new Error("missing option: topic");
throw new Error("missing option: topic");
}
if (data === undefined) {
throw new Error("missing option: data");
throw new Error("missing option: data");
}
topics = this.web3.utils.toHex(topics).slice(0, 10);
payload = JSON.stringify(data);
let message = {
symKeyID: this.symKeyID, // encrypts using the sym key ID
sig: this.sig, // signs the message using the keyPair ID
ttl: ttl,
topic: topics,
payload: EmbarkJS.Utils.fromAscii(payload),
powTime: powTime,
powTarget: powTarget
};
this.web3.shh.post(message, function() { });
} else {
topics = options.topic || options.topics;
data = options.data || options.payload;
ttl = options.ttl || 100;
priority = options.priority || 1000;
var identity = options.identity || this.identity || web3.shh.newIdentity();
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)];
_topics = [EmbarkJS.Utils.fromAscii(topics)];
} else {
// TODO: replace with es6 + babel;
for (var i = 0; i < topics.length; i++) {
_topics.push(web3.fromAscii(topics[i]));
}
_topics = topics.map((t) => EmbarkJS.Utils.fromAscii(t));
}
topics = _topics;
var payload = JSON.stringify(data);
payload = JSON.stringify(data);
var message = {
from: identity,
topics: topics,
payload: web3.fromAscii(payload),
ttl: ttl,
priority: priority
var message;
message = {
from: identity,
topics: topics,
payload: EmbarkJS.Utils.fromAscii(payload),
ttl: ttl,
priority: priority
};
return web3.shh.post(message, function() {});
return EmbarkJS.Messages.currentMessages.web3.shh.post(message, function() { });
}
};
EmbarkJS.Messages.Whisper.listenTo = function(options) {
var topics = options.topic || options.topics;
var _topics = [];
if (typeof topics === 'string') {
_topics = [topics];
} else {
// TODO: replace with es6 + babel;
for (var i = 0; i < topics.length; i++) {
_topics.push(topics[i]);
}
}
topics = _topics;
var filterOptions = {
topics: topics
};
var messageEvents = function() {
this.cb = function() {};
var topics, _topics, messageEvents;
if (EmbarkJS.Messages.isNewWeb3()) {
messageEvents = function() {
this.cb = function() {};
};
messageEvents.prototype.then = function(cb) {
this.cb = cb;
this.cb = cb;
};
messageEvents.prototype.error = function(err) {
return err;
return err;
};
messageEvents.prototype.stop = function() {
this.filter.stopWatching();
this.filter.stopWatching();
};
var promise = new messageEvents();
topics = options.topic || options.topics;
_topics = [];
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);
}
let promise = new messageEvents();
// listenTo
if (typeof topics === 'string') {
topics = [this.web3.utils.toHex(topics).slice(0, 10)];
} else {
topics = topics.map((t) => this.web3.utils.toHex(t).slice(0, 10));
}
let filter = this.web3.shh.subscribe("messages", {
symKeyID: this.symKeyID,
topics: topics
}).on('data', function(result) {
var payload = JSON.parse(EmbarkJS.Utils.toAscii(result.payload));
var data;
data = {
topic: result.topic,
data: payload,
//from: result.from,
time: result.timestamp
};
promise.cb(payload, data, result);
});
promise.filter = filter;
return promise;
} else {
topics = options.topic || options.topics;
_topics = [];
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();
};
if (typeof topics === 'string') {
_topics = [topics];
} else {
_topics = topics.map((t) => EmbarkJS.Utils.fromAscii(t));
}
topics = _topics;
var filterOptions = {
topics: topics
};
let promise = new messageEvents();
let filter = this.web3.shh.filter(filterOptions, function(err, result) {
var payload = JSON.parse(EmbarkJS.Utils.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 = {};
@ -521,4 +665,15 @@ EmbarkJS.Messages.Orbit.listenTo = function(options) {
return promise;
};
EmbarkJS.Utils = {
fromAscii: function(str) {
var _web3 = new Web3();
return _web3.utils ? _web3.utils.fromAscii(str) : _web3.fromAscii(str);
},
toAscii: function(str) {
var _web3 = new Web3();
return _web3.utils.toAscii(str);
}
};
module.exports = EmbarkJS;

1
js/web3-1.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,5 @@
let program = require('commander');
let colors = require('colors');
let shelljs = require('shelljs');
let promptly = require('promptly');
let path = require('path');
const program = require('commander');
const promptly = require('promptly');
const Embark = require('../lib/index');
let embark = new Embark;
@ -30,11 +27,11 @@ class Cmd {
program.parse(args);
}
newApp(name) {
newApp() {
let validateName = function (value) {
try {
if (value.match(/^[a-zA-Z\s\-]+$/)) return value;
if (value.match(/^[a-zA-Z\s-]+$/)) return value;
} catch (e) {
throw new Error('Name must be only letters, spaces, or dashes');
}
@ -45,9 +42,8 @@ class Cmd {
.description('new application')
.action(function (name) {
if (name === undefined) {
let parentDirectory = path.dirname(__dirname).split("/").pop();
return promptly.prompt("Name your app (default is " + parentDirectory + "):", {
default: parentDirectory,
return promptly.prompt("Name your app (default is embarkDApp):", {
default: "embarkDApp",
validator: validateName
}, function (err, inputvalue) {
if (err) {
@ -80,7 +76,7 @@ class Cmd {
program
.command('build [environment]')
.description('deploy and build dapp at dist/ (default: development)')
.action(function (env, options) {
.action(function (env, _options) {
embark.build({env: env || 'development'});
});
}
@ -137,10 +133,13 @@ class Cmd {
test() {
program
.command('test')
.command('test [file]')
.description('run tests')
.action(function () {
shelljs.exec('mocha test');
.action(function (file) {
embark.initConfig('development', {
embarkConfig: 'embark.json', interceptLogs: false
});
embark.runTests(file);
});
}
@ -148,7 +147,7 @@ class Cmd {
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) {
.action(function (platform, env, _options) {
// TODO: get env in cmd line as well
embark.initConfig(env || 'development', {
embarkConfig: 'embark.json', interceptLogs: false

View File

@ -1,4 +1,3 @@
var colors = require('colors');
var shelljs = require('shelljs');
var fs = require('../../core/fs.js');
@ -29,6 +28,10 @@ var Blockchain = function(options) {
maxpeers: ((this.blockchainConfig.maxpeers === 0) ? 0 : (this.blockchainConfig.maxpeers || 25)),
bootnodes: this.blockchainConfig.bootnodes || "",
rpcApi: (this.blockchainConfig.rpcApi || ['eth', 'web3', 'net']),
wsHost: this.blockchainConfig.wsHost || 'localhost',
wsPort: this.blockchainConfig.wsPort || 8546,
wsOrigins: this.blockchainConfig.wsOrigins || false,
wsApi: (this.blockchainConfig.wsApi || ['eth', 'web3', 'net', 'shh']),
vmdebug: this.blockchainConfig.vmdebug || false
};

View File

@ -75,6 +75,7 @@ class GethCommands {
if (config.rpcCorsDomain) {
if (config.rpcCorsDomain === '*') {
console.log('==================================');
console.log('rpcCorsDomain set to *');
console.log('make sure you know what you are doing');
console.log('==================================');
}
@ -88,10 +89,34 @@ class GethCommands {
return cmd;
}
determineWsOptions(config) {
let cmd = "";
cmd += "--ws ";
cmd += "--wsport " + config.wsPort + " ";
cmd += "--wsaddr " + config.wsHost + " ";
if (config.wsOrigins) {
if (config.wsOrigins === '*') {
console.log('==================================');
console.log('rpcCorsDomain set to *');
console.log('make sure you know what you are doing');
console.log('==================================');
}
cmd += "--wsorigins \"" + config.wsOrigins + "\" ";
} else {
console.log('==================================');
console.log('warning: cors is not set');
console.log('==================================');
}
return cmd;
}
mainCommand(address, done) {
let self = this;
let config = this.config;
let rpc_api = (this.config.rpcApi || ['eth', 'web3', 'net']);
let ws_api = (this.config.wsApi || ['eth', 'web3', 'net']);
async.series([
function commonOptions(callback) {
@ -102,6 +127,10 @@ class GethCommands {
let cmd = self.determineRpcOptions(self.config);
callback(null, cmd);
},
function wsOptions(callback) {
let cmd = self.determineWsOptions(self.config);
callback(null, cmd);
},
function dontGetPeers(callback) {
if (config.nodiscover) {
return callback(null, "--nodiscover");
@ -133,6 +162,9 @@ class GethCommands {
function whisper(callback) {
if (config.whisper) {
rpc_api.push('shh');
if (ws_api.indexOf('shh') === -1) {
ws_api.push('shh');
}
return callback(null, "--shh ");
}
callback("");
@ -140,6 +172,9 @@ class GethCommands {
function rpcApi(callback) {
callback(null, '--rpcapi "' + rpc_api.join(',') + '"');
},
function wsApi(callback) {
callback(null, '--wsapi "' + ws_api.join(',') + '"');
},
function accountToUnlock(callback) {
let accountAddress = "";
if(config.hasOwnProperty('address') && config.account.hasOwnProperty('address')) {

View File

@ -2,7 +2,7 @@ let fs = require('../core/fs.js');
let utils = require('../utils/utils.js');
class TemplateGenerator {
constuctor(templateName) {
constructor(templateName) {
this.templateName = templateName;
}
@ -15,8 +15,6 @@ class TemplateGenerator {
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);

View File

@ -1,143 +0,0 @@
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;
}
generateProvider() {
let self = this;
let result = "";
let providerPlugins;
if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
return "";
}
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 += "\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];";
}
return result;
}
generateContracts(useEmbarkJS) {
let self = this;
let result = "\n";
let 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 (let className in this.contractsManager.contracts) {
let contract = this.contractsManager.contracts[className];
let abi = JSON.stringify(contract.abiDefinition);
let gasEstimates = JSON.stringify(contract.gasEstimates);
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 + "');";
}
}
}
return result;
}
generateStorageInitialization(useEmbarkJS) {
let self = this;
let result = "\n";
if (!useEmbarkJS || self.storageConfig === {}) 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 + "'});";
}
return result;
}
generateCommunicationInitialization(useEmbarkJS) {
let self = this;
let result = "\n";
if (!useEmbarkJS || self.communicationConfig === {}) return "";
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;
}
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

@ -0,0 +1,262 @@
require('ejs');
const Templates = {
utils: require('./code_templates/utils.js.ejs'),
vanilla_contract: require('./code_templates/vanilla-contract.js.ejs'),
embarkjs_contract: require('./code_templates/embarkjs-contract.js.ejs'),
exec_when_ready: require('./code_templates/exec-when-ready.js.ejs'),
load_manager: require('./code_templates/load-manager.js.ejs'),
define_when_env_loaded: require('./code_templates/define-when-env-loaded.js.ejs'),
main_context: require('./code_templates/main-context.js.ejs'),
define_web3_simple: require('./code_templates/define-web3-simple.js.ejs'),
web3_connector: require('./code_templates/web3-connector.js.ejs'),
do_when_loaded: require('./code_templates/do-when-loaded.js.ejs'),
exec_when_env_loaded: require('./code_templates/exec-when-env-loaded.js.ejs')
};
class CodeGenerator {
constructor(options) {
this.blockchainConfig = options.blockchainConfig || {};
this.contractsConfig = options.contractsConfig || {};
this.storageConfig = options.storageConfig || {};
this.communicationConfig = options.communicationConfig || {};
this.contractsManager = options.contractsManager;
this.plugins = options.plugins;
this.events = options.events;
}
listenToCommands() {
let self = this;
// deprecated events; to remove in embark 2.7.0
this.events.setCommandHandlerOnce('abi-vanila', function(cb) {
let vanillaABI = self.generateABI({useEmbarkJS: false});
let contractsJSON = self.generateContractsJSON();
cb(vanillaABI, contractsJSON);
});
this.events.setCommandHandlerOnce('abi', function(cb) {
let embarkJSABI = self.generateABI({useEmbarkJS: true});
let contractsJSON = self.generateContractsJSON();
cb(embarkJSABI, contractsJSON);
});
this.events.setCommandHandlerOnce('abi-contracts-vanila', function(cb) {
let vanillaContractsABI = self.generateContracts(false, true, false);
let contractsJSON = self.generateContractsJSON();
cb(vanillaContractsABI, contractsJSON);
});
this.events.setCommandHandlerOnce('abi-vanila-deployment', function(cb) {
let vanillaABI = self.generateABI({useEmbarkJS: false, deployment: true});
let contractsJSON = self.generateContractsJSON();
cb(vanillaABI, contractsJSON);
});
// new events
this.events.setCommandHandlerOnce('code-vanila', function(cb) {
let vanillaABI = self.generateABI({useEmbarkJS: false});
let contractsJSON = self.generateContractsJSON();
cb(vanillaABI, contractsJSON);
});
this.events.setCommandHandlerOnce('code', function(cb) {
let embarkJSABI = self.generateABI({useEmbarkJS: true});
let contractsJSON = self.generateContractsJSON();
cb(embarkJSABI, contractsJSON);
});
this.events.setCommandHandlerOnce('code-contracts-vanila', function(cb) {
let vanillaContractsABI = self.generateContracts(false, true, false);
let contractsJSON = self.generateContractsJSON();
cb(vanillaContractsABI, contractsJSON);
});
this.events.setCommandHandlerOnce('code-vanila-deployment', function(cb) {
let vanillaABI = self.generateABI({useEmbarkJS: false, deployment: true});
let contractsJSON = self.generateContractsJSON();
cb(vanillaABI, contractsJSON);
});
}
generateProvider(isDeployment) {
let self = this;
let result = "";
let providerPlugins;
// TODO: check contractsConfig for enabled
if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
return "";
}
result += Templates.utils();
result += Templates.main_context();
result += Templates.load_manager();
result += Templates.define_when_env_loaded();
if (this.plugins) {
providerPlugins = this.plugins.getPluginsFor('clientWeb3Provider');
}
if (this.plugins && providerPlugins.length > 0) {
providerPlugins.forEach(function(plugin) {
result += plugin.generateProvider(self) + "\n";
});
} else {
let web3Load;
if (isDeployment) {
let connection = "http://" + this.contractsConfig.deployment.host + ":" + this.contractsConfig.deployment.port;
web3Load = Templates.define_web3_simple({url: connection, done: 'done();'});
} else {
let connectionList = "[" + this.contractsConfig.dappConnection.map((x) => '"' + x + '"').join(',') + "]";
web3Load = Templates.web3_connector({connectionList: connectionList, done: 'done();'});
}
result += Templates.do_when_loaded({block: web3Load});
}
return result;
}
generateContracts(useEmbarkJS, isDeployment, useLoader) {
let self = this;
let result = "\n";
let contractsPlugins;
if (useLoader === false) {
for (let className in this.contractsManager.contracts) {
let contract = this.contractsManager.contracts[className];
let abi = JSON.stringify(contract.abiDefinition);
result += Templates.vanilla_contract({className: className, abi: abi, contract: contract});
}
return result;
}
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 (let className in this.contractsManager.contracts) {
let contract = this.contractsManager.contracts[className];
let abi = JSON.stringify(contract.abiDefinition);
let gasEstimates = JSON.stringify(contract.gasEstimates);
let block = "";
if (useEmbarkJS) {
let contractAddress = contract.deployedAddress ? ("'" + contract.deployedAddress + "'") : "undefined";
block += Templates.embarkjs_contract({className: className, abi: abi, contract: contract, contractAddress: contractAddress, gasEstimates: gasEstimates});
} else {
block += Templates.vanilla_contract({className: className, abi: abi, contract: contract});
}
result += Templates.exec_when_ready({block: block});
}
}
return result;
}
generateStorageInitialization(useEmbarkJS) {
let self = this;
let result = "\n";
if (!useEmbarkJS || self.storageConfig === {}) return "";
result += Templates.define_when_env_loaded();
if (self.storageConfig.provider === 'ipfs' && self.storageConfig.enabled === true) {
let block = "\nEmbarkJS.Storage.setProvider('" + self.storageConfig.provider + "', {server: '" + self.storageConfig.host + "', port: '" + self.storageConfig.port + "', getUrl: '" + self.storageConfig.getUrl + "'});";
result += Templates.exec_when_env_loaded({block: block});
}
return result;
}
generateCommunicationInitialization(useEmbarkJS) {
let self = this;
let result = "\n";
if (!useEmbarkJS || self.communicationConfig === {}) return "";
// TODO: don't repeat this twice; should have 'requirements' generator first
result += Templates.define_when_env_loaded();
let block;
// TODO: refactor this
if (self.communicationConfig.provider === 'whisper' && self.communicationConfig.enabled === true) {
if (self.communicationConfig.connection === undefined) {
block = "\nEmbarkJS.Messages.setProvider('" + self.communicationConfig.provider + "');";
} else {
block = "\nEmbarkJS.Messages.setProvider('" + self.communicationConfig.provider + "', {server: '" + self.communicationConfig.connection.host + "', port: '" + self.communicationConfig.connection.port + "', type: '" + self.communicationConfig.connection.type + "'});";
}
result += Templates.exec_when_env_loaded({block: block});
} else if (self.communicationConfig.provider === 'orbit' && self.communicationConfig.enabled === true) {
if (self.communicationConfig.connection === undefined) {
block = "\nEmbarkJS.Messages.setProvider('" + self.communicationConfig.provider + "');";
} else {
block = "\nEmbarkJS.Messages.setProvider('" + self.communicationConfig.provider + "', {server: '" + self.communicationConfig.connection.host + "', port: '" + self.communicationConfig.connection.port + "', type: '" + self.communicationConfig.connection.type + "'});";
}
result += Templates.exec_when_env_loaded({block: block});
}
return result;
}
generateABI(options) {
let result = "";
result += this.generateProvider(options.deployment);
result += this.generateContracts(options.useEmbarkJS, options.deployment, true);
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 = {};
contractJSON.contract_name = className;
contractJSON.address = contract.deployedAddress;
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 = CodeGenerator;

View File

@ -0,0 +1,3 @@
__mainContext.web3 = undefined;
web3 = new Web3(new Web3.providers.HttpProvider("<%- url -%>'"));
<%- done %>

View File

@ -0,0 +1,7 @@
var whenEnvIsLoaded = function(cb) {
if (typeof document !== 'undefined' && document !== null) {
document.addEventListener('DOMContentLoaded', cb);
} else {
cb();
}
}

View File

@ -0,0 +1,6 @@
whenEnvIsLoaded(function(){
__mainContext.__loadManagerInstance.doFirst(function(done) {
<%- block %>
})
});

View File

@ -0,0 +1 @@
__mainContext.<%- className %> = new EmbarkJS.Contract({abi: <%- abi %>, address: <%- contractAddress %>, code: '<%- contract.code %>', gasEstimates: <%- gasEstimates %>});

View File

@ -0,0 +1,3 @@
whenEnvIsLoaded(function() {
<%- block %>
});

View File

@ -0,0 +1,3 @@
__mainContext.__loadManagerInstance.execWhenReady(function() {
<%- block %>
});

View File

@ -0,0 +1,4 @@
__mainContext.__LoadManager = function() { this.list = []; this.done = false; }
__mainContext.__LoadManager.prototype.execWhenReady = function(cb) { if (this.done) { cb(); } else { this.list.push(cb) } }
__mainContext.__LoadManager.prototype.doFirst = function(todo) { var self = this; todo(function() { self.done = true; self.list.map((x) => x.apply()) }) }
__mainContext.__loadManagerInstance = new __mainContext.__LoadManager();

View File

@ -0,0 +1 @@
var __mainContext = __mainContext || this;

View File

@ -0,0 +1,36 @@
function __reduce(arr, memo, iteratee, cb) {
if (typeof cb !== 'function') {
if (typeof memo === 'function' && typeof iteratee === 'function') {
cb = iteratee;
iteratee = memo;
memo = [];
} else {
throw new TypeError('expected callback to be a function');
}
}
if (!Array.isArray(arr)) {
cb(new TypeError('expected an array'));
return;
}
if (typeof iteratee !== 'function') {
cb(new TypeError('expected iteratee to be a function'));
return;
}
(function next(i, acc) {
if (i === arr.length) {
cb(null, acc);
return;
}
iteratee(acc, arr[i], function(err, val) {
if (err) {
cb(err);
return;
}
next(i + 1, val);
});
})(0, memo);
};

View File

@ -0,0 +1,3 @@
<%- className %>Abi = <%- abi %>;
<%- className %>Contract = web3.eth.contract(<%- className %>Abi);
<%- className %> = <%= className %>Contract.at('<%- contract.deployedAddress %>');

View File

@ -0,0 +1,28 @@
__mainContext.web3 = undefined;
__reduce(<%- connectionList %>,function(prev, value, next) {
if (prev === false) {
return next(null, false);
}
if (value === '$WEB3' && (typeof web3 !== 'undefined' && typeof Web3 !== 'undefined')) {
web3 = new Web3(web3.currentProvider);
} else if (value !== '$WEB3' && (typeof Web3 !== 'undefined' && ((typeof web3 === 'undefined') || (typeof web3 !== 'undefined' && (!web3.isConnected || (web3.isConnected && !web3.isConnected())))))) {
web3 = new Web3(new Web3.providers.HttpProvider(value));
} else if (value === '$WEB3') {
return next(null, '');
}
web3.eth.getAccounts(function(err, account) {
if (err) {
next(null, true)
} else {
next(null, false)
}
});
}, function(err, _result) {
web3.eth.getAccounts(function(err, accounts) {
web3.eth.defaultAccount = accounts[0];
<%- done %>
});
});

View File

@ -6,6 +6,7 @@ class Compiler {
constructor(options) {
this.plugins = options.plugins;
this.logger = options.logger;
this.solcVersion = options.solcVersion;
}
compile_contracts(contractFiles, cb) {
@ -32,7 +33,8 @@ class Compiler {
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);
let fileMatch = file.filename.match(/\.[0-9a-z]+$/);
return (fileMatch && (fileMatch[0] === extension));
});
compiler.call(compiler, matchingFiles || [], function (err, compileResult) {
@ -52,16 +54,22 @@ class Compiler {
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();
async.each(contractFiles,
function(file, fileCb) {
let filename = file.filename.replace('app/contracts/', '');
file.content(function(fileContent) {
input[filename] = fileContent;
fileCb();
});
},
function (err) {
callback(err);
}
);
},
function loadCompiler(callback) {
// TODO: there ino need to load this twice
solcW = new SolcW();
solcW = new SolcW({logger: self.logger, solcVersion: self.solcVersion});
if (solcW.isCompilerLoaded()) {
return callback();
}
@ -75,7 +83,12 @@ class Compiler {
self.logger.info("compiling contracts...");
solcW.compile({sources: input}, 1, function (output) {
if (output.errors) {
return callback(new Error("Solidity errors: " + output.errors).message);
for (let i=0; i<output.errors; i++) {
if (output.errors[i].indexOf('Warning:') >= 0) {
return callback(new Error("Solidity errors: " + output.errors).message);
}
}
self.logger.warn(output.errors.join('\n'));
}
callback(null, output);
});
@ -94,6 +107,7 @@ class Compiler {
// [2] classname
const regex = /(.*):(.*)/;
const className = contractName.match(regex)[2];
const filename = contractName.match(regex)[1];
compiled_object[className] = {};
compiled_object[className].code = contract.bytecode;
@ -103,7 +117,9 @@ class Compiler {
compiled_object[className].gasEstimates = contract.gasEstimates;
compiled_object[className].functionHashes = contract.functionHashes;
compiled_object[className].abiDefinition = JSON.parse(contract.interface);
compiled_object[className].filename = filename;
}
callback(null, compiled_object);
}
], function (err, result) {

View File

@ -12,6 +12,11 @@ class ContractsManager {
this.contracts = {};
this.logger = options.logger;
this.plugins = options.plugins;
if (!options.contractsConfig.versions) {
this.solcVersion = "0.4.17";
} else {
this.solcVersion = options.contractsConfig.versions.solc;
}
this.contractDependencies = {};
}
@ -20,7 +25,7 @@ class ContractsManager {
let self = this;
async.waterfall([
function compileContracts(callback) {
let compiler = new Compiler({plugins: self.plugins, logger: self.logger});
let compiler = new Compiler({plugins: self.plugins, logger: self.logger, solcVersion: self.solcVersion});
compiler.compile_contracts(self.contractFiles, function (err, compiledObject) {
self.compiledContracts = compiledObject;
callback(err);
@ -61,6 +66,7 @@ class ContractsManager {
contract.gasEstimates = compiledContract.gasEstimates;
contract.functionHashes = compiledContract.functionHashes;
contract.abiDefinition = compiledContract.abiDefinition;
contract.filename = compiledContract.filename;
contract.gas = (contractConfig && contractConfig.gas) || self.contractsConfig.gas || 'auto';
self.adjustGas(contract);
@ -136,8 +142,15 @@ class ContractsManager {
for (className in self.contracts) {
contract = self.contracts[className];
if (contract.args === []) continue;
// look in code for dependencies
let libMatches = (contract.code.match(/\:(.*?)(?=_)/g) || []);
for (let match of libMatches) {
self.contractDependencies[className] = self.contractDependencies[className] || [];
self.contractDependencies[className].push(match.substr(1));
}
// look in arguments for dependencies
if (contract.args === []) continue;
let ref = contract.args;
for (let j = 0; j < ref.length; j++) {
let arg = ref[j];
@ -149,7 +162,7 @@ class ContractsManager {
}
callback();
}
], function (err, result) {
], function (err, _result) {
if (err) {
self.logger.error("Error Compiling/Building contracts: " + err);
}

View File

@ -3,7 +3,7 @@ let async = require('async');
let RunCode = require('../core/runCode.js');
let DeployTracker = require('./deploy_tracker.js');
let ABIGenerator = require('./abi.js');
let CodeGenerator = require('./code_generator.js');
class Deploy {
constructor(options) {
@ -36,12 +36,7 @@ class Deploy {
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) {
@ -81,11 +76,11 @@ class Deploy {
if (contract.onDeploy !== undefined) {
self.logger.info('executing onDeploy commands');
let abiGenerator = new ABIGenerator({contractsManager: self.contractsManager});
let abi = abiGenerator.generateContracts(false);
let codeGenerator = new CodeGenerator({contractsManager: self.contractsManager});
let code = codeGenerator.generateContracts(false, true, true);
let cmds = contract.onDeploy.join(';\n');
RunCode.doEval(abi + "\n" + cmds, self.web3);
RunCode.doEval(code + "\n" + cmds, self.web3);
}
callback();
@ -105,18 +100,32 @@ class Deploy {
return callback(new Error(err));
}
let contractCode = contract.code;
let contractsList = self.contractsManager.listContracts();
for (let contractObj of contractsList) {
let filename = contractObj.filename;
let deployedAddress = contractObj.deployedAddress;
if (deployedAddress) {
deployedAddress = deployedAddress.substr(2);
}
let linkReference = '__' + filename + ":" + contractObj.className;
let toReplace = linkReference + "_".repeat(40 - linkReference.length);
contractCode = contractCode.replace(new RegExp(toReplace, "g"), deployedAddress);
}
// 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,
data: "0x" + contractCode,
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());
@ -150,7 +159,7 @@ class Deploy {
self.logger.trace(arguments);
self.checkAndDeployContract(contract, null, callback);
},
function (err, results) {
function (err, _results) {
if (err) {
self.logger.error("error deploying contracts");
self.logger.error(err.message);

View File

@ -42,7 +42,7 @@ class DeployManager {
return callback(Error("error connecting to blockchain node"));
}
if (self.web3.currentProvider.isConnected === undefined) {
self.web3.version.getNode(function (err, version) {
self.web3.version.getNode(function (err, _version) {
if (err) {
return callback(Error("error connecting to blockchain node"));
}

View File

@ -2,7 +2,7 @@ let solc;
process.on('message', function (msg) {
if (msg.action === 'loadCompiler') {
solc = require('solc');
solc = require(msg.solcLocation);
process.send({result: "loadedCompiler"});
}

View File

@ -1,9 +1,17 @@
let utils = require('../utils/utils.js');
let solcProcess;
let compilerLoaded = false;
var Npm = require('../pipeline/npm.js');
let path = require('path');
let currentSolcVersion = require('../../package.json').dependencies.solc;
class SolcW {
constructor(options) {
this.solcVersion = options.solcVersion;
this.logger = options.logger;
}
load_compiler(done) {
if (compilerLoaded) {
done();
@ -16,7 +24,17 @@ class SolcW {
compilerLoaded = true;
done();
});
solcProcess.send({action: 'loadCompiler'});
if (this.solcVersion === currentSolcVersion) {
solcProcess.send({action: 'loadCompiler', solcLocation: 'solc'});
} else {
let npm = new Npm({logger: this.logger});
npm.getPackageVersion('solc', this.solcVersion, false, false, function(location) {
let requirePath = path.join(process.env.PWD, location);
solcProcess.send({action: 'loadCompiler', solcLocation: requirePath});
});
}
}
isCompilerLoaded() {

View File

@ -1,6 +1,9 @@
var fs = require('./fs.js');
var File = require('./file.js');
var Plugins = require('./plugins.js');
var utils = require('../utils/utils.js');
var Npm = require('../pipeline/npm.js');
let currentWeb3Version = require('../../package.json').dependencies.web3.replace("^","");
// TODO: add wrapper for fs so it can also work in the browser
// can work with both read and save
@ -44,6 +47,7 @@ Config.prototype.loadConfigFiles = function(options) {
this.loadStorageConfigFile();
this.loadCommunicationConfigFile();
this.loadContractsConfigFile();
this.loadPipelineConfigFile();
this.loadContractsConfigFile();
@ -57,6 +61,7 @@ Config.prototype.reloadConfig = function() {
this.loadBlockchainConfigFile();
this.loadStorageConfigFile();
this.loadCommunicationConfigFile();
this.loadContractsConfigFile();
this.loadPipelineConfigFile();
this.loadContractsConfigFile();
this.loadChainTrackerFile();
@ -73,7 +78,21 @@ Config.prototype.loadBlockchainConfigFile = function() {
Config.prototype.loadContractsConfigFile = function() {
var configObject = {};
var configObject = {
"versions": {
"web3.js": "0.19.1",
"solc": "0.4.17"
},
"deployment": {
"host": "localhost",
"port": 8545,
"type": "rpc"
},
"dappConnection": [
"$WEB3",
"localhost:8545"
]
};
var configPlugins = this.plugins.getPluginsFor('contractsConfig');
if (configPlugins.length > 0) {
@ -102,7 +121,8 @@ Config.prototype.loadStorageConfigFile = function() {
"ipfs_bin": "ipfs",
"provider": "ipfs",
"host": "localhost",
"port": 5001
"port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
},
"development": {
}
@ -142,7 +162,12 @@ Config.prototype.loadCommunicationConfigFile = function() {
"default": {
"enabled": true,
"provider": "whisper",
"available_providers": ["whisper", "orbit"]
"available_providers": ["whisper", "orbit"],
"connection": {
"host": "localhost",
"port": 8546,
"type": "ws"
}
}
};
@ -228,24 +253,46 @@ Config.prototype.loadFiles = function(files) {
// get embark.js object first
originalFiles.filter(function(file) {
return file.indexOf('.') >= 0;
return (file[0] === '$' || file.indexOf('.') >= 0);
}).filter(function(file) {
if (file === 'embark.js') {
if (self.blockchainConfig.enabled || self.communicationConfig.provider === 'whisper' || self.communicationConfig.available_providers.indexOf('whisper') >= 0) {
readFiles.push({filename: 'web3.js', content: fs.readFileSync(fs.embarkPath("node_modules/web3/dist/web3.min.js")).toString(), path: fs.embarkPath("node_modules/web3/dist/web3.min.js")});
let web3Version = self.contractsConfig.versions["web3.js"];
if (web3Version && web3Version != currentWeb3Version) {
//if (false) {
//readFiles.push(new File({filename: 'web3-' + web3Version + '.js', type: 'custom', resolver: function(callback) {
readFiles.push(new File({filename: 'web3.js', type: 'custom', resolver: function(callback) {
if (web3Version === "1.0.0-beta") {
return callback(fs.readFileSync(fs.embarkPath('js/web3-1.0.min.js')).toString());
} else {
let npm = new Npm({logger: self.logger});
npm.getPackageVersion('web3', web3Version, 'dist/web3.min.js', true, function(web3Content) {
callback(web3Content);
});
}
}}));
} else {
readFiles.push(new File({filename: 'web3.js', type: 'embark_internal', path: "js/web3.js"}));
}
}
if (self.storageConfig.enabled && (self.storageConfig.provider === 'ipfs' || self.storageConfig.available_providers.indexOf('ipfs') >= 0)) {
readFiles.push({filename: 'ipfs.js', content: fs.readFileSync(fs.embarkPath("node_modules/ipfs-api/dist/index.min.js")).toString(), path: fs.embarkPath("node_modules/ipfs-api/dist/index.min.js")});
readFiles.push(new File({filename: 'ipfs.js', type: 'embark_internal', path: "node_modules/ipfs-api/dist/index.min.js"}));
}
if (self.communicationConfig.enabled && (self.communicationConfig.provider === 'orbit' || self.communicationConfig.available_providers.indexOf('orbit') >= 0)) {
readFiles.push({filename: 'orbit.js', content: fs.readFileSync(fs.embarkPath("node_modules/orbit-db/dist/orbitdb.min.js")).toString(), path: fs.embarkPath("node_modules/orbit-db/dist/orbitdb.min.js")});
readFiles.push(new File ({filename: 'orbit.js', type: 'embark_internal', path: "node_modules/orbit-db/dist/orbitdb.min.js"}));
}
readFiles.push({filename: 'embark.js', content: fs.readFileSync(fs.embarkPath("js/build/embark.bundle.js")).toString(), path: fs.embarkPath("js/build/embark.bundle.js")});
readFiles.push(new File ({filename: 'embark.js', type: 'embark_internal', path: "js/build/embark.bundle.js"}));
}
if (file === '$EMBARK_JS') {
readFiles.push(new File({filename: '$EMBARK_JS', type: 'embark_internal', path: "js/build/embark.bundle.js"}));
}
//if (file === "web3.js") {
// readFiles.push(new File({filename: 'web3.js', type: 'embark_internal', path: "js/web3.js"));
//}
});
// get plugins
@ -280,10 +327,18 @@ Config.prototype.loadFiles = function(files) {
}).filter(function(file) {
if (file === 'embark.js') {
return;
} else if (file === 'abi.js') {
readFiles.push({filename: file, content: "", path: file});
} else if (file.indexOf("web3-") === 0) {
return;
} else if (file.indexOf("web3") === 0) {
return;
//} else if (file === 'abi.js') {
// readFiles.push({filename: file, content: "", path: file});
} else {
readFiles.push({filename: file, content: fs.readFileSync(file).toString(), path: file});
if (file.indexOf('.') >= 0) {
readFiles.push(new File({filename: file, type: "dapp_file", path: file}));
} else if (file[0] === '$') {
//readFiles.push(new File({filename: file, type: 'embark_internal', path: file}));
}
}
});
@ -298,7 +353,10 @@ Config.prototype.loadPluginContractFiles = function() {
contractsPlugins.forEach(function(plugin) {
plugin.contractsFiles.forEach(function(file) {
var filename = file.replace('./','');
self.contractsFiles.push({filename: filename, content: plugin.loadPluginFile(file), path: plugin.pathToFile(file)});
//self.contractsFiles.push({filename: filename, content: plugin.loadPluginFile(file), path: plugin.pathToFile(file)});
self.contractsFiles.push(new File({filename: filename, type: 'custom', resolver: function(callback) {
callback(plugin.loadPluginFile(file));
}}));
});
});
}

View File

@ -4,7 +4,7 @@ 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 CodeGenerator = require('../contracts/code_generator.js');
let ServicesMonitor = require('./services_monitor.js');
let Pipeline = require('../pipeline/pipeline.js');
let Server = require('../pipeline/server.js');
@ -22,7 +22,7 @@ class Engine {
let self = this;
let options = _options || {};
this.events = new Events();
this.logger = options.logger || new Logger({logLevel: 'debug'});
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;
@ -51,7 +51,7 @@ class Engine {
let services = {
"pipeline": this.pipelineService,
"abi": this.abiService,
"codeGenerator": this.codeGeneratorService,
"deployment": this.deploymentService,
"fileWatcher": this.fileWatchService,
"webServer": this.webServerService,
@ -70,7 +70,7 @@ class Engine {
return service.apply(this, [options]);
}
pipelineService(options) {
pipelineService(_options) {
let self = this;
this.logger.setStatus("Building Assets");
let pipeline = new Pipeline({
@ -80,11 +80,14 @@ class Engine {
logger: this.logger,
plugins: this.plugins
});
this.events.on('abi', function (abi, contractsJSON) {
self.currentAbi = abi;
self.contractsJSON = contractsJSON;
pipeline.build(abi, contractsJSON);
self.events.emit('outputDone');
this.events.on('code-generator-ready', function () {
self.events.request('code', function (abi, contractsJSON) {
self.currentAbi = abi;
self.contractsJSON = contractsJSON;
pipeline.build(abi, contractsJSON, null, function() {
self.events.emit('outputDone');
});
});
});
// TODO: still need to redeploy contracts because the original contracts
// config is being corrupted
@ -97,27 +100,24 @@ class Engine {
//});
}
abiService(options) {
codeGeneratorService(_options) {
let self = this;
let generateABICode = function (contractsManager) {
let abiGenerator = new ABIGenerator({
let generateCode = function (contractsManager) {
let codeGenerator = new CodeGenerator({
blockchainConfig: self.config.blockchainConfig,
contractsConfig: self.config.contractsConfig,
contractsManager: contractsManager,
plugins: self.plugins,
storageConfig: self.config.storageConfig,
communicationConfig: self.config.communicationConfig
communicationConfig: self.config.communicationConfig,
events: self.events
});
let embarkJSABI = abiGenerator.generateABI({useEmbarkJS: true});
let vanillaABI = abiGenerator.generateABI({useEmbarkJS: false});
let vanillaContractsABI = abiGenerator.generateContracts(false);
let contractsJSON = abiGenerator.generateContractsJSON();
codeGenerator.listenToCommands();
self.events.emit('abi-contracts-vanila', vanillaContractsABI, contractsJSON);
self.events.emit('abi-vanila', vanillaABI, contractsJSON);
self.events.emit('abi', embarkJSABI, contractsJSON);
self.events.emit('code-generator-ready');
};
this.events.on('contractsDeployed', generateABICode);
this.events.on('blockchainDisabled', generateABICode);
this.events.on('contractsDeployed', generateCode);
this.events.on('blockchainDisabled', generateCode);
}
deploymentService(options) {
@ -131,7 +131,7 @@ class Engine {
events: this.events
});
this.events.on('file-event', function (fileType, path) {
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') {
@ -142,7 +142,7 @@ class Engine {
});
}
fileWatchService(options) {
fileWatchService(_options) {
this.logger.setStatus("Watching for changes");
let watch = new Watch({logger: this.logger, events: this.events});
watch.start();
@ -174,7 +174,7 @@ class Engine {
});
}
ipfsService(options) {
ipfsService(_options) {
let self = this;
self.servicesMonitor.addCheck('IPFS', function (cb) {
utils.checkIsAvailable('http://localhost:5001', function (available) {
@ -219,8 +219,12 @@ class Engine {
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));
if (this.config.contractsConfig.deployment.type === "rpc") {
let web3Endpoint = 'http://' + this.config.contractsConfig.deployment.host + ':' + this.config.contractsConfig.deployment.port;
this.web3.setProvider(new this.web3.providers.HttpProvider(web3Endpoint));
} else {
throw new Error("contracts config error: unknown deployment type " + this.config.contractsConfig.deployment.type);
}
}
self.servicesMonitor.addCheck('Ethereum', function (cb) {
@ -235,11 +239,13 @@ class Engine {
});
self.servicesMonitor.addCheck('Whisper', function (cb) {
self.web3.version.getWhisper(function (err, res) {
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', status: 'on'});
return cb({name: 'Whisper (version ' + version + ')', status: 'on'});
}
});
});

View File

@ -1,3 +1,52 @@
var EventEmitter = require('events');
function warnIfLegacy(eventName) {
const legacyEvents = ['abi-vanila', 'abi', 'abi-contracts-vanila', 'abi-vanila-deployment'];
if (legacyEvents.indexOf(eventName) >= 0) {
console.info("this event is deprecated and will be removed in future versions: " + eventName);
}
}
function log(eventType, eventName) {
if (['end', 'prefinish', 'error', 'new', 'demo', 'block', 'version'].indexOf(eventName) >= 0) {
return;
}
//console.log(eventType, eventName);
}
const _on = EventEmitter.prototype.on;
const _setHandler = EventEmitter.prototype.setHandler;
EventEmitter.prototype.on = function(requestName, cb) {
log("listening to event: ", requestName);
warnIfLegacy(requestName);
return _on.call(this, requestName, cb);
};
EventEmitter.prototype.setHandler = function(requestName, cb) {
log("setting handler for: ", requestName);
warnIfLegacy(requestName);
return _setHandler.call(this, requestName, cb);
};
EventEmitter.prototype.request = function(requestName, cb) {
log("requesting: ", requestName);
warnIfLegacy(requestName);
return this.emit('request:' + requestName, cb);
};
EventEmitter.prototype.setCommandHandler = function(requestName, cb) {
log("setting command handler for: ", requestName);
return this.on('request:' + requestName, function(_cb) {
cb.call(this, _cb);
});
};
EventEmitter.prototype.setCommandHandlerOnce = function(requestName, cb) {
log("setting command handler for: ", requestName);
return this.once('request:' + requestName, function(_cb) {
cb.call(this, _cb);
});
};
module.exports = EventEmitter;

26
lib/core/file.js Normal file
View File

@ -0,0 +1,26 @@
let fs = require('./fs.js');
class File {
constructor(options) {
this.filename = options.filename;
this.type = options.type;
this.path = options.path;
this.resolver = options.resolver;
}
content(callback) {
if (this.type === 'embark_internal') {
return callback(fs.readFileSync(fs.embarkPath(this.path)).toString());
} else if (this.type === 'dapp_file') {
return callback(fs.readFileSync(this.path).toString());
} else if (this.type === 'custom') {
return this.resolver(callback);
} else {
throw new Error("unknown file: " + this.filename);
}
}
}
module.exports = File;

View File

@ -34,6 +34,10 @@ function embarkPath(fileOrDir) {
return utils.joinPath(__dirname, '/../../', fileOrDir);
}
function dappPath() {
return process.env.PWD;
}
module.exports = {
mkdirpSync: mkdirpSync,
copySync: copySync,

View File

@ -1,5 +1,6 @@
let Web3 = require('web3');
let web3;
let __mainContext;
// ======================
// the eval is used for evaluating some of the contact calls for different purposes
@ -8,9 +9,14 @@ let web3;
// ======================
function doEval(code, _web3) {
if (_web3) {
let web3 = _web3;
web3 = _web3;
}
try {
return eval(code); // jshint ignore:line
} catch(e) {
throw new Error(e + "\n" + code);
}
return eval(code); // jshint ignore:line
}
module.exports = {

76
lib/core/run_tests.js Normal file
View File

@ -0,0 +1,76 @@
module.exports = {
run: function(filepath) {
var Mocha = require('mocha'),
fs = require('fs'),
path = require('path');
var mocha = new Mocha();
if (filepath) {
if (filepath.substr(-1) === '/') {
// Add each .js file to the mocha instance
fs.readdirSync(filepath).filter(function(file){
// Only keep the .js files
// TODO: make this a configuration in embark.json
return file.substr(-3) === '.js';
}).forEach(function(file){
mocha.addFile(
path.join(filepath, file)
);
});
} else {
mocha.addFile(filepath);
}
} else {
var testDir = 'test/';
// Add each .js file to the mocha instance
fs.readdirSync(testDir).filter(function(file){
// Only keep the .js files
// TODO: make this a configuration in embark.json
return file.substr(-3) === '.js';
}).forEach(function(file){
mocha.addFile(
path.join(testDir, file)
);
});
}
let Test = require('./test.js');
global.assert = require('assert');
//global.Embark = require("../index.js");
//global.EmbarkSpec = global.Embark.initTests();
// TODO: check how to pass the options
//global.EmbarkSpec = new Test(options);
global.EmbarkSpec = new Test({});
global.web3 = global.EmbarkSpec.web3;
global.contract = function(describeName, callback) {
return Mocha.describe(describeName, callback);
};
// Run the tests.
let runner = mocha.run(function(failures){
process.on('exit', function () {
process.exit(failures); // exit with non-zero status if there were failures
});
process.exit();
});
runner.on('suite', function() {
global.assert = require('assert');
//global.Embark = require("../index.js");
//global.EmbarkSpec = global.Embark.initTests();
// TODO: check how to pass the options
//global.EmbarkSpec = new Test(options);
global.EmbarkSpec = new Test({});
global.web3 = global.EmbarkSpec.web3;
//global.contract = Mocha.describe;
});
}
};

View File

@ -1,6 +1,22 @@
let getSimulator = function () {
var async = require('async');
var Web3 = require('web3');
var Embark = require('../index.js');
var Engine = require('./engine.js');
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 __mainContext;
var getSimulator = function() {
try {
return require('ethereumjs-testrpc');
var sim = require('ethereumjs-testrpc');
return sim;
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND') {
console.log('Simulator not found; Please install it with "npm install ethereumjs-testrpc --save"');
@ -17,25 +33,74 @@ let getSimulator = function () {
}
};
var Test = function(options) {
this.options = options || {};
var simOptions = this.options.simulatorOptions || {};
class Test {
constructor(options) {
this.opts = options === undefined ? {} : options;
this.opts.logLevel = this.opts.hasOwnProperty('logLevel') ? this.opts.logLevel : 'debug';
this.opts.simulatorOptions = this.opts.hasOwnProperty('simulatorOptions') ? this.opts.simulatorOptions : {};
this.sim = getSimulator();
}
this.engine = new Engine({
env: this.options.env || 'test',
// TODO: confi will need to detect if this is a obj
embarkConfig: this.options.embarkConfig || 'embark.json',
interceptLogs: false
});
newWebThree() {
try {
let Web3 = require('web3');
let web3 = new Web3();
web3.setProvider(this.sim.provider(this.opts.simulatorOptions));
return web3;
} catch (e) {
throw new Error(e);
this.engine.init({
logger: new TestLogger({logLevel: 'debug'})
});
this.sim = getSimulator();
this.web3 = new Web3();
this.web3.setProvider(this.sim.provider(simOptions));
};
Test.prototype.deployAll = function(contractsConfig, cb) {
var self = this;
async.waterfall([
function getConfig(callback) {
self.engine.config.contractsConfig = {contracts: contractsConfig};
callback();
},
function startServices(callback) {
//{abiType: 'contracts', embarkJS: false}
self.engine.startService("codeGenerator");
self.engine.startService("deployment", {
web3: self.web3,
trackContracts: false
});
callback();
},
function deploy(callback) {
self.engine.events.on('code-generator-ready', function () {
self.engine.events.request('code-contracts-vanila', function(vanillaABI) {
callback(null, vanillaABI);
});
});
self.engine.deployManager.deployContracts(function(err, result) {
console.log("deployed contracts");
if (err) {
console.log(err);
callback(err);
}
});
}
], function(err, result) {
if (err) {
console.log("got error");
process.exit();
}
}
}
// this should be part of the waterfall and not just something done at the
// end
self.web3.eth.getAccounts(function(err, accounts) {
if (err) {
throw new Error(err);
}
self.web3.eth.defaultAccount = accounts[0];
RunCode.doEval(result, self.web3); // jshint ignore:line
cb();
});
});
};
module.exports = Test;

View File

@ -5,6 +5,7 @@ class Console {
constructor(options) {
this.plugins = options.plugins;
this.version = options.version;
this.contractsConfig = options.contractsConfig;
}
runCode(code) {
@ -17,6 +18,7 @@ class Console {
'Welcome to Embark ' + this.version,
'',
'possible commands are:',
'versions - display versions in use for libraries and tools like web3 and solc',
// 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',
@ -25,6 +27,20 @@ class Console {
'The web3 object and the interfaces for the deployed contracts and their methods are also available'
];
return helpText.join('\n');
} else if (cmd === 'versions') {
//let currentSolcVersion = require('../../package.json').dependencies.solc;
let solcVersionInConfig = this.contractsConfig.versions.solc;
//let web3Version = require('../../package.json').dependencies["web3.js"].replace("^","");
let web3VersionInConfig = this.contractsConfig.versions["web3.js"];
let text = [
'versions in use:',
'solc: ' + solcVersionInConfig,
'web3.js: ' + web3VersionInConfig
];
return text.join('\n');
} else if (cmd === 'quit') {
utils.exit();
}
@ -32,9 +48,9 @@ class Console {
}
executeCmd(cmd, callback) {
var plugin, pluginOutput;
var plugins = this.plugins.getPluginsFor('console');
for (var i = 0; i < plugins.length; i++) {
let plugin, pluginOutput;
let plugins = this.plugins.getPluginsFor('console');
for (let i = 0; i < plugins.length; i++) {
plugin = plugins[i];
pluginOutput = plugin.runCommands(cmd, {});
if (pluginOutput !== false && pluginOutput !== 'false') return callback(pluginOutput);

View File

@ -9,6 +9,7 @@ class Dashboard {
this.plugins = options.plugins;
this.version = options.version;
this.env = options.env;
this.contractsConfig = options.contractsConfig;
}
start(done) {
@ -17,7 +18,7 @@ class Dashboard {
async.waterfall([
function startConsole(callback) {
console = new Console({plugins: self.plugins, version: self.version});
console = new Console({plugins: self.plugins, version: self.version, contractsConfig: self.contractsConfig});
callback();
},
function startMonitor(callback) {

View File

@ -49,6 +49,8 @@ class Dashboard {
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);
}

View File

@ -76,11 +76,14 @@ class Embark {
logger: engine.logger,
plugins: engine.plugins,
version: self.version,
env: engine.env
env: engine.env,
contractsConfig: engine.config.contractsConfig
});
dashboard.start(function () {
engine.events.on('abi-vanila', function (abi) {
dashboard.console.runCode(abi);
engine.events.on('code-generator-ready', function () {
engine.events.request('code-vanila-deployment', function (abi) {
dashboard.console.runCode(abi);
});
});
engine.logger.info('dashboard start');
@ -100,7 +103,7 @@ class Embark {
engine.startMonitor();
engine.startService("web3");
engine.startService("pipeline");
engine.startService("abi");
engine.startService("codeGenerator");
engine.startService("deployment");
engine.startService("ipfs");
@ -155,7 +158,7 @@ class Embark {
engine.startService("web3");
engine.startService("pipeline");
engine.startService("abi");
engine.startService("codeGenerator");
engine.startService("deployment");
callback();
},
@ -195,6 +198,17 @@ class Embark {
}
}
runTests(file) {
let RunTests = require('./core/run_tests.js');
RunTests.run(file);
}
}
// temporary until next refactor
Embark.initTests = function(options) {
let Test = require('./core/test.js');
return new Test(options);
};
module.exports = Embark;

122
lib/pipeline/npm.js Normal file
View File

@ -0,0 +1,122 @@
// TODO: this is horrible and needs to be refactored ASAP
let utils = require('../utils/utils.js');
let fs = require('../core/fs.js');
let o_fs = require('fs-extra');
let http = require('follow-redirects').http;
let https = require('follow-redirects').https;
var tar = require('tar');
class Npm {
constructor(options) {
this.logger = options.logger;
}
// TODO: callback should accept an error
getPackageVersion(packageName, version, returnContent, getFromGit, callback) {
let self = this;
let npmRegistry = "https://registry.npmjs.org/" + packageName + "/" + version;
utils.httpsGet(npmRegistry, function (res) {
let body = '';
res.on('data', function (d) {
body += d;
});
res.on('end', function () {
let registryJSON = JSON.parse(body);
let tarball = registryJSON.dist.tarball;
var download = function(url, dest, cb) {
var file = o_fs.createWriteStream(dest);
var request = (url.substring(0,5) === 'https' ? https : http).get(url, function(response) {
response.pipe(file);
file.on('finish', function() {
file.close(cb); // close() is async, call cb after close completes.
});
}).on('error', function(err) { // Handle errors
fs.unlink(dest); // Delete the file async. (But we don't check the result)
if (cb) cb(err.message);
});
};
if (getFromGit) {
let repoName = registryJSON.repository.url.replace("git+https://github.com/", "").replace(".git","");
let gitHead = registryJSON.gitHead;
if (!gitHead) {
console.error("Could not download " + packageName + " " + version);
return callback("error");
}
let fileLocation = "https://raw.githubusercontent.com/" + repoName + "/" + gitHead + "/dist/web3.min.js";
let packageDirectory = './.embark/versions/' + packageName + '/' + version + '/';
if (fs.existsSync(packageDirectory + "/" + packageName + ".js")) {
if (returnContent) {
let distFile = packageDirectory + packageName + ".js";
callback(fs.readFileSync(distFile).toString());
} else {
callback(packageDirectory);
}
} else {
fs.mkdirpSync(packageDirectory);
self.logger.info("downloading " + packageName + " " + version + "....");
download(fileLocation, packageDirectory + "/" + packageName + ".js", function() {
o_fs.createReadStream(packageDirectory + "/" + packageName + ".js").pipe(
tar.x({
strip: 1,
C: packageDirectory
}).on('end', function() {
if (returnContent) {
let distFile = packageDirectory + packageName + ".js";
callback(fs.readFileSync(distFile).toString());
} else {
callback(packageDirectory);
}
})
);
});
}
} else {
let packageDirectory = './.embark/versions/' + packageName + '/' + version + '/';
if (fs.existsSync(packageDirectory + "/downloaded_package.tgz")) {
if (returnContent) {
let distFile = packageDirectory + returnContent;
callback(fs.readFileSync(distFile).toString());
} else {
callback(packageDirectory);
}
} else {
fs.mkdirpSync(packageDirectory);
self.logger.info("downloading " + packageName + " " + version + "....");
download(tarball, packageDirectory + "/downloaded_package.tgz", function() {
o_fs.createReadStream(packageDirectory + '/downloaded_package.tgz').pipe(
tar.x({
strip: 1,
C: packageDirectory
}).on('end', function() {
if (returnContent) {
let distFile = packageDirectory + returnContent;
callback(fs.readFileSync(distFile).toString());
} else {
callback(packageDirectory);
}
})
);
});
}
}
});
});
}
}
module.exports = Npm;

View File

@ -1,5 +1,6 @@
/*jshint esversion: 6, loopfunc: true */
let fs = require('../core/fs.js');
let async = require('async');
class Pipeline {
@ -11,73 +12,105 @@ class Pipeline {
this.plugins = options.plugins;
}
build(abi, contractsJSON, path) {
build(abi, contractsJSON, path, callback) {
let self = this;
for (let targetFile in this.assetFiles) {
let contentFiles = this.assetFiles[targetFile].map(file => {
self.logger.trace("reading " + file.filename);
let pipelinePlugins = this.plugins.getPluginsFor('pipeline');
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;
}
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 + '/';
}
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);
}
}
this.buildContracts(contractsJSON);
// limit:1 due to issues when downloading required files such as web3.js
async.eachOfLimit(this.assetFiles, 1, function (files, targetFile, cb) {
// limit:1 due to issues when downloading required files such as web3.js
async.mapLimit(files, 1,
function(file, fileCb) {
self.logger.trace("reading " + file.filename);
let pipelinePlugins = self.plugins.getPluginsFor('pipeline');
if (file.filename === "$ALL_CONTRACTS") {
return fileCb(null, {content: abi, filename: file.filename, path: file.path, modified: true});
} else if (file.filename === "$EMBARK_JS") {
return file.content(function(fileContent) {
return fileCb(null, {content: fileContent, filename: "embark.js", path: file.path, modified: true});
});
} else if (file.filename[0] === '$') {
let contractName = file.filename.substr(1);
return fileCb(null, {content: self.buildContractJS(contractName), filename: contractName + ".js", path: file.path, modified: true});
} else if (file.filename === 'embark.js') {
return file.content(function(fileContent) {
return fileCb(null, {content: fileContent + "\n" + abi, filename: file.filename, path: file.path, modified: true});
});
} else if (file.filename === 'abi.js') {
return fileCb(null, {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.content(function(fileContent) {
return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, modified: true});
});
} else {
if (pipelinePlugins.length > 0) {
file.content(function(fileContent) {
async.eachSeries(pipelinePlugins, function(plugin, pluginCB) {
if (file.options && file.options.skipPipeline) {
return pluginCB();
}
fileContent = plugin.runPipeline({targetFile: file.filename, source: fileContent});
file.modified = true;
pluginCB();
},
function (err) {
if (err) {
self.logger.error(err.message);
}
return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, modified: true});
});
});
} else {
file.content(function(fileContent) {
return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, modified: true});
});
}
}
},
function (err, contentFiles) {
let dir = targetFile.split('/').slice(0, -1).join('/');
self.logger.trace("creating dir " + self.buildDir + dir);
fs.mkdirpSync(self.buildDir + dir);
// if it's a directory
if (targetFile.slice(-1) === '/' || targetFile.indexOf('.') === -1) {
let targetDir = targetFile;
if (targetDir.slice(-1) !== '/') {
targetDir = targetDir + '/';
}
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) {
if (file === undefined) {
return "";
}
return file.content;
}).join("\n");
self.logger.info("writing file " + (self.buildDir + targetFile).bold.dim);
fs.writeFileSync(self.buildDir + targetFile, content);
}
cb();
}
);
},
function (err, results) {
callback();
});
}
buildContracts(contractsJSON) {
@ -88,6 +121,21 @@ class Pipeline {
fs.writeJSONSync(this.buildDir + 'contracts/' + className + ".json", contract, {spaces: 2});
}
}
buildContractJS(contractName) {
let contractJSON = fs.readFileSync('dist/contracts/' + contractName + '.json').toString();
//let EmbarkJSLib = fs.readFileSync(fs.embarkPath("js/embark.js")).toString();
let contractCode = "";
contractCode += "let " + contractName + "JSONConfig = " + contractJSON + ";\n";
//contractCode += EmbarkJSLib + "\n";
contractCode += "let " + contractName + " = new EmbarkJS.Contract(" + contractName + "JSONConfig);\n";
contractCode += "if (typeof module !== 'undefined' && module.exports) {\n";
contractCode += "module.exports = " + contractName + ";\n";
contractCode += "}\n";
return contractCode;
}
}
module.exports = Pipeline;

View File

@ -2,7 +2,8 @@
let path = require('path');
let globule = require('globule');
let merge = require('merge');
let http = require('http');
let http = require('follow-redirects').http;
let https = require('follow-redirects').https;
let shelljs = require('shelljs');
function joinPath() {
@ -33,6 +34,10 @@ function httpGet(url, callback) {
return http.get(url, callback);
}
function httpsGet(url, callback) {
return https.get(url, callback);
}
function runCmd(cmd, options) {
let result = shelljs.exec(cmd, options || {silent: true});
if (result.code !== 0) {
@ -65,6 +70,7 @@ module.exports = {
recursiveMerge: recursiveMerge,
checkIsAvailable: checkIsAvailable,
httpGet: httpGet,
httpsGet: httpsGet,
runCmd: runCmd,
cd: cd,
sed: sed,

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -1,9 +1,9 @@
{
"name": "embark",
"version": "2.4.3",
"version": "2.6.0",
"description": "Embark is a framework that allows you to easily develop and deploy DApps",
"scripts": {
"test": "grunt jshint && mocha test/ --no-timeouts",
"test": "grunt jshint && mocha test/ --no-timeouts && cd test_app/ && npm install && ../bin/embark test",
"prepare": "webpack"
},
"bin": {
@ -23,20 +23,25 @@
"chokidar": "^1.6.0",
"colors": "^1.1.2",
"commander": "^2.8.1",
"ejs": "^2.5.7",
"ethereumjs-testrpc": "3.9.2",
"finalhandler": "^0.5.0",
"follow-redirects": "^1.2.4",
"fs-extra": "^2.0.0",
"globule": "^1.1.0",
"ipfs-api": "^14.0.3",
"merge": "^1.2.0",
"mocha": "^2.2.5",
"orbit-db": "^0.17.3",
"promptly": "^2.1.0",
"serve-static": "^1.11.1",
"shelljs": "^0.5.0",
"solc": "0.4.11",
"solc": "0.4.17",
"tar": "^3.1.5",
"toposort": "^1.0.0",
"underscore": "^1.8.3",
"underscore.string": "^3.3.4",
"web3": "^0.18.2"
"web3": "^0.19.1"
},
"author": "Iuri Matias <iuri.matias@gmail.com>",
"contributors": [],

14
script_test.js Normal file
View File

@ -0,0 +1,14 @@
var Web3 = require('web3');
web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'))
EmbarkJS = require('./js/embark.js');
MyToken = require('./test_app/dist/js/mytoken.js');
console.log(MyToken.address);
MyToken.balanceOf(web3.eth.accounts[0]).then((x) => console.log(x.toNumber()));

View File

@ -1,59 +0,0 @@
/*globals describe, it*/
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() {
let generator = new ABIGenerator({blockchainConfig: {rpcHost: 'somehost', rpcPort: '1234'}, contractsManager: {}});
it('should generate code to connect to a provider', function() {
let providerCode = "\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];";
assert.equal(generator.generateProvider(), providerCode);
});
});
describe('#generateContracts', function() {
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"}],
gasEstimates: 12000,
deployedAddress: "0x123",
code: '12345'
},
Foo: {
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"}],
gasEstimates: 12000,
deployedAddress: "0x124",
code: '123456'
}
}
}});
describe('with EmbarkJS', function() {
let withEmbarkJS = true;
it('should generate contract code', function() {
let contractCode = "\n\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});\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});";
assert.equal(generator.generateContracts(withEmbarkJS), contractCode);
});
});
describe('with default interface', function() {
let withEmbarkJS = false;
it('should generate contract code', function() {
let contractCode = "\n\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');\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');";
assert.equal(generator.generateContracts(withEmbarkJS), contractCode);
});
});
});
//describe('#generateABI', function() {
//});
});

View File

@ -30,7 +30,11 @@ describe('embark.Blockchain', function () {
vmdebug: false,
whisper: true,
account: {},
bootnodes: ""
bootnodes: "",
wsApi: [ "eth", "web3", "net", "shh" ],
wsHost: "localhost",
wsOrigins: false,
wsPort: 8546
};
let blockchain = new Blockchain(config, 'geth');
@ -59,7 +63,11 @@ describe('embark.Blockchain', function () {
vmdebug: false,
whisper: false,
account: {},
bootnodes: ""
bootnodes: "",
wsApi: [ "eth", "web3", "net", "shh" ],
wsHost: "localhost",
wsOrigins: false,
wsPort: 8546
};
let blockchain = new Blockchain(config, 'geth');

59
test/code_generator.js Normal file
View File

@ -0,0 +1,59 @@
/*globals describe, it*/
let CodeGenerator = require('../lib/contracts/code_generator.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.CodeGenerator', function() {
this.timeout(0);
describe('#generateProvider', function() {
let generator = new CodeGenerator({contractsConfig: {"dappConnection": [ "$WEB3", "http://somehost:1234" ] }, contractsManager: {}});
it('should generate code to connect to a provider', function() {
var providerCode = "function __reduce(arr, memo, iteratee, cb) {\n if (typeof cb !== 'function') {\n if (typeof memo === 'function' && typeof iteratee === 'function') {\n cb = iteratee;\n iteratee = memo;\n memo = [];\n } else {\n throw new TypeError('expected callback to be a function');\n }\n }\n\n if (!Array.isArray(arr)) {\n cb(new TypeError('expected an array'));\n return;\n }\n\n if (typeof iteratee !== 'function') {\n cb(new TypeError('expected iteratee to be a function'));\n return;\n }\n\n (function next(i, acc) {\n if (i === arr.length) {\n cb(null, acc);\n return;\n }\n\n iteratee(acc, arr[i], function(err, val) {\n if (err) {\n cb(err);\n return;\n }\n next(i + 1, val);\n });\n })(0, memo);\n};\nvar __mainContext = __mainContext || this;\n__mainContext.__LoadManager = function() { this.list = []; this.done = false; }\n__mainContext.__LoadManager.prototype.execWhenReady = function(cb) { if (this.done) { cb(); } else { this.list.push(cb) } }\n__mainContext.__LoadManager.prototype.doFirst = function(todo) { var self = this; todo(function() { self.done = true; self.list.map((x) => x.apply()) }) }\n__mainContext.__loadManagerInstance = new __mainContext.__LoadManager();\nvar whenEnvIsLoaded = function(cb) {\n if (typeof document !== 'undefined' && document !== null) {\n document.addEventListener('DOMContentLoaded', cb);\n } else {\n cb();\n }\n}\nwhenEnvIsLoaded(function(){\n __mainContext.__loadManagerInstance.doFirst(function(done) {\n __mainContext.web3 = undefined;\n__reduce([\"$WEB3\",\"http://somehost:1234\"],function(prev, value, next) {\n if (prev === false) {\n return next(null, false);\n }\n\n if (value === '$WEB3' && (typeof web3 !== 'undefined' && typeof Web3 !== 'undefined')) {\n web3 = new Web3(web3.currentProvider);\n } else if (value !== '$WEB3' && (typeof Web3 !== 'undefined' && ((typeof web3 === 'undefined') || (typeof web3 !== 'undefined' && (!web3.isConnected || (web3.isConnected && !web3.isConnected())))))) {\n\n web3 = new Web3(new Web3.providers.HttpProvider(value));\n } else if (value === '$WEB3') {\n return next(null, '');\n }\n\n web3.eth.getAccounts(function(err, account) {\n if (err) {\n next(null, true)\n } else {\n next(null, false)\n }\n });\n}, function(err, _result) {\n web3.eth.getAccounts(function(err, accounts) {\n web3.eth.defaultAccount = accounts[0];\n done();\n });\n});\n\n })\n});\n\n";
assert.equal(generator.generateProvider(), providerCode);
});
});
describe('#generateContracts', function() {
let generator = new CodeGenerator({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"}],
gasEstimates: 12000,
deployedAddress: "0x123",
code: '12345'
},
Foo: {
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"}],
gasEstimates: 12000,
deployedAddress: "0x124",
code: '123456'
}
}
}});
describe('with EmbarkJS', function() {
let withEmbarkJS = true;
it('should generate contract code', function() {
var contractCode = "\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n __mainContext.SimpleStorage = 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\n});\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n __mainContext.Foo = 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\n});\n";
assert.equal(generator.generateContracts(withEmbarkJS), contractCode);
});
});
describe('with default interface', function() {
let withEmbarkJS = false;
it('should generate contract code', function() {
var contractCode = "\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n SimpleStorageAbi = [{\"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\n});\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n FooAbi = [{\"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\n});\n";
assert.equal(generator.generateContracts(withEmbarkJS), contractCode);
});
});
});
//describe('#generateABI', function() {
//});
});

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,12 @@
/*globals describe, it*/
let ContractsManager = require('../lib/contracts/contracts.js');
let Logger = require('../lib/core/logger.js');
let File = require('../lib/core/file.js');
let assert = require('assert');
let fs = require('fs');
let readFile = function(file) {
return {filename: file, content: fs.readFileSync(file).toString()};
return new File({filename: file, type: 'dapp_file', path: file});
};
describe('embark.Contratcs', function() {
@ -17,6 +18,19 @@ describe('embark.Contratcs', function() {
readFile('test/contracts/token.sol')
],
contractsConfig: {
"versions": {
"web3.js": "0.19.1",
"solc": "0.4.11"
},
"deployment": {
"host": "localhost",
"port": 8545,
"type": "rpc"
},
"dappConnection": [
"$WEB3",
"localhost:8545"
],
"gas": "auto",
"contracts": {
"Token": {
@ -76,6 +90,19 @@ describe('embark.Contratcs', function() {
readFile('test/contracts/token_storage.sol')
],
contractsConfig: {
"versions": {
"web3.js": "0.19.1",
"solc": "0.4.11"
},
"deployment": {
"host": "localhost",
"port": 8545,
"type": "rpc"
},
"dappConnection": [
"$WEB3",
"localhost:8545"
],
"gas": "auto",
"contracts": {
"TokenStorage": {

View File

@ -1,8 +1,9 @@
pragma solidity ^0.4.7;
pragma solidity ^0.4.17;
contract AnotherStorage {
address public simpleStorageAddress;
address simpleStorageAddress2;
function AnotherStorage(address addr) {
function AnotherStorage(address addr) public {
simpleStorageAddress = addr;
}

View File

@ -0,0 +1,66 @@
// https://github.com/nexusdev/erc20/blob/master/contracts/base.sol
pragma solidity ^0.4.2;
contract Token {
event Transfer(address indexed from, address indexed to, uint value);
event Approval( address indexed owner, address indexed spender, uint value);
mapping( address => uint ) _balances;
mapping( address => mapping( address => uint ) ) _approvals;
uint public _supply;
//uint public _supply2;
function Token( uint initial_balance ) {
_balances[msg.sender] = initial_balance;
_supply = initial_balance;
}
function totalSupply() constant returns (uint supply) {
return _supply;
}
function balanceOf( address who ) constant returns (uint value) {
return _balances[who];
}
function transfer( address to, uint value) returns (bool ok) {
if( _balances[msg.sender] < value ) {
throw;
}
if( !safeToAdd(_balances[to], value) ) {
throw;
}
_balances[msg.sender] -= value;
_balances[to] += value;
Transfer( msg.sender, to, value );
return true;
}
function transferFrom( address from, address to, uint value) returns (bool ok) {
// if you don't have enough balance, throw
if( _balances[from] < value ) {
throw;
}
// if you don't have approval, throw
if( _approvals[from][msg.sender] < value ) {
throw;
}
if( !safeToAdd(_balances[to], value) ) {
throw;
}
// transfer and return true
_approvals[from][msg.sender] -= value;
_balances[from] -= value;
_balances[to] += value;
Transfer( from, to, value );
return true;
}
function approve(address spender, uint value) returns (bool ok) {
// TODO: should increase instead
_approvals[msg.sender][spender] = value;
Approval( msg.sender, spender, value );
return true;
}
function allowance(address owner, address spender) constant returns (uint _allowance) {
return _approvals[owner][spender];
}
function safeToAdd(uint a, uint b) internal returns (bool) {
return (a + b >= a);
}
}

View File

@ -0,0 +1,42 @@
pragma solidity ^0.4.17;
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
if (msg.sender != owner) {
revert();
}
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
if (newOwner != address(0)) {
owner = newOwner;
}
}
}

View File

@ -1,22 +1,29 @@
pragma solidity ^0.4.7;
contract SimpleStorage {
pragma solidity ^0.4.17;
import "ownable.sol";
contract SimpleStorage is Ownable {
uint public storedData;
function() payable { }
function() public payable { }
function SimpleStorage(uint initialValue) {
function SimpleStorage(uint initialValue) public {
storedData = initialValue;
}
function set(uint x) {
function set(uint x) public {
storedData = x;
}
function get() constant returns (uint retVal) {
function set2(uint x, uint unusedGiveWarning) public onlyOwner {
storedData = x;
}
function get() public view returns (uint retVal) {
return storedData;
}
function getS() constant returns (string d) {
function getS() public pure returns (string d) {
return "hello";
}

View File

@ -0,0 +1,17 @@
pragma solidity ^0.4.17;
library ZAMyLib {
function add(uint _a, uint _b) public pure returns (uint _c) {
return _a + _b;
}
}
contract Test {
function testAdd() public pure returns (uint _result) {
return ZAMyLib.add(1, 2);
}
}

View File

@ -1,6 +1,6 @@
// https://github.com/nexusdev/erc20/blob/master/contracts/base.sol
pragma solidity ^0.4.2;
pragma solidity ^0.4.17;
contract Token {
event Transfer(address indexed from, address indexed to, uint value);
@ -10,39 +10,39 @@ contract Token {
mapping( address => mapping( address => uint ) ) _approvals;
uint public _supply;
//uint public _supply2;
function Token( uint initial_balance ) {
function Token( uint initial_balance ) public {
_balances[msg.sender] = initial_balance;
_supply = initial_balance;
}
function totalSupply() constant returns (uint supply) {
function totalSupply() public constant returns (uint supply) {
return _supply;
}
function balanceOf( address who ) constant returns (uint value) {
function balanceOf( address who ) public constant returns (uint value) {
return _balances[who];
}
function transfer( address to, uint value) returns (bool ok) {
function transfer( address to, uint value) public returns (bool ok) {
if( _balances[msg.sender] < value ) {
throw;
revert();
}
if( !safeToAdd(_balances[to], value) ) {
throw;
revert();
}
_balances[msg.sender] -= value;
_balances[to] += value;
Transfer( msg.sender, to, value );
return true;
}
function transferFrom( address from, address to, uint value) returns (bool ok) {
function transferFrom( address from, address to, uint value) public returns (bool ok) {
// if you don't have enough balance, throw
if( _balances[from] < value ) {
throw;
revert();
}
// if you don't have approval, throw
if( _approvals[from][msg.sender] < value ) {
throw;
revert();
}
if( !safeToAdd(_balances[to], value) ) {
throw;
revert();
}
// transfer and return true
_approvals[from][msg.sender] -= value;
@ -51,16 +51,16 @@ contract Token {
Transfer( from, to, value );
return true;
}
function approve(address spender, uint value) returns (bool ok) {
function approve(address spender, uint value) public returns (bool ok) {
// TODO: should increase instead
_approvals[msg.sender][spender] = value;
Approval( msg.sender, spender, value );
return true;
}
function allowance(address owner, address spender) constant returns (uint _allowance) {
function allowance(address owner, address spender) public constant returns (uint _allowance) {
return _approvals[owner][spender];
}
function safeToAdd(uint a, uint b) internal returns (bool) {
function safeToAdd(uint a, uint b) internal pure returns (bool) {
return (a + b >= a);
}
}

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

@ -11,15 +11,31 @@ $(document).ready(function() {
$("#blockchain button.set").click(function() {
var value = parseInt($("#blockchain input.text").val(), 10);
SimpleStorage.set(value);
addToLog("#blockchain", "SimpleStorage.set(" + value + ")");
// If web3.js 1.0 is being used
if (EmbarkJS.isNewWeb3()) {
SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount});
addToLog("#blockchain", "SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount})");
} else {
SimpleStorage.set(value);
addToLog("#blockchain", "SimpleStorage.set(" + value + ")");
}
});
$("#blockchain button.get").click(function() {
SimpleStorage.get().then(function(value) {
$("#blockchain .value").html(value.toNumber());
});
addToLog("#blockchain", "SimpleStorage.get()");
// If web3.js 1.0 is being used
if (EmbarkJS.isNewWeb3()) {
SimpleStorage.methods.get().call(function(err, value) {
$("#blockchain .value").html(value);
});
addToLog("#blockchain", "SimpleStorage.methods.get(console.log)");
} else {
SimpleStorage.get().then(function(value) {
$("#blockchain .value").html(value.toNumber());
});
addToLog("#blockchain", "SimpleStorage.get()");
}
});
});
@ -28,23 +44,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 +104,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 +130,19 @@ $(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();
if (EmbarkJS.Messages.providerName === 'whisper') {
EmbarkJS.Messages.getWhisperVersion(function(err, version) {
if (err) {
$("#communication .error").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 +161,3 @@ $(document).ready(function() {
});
});

View File

@ -1,53 +1,56 @@
$(document).ready(function() {
async.waterfall([
function test1(callback) {
AnotherStorage.simpleStorageAddress().then(function(simpleStorageAddress) {
$("#tests").append("<br>test 1: " + (simpleStorageAddress === SimpleStorage.address));
callback();
});
},
function test2(callback) {
SimpleStorage.storedData().then(function(result) {
$("#tests").append("<br>test 2 (true first time): " + (result.toNumber() === 100));
$("#tests").append("<br>test 2 (true after): " + (result.toNumber() === 150));
callback();
});
},
function test3(callback) {
SimpleStorage.set(150).then(function() {
SimpleStorage.get().then(function(result) {
$("#tests").append("<br>test 3: " + (result.toNumber() === 150));
document.getElementById("runTests").onclick = function() {
async.waterfall([
function test1(callback) {
AnotherStorage.methods.simpleStorageAddress().call().then(function(simpleStorageAddress) {
$("#tests").append("<br>test 1: " + (simpleStorageAddress === SimpleStorage._address));
callback();
});
});
},
function test4(callback) {
$("#tests").append("<br>test 4: " + (Token.address === "undefined"));
$("#tests").append("<br>test 4: " + (MyToken.address !== undefined));
$("#tests").append("<br>test 4: " + (MyToken2.address !== undefined));
callback();
},
function test5(callback) {
MyToken._supply().then(function(result) {
$("#tests").append("<br>test 5: " + (result.toNumber() === 1000));
},
function test2(callback) {
SimpleStorage.methods.storedData().call().then(function(result) {
$("#tests").append("<br>test 2 (true first time): " + (result === "100"));
$("#tests").append("<br>test 2 (true after): " + (result === "150"));
callback();
});
},
function test3(callback) {
SimpleStorage.methods.set(150).send({from: web3.eth.defaultAccount}).then(function() {
SimpleStorage.methods.get().call().then(function(result) {
$("#tests").append("<br>test 3: " + (result === "150"));
callback();
});
});
},
function test4(callback) {
$("#tests").append("<br>test 4: " + (Token._address === null));
$("#tests").append("<br>test 4: " + (MyToken._address !== undefined));
$("#tests").append("<br>test 4: " + (MyToken2._address !== undefined));
callback();
});
},
function test6(callback) {
MyToken2._supply().then(function(result) {
$("#tests").append("<br>test 6: " + (result.toNumber() === 2000));
},
function test5(callback) {
MyToken.methods._supply().call().then(function(result) {
$("#tests").append("<br>test 5: " + (result === "1000"));
callback();
});
},
function test6(callback) {
MyToken2.methods._supply().call().then(function(result) {
$("#tests").append("<br>test 6: " + (result === "2000"));
callback();
});
},
function test7(callback) {
$("#tests").append("<br>test 7: " + (AlreadyDeployedToken._address === "0xeCE374063fE5Cc7EFbACA0a498477CaDA94E5AD6"));
callback();
});
},
function test7(callback) {
$("#tests").append("<br>test 7: " + (AlreadyDeployedToken.address === "0x123"));
callback();
}
], function (err, result) {
}
], function (err, result) {
$("#tests").append("<br>done");
});
});
};
});

View File

View File

@ -6,6 +6,7 @@
</head>
<body class="container">
<button id="runTests">Run Tests</button>
<div id="tests"></div>
</body>

View File

@ -12,7 +12,8 @@
"rpcCorsDomain": "http://localhost:8000",
"account": {
"password": "config/development/password"
}
},
"wsOrigins": "http://localhost:8000"
},
"testnet": {
"networkType": "testnet",

View File

@ -2,6 +2,11 @@
"default": {
"enabled": true,
"provider": "whisper",
"available_providers": ["whisper", "orbit"]
"available_providers": ["whisper", "orbit"],
"connection": {
"host": "localhost",
"port": 8546,
"type": "ws"
}
}
}

View File

@ -1,7 +1,25 @@
{
"default": {
"versions": {
"web3.js": "1.0.0-beta",
"solc": "0.4.17"
},
"deployment": {
"host": "localhost",
"port": 8545,
"type": "rpc"
},
"dappConnection": [
"$WEB3",
"http://localhost:8550",
"http://localhost:8545",
"http://localhost:8550"
],
"gas": "auto",
"contracts": {
"Ownable": {
"deploy": false
},
"SimpleStorage": {
"args": [
100
@ -24,7 +42,7 @@
"args": [200]
},
"AlreadyDeployedToken": {
"address": "0x123",
"address": "0xece374063fe5cc7efbaca0a498477cada94e5ad6",
"instanceOf": "Token"
}
}

View File

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

View File

@ -11,6 +11,7 @@
"enabled": true,
"provider": "ipfs",
"host": "localhost",
"port": 5001
"port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
}
}

View File

@ -7,9 +7,14 @@
"js/embark.js": ["embark.js"],
"js/abi.js": "abi.js",
"js/test.js": ["embark.js", "app/js/_vendor/jquery.min.js", "app/js/_vendor/async.min.js", "app/js/test.js"],
"js/mytoken.js": ["$MyToken", "app/js/token_test.js"],
"index.html": "app/index.html",
"test.html": "app/test.html",
"test2.html": "app/test2.html"
"test2.html": "app/test2.html",
"js/myweb3.js": "web3-0.18.js",
"js/web3.js": "web3.js",
"js/all_contracts.js": "$ALL_CONTRACTS",
"js/only_embark.js": "$EMBARK_JS"
},
"buildDir": "dist/",
"config": "config/",

View File

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

View File

@ -1,7 +1,4 @@
var assert = require('assert');
var EmbarkSpec = require('embark/lib/core/test.js');
describe("AnotherStorage", function() {
contract("AnotherStorage", function() {
before(function(done) {
this.timeout(0);
var contractsConfig = {

View File

@ -1,6 +1,3 @@
var assert = require('assert');
var EmbarkSpec = require('embark/lib/core/test.js');
describe("SimpleStorage", function() {
before(function(done) {
this.timeout(0);

View File

@ -1,6 +1,3 @@
var assert = require('assert');
var EmbarkSpec = require('embark/lib/core/test.js');
describe("Token", function() {
before(function(done) {
this.timeout(0);
@ -31,7 +28,7 @@ describe("Token", function() {
});
it("not deploy Token", function(done) {
assert.equal(Token.address, "undefined");
assert.equal(Token.address, "");
done();
});

View File

@ -1,7 +1,7 @@
module.exports = {
entry: './js/embark.js',
output: {
libraryTarget: 'var',
libraryTarget: 'umd',
library: 'EmbarkJS',
path: __dirname + '/js/build',
filename: 'embark.bundle.js'