add contract logs
This commit is contained in:
parent
11e15d57ad
commit
245beeeb59
|
@ -76,6 +76,13 @@ export const processLogs = {
|
|||
failure: (error) => action(PROCESS_LOGS[FAILURE], {error})
|
||||
};
|
||||
|
||||
export const CONTRACT_LOGS = createRequestTypes('CONTRACT_LOGS');
|
||||
export const contractLogs = {
|
||||
request: () => action(CONTRACT_LOGS[REQUEST]),
|
||||
success: (contractLogs) => action(CONTRACT_LOGS[SUCCESS], {contractLogs}),
|
||||
failure: (error) => action(CONTRACT_LOGS[FAILURE], {error})
|
||||
};
|
||||
|
||||
export const CONTRACTS = createRequestTypes('CONTRACTS');
|
||||
export const contracts = {
|
||||
request: () => action(CONTRACTS[REQUEST]),
|
||||
|
|
|
@ -56,6 +56,10 @@ export function fetchProcessLogs(payload) {
|
|||
return get(`/process-logs/${payload.processName}`);
|
||||
}
|
||||
|
||||
export function fetchContractLogs() {
|
||||
return get(`/contracts/logs`);
|
||||
}
|
||||
|
||||
export function fetchContracts() {
|
||||
return get('/contracts');
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
} from "tabler-react";
|
||||
|
||||
import ContractContainer from '../containers/ContractContainer';
|
||||
import ContractLoggerContainer from '../containers/ContractLoggerContainer';
|
||||
import ContractProfileContainer from '../containers/ContractProfileContainer';
|
||||
|
||||
const ContractLayout = (props) => (
|
||||
|
@ -48,11 +49,20 @@ const ContractLayout = (props) => (
|
|||
>
|
||||
Profile
|
||||
</List.GroupItem>
|
||||
<List.GroupItem
|
||||
className="d-flex align-items-center"
|
||||
to={`/embark/contracts/${props.match.params.contractName}/logger`}
|
||||
icon="chevrons-right"
|
||||
RootComponent={withRouter(NavLink)}
|
||||
>
|
||||
Logger
|
||||
</List.GroupItem>
|
||||
</List.Group>
|
||||
</div>
|
||||
</Grid.Col>
|
||||
<Grid.Col md={9}>
|
||||
<Switch>
|
||||
<Route exact path="/embark/contracts/:contractName/logger" component={ContractLoggerContainer} />
|
||||
<Route exact path="/embark/contracts/:contractName/profiler" component={ContractProfileContainer} />
|
||||
<ContractContainer />
|
||||
</Switch>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import PropTypes from "prop-types";
|
||||
import React from 'react';
|
||||
import {
|
||||
Page,
|
||||
Grid, Table
|
||||
} from "tabler-react";
|
||||
|
||||
const ContractLogger = ({contractName, contractLogs}) => (
|
||||
<Page.Content title={contractName + ' Logger'}>
|
||||
<Grid.Row>
|
||||
<Grid.Col>
|
||||
<Table
|
||||
responsive
|
||||
className="card-table table-vcenter text-nowrap"
|
||||
headerItems={[
|
||||
{content: "Function name"},
|
||||
{content: "Params"},
|
||||
{content: "Transaction hash"},
|
||||
{content: "Gas Used"},
|
||||
{content: "Block number"},
|
||||
{content: "Status"}
|
||||
]}
|
||||
bodyItems={
|
||||
contractLogs.map((log) => {
|
||||
return ([
|
||||
{content: log.functionName},
|
||||
{content: log.paramString},
|
||||
{content: log.transactionHash},
|
||||
{content: log.gasUsed},
|
||||
{content: log.blockNumber},
|
||||
{content: log.status}
|
||||
]);
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Grid.Col>
|
||||
</Grid.Row>
|
||||
</Page.Content>
|
||||
);
|
||||
|
||||
ContractLogger.propTypes = {
|
||||
contractName: PropTypes.string.isRequired,
|
||||
contractLogs: PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
export default ContractLogger;
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import React, {Component} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import {withRouter} from 'react-router-dom';
|
||||
import {contractLogs as contractLogsAction} from '../actions';
|
||||
|
||||
import ContractLogger from '../components/ContractLogger';
|
||||
// import DataWrapper from "../components/DataWrapper";
|
||||
import {getContractLogsByContract} from "../reducers/selectors";
|
||||
|
||||
class ContractProfileContainer extends Component {
|
||||
componentDidMount() {
|
||||
if (this.props.contractLogs.length === 0) {
|
||||
this.props.fetchContractLogs(this.props.match.params.contractName);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ContractLogger contractLogs={this.props.contractLogs} contractName={this.props.match.params.contractName}/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state, props) {
|
||||
return {
|
||||
contractLogs: getContractLogsByContract(state, props.match.params.contractName)
|
||||
};
|
||||
}
|
||||
|
||||
ContractProfileContainer.propTypes = {
|
||||
contractLogs: PropTypes.array,
|
||||
fetchContractLogs: PropTypes.func,
|
||||
match: PropTypes.object
|
||||
};
|
||||
|
||||
export default withRouter(connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
fetchContractLogs: contractLogsAction.request
|
||||
}
|
||||
)(ContractProfileContainer));
|
|
@ -11,6 +11,7 @@ const entitiesDefaultState = {
|
|||
processLogs: [],
|
||||
contracts: [],
|
||||
contractProfiles: [],
|
||||
contractLogs: [],
|
||||
commands: [],
|
||||
messages: [],
|
||||
messageChannels: [],
|
||||
|
@ -27,6 +28,9 @@ const sorter = {
|
|||
processLogs: function(a, b) {
|
||||
return a.timestamp - b.timestamp;
|
||||
},
|
||||
contractLogs: function(a, b) {
|
||||
return a.timestamp - b.timestamp;
|
||||
},
|
||||
messages: function(a, b) {
|
||||
return a.time - b.time;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,11 @@ export function getProcessLogsByProcess(state, processName) {
|
|||
return state.entities.processLogs.filter((processLog => processLog.name === processName));
|
||||
}
|
||||
|
||||
export function getContractLogsByContract(state, contractName) {
|
||||
return state.entities.contractLogs;
|
||||
// return state.entities.processLogs.filter((processLog => processLog.name === processName));
|
||||
}
|
||||
|
||||
export function getContracts(state) {
|
||||
return state.entities.contracts;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import {eventChannel} from 'redux-saga';
|
|||
import {all, call, fork, put, takeEvery, take} from 'redux-saga/effects';
|
||||
|
||||
const {account, accounts, block, blocks, transaction, transactions, processes, commands, processLogs,
|
||||
contracts, contract, contractProfile, messageSend, messageVersion, messageListen} = actions;
|
||||
contracts, contract, contractProfile, messageSend, messageVersion, messageListen, contractLogs} = actions;
|
||||
|
||||
function *doRequest(entity, apiFn, payload) {
|
||||
const {response, error} = yield call(apiFn, payload);
|
||||
|
@ -24,6 +24,7 @@ export const fetchTransactions = doRequest.bind(null, transactions, api.fetchTra
|
|||
export const fetchProcesses = doRequest.bind(null, processes, api.fetchProcesses);
|
||||
export const postCommand = doRequest.bind(null, commands, api.postCommand);
|
||||
export const fetchProcessLogs = doRequest.bind(null, processLogs, api.fetchProcessLogs);
|
||||
export const fetchContractLogs = doRequest.bind(null, contractLogs, api.fetchContractLogs);
|
||||
export const fetchContracts = doRequest.bind(null, contracts, api.fetchContracts);
|
||||
export const fetchContract = doRequest.bind(null, contract, api.fetchContract);
|
||||
export const fetchContractProfile = doRequest.bind(null, contractProfile, api.fetchContractProfile);
|
||||
|
@ -64,6 +65,10 @@ export function *watchFetchProcessLogs() {
|
|||
yield takeEvery(actions.PROCESS_LOGS[actions.REQUEST], fetchProcessLogs);
|
||||
}
|
||||
|
||||
export function *watchFetchContractLogs() {
|
||||
yield takeEvery(actions.CONTRACT_LOGS[actions.REQUEST], fetchContractLogs);
|
||||
}
|
||||
|
||||
export function *watchFetchContract() {
|
||||
yield takeEvery(actions.CONTRACT[actions.REQUEST], fetchContract);
|
||||
}
|
||||
|
@ -146,6 +151,7 @@ export default function *root() {
|
|||
fork(watchFetchAccount),
|
||||
fork(watchFetchProcesses),
|
||||
fork(watchFetchProcessLogs),
|
||||
fork(watchFetchContractLogs),
|
||||
fork(watchListenToProcessLogs),
|
||||
fork(watchFetchBlock),
|
||||
fork(watchFetchTransactions),
|
||||
|
|
|
@ -86,7 +86,9 @@ exports.serve = function(ipc, host, port, ws){
|
|||
|
||||
let server = http.createServer((req, res) => {
|
||||
let reqBody = [];
|
||||
req.on('data', (b) => { reqBody.push(b); })
|
||||
req.on('data', (b) => {
|
||||
reqBody.push(b);
|
||||
})
|
||||
.on('end', () => {
|
||||
reqBody = Buffer.concat(reqBody).toString();
|
||||
if (reqBody) {
|
||||
|
|
|
@ -2,10 +2,12 @@ const utils = require('../../utils/utils.js');
|
|||
|
||||
class ConsoleListener {
|
||||
constructor(embark, options) {
|
||||
this.embark = embark;
|
||||
this.logger = embark.logger;
|
||||
this.ipc = options.ipc;
|
||||
this.events = embark.events;
|
||||
this.addressToContract = [];
|
||||
this.logs = [];
|
||||
this.contractsConfig = embark.config.contractsConfig;
|
||||
this.contractsDeployed = false;
|
||||
this.outputDone = false;
|
||||
|
@ -13,6 +15,7 @@ class ConsoleListener {
|
|||
this.events.on('outputDone', () => {
|
||||
this.outputDone = true;
|
||||
});
|
||||
this._registerAPI();
|
||||
|
||||
this.events.on("contractsDeployed", () => {
|
||||
this.contractsDeployed = true;
|
||||
|
@ -91,12 +94,25 @@ class ConsoleListener {
|
|||
gasUsed = utils.hexToNumber(gasUsed);
|
||||
blockNumber = utils.hexToNumber(blockNumber);
|
||||
|
||||
this.logs.push(Object.assign({}, request, {name, functionName, paramString}));
|
||||
|
||||
this.logger.info(`Blockchain>`.underline + ` ${name}.${functionName}(${paramString})`.bold + ` | ${transactionHash} | gas:${gasUsed} | blk:${blockNumber} | status:${status}`);
|
||||
} else {
|
||||
this.logger.info(JSON.stringify(request));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_registerAPI() {
|
||||
const apiRoute = '/embark-api/contracts/logs';
|
||||
this.embark.registerAPICall(
|
||||
'get',
|
||||
apiRoute,
|
||||
(req, res) => {
|
||||
res.send(JSON.stringify(this.logs));
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ConsoleListener;
|
||||
|
|
Loading…
Reference in New Issue