mirror of https://github.com/embarklabs/embark.git
Add for loops and variable declarations; Coverage improvements
This commit is contained in:
parent
782e7b04e8
commit
5dcd679e12
|
@ -1,3 +1,5 @@
|
||||||
|
const util = require('util');
|
||||||
|
|
||||||
const SourceMap = require('./source_map');
|
const SourceMap = require('./source_map');
|
||||||
|
|
||||||
class ContractSource {
|
class ContractSource {
|
||||||
|
@ -68,18 +70,29 @@ class ContractSource {
|
||||||
var bytecodeIdx = 0;
|
var bytecodeIdx = 0;
|
||||||
var pc = 0;
|
var pc = 0;
|
||||||
var instructions = 0;
|
var instructions = 0;
|
||||||
|
var previousSourceMap = null;
|
||||||
do {
|
do {
|
||||||
|
let sourceMap;
|
||||||
|
|
||||||
|
if(previousSourceMap === null) {
|
||||||
|
sourceMap = new SourceMap(sourceMaps[instructions]);
|
||||||
|
} else {
|
||||||
|
sourceMap = previousSourceMap.createRelativeTo(sourceMaps[instructions]);
|
||||||
|
}
|
||||||
|
|
||||||
var instruction = opcodes[bytecodeIdx];
|
var instruction = opcodes[bytecodeIdx];
|
||||||
var length = this._instructionLength(instruction);
|
var length = this._instructionLength(instruction);
|
||||||
bytecodeMapping[pc] = {
|
bytecodeMapping[pc] = {
|
||||||
instruction: instruction,
|
instruction: instruction,
|
||||||
sourceMap: sourceMaps[instructions],
|
sourceMap: sourceMap,
|
||||||
|
jump: sourceMap.jump,
|
||||||
seen: false
|
seen: false
|
||||||
};
|
};
|
||||||
|
|
||||||
pc += length;
|
pc += length;
|
||||||
instructions++;
|
instructions++;
|
||||||
bytecodeIdx += (length > 1) ? 2 : 1;
|
bytecodeIdx += (length > 1) ? 2 : 1;
|
||||||
|
previousSourceMap = sourceMap;
|
||||||
} while(bytecodeIdx < opcodes.length);
|
} while(bytecodeIdx < opcodes.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +102,7 @@ class ContractSource {
|
||||||
if(!this.ast || !this.contractBytecode) throw new Error('Error generating coverage: solc output was not assigned');
|
if(!this.ast || !this.contractBytecode) throw new Error('Error generating coverage: solc output was not assigned');
|
||||||
|
|
||||||
var coverage = {
|
var coverage = {
|
||||||
code: this.body.split("\n"),
|
code: this.body.trim().split("\n"),
|
||||||
l: {},
|
l: {},
|
||||||
path: this.file,
|
path: this.file,
|
||||||
s: {},
|
s: {},
|
||||||
|
@ -111,10 +124,10 @@ class ContractSource {
|
||||||
var markLocations = [];
|
var markLocations = [];
|
||||||
|
|
||||||
switch(node.nodeType) {
|
switch(node.nodeType) {
|
||||||
case 'Identifier':
|
case 'Assignment':
|
||||||
case 'Literal':
|
case 'Literal':
|
||||||
case 'VariableDeclaration':
|
|
||||||
case 'PragmaDirective':
|
case 'PragmaDirective':
|
||||||
|
case 'VariableDeclaration':
|
||||||
// We don't need to do anything with these. Just carry on.
|
// We don't need to do anything with these. Just carry on.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -166,8 +179,9 @@ class ContractSource {
|
||||||
node.src = node.expression.src;
|
node.src = node.expression.src;
|
||||||
// falls through
|
// falls through
|
||||||
|
|
||||||
case 'Assignment':
|
|
||||||
case 'ExpressionStatement':
|
case 'ExpressionStatement':
|
||||||
|
case 'Identifier':
|
||||||
|
case 'UnaryOperation':
|
||||||
coverage.s[node.id] = 0;
|
coverage.s[node.id] = 0;
|
||||||
|
|
||||||
location = this.sourceMapToLocations(node.src);
|
location = this.sourceMapToLocations(node.src);
|
||||||
|
@ -219,8 +233,43 @@ class ContractSource {
|
||||||
markLocations = [location];
|
markLocations = [location];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'ForStatement':
|
||||||
|
// For statements will be a bit of a special case. We want to count the body
|
||||||
|
// iterations but we only want to count the for loop being hit once. Because
|
||||||
|
// of this, we cover the initialization on the node.
|
||||||
|
let sourceMap = new SourceMap(node.src);
|
||||||
|
let bodySourceMap = new SourceMap(node.body.src);
|
||||||
|
let forLoopDeclaration = sourceMap.subtract(bodySourceMap).toString();
|
||||||
|
let initializationLocation = this.sourceMapToLocations(node.initializationExpression.src);
|
||||||
|
|
||||||
|
location = this.sourceMapToLocations(forLoopDeclaration);
|
||||||
|
|
||||||
|
coverage.s[node.id] = 0;
|
||||||
|
coverage.statementMap[node.id] = location;
|
||||||
|
|
||||||
|
if(!sourceMapToNodeType[node.initializationExpression.src]) sourceMapToNodeType[node.initializationExpression.src] = [];
|
||||||
|
sourceMapToNodeType[node.initializationExpression.src].push({type: 's', id: node.id, body: {loc: location}});
|
||||||
|
|
||||||
|
console.dir(node);
|
||||||
|
|
||||||
|
children = node.body.statements;
|
||||||
|
markLocations = [initializationLocation];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'VariableDeclarationStatement':
|
||||||
|
location = this.sourceMapToLocations(node.src);
|
||||||
|
|
||||||
|
coverage.s[node.id] = 0;
|
||||||
|
coverage.statementMap[node.id] = location;
|
||||||
|
markLocations = [location];
|
||||||
|
|
||||||
|
if(!sourceMapToNodeType[node.src]) sourceMapToNodeType[node.src] = [];
|
||||||
|
sourceMapToNodeType[node.src].push({type: 's', id: node.id, body: {loc: location}, foo: 'bar'});
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// console.log(`Don't know how to handle node type ${node.nodeType}`);
|
console.log(`Don't know how to handle node type ${node.nodeType}`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,23 +292,26 @@ class ContractSource {
|
||||||
contractMatches = trace.structLogs.every((step) => { return bytecode[step.pc]; });
|
contractMatches = trace.structLogs.every((step) => { return bytecode[step.pc]; });
|
||||||
if(!contractMatches) break;
|
if(!contractMatches) break;
|
||||||
|
|
||||||
|
console.log(sourceMapToNodeType);
|
||||||
|
|
||||||
trace.structLogs.forEach((step) => {
|
trace.structLogs.forEach((step) => {
|
||||||
step = bytecode[step.pc];
|
step = bytecode[step.pc];
|
||||||
if(!step.sourceMap || step.sourceMap == '') return;
|
if(!step.sourceMap || step.sourceMap == '') return;
|
||||||
|
|
||||||
var nodes = sourceMapToNodeType[step.sourceMap];
|
let sourceMapString = step.sourceMap.toString(this.id);
|
||||||
|
var nodes = sourceMapToNodeType[sourceMapString];
|
||||||
|
|
||||||
|
if(step.sourceMap.offset == 189) console.log(nodes);
|
||||||
if(!nodes) return;
|
if(!nodes) return;
|
||||||
|
|
||||||
var recordedLineHit = false;
|
|
||||||
|
|
||||||
nodes.forEach((node) => {
|
nodes.forEach((node) => {
|
||||||
if(node.body && node.body.loc && !recordedLineHit) {
|
// Skip duplicate function reports by only reporting when there is a jump.
|
||||||
|
if(node.type == 'f' && step.jump) return;
|
||||||
|
|
||||||
|
if(node.body && node.body.loc) {
|
||||||
for(var line = node.body.loc.start.line; line <= node.body.loc.end.line; line++) {
|
for(var line = node.body.loc.start.line; line <= node.body.loc.end.line; line++) {
|
||||||
coverage.l[line]++;
|
coverage.l[line]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
recordedLineHit = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node.type != 'b') coverage[node.type][node.id]++;
|
if(node.type != 'b') coverage[node.type][node.id]++;
|
||||||
|
|
|
@ -10,6 +10,7 @@ web3.extend({
|
||||||
methods: [{name: 'traceTransaction', call: 'debug_traceTransaction', params: 2}]
|
methods: [{name: 'traceTransaction', call: 'debug_traceTransaction', params: 2}]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
class CodeCoverage {
|
class CodeCoverage {
|
||||||
constructor(embark, _options) {
|
constructor(embark, _options) {
|
||||||
this.events = embark.events;
|
this.events = embark.events;
|
||||||
|
@ -21,6 +22,7 @@ class CodeCoverage {
|
||||||
embark.events.on('block:header', this.runSolc.bind(this));
|
embark.events.on('block:header', this.runSolc.bind(this));
|
||||||
|
|
||||||
this.seenTransactions = {};
|
this.seenTransactions = {};
|
||||||
|
this.coverageReport = {};
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,64 @@
|
||||||
|
class EmptySourceMap {
|
||||||
|
static createRelativeTo(sourceMapString) {
|
||||||
|
if(sourceMapString == '') return EmptySourceMap;
|
||||||
|
|
||||||
|
return new SourceMap(sourceMapString);
|
||||||
|
}
|
||||||
|
|
||||||
|
static toString() {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SourceMap {
|
class SourceMap {
|
||||||
constructor(sourceMapStringOrOffset, length, id) {
|
constructor(sourceMapStringOrOffset, length, id, jump) {
|
||||||
if(typeof sourceMapStringOrOffset == 'string') {
|
if(typeof sourceMapStringOrOffset == 'string') {
|
||||||
let [offset, length, id, ..._rest] = sourceMapStringOrOffset.split(":");
|
let [offset, length, id, jump] = sourceMapStringOrOffset.split(":");
|
||||||
|
|
||||||
this.offset = parseInt(offset, 10);
|
this.offset = parseInt(offset, 10);
|
||||||
this.length = parseInt(length, 10);
|
this.length = parseInt(length, 10);
|
||||||
|
|
||||||
if(id) this.id = parseInt(id, 10);
|
if(id) this.id = parseInt(id, 10);
|
||||||
|
this.jump = jump;
|
||||||
} else {
|
} else {
|
||||||
this.offset = sourceMapStringOrOffset;
|
this.offset = sourceMapStringOrOffset;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.jump = jump;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createRelativeTo(sourceMapString) {
|
||||||
|
if(sourceMapString == '' || sourceMapString == undefined) return EmptySourceMap;
|
||||||
|
|
||||||
|
let [offset, length, id, jump] = sourceMapString.split(":");
|
||||||
|
|
||||||
|
(offset == '') ? offset = this.offset : offset = parseInt(offset, 10);
|
||||||
|
(id == '' || id == undefined) ? id = this.id : id = parseInt(id, 10);
|
||||||
|
length = parseInt(length, 10);
|
||||||
|
|
||||||
|
return new SourceMap(offset, length, id, jump);
|
||||||
|
}
|
||||||
|
|
||||||
subtract(sourceMap) {
|
subtract(sourceMap) {
|
||||||
return new SourceMap(this.offset, sourceMap.offset - this.offset);
|
return new SourceMap(this.offset, sourceMap.offset - this.offset, this.id, this.jump);
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString(defaultId) {
|
||||||
var parts = [this.offset, this.length];
|
let parts = [this.offset, this.length];
|
||||||
if(this.id) parts.push(this.id);
|
|
||||||
|
if(this.id !== undefined && this.id != '') {
|
||||||
|
parts.push(this.id)
|
||||||
|
} else if(defaultId !== undefined) {
|
||||||
|
parts.push(defaultId);
|
||||||
|
}
|
||||||
|
|
||||||
return parts.join(':');
|
return parts.join(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static empty() {
|
||||||
|
return EmptySourceMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = SourceMap;
|
module.exports = SourceMap;
|
||||||
|
|
|
@ -112,7 +112,6 @@ class Test {
|
||||||
compileOnceOnly: true
|
compileOnceOnly: true
|
||||||
});
|
});
|
||||||
this.events.request('deploy:setGasLimit', 6000000);
|
this.events.request('deploy:setGasLimit', 6000000);
|
||||||
this.engine.startService("codeCoverage");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init(callback) {
|
init(callback) {
|
||||||
|
@ -139,6 +138,7 @@ class Test {
|
||||||
this.engine.startService("codeRunner");
|
this.engine.startService("codeRunner");
|
||||||
this.initDeployServices();
|
this.initDeployServices();
|
||||||
this.engine.startService("codeGenerator");
|
this.engine.startService("codeGenerator");
|
||||||
|
this.engine.startService("codeCoverage");
|
||||||
|
|
||||||
if (this.options.node === 'embark') {
|
if (this.options.node === 'embark') {
|
||||||
return this.engine.ipc.connect((err) => {
|
return this.engine.ipc.connect((err) => {
|
||||||
|
|
|
@ -162,10 +162,10 @@ contract x {
|
||||||
|
|
||||||
var bytecode = contractSource.contractBytecode['x'];
|
var bytecode = contractSource.contractBytecode['x'];
|
||||||
|
|
||||||
assert.deepEqual({instruction: 'PUSH1', sourceMap: '26:487:0:-', seen: false}, bytecode[0]);
|
assert.deepEqual({instruction: 'PUSH1', sourceMap: {offset: 26, length: 487, id: 0}, seen: false}, bytecode[0]);
|
||||||
assert.deepEqual({instruction: 'PUSH1', sourceMap: '', seen: false}, bytecode[2]);
|
assert.deepEqual({instruction: 'PUSH1', sourceMap: SourceMap.empty(), seen: false}, bytecode[2]);
|
||||||
assert.deepEqual({instruction: 'MSTORE', sourceMap: '', seen: false}, bytecode[4]);
|
assert.deepEqual({instruction: 'MSTORE', sourceMap: SourceMap.empty(), seen: false}, bytecode[4]);
|
||||||
assert.deepEqual({instruction: 'PUSH1', sourceMap: '', seen: false}, bytecode[5]);
|
assert.deepEqual({instruction: 'PUSH1', sourceMap: SourceMap.empty(), seen: false}, bytecode[5]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -193,6 +193,7 @@ contract x {
|
||||||
|
|
||||||
var trace = JSON.parse(loadFixture('geth-debugtrace-output-h-5.json'));
|
var trace = JSON.parse(loadFixture('geth-debugtrace-output-h-5.json'));
|
||||||
var coverage = cs.generateCodeCoverage(trace);
|
var coverage = cs.generateCodeCoverage(trace);
|
||||||
|
assert.exists(coverage);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -213,7 +214,7 @@ contract x {
|
||||||
// In the fixture, the branch has an ID of 61, and the function has the
|
// In the fixture, the branch has an ID of 61, and the function has the
|
||||||
// ID of 63
|
// ID of 63
|
||||||
assert.deepEqual([1,1], coverage.b['61']);
|
assert.deepEqual([1,1], coverage.b['61']);
|
||||||
assert.equal(2, coverage.f['63']);
|
assert.equal(4, coverage.f['63']);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -234,4 +235,26 @@ describe('SourceMap', () => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#createRelativeTo', () => {
|
||||||
|
it('should return an empty source map on an empty string', (done) => {
|
||||||
|
var sm1 = new SourceMap('192:10:0');
|
||||||
|
var sm2 = sm1.createRelativeTo('');
|
||||||
|
|
||||||
|
assert.equal('', sm2.toString());
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the correct source map on a relative string', (done) => {
|
||||||
|
var sm1 = new SourceMap('192:10:0');
|
||||||
|
var sm2 = sm1.createRelativeTo(':14');
|
||||||
|
|
||||||
|
assert.equal(192, sm2.offset);
|
||||||
|
assert.equal(14, sm2.length);
|
||||||
|
assert.equal(0, sm2.id);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
.embark/
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
config/production/password
|
||||||
|
config/livenet/password
|
||||||
|
coverage/
|
|
@ -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;
|
|
@ -0,0 +1,172 @@
|
||||||
|
/*global web3*/
|
||||||
|
import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
|
import React from 'react';
|
||||||
|
import { Alert, Form, FormGroup, FormControl, Button } from 'react-bootstrap';
|
||||||
|
|
||||||
|
window.EmbarkJS = EmbarkJS;
|
||||||
|
|
||||||
|
class ENS extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
valueResolve: 'embark.eth',
|
||||||
|
responseResolve: null,
|
||||||
|
isResolveError: false,
|
||||||
|
valueLookup: '',
|
||||||
|
responseLookup: null,
|
||||||
|
isLookupError: false,
|
||||||
|
valueRegister: '',
|
||||||
|
addressRegister: '',
|
||||||
|
responseRegister: null,
|
||||||
|
isRegisterError: false,
|
||||||
|
embarkLogs: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
EmbarkJS.onReady(() => {
|
||||||
|
if (!web3.eth.defaultAccount) {
|
||||||
|
this.setState({
|
||||||
|
globalError: 'There is currently no default account. If Metamask is active, please sign in or deactivate it.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
addressRegister: web3.eth.defaultAccount,
|
||||||
|
valueLookup: web3.eth.defaultAccount
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange(stateName, e) {
|
||||||
|
this.setState({ [stateName]: e.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
registerSubDomain(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const self = this;
|
||||||
|
const embarkLogs = this.state.embarkLogs;
|
||||||
|
embarkLogs.push(`EmbarkJS.Names.registerSubDomain('${this.state.valueRegister}', '${this.state.addressRegister}', console.log)`);
|
||||||
|
this.setState({
|
||||||
|
embarkLogs: embarkLogs
|
||||||
|
});
|
||||||
|
|
||||||
|
EmbarkJS.Names.registerSubDomain(this.state.valueRegister, this.state.addressRegister, (err, transaction) => {
|
||||||
|
const message = err ? err : `Successfully registered "${this.state.valueRegister}" with ${transaction.gasUsed} gas`;
|
||||||
|
self.setState({
|
||||||
|
responseRegister: message,
|
||||||
|
isRegisterError: !!err
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveName(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const embarkLogs = this.state.embarkLogs;
|
||||||
|
embarkLogs.push(`EmbarkJS.Names.resolve('${this.state.valueResolve}', console.log)`);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
embarkLogs: embarkLogs
|
||||||
|
});
|
||||||
|
EmbarkJS.Names.resolve(this.state.valueResolve, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
return this.setState({
|
||||||
|
responseResolve: err.message || err,
|
||||||
|
isResolveError: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
responseResolve: result,
|
||||||
|
isResolveError: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
lookupAddress(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const embarkLogs = this.state.embarkLogs;
|
||||||
|
embarkLogs.push(`EmbarkJS.Names.resolve('${this.state.valueLookup}', console.log)`);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
embarkLogs: embarkLogs
|
||||||
|
});
|
||||||
|
EmbarkJS.Names.lookup(this.state.valueLookup, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
return this.setState({
|
||||||
|
responseLookup: err.message || err,
|
||||||
|
isLookupError: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
responseLookup: result,
|
||||||
|
isLookupError: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (<React.Fragment>
|
||||||
|
{this.state.globalError && <Alert bsStyle="danger">{this.state.globalError}</Alert>}
|
||||||
|
<h3>Resolve a name</h3>
|
||||||
|
<Form inline>
|
||||||
|
<FormGroup>
|
||||||
|
{this.state.responseResolve &&
|
||||||
|
<Alert className="alert-result" bsStyle={this.state.isResolveError ? 'danger' : 'success'}>
|
||||||
|
Resolved address: <span className="value">{this.state.responseResolve}</span>
|
||||||
|
</Alert>}
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.valueResolve}
|
||||||
|
onChange={(e) => this.handleChange('valueResolve', e)}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.resolveName(e)}>Resolve name</Button>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Lookup an address</h3>
|
||||||
|
<Form inline>
|
||||||
|
<FormGroup>
|
||||||
|
{this.state.responseLookup &&
|
||||||
|
<Alert className="alert-result" bsStyle={this.state.isLookupError ? 'danger' : 'success'}>
|
||||||
|
Looked up domain: <span className="value">{this.state.responseLookup}</span>
|
||||||
|
</Alert>}
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.valueLookup}
|
||||||
|
onChange={(e) => this.handleChange('valueLookup', e)}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.lookupAddress(e)}>Lookup address</Button>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Register subdomain for embark</h3>
|
||||||
|
<Form inline>
|
||||||
|
<FormGroup>
|
||||||
|
{this.state.responseRegister &&
|
||||||
|
<Alert className="alert-result" bsStyle={this.state.isRegisterError ? 'danger' : 'success'}>
|
||||||
|
<span className="value">{this.state.responseRegister}</span>
|
||||||
|
</Alert>}
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.valueRegister}
|
||||||
|
onChange={(e) => this.handleChange('valueRegister', e)}/>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
defaultValue={this.state.addressRegister}
|
||||||
|
onChange={(e) => this.handleChange('addressRegister', e)}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.registerSubDomain(e)}>Register subdomain</Button>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Embark Calls </h3>
|
||||||
|
<p>Javascript calls being made: </p>
|
||||||
|
<div className="logs">
|
||||||
|
{
|
||||||
|
this.state.embarkLogs.map((item, i) => <p key={i}>{item}</p>)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ENS;
|
|
@ -0,0 +1,258 @@
|
||||||
|
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: '',
|
||||||
|
valueRegister: '',
|
||||||
|
valueResolver: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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 + "')");
|
||||||
|
}
|
||||||
|
|
||||||
|
ipnsRegister(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.setState({ registering: true, responseRegister: false });
|
||||||
|
this.addToLog("EmbarkJS.Names.register(this.state.ipfsHash).then(function(hash) { })");
|
||||||
|
EmbarkJS.Names.register(this.state.valueRegister, (err, name) => {
|
||||||
|
let responseRegister;
|
||||||
|
let isRegisterError = false;
|
||||||
|
if (err) {
|
||||||
|
isRegisterError = true;
|
||||||
|
responseRegister = "Name Register Error: " + (err.message || err)
|
||||||
|
} else {
|
||||||
|
responseRegister = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
registering: false,
|
||||||
|
responseRegister,
|
||||||
|
isRegisterError
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ipnsResolve(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.setState({ resolving: true, responseResolver: false });
|
||||||
|
this.addToLog("EmbarkJS.Names.resolve(this.state.ipnsName, function(err, path) { })");
|
||||||
|
EmbarkJS.Names.resolve(this.state.valueResolver, (err, path) => {
|
||||||
|
let responseResolver;
|
||||||
|
let isResolverError = false;
|
||||||
|
if (err) {
|
||||||
|
isResolverError = true;
|
||||||
|
responseResolver = "Name Resolve Error: " + (err.message || err)
|
||||||
|
} else {
|
||||||
|
responseResolver = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
resolving: false,
|
||||||
|
responseResolver,
|
||||||
|
isResolverError
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
||||||
|
<h3>Register to IPNS</h3>
|
||||||
|
<Form inline>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
value={this.state.valueRegister}
|
||||||
|
onChange={e => this.handleChange(e, 'valueRegister')}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.ipnsRegister(e)}>
|
||||||
|
{this.state.registering ? 'Registering...' : 'Register' }
|
||||||
|
</Button>
|
||||||
|
<HelpBlock>It will take around 1 minute</HelpBlock>
|
||||||
|
{this.state.responseRegister &&
|
||||||
|
<Alert className="alert-result" bsStyle={this.state.isRegisterError ? 'danger' : 'success'}>
|
||||||
|
<span className="value">{this.state.responseRegister}</span>
|
||||||
|
</Alert>}
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<h3>Resolve name</h3>
|
||||||
|
<Form inline>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControl
|
||||||
|
type="text"
|
||||||
|
value={this.state.valueResolver}
|
||||||
|
onChange={e => this.handleChange(e, 'valueResolver')}/>
|
||||||
|
<Button bsStyle="primary" onClick={(e) => this.ipnsResolve(e)}>
|
||||||
|
{this.state.resolving ? 'Resolving...' : 'Resolve' }
|
||||||
|
</Button>
|
||||||
|
<HelpBlock>It will take around 1 minute</HelpBlock>
|
||||||
|
{this.state.responseResolver &&
|
||||||
|
<Alert className="alert-result" bsStyle={this.state.isResolverError ? 'danger' : 'success'}>
|
||||||
|
<span className="value">{this.state.responseResolver}</span>
|
||||||
|
</Alert>}
|
||||||
|
</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;
|
|
@ -0,0 +1,118 @@
|
||||||
|
import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
|
import React from 'react';
|
||||||
|
import {Alert, Form, FormGroup, FormControl, 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();
|
||||||
|
|
||||||
|
const subscribedChannels = this.state.subscribedChannels;
|
||||||
|
subscribedChannels.push(<span>Subscribed to <b>{this.state.listenTo}</b>. Now try sending a message</span>);
|
||||||
|
this.setState({
|
||||||
|
subscribedChannels
|
||||||
|
});
|
||||||
|
|
||||||
|
EmbarkJS.Messages.listenTo({topic: [this.state.listenTo]}, (error, message) => {
|
||||||
|
const messageList = this.state.messageList;
|
||||||
|
if (error) {
|
||||||
|
messageList.push(<span className="alert-danger">Error: {error}</span>);
|
||||||
|
} else {
|
||||||
|
messageList.push(<span>Channel: <b>{message.topic}</b> | Message: <b>{message.data}</b></span>);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
messageList
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
|
@ -0,0 +1,57 @@
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logs {
|
||||||
|
background-color: black;
|
||||||
|
font-size: 14px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
border-left: 1px solid #ddd;
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tabs {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.form-control {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-result {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import {Tabs, Tab} from 'react-bootstrap';
|
||||||
|
|
||||||
|
import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
|
import Blockchain from './components/blockchain';
|
||||||
|
import Whisper from './components/whisper';
|
||||||
|
import Storage from './components/storage';
|
||||||
|
import ENS from './components/ens';
|
||||||
|
|
||||||
|
import './dapp.css';
|
||||||
|
|
||||||
|
class App extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleSelect = this.handleSelect.bind(this);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
activeKey: 1,
|
||||||
|
whisperEnabled: false,
|
||||||
|
storageEnabled: false,
|
||||||
|
ensEnabled: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
EmbarkJS.onReady(() => {
|
||||||
|
if (EmbarkJS.isNewWeb3()) {
|
||||||
|
EmbarkJS.Messages.Providers.whisper.getWhisperVersion((err, _version) => {
|
||||||
|
if (err) {
|
||||||
|
return console.log(err);
|
||||||
|
}
|
||||||
|
this.setState({whisperEnabled: true});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (EmbarkJS.Messages.providerName === 'whisper') {
|
||||||
|
EmbarkJS.Messages.getWhisperVersion((err, _version) => {
|
||||||
|
if (err) {
|
||||||
|
return console.log(err);
|
||||||
|
}
|
||||||
|
this.setState({whisperEnabled: true});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
storageEnabled: EmbarkJS.Storage.isAvailable(),
|
||||||
|
ensEnabled: EmbarkJS.Names.isAvailable(),
|
||||||
|
ensNameSystems: EmbarkJS.Names.currentNameSystems
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderStatus(title, available) {
|
||||||
|
let className = available ? 'pull-right status-online' : 'pull-right status-offline';
|
||||||
|
return <React.Fragment>
|
||||||
|
{title}
|
||||||
|
<span className={className}></span>
|
||||||
|
</React.Fragment>;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSelect(key) {
|
||||||
|
if (key === 2) {
|
||||||
|
EmbarkJS.Names.setProvider('ipns', {server: 'localhost', port: '5001'});
|
||||||
|
} else if (key === 4) {
|
||||||
|
EmbarkJS.Names.currentNameSystems = this.state.ensNameSystems
|
||||||
|
}
|
||||||
|
this.setState({ activeKey: key });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (<div><h3>Embark - Usage Example</h3>
|
||||||
|
<Tabs onSelect={this.handleSelect} activeKey={this.state.activeKey} 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)', this.state.whisperEnabled)}>
|
||||||
|
<Whisper enabled={this.state.whisperEnabled}/>
|
||||||
|
</Tab>
|
||||||
|
<Tab eventKey={4} title={this._renderStatus('Naming (ENS)', this.state.ensEnabled)}>
|
||||||
|
<ENS enabled={this.state.ensEnabled}/>
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(<App></App>, document.getElementById('app'));
|
|
@ -0,0 +1,12 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Embark - SimpleStorage Demo</title>
|
||||||
|
<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">
|
||||||
|
<div id="app">
|
||||||
|
</div>
|
||||||
|
<script src="js/dapp.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,73 @@
|
||||||
|
module.exports = {
|
||||||
|
development: {
|
||||||
|
enabled: true,
|
||||||
|
networkType: "custom", // Can be: testnet, rinkeby, livenet or custom, in which case, it will use the specified networkId
|
||||||
|
networkId: "1337", // Network id used when networkType is custom
|
||||||
|
isDev: true, // Uses and ephemeral proof-of-authority network with a pre-funded developer account, mining enabled
|
||||||
|
datadir: ".embark/development/datadir", // Data directory for the databases and keystore
|
||||||
|
mineWhenNeeded: true, // Uses our custom script (if isDev is false) to mine only when needed
|
||||||
|
nodiscover: true, // Disables the peer discovery mechanism (manual peer addition)
|
||||||
|
maxpeers: 0, // Maximum number of network peers (network disabled if set to 0) (default: 25)
|
||||||
|
rpcHost: "localhost", // HTTP-RPC server listening interface (default: "localhost")
|
||||||
|
rpcPort: 8545, // HTTP-RPC server listening port (default: 8545)
|
||||||
|
rpcCorsDomain: "auto", // Comma separated list of domains from which to accept cross origin requests (browser enforced)
|
||||||
|
// When set to "auto", Embark will automatically set the cors to the address of the webserver
|
||||||
|
proxy: true, // Proxy is used to present meaningful information about transactions
|
||||||
|
targetGasLimit: 8000000, // Target gas limit sets the artificial target gas floor for the blocks to mine
|
||||||
|
wsRPC: true, // Enable the WS-RPC server
|
||||||
|
wsOrigins: "http://localhost:8000,http://localhost:8080,embark", // Origins from which to accept websockets requests
|
||||||
|
// When set to "auto", Embark will automatically set the cors to the address of the webserver
|
||||||
|
wsHost: "localhost", // WS-RPC server listening interface (default: "localhost")
|
||||||
|
wsPort: 8546, // WS-RPC server listening port (default: 8546)
|
||||||
|
simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm", // Mnemonic used by the simulator to generate a wallet
|
||||||
|
simulatorBlocktime: 0 // Specify blockTime in seconds for automatic mining. Default is 0 and no auto-mining.
|
||||||
|
},
|
||||||
|
privatenet: {
|
||||||
|
enabled: true,
|
||||||
|
networkType: "custom",
|
||||||
|
networkId: "1337",
|
||||||
|
isDev: false,
|
||||||
|
genesisBlock: "config/privatenet/genesis.json", // Genesis block to initiate on first creation of a development node
|
||||||
|
datadir: ".embark/privatenet/datadir",
|
||||||
|
mineWhenNeeded: true,
|
||||||
|
nodiscover: true,
|
||||||
|
maxpeers: 0,
|
||||||
|
rpcHost: "localhost",
|
||||||
|
rpcPort: 8545,
|
||||||
|
rpcCorsDomain: "auto",
|
||||||
|
proxy: true,
|
||||||
|
account: {
|
||||||
|
// "address": "", // When specified, uses that address instead of the default one for the network
|
||||||
|
password: "config/privatenet/password" // Password to unlock the account
|
||||||
|
},
|
||||||
|
targetGasLimit: 8000000,
|
||||||
|
wsRPC: true,
|
||||||
|
wsOrigins: "auto",
|
||||||
|
wsHost: "localhost",
|
||||||
|
wsPort: 8546,
|
||||||
|
simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm",
|
||||||
|
simulatorBlocktime: 0
|
||||||
|
},
|
||||||
|
testnet: {
|
||||||
|
enabled: true,
|
||||||
|
networkType: "testnet",
|
||||||
|
syncMode: "light",
|
||||||
|
rpcHost: "localhost",
|
||||||
|
rpcPort: 8545,
|
||||||
|
rpcCorsDomain: "http://localhost:8000",
|
||||||
|
account: {
|
||||||
|
password: "config/testnet/password"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
livenet: {
|
||||||
|
enabled: true,
|
||||||
|
networkType: "livenet",
|
||||||
|
syncMode: "light",
|
||||||
|
rpcHost: "localhost",
|
||||||
|
rpcPort: 8545,
|
||||||
|
rpcCorsDomain: "http://localhost:8000",
|
||||||
|
account: {
|
||||||
|
password: "config/livenet/password"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
module.exports = {
|
||||||
|
default: {
|
||||||
|
enabled: true,
|
||||||
|
provider: "whisper", // Communication provider. Currently, Embark only supports whisper
|
||||||
|
available_providers: ["whisper"], // Array of available providers
|
||||||
|
connection: {
|
||||||
|
host: "localhost", // Host of the blockchain node
|
||||||
|
port: 8546, // Port of the blockchain node
|
||||||
|
type: "ws" // Type of connection (ws or rpc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,41 @@
|
||||||
|
module.exports = {
|
||||||
|
// default applies to all environments
|
||||||
|
default: {
|
||||||
|
// Blockchain node to deploy the contracts
|
||||||
|
deployment: {
|
||||||
|
host: "localhost", // Host of the blockchain node
|
||||||
|
port: 8545, // Port of the blockchain node
|
||||||
|
type: "rpc" // Type of connection (ws or rpc),
|
||||||
|
// Accounts to use instead of the default account to populate your wallet
|
||||||
|
/*,accounts: [
|
||||||
|
{
|
||||||
|
privateKey: "your_private_key",
|
||||||
|
balance: "5 ether" // You can set the balance of the account in the dev environment
|
||||||
|
// Balances are in Wei, but you can specify the unit with its name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
privateKeyFile: "path/to/file" // You can put more than one key, separated by , or ;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mnemonic: "12 word mnemonic",
|
||||||
|
addressIndex: "0", // Optionnal. The index to start getting the address
|
||||||
|
numAddresses: "1", // Optionnal. The number of addresses to get
|
||||||
|
hdpath: "m/44'/60'/0'/0/" // Optionnal. HD derivation path
|
||||||
|
}
|
||||||
|
]*/
|
||||||
|
},
|
||||||
|
// order of connections the dapp should connect to
|
||||||
|
dappConnection: [
|
||||||
|
"$WEB3", // uses pre existing web3 object if available (e.g in Mist)
|
||||||
|
"ws://localhost:8546",
|
||||||
|
"http://localhost:8545"
|
||||||
|
],
|
||||||
|
gas: "auto",
|
||||||
|
contracts: {
|
||||||
|
SimpleStorage: {
|
||||||
|
fromIndex: 0,
|
||||||
|
args: [100]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
module.exports = {
|
||||||
|
default: {
|
||||||
|
available_providers: ["ens", "ipns"],
|
||||||
|
provider: "ens",
|
||||||
|
register: {
|
||||||
|
rootDomain: "embark.eth",
|
||||||
|
subdomains: {
|
||||||
|
'status': '0x1a2f3b98e434c02363f3dac3174af93c1d690914'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"homesteadBlock": 0,
|
||||||
|
"byzantiumBlock": 0,
|
||||||
|
"daoForkSupport": true
|
||||||
|
},
|
||||||
|
"nonce": "0x0000000000000042",
|
||||||
|
"difficulty": "0x0",
|
||||||
|
"alloc": {
|
||||||
|
"0x3333333333333333333333333333333333333333": {"balance": "15000000000000000000"}
|
||||||
|
},
|
||||||
|
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"coinbase": "0x3333333333333333333333333333333333333333",
|
||||||
|
"timestamp": "0x00",
|
||||||
|
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"extraData": "0x",
|
||||||
|
"gasLimit": "0x7a1200"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
dev_password
|
|
@ -0,0 +1,35 @@
|
||||||
|
module.exports = {
|
||||||
|
default: {
|
||||||
|
enabled: true,
|
||||||
|
ipfs_bin: "ipfs",
|
||||||
|
provider: "ipfs",
|
||||||
|
available_providers: ["ipfs"],
|
||||||
|
upload: {
|
||||||
|
host: "localhost",
|
||||||
|
port: 5001
|
||||||
|
},
|
||||||
|
dappConnection: [
|
||||||
|
{
|
||||||
|
provider:"ipfs",
|
||||||
|
host: "localhost",
|
||||||
|
port: 5001,
|
||||||
|
getUrl: "http://localhost:8080/ipfs/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
// Configuration to start Swarm in the same terminal as `embark run`
|
||||||
|
/*,account: {
|
||||||
|
address: "YOUR_ACCOUNT_ADDRESS", // Address of account accessing Swarm
|
||||||
|
password: "PATH/TO/PASSWORD/FILE" // File containing the password of the account
|
||||||
|
},
|
||||||
|
swarmPath: "PATH/TO/SWARM/EXECUTABLE" // Path to swarm executable (default: swarm)*/
|
||||||
|
},
|
||||||
|
development: {
|
||||||
|
enabled: true,
|
||||||
|
provider: "ipfs",
|
||||||
|
upload: {
|
||||||
|
host: "localhost",
|
||||||
|
port: 5001,
|
||||||
|
getUrl: "http://localhost:8080/ipfs/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1 @@
|
||||||
|
test_password
|
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
enabled: true,
|
||||||
|
host: "localhost",
|
||||||
|
port: 8000
|
||||||
|
};
|
|
@ -0,0 +1,21 @@
|
||||||
|
pragma solidity ^0.4.23;
|
||||||
|
|
||||||
|
contract Loops {
|
||||||
|
uint public storedData;
|
||||||
|
|
||||||
|
constructor(uint initialValue) public {
|
||||||
|
storedData = initialValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function set(uint x) public {
|
||||||
|
for(uint i = storedData; i < x; i++) {
|
||||||
|
uint newValue = storedData + x;
|
||||||
|
storedData = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function get() public view returns (uint retVal) {
|
||||||
|
return storedData;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
pragma solidity ^0.4.23;
|
||||||
|
|
||||||
|
contract SimpleStorage {
|
||||||
|
uint public storedData;
|
||||||
|
|
||||||
|
constructor(uint initialValue) public {
|
||||||
|
storedData = initialValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set(uint x) public {
|
||||||
|
storedData = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get() public view returns (uint retVal) {
|
||||||
|
return storedData;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"contracts": ["contracts/**"],
|
||||||
|
"app": {
|
||||||
|
"js/dapp.js": ["app/dapp.js"],
|
||||||
|
"index.html": "app/index.html",
|
||||||
|
"images/": ["app/images/**"]
|
||||||
|
},
|
||||||
|
"buildDir": "dist/",
|
||||||
|
"config": "config/",
|
||||||
|
"versions": {
|
||||||
|
"web3": "1.0.0-beta",
|
||||||
|
"solc": "0.4.24",
|
||||||
|
"ipfs-api": "17.2.4"
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,278 @@
|
||||||
|
{
|
||||||
|
"name": "app_name",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"asap": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
||||||
|
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
|
||||||
|
},
|
||||||
|
"babel-runtime": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||||
|
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "^2.4.0",
|
||||||
|
"regenerator-runtime": "^0.11.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": {
|
||||||
|
"version": "2.5.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
|
||||||
|
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"classnames": {
|
||||||
|
"version": "2.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
|
||||||
|
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
|
||||||
|
},
|
||||||
|
"core-js": {
|
||||||
|
"version": "1.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
|
||||||
|
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
|
||||||
|
},
|
||||||
|
"dom-helpers": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg=="
|
||||||
|
},
|
||||||
|
"encoding": {
|
||||||
|
"version": "0.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
|
||||||
|
"integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
|
||||||
|
"requires": {
|
||||||
|
"iconv-lite": "~0.4.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fbjs": {
|
||||||
|
"version": "0.8.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
|
||||||
|
"integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "^1.0.0",
|
||||||
|
"isomorphic-fetch": "^2.1.1",
|
||||||
|
"loose-envify": "^1.0.0",
|
||||||
|
"object-assign": "^4.1.0",
|
||||||
|
"promise": "^7.1.1",
|
||||||
|
"setimmediate": "^1.0.5",
|
||||||
|
"ua-parser-js": "^0.7.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"iconv-lite": {
|
||||||
|
"version": "0.4.23",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
|
||||||
|
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
|
||||||
|
"requires": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"invariant": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-stream": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||||
|
},
|
||||||
|
"isomorphic-fetch": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
|
||||||
|
"integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
|
||||||
|
"requires": {
|
||||||
|
"node-fetch": "^1.0.1",
|
||||||
|
"whatwg-fetch": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"js-tokens": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||||
|
},
|
||||||
|
"keycode": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ="
|
||||||
|
},
|
||||||
|
"loose-envify": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||||
|
"requires": {
|
||||||
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
|
||||||
|
"integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
|
||||||
|
"requires": {
|
||||||
|
"encoding": "^0.1.11",
|
||||||
|
"is-stream": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"object-assign": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||||
|
},
|
||||||
|
"promise": {
|
||||||
|
"version": "7.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
|
||||||
|
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
|
||||||
|
"requires": {
|
||||||
|
"asap": "~2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prop-types": {
|
||||||
|
"version": "15.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
|
||||||
|
"integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.3.1",
|
||||||
|
"object-assign": "^4.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prop-types-extra": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-QFyuDxvMipmIVKD2TwxLVPzMnO4e5oOf1vr3tJIomL8E7d0lr6phTHd5nkPhFIzTD1idBLLEPeylL9g+rrTzRg==",
|
||||||
|
"requires": {
|
||||||
|
"react-is": "^16.3.2",
|
||||||
|
"warning": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"version": "16.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react/-/react-16.4.2.tgz",
|
||||||
|
"integrity": "sha512-dMv7YrbxO4y2aqnvA7f/ik9ibeLSHQJTI6TrYAenPSaQ6OXfb+Oti+oJiy8WBxgRzlKatYqtCjphTgDSCEiWFg==",
|
||||||
|
"requires": {
|
||||||
|
"fbjs": "^0.8.16",
|
||||||
|
"loose-envify": "^1.1.0",
|
||||||
|
"object-assign": "^4.1.1",
|
||||||
|
"prop-types": "^15.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-bootstrap": {
|
||||||
|
"version": "0.32.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.32.1.tgz",
|
||||||
|
"integrity": "sha512-RbfzKUbsukWsToWqGHfCCyMFq9QQI0TznutdyxyJw6dih2NvIne25Mrssg8LZsprqtPpyQi8bN0L0Fx3fUsL8Q==",
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "^6.11.6",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"dom-helpers": "^3.2.0",
|
||||||
|
"invariant": "^2.2.1",
|
||||||
|
"keycode": "^2.1.2",
|
||||||
|
"prop-types": "^15.5.10",
|
||||||
|
"prop-types-extra": "^1.0.1",
|
||||||
|
"react-overlays": "^0.8.0",
|
||||||
|
"react-prop-types": "^0.4.0",
|
||||||
|
"react-transition-group": "^2.0.0",
|
||||||
|
"uncontrollable": "^4.1.0",
|
||||||
|
"warning": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"version": "16.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.4.2.tgz",
|
||||||
|
"integrity": "sha512-Usl73nQqzvmJN+89r97zmeUpQDKDlh58eX6Hbs/ERdDHzeBzWy+ENk7fsGQ+5KxArV1iOFPT46/VneklK9zoWw==",
|
||||||
|
"requires": {
|
||||||
|
"fbjs": "^0.8.16",
|
||||||
|
"loose-envify": "^1.1.0",
|
||||||
|
"object-assign": "^4.1.1",
|
||||||
|
"prop-types": "^15.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-is": {
|
||||||
|
"version": "16.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.4.2.tgz",
|
||||||
|
"integrity": "sha512-rI3cGFj/obHbBz156PvErrS5xc6f1eWyTwyV4mo0vF2lGgXgS+mm7EKD5buLJq6jNgIagQescGSVG2YzgXt8Yg=="
|
||||||
|
},
|
||||||
|
"react-lifecycles-compat": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||||
|
},
|
||||||
|
"react-overlays": {
|
||||||
|
"version": "0.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.8.3.tgz",
|
||||||
|
"integrity": "sha512-h6GT3jgy90PgctleP39Yu3eK1v9vaJAW73GOA/UbN9dJ7aAN4BTZD6793eI1D5U+ukMk17qiqN/wl3diK1Z5LA==",
|
||||||
|
"requires": {
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"dom-helpers": "^3.2.1",
|
||||||
|
"prop-types": "^15.5.10",
|
||||||
|
"prop-types-extra": "^1.0.1",
|
||||||
|
"react-transition-group": "^2.2.0",
|
||||||
|
"warning": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-prop-types": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-prop-types/-/react-prop-types-0.4.0.tgz",
|
||||||
|
"integrity": "sha1-+ZsL+0AGkpya8gUefBQUpcdbk9A=",
|
||||||
|
"requires": {
|
||||||
|
"warning": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-transition-group": {
|
||||||
|
"version": "2.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.4.0.tgz",
|
||||||
|
"integrity": "sha512-Xv5d55NkJUxUzLCImGSanK8Cl/30sgpOEMGc5m86t8+kZwrPxPCPcFqyx83kkr+5Lz5gs6djuvE5By+gce+VjA==",
|
||||||
|
"requires": {
|
||||||
|
"dom-helpers": "^3.3.1",
|
||||||
|
"loose-envify": "^1.3.1",
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||||
|
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||||
|
},
|
||||||
|
"safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
|
},
|
||||||
|
"setimmediate": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||||
|
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
|
||||||
|
},
|
||||||
|
"ua-parser-js": {
|
||||||
|
"version": "0.7.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz",
|
||||||
|
"integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA=="
|
||||||
|
},
|
||||||
|
"uncontrollable": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-4.1.0.tgz",
|
||||||
|
"integrity": "sha1-4DWCkSUuGGUiLZCTmxny9J+Bwak=",
|
||||||
|
"requires": {
|
||||||
|
"invariant": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"whatwg-fetch": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "coverage_app",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"main": "Gruntfile.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "../../bin/embark test",
|
||||||
|
"coverage": "istanbul report --root .embark --format html"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"homepage": "",
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^16.3.2",
|
||||||
|
"react-bootstrap": "^0.32.1",
|
||||||
|
"react-dom": "^16.3.2",
|
||||||
|
"istanbul": "^0.4.5"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*global contract, config, it, assert*/
|
||||||
|
const Loops = require('Embark/contracts/Loops');
|
||||||
|
|
||||||
|
config({
|
||||||
|
contracts: {
|
||||||
|
"Loops": {
|
||||||
|
args: [1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
contract("Loops", function() {
|
||||||
|
it("should set constructor value", function(done) {
|
||||||
|
Loops.methods.storedData().call().then((result) => {
|
||||||
|
assert.strictEqual(parseInt(result, 10), 1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("set storage value", function(done) {
|
||||||
|
Loops.methods.set(5).send().then(() => {
|
||||||
|
Loops.methods.get().call().then((result) => {
|
||||||
|
assert.strictEqual(parseInt(result, 10), 21);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*global contract, config, it, assert*/
|
||||||
|
const SimpleStorage = require('Embark/contracts/SimpleStorage');
|
||||||
|
|
||||||
|
config({
|
||||||
|
contracts: {
|
||||||
|
"SimpleStorage": {
|
||||||
|
args: [100]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
contract("SimpleStorage", function() {
|
||||||
|
it("should set constructor value", function(done) {
|
||||||
|
SimpleStorage.methods.storedData().call().then((result) => {
|
||||||
|
assert.strictEqual(parseInt(result, 10), 100);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("set storage value", function(done) {
|
||||||
|
SimpleStorage.methods.set(150).send().then(() => {
|
||||||
|
SimpleStorage.methods.get().call().then((result) => {
|
||||||
|
assert.strictEqual(parseInt(result, 10), 150);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue