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');
|
||||
|
||||
class ContractSource {
|
||||
|
@ -68,18 +70,29 @@ class ContractSource {
|
|||
var bytecodeIdx = 0;
|
||||
var pc = 0;
|
||||
var instructions = 0;
|
||||
var previousSourceMap = null;
|
||||
do {
|
||||
let sourceMap;
|
||||
|
||||
if(previousSourceMap === null) {
|
||||
sourceMap = new SourceMap(sourceMaps[instructions]);
|
||||
} else {
|
||||
sourceMap = previousSourceMap.createRelativeTo(sourceMaps[instructions]);
|
||||
}
|
||||
|
||||
var instruction = opcodes[bytecodeIdx];
|
||||
var length = this._instructionLength(instruction);
|
||||
bytecodeMapping[pc] = {
|
||||
instruction: instruction,
|
||||
sourceMap: sourceMaps[instructions],
|
||||
sourceMap: sourceMap,
|
||||
jump: sourceMap.jump,
|
||||
seen: false
|
||||
};
|
||||
|
||||
pc += length;
|
||||
instructions++;
|
||||
bytecodeIdx += (length > 1) ? 2 : 1;
|
||||
previousSourceMap = sourceMap;
|
||||
} 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');
|
||||
|
||||
var coverage = {
|
||||
code: this.body.split("\n"),
|
||||
code: this.body.trim().split("\n"),
|
||||
l: {},
|
||||
path: this.file,
|
||||
s: {},
|
||||
|
@ -111,10 +124,10 @@ class ContractSource {
|
|||
var markLocations = [];
|
||||
|
||||
switch(node.nodeType) {
|
||||
case 'Identifier':
|
||||
case 'Assignment':
|
||||
case 'Literal':
|
||||
case 'VariableDeclaration':
|
||||
case 'PragmaDirective':
|
||||
case 'VariableDeclaration':
|
||||
// We don't need to do anything with these. Just carry on.
|
||||
break;
|
||||
|
||||
|
@ -166,8 +179,9 @@ class ContractSource {
|
|||
node.src = node.expression.src;
|
||||
// falls through
|
||||
|
||||
case 'Assignment':
|
||||
case 'ExpressionStatement':
|
||||
case 'Identifier':
|
||||
case 'UnaryOperation':
|
||||
coverage.s[node.id] = 0;
|
||||
|
||||
location = this.sourceMapToLocations(node.src);
|
||||
|
@ -219,8 +233,43 @@ class ContractSource {
|
|||
markLocations = [location];
|
||||
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:
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -243,23 +292,26 @@ class ContractSource {
|
|||
contractMatches = trace.structLogs.every((step) => { return bytecode[step.pc]; });
|
||||
if(!contractMatches) break;
|
||||
|
||||
console.log(sourceMapToNodeType);
|
||||
|
||||
trace.structLogs.forEach((step) => {
|
||||
step = bytecode[step.pc];
|
||||
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;
|
||||
|
||||
var recordedLineHit = false;
|
||||
|
||||
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++) {
|
||||
coverage.l[line]++;
|
||||
}
|
||||
|
||||
recordedLineHit = true;
|
||||
}
|
||||
|
||||
if(node.type != 'b') coverage[node.type][node.id]++;
|
||||
|
|
|
@ -10,6 +10,7 @@ web3.extend({
|
|||
methods: [{name: 'traceTransaction', call: 'debug_traceTransaction', params: 2}]
|
||||
});
|
||||
|
||||
|
||||
class CodeCoverage {
|
||||
constructor(embark, _options) {
|
||||
this.events = embark.events;
|
||||
|
@ -21,6 +22,7 @@ class CodeCoverage {
|
|||
embark.events.on('block:header', this.runSolc.bind(this));
|
||||
|
||||
this.seenTransactions = {};
|
||||
this.coverageReport = {};
|
||||
|
||||
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 {
|
||||
constructor(sourceMapStringOrOffset, length, id) {
|
||||
constructor(sourceMapStringOrOffset, length, id, jump) {
|
||||
if(typeof sourceMapStringOrOffset == 'string') {
|
||||
let [offset, length, id, ..._rest] = sourceMapStringOrOffset.split(":");
|
||||
let [offset, length, id, jump] = sourceMapStringOrOffset.split(":");
|
||||
|
||||
this.offset = parseInt(offset, 10);
|
||||
this.length = parseInt(length, 10);
|
||||
|
||||
if(id) this.id = parseInt(id, 10);
|
||||
this.jump = jump;
|
||||
} else {
|
||||
this.offset = sourceMapStringOrOffset;
|
||||
this.length = length;
|
||||
this.id = id;
|
||||
this.jump = jump;
|
||||
}
|
||||
}
|
||||
|
||||
subtract(sourceMap) {
|
||||
return new SourceMap(this.offset, sourceMap.offset - this.offset);
|
||||
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);
|
||||
}
|
||||
|
||||
toString() {
|
||||
var parts = [this.offset, this.length];
|
||||
if(this.id) parts.push(this.id);
|
||||
subtract(sourceMap) {
|
||||
return new SourceMap(this.offset, sourceMap.offset - this.offset, this.id, this.jump);
|
||||
}
|
||||
|
||||
toString(defaultId) {
|
||||
let parts = [this.offset, this.length];
|
||||
|
||||
if(this.id !== undefined && this.id != '') {
|
||||
parts.push(this.id)
|
||||
} else if(defaultId !== undefined) {
|
||||
parts.push(defaultId);
|
||||
}
|
||||
|
||||
return parts.join(':');
|
||||
}
|
||||
|
||||
static empty() {
|
||||
return EmptySourceMap;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SourceMap;
|
||||
|
|
|
@ -112,7 +112,6 @@ class Test {
|
|||
compileOnceOnly: true
|
||||
});
|
||||
this.events.request('deploy:setGasLimit', 6000000);
|
||||
this.engine.startService("codeCoverage");
|
||||
}
|
||||
|
||||
init(callback) {
|
||||
|
@ -139,6 +138,7 @@ class Test {
|
|||
this.engine.startService("codeRunner");
|
||||
this.initDeployServices();
|
||||
this.engine.startService("codeGenerator");
|
||||
this.engine.startService("codeCoverage");
|
||||
|
||||
if (this.options.node === 'embark') {
|
||||
return this.engine.ipc.connect((err) => {
|
||||
|
|
|
@ -162,10 +162,10 @@ contract x {
|
|||
|
||||
var bytecode = contractSource.contractBytecode['x'];
|
||||
|
||||
assert.deepEqual({instruction: 'PUSH1', sourceMap: '26:487:0:-', seen: false}, bytecode[0]);
|
||||
assert.deepEqual({instruction: 'PUSH1', sourceMap: '', seen: false}, bytecode[2]);
|
||||
assert.deepEqual({instruction: 'MSTORE', sourceMap: '', seen: false}, bytecode[4]);
|
||||
assert.deepEqual({instruction: 'PUSH1', sourceMap: '', seen: false}, bytecode[5]);
|
||||
assert.deepEqual({instruction: 'PUSH1', sourceMap: {offset: 26, length: 487, id: 0}, seen: false}, bytecode[0]);
|
||||
assert.deepEqual({instruction: 'PUSH1', sourceMap: SourceMap.empty(), seen: false}, bytecode[2]);
|
||||
assert.deepEqual({instruction: 'MSTORE', sourceMap: SourceMap.empty(), seen: false}, bytecode[4]);
|
||||
assert.deepEqual({instruction: 'PUSH1', sourceMap: SourceMap.empty(), seen: false}, bytecode[5]);
|
||||
|
||||
done();
|
||||
});
|
||||
|
@ -193,6 +193,7 @@ contract x {
|
|||
|
||||
var trace = JSON.parse(loadFixture('geth-debugtrace-output-h-5.json'));
|
||||
var coverage = cs.generateCodeCoverage(trace);
|
||||
assert.exists(coverage);
|
||||
|
||||
done();
|
||||
});
|
||||
|
@ -213,7 +214,7 @@ contract x {
|
|||
// In the fixture, the branch has an ID of 61, and the function has the
|
||||
// ID of 63
|
||||
assert.deepEqual([1,1], coverage.b['61']);
|
||||
assert.equal(2, coverage.f['63']);
|
||||
assert.equal(4, coverage.f['63']);
|
||||
|
||||
done();
|
||||
});
|
||||
|
@ -234,4 +235,26 @@ describe('SourceMap', () => {
|
|||
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