Merge pull request #36 from status-im/features/backend_tab/functions
Features/backend tab/functions
This commit is contained in:
commit
6c2489d5e0
|
@ -111,6 +111,20 @@ export const contractFile = {
|
||||||
failure: (error) => action(CONTRACT_FILE[FAILURE], {error})
|
failure: (error) => action(CONTRACT_FILE[FAILURE], {error})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const CONTRACT_FUNCTION = createRequestTypes('CONTRACT_FUNCTION');
|
||||||
|
export const contractFunction = {
|
||||||
|
post: (contractName, method, inputs) => action(CONTRACT_FUNCTION[REQUEST], {contractName, method, inputs}),
|
||||||
|
success: (result, payload) => action(CONTRACT_FUNCTION[SUCCESS], {contractFunctions: [{...result, ...payload}]}),
|
||||||
|
failure: (error) => action(CONTRACT_FUNCTION[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CONTRACT_DEPLOY = createRequestTypes('CONTRACT_DEPLOY');
|
||||||
|
export const contractDeploy = {
|
||||||
|
post: (contractName, method, inputs) => action(CONTRACT_DEPLOY[REQUEST], {contractName, method, inputs}),
|
||||||
|
success: (result, payload) => action(CONTRACT_DEPLOY[SUCCESS], {contractDeploys: [{...result, ...payload}]}),
|
||||||
|
failure: (error) => action(CONTRACT_DEPLOY[FAILURE], {error})
|
||||||
|
};
|
||||||
|
|
||||||
export const VERSIONS = createRequestTypes('VERSIONS');
|
export const VERSIONS = createRequestTypes('VERSIONS');
|
||||||
export const versions = {
|
export const versions = {
|
||||||
request: () => action(VERSIONS[REQUEST]),
|
request: () => action(VERSIONS[REQUEST]),
|
||||||
|
|
|
@ -68,6 +68,14 @@ export function fetchContract(payload) {
|
||||||
return get(`/contract/${payload.contractName}`);
|
return get(`/contract/${payload.contractName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function postContractFunction(payload) {
|
||||||
|
return post(`/contract/${payload.contractName}/function`, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function postContractDeploy(payload) {
|
||||||
|
return post(`/contract/${payload.contractName}/deploy`, payload);
|
||||||
|
}
|
||||||
|
|
||||||
export function fetchVersions() {
|
export function fetchVersions() {
|
||||||
return get('/versions');
|
return get('/versions');
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {
|
||||||
|
Page,
|
||||||
|
Grid,
|
||||||
|
Form,
|
||||||
|
Button,
|
||||||
|
List,
|
||||||
|
Card
|
||||||
|
} from "tabler-react";
|
||||||
|
|
||||||
|
class ContractFunction extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { inputs: {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonTitle() {
|
||||||
|
const { method } =this.props;
|
||||||
|
if (method.name === 'constructor') {
|
||||||
|
return 'Deploy';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (method.mutability === 'view' || method.mutability === 'pure') ? 'Call' : 'Send';
|
||||||
|
}
|
||||||
|
|
||||||
|
inputsAsArray(){
|
||||||
|
return this.props.method.inputs
|
||||||
|
.map(input => this.state.inputs[input.name])
|
||||||
|
.filter(value => value);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange(e, name) {
|
||||||
|
let newInputs = this.state.inputs;
|
||||||
|
newInputs[name] = e.target.value;
|
||||||
|
this.setState({ inputs: newInputs});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCall(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.props.postContractFunction(this.props.contractProfile.name, this.props.method.name, this.inputsAsArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
callDisabled() {
|
||||||
|
return this.inputsAsArray().length !== this.props.method.inputs.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Grid.Row>
|
||||||
|
<Grid.Col>
|
||||||
|
<Card>
|
||||||
|
<Card.Header>
|
||||||
|
<Card.Title>{this.props.method.name}</Card.Title>
|
||||||
|
</Card.Header>
|
||||||
|
<Card.Body>
|
||||||
|
{this.props.method.inputs.map(input => (
|
||||||
|
<Form.Group key={input.name} label={input.name}>
|
||||||
|
<Form.Input placeholder={input.type} onChange={(e) => this.handleChange(e, input.name)}/>
|
||||||
|
</Form.Group>
|
||||||
|
))}
|
||||||
|
<Button color="primary" disabled={this.callDisabled()} onClick={(e) => this.handleCall(e)}>
|
||||||
|
{this.buttonTitle()}
|
||||||
|
</Button>
|
||||||
|
</Card.Body>
|
||||||
|
<Card.Footer>
|
||||||
|
<List>
|
||||||
|
{this.props.contractFunctions.map(contractFunction => (
|
||||||
|
<List.Item key={contractFunction.result}>
|
||||||
|
{contractFunction.inputs.length > 0 && <p>Inputs: {contractFunction.inputs.join(', ')}</p>}
|
||||||
|
<strong>Result: {contractFunction.result}</strong>
|
||||||
|
</List.Item>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Card.Footer>
|
||||||
|
</Card>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid.Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContractFunction.propTypes = {
|
||||||
|
contractProfile: PropTypes.object,
|
||||||
|
method: PropTypes.object,
|
||||||
|
contractFunctions: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
postContractFunction: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
const filterContractFunctions = (contractFunctions, contractName, method) => {
|
||||||
|
return contractFunctions.filter((contractFunction) => (
|
||||||
|
contractFunction.contractName === contractName && contractFunction.method === method
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
const ContractFunctions = (props) => {
|
||||||
|
const {contractProfile} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page.Content title={contractProfile.name + ' Functions'}>
|
||||||
|
{contractProfile.methods
|
||||||
|
.filter((method) => {
|
||||||
|
return props.onlyConstructor ? method.name === 'constructor' : method.name !== 'constructor';
|
||||||
|
})
|
||||||
|
.map(method => <ContractFunction key={method.name}
|
||||||
|
method={method}
|
||||||
|
contractFunctions={filterContractFunctions(props.contractFunctions, contractProfile.name, method.name)}
|
||||||
|
contractProfile={contractProfile}
|
||||||
|
postContractFunction={props.postContractFunction} />)}
|
||||||
|
</Page.Content>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ContractFunctions.propTypes = {
|
||||||
|
onlyConstructor: PropTypes.bool,
|
||||||
|
contractProfile: PropTypes.object,
|
||||||
|
contractFunctions: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
postContractFunction: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
ContractFunctions.defaultProps = {
|
||||||
|
onlyConstructor: false
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ContractFunctions;
|
||||||
|
|
|
@ -9,6 +9,8 @@ import {
|
||||||
|
|
||||||
import ContractContainer from '../containers/ContractContainer';
|
import ContractContainer from '../containers/ContractContainer';
|
||||||
import ContractLoggerContainer from '../containers/ContractLoggerContainer';
|
import ContractLoggerContainer from '../containers/ContractLoggerContainer';
|
||||||
|
import ContractFunctionsContainer from '../containers/ContractFunctionsContainer';
|
||||||
|
import ContractDeploymentContainer from '../containers/ContractDeploymentContainer';
|
||||||
import ContractProfileContainer from '../containers/ContractProfileContainer';
|
import ContractProfileContainer from '../containers/ContractProfileContainer';
|
||||||
import ContractSourceContainer from '../containers/ContractSourceContainer';
|
import ContractSourceContainer from '../containers/ContractSourceContainer';
|
||||||
|
|
||||||
|
@ -72,6 +74,8 @@ const ContractLayout = ({match}) => (
|
||||||
<Grid.Col md={9}>
|
<Grid.Col md={9}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/embark/contracts/:contractName/overview" component={ContractContainer} />
|
<Route exact path="/embark/contracts/:contractName/overview" component={ContractContainer} />
|
||||||
|
<Route exact path="/embark/contracts/:contractName/deployment" component={ContractDeploymentContainer} />
|
||||||
|
<Route exact path="/embark/contracts/:contractName/functions" component={ContractFunctionsContainer} />
|
||||||
<Route exact path="/embark/contracts/:contractName/source" component={ContractSourceContainer} />
|
<Route exact path="/embark/contracts/:contractName/source" component={ContractSourceContainer} />
|
||||||
<Route exact path="/embark/contracts/:contractName/profiler" component={ContractProfileContainer} />
|
<Route exact path="/embark/contracts/:contractName/profiler" component={ContractProfileContainer} />
|
||||||
<Route exact path="/embark/contracts/:contractName/logger" component={ContractLoggerContainer} />
|
<Route exact path="/embark/contracts/:contractName/logger" component={ContractLoggerContainer} />
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {connect} from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {withRouter} from 'react-router-dom';
|
import {withRouter} from 'react-router-dom';
|
||||||
|
|
||||||
import {contract as contractAction} from '../actions';
|
|
||||||
import Contract from '../components/Contract';
|
import Contract from '../components/Contract';
|
||||||
import DataWrapper from "../components/DataWrapper";
|
import DataWrapper from "../components/DataWrapper";
|
||||||
import {getContract} from "../reducers/selectors";
|
import {getContract} from "../reducers/selectors";
|
||||||
|
@ -33,8 +32,5 @@ ContractContainer.propTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withRouter(connect(
|
export default withRouter(connect(
|
||||||
mapStateToProps,
|
mapStateToProps
|
||||||
{
|
|
||||||
fetchContract: contractAction.request
|
|
||||||
}
|
|
||||||
)(ContractContainer));
|
)(ContractContainer));
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {withRouter} from 'react-router-dom';
|
||||||
|
|
||||||
|
import {contractProfile as contractProfileAction, contractDeploy as contractDeployAction} from '../actions';
|
||||||
|
import ContractFunctions from '../components/ContractFunctions';
|
||||||
|
import DataWrapper from "../components/DataWrapper";
|
||||||
|
import {getContractProfile, getContractDeploys} from "../reducers/selectors";
|
||||||
|
|
||||||
|
class ContractDeploymentContainer extends Component {
|
||||||
|
componentDidMount() {
|
||||||
|
this.props.fetchContractProfile(this.props.match.params.contractName);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<DataWrapper shouldRender={this.props.contractProfile !== undefined }
|
||||||
|
{...this.props}
|
||||||
|
render={({contractProfile, contractDeploys, postContractDeploy}) => (
|
||||||
|
<ContractFunctions contractProfile={contractProfile}
|
||||||
|
contractFunctions={contractDeploys}
|
||||||
|
onlyConstructor
|
||||||
|
postContractFunction={postContractDeploy}/>
|
||||||
|
)} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state, props) {
|
||||||
|
return {
|
||||||
|
contractProfile: getContractProfile(state, props.match.params.contractName),
|
||||||
|
contractDeploys: getContractDeploys(state, props.match.params.contractName),
|
||||||
|
error: state.errorMessage,
|
||||||
|
loading: state.loading
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ContractDeploymentContainer.propTypes = {
|
||||||
|
match: PropTypes.object,
|
||||||
|
contractProfile: PropTypes.object,
|
||||||
|
contractFunctions: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
postContractDeploy: PropTypes.func,
|
||||||
|
fetchContractProfile: PropTypes.func,
|
||||||
|
error: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withRouter(connect(
|
||||||
|
mapStateToProps,
|
||||||
|
{
|
||||||
|
fetchContractProfile: contractProfileAction.request,
|
||||||
|
postContractDeploy: contractDeployAction.post
|
||||||
|
}
|
||||||
|
)(ContractDeploymentContainer));
|
|
@ -0,0 +1,53 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {withRouter} from 'react-router-dom';
|
||||||
|
|
||||||
|
import {contractProfile as contractProfileAction, contractFunction as contractFunctionAction} from '../actions';
|
||||||
|
import ContractFunctions from '../components/ContractFunctions';
|
||||||
|
import DataWrapper from "../components/DataWrapper";
|
||||||
|
import {getContractProfile, getContractFunctions} from "../reducers/selectors";
|
||||||
|
|
||||||
|
class ContractFunctionsContainer extends Component {
|
||||||
|
componentDidMount() {
|
||||||
|
this.props.fetchContractProfile(this.props.match.params.contractName);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<DataWrapper shouldRender={this.props.contractProfile !== undefined }
|
||||||
|
{...this.props}
|
||||||
|
render={({contractProfile, contractFunctions, postContractFunction}) => (
|
||||||
|
<ContractFunctions contractProfile={contractProfile}
|
||||||
|
contractFunctions={contractFunctions}
|
||||||
|
postContractFunction={postContractFunction}/>
|
||||||
|
)} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state, props) {
|
||||||
|
return {
|
||||||
|
contractProfile: getContractProfile(state, props.match.params.contractName),
|
||||||
|
contractFunctions: getContractFunctions(state, props.match.params.contractName),
|
||||||
|
error: state.errorMessage,
|
||||||
|
loading: state.loading
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ContractFunctionsContainer.propTypes = {
|
||||||
|
match: PropTypes.object,
|
||||||
|
contractProfile: PropTypes.object,
|
||||||
|
contractFunctions: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
postContractFunction: PropTypes.func,
|
||||||
|
fetchContractProfile: PropTypes.func,
|
||||||
|
error: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withRouter(connect(
|
||||||
|
mapStateToProps,
|
||||||
|
{
|
||||||
|
fetchContractProfile: contractProfileAction.request,
|
||||||
|
postContractFunction: contractFunctionAction.post
|
||||||
|
}
|
||||||
|
)(ContractFunctionsContainer));
|
|
@ -27,7 +27,7 @@ function mapStateToProps(state) {
|
||||||
|
|
||||||
ContractsContainer.propTypes = {
|
ContractsContainer.propTypes = {
|
||||||
contracts: PropTypes.array,
|
contracts: PropTypes.array,
|
||||||
fetchContracts: PropTypes.func,
|
fetchContracts: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -13,6 +13,8 @@ const entitiesDefaultState = {
|
||||||
contracts: [],
|
contracts: [],
|
||||||
contractProfiles: [],
|
contractProfiles: [],
|
||||||
contractFiles: [],
|
contractFiles: [],
|
||||||
|
contractFunctions: [],
|
||||||
|
contractDeploys: [],
|
||||||
contractLogs: [],
|
contractLogs: [],
|
||||||
commands: [],
|
commands: [],
|
||||||
messages: [],
|
messages: [],
|
||||||
|
|
|
@ -66,6 +66,14 @@ export function getContractFile(state, filename) {
|
||||||
return state.entities.contractFiles.find((contractFile => contractFile.filename === filename));
|
return state.entities.contractFiles.find((contractFile => contractFile.filename === filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getContractFunctions(state, contractName) {
|
||||||
|
return state.entities.contractFunctions.filter((contractFunction => contractFunction.contractName === contractName));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getContractDeploys(state, contractName) {
|
||||||
|
return state.entities.contractDeploys.filter((contractDeploy => contractDeploy.contractName === contractName));
|
||||||
|
}
|
||||||
|
|
||||||
export function getVersions(state) {
|
export function getVersions(state) {
|
||||||
return state.entities.versions;
|
return state.entities.versions;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {all, call, fork, put, takeEvery, take} from 'redux-saga/effects';
|
||||||
|
|
||||||
const {account, accounts, block, blocks, transaction, transactions, processes, commands, processLogs,
|
const {account, accounts, block, blocks, transaction, transactions, processes, commands, processLogs,
|
||||||
contracts, contract, contractProfile, messageSend, versions, plugins, messageListen, fiddle,
|
contracts, contract, contractProfile, messageSend, versions, plugins, messageListen, fiddle,
|
||||||
ensRecord, ensRecords, contractLogs, contractFile} = actions;
|
ensRecord, ensRecords, contractLogs, contractFile, contractFunction, contractDeploy} = actions;
|
||||||
|
|
||||||
function *doRequest(entity, apiFn, payload) {
|
function *doRequest(entity, apiFn, payload) {
|
||||||
const {response, error} = yield call(apiFn, payload);
|
const {response, error} = yield call(apiFn, payload);
|
||||||
|
@ -32,6 +32,8 @@ export const fetchContracts = doRequest.bind(null, contracts, api.fetchContracts
|
||||||
export const fetchContract = doRequest.bind(null, contract, api.fetchContract);
|
export const fetchContract = doRequest.bind(null, contract, api.fetchContract);
|
||||||
export const fetchContractProfile = doRequest.bind(null, contractProfile, api.fetchContractProfile);
|
export const fetchContractProfile = doRequest.bind(null, contractProfile, api.fetchContractProfile);
|
||||||
export const fetchContractFile = doRequest.bind(null, contractFile, api.fetchContractFile);
|
export const fetchContractFile = doRequest.bind(null, contractFile, api.fetchContractFile);
|
||||||
|
export const postContractFunction = doRequest.bind(null, contractFunction, api.postContractFunction);
|
||||||
|
export const postContractDeploy = doRequest.bind(null, contractDeploy, api.postContractDeploy);
|
||||||
export const fetchFiddle = doRequest.bind(null, fiddle, api.fetchFiddle);
|
export const fetchFiddle = doRequest.bind(null, fiddle, api.fetchFiddle);
|
||||||
export const sendMessage = doRequest.bind(null, messageSend, api.sendMessage);
|
export const sendMessage = doRequest.bind(null, messageSend, api.sendMessage);
|
||||||
export const fetchEnsRecord = doRequest.bind(null, ensRecord, api.fetchEnsRecord);
|
export const fetchEnsRecord = doRequest.bind(null, ensRecord, api.fetchEnsRecord);
|
||||||
|
@ -93,6 +95,14 @@ export function *watchFetchContractFile() {
|
||||||
yield takeEvery(actions.CONTRACT_FILE[actions.REQUEST], fetchContractFile);
|
yield takeEvery(actions.CONTRACT_FILE[actions.REQUEST], fetchContractFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function *watchPostContractFunction() {
|
||||||
|
yield takeEvery(actions.CONTRACT_FUNCTION[actions.REQUEST], postContractFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function *watchPostContractDeploy() {
|
||||||
|
yield takeEvery(actions.CONTRACT_DEPLOY[actions.REQUEST], postContractDeploy);
|
||||||
|
}
|
||||||
|
|
||||||
export function *watchFetchVersions() {
|
export function *watchFetchVersions() {
|
||||||
yield takeEvery(actions.VERSIONS[actions.REQUEST], fetchVersions);
|
yield takeEvery(actions.VERSIONS[actions.REQUEST], fetchVersions);
|
||||||
}
|
}
|
||||||
|
@ -200,6 +210,8 @@ export default function *root() {
|
||||||
fork(watchFetchContracts),
|
fork(watchFetchContracts),
|
||||||
fork(watchFetchContractProfile),
|
fork(watchFetchContractProfile),
|
||||||
fork(watchFetchContractFile),
|
fork(watchFetchContractFile),
|
||||||
|
fork(watchPostContractFunction),
|
||||||
|
fork(watchPostContractDeploy),
|
||||||
fork(watchListenToMessages),
|
fork(watchListenToMessages),
|
||||||
fork(watchSendMessage),
|
fork(watchSendMessage),
|
||||||
fork(watchFetchContract),
|
fork(watchFetchContract),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/*global web3*/
|
||||||
let toposort = require('toposort');
|
let toposort = require('toposort');
|
||||||
let async = require('async');
|
let async = require('async');
|
||||||
const cloneDeep = require('clone-deep');
|
const cloneDeep = require('clone-deep');
|
||||||
|
@ -83,6 +84,73 @@ class ContractsManager {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
plugin.registerAPICall(
|
||||||
|
'post',
|
||||||
|
'/embark-api/contract/:contractName/function',
|
||||||
|
(req, res) => {
|
||||||
|
async.parallel({
|
||||||
|
contract: (callback) => {
|
||||||
|
self.events.request('contracts:contract', req.body.contractName, (contract) => callback(null, contract));
|
||||||
|
},
|
||||||
|
account: (callback) => {
|
||||||
|
self.events.request("blockchain:defaultAccount:get", (account) => callback(null, account));
|
||||||
|
}
|
||||||
|
}, (error, result) => {
|
||||||
|
if (error) {
|
||||||
|
return res.send({error: error.message});
|
||||||
|
}
|
||||||
|
const {account, contract} = result;
|
||||||
|
const abi = contract.abiDefinition.find(definition => definition.name === req.body.method);
|
||||||
|
const funcCall = (abi.constant === true || abi.stateMutability === 'view' || abi.stateMutability === 'pure') ? 'call' : 'send';
|
||||||
|
|
||||||
|
self.events.request("blockchain:contract:create", {abi: contract.abiDefinition, address: contract.deployedAddress}, (contractObj) => {
|
||||||
|
try {
|
||||||
|
contractObj.methods[req.body.method].apply(this, req.body.inputs)[funcCall]({from: account}, (error, result) => {
|
||||||
|
if (error) {
|
||||||
|
return res.send({result: error.message});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send({result});
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
res.send({result: e.message});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
plugin.registerAPICall(
|
||||||
|
'post',
|
||||||
|
'/embark-api/contract/:contractName/deploy',
|
||||||
|
(req, res) => {
|
||||||
|
async.parallel({
|
||||||
|
contract: (callback) => {
|
||||||
|
self.events.request('contracts:contract', req.body.contractName, (contract) => callback(null, contract));
|
||||||
|
},
|
||||||
|
account: (callback) => {
|
||||||
|
self.events.request("blockchain:defaultAccount:get", (account) => callback(null, account));
|
||||||
|
}
|
||||||
|
}, (error, result) => {
|
||||||
|
if (error) {
|
||||||
|
return res.send({error: error.message});
|
||||||
|
}
|
||||||
|
const {account, contract} = result;
|
||||||
|
|
||||||
|
self.events.request("blockchain:contract:create", {abi: contract.abiDefinition}, async (contractObj) => {
|
||||||
|
try {
|
||||||
|
const params = {data: `0x${contract.code}`, arguments: req.body.inputs};
|
||||||
|
let gas = await contractObj.deploy(params).estimateGas();
|
||||||
|
let newContract = await contractObj.deploy(params).send({from: account, gas});
|
||||||
|
res.send({result: newContract._address});
|
||||||
|
} catch (e) {
|
||||||
|
res.send({result: e.message});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
plugin.registerAPICall(
|
plugin.registerAPICall(
|
||||||
'get',
|
'get',
|
||||||
'/embark-api/contracts',
|
'/embark-api/contracts',
|
||||||
|
@ -203,7 +271,10 @@ class ContractsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentContract === undefined) {
|
if (parentContract === undefined) {
|
||||||
self.logger.error(__("{{className}}: couldn't find instanceOf contract {{parentContractName}}", {className: className, parentContractName: parentContractName}));
|
self.logger.error(__("{{className}}: couldn't find instanceOf contract {{parentContractName}}", {
|
||||||
|
className: className,
|
||||||
|
parentContractName: parentContractName
|
||||||
|
}));
|
||||||
let suggestion = utils.proposeAlternative(parentContractName, dictionary, [className, parentContractName]);
|
let suggestion = utils.proposeAlternative(parentContractName, dictionary, [className, parentContractName]);
|
||||||
if (suggestion) {
|
if (suggestion) {
|
||||||
self.logger.warn(__('did you mean "%s"?', suggestion));
|
self.logger.warn(__('did you mean "%s"?', suggestion));
|
||||||
|
@ -216,7 +287,10 @@ class ContractsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contract.code !== undefined) {
|
if (contract.code !== undefined) {
|
||||||
self.logger.error(__("{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}", {className: className, parentContractName: parentContractName}));
|
self.logger.error(__("{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}", {
|
||||||
|
className: className,
|
||||||
|
parentContractName: parentContractName
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
contract.code = parentContract.code;
|
contract.code = parentContract.code;
|
||||||
|
@ -261,8 +335,8 @@ class ContractsManager {
|
||||||
// look in code for dependencies
|
// look in code for dependencies
|
||||||
let libMatches = (contract.code.match(/:(.*?)(?=_)/g) || []);
|
let libMatches = (contract.code.match(/:(.*?)(?=_)/g) || []);
|
||||||
for (let match of libMatches) {
|
for (let match of libMatches) {
|
||||||
self.contractDependencies[className] = self.contractDependencies[className] || [];
|
self.contractDependencies[className] = self.contractDependencies[className] || [];
|
||||||
self.contractDependencies[className].push(match.substr(1));
|
self.contractDependencies[className].push(match.substr(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// look in arguments for dependencies
|
// look in arguments for dependencies
|
||||||
|
@ -358,7 +432,7 @@ class ContractsManager {
|
||||||
self.compileError = true;
|
self.compileError = true;
|
||||||
self.events.emit("status", __("Compile/Build error"));
|
self.events.emit("status", __("Compile/Build error"));
|
||||||
self.logger.error(__("Error Compiling/Building contracts: ") + err);
|
self.logger.error(__("Error Compiling/Building contracts: ") + err);
|
||||||
}else{
|
} else {
|
||||||
self.compileError = false;
|
self.compileError = false;
|
||||||
}
|
}
|
||||||
self.logger.trace("finished".underline);
|
self.logger.trace("finished".underline);
|
||||||
|
@ -398,8 +472,8 @@ class ContractsManager {
|
||||||
let orderedDependencies;
|
let orderedDependencies;
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
this.logger.error((__("Error: ") + e.message).red);
|
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);
|
this.logger.error(__("there are two or more contracts that depend on each other in a cyclic manner").bold.red);
|
||||||
this.logger.error(__("Embark couldn't determine which one to deploy first").red);
|
this.logger.error(__("Embark couldn't determine which one to deploy first").red);
|
||||||
|
|
Loading…
Reference in New Issue