WIP to merge in other swarm changes

Adding swarm to embarkjs. WIP.

Add 'auto' setting for geth CORS and websockets origin

* 'auto' now supported for `rpcCorsDomain` and `wsOrigins` in the blockchain config.
* 'auto' set to the default value in blockchain config for test and demo apps.
test add config and contract and add test

addFileToPipeline test and registerBeforeDeploy with new arg

add more registers but generation one fails in run

WIP commit

Undo changes to test config.

Merge pull request #381 from embark-framework/features/cors-auto

Add 'auto' setting for geth CORS and websockets origin
fix a bug where upload cmd used plugin name

don't error if it's an empty dapp with no contracts yet

Merge pull request #383 from embark-framework/no_contracts

don't error if it's an empty dapp with no contracts yet
remove duplicated entry

force zepplein version for travis

Merge pull request #384 from embark-framework/chores/test-allpligin-apis

Small fixes for plugin APIs
intercept logs in the app itself - stopgap fix

Merge pull request #385 from embark-framework/console_logs_fix

intercept logs in the app itself - stopgap fix
* removed unneeded provider property.
* add 'swarm' as a provider in the storage.config
* update method for swarm service check

Merge branch 'develop' into features/add-swarm-to-embarkjs


More work to add swarm to embarkjs

* added eth-lib to parse result of swarm text
* changed "currentStorage" and "currentMessages" to "currentProvider" for consistency.
* added protocol to storage config
* selectively starts storage service depending on which one is configured in the storage config
* run service check for ipfs/swarm prior to uploaded
* added swarm methods for embarkjs

Updated code based on code review

check if testrpc is installed and warn if not

Merge pull request #386 from embark-framework/bug_fix/test-rpc-not-installed

check if testrpc is installed and warn if not
Removed timeout

Removed spacer

Merge pull request #382 from embark-framework/react-demo

Updating embark demo to use react instead of jquery
fix on contract add

Merge pull request #387 from embark-framework/bug_fix/new-contract-in-empty-dapp

Fix adding a contract
redeploy with right config on config change

fix tests

reset watchers after build to make sure files remain watch

Merge pull request #389 from embark-framework/bug_fix/file-changes-not-watched

Fix files not being watched
Merge pull request #388 from embark-framework/bug_fix/changing-contract-config

Redeploy with right config on config change
Added swarm support in embarkjs and isAvailable for messages/storage

* reverted currentProvider back to currentStorage and currentMessages
* added `EmbarkJS.Storage.isAvailable` and `EmbarkJS.Messages.isAvailable()` and underlying provider functions for Whisper, Orbit, IPFS, and Swarm
* Finished swarm implementation in embarkjs plus cleanup
* updated test app storage config to swarm to show swarm config option

Merge branch 'develop' into features/add-swarm-to-embarkjs
This commit is contained in:
Eric Mastro 2018-04-30 15:56:43 +10:00
parent acf1fa427b
commit 2bb977df76
42 changed files with 1445 additions and 383 deletions

View File

@ -182,9 +182,7 @@ EmbarkJS.Contract.prototype.send = function(value, unit, _options) {
EmbarkJS.Storage = {};
EmbarkJS.Storage.Providers = {
SWARM: 'swarm'
};
EmbarkJS.Storage.Providers = {};
EmbarkJS.Storage.saveText = function(text) {
if (!this.currentStorage) {
@ -230,6 +228,10 @@ EmbarkJS.Storage.setProvider = function(provider, options) {
return providerObj.setProvider(options);
};
EmbarkJS.Storage.isAvailable = function(){
return this.currentStorage.isAvailable();
};
EmbarkJS.Messages = {};
EmbarkJS.Messages.Providers = {};
@ -250,6 +252,10 @@ EmbarkJS.Messages.setProvider = function(provider, options) {
return providerObj.setProvider(options);
};
EmbarkJS.Messages.isAvailable = function(){
return this.currentMessages.isAvailable();
};
EmbarkJS.Messages.sendMessage = function(options) {
if (!this.currentMessages) {
throw new Error('Messages provider not set; e.g EmbarkJS.Messages.setProvider("whisper")');

View File

@ -85,3 +85,11 @@ EmbarkJS.Messages.Orbit.listenTo = function(options) {
return promise;
};
// TODO: needs a real check for availability
// TODO: not tested as orbit is not loaded and therefore the provider is not available
EmbarkJS.Messages.Orbit.isAvailable = function(){
return new Promise((resolve) => {
if(!this.orbit) resolve(false);
resolve(true);
});
}

View File

@ -103,14 +103,14 @@ class GethCommands {
if (config.wsOrigins) {
if (config.wsOrigins === '*') {
console.log('==================================');
console.log('rpcCorsDomain set to *');
console.log('wsOrigins 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('warning: wsOrigins is not set');
console.log('==================================');
}
}

View File

@ -3,11 +3,20 @@ let shelljs = require('shelljs');
class Simulator {
constructor(options) {
this.blockchainConfig = options.blockchainConfig;
this.logger = options.logger;
}
run(options) {
let cmds = [];
const testrpc = shelljs.which('testrpc');
const ganache = shelljs.which('ganache-cli');
if (!testrpc && !ganache) {
this.logger.warn('Ganache CLI (TestRPC) is not installed on your machine');
this.logger.info('You can install it by running: npm -g install ganache-cli');
process.exit();
}
cmds.push("-p " + (this.blockchainConfig.rpcPort || options.port || 8545));
cmds.push("-h " + (this.blockchainConfig.rpcHost || options.host || 'localhost'));
cmds.push("-a " + (options.numAccounts || 10));
@ -26,7 +35,8 @@ class Simulator {
cmds.push("-b \"" + (simulatorBlocktime) +"\"");
}
shelljs.exec('testrpc ' + cmds.join(' '), {async : true});
const program = ganache ? 'ganache-cli' : 'testrpc';
shelljs.exec(`${program} ${cmds.join(' ')}`, {async : true});
}
}

View File

@ -13,6 +13,7 @@
"any": "any"
},
"events": {
"contextChange": "contextChange"
"contractFilesChanged": "contractFilesChanged",
"contractConfigChanged": "contractConfigChanged"
}
}

View File

@ -19,6 +19,8 @@ const Templates = {
class CodeGenerator {
constructor(options) {
this.blockchainConfig = options.blockchainConfig || {};
this.rpcHost = this.blockchainConfig.rpcHost || '';
this.rpcPort = this.blockchainConfig.rpcPort || '';
this.contractsConfig = options.contractsConfig || {};
this.storageConfig = options.storageConfig || {};
this.communicationConfig = options.communicationConfig || {};

View File

@ -10,6 +10,10 @@ class Compiler {
const self = this;
let available_compilers = {};
if (contractFiles.length === 0) {
return cb(null, {});
}
let pluginCompilers = self.plugins.getPluginsProperty('compilers', 'compilers');
pluginCompilers.forEach(function (compilerObject) {
available_compilers[compilerObject.extension] = compilerObject.cb;

View File

@ -3,6 +3,7 @@ let async = require('async');
let Compiler = require('./compiler.js');
let utils = require('../utils/utils.js');
const constants = require('../constants');
// TODO: create a contract object
@ -16,6 +17,14 @@ class ContractsManager {
this.contractDependencies = {};
this.gasLimit = options.gasLimit;
this.deployOnlyOnConfig = false;
this.events = options.events;
this.events.on(constants.events.contractFilesChanged, (newContractFiles) => {
this.contractFiles = newContractFiles;
});
this.events.on(constants.events.contractConfigChanged, (newContracts) => {
this.contractsConfig = newContracts;
});
}
build(done) {

View File

@ -280,17 +280,17 @@ class Deploy {
// calling each beforeDeploy handler declared by the plugin
async.eachSeries(plugin.beforeDeploy, (beforeDeployFn, eachCb) => {
function beforeDeployCb(resObj){
contract.code = resObj.contractCode;
eachCb();
}
beforeDeployFn({
embarkDeploy: self,
pluginConfig: plugin.pluginConfig,
deploymentAccount: deploymentAccount,
contract: contract,
callback:
(function(resObj){
contract.code = resObj.contractCode;
eachCb();
})
});
callback: beforeDeployCb
}, beforeDeployCb);
}, () => {
//self.logger.info('All beforeDeploy handlers of the plugin has processed.');
eachPluginCb();
@ -352,8 +352,9 @@ class Deploy {
deployAll(done) {
let self = this;
this.logger.info("deploying contracts");
let contracts = this.contractsManager.listContracts();
async.eachOfSeries(this.contractsManager.listContracts(),
async.eachOfSeries(contracts,
function (contract, key, callback) {
self.logger.trace(arguments);
self.checkAndDeployContract(contract, null, callback);
@ -364,6 +365,10 @@ class Deploy {
self.logger.error(err.message);
self.logger.debug(err.stack);
}
if (contracts.length === 0) {
self.logger.info("no contracts found");
return done();
}
self.logger.info("finished deploying contracts");
self.logger.trace(arguments);
done(err);

View File

@ -3,6 +3,7 @@ const File = require('./file.js');
const Plugins = require('./plugins.js');
const utils = require('../utils/utils.js');
const path = require('path');
const deepEqual = require('deep-equal');
const constants = require('../constants');
var Config = function(options) {
@ -102,7 +103,9 @@ Config.prototype._getFileOrOject = function(object, filePath, property) {
Config.prototype.loadBlockchainConfigFile = function() {
var configObject = {
"default": {
"enabled": true
"enabled": true,
"rpcCorsDomain": "auto",
"wsOrigins": "auto"
}
};
@ -141,7 +144,12 @@ Config.prototype.loadContractsConfigFile = function() {
let configFilePath = this._getFileOrOject(this.configDir, 'contracts.json', 'contracts');
this.contractsConfig = this._mergeConfig(configFilePath, configObject, this.env);
const newContractsConfig = this._mergeConfig(configFilePath, configObject, this.env);
if (!deepEqual(newContractsConfig, this.contractsConfig)) {
this.events.emit(constants.events.contractConfigChanged, newContractsConfig);
this.contractsConfig = newContractsConfig;
}
};
Config.prototype.loadExternalContractsFiles = function() {
@ -175,9 +183,10 @@ Config.prototype.loadStorageConfigFile = function() {
"default": {
"versions": versions,
"enabled": true,
"available_providers": ["ipfs"],
"available_providers": ["ipfs", "swarm"],
"ipfs_bin": "ipfs",
"provider": "ipfs",
"protocol": "http",
"host": "localhost",
"port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
@ -217,8 +226,12 @@ Config.prototype.loadWebServerConfigFile = function() {
};
Config.prototype.loadEmbarkConfigFile = function() {
var contracts = this.embarkConfig.contracts;
this.contractsFiles = this.loadFiles(contracts);
const contracts = this.embarkConfig.contracts;
const newContractsFiles = this.loadFiles(contracts);
if (!this.contractFiles || newContractsFiles.length !== this.contractFiles.length || !deepEqual(newContractsFiles, this.contractFiles)) {
this.events.emit(constants.events.contractFilesChanged, newContractsFiles);
this.contractsFiles = newContractsFiles;
}
// determine contract 'root' directories
this.contractDirectories = contracts.map((dir) => {
return dir.split("**")[0];
@ -286,7 +299,7 @@ Config.prototype.loadFiles = function(files) {
}
});
filesFromPlugins.filter(function(file) {
if (utils.fileMatchesPattern(files, file.intendedPath)) {
if ((file.intendedPath && utils.fileMatchesPattern(files, file.intendedPath)) || utils.fileMatchesPattern(files, file.file)) {
readFiles.push(file);
}
});
@ -301,7 +314,7 @@ Config.prototype.loadPluginContractFiles = function() {
contractsPlugins.forEach(function(plugin) {
plugin.contractsFiles.forEach(function(file) {
var filename = file.replace('./','');
self.contractsFiles.push(new File({filename: filename, type: File.types.custom, resolver: function(callback) {
self.contractsFiles.push(new File({filename: filename, type: File.types.custom, path: filename, resolver: function(callback) {
callback(plugin.loadPluginFile(file));
}}));
});

View File

@ -35,6 +35,53 @@ class Engine {
this.servicesMonitor.addCheck('embarkVersion', function (cb) {
return cb({name: 'Embark ' + self.version, status: 'on'});
}, 0);
if (this.interceptLogs || this.interceptLogs === undefined) {
this.doInterceptLogs();
}
}
doInterceptLogs() {
var self = this;
let context = {};
context.console = console;
let normalizeInput = function(input) {
let args = Object.values(input);
if (args.length === 0) {
return "";
}
if (args.length === 1) {
if (Array.isArray(args[0])) { return args[0].join(','); }
return args[0] || "";
}
return ('[' + args.map((x) => {
if (x === null) { return "null"; }
if (x === undefined) { return "undefined"; }
if (Array.isArray(x)) { return x.join(','); }
return x;
}).toString() + ']');
};
context.console.log = function() {
self.logger.info(normalizeInput(arguments));
};
context.console.warn = function() {
self.logger.warn(normalizeInput(arguments));
};
context.console.info = function() {
self.logger.info(normalizeInput(arguments));
};
context.console.debug = function() {
// TODO: ue JSON.stringify
self.logger.debug(normalizeInput(arguments));
};
context.console.trace = function() {
self.logger.trace(normalizeInput(arguments));
};
context.console.dir = function() {
self.logger.dir(normalizeInput(arguments));
};
}
startMonitor() {
@ -99,17 +146,11 @@ class Engine {
self.currentAbi = abi;
self.contractsJSON = contractsJSON;
pipeline.build(abi, contractsJSON, null, function() {
self.watch.restart(); // Necessary because changing a file while it is writing can stop it from being watched
self.events.emit('outputDone');
});
});
});
// TODO: still need to redeploy contracts because the original contracts
// config is being corrupted
this.events.on('file-event', function(fileType, _path) {
if (fileType === 'asset') {
self.events.emit('asset-changed', self.contractsManager);
}
});
}
codeGeneratorService(_options) {
@ -150,7 +191,8 @@ class Engine {
contractsConfig: this.config.contractsConfig,
logger: this.logger,
plugins: this.plugins,
gasLimit: false
gasLimit: false,
events: this.events
});
this.deployManager = new DeployManager({
@ -164,7 +206,12 @@ class Engine {
onlyCompile: options.onlyCompile
});
this.events.on('file-event', function (fileType, _path) {
this.events.on('file-event', function (fileType) {
// TODO: still need to redeploy contracts because the original contracts
// config is being corrupted
if (fileType === 'asset') {
self.events.emit('asset-changed', self.contractsManager);
}
// 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') {
@ -177,8 +224,8 @@ class Engine {
fileWatchService(_options) {
this.events.emit("status", "Watching for changes");
let watch = new Watch({logger: this.logger, events: this.events});
watch.start();
this.watch = new Watch({logger: this.logger, events: this.events});
this.watch.start();
}
webServerService() {
@ -200,7 +247,7 @@ class Engine {
this.registerModule('swarm', {
addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor),
storageConfig: this.config.storageConfig,
web3: _options.web3
bzz: _options.bzz
});
}

View File

@ -1,5 +1,6 @@
let async = require('async');
const constants = require('./constants');
const _ = require('underscore');
// require("./utils/debug_util.js")(__filename, async);
require('colors');
@ -39,13 +40,25 @@ class Embark {
blockchain(env, client) {
this.context = [constants.contexts.blockchain];
return require('./cmds/blockchain/blockchain.js')(this.config.blockchainConfig, client, env).run();
let blockchainConfig = this.config.blockchainConfig;
let storageConfig = this.config.storageConfig;
let webServerConfig = this.config.webServerConfig;
if(blockchainConfig.rpcCorsDomain === 'auto') {
if(webServerConfig) blockchainConfig.rpcCorsDomain = `http://${webServerConfig.host}:${webServerConfig.port}`;
if(storageConfig) blockchainConfig.rpcCorsDomain += `${blockchainConfig.rpcCorsDomain.length ? ',' : ''}${storageConfig.protocol}://${storageConfig.host}:${storageConfig.port}`;
}
if(blockchainConfig.wsOrigins === 'auto') {
if(webServerConfig) blockchainConfig.wsOrigins = `http://${webServerConfig.host}:${webServerConfig.port}`;
if(storageConfig) blockchainConfig.wsOrigins += `${blockchainConfig.wsOrigins.length ? ',' : ''}${storageConfig.protocol}://${storageConfig.host}:${storageConfig.port}`;
}
return require('./cmds/blockchain/blockchain.js')(blockchainConfig, client, env).run();
}
simulator(options) {
this.context = options.context || [constants.contexts.simulator, constants.contexts.blockchain];
let Simulator = require('./cmds/simulator.js');
let simulator = new Simulator({blockchainConfig: this.config.blockchainConfig});
let simulator = new Simulator({blockchainConfig: this.config.blockchainConfig, logger: this.logger});
simulator.run(options);
}
@ -115,7 +128,7 @@ class Embark {
engine.startService("pipeline");
engine.startService("codeGenerator");
engine.startService("deployment");
engine.startService("ipfs");
engine.startService(engine.config.storageConfig.provider, {bzz: engine.web3.bzz});
engine.events.on('check:backOnline:Ethereum', function () {
engine.logger.info('Ethereum node detected..');
@ -128,6 +141,7 @@ class Embark {
engine.events.on('outputDone', function () {
engine.logger.info("Looking for documentation? You can find it at ".cyan + "http://embark.readthedocs.io/".green.underline + ".".cyan);
engine.logger.info("Ready".underline);
engine.events.emit("status", "Ready".green);
});
engine.deployManager.deployContracts(function (err) {
@ -147,7 +161,6 @@ class Embark {
engine.logger.info(err.stack);
} else {
engine.events.emit('firstDeploymentDone');
engine.events.emit("status", "Ready".green);
let size = windowSize.get();
if (size.height < 40 || size.width < 118) {
@ -188,6 +201,7 @@ class Embark {
engine.startService("codeGenerator");
engine.startService("deployment");
engine.startService("ipfs");
engine.startService("swarm", {bzz: engine.web3.bzz});
callback();
},
function deploy(callback) {
@ -297,10 +311,29 @@ class Embark {
engine.startService("pipeline");
engine.startService("codeGenerator");
engine.startService("deployment");
engine.startService("ipfs");
engine.startService("swarm", {buildDir:'dist/',web3: engine.web3});
engine.startService(platform.toLowerCase(), {bzz: engine.web3.bzz});
engine.startMonitor();
callback();
},
function checkStorageService(callback){
let checkFn;
_.find(engine.servicesMonitor.checkList, (value, key) => {
if(key.toLowerCase() === platform.toLowerCase()){
checkFn = value;
return true;
}
});
if(!checkFn || typeof checkFn.fn !== 'function') callback();
else{
checkFn.fn(function(serviceCheckResult){
if(!serviceCheckResult.status || serviceCheckResult.status === 'off'){
callback({message:`Cannot upload: ${platform} node is not running on http://${engine.config.storageConfig.host}:${engine.config.storageConfig.port}.`});
} else {
callback(null);
}
});
}
},
function setupStoragePlugin(callback){
let pluginList = engine.plugins.listPlugins();
if (pluginList.length > 0) {
@ -312,15 +345,16 @@ class Embark {
if (cmdPlugins.length > 0) {
cmdPlugin = cmdPlugins.find((pluginCmd) => {
return pluginCmd.name == platform;
return pluginCmd.uploadCmds.some(uploadCmd => {
return uploadCmd.cmd === platform;
});
});
}
if (!cmdPlugin) {
engine.logger.info('try "embark upload ipfs" or "embark upload swarm"'.green);
callback({message: 'unknown platform: ' + platform});
} else {
callback();
}
}
else callback(null);
},
function deploy(callback) {
// 2. upload to storage (outputDone event triggered after webpack finished)

View File

@ -100,6 +100,15 @@ __embarkIPFS.uploadFile = function(inputSelector) {
return promise;
};
__embarkIPFS.isAvailable = function(){
return new Promise((resolve) => {
if(!this.ipfsConnection) resolve(false);
this.ipfsConnection.id()
.then((id) => { resolve(Boolean(id)); })
.catch(() => { resolve(false); });
});
};
__embarkIPFS.getUrl = function(hash) {
return (this._getUrl || "http://localhost:8080/ipfs/") + hash;
};

View File

@ -29,7 +29,7 @@ class IPFS {
function runCommand(ipfs_bin, callback) {
let cmd = `"${ipfs_bin}" add -r ${self.buildDir}`;
console.log(("=== adding " + self.buildDir + " to ipfs").green);
console.trace(cmd);
console.debug(cmd);
shelljs.exec(cmd, {silent:true}, function(code, stdout, stderr){ // {silent:true}: don't echo cmd output so it can be controlled via logLevel
console.log(stdout.green);
callback(stderr, stdout);

View File

@ -0,0 +1,84 @@
let __embarkSwarm = {};
const bytes = require("eth-lib/lib/bytes");
__embarkSwarm.setProvider = function(options) {
this.bzz = web3.bzz;
this.protocol = options.protocol;
this.host = options.host;
this.port = options.port;
this.connectUrl = `${options.protocol}://${options.host}:${options.port}`;
this.connectError = new Error(`Cannot connect to Swarm node on ${this.connectUrl}`);
this._getUrl = options.getUrl || `${this.connectUrl}/bzzr:/`;
var promise = new Promise((resolve, reject) => {
try {
if(!this.bzz.currentProvider) {
this.bzz.setProvider(`${options.protocol}://${options.host}:${options.port}`);
}
resolve(this);
} catch (err) {
console.log(err);
reject(this.connectError);
}
});
return promise;
};
__embarkSwarm.isAvailable = function(){
return new Promise((resolve, reject) => {
if(!this.bzz) resolve(false);
this.bzz.isAvailable()
.then(resolve)
.catch(() => { reject(this.connectError); });
});
};
__embarkSwarm.saveText = function(text) {
return new Promise((resolve, reject) => {
this.isAvailable().then((isAvailable) => {
if(!isAvailable) reject(this.connectError);
this.bzz.upload(text)
.then(resolve)
.catch(reject);
}).catch(reject);
});
};
__embarkSwarm.get = function(hash) {
return new Promise((resolve, reject) => {
this.isAvailable().then((isAvailable) => {
if(!isAvailable) reject(this.connectError);
this.bzz.download(hash)
.then((uint8Array) => resolve(bytes.toString(bytes.fromUint8Array(uint8Array))))
.catch(reject);
}).catch(reject);
});
};
__embarkSwarm.uploadFile = function(inputSelector) {
let file = inputSelector[0].files[0];
if (file === undefined) {
throw new Error('no file found');
}
return new Promise((resolve, reject) => {
var reader = new FileReader();
reader.onloadend = (event) => {
var fileContent = new Uint8Array(event.target.result);
this.isAvailable().then((isAvailable) => {
if(!isAvailable) reject(this.connectError);
this.bzz.upload(fileContent)
.then(resolve)
.catch(reject);
}).catch(reject);
};
reader.onerror = reject;
reader.readAsArrayBuffer(file);
});
};
__embarkSwarm.getUrl = function(hash) {
return this._getUrl + hash;
};

View File

@ -1,19 +1,112 @@
let UploadSwarm = require('./upload.js');
let utils = require('../../utils/utils.js');
let fs = require('../../core/fs.js');
class Swarm {
constructor(embark, options) {
this.logger = embark.logger;
this.events = embark.events;
this.buildDir = options.buildDir;
this.storageConfig = options.storageConfig;
this.host = options.host || this.storageConfig.host;
this.port = options.port || this.storageConfig.port;
this.addCheck = options.addCheck;
this.embark = embark;
this.bzz = options.bzz;
this.upload_swarm = new UploadSwarm({
buildDir: options.buildDir || 'dist/',
storageConfig: options.storageConfig,
web3: options.web3
});
embark.registerUploadCommand('swarm', this.upload_swarm.deploy.bind(this.upload_swarm));
this.initSwarmProvider();
this.commandlineDeploy();
this.setServiceCheck();
this.addSwarmToEmbarkJS();
this.addSetProvider();
}
initSwarmProvider(){
if(!this.bzz.currentProvider) {
this.bzz.setProvider(`http://${this.host}:${this.port}`);
}
}
commandlineDeploy() {
this.upload_swarm = new UploadSwarm({
buildDir: this.buildDir || 'dist/',
storageConfig: this.storageConfig,
bzz: this.bzz
});
this.embark.registerUploadCommand('swarm', this.upload_swarm.deploy.bind(this.upload_swarm));
}
setServiceCheck() {
let self = this;
let storageConfig = this.storageConfig;
if (!storageConfig.enabled) {
return;
}
if (storageConfig.provider !== 'swarm' && storageConfig.available_providers.indexOf("swarm") < 0) {
return;
}
this.events.on('check:backOnline:Swarm', function () {
self.logger.info('Swarm node detected...');
});
this.events.on('check:wentOffline:Swarm', function () {
self.logger.info('Swarm node is offline...');
});
if (!this.addCheck) {
return;
}
// add check for console
this.addCheck('Swarm', function(cb){
self.logger.trace("Checking Swarm availability...");
self.bzz.isAvailable().then(result => {
return cb({name: "Swarm ", status: result ? 'on':'off'});
}).catch(err => {
self.logger.trace("Check Swarm availability error: " + err);
return cb({name: "Swarm ", status: 'off'});
});
});
}
addSwarmToEmbarkJS() {
// TODO: make this a shouldAdd condition
if (this.storageConfig === {}) {
return;
}
if ((this.storageConfig.available_providers.indexOf('swarm') < 0) && (this.storageConfig.provider !== 'swarm' || this.storageConfig.enabled !== true)) {
return;
}
let code = "";
code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString();
code += "\nEmbarkJS.Storage.registerProvider('swarm', __embarkSwarm);";
this.embark.addCodeToEmbarkJS(code);
}
addSetProvider() {
let config = JSON.stringify({
host: this.storageConfig.host,
port: this.storageConfig.port,
protocol: this.storageConfig.protocol,
getUrl: this.storageConfig.getUrl
});
let code = "\nEmbarkJS.Storage.setProvider('swarm'," + config + ");";
let shouldInit = (storageConfig) => {
return (storageConfig.provider === 'swarm' && storageConfig.enabled === true);
};
this.embark.addProviderInit('storage', code, shouldInit);
}
}
module.exports = Swarm;

View File

@ -5,7 +5,7 @@ class Swarm {
constructor(options) {
this.options = options;
this.buildDir = options.buildDir || 'dist/';
this.web3 = options.web3;
this.bzz = options.bzz;
this.storageConfig = options.storageConfig;
}
@ -13,15 +13,11 @@ class Swarm {
return new Promise((resolve, reject) => {
console.log("deploying to swarm!");
let self = this;
let web3 = this.web3;
let bzz = this.bzz;
async.waterfall([
function setProvider(callback){
web3.bzz.setProvider(`http://${self.storageConfig.host}:${self.storageConfig.port}`);
callback();
},
function runCommand(callback) {
console.log(("=== adding " + self.buildDir + " to swarm").green);
web3.bzz.upload({
bzz.upload({
path: self.buildDir, // path to data / file / directory
kind: "directory", // could also be "file" or "data"
defaultFile: "index.html" // optional, and only for kind === "directory"

View File

@ -97,3 +97,15 @@ __embarkWhisperNewWeb3.getWhisperVersion = function(cb) {
});
};
__embarkWhisperNewWeb3.isAvailable = function(){
return new Promise((resolve, reject) => {
if(!this.web3.shh) resolve(false);
try{
this.getWhisperVersion((err) => {
resolve(Boolean(!err));
});
}
catch(err){ reject(err); }
});
};

View File

@ -107,3 +107,14 @@ __embarkWhisperOld.getWhisperVersion = function(cb) {
});
};
__embarkWhisperOld.isAvailable = function(){
return new Promise((resolve, reject) => {
if(!this.web3) resolve(false);
try{
this.getWhisperVersion((err) => {
resolve(Boolean(!err));
});
}
catch(err){ reject(err); }
});
};

View File

@ -9,6 +9,7 @@ class Watch {
constructor(options) {
this.logger = options.logger;
this.events = options.events;
this.fileWatchers = [];
}
start() {
@ -32,6 +33,19 @@ class Watch {
this.logger.info("ready to watch file changes");
}
restart() {
this.stop();
this.start();
}
stop() {
this.fileWatchers.forEach(fileWatcher => {
fileWatcher.close();
fileWatcher = null;
});
this.fileWatchers = [];
}
watchAssets(embarkConfig, callback) {
let self = this;
let appConfig = embarkConfig.app;
@ -102,6 +116,7 @@ class Watch {
let configWatcher = chokidar.watch(files, {
ignored: /[\/\\]\./, persistent: true, ignoreInitial: true, followSymlinks: true
});
this.fileWatchers.push(configWatcher);
configWatcher
.on('add', path => changeCallback('add', path))

534
package-lock.json generated
View File

@ -23,7 +23,7 @@
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.2.tgz",
"integrity": "sha512-Q3FWsbdmkQd1ib11A4XNWQvRD//5KpPoGawA8aB2DR7pWKoW9XQv3+dGxD/Z1eVFze23Okdo27ZQytVFlweKvQ==",
"requires": {
"@types/node": "9.6.6"
"@types/node": "10.0.0"
}
},
"@types/lockfile": {
@ -32,16 +32,16 @@
"integrity": "sha512-pD6JuijPmrfi84qF3/TzGQ7zi0QIX+d7ZdetD6jUA6cp+IsCzAquXZfi5viesew+pfpOTIdAVKuh1SHA7KeKzg=="
},
"@types/node": {
"version": "9.6.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.6.tgz",
"integrity": "sha512-SJe0g5cZeGNDP5sD8mIX3scb+eq8LQQZ60FXiKZHipYSeEFZ5EKml+NNMiO76F74TY4PoMWlNxF/YRY40FOvZQ=="
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.0.0.tgz",
"integrity": "sha512-kctoM36XiNZT86a7tPsUje+Q/yl+dqELjtYApi0T5eOQ90Elhu0MI10rmYk44yEP4v1jdDvtjQ9DFtpRtHf2Bw=="
},
"@types/node-fetch": {
"version": "1.6.9",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-1.6.9.tgz",
"integrity": "sha512-n2r6WLoY7+uuPT7pnEtKJCmPUGyJ+cbyBR8Avnu4+m1nzz7DwBVuyIvvlBzCZ/nrpC7rIgb3D6pNavL7rFEa9g==",
"requires": {
"@types/node": "9.6.6"
"@types/node": "10.0.0"
}
},
"@types/semver": {
@ -54,7 +54,7 @@
"resolved": "https://registry.npmjs.org/@types/tar/-/tar-4.0.0.tgz",
"integrity": "sha512-YybbEHNngcHlIWVCYsoj7Oo1JU9JqONuAlt1LlTH/lmL8BMhbzdFUgReY87a05rY1j8mfK47Del+TCkaLAXwLw==",
"requires": {
"@types/node": "9.6.6"
"@types/node": "10.0.0"
}
},
"@types/url-join": {
@ -166,12 +166,236 @@
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
},
"anymatch": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
"integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
"integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
"requires": {
"micromatch": "2.3.11",
"micromatch": "3.1.10",
"normalize-path": "2.1.1"
},
"dependencies": {
"arr-diff": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
"integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
},
"array-unique": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
},
"braces": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
"integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
"requires": {
"arr-flatten": "1.1.0",
"array-unique": "0.3.2",
"extend-shallow": "2.0.1",
"fill-range": "4.0.0",
"isobject": "3.0.1",
"repeat-element": "1.1.2",
"snapdragon": "0.8.2",
"snapdragon-node": "2.1.1",
"split-string": "3.1.0",
"to-regex": "3.0.2"
},
"dependencies": {
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"requires": {
"is-extendable": "0.1.1"
}
}
}
},
"expand-brackets": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
"integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
"requires": {
"debug": "2.6.9",
"define-property": "0.2.5",
"extend-shallow": "2.0.1",
"posix-character-classes": "0.1.1",
"regex-not": "1.0.2",
"snapdragon": "0.8.2",
"to-regex": "3.0.2"
},
"dependencies": {
"define-property": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
"integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
"requires": {
"is-descriptor": "0.1.6"
}
},
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"requires": {
"is-extendable": "0.1.1"
}
},
"is-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
"integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
"requires": {
"is-accessor-descriptor": "0.1.6",
"is-data-descriptor": "0.1.4",
"kind-of": "5.1.0"
}
},
"kind-of": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
"integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
}
}
},
"extglob": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
"integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
"requires": {
"array-unique": "0.3.2",
"define-property": "1.0.0",
"expand-brackets": "2.1.4",
"extend-shallow": "2.0.1",
"fragment-cache": "0.2.1",
"regex-not": "1.0.2",
"snapdragon": "0.8.2",
"to-regex": "3.0.2"
},
"dependencies": {
"define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
"integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
"requires": {
"is-descriptor": "1.0.2"
}
},
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"requires": {
"is-extendable": "0.1.1"
}
}
}
},
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
"requires": {
"extend-shallow": "2.0.1",
"is-number": "3.0.0",
"repeat-string": "1.6.1",
"to-regex-range": "2.1.1"
},
"dependencies": {
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"requires": {
"is-extendable": "0.1.1"
}
}
}
},
"is-accessor-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
"integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
"requires": {
"kind-of": "3.2.2"
},
"dependencies": {
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"requires": {
"is-buffer": "1.1.6"
}
}
}
},
"is-data-descriptor": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
"integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
"requires": {
"kind-of": "3.2.2"
},
"dependencies": {
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"requires": {
"is-buffer": "1.1.6"
}
}
}
},
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"requires": {
"kind-of": "3.2.2"
},
"dependencies": {
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"requires": {
"is-buffer": "1.1.6"
}
}
}
},
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
},
"kind-of": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
"integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
"requires": {
"arr-diff": "4.0.0",
"array-unique": "0.3.2",
"braces": "2.3.2",
"define-property": "2.0.2",
"extend-shallow": "3.0.2",
"extglob": "2.0.4",
"fragment-cache": "0.2.1",
"kind-of": "6.0.2",
"nanomatch": "1.2.9",
"object.pick": "1.3.0",
"regex-not": "1.0.2",
"snapdragon": "0.8.2",
"to-regex": "3.0.2"
}
}
}
},
"argparse": {
@ -186,6 +410,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
"integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
"dev": true,
"requires": {
"arr-flatten": "1.1.0"
}
@ -229,7 +454,8 @@
"array-unique": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
"integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="
"integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
"dev": true
},
"arrify": {
"version": "1.0.1",
@ -1177,6 +1403,7 @@
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
"integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
"dev": true,
"requires": {
"expand-range": "1.8.2",
"preserve": "0.2.0",
@ -1455,19 +1682,110 @@
"dev": true
},
"chokidar": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
"integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz",
"integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==",
"requires": {
"anymatch": "1.3.2",
"anymatch": "2.0.0",
"async-each": "1.0.1",
"braces": "2.3.2",
"fsevents": "1.1.3",
"glob-parent": "2.0.0",
"glob-parent": "3.1.0",
"inherits": "2.0.3",
"is-binary-path": "1.0.1",
"is-glob": "2.0.1",
"is-glob": "4.0.0",
"normalize-path": "2.1.1",
"path-is-absolute": "1.0.1",
"readdirp": "2.1.0"
"readdirp": "2.1.0",
"upath": "1.0.4"
},
"dependencies": {
"array-unique": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
},
"braces": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
"integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
"requires": {
"arr-flatten": "1.1.0",
"array-unique": "0.3.2",
"extend-shallow": "2.0.1",
"fill-range": "4.0.0",
"isobject": "3.0.1",
"repeat-element": "1.1.2",
"snapdragon": "0.8.2",
"snapdragon-node": "2.1.1",
"split-string": "3.1.0",
"to-regex": "3.0.2"
}
},
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"requires": {
"is-extendable": "0.1.1"
}
},
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
"requires": {
"extend-shallow": "2.0.1",
"is-number": "3.0.0",
"repeat-string": "1.6.1",
"to-regex-range": "2.1.1"
}
},
"glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
"integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
"requires": {
"is-glob": "3.1.0",
"path-dirname": "1.0.2"
},
"dependencies": {
"is-glob": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
"integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
"requires": {
"is-extglob": "2.1.1"
}
}
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"is-glob": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
"integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
"requires": {
"is-extglob": "2.1.1"
}
},
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"requires": {
"kind-of": "3.2.2"
}
},
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
}
}
},
"chownr": {
@ -2138,6 +2456,11 @@
}
}
},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
},
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@ -2677,16 +3000,12 @@
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"eth-lib": {
"version": "0.1.27",
"resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz",
"integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==",
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz",
"integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==",
"requires": {
"bn.js": "4.11.8",
"elliptic": "6.4.0",
"keccakjs": "0.2.1",
"nano-json-stream-parser": "0.1.2",
"servify": "0.1.12",
"ws": "3.3.3",
"xhr-request-promise": "0.1.2"
}
},
@ -2772,6 +3091,7 @@
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
"integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
"dev": true,
"requires": {
"is-posix-bracket": "0.1.1"
}
@ -2780,6 +3100,7 @@
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
"integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
"dev": true,
"requires": {
"fill-range": "2.2.3"
}
@ -2821,20 +3142,6 @@
"vary": "1.1.2"
},
"dependencies": {
"finalhandler": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
"requires": {
"debug": "2.6.9",
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"on-finished": "2.3.0",
"parseurl": "1.3.2",
"statuses": "1.4.0",
"unpipe": "1.0.0"
}
},
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
@ -2886,6 +3193,7 @@
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
"integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
"dev": true,
"requires": {
"is-extglob": "1.0.0"
}
@ -2977,12 +3285,14 @@
"filename-regex": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
"integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY="
"integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
"dev": true
},
"fill-range": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
"integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
"dev": true,
"requires": {
"is-number": "2.1.0",
"isobject": "2.1.0",
@ -3111,6 +3421,7 @@
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
"integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
"dev": true,
"requires": {
"for-in": "1.0.2"
}
@ -4188,6 +4499,7 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
"integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
"dev": true,
"requires": {
"glob-parent": "2.0.0",
"is-glob": "2.0.1"
@ -4202,6 +4514,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
"integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
"dev": true,
"requires": {
"is-glob": "2.0.1"
}
@ -5182,12 +5495,14 @@
"is-dotfile": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
"integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE="
"integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
"dev": true
},
"is-equal-shallow": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
"integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
"dev": true,
"requires": {
"is-primitive": "2.0.0"
}
@ -5200,7 +5515,8 @@
"is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
"integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
"integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
"dev": true
},
"is-finite": {
"version": "1.0.2",
@ -5227,6 +5543,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
"dev": true,
"requires": {
"is-extglob": "1.0.0"
}
@ -5255,6 +5572,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
"integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
"dev": true,
"requires": {
"kind-of": "3.2.2"
}
@ -5326,12 +5644,14 @@
"is-posix-bracket": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
"integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q="
"integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
"dev": true
},
"is-primitive": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
"integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU="
"integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
"dev": true
},
"is-promise": {
"version": "1.0.1",
@ -5396,6 +5716,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
"integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
"dev": true,
"requires": {
"isarray": "1.0.0"
}
@ -6189,6 +6510,7 @@
"version": "2.3.11",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
"integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
"dev": true,
"requires": {
"arr-diff": "2.0.0",
"array-unique": "0.2.1",
@ -6647,7 +6969,6 @@
"version": "1.0.35",
"resolved": "https://registry.npmjs.org/node-webcrypto-ossl/-/node-webcrypto-ossl-1.0.35.tgz",
"integrity": "sha1-FCJVeb0J9dY7CtbO4LqAD4xqBg0=",
"optional": true,
"requires": {
"mkdirp": "0.5.1",
"nan": "2.9.2",
@ -6834,6 +7155,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
"integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
"dev": true,
"requires": {
"for-own": "0.1.5",
"is-extendable": "0.1.1"
@ -7132,6 +7454,7 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
"integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
"dev": true,
"requires": {
"glob-base": "0.3.0",
"is-dotfile": "1.0.3",
@ -7846,7 +8169,8 @@
"preserve": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks="
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
"dev": true
},
"private": {
"version": "0.1.8",
@ -8097,6 +8421,7 @@
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
"integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=",
"dev": true,
"requires": {
"is-number": "3.0.0",
"kind-of": "4.0.0"
@ -8106,6 +8431,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true,
"requires": {
"kind-of": "3.2.2"
},
@ -8114,6 +8440,7 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"requires": {
"is-buffer": "1.1.6"
}
@ -8124,6 +8451,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
"integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
"dev": true,
"requires": {
"is-buffer": "1.1.6"
}
@ -8286,6 +8614,7 @@
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
"integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=",
"dev": true,
"requires": {
"is-equal-shallow": "0.1.3"
}
@ -9589,6 +9918,20 @@
"base64-js": "1.2.3",
"ieee754": "1.1.8"
}
},
"eth-lib": {
"version": "0.1.27",
"resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz",
"integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==",
"requires": {
"bn.js": "4.11.8",
"elliptic": "6.4.0",
"keccakjs": "0.2.1",
"nano-json-stream-parser": "0.1.2",
"servify": "0.1.12",
"ws": "3.3.3",
"xhr-request-promise": "0.1.2"
}
}
}
},
@ -10014,9 +10357,9 @@
}
},
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.0.tgz",
"integrity": "sha512-4IV1DSSxC1QK48j9ONFK1MoIAKKkbE8i7u55w2R6IqBqbT7A/iG7aZBCR2Bi8piF0Uz+i/MG1aeqLwl/5vqF+A=="
},
"underscore.string": {
"version": "3.3.4",
@ -10642,6 +10985,13 @@
"got": "7.1.0",
"swarm-js": "0.1.37",
"underscore": "1.8.3"
},
"dependencies": {
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
"web3-core": {
@ -10663,6 +11013,13 @@
"underscore": "1.8.3",
"web3-eth-iban": "1.0.0-beta.34",
"web3-utils": "1.0.0-beta.34"
},
"dependencies": {
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
"web3-core-method": {
@ -10675,6 +11032,13 @@
"web3-core-promievent": "1.0.0-beta.34",
"web3-core-subscriptions": "1.0.0-beta.34",
"web3-utils": "1.0.0-beta.34"
},
"dependencies": {
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
"web3-core-promievent": {
@ -10696,6 +11060,13 @@
"web3-providers-http": "1.0.0-beta.34",
"web3-providers-ipc": "1.0.0-beta.34",
"web3-providers-ws": "1.0.0-beta.34"
},
"dependencies": {
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
"web3-core-subscriptions": {
@ -10706,6 +11077,13 @@
"eventemitter3": "1.1.1",
"underscore": "1.8.3",
"web3-core-helpers": "1.0.0-beta.34"
},
"dependencies": {
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
"web3-eth": {
@ -10725,6 +11103,13 @@
"web3-eth-personal": "1.0.0-beta.34",
"web3-net": "1.0.0-beta.34",
"web3-utils": "1.0.0-beta.34"
},
"dependencies": {
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
"web3-eth-abi": {
@ -10742,6 +11127,11 @@
"version": "4.11.6",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz",
"integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU="
},
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
@ -10772,6 +11162,11 @@
"xhr-request-promise": "0.1.2"
}
},
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
},
"uuid": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz",
@ -10792,6 +11187,13 @@
"web3-core-subscriptions": "1.0.0-beta.34",
"web3-eth-abi": "1.0.0-beta.34",
"web3-utils": "1.0.0-beta.34"
},
"dependencies": {
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
"web3-eth-iban": {
@ -10849,6 +11251,13 @@
"oboe": "2.1.3",
"underscore": "1.8.3",
"web3-core-helpers": "1.0.0-beta.34"
},
"dependencies": {
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
"web3-providers-ws": {
@ -10859,6 +11268,13 @@
"underscore": "1.8.3",
"web3-core-helpers": "1.0.0-beta.34",
"websocket": "1.0.25"
},
"dependencies": {
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
"web3-shh": {
@ -10890,6 +11306,25 @@
"version": "4.11.6",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz",
"integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU="
},
"eth-lib": {
"version": "0.1.27",
"resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz",
"integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==",
"requires": {
"bn.js": "4.11.6",
"elliptic": "6.4.0",
"keccakjs": "0.2.1",
"nano-json-stream-parser": "0.1.2",
"servify": "0.1.12",
"ws": "3.3.3",
"xhr-request-promise": "0.1.2"
}
},
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
}
}
},
@ -10897,7 +11332,6 @@
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-0.1.19.tgz",
"integrity": "sha1-8CTjoCu8oW3tRtJpaMQlNaORJNw=",
"optional": true,
"requires": {
"tslib": "1.9.0"
}

View File

@ -30,11 +30,13 @@
"babel-preset-es2017": "6.24.1",
"babel-preset-react": "^6.24.1",
"blessed": "^0.1.81",
"chokidar": "^1.6.0",
"chokidar": "^2.0.3",
"colors": "^1.1.2",
"commander": "^2.15.1",
"css-loader": "^0.28.11",
"deep-equal": "^1.0.1",
"ejs": "^2.5.8",
"eth-lib": "^0.2.8",
"ethereumjs-testrpc": "^6.0.3",
"file-loader": "^1.1.5",
"finalhandler": "^1.1.1",
@ -57,7 +59,7 @@
"style-loader": "^0.19.0",
"tar": "^3.1.5",
"toposort": "^1.0.0",
"underscore": "^1.8.3",
"underscore": "^1.9.0",
"underscore.string": "^3.3.4",
"url-loader": "^0.6.2",
"viz.js": "^1.8.1",

View File

@ -9,12 +9,12 @@
"maxpeers": 0,
"rpcHost": "localhost",
"rpcPort": 8545,
"rpcCorsDomain": "http://localhost:8000",
"rpcCorsDomain": "auto",
"account": {
"password": "config/development/password"
},
"targetGasLimit": 8000000,
"wsOrigins": "http://localhost:8000",
"wsOrigins": "auto",
"wsRPC": true,
"wsHost": "localhost",
"wsPort": 8546,

View File

@ -0,0 +1,91 @@
import EmbarkJS from 'Embark/EmbarkJS';
import SimpleStorage from 'Embark/contracts/SimpleStorage';
import React from 'react';
import { Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap';
class Blockchain extends React.Component {
constructor(props) {
super(props);
this.state = {
valueSet: 10,
valueGet: "",
logs: []
}
}
handleChange(e){
this.setState({valueSet: e.target.value});
}
setValue(e){
e.preventDefault();
var value = parseInt(this.state.valueSet, 10);
// If web3.js 1.0 is being used
if (EmbarkJS.isNewWeb3()) {
SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount});
this._addToLog("SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount})");
} else {
SimpleStorage.set(value);
this._addToLog("#blockchain", "SimpleStorage.set(" + value + ")");
}
}
getValue(e){
e.preventDefault();
if (EmbarkJS.isNewWeb3()) {
SimpleStorage.methods.get().call()
.then(_value => this.setState({valueGet: _value}))
this._addToLog("SimpleStorage.methods.get(console.log)");
} else {
SimpleStorage.get()
.then(_value => this.setState({valueGet: _value}));
this._addToLog("SimpleStorage.get()");
}
}
_addToLog(txt){
this.state.logs.push(txt);
this.setState({logs: this.state.logs});
}
render(){
return (<React.Fragment>
<h3> 1. Set the value in the blockchain</h3>
<Form inline>
<FormGroup>
<FormControl
type="text"
defaultValue={this.state.valueSet}
onChange={(e) => this.handleChange(e)} />
<Button bsStyle="primary" onClick={(e) => this.setValue(e)}>Set Value</Button>
<HelpBlock>Once you set the value, the transaction will need to be mined and then the value will be updated on the blockchain.</HelpBlock>
</FormGroup>
</Form>
<h3> 2. Get the current value</h3>
<Form inline>
<FormGroup>
<HelpBlock>current value is <span className="value">{this.state.valueGet}</span></HelpBlock>
<Button bsStyle="primary" onClick={(e) => this.getValue(e)}>Get Value</Button>
<HelpBlock>Click the button to get the current value. The initial value is 100.</HelpBlock>
</FormGroup>
</Form>
<h3> 3. Contract Calls </h3>
<p>Javascript calls being made: </p>
<div className="logs">
{
this.state.logs.map((item, i) => <p key={i}>{item}</p>)
}
</div>
</React.Fragment>
);
}
}
export default Blockchain;

View File

@ -0,0 +1,172 @@
import EmbarkJS from 'Embark/EmbarkJS';
import React from 'react';
import { Alert, Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap';
class Storage extends React.Component {
constructor(props) {
super(props);
this.state = {
textToSave: 'hello world!',
generatedHash: '',
loadText: '',
storedText: '',
fileToUpload: null,
fileHash: '',
imageToDownload: '',
url: '',
logs: [],
storageError: ''
};
}
handleChange(e, name){
this.state[name] = e.target.value;
this.setState(this.state);
}
handleFileUpload(e){
this.setState({ fileToUpload: [e.target] });
}
addToLog(txt){
this.state.logs.push(txt);
this.setState({logs: this.state.logs});
}
setText(e){
e.preventDefault();
EmbarkJS.Storage.saveText(this.state.textToSave)
.then((hash) => {
this.setState({
generatedHash: hash,
loadText: hash,
storageError: ''
});
this.addToLog("EmbarkJS.Storage.saveText('" + this.state.textToSave + "').then(function(hash) { })");
})
.catch((err) => {
if(err){
this.setState({storageError: err.message});
console.log("Storage saveText Error => " + err.message);
}
});
}
loadHash(e){
e.preventDefault();
EmbarkJS.Storage.get(this.state.loadText)
.then((content) => {
this.setState({storedText: content, storageError: ''});
this.addToLog("EmbarkJS.Storage.get('" + this.state.loadText + "').then(function(content) { })");
})
.catch((err) => {
if(err){
this.setState({storageError: err.message})
console.log("Storage get Error => " + err.message);
}
});
}
uploadFile(e){
e.preventDefault();
EmbarkJS.Storage.uploadFile(this.state.fileToUpload)
.then((hash) => {
this.setState({
fileHash: hash,
imageToDownload: hash,
storageError: ''
});
this.addToLog("EmbarkJS.Storage.uploadFile(this.state.fileToUpload).then(function(hash) { })");
})
.catch((err) => {
if(err){
this.setState({storageError: err.message});
console.log("Storage uploadFile Error => " + err.message);
}
});
}
loadFile(e){
let _url = EmbarkJS.Storage.getUrl(this.state.imageToDownload);
this.setState({url: _url})
this.addToLog("EmbarkJS.Storage.getUrl('" + this.state.imageToDownload + "')");
}
render(){
return <React.Fragment>
{
!this.props.enabled ?
<React.Fragment>
<Alert bsStyle="warning">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.</Alert>
</React.Fragment> : ''
}
{
this.state.storageError !== '' ?
<Alert bsStyle="danger">{this.state.storageError}</Alert>
: ''
}
<h3>Save text to storage</h3>
<Form inline>
<FormGroup>
<FormControl
type="text"
defaultValue={this.state.textToSave}
onChange={e => this.handleChange(e, 'textToSave')} />
<Button bsStyle="primary" onClick={(e) => this.setText(e)}>Save Text</Button>
<HelpBlock>generated Hash: <span className="textHash">{this.state.generatedHash}</span></HelpBlock>
</FormGroup>
</Form>
<h3>Load text from storage given an hash</h3>
<Form inline>
<FormGroup>
<FormControl
type="text"
value={this.state.loadText}
onChange={e => this.handleChange(e, 'loadText')} />
<Button bsStyle="primary" onClick={(e) => this.loadHash(e)}>Load</Button>
<HelpBlock>result: <span className="textHash">{this.state.storedText}</span></HelpBlock>
</FormGroup>
</Form>
<h3>Upload file to storage</h3>
<Form inline>
<FormGroup>
<FormControl
type="file"
onChange={(e) => this.handleFileUpload(e)} />
<Button bsStyle="primary" onClick={(e) => this.uploadFile(e)}>Upload</Button>
<HelpBlock>generated hash: <span className="fileHash">{this.state.fileHash}</span></HelpBlock>
</FormGroup>
</Form>
<h3>Get file or image from storage</h3>
<Form inline>
<FormGroup>
<FormControl
type="text"
value={this.state.imageToDownload}
onChange={e => this.handleChange(e, 'imageToDownload')} />
<Button bsStyle="primary" onClick={(e) => this.loadFile(e)}>Download</Button>
<HelpBlock>file available at: <span><a href={this.state.url} target="_blank">{this.state.url}</a></span></HelpBlock>
<HelpBlock><img src={this.state.url} /></HelpBlock>
</FormGroup>
</Form>
<p>Javascript calls being made: </p>
<div className="logs">
<p>EmbarkJS.Storage.setProvider('ipfs',{'{'}server: 'localhost', port: '5001'{'}'})</p>
{
this.state.logs.map((item, i) => <p key={i}>{item}</p>)
}
</div>
</React.Fragment>;
}
}
export default Storage;

View File

@ -0,0 +1,105 @@
import EmbarkJS from 'Embark/EmbarkJS';
import React from 'react';
import { Alert, Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap';
class Whisper extends React.Component {
constructor(props) {
super(props);
this.state = {
listenTo: '',
channel: '',
message: '',
subscribedChannels: [],
messageList: [],
logs: []
}
}
handleChange(e, name){
this.state[name] = e.target.value;
this.setState(this.state);
}
sendMessage(e){
e.preventDefault();
EmbarkJS.Messages.sendMessage({topic: this.state.channel, data: this.state.message});
this.addToLog("EmbarkJS.Messages.sendMessage({topic: '" + this.state.channel + "', data: '" + this.state.message + "'})");
}
listenToChannel(e){
e.preventDefault();
this.state.subscribedChannels.push(`subscribed to ${this.state.listenTo} now try sending a message`);
EmbarkJS.Messages.listenTo({topic: [this.state.listenTo]})
.then(message => this.state.messageList.push(`channel: ${this.state.listenTo} message: ${message}`))
this.addToLog("EmbarkJS.Messages.listenTo({topic: ['" + this.state.listenTo + "']}).then(function(message) {})");
}
addToLog(txt){
this.state.logs.push(txt);
this.setState({logs: this.state.logs});
}
render(){
return (
<React.Fragment>
{
!this.props.enabled ?
<React.Fragment>
<Alert bsStyle="warning">The node you are using does not support Whisper</Alert>
<Alert bsStyle="warning">The node uses an unsupported version of Whisper</Alert>
</React.Fragment> : ''
}
<h3>Listen To channel</h3>
<Form inline>
<FormGroup>
<FormControl
type="text"
defaultValue={this.state.listenTo}
placeholder="channel"
onChange={e => this.handleChange(e, 'listenTo')} />
<Button bsStyle="primary" onClick={(e) => this.listenToChannel(e)}>Start Listening</Button>
<div id="subscribeList">
{ this.state.subscribedChannels.map((item, i) => <p key={i}>{item}</p>) }
</div>
<p>messages received:</p>
<div id="messagesList">
{ this.state.messageList.map((item, i) => <p key={i}>{item}</p>) }
</div>
</FormGroup>
</Form>
<h3>Send Message</h3>
<Form inline>
<FormGroup>
<FormControl
type="text"
defaultValue={this.state.channel}
placeholder="channel"
onChange={e => this.handleChange(e, 'channel')} />
<FormControl
type="text"
defaultValue={this.state.message}
placeholder="message"
onChange={e => this.handleChange(e, 'message')} />
<Button bsStyle="primary" onClick={(e) => this.sendMessage(e)}>Send Message</Button>
</FormGroup>
</Form>
<p>Javascript calls being made: </p>
<div className="logs">
<p>EmbarkJS.Messages.setProvider('whisper')</p>
{
this.state.logs.map((item, i) => <p key={i}>{item}</p>)
}
</div>
</React.Fragment>
);
}
}
export default Whisper;

View File

@ -47,3 +47,7 @@ div {
-webkit-border-radius: 10px;
border-radius: 10px;
}
input.form-control {
margin-right: 5px;
}

View File

@ -1,161 +1,75 @@
/*globals $, SimpleStorage, document*/
import React from 'react';
import ReactDOM from 'react-dom';
import { Tabs, Tab } from 'react-bootstrap';
import $ from 'jquery';
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import EmbarkJS from 'Embark/EmbarkJS';
import SimpleStorage from 'Embark/contracts/SimpleStorage';
import Blockchain from './components/blockchain';
import Whisper from './components/whisper';
import Storage from './components/storage';
import './dapp.css';
var addToLog = function(id, txt) {
$(id + " .logs").append("<br>" + txt);
};
class App extends React.Component {
// ===========================
// Blockchain example
// ===========================
$(document).ready(function() {
constructor(props) {
super(props);
$("#blockchain button.set").click(function() {
var value = parseInt($("#blockchain input.text").val(), 10);
// 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 + ")");
this.state = {
whisperEnabled: false,
storageEnabled: false
}
}
});
$("#blockchain button.get").click(function() {
// 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()");
}
});
});
// ===========================
// 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.ipfsConnection.version()
// .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();
// }
// });
$("#storage button.setIpfsText").click(function() {
var value = $("#storage input.ipfsText").val();
EmbarkJS.Storage.saveText(value).then(function(hash) {
$("span.textHash").html(hash);
$("input.textHash").val(hash);
addToLog("#storage", "EmbarkJS.Storage.saveText('" + value + "').then(function(hash) { })");
})
.catch(function(err) {
if(err){
console.log("IPFS saveText Error => " + err.message);
}
});
});
$("#storage button.loadIpfsHash").click(function() {
var value = $("#storage input.textHash").val();
EmbarkJS.Storage.get(value).then(function(content) {
$("span.ipfsText").html(content);
addToLog("#storage", "EmbarkJS.Storage.get('" + value + "').then(function(content) { })");
})
.catch(function(err) {
if(err){
console.log("IPFS get Error => " + err.message);
}
});
});
$("#storage button.uploadFile").click(function() {
var input = $("#storage input[type=file]");
EmbarkJS.Storage.uploadFile(input).then(function(hash) {
$("span.fileIpfsHash").html(hash);
$("input.fileIpfsHash").val(hash);
addToLog("#storage", "EmbarkJS.Storage.uploadFile($('input[type=file]')).then(function(hash) { })");
})
.catch(function(err) {
if(err){
console.log("IPFS uploadFile Error => " + err.message);
}
});
});
$("#storage button.loadIpfsFile").click(function() {
var hash = $("#storage input.fileIpfsHash").val();
var url = EmbarkJS.Storage.getUrl(hash);
var link = '<a href="' + url + '" target="_blank">' + url + '</a>';
$("span.ipfsFileUrl").html(link);
$(".ipfsImage").attr('src', url);
addToLog("#storage", "EmbarkJS.Storage.getUrl('" + hash + "')");
});
});
// ===========================
// Communication (Whisper) example
// ===========================
$(document).ready(function() {
$("#communication .error").hide();
$("#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');
componentDidMount(){
__embarkContext.execWhenReady(() => {
if (EmbarkJS.isNewWeb3()) {
EmbarkJS.Messages.Providers.whisper.getWhisperVersion((err, version) => {
if(!err)
this.setState({whisperEnabled: true})
else
console.log(err);
});
} else {
EmbarkJS.Messages.setProvider('whisper');
$("#status-communication").addClass('status-online');
if (EmbarkJS.Messages.providerName === 'whisper') {
EmbarkJS.Messages.getWhisperVersion((err, version) => {
if(!err)
this.setState({whisperEnabled: true})
else
console.log(err);
});
}
}
this.setState({
storageEnabled: true
});
});
}
$("#communication button.listenToChannel").click(function() {
var channel = $("#communication .listen input.channel").val();
$("#communication #subscribeList").append("<br> subscribed to " + channel + " now try sending a message");
EmbarkJS.Messages.listenTo({topic: [channel]}).then(function(message) {
$("#communication #messagesList").append("<br> channel: " + channel + " message: " + message);
});
addToLog("#communication", "EmbarkJS.Messages.listenTo({topic: ['" + channel + "']}).then(function(message) {})");
});
$("#communication button.sendMessage").click(function() {
var channel = $("#communication .send input.channel").val();
var message = $("#communication .send input.message").val();
EmbarkJS.Messages.sendMessage({topic: channel, data: message});
addToLog("#communication", "EmbarkJS.Messages.sendMessage({topic: '" + channel + "', data: '" + message + "'})");
});
_renderStatus(title, available){
let className = available ? 'pull-right status-online' : 'pull-right status-offline';
return <React.Fragment>
{title}
<span className={className}></span>
</React.Fragment>;
}
});
render(){
return (<div><h3>Embark - Usage Example</h3>
<Tabs defaultActiveKey={1} id="uncontrolled-tab-example">
<Tab eventKey={1} title="Blockchain">
<Blockchain />
</Tab>
<Tab eventKey={2} title={this._renderStatus('Decentralized Storage', this.state.storageEnabled)}>
<Storage enabled={this.state.storageEnabled} />
</Tab>
<Tab eventKey={3} title={this._renderStatus('P2P communication (Whisper/Orbit)', this.state.whisperEnabled)}>
<Whisper enabled={this.state.whisperEnabled} />
</Tab>
</Tabs>
</div>);
}
}
ReactDOM.render(<App></App>, document.getElementById('app'));

View File

@ -1,107 +1,12 @@
<html>
<head>
<title>Embark - SimpleStorage Demo</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js"></script>
<script src="js/dapp.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body class="container">
<h3>Embark - Usage Example</h3>
<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)<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">
<div role="tabpanel" class="tab-pane active" id="blockchain">
<h3> 1. Set the value in the blockchain</h3>
<div class="form-group form-inline">
<input type="text" class="text form-control" value="10">
<button class="set btn btn-primary">Set Value</button>
<p>Once you set the value, the transaction will need to be mined and then the value will be updated on the blockchain.</p>
</div>
<h3> 2. Get the current value</h3>
<div class="form-group">
<div>
current value is <span class="value"></span>
</div>
<button class="get btn btn-primary">Get Value</button>
<p>Click the button to get the current value. The initial value is 100.</p>
</div>
<h3> 3. Contract Calls </h3>
<p>Javascript calls being made: </p>
<div class="logs">
</div>
<div id="app">
</div>
<div role="tabpanel" class="tab-pane" id="storage">
<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">
<input type="text" class="ipfsText text form-control" value="hello world!">
<button class="setIpfsText btn btn-primary">Save</button>
<p>generated Hash: <span class="textHash"></span></p>
</div>
<h3>Load text from IPFS given an hash</h3>
<div class="form-group form-inline">
<input type="text" class="textHash text form-control" size="60">
<button class="loadIpfsHash set btn btn-primary">Load</button>
<p>result: <span class="ipfsText"></span></p>
</div>
<h3>upload file to ipfs</h3>
<div class="form-group form-inline">
<input type="file" class="form-control">
<button class="uploadFile set btn btn-primary">upload</button>
<p>generated hash: <span class="fileIpfsHash"></span></p>
</div>
<h3>Get file or image from ipfs</h3>
<div class="form-group form-inline">
<input type="text" class="fileIpfsHash form-control" size="60">
<button class="loadIpfsFile set btn btn-primary">Load</button>
<p>file available at: <span class="ipfsFileUrl"></span></p>
<p><img class="ipfsImage" src=""></p>
</div>
<p>Javascript calls being made: </p>
<div class="logs">
<br> EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'})
</div>
</div>
</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">
<input type="text" class="channel text form-control" placeholder="channel">
<button class="listenToChannel set btn btn-primary">Start Listening</button>
<div id="subscribeList"></div>
<p>messages received:<p>
<div id="messagesList"></div>
</div>
<h3>Send Message</h3>
<div class="form-group form-inline send">
<input type="text" class="channel text form-control" placeholder="channel">
<input type="text" class="message text form-control" placeholder="message">
<button class="sendMessage set btn btn-primary">Send Message</button>
</div>
<p>Javascript calls being made: </p>
<div class="logs">
<br> EmbarkJS.Messages.setProvider('whisper')
</div>
</div>
</div>
</div>
<script src="js/dapp.js"></script>
</body>
</html>

View File

@ -9,12 +9,12 @@
"maxpeers": 0,
"rpcHost": "localhost",
"rpcPort": 8545,
"rpcCorsDomain": "http://localhost:8000",
"rpcCorsDomain": "auto",
"account": {
"password": "config/development/password"
},
"targetGasLimit": 8000000,
"wsOrigins": "http://localhost:8000",
"wsOrigins": "auto",
"wsRPC": true,
"wsHost": "localhost",
"wsPort": 8546,

View File

@ -9,8 +9,9 @@
"author": "",
"license": "ISC",
"homepage": "",
"devDependencies": {
"bootstrap": "^3.3.6",
"jquery": "^1.11.3"
"dependencies": {
"react": "^16.3.2",
"react-bootstrap": "^0.32.1",
"react-dom": "^16.3.2"
}
}

View File

@ -3,11 +3,13 @@ const Config = require('../lib/core/config.js');
const Plugins = require('../lib/core/plugins.js');
const assert = require('assert');
const TestLogger = require('../lib/tests/test_logger.js');
const Events = require('../lib/core/events');
describe('embark.Config', function () {
let config = new Config({
env: 'myenv',
configDir: './test/test1/config/'
configDir: './test/test1/config/',
events: new Events()
});
config.plugins = new Plugins({plugins: {}});
config.logger = new TestLogger({});

View File

@ -3,6 +3,7 @@ let ContractsManager = require('../lib/contracts/contracts.js');
let Logger = require('../lib/core/logger.js');
let File = require('../lib/core/file.js');
let TestLogger = require('../lib/tests/test_logger.js');
let Events = require('../lib/core/events');
let assert = require('assert');
//let SolidityCompiler = require('../lib/modules/solidity');
@ -55,7 +56,8 @@ describe('embark.Contracts', function() {
}
}
},
logger: new Logger({})
logger: new Logger({}),
events: new Events()
});
describe('#build', function() {
@ -146,7 +148,8 @@ describe('embark.Contracts', function() {
}
}
},
logger: new Logger({})
logger: new Logger({}),
events: new Events()
});
describe('#build', function() {

View File

@ -9,12 +9,12 @@
"maxpeers": 0,
"rpcHost": "localhost",
"rpcPort": 8545,
"rpcCorsDomain": "http://localhost:8000",
"rpcCorsDomain": "auto",
"account": {
"password": "development/password"
},
"targetGasLimit": 8000000,
"wsOrigins": "http://localhost:8000",
"wsOrigins": "auto",
"wsRPC": true,
"wsHost": "localhost",
"wsPort": 8546

View File

@ -9,12 +9,12 @@
"maxpeers": 0,
"rpcHost": "localhost",
"rpcPort": 8545,
"rpcCorsDomain": "http://localhost:8000",
"rpcCorsDomain": "auto",
"account": {
"password": "config/development/password"
},
"targetGasLimit": 8000000,
"wsOrigins": "http://localhost:8000",
"wsOrigins": "auto",
"wsRPC": true,
"wsHost": "localhost",
"wsPort": 8546

View File

@ -1,7 +1,7 @@
{
"default": {
"enabled": true,
"available_providers": ["ipfs"],
"available_providers": ["ipfs", "swarm"],
"ipfs_bin": "ipfs",
"provider": "ipfs",
"host": "localhost",
@ -9,10 +9,10 @@
},
"development": {
"enabled": true,
"provider": "ipfs",
"host": "localhost",
"port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
"provider": "swarm",
"host": "swarm-gateways.net",
"port": 80,
"getUrl": "http://swarm-gateways.net/bzzr:/"
},
"livenet": {
"enabled": true,

View File

@ -0,0 +1,10 @@
pragma solidity ^0.4.18;
contract PluginStorage {
address public simpleStorageAddress;
address simpleStorageAddress2;
function PluginStorage(address addr) public {
simpleStorageAddress = addr;
}
}

View File

@ -0,0 +1 @@
console.log('File added to the pipeline using embark.addFileToPipeline');

View File

@ -1,12 +1,47 @@
var Haml = require('haml');
const Haml = require('haml');
module.exports = function(embark) {
embark.registerServiceCheck('PluginService', function(cb) {
module.exports = function (embark) {
embark.registerServiceCheck('PluginService', function (cb) {
cb({name: "ServiceName", status: "on"});
});
embark.registerPipeline((embark.pluginConfig.files || ['**/*.haml']), function(opts) {
var source = opts.source;
return Haml.render(source);
embark.registerPipeline((embark.pluginConfig.files || ['**/*.haml']), function (opts) {
return Haml.render(opts.source);
});
embark.registerContractConfiguration({
"default": {
"contracts": {
"PluginStorage": {
"args": ["$SimpleStorage"]
}
}
}
});
embark.addContractFile("./contracts/pluginSimpleStorage.sol");
embark.addFileToPipeline('./fileInPipeline.js');
embark.addFileToPipeline('./fileInPipeline.js', 'js/fileInPipeline.js');
embark.registerBeforeDeploy(function (options, callback) {
// Just calling register to prove it works. We don't actually want to change the contracts
callback({contractCode: options.contract.code});
});
embark.registerClientWeb3Provider(function(options) {
return "web3 = new Web3(new Web3.providers.HttpProvider('http://" + options.rpcHost + ":" + options.rpcPort + "'));";
});
embark.registerConsoleCommand((cmd) => {
if (cmd === "hello") {
return "hello there!";
}
// continue to embark or next plugin;
return false;
});
embark.events.on("contractsDeployed", function() {
embark.logger.info("plugin says: your contracts have been deployed");
});
};

View File

@ -14,11 +14,11 @@
},
"dependencies": {
"bootstrap": "^3.3.6",
"embark-service": "./extensions/embark-service",
"embark-service": "file:extensions/embark-service",
"jquery": "^1.11.3",
"react": "^16.0.0",
"react-bootstrap": "^0.32.0",
"react-dom": "^16.2.0",
"zeppelin-solidity": "^1.8.0"
"zeppelin-solidity": "1.8.0"
}
}

View File

@ -0,0 +1,26 @@
/*global contract, before, EmbarkSpec, PluginStorage, SimpleStorage, it*/
const assert = require('assert');
contract("PluginSimpleStorage", function () {
this.timeout(0);
before((done) => {
const contractsConfig = {
"SimpleStorage": {
args: [100]
},
"PluginStorage": {
args: ["$SimpleStorage"]
}
};
EmbarkSpec.deployAll(contractsConfig, () => {
done();
});
});
it("set SimpleStorage address", async function () {
let result = await PluginStorage.methods.simpleStorageAddress().call();
assert.equal(result.toString(), SimpleStorage.options.address);
});
});

View File

@ -13,8 +13,6 @@ describe("Token", function() {
var contractsConfig = {
"ZAMyLib": {
},
"Token": {
},
"SimpleStorage": {
args: [100]
},