mirror of https://github.com/embarklabs/embark.git
fix eslint on EVERYTHING
This commit is contained in:
parent
0b6cb01a80
commit
4e7a0389bb
|
@ -0,0 +1 @@
|
|||
lib/modules/webserver/backend/assets/*
|
|
@ -67,7 +67,7 @@
|
|||
],
|
||||
"dot-notation": "off",
|
||||
"eol-last": "error",
|
||||
"eqeqeq": "off",
|
||||
"eqeqeq": "error",
|
||||
"for-direction": "error",
|
||||
"func-call-spacing": "error",
|
||||
"func-name-matching": "error",
|
||||
|
|
|
@ -31,8 +31,8 @@ class Dashboard {
|
|||
plugin.registerAPICall(
|
||||
'ws',
|
||||
'/embark-api/dashboard',
|
||||
(ws, req) => {
|
||||
let dashboardState = { contractsState: [], environment: "", status: "", availableServices: [] };
|
||||
(ws, _req) => {
|
||||
let dashboardState = {contractsState: [], environment: "", status: "", availableServices: []};
|
||||
|
||||
// TODO: doesn't feel quite right, should be refactored into a shared
|
||||
// dashboard state
|
||||
|
|
|
@ -3,7 +3,7 @@ import {NavLink, Route, Switch, withRouter} from 'react-router-dom';
|
|||
import {
|
||||
Page,
|
||||
Grid,
|
||||
List,
|
||||
List
|
||||
} from "tabler-react";
|
||||
|
||||
import AccountsContainer from '../containers/AccountsContainer';
|
||||
|
|
|
@ -20,7 +20,8 @@ const Transactions = ({transactions}) => (
|
|||
{content: "From"},
|
||||
{content: "To"},
|
||||
{content: "Type"},
|
||||
{content: "Hash"}]}
|
||||
{content: "Hash"}
|
||||
]}
|
||||
bodyItems={
|
||||
transactions.map((transaction) => {
|
||||
return ([
|
||||
|
|
|
@ -11,7 +11,7 @@ class Scaffolding {
|
|||
}
|
||||
|
||||
generate(contractName, contractConfiguration){
|
||||
if(this.framework == 'react'){
|
||||
if(this.framework === 'react'){
|
||||
this.embark.plugins.loadInternalPlugin('scaffolding-react', this.options);
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ class Scaffolding {
|
|||
let build = null;
|
||||
dappGenerators.forEach((plugin) => {
|
||||
plugin.dappGenerators.forEach((d) => {
|
||||
if(d.framework == this.framework){
|
||||
if(d.framework === this.framework){
|
||||
build = d.cb;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -416,7 +416,7 @@ class ContractsManager {
|
|||
let orderedDependencies;
|
||||
|
||||
try {
|
||||
orderedDependencies = toposort(converted_dependencies.filter((x) => x[0] != x[1])).reverse();
|
||||
orderedDependencies = toposort(converted_dependencies.filter((x) => x[0] !== x[1])).reverse();
|
||||
} catch(e) {
|
||||
this.logger.error((__("Error: ") + e.message).red);
|
||||
this.logger.error(__("there are two or more contracts that depend on each other in a cyclic manner").bold.red);
|
||||
|
@ -425,13 +425,11 @@ class ContractsManager {
|
|||
//process.exit(0);
|
||||
}
|
||||
|
||||
let newList = contractList.sort(function (a, b) {
|
||||
return contractList.sort(function (a, b) {
|
||||
let order_a = orderedDependencies.indexOf(a.className);
|
||||
let order_b = orderedDependencies.indexOf(b.className);
|
||||
return order_a - order_b;
|
||||
});
|
||||
|
||||
return newList;
|
||||
}
|
||||
|
||||
// TODO: should be built contracts
|
||||
|
|
|
@ -58,7 +58,7 @@ class GraphGenerator {
|
|||
|
||||
for (let i = 0; i < contract.abiDefinition.length; i++) {
|
||||
let abiDef = contract.abiDefinition[i];
|
||||
if (abiDef.type == 'event' && options.skipEvents) continue;
|
||||
if (abiDef.type === 'event' && options.skipEvents) continue;
|
||||
if (['constructor', 'fallback'].indexOf(abiDef.type) > -1 && options.skipFunctions) continue;
|
||||
|
||||
switch(abiDef.type){
|
||||
|
@ -68,14 +68,14 @@ class GraphGenerator {
|
|||
case 'constructor':
|
||||
contractLabel += "«constructor»(";
|
||||
abiDef.inputs.forEach(function(elem, index){
|
||||
contractLabel += (index == 0 ? "" : ", ") + elem.type;
|
||||
contractLabel += (index === 0 ? "" : ", ") + elem.type;
|
||||
});
|
||||
contractLabel += ")\\l";
|
||||
break;
|
||||
case 'event':
|
||||
contractLabel += "«event»" + abiDef.name + "(";
|
||||
abiDef.inputs.forEach(function(elem, index){
|
||||
contractLabel += (index == 0 ? "" : ", ") + elem.type;
|
||||
contractLabel += (index === 0 ? "" : ", ") + elem.type;
|
||||
});
|
||||
contractLabel += ")\\l";
|
||||
break;
|
||||
|
@ -84,7 +84,7 @@ class GraphGenerator {
|
|||
}
|
||||
|
||||
let fHashes = contract.functionHashes;
|
||||
if (fHashes != {} && fHashes != undefined && !options.skipFunctions){
|
||||
if (fHashes !== {} && fHashes !== undefined && !options.skipFunctions){
|
||||
for (let method in contract.functionHashes){
|
||||
contractLabel += method + '\\l';
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ class Npm {
|
|||
}
|
||||
|
||||
_isInstalling(packageName, version){
|
||||
return typeof this._installing[packageName + version] != 'undefined';
|
||||
return typeof this._installing[packageName + version] !== 'undefined';
|
||||
}
|
||||
|
||||
getPackageVersion(packageName, version, callback) {
|
||||
|
|
|
@ -6,7 +6,7 @@ i18n.setOrDetectLocale('en');
|
|||
|
||||
class NpmTimer{
|
||||
constructor(options){
|
||||
this._logger = (options.logger && typeof options.logger.info == 'function') ? options.logger : console;
|
||||
this._logger = (options.logger && typeof options.logger.info === 'function') ? options.logger : console;
|
||||
this._packageName = options.packageName;
|
||||
this._version = options.version;
|
||||
this._showSpinner = options.showSpinner || false;
|
||||
|
@ -24,7 +24,7 @@ class NpmTimer{
|
|||
}
|
||||
|
||||
get observer(){
|
||||
if(typeof this._observer == 'undefined'){
|
||||
if(typeof this._observer === 'undefined'){
|
||||
this._observer = new PerformanceObserver((items) => {
|
||||
let entry;
|
||||
let strDuration;
|
||||
|
|
|
@ -14,7 +14,7 @@ class ContractFuzzer {
|
|||
generateFuzz(iterations, contract) {
|
||||
const self = this;
|
||||
let fuzzMap = {};
|
||||
contract.abiDefinition.filter((x) => x.inputs && x.inputs.length != 0 && x.type != "event").forEach((abiMethod) => {
|
||||
contract.abiDefinition.filter((x) => x.inputs && x.inputs.length !== 0 && x.type !== "event").forEach((abiMethod) => {
|
||||
let name = abiMethod.type === "constructor" ? "constructor" : abiMethod.name;
|
||||
let inputTypes = abiMethod.inputs.map(input => input.type);
|
||||
fuzzMap[name] = {};
|
||||
|
@ -48,7 +48,7 @@ class ContractFuzzer {
|
|||
let length = arraySize === undefined || arraySize === null || arraySize === '' ? Math.floor((Math.random() * 256) + 1) : arraySize;
|
||||
return self.generateArrayOfType(length, type);
|
||||
}
|
||||
case kind == "bool":
|
||||
case kind === "bool":
|
||||
return self.generateRandomBool();
|
||||
case kind == "uint" || kind == "int":
|
||||
return self.generateRandomInt(size || 256);
|
||||
|
|
|
@ -23,7 +23,7 @@ class GasEstimator {
|
|||
// already provided for us
|
||||
gasMap['constructor'] = contract.gasEstimates.creation.totalCost.toString();
|
||||
return gasCb(null, name, abiMethod.type);
|
||||
} else if (abiMethod.type == "fallback") {
|
||||
} else if (abiMethod.type === "fallback") {
|
||||
gasMap['fallback'] = contract.gasEstimates.external[""].toString();
|
||||
return gasCb(null, name, abiMethod.type);
|
||||
} else if (
|
||||
|
|
|
@ -7,7 +7,7 @@ Handlebars.registerHelper('capitalize', function(word) {
|
|||
});
|
||||
|
||||
Handlebars.registerHelper('ifview', function(stateMutability, options) {
|
||||
let result = stateMutability == 'view' || stateMutability == 'pure' || stateMutability == 'constant';
|
||||
let result = stateMutability === 'view' || stateMutability === 'pure' || stateMutability === 'constant';
|
||||
if (result) {
|
||||
return options.fn(this);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ Handlebars.registerHelper('ifview', function(stateMutability, options) {
|
|||
});
|
||||
|
||||
Handlebars.registerHelper('ifeq', function(elem, value, options){
|
||||
if (elem == value) {
|
||||
if (elem === value) {
|
||||
return options.fn(this);
|
||||
}
|
||||
return options.inverse(this);
|
||||
|
@ -34,8 +34,8 @@ Handlebars.registerHelper('emptyname', function(name, index) {
|
|||
|
||||
|
||||
Handlebars.registerHelper('methodname', function(abiDefinition, functionName, inputs){
|
||||
let funCount = abiDefinition.filter(x => x.name == functionName).length;
|
||||
if(funCount == 1){
|
||||
let funCount = abiDefinition.filter(x => x.name === functionName).length;
|
||||
if(funCount === 1){
|
||||
return '.' + functionName;
|
||||
}
|
||||
return new Handlebars.SafeString(`['${functionName}(${inputs !== null ? inputs.map(input => input.type).join(',') : ''})']`);
|
||||
|
@ -73,7 +73,7 @@ class ScaffoldingReact {
|
|||
});
|
||||
}
|
||||
|
||||
async build(contract){
|
||||
build(contract){
|
||||
this._buildHTML(contract);
|
||||
|
||||
const filename = contract.className.toLowerCase();
|
||||
|
@ -82,7 +82,7 @@ class ScaffoldingReact {
|
|||
{
|
||||
'title': contract.className,
|
||||
'contractName': contract.className,
|
||||
'functions': contract.abiDefinition.filter(x => x.type == 'function')
|
||||
'functions': contract.abiDefinition.filter(x => x.type === 'function')
|
||||
});
|
||||
|
||||
// Update config
|
||||
|
|
|
@ -22,7 +22,6 @@ class Solidity {
|
|||
}
|
||||
let self = this;
|
||||
let input = {};
|
||||
let solcW;
|
||||
let originalFilepath = {};
|
||||
|
||||
async.waterfall([
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,75 +1,82 @@
|
|||
import React from 'react';
|
||||
import ContractContext from './contract-context';
|
||||
import CardAlert from './card-alert';
|
||||
|
||||
class AccountList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
error: false,
|
||||
errorMessage: "",
|
||||
accounts: []
|
||||
};
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
error: false,
|
||||
errorMessage: "",
|
||||
accounts: []
|
||||
};
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.handleCopyClick = this.handleCopyClick.bind(this);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.handleCopyClick = this.handleCopyClick.bind(this);
|
||||
}
|
||||
|
||||
|
||||
handleClick(e, updateAccountsCallback) {
|
||||
e.preventDefault();
|
||||
|
||||
try {
|
||||
updateAccountsCallback();
|
||||
} catch (err) {
|
||||
this.setState({
|
||||
error: true,
|
||||
errorMessage: e.name + ': ' + e.message
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async handleClick(e, updateAccountsCallback){
|
||||
e.preventDefault();
|
||||
handleCopyClick(e) {
|
||||
e.preventDefault();
|
||||
|
||||
try {
|
||||
updateAccountsCallback();
|
||||
} catch(err) {
|
||||
this.setState({
|
||||
error: true,
|
||||
errorMessage: e.name + ': ' + e.message
|
||||
})
|
||||
}
|
||||
var dummy = document.createElement("input");
|
||||
document.body.appendChild(dummy);
|
||||
dummy.setAttribute('value', "await web3.eth.getAccounts();");
|
||||
dummy.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(dummy);
|
||||
}
|
||||
|
||||
}
|
||||
render() {
|
||||
return <ContractContext.Consumer>
|
||||
{(context) => (
|
||||
|
||||
handleCopyClick(e){
|
||||
e.preventDefault();
|
||||
|
||||
var dummy = document.createElement("input");
|
||||
document.body.appendChild(dummy);
|
||||
dummy.setAttribute('value', "await web3.eth.getAccounts();");
|
||||
dummy.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(dummy);
|
||||
}
|
||||
|
||||
render(){
|
||||
return <ContractContext.Consumer>
|
||||
{(context) => (
|
||||
|
||||
<div className="card function">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">Get Accounts</h3>
|
||||
<div className="card-options">
|
||||
<a href="#" onClick={this.handleCopyClick} title="Copy to clipboard"><i className="fe fe-copy"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<CardAlert show={this.state.error} message={this.state.errorMessage} />
|
||||
<div className="card-body row">
|
||||
<div className="col-md-11">
|
||||
<code>
|
||||
await web3.eth.getAccounts();
|
||||
<input type="text" id="accountsTxt" />
|
||||
</code>
|
||||
</div>
|
||||
<div className="col-md-1">
|
||||
<button className="btn btn-primary ml-auto" onClick={event => this.handleClick(event, context.updateAccounts)}>⏎</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-footer">
|
||||
<p><tt>accounts</tt> variable is available in the console</p>
|
||||
<ul>
|
||||
{
|
||||
context.accounts.map((account, i) => <li key={i}>{account}</li>)
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="card function">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">Get Accounts</h3>
|
||||
<div className="card-options">
|
||||
<a href="#" onClick={this.handleCopyClick} title="Copy to clipboard"><i className="fe fe-copy"></i></a>
|
||||
</div>
|
||||
)}
|
||||
</ContractContext.Consumer>;
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<CardAlert show={this.state.error} message={this.state.errorMessage}/>
|
||||
<div className="card-body row">
|
||||
<div className="col-md-11">
|
||||
<code>
|
||||
await web3.eth.getAccounts();
|
||||
<input type="text" id="accountsTxt"/>
|
||||
</code>
|
||||
</div>
|
||||
<div className="col-md-1">
|
||||
<button className="btn btn-primary ml-auto"
|
||||
onClick={event => this.handleClick(event, context.updateAccounts)}>⏎</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-footer">
|
||||
<p><tt>accounts</tt> variable is available in the console</p>
|
||||
<ul>
|
||||
{
|
||||
context.accounts.map((account, i) => <li key={i}>{account}</li>)
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ContractContext.Consumer>;
|
||||
}
|
||||
}
|
||||
|
||||
export default AccountList;
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
class CardAlert extends React.Component {
|
||||
render(){
|
||||
return this.props.show ?
|
||||
<div className="card-alert alert alert-danger mb-0">
|
||||
{this.props.message}
|
||||
</div>
|
||||
:
|
||||
'';
|
||||
}
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class CardAlert extends React.Component {
|
||||
render() {
|
||||
return this.props.show ? <div className="card-alert alert alert-danger mb-0">{this.props.message}</div> : '';
|
||||
}
|
||||
}
|
||||
|
||||
CardAlert.propTypes = {
|
||||
show: PropTypes.bool,
|
||||
message: PropTypes.string
|
||||
};
|
||||
|
||||
|
||||
export default CardAlert;
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
const ContractContext = React.createContext({
|
||||
accounts: [],
|
||||
instances: [],
|
||||
updateAccounts: () => {},
|
||||
updateInstances: (_instance) => {}
|
||||
import React from 'react';
|
||||
|
||||
const ContractContext = React.createContext({
|
||||
accounts: [],
|
||||
instances: [],
|
||||
updateAccounts: () => {
|
||||
},
|
||||
updateInstances: (_instance) => {
|
||||
}
|
||||
});
|
||||
|
||||
export default ContractContext;
|
||||
|
|
|
@ -1,133 +1,141 @@
|
|||
/*global web3*/
|
||||
import React from 'react';
|
||||
import ContractContext from './contract-context';
|
||||
import MenuItem from './menu-item';
|
||||
import AccountList from './account-list';
|
||||
import FunctionArea from './function-area';
|
||||
import Tab from './tab';
|
||||
import InstanceSelector from './instance-selector';
|
||||
import SourceArea from './source-area';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class ContractUI extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.updateInstances = this.updateInstances.bind(this);
|
||||
this.updateAccounts = this.updateAccounts.bind(this);
|
||||
this.handleInstanceSelection = this.handleInstanceSelection.bind(this);
|
||||
this.handleMenuClick = this.handleMenuClick.bind(this);
|
||||
|
||||
this.state = {
|
||||
accounts: [],
|
||||
instances: [],
|
||||
selectedInstance: null,
|
||||
updateAccounts: this.updateAccounts,
|
||||
updateInstances: this.updateInstances,
|
||||
selectedTab: 'deploy'
|
||||
};
|
||||
this.updateInstances = this.updateInstances.bind(this);
|
||||
this.updateAccounts = this.updateAccounts.bind(this);
|
||||
this.handleInstanceSelection = this.handleInstanceSelection.bind(this);
|
||||
this.handleMenuClick = this.handleMenuClick.bind(this);
|
||||
|
||||
if(props.contract.options.address != null){
|
||||
this.state.instances = [props.contract.options.address];
|
||||
this.state.selectedInstance = props.contract.options.address;
|
||||
}
|
||||
this.state = {
|
||||
accounts: [],
|
||||
instances: [],
|
||||
selectedInstance: null,
|
||||
updateAccounts: this.updateAccounts,
|
||||
updateInstances: this.updateInstances,
|
||||
selectedTab: 'deploy'
|
||||
};
|
||||
|
||||
if (props.contract.options.address !== null) {
|
||||
this.state.instances = [props.contract.options.address];
|
||||
this.state.selectedInstance = props.contract.options.address;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
this.updateAccounts();
|
||||
}
|
||||
componentDidMount() {
|
||||
this.updateAccounts();
|
||||
}
|
||||
|
||||
handleMenuClick(e){
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
selectedTab: e.target.getAttribute('data-target')
|
||||
});
|
||||
}
|
||||
handleMenuClick(e) {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
selectedTab: e.target.getAttribute('data-target')
|
||||
});
|
||||
}
|
||||
|
||||
async updateAccounts(){
|
||||
let accounts = await web3.eth.getAccounts();
|
||||
window.accounts = accounts;
|
||||
async updateAccounts() {
|
||||
let accounts = await web3.eth.getAccounts();
|
||||
window.accounts = accounts;
|
||||
|
||||
console.log("%cawait web3.eth.getAccounts()", 'font-weight: bold');
|
||||
console.log(accounts);
|
||||
console.log("%cawait web3.eth.getAccounts()", 'font-weight: bold');
|
||||
console.log(accounts);
|
||||
|
||||
this.setState({accounts: accounts});
|
||||
}
|
||||
this.setState({accounts: accounts});
|
||||
}
|
||||
|
||||
updateInstances(_instance){
|
||||
this.state.instances.push(_instance);
|
||||
this.setState({
|
||||
instances: this.state.instances
|
||||
});
|
||||
}
|
||||
updateInstances(_instance) {
|
||||
this.state.instances.push(_instance);
|
||||
this.setState({
|
||||
instances: this.state.instances
|
||||
});
|
||||
}
|
||||
|
||||
handleInstanceSelection(_instance){
|
||||
this.props.contract.options.address = _instance;
|
||||
this.setState({
|
||||
selectedInstance: _instance
|
||||
})
|
||||
}
|
||||
handleInstanceSelection(_instance) {
|
||||
this.props.contract.options.address = _instance;
|
||||
this.setState({
|
||||
selectedInstance: _instance
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ContractContext.Provider value={this.state}>
|
||||
<div className="row">
|
||||
<div className="col-md-3">
|
||||
<h3 className="page-title mb-5">{this.props.name}</h3>
|
||||
<div>
|
||||
<div className="list-group list-group-transparent mb-0">
|
||||
<MenuItem icon="fe-file-plus" click={this.handleMenuClick} selectedTab={this.state.selectedTab} target="deploy" text="Deployment / Utils" />
|
||||
<MenuItem icon="fe-list" click={this.handleMenuClick} selectedTab={this.state.selectedTab} target="functions" text="Functions" />
|
||||
<MenuItem icon="fe-file-text" click={this.handleMenuClick} selectedTab={this.state.selectedTab} target="contract" text="Source Code" />
|
||||
</div>
|
||||
</div>
|
||||
render() {
|
||||
return (
|
||||
<ContractContext.Provider value={this.state}>
|
||||
<div className="row">
|
||||
<div className="col-md-3">
|
||||
<h3 className="page-title mb-5">{this.props.name}</h3>
|
||||
<div>
|
||||
<div className="list-group list-group-transparent mb-0">
|
||||
<MenuItem icon="fe-file-plus" click={this.handleMenuClick} selectedTab={this.state.selectedTab}
|
||||
target="deploy" text="Deployment / Utils"/>
|
||||
<MenuItem icon="fe-list" click={this.handleMenuClick} selectedTab={this.state.selectedTab}
|
||||
target="functions" text="Functions"/>
|
||||
<MenuItem icon="fe-file-text" click={this.handleMenuClick} selectedTab={this.state.selectedTab}
|
||||
target="contract" text="Source Code"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-9">
|
||||
<Tab id="deploy" selectedTab={this.state.selectedTab}>
|
||||
<h4 className="mb-5">Deployment Utils</h4>
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<ul>
|
||||
<li>Open your browser's console: <code>Tools > Developer Tools</code></li>
|
||||
<li>Remix: <a href="https://remix.ethereum.org" target="_blank" rel="noopener noreferrer">http://remix.ethereum.org</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="col-md-9">
|
||||
<Tab id="deploy" selectedTab={this.state.selectedTab}>
|
||||
<h4 className="mb-5">Deployment Utils</h4>
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<ul>
|
||||
<li>Open your browser's console: <code>Tools > Developer Tools</code></li>
|
||||
<li>Remix: <a href="https://remix.ethereum.org" target="_blank">http://remix.ethereum.org</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<AccountList accountUpdate={this.updateAccounts} />
|
||||
<h5>Deploy</h5>
|
||||
{
|
||||
this.props.definition.code == "" ? <p>Interface or set to not deploy</p>: ""
|
||||
}
|
||||
<FunctionArea definition={this.props.definition} contractName={this.props.name} contract={this.props.contract} type="constructor" />
|
||||
</Tab>
|
||||
</div>
|
||||
<AccountList accountUpdate={this.updateAccounts}/>
|
||||
<h5>Deploy</h5>
|
||||
{
|
||||
this.props.definition.code === "" ? <p>Interface or set to not deploy</p> : ""
|
||||
}
|
||||
<FunctionArea definition={this.props.definition} contractName={this.props.name}
|
||||
contract={this.props.contract} type="constructor"/>
|
||||
</Tab>
|
||||
|
||||
<Tab id="functions" selectedTab={this.state.selectedTab}>
|
||||
<h4 className="mb-5">Functions</h4>
|
||||
{
|
||||
this.props.definition.code != "" ?
|
||||
<InstanceSelector selectedInstance={this.state.selectedInstance} instanceUpdate={this.handleInstanceSelection} />
|
||||
: ""
|
||||
}
|
||||
<FunctionArea definition={this.props.definition} contractName={this.props.name} contract={this.props.contract} type="function" />
|
||||
<FunctionArea definition={this.props.definition} contractName={this.props.name} contract={this.props.contract} type="fallback" />
|
||||
</Tab>
|
||||
<Tab id="functions" selectedTab={this.state.selectedTab}>
|
||||
<h4 className="mb-5">Functions</h4>
|
||||
{(this.props.definition.code !== "") && <InstanceSelector selectedInstance={this.state.selectedInstance}
|
||||
instanceUpdate={this.handleInstanceSelection}/>
|
||||
}
|
||||
<FunctionArea definition={this.props.definition} contractName={this.props.name}
|
||||
contract={this.props.contract} type="function"/>
|
||||
<FunctionArea definition={this.props.definition} contractName={this.props.name}
|
||||
contract={this.props.contract} type="fallback"/>
|
||||
</Tab>
|
||||
|
||||
<Tab id="contract" selectedTab={this.state.selectedTab}>
|
||||
<h4 className="mb-5">Source Code</h4>
|
||||
<SourceArea definition={this.props.definition} source={this.props.source} />
|
||||
</Tab>
|
||||
</div>
|
||||
</div>,
|
||||
<Tab id="contract" selectedTab={this.state.selectedTab}>
|
||||
<h4 className="mb-5">Source Code</h4>
|
||||
<SourceArea definition={this.props.definition} source={this.props.source}/>
|
||||
</Tab>
|
||||
</div>
|
||||
</div>
|
||||
,
|
||||
|
||||
|
||||
</ContractContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ContractUI.propTypes = {
|
||||
definition: PropTypes.object,
|
||||
source: PropTypes.string,
|
||||
contract: PropTypes.object,
|
||||
name: PropTypes.string
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ContractContext.Provider>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default ContractUI;
|
||||
|
|
|
@ -1,20 +1,36 @@
|
|||
class FunctionArea extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { };
|
||||
}
|
||||
import React from 'react';
|
||||
import FunctionForm from './function-form';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
render(){
|
||||
const type = this.props.type;
|
||||
const contract = this.props.contract;
|
||||
const contractName = this.props.contractName;
|
||||
|
||||
return <React.Fragment>
|
||||
{
|
||||
this.props.contract.options.jsonInterface
|
||||
.filter(item => item.type == type)
|
||||
.map((item, i) => <FunctionForm definition={this.props.definition} key={i} contract={contract} contractName={contractName} abi={item} instanceUpdate={this.props.instanceUpdate} />)
|
||||
}
|
||||
</React.Fragment>;
|
||||
}
|
||||
class FunctionArea extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
render() {
|
||||
const type = this.props.type;
|
||||
const contract = this.props.contract;
|
||||
const contractName = this.props.contractName;
|
||||
|
||||
return <React.Fragment>
|
||||
{
|
||||
this.props.contract.options.jsonInterface
|
||||
.filter(item => item.type === type)
|
||||
.map((item, i) => <FunctionForm definition={this.props.definition} key={i} contract={contract}
|
||||
contractName={contractName} abi={item}
|
||||
instanceUpdate={this.props.instanceUpdate}/>)
|
||||
}
|
||||
</React.Fragment>;
|
||||
}
|
||||
}
|
||||
|
||||
FunctionArea.propTypes = {
|
||||
type: PropTypes.string,
|
||||
contract: PropTypes.object,
|
||||
contractName: PropTypes.string,
|
||||
definition: PropTypes.object,
|
||||
instanceUpdate: PropTypes.func
|
||||
};
|
||||
|
||||
export default FunctionArea;
|
||||
|
|
|
@ -1,136 +1,159 @@
|
|||
import React from 'react';
|
||||
import CardAlert from './card-alert';
|
||||
import Function from './function';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class FunctionForm extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
fields: {},
|
||||
error: false,
|
||||
message: null,
|
||||
receipt: null
|
||||
};
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
fields: {},
|
||||
error: false,
|
||||
message: null,
|
||||
receipt: null
|
||||
};
|
||||
|
||||
this.child = React.createRef();
|
||||
this.child = React.createRef();
|
||||
|
||||
this.showResults = this.showResults.bind(this);
|
||||
this.handleCopyClick = this.handleCopyClick.bind(this);
|
||||
this.showResults = this.showResults.bind(this);
|
||||
this.handleCopyClick = this.handleCopyClick.bind(this);
|
||||
}
|
||||
|
||||
handleCopyClick(e) {
|
||||
this.child.current.copyCommand(e);
|
||||
}
|
||||
|
||||
_getFunctionParamFields(_elem) {
|
||||
if (this.props.abi.type === 'fallback') return '';
|
||||
|
||||
return '(' + this.props.abi.inputs
|
||||
.map((input, i) => <input type="text" data-var-type={input.type} data-type="inputParam" data-name={input.name}
|
||||
placeholder={input.name} title={input.type + ' ' + input.name}
|
||||
size={input.name.length}
|
||||
key={'input' + i}/>)
|
||||
.join(', ') + ')';
|
||||
}
|
||||
|
||||
_getMethodType(_elem) {
|
||||
return (this.props.abi.constant === true || this.props.abi.stateMutability === 'view' || this.props.abi.stateMutability === 'pure') ? 'call' : 'send';
|
||||
}
|
||||
|
||||
renderContent(receipt, contract) {
|
||||
if (receipt === null && (this.state.error || this.state.message === null)) {
|
||||
return '';
|
||||
}
|
||||
let messagesList;
|
||||
if (this.props.abi.outputs.filter(x => x.name !== "").length > 0) {
|
||||
messagesList = Object.keys(this.state.message).map((key, index) => {
|
||||
if (isNaN(key)) {
|
||||
return <li key={index}>{key}: {this.state.message[key]}</li>;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
} else {
|
||||
messagesList = Object.keys(this.state.message).map((key, index) => {
|
||||
return <li key={index}>{key}: {this.state.message[key]}</li>;
|
||||
});
|
||||
}
|
||||
|
||||
handleCopyClick(e){
|
||||
this.child.current.copyCommand(e);
|
||||
let message;
|
||||
if (this.state.message !== null && typeof this.state.message === 'object') {
|
||||
message = <ul>
|
||||
{messagesList}
|
||||
</ul>;
|
||||
} else if (typeof this.state.message === "boolean") {
|
||||
message = (this.state.message ? 'true' : 'false');
|
||||
} else {
|
||||
message = this.state.message;
|
||||
}
|
||||
|
||||
_getFunctionParamFields(elem){
|
||||
if(this.props.abi.type == 'fallback') return '';
|
||||
|
||||
return '(' + this.props.abi.inputs
|
||||
.map((input, i) => <input type="text" data-var-type={input.type} data-type="inputParam" data-name={input.name} placeholder={input.name} title={input.type + ' ' + input.name} size={input.name.length} />)
|
||||
.join(', ') + ')';
|
||||
}
|
||||
|
||||
_getMethodType(elem){
|
||||
return (this.props.abi.constant == true || this.props.abi.stateMutability == 'view' || this.props.abi.stateMutability == 'pure') ? 'call' : 'send';
|
||||
}
|
||||
|
||||
render(){
|
||||
const functionName = this.props.abi.name;
|
||||
const isDuplicated = this.props.contract.options.jsonInterface.filter(x => x.name == functionName).length > 1;
|
||||
const contract = this.props.contract;
|
||||
const receipt = this.state.receipt;
|
||||
|
||||
return <div className="card function">
|
||||
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">{this.props.abi.type == 'function' ? this.props.abi.name : (this.props.abi.type == 'fallback' ? '(fallback)' : this.props.abi.name)}</h3>
|
||||
<div className="card-options">
|
||||
<a href="#" onClick={this.handleCopyClick} title="Copy to clipboard"><i className="fe fe-copy"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CardAlert show={this.state.error} message={this.state.message} />
|
||||
|
||||
<div className="card-body row">
|
||||
<Function ref={this.child} definition={this.props.definition} contract={this.props.contract} contractName={this.props.contractName} duplicated={isDuplicated} abi={this.props.abi} resultHandler={this.showResults} />
|
||||
</div>
|
||||
{
|
||||
receipt != null || !this.state.error && this.state.message != null
|
||||
?
|
||||
<div className="card-footer">
|
||||
{ receipt != null ?
|
||||
<ul>
|
||||
<li>Status: {receipt.status}</li>
|
||||
<li>Transaction Hash: {receipt.transactionHash}</li>
|
||||
{
|
||||
receipt.events != null ?
|
||||
<li>Events:
|
||||
<ul>
|
||||
{
|
||||
Object.keys(receipt.events).map(function(ev, index) {
|
||||
if(!isNaN(ev)) return null;
|
||||
const eventAbi = contract.options.jsonInterface.filter(x => x.name == ev)[0];
|
||||
let props = [];
|
||||
for(let prop in receipt.events[ev].returnValues){
|
||||
if(isNaN(prop)){
|
||||
let input = eventAbi.inputs.filter(x => x.name == prop)[0];
|
||||
props.push(prop + ': '
|
||||
+ (input.type.indexOf('int') == -1 ? '"' : '')
|
||||
+ receipt.events[ev].returnValues[prop]
|
||||
+ (input.type.indexOf('int') == -1 ? '"' : ''));
|
||||
}
|
||||
}
|
||||
return <li key={index}>{ev}({props.join(', ')})</li>;
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</li>
|
||||
: ''
|
||||
return (<div className="card-footer">
|
||||
{receipt && <ul>
|
||||
<li>Status: {receipt.status}</li>
|
||||
<li>Transaction Hash: {receipt.transactionHash}</li>
|
||||
{
|
||||
receipt.events && <li>Events:
|
||||
<ul>
|
||||
{
|
||||
Object.keys(receipt.events).map(function(ev, index) {
|
||||
if (!isNaN(ev)) return null;
|
||||
const eventAbi = contract.options.jsonInterface.filter(x => x.name === ev)[0];
|
||||
let props = [];
|
||||
for (let prop in receipt.events[ev].returnValues) {
|
||||
if (isNaN(prop)) {
|
||||
let input = eventAbi.inputs.filter(x => x.name === prop)[0];
|
||||
props.push(prop + ': ' +
|
||||
(input.type.indexOf('int') === -1 ? '"' : '') +
|
||||
receipt.events[ev].returnValues[prop] +
|
||||
(input.type.indexOf('int') === -1 ? '"' : ''));
|
||||
}
|
||||
</ul>
|
||||
: ""
|
||||
}
|
||||
{
|
||||
!this.state.error && this.state.message != null
|
||||
?
|
||||
<React.Fragment>{
|
||||
(this.state.message !== null && typeof this.state.message === 'object')
|
||||
?
|
||||
(
|
||||
<ul>
|
||||
{
|
||||
this.props.abi.outputs.filter(x => x.name !== "").length > 0
|
||||
?
|
||||
Object.keys(this.state.message).map((key, index) => {
|
||||
if(isNaN(key)){
|
||||
return <li key={index}>{key}: {this.state.message[key]}</li>
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
})
|
||||
:
|
||||
Object.keys(this.state.message).map((key, index) => {
|
||||
return <li key={index}>{key}: {this.state.message[key]}</li>
|
||||
})
|
||||
|
||||
}
|
||||
</ul>
|
||||
)
|
||||
:
|
||||
(typeof this.state.message === "boolean" ?
|
||||
(this.state.message ? 'true' : 'false')
|
||||
:
|
||||
this.state.message)
|
||||
}</React.Fragment>
|
||||
: '' }
|
||||
|
||||
</div>
|
||||
: ''
|
||||
}
|
||||
</div>;
|
||||
}
|
||||
return <li key={index}>{ev}({props.join(', ')})</li>;
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
{
|
||||
!this.state.error && this.state.message && <React.Fragment>
|
||||
{message}
|
||||
</React.Fragment>}
|
||||
|
||||
</div>);
|
||||
}
|
||||
|
||||
render() {
|
||||
const functionName = this.props.abi.name;
|
||||
const isDuplicated = this.props.contract.options.jsonInterface.filter(x => x.name === functionName).length > 1;
|
||||
const contract = this.props.contract;
|
||||
const receipt = this.state.receipt;
|
||||
let title;
|
||||
if (this.props.abi.type === 'function') {
|
||||
title = this.props.abi.name;
|
||||
} else if (this.props.abi.type === 'fallback') {
|
||||
title = '(fallback)';
|
||||
} else {
|
||||
title = this.props.abi.name;
|
||||
}
|
||||
|
||||
showResults(_error, _message, _receipt){
|
||||
this.setState({
|
||||
error: _error,
|
||||
message: _message,
|
||||
receipt: _receipt
|
||||
})
|
||||
}
|
||||
}
|
||||
return <div className="card function">
|
||||
|
||||
<div className="card-header">
|
||||
<h3
|
||||
className="card-title">{title}</h3>
|
||||
<div className="card-options">
|
||||
<a href="#" onClick={this.handleCopyClick} title="Copy to clipboard"><i className="fe fe-copy"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CardAlert show={this.state.error} message={this.state.message}/>
|
||||
|
||||
<div className="card-body row">
|
||||
<Function ref={this.child} definition={this.props.definition} contract={this.props.contract}
|
||||
contractName={this.props.contractName} duplicated={isDuplicated} abi={this.props.abi}
|
||||
resultHandler={this.showResults}/>
|
||||
</div>
|
||||
{this.renderContent(receipt, contract)}
|
||||
</div>;
|
||||
}
|
||||
|
||||
showResults(_error, _message, _receipt) {
|
||||
this.setState({
|
||||
error: _error,
|
||||
message: _message,
|
||||
receipt: _receipt
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
FunctionForm.propTypes = {
|
||||
abi: PropTypes.object,
|
||||
contract: PropTypes.object,
|
||||
definition: PropTypes.object,
|
||||
contractName: PropTypes.string
|
||||
};
|
||||
|
||||
export default FunctionForm;
|
||||
|
|
|
@ -1,272 +1,271 @@
|
|||
/*global web3*/
|
||||
import React from 'react';
|
||||
import ContractContext from './contract-context';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class Function extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
onRequest: false,
|
||||
fields: {},
|
||||
methodFields: {
|
||||
from: '',
|
||||
to: '',
|
||||
value: 0,
|
||||
data: '',
|
||||
gasLimit: '7000000'
|
||||
},
|
||||
receipt: null
|
||||
};
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
onRequest: false,
|
||||
fields: {},
|
||||
methodFields: {
|
||||
from: '',
|
||||
to: '',
|
||||
value: 0,
|
||||
data: '',
|
||||
gasLimit: '7000000'
|
||||
},
|
||||
receipt: null
|
||||
};
|
||||
|
||||
this.handleParameterChange = this.handleParameterChange.bind(this);
|
||||
this.handleMethodFieldChange = this.handleMethodFieldChange.bind(this);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.handleParameterChange = this.handleParameterChange.bind(this);
|
||||
this.handleMethodFieldChange = this.handleMethodFieldChange.bind(this);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
|
||||
copyCommand(e) {
|
||||
e.preventDefault();
|
||||
|
||||
let functionLabel = this._getFunctionLabel();
|
||||
let functionParams = this._getFunctionParamString();
|
||||
let methodParams = this._getMethodString();
|
||||
if (this.props.abi.type === "constructor") functionParams = `{arguments: [${functionParams}]}`;
|
||||
|
||||
const command = `await ${functionLabel}(${functionParams})${this.props.abi.type !== 'fallback' ? '.' + this._getMethodType() : ''}${methodParams}`;
|
||||
|
||||
var dummy = document.createElement("input");
|
||||
document.body.appendChild(dummy);
|
||||
dummy.setAttribute('value', command);
|
||||
dummy.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(dummy);
|
||||
}
|
||||
|
||||
|
||||
async handleClick(e, instanceUpdateCallback) {
|
||||
e.preventDefault();
|
||||
|
||||
this.setState({onRequest: true, receipt: null});
|
||||
|
||||
this.props.resultHandler(false, null, null);
|
||||
|
||||
let executionParams = {
|
||||
from: this.state.methodFields.from,
|
||||
gasLimit: this.state.methodFields.gasLimit
|
||||
};
|
||||
|
||||
if (this.props.abi.payable) executionParams.value = this.state.methodFields.value;
|
||||
|
||||
if (this.props.abi.type === 'fallback') {
|
||||
executionParams.data = this.state.methodFields.data;
|
||||
executionParams.to = this.props.contract.options.address;
|
||||
}
|
||||
|
||||
let fields = this.state.fields;
|
||||
|
||||
copyCommand(e){
|
||||
e.preventDefault();
|
||||
let functionLabel = this._getFunctionLabel();
|
||||
let functionParams = this._getFunctionParamString();
|
||||
let methodParams = this._getMethodString();
|
||||
if (this.props.abi.type === "constructor") functionParams = `{arguments: [${functionParams}]}`;
|
||||
|
||||
let fields = this.state.fields;
|
||||
console.log(`%cawait ${functionLabel}(${functionParams})${this.props.abi.type !== 'fallback' ? '.' + this._getMethodType() : ''}${methodParams}`, 'font-weight: bold');
|
||||
|
||||
let functionLabel = this._getFunctionLabel();
|
||||
let functionParams = this._getFunctionParamString();
|
||||
let methodParams = this._getMethodString();
|
||||
if(this.props.abi.type == "constructor")
|
||||
functionParams = `{arguments: [${functionParams}]}`;
|
||||
let _receipt;
|
||||
|
||||
const command = `await ${functionLabel}(${functionParams})${this.props.abi.type != 'fallback' ? '.' + this._getMethodType() : ''}${methodParams}`;
|
||||
try {
|
||||
if (this.props.abi.type === 'constructor') {
|
||||
let contractInstance = await this.props.contract.deploy({arguments: Object.keys(fields).map(val => fields[val])}).send(executionParams);
|
||||
instanceUpdateCallback(contractInstance.options.address);
|
||||
this.setState({onRequest: false});
|
||||
console.log(contractInstance.options.address);
|
||||
this.props.resultHandler(false, 'New instance: ' + contractInstance.options.address);
|
||||
} else {
|
||||
|
||||
var dummy = document.createElement("input");
|
||||
document.body.appendChild(dummy);
|
||||
dummy.setAttribute('value', command);
|
||||
dummy.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(dummy);
|
||||
}
|
||||
if (this.props.abi.type === 'fallback') _receipt = await web3.eth.sendTransaction(executionParams);
|
||||
else _receipt = await this.props.contract
|
||||
.methods[this.props.abi.name + '(' + this.props.abi.inputs.map(input => input.type).join(',') + ')']
|
||||
.apply(null, Object.keys(fields).map(val => {
|
||||
let input = this.props.abi.inputs.filter(x => x.name === val)[0];
|
||||
return input.type.indexOf('bool') === -1 ? fields[val] : (fields[val].toLowerCase() === 'true');
|
||||
}))[this._getMethodType()](executionParams);
|
||||
|
||||
|
||||
|
||||
async handleClick(e, instanceUpdateCallback){
|
||||
e.preventDefault();
|
||||
|
||||
this.setState({onRequest: true, receipt: null});
|
||||
|
||||
this.props.resultHandler(false, null, null);
|
||||
|
||||
let executionParams = {
|
||||
from: this.state.methodFields.from,
|
||||
gasLimit: this.state.methodFields.gasLimit
|
||||
}
|
||||
|
||||
if(this.props.abi.payable)
|
||||
executionParams.value = this.state.methodFields.value;
|
||||
|
||||
if(this.props.abi.type == 'fallback'){
|
||||
executionParams.data = this.state.methodFields.data;
|
||||
executionParams.to = this.props.contract.options.address;
|
||||
}
|
||||
|
||||
let fields = this.state.fields;
|
||||
|
||||
let functionLabel = this._getFunctionLabel();
|
||||
let functionParams = this._getFunctionParamString();
|
||||
let methodParams = this._getMethodString();
|
||||
if(this.props.abi.type == "constructor")
|
||||
functionParams = `{arguments: [${functionParams}]}`;
|
||||
|
||||
console.log(`%cawait ${functionLabel}(${functionParams})${this.props.abi.type != 'fallback' ? '.' + this._getMethodType() : ''}${methodParams}`, 'font-weight: bold');
|
||||
|
||||
let _receipt;
|
||||
|
||||
try {
|
||||
if(this.props.abi.type == 'constructor'){
|
||||
let contractInstance = await this.props.contract.deploy({arguments: Object.keys(fields).map(val => fields[val])}).send(executionParams);
|
||||
instanceUpdateCallback(contractInstance.options.address);
|
||||
this.setState({onRequest: false});
|
||||
console.log(contractInstance.options.address);
|
||||
this.props.resultHandler(false, 'New instance: ' + contractInstance.options.address);
|
||||
} else {
|
||||
|
||||
if(this.props.abi.type == 'fallback')
|
||||
_receipt = await web3.eth.sendTransaction(executionParams);
|
||||
else
|
||||
_receipt = await this.props.contract
|
||||
.methods[this.props.abi.name + '(' + this.props.abi.inputs.map(input => input.type).join(',') + ')']
|
||||
.apply(null, Object.keys(fields).map(val => {
|
||||
let input = this.props.abi.inputs.filter(x => x.name == val)[0];
|
||||
return input.type.indexOf('bool') == -1 ? fields[val] : (fields[val].toLowerCase() === 'true')
|
||||
}))
|
||||
[this._getMethodType()](executionParams)
|
||||
|
||||
if(this._getMethodType() == 'call'){
|
||||
this.props.resultHandler(false, _receipt, null);
|
||||
} else {
|
||||
this.props.resultHandler(false, null, _receipt);
|
||||
}
|
||||
|
||||
this.setState({onRequest: false, receipt: _receipt});
|
||||
console.log(_receipt);
|
||||
}
|
||||
|
||||
|
||||
} catch (e) {
|
||||
console.error('%s: %s', e.name, e.message);
|
||||
this.setState({onRequest: false});
|
||||
this.props.resultHandler(true, e.name + ": " + e.message, _receipt);
|
||||
}
|
||||
}
|
||||
|
||||
handleParameterChange(e){
|
||||
let newState = this.state;
|
||||
newState.fields[e.target.getAttribute('data-name')] = e.target.value;
|
||||
this.setState(newState);
|
||||
}
|
||||
|
||||
handleMethodFieldChange(e){
|
||||
let newState = this.state;
|
||||
newState.methodFields[e.target.getAttribute('data-param')] = e.target.value;
|
||||
|
||||
if(e.target.getAttribute('data-param') == 'from'){
|
||||
newState.selectedAccount = e.target.options[e.target.selectedIndex].text;
|
||||
}
|
||||
this.setState(newState);
|
||||
}
|
||||
|
||||
_getFunctionLabel(){
|
||||
if(this.props.abi.type == 'function')
|
||||
if(!this.props.duplicated)
|
||||
return `${this.props.contractName}.methods.${this.props.abi.name}`;
|
||||
else {
|
||||
return `${this.props.contractName}.methods['${this.props.abi.name + '(' + (this.props.abi.inputs != null ? this.props.abi.inputs.map(input => input.type).join(',') : '') + ')'}']`;
|
||||
}
|
||||
else if(this.props.abi.type == 'fallback'){
|
||||
return `web3.eth.sendTransaction`;
|
||||
}
|
||||
else
|
||||
return `${this.props.contractName}.deploy`;
|
||||
}
|
||||
|
||||
_getMethodType(){
|
||||
return (this.props.abi.constant == true || this.props.abi.stateMutability == 'view' || this.props.abi.stateMutability == 'pure') ? 'call' : 'send';
|
||||
}
|
||||
|
||||
_getMethodFields(accounts){
|
||||
let methodParams;
|
||||
return <React.Fragment>
|
||||
from: <select data-param="from" disabled={accounts.length == 0} value={this.state.from} onChange={this.handleMethodFieldChange}>
|
||||
<option>-</option>
|
||||
{
|
||||
accounts.map(function (item, i) {
|
||||
return <option key={i} value={item}>{`accounts[${i}]`}</option>;
|
||||
})
|
||||
}
|
||||
</select>
|
||||
{
|
||||
this.props.abi.payable ?
|
||||
<span>, value:
|
||||
<input type="text" data-param="value" value={this.state.methodFields.value} size="6" onChange={this.handleMethodFieldChange} />
|
||||
</span>
|
||||
: ''
|
||||
}
|
||||
{
|
||||
this._getMethodType() == 'send' ?
|
||||
<span>, gasLimit:
|
||||
<input type="text" data-param="gasLimit" value={this.state.methodFields.gasLimit} size="6" onChange={this.handleMethodFieldChange} />
|
||||
</span>
|
||||
: ''
|
||||
}
|
||||
{
|
||||
this._getMethodType() == 'send' && this.props.abi.type == 'fallback' ?
|
||||
<span>, data:
|
||||
<input type="text" data-param="data" value={this.state.methodFields.data} size="6" onChange={this.handleMethodFieldChange} />
|
||||
</span>
|
||||
: ''
|
||||
}
|
||||
</React.Fragment>;
|
||||
}
|
||||
|
||||
|
||||
_getFunctionParamFields(){
|
||||
return <React.Fragment>
|
||||
{
|
||||
this.props.abi.inputs
|
||||
.map((input, i) => <input key={i} type="text" data-var-type={input.type} data-type="inputParam" data-name={input.name} placeholder={input.name} title={input.type + ' ' + input.name} size={input.name.length} value={this.state.fields[input.name] || ''} onChange={this.handleParameterChange} />)
|
||||
.reduce((accu, elem) => {
|
||||
return accu === null ? [elem] : [...accu, ', ', elem]
|
||||
}, null)
|
||||
}
|
||||
</React.Fragment>;
|
||||
}
|
||||
|
||||
_getFunctionParamString(){
|
||||
if(this.props.abi.type == 'fallback') return '';
|
||||
return this.props.abi.inputs
|
||||
.map((input, i) => (input.type.indexOf('int') == -1 && input.type.indexOf('bool') == -1 ? '"' : '') + (this.state.fields[input.name] || (input.type.indexOf('int') == -1 ? '' : '0')) + (input.type.indexOf('int') == -1 ? '"' : ''))
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
_getMethodString(elem){
|
||||
let methodParams = "({";
|
||||
|
||||
methodParams += `from: ` + (this.state.selectedAccount || '"0x00"');
|
||||
if(this._getMethodType() == 'send'){
|
||||
methodParams += ', gasLimit: ' + (this.state.methodFields.gasLimit || 0)
|
||||
if(this.props.abi.payable){
|
||||
methodParams += ', value: ' + (this.state.methodFields.value || 0)
|
||||
}
|
||||
if(this.props.abi.type == 'fallback'){
|
||||
methodParams += ', data: "' + (this.state.methodFields.data || '"0x00"' ) + '", to: "' + (this.state.methodFields.to || '"0x00"') + '"'
|
||||
}
|
||||
}
|
||||
return methodParams + "})";
|
||||
}
|
||||
|
||||
render(){
|
||||
|
||||
let btnClass = "btn ml-auto ";
|
||||
let disabled = false;
|
||||
|
||||
if(this.state.onRequest){
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
if(this.props.definition.code == ""){
|
||||
btnClass += "btn-secondary";
|
||||
disabled = true;
|
||||
if (this._getMethodType() === 'call') {
|
||||
this.props.resultHandler(false, _receipt, null);
|
||||
} else {
|
||||
btnClass += "btn-primary";
|
||||
this.props.resultHandler(false, null, _receipt);
|
||||
}
|
||||
|
||||
return <ContractContext.Consumer>
|
||||
{ (context) => (
|
||||
<React.Fragment>
|
||||
<div className="col-md-11">
|
||||
<code>
|
||||
await {this._getFunctionLabel()}
|
||||
{ this.props.abi.type != 'fallback' ? '(' : '' }
|
||||
{ this.props.abi.type != 'fallback' ? this._getFunctionParamFields() : '' }
|
||||
{ this.props.abi.type != 'fallback' ? ')' : '' }
|
||||
{ this.props.abi.type != 'fallback' ? '.' + this._getMethodType() : '' }
|
||||
({ this._getMethodFields(context.accounts) })
|
||||
</code>
|
||||
</div>
|
||||
<div className="col-md-1">
|
||||
<button className={btnClass} title={this.props.definition.code == "" ? "Can't execute function" : "Execute function"} onClick={event => this.handleClick(event, context.updateInstances)} disabled={disabled}>
|
||||
{ this.state.onRequest ?
|
||||
<img src="../assets/images/loading.gif" className="loading" alt="" />
|
||||
:
|
||||
(
|
||||
this.props.definition.code == ""
|
||||
?
|
||||
<React.Fragment>_</React.Fragment>
|
||||
:
|
||||
<React.Fragment>⏎</React.Fragment>
|
||||
)
|
||||
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</ContractContext.Consumer>;
|
||||
this.setState({onRequest: false, receipt: _receipt});
|
||||
console.log(_receipt);
|
||||
}
|
||||
|
||||
|
||||
} catch (err) {
|
||||
console.error('%s: %s', err.name, err.message);
|
||||
this.setState({onRequest: false});
|
||||
this.props.resultHandler(true, err.name + ": " + err.message, _receipt);
|
||||
}
|
||||
}
|
||||
|
||||
handleParameterChange(e) {
|
||||
let newState = this.state;
|
||||
newState.fields[e.target.getAttribute('data-name')] = e.target.value;
|
||||
this.setState(newState);
|
||||
}
|
||||
|
||||
handleMethodFieldChange(e) {
|
||||
let newState = this.state;
|
||||
newState.methodFields[e.target.getAttribute('data-param')] = e.target.value;
|
||||
|
||||
if (e.target.getAttribute('data-param') === 'from') {
|
||||
newState.selectedAccount = e.target.options[e.target.selectedIndex].text;
|
||||
}
|
||||
this.setState(newState);
|
||||
}
|
||||
|
||||
_getFunctionLabel() {
|
||||
if (this.props.abi.type === 'function') if (!this.props.duplicated) return `${this.props.contractName}.methods.${this.props.abi.name}`;
|
||||
else {
|
||||
return `${this.props.contractName}.methods['${this.props.abi.name + '(' + (this.props.abi.inputs !== null ? this.props.abi.inputs.map(input => input.type).join(',') : '') + ')'}']`;
|
||||
}
|
||||
else if (this.props.abi.type === 'fallback') {
|
||||
return `web3.eth.sendTransaction`;
|
||||
}
|
||||
else return `${this.props.contractName}.deploy`;
|
||||
}
|
||||
|
||||
_getMethodType() {
|
||||
return (this.props.abi.constant === true || this.props.abi.stateMutability === 'view' || this.props.abi.stateMutability === 'pure') ? 'call' : 'send';
|
||||
}
|
||||
|
||||
_getMethodFields(accounts) {
|
||||
return <React.Fragment>
|
||||
from: <select data-param="from" disabled={accounts.length === 0} value={this.state.from}
|
||||
onChange={this.handleMethodFieldChange}>
|
||||
<option>-</option>
|
||||
{
|
||||
accounts.map(function(item, i) {
|
||||
return <option key={i} value={item}>{`accounts[${i}]`}</option>;
|
||||
})
|
||||
}
|
||||
</select>
|
||||
{this.props.abi.payable &&
|
||||
<span>, value:
|
||||
<input type="text" data-param="value" value={this.state.methodFields.value} size="6"
|
||||
onChange={this.handleMethodFieldChange}/>
|
||||
</span>
|
||||
}
|
||||
{this._getMethodType() === 'send' &&
|
||||
<span>, gasLimit:
|
||||
<input type="text" data-param="gasLimit" value={this.state.methodFields.gasLimit} size="6"
|
||||
onChange={this.handleMethodFieldChange}/>
|
||||
</span>}
|
||||
{this._getMethodType() === 'send' && this.props.abi.type === 'fallback' &&
|
||||
<span>, data:
|
||||
<input type="text" data-param="data" value={this.state.methodFields.data} size="6"
|
||||
onChange={this.handleMethodFieldChange}/>
|
||||
</span>}
|
||||
</React.Fragment>;
|
||||
}
|
||||
|
||||
|
||||
_getFunctionParamFields() {
|
||||
return <React.Fragment>
|
||||
{
|
||||
this.props.abi.inputs
|
||||
.map((input, i) => <input key={i} type="text" data-var-type={input.type} data-type="inputParam"
|
||||
data-name={input.name} placeholder={input.name}
|
||||
title={input.type + ' ' + input.name} size={input.name.length}
|
||||
value={this.state.fields[input.name] || ''} onChange={this.handleParameterChange}/>)
|
||||
.reduce((accu, elem) => {
|
||||
return accu === null ? [elem] : [...accu, ', ', elem];
|
||||
}, null)
|
||||
}
|
||||
</React.Fragment>;
|
||||
}
|
||||
|
||||
_getFunctionParamString() {
|
||||
if (this.props.abi.type === 'fallback') return '';
|
||||
return this.props.abi.inputs
|
||||
.map((input, _i) => (input.type.indexOf('int') === -1 && input.type.indexOf('bool') === -1 ? '"' : '') + (this.state.fields[input.name] || (input.type.indexOf('int') === -1 ? '' : '0')) + (input.type.indexOf('int') === -1 ? '"' : ''))
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
_getMethodString(_elem) {
|
||||
let methodParams = "({";
|
||||
|
||||
methodParams += `from: ` + (this.state.selectedAccount || '"0x00"');
|
||||
if (this._getMethodType() === 'send') {
|
||||
methodParams += ', gasLimit: ' + (this.state.methodFields.gasLimit || 0);
|
||||
if (this.props.abi.payable) {
|
||||
methodParams += ', value: ' + (this.state.methodFields.value || 0);
|
||||
}
|
||||
if (this.props.abi.type === 'fallback') {
|
||||
methodParams += ', data: "' + (this.state.methodFields.data || '"0x00"') + '", to: "' + (this.state.methodFields.to || '"0x00"') + '"';
|
||||
}
|
||||
}
|
||||
return methodParams + "})";
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
let btnClass = "btn ml-auto ";
|
||||
let disabled = false;
|
||||
|
||||
if (this.state.onRequest) {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
}
|
||||
if (this.props.definition.code === "") {
|
||||
btnClass += "btn-secondary";
|
||||
disabled = true;
|
||||
} else {
|
||||
btnClass += "btn-primary";
|
||||
}
|
||||
|
||||
let requestResult;
|
||||
if (this.state.onRequest) {
|
||||
requestResult = <img src="../assets/images/loading.gif" className="loading" alt=""/>;
|
||||
} else {
|
||||
requestResult = this.props.definition.code === "" ? <React.Fragment>_</React.Fragment>: <React.Fragment>⏎</React.Fragment>;
|
||||
}
|
||||
|
||||
return <ContractContext.Consumer>
|
||||
{(context) => (
|
||||
<React.Fragment>
|
||||
<div className="col-md-11">
|
||||
<code>
|
||||
await {this._getFunctionLabel()}
|
||||
{this.props.abi.type !== 'fallback' ? '(' : ''}
|
||||
{this.props.abi.type !== 'fallback' ? this._getFunctionParamFields() : ''}
|
||||
{this.props.abi.type !== 'fallback' ? ')' : ''}
|
||||
{this.props.abi.type !== 'fallback' ? '.' + this._getMethodType() : ''}
|
||||
({this._getMethodFields(context.accounts)})
|
||||
</code>
|
||||
</div>
|
||||
<div className="col-md-1">
|
||||
<button className={btnClass}
|
||||
title={this.props.definition.code === "" ? "Can't execute function" : "Execute function"}
|
||||
onClick={event => this.handleClick(event, context.updateInstances)} disabled={disabled}>
|
||||
{requestResult}
|
||||
</button>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</ContractContext.Consumer>;
|
||||
}
|
||||
}
|
||||
|
||||
Function.propTypes = {
|
||||
definition: PropTypes.object,
|
||||
abi: PropTypes.object,
|
||||
contract: PropTypes.object,
|
||||
resultHandler: PropTypes.func,
|
||||
duplicated: PropTypes.bool,
|
||||
contractName: PropTypes.string
|
||||
};
|
||||
|
||||
export default Function;
|
||||
|
|
|
@ -1,130 +1,131 @@
|
|||
class InstanceSelector extends React.Component {
|
||||
import React from 'react';
|
||||
import ContractContext from './contract-context';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showInstances: false,
|
||||
showCustomAddressField: false,
|
||||
selectedInstance: props.selectedInstance,
|
||||
customInstance: "",
|
||||
error: false,
|
||||
errorMessage: ""
|
||||
};
|
||||
class InstanceSelector extends React.Component {
|
||||
|
||||
this.handleShowInstances = this.handleShowInstances.bind(this);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.handleTextChange = this.handleTextChange.bind(this);
|
||||
}
|
||||
|
||||
handleTextChange(e){
|
||||
this.setState({customInstance: e.target.value});
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showInstances: false,
|
||||
showCustomAddressField: false,
|
||||
selectedInstance: props.selectedInstance,
|
||||
customInstance: "",
|
||||
error: false,
|
||||
errorMessage: ""
|
||||
};
|
||||
|
||||
this.handleShowInstances = this.handleShowInstances.bind(this);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.handleTextChange = this.handleTextChange.bind(this);
|
||||
}
|
||||
|
||||
handleTextChange(e) {
|
||||
this.setState({customInstance: e.target.value});
|
||||
}
|
||||
|
||||
handleShowInstances(e) {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
showInstances: !this.state.showInstances
|
||||
});
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
e.preventDefault();
|
||||
|
||||
let instance;
|
||||
if (this.state.selectedInstance === "custom") {
|
||||
instance = this.state.customInstance;
|
||||
} else {
|
||||
instance = this.state.selectedInstance;
|
||||
}
|
||||
|
||||
handleShowInstances(e){
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
showInstances: !this.state.showInstances
|
||||
});
|
||||
if (!(/^0x[0-9a-f]{40}$/i).test(instance)) {
|
||||
this.setState({error: true, errorMessage: 'Not a valid Ethereum address.'});
|
||||
console.log(this.state.errorMessage);
|
||||
return;
|
||||
} else {
|
||||
this.setState({error: false});
|
||||
}
|
||||
|
||||
handleClick(e){
|
||||
e.preventDefault();
|
||||
this.props.instanceUpdate(instance);
|
||||
|
||||
let instance;
|
||||
if(this.state.selectedInstance == "custom"){
|
||||
instance = this.state.customInstance;
|
||||
} else {
|
||||
instance = this.state.selectedInstance;
|
||||
}
|
||||
this.setState({
|
||||
showInstances: false,
|
||||
showCustomAddressField: false,
|
||||
selectedInstance: instance,
|
||||
customInstance: this.state.selectedInstance === "custom" ? this.state.customInstance : ""
|
||||
});
|
||||
}
|
||||
|
||||
if(!/^0x[0-9a-f]{40}$/i.test(instance)){
|
||||
this.setState({error: true, errorMessage: 'Not a valid Ethereum address.'});
|
||||
console.log(this.state.errorMessage);
|
||||
return;
|
||||
} else {
|
||||
this.setState({error: false});
|
||||
}
|
||||
handleChange(e) {
|
||||
this.setState({
|
||||
showCustomAddressField: e.target.value === "custom",
|
||||
selectedInstance: e.target.value
|
||||
});
|
||||
}
|
||||
|
||||
this.props.instanceUpdate(instance);
|
||||
|
||||
this.setState({
|
||||
showInstances: false,
|
||||
showCustomAddressField: false,
|
||||
selectedInstance: instance,
|
||||
customInstance: this.state.selectedInstance == "custom" ? this.state.customInstance : ""
|
||||
})
|
||||
render() {
|
||||
let showInstance;
|
||||
if (!this.state.showInstances) {
|
||||
showInstance = <a href="#" className="btn btn-primary btn-sm" onClick={this.handleShowInstances}>Change</a>;
|
||||
} else {
|
||||
showInstance = <a href="#" className="btn btn-secondary btn-sm" onClick={this.handleShowInstances}>Cancel</a>;
|
||||
}
|
||||
|
||||
handleChange(e){
|
||||
this.setState({
|
||||
showCustomAddressField: e.target.value == "custom",
|
||||
selectedInstance: e.target.value
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
|
||||
return <ContractContext.Consumer>
|
||||
{ (context) => (<div className="contractSelection">
|
||||
|
||||
|
||||
|
||||
<div className="card">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">
|
||||
Instance Selected: <b>{this.props.selectedInstance != null ? this.props.selectedInstance : 'none'}</b>
|
||||
</h3>
|
||||
<div className="card-options">
|
||||
{
|
||||
!this.state.showInstances
|
||||
?
|
||||
<a href="#" className="btn btn-primary btn-sm" onClick={this.handleShowInstances}>Change</a>
|
||||
:
|
||||
<a href="#" className="btn btn-secondary btn-sm" onClick={this.handleShowInstances}>Cancel</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
this.state.showInstances ?
|
||||
<React.Fragment>
|
||||
{
|
||||
this.state.error
|
||||
?
|
||||
<div className="card-alert alert alert-danger mb-0">
|
||||
{this.state.errorMessage}
|
||||
</div>
|
||||
:
|
||||
''
|
||||
}
|
||||
<div className="card-body">
|
||||
<div className="form-group control-group error">
|
||||
<select className="form-control" id="contracts" value={this.state.selectedInstance} onChange={this.handleChange}>
|
||||
<option value="custom">Specific contract address</option>
|
||||
{
|
||||
context.instances.map(function (item, i) {
|
||||
return <option key={i} value={item}>{item}</option>;
|
||||
})
|
||||
}
|
||||
</select>
|
||||
{
|
||||
this.state.showCustomAddressField ?
|
||||
<input type="text" className="form-control" id="specificAddress" onChange={this.handleTextChange} placeholder="0x" />
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-footer text-right">
|
||||
<button className="btn btn-primary" onClick={this.handleClick}>Change</button>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
:
|
||||
''
|
||||
}
|
||||
return <ContractContext.Consumer>
|
||||
{(context) => (<div className="contractSelection">
|
||||
<div className="card">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">
|
||||
Instance Selected: <b>{this.props.selectedInstance !== null ? this.props.selectedInstance : 'none'}</b>
|
||||
</h3>
|
||||
<div className="card-options">
|
||||
{showInstance}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ContractContext.Consumer>;
|
||||
}
|
||||
{
|
||||
this.state.showInstances && <React.Fragment>
|
||||
{
|
||||
this.state.error && <div className="card-alert alert alert-danger mb-0">
|
||||
{this.state.errorMessage}
|
||||
</div>
|
||||
}
|
||||
<div className="card-body">
|
||||
<div className="form-group control-group error">
|
||||
<select className="form-control" id="contracts" value={this.state.selectedInstance}
|
||||
onChange={this.handleChange}>
|
||||
<option value="custom">Specific contract address</option>
|
||||
{
|
||||
context.instances.map(function(item, i) {
|
||||
return <option key={i} value={item}>{item}</option>;
|
||||
})
|
||||
}
|
||||
</select>
|
||||
{
|
||||
this.state.showCustomAddressField &&
|
||||
<input type="text" className="form-control" id="specificAddress"
|
||||
onChange={this.handleTextChange} placeholder="0x"/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-footer text-right">
|
||||
<button className="btn btn-primary" onClick={this.handleClick}>Change</button>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ContractContext.Consumer>;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
InstanceSelector.propTypes = {
|
||||
instanceUpdate: PropTypes.func,
|
||||
selectedInstance: PropTypes.string
|
||||
};
|
||||
|
||||
export default InstanceSelector;
|
||||
|
|
|
@ -1,14 +1,27 @@
|
|||
class MenuItem extends React.Component {
|
||||
render(){
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
let classNames = "list-group-item list-group-item-action d-flex align-items-center ";
|
||||
let icon = "fe " + this.props.icon;
|
||||
if(this.props.target == this.props.selectedTab){
|
||||
classNames += "active";
|
||||
}
|
||||
class MenuItem extends React.Component {
|
||||
render() {
|
||||
|
||||
return <a href="#" onClick={this.props.click} data-target={this.props.target} className={classNames}>
|
||||
<span className="icon mr-3"><i className={icon}></i></span>{this.props.text}
|
||||
</a>;
|
||||
let classNames = "list-group-item list-group-item-action d-flex align-items-center ";
|
||||
let icon = "fe " + this.props.icon;
|
||||
if (this.props.target === this.props.selectedTab) {
|
||||
classNames += "active";
|
||||
}
|
||||
|
||||
return <a href="#" onClick={this.props.click} data-target={this.props.target} className={classNames}>
|
||||
<span className="icon mr-3"><i className={icon}></i></span>{this.props.text}
|
||||
</a>;
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem.propTypes = {
|
||||
icon: PropTypes.string,
|
||||
target: PropTypes.string,
|
||||
selectedTab: PropTypes.string,
|
||||
text: PropTypes.string,
|
||||
click: PropTypes.func
|
||||
};
|
||||
|
||||
export default MenuItem;
|
||||
|
|
|
@ -1,27 +1,38 @@
|
|||
class SourceArea extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
sourceCode: ""
|
||||
};
|
||||
}
|
||||
/*global hljs*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
componentDidMount(){
|
||||
let colorCodedText = hljs.highlight('javascript', this.props.source, true).value;
|
||||
this.setState({sourceCode: colorCodedText});
|
||||
}
|
||||
|
||||
render(){
|
||||
return <div className="card">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">{this.props.definition.className}</h3>
|
||||
<div className="card-options">
|
||||
<small>{this.props.definition.filename}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<pre dangerouslySetInnerHTML={{__html: this.state.sourceCode}}></pre>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
class SourceArea extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
sourceCode: ""
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let colorCodedText = hljs.highlight('javascript', this.props.source, true).value;
|
||||
this.setState({sourceCode: colorCodedText});
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className="card">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">{this.props.definition.className}</h3>
|
||||
<div className="card-options">
|
||||
<small>{this.props.definition.filename}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<pre dangerouslySetInnerHTML={{__html: this.state.sourceCode}}></pre>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
SourceArea.propTypes = {
|
||||
definition: PropTypes.object,
|
||||
source: PropTypes.string
|
||||
};
|
||||
|
||||
export default SourceArea;
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class Tab extends React.Component {
|
||||
render(){
|
||||
return (
|
||||
this.props.selectedTab == this.props.id
|
||||
?
|
||||
<div id={this.props.id}>
|
||||
{ this.props.children }
|
||||
</div>
|
||||
:
|
||||
''
|
||||
);
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
this.props.selectedTab === this.props.id && <div id={this.props.id}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Tab.propTypes = {
|
||||
selectedTab: PropTypes.string,
|
||||
id: PropTypes.string,
|
||||
children: PropTypes.element
|
||||
};
|
||||
|
||||
export default Tab;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/*global Web3*/
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ContractUI from './components/contract-ui';
|
||||
|
||||
const contractName = location.search.replace(/\?/, '');
|
||||
|
||||
|
@ -5,47 +9,49 @@ let contractDefinition;
|
|||
let host;
|
||||
|
||||
fetch("/embark/console", {
|
||||
method: "POST",
|
||||
headers: { 'content-type' : 'application/x-www-form-urlencoded; charset=UTF-8' },
|
||||
body: "cmd=web3.currentProvider.host"
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(text => {
|
||||
method: "POST",
|
||||
headers: {'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
|
||||
body: "cmd=web3.currentProvider.host"
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(text => {
|
||||
host = text;
|
||||
return fetch("/embark/contract/" + contractName);
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(_contractDefinition => {
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(_contractDefinition => {
|
||||
contractDefinition = _contractDefinition;
|
||||
return fetch("/embark/files/contracts?filename=" + contractDefinition.originalFilename);
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(contractSource => {
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(contractSource => {
|
||||
const web3 = new Web3(host);
|
||||
window.web3 = web3;
|
||||
|
||||
let contractObj = new web3.eth.Contract(contractDefinition.abiDefinition);
|
||||
contractObj.options.data = "0x" + contractDefinition.code;
|
||||
contractObj.options.address = contractDefinition.deployedAddress;
|
||||
contractObj.options.data = "0x" + contractDefinition.code;
|
||||
contractObj.options.address = contractDefinition.deployedAddress;
|
||||
|
||||
window[contractDefinition.className] = contractObj;
|
||||
|
||||
ReactDOM.render(
|
||||
<ContractUI name={contractDefinition.className} definition={contractDefinition} contract={contractObj} source={contractSource} />,
|
||||
document.getElementById('contracts-area')
|
||||
<ContractUI name={contractDefinition.className} definition={contractDefinition} contract={contractObj}
|
||||
source={contractSource}/>,
|
||||
document.getElementById('contracts-area')
|
||||
);
|
||||
})
|
||||
.catch(function(err) {
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log('%cError while rendering UI', 'font-weight: bold');
|
||||
console.error(err);
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<h1 className="h2 mb-3">Error rendering the UI</h1>
|
||||
<p className="h4 text-muted font-weight-normal mb-7">UI for "{contractName}" cannot be generated</p>
|
||||
</div>,
|
||||
document.getElementById('contracts-area')
|
||||
<div>
|
||||
<h1 className="h2 mb-3">Error rendering the UI</h1>
|
||||
<p className="h4 text-muted font-weight-normal mb-7">UI for "{contractName}" cannot be
|
||||
generated</p>
|
||||
</div>,
|
||||
document.getElementById('contracts-area')
|
||||
);
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -54,7 +54,7 @@ class Whisper {
|
|||
// TOFIX Assume Whisper v6 until there's a way to understand it via JSON-RPC
|
||||
return cb({name: 'Whisper (version 6)', status: 'on'});
|
||||
});
|
||||
}
|
||||
}
|
||||
// Assume it is a Geth compliant client
|
||||
self.web3.shh.getVersion(function(err, version) {
|
||||
if (err || version == "2") {
|
||||
|
|
Loading…
Reference in New Issue