ContractTransactions.js
1 import PropTypes from "prop-types"; 2 import React from 'react'; 3 import {Row, Col, Table, FormGroup, Label, Input, Form} from 'reactstrap'; 4 5 const TX_STATES = {Success: '0x1', Fail: '0x0', Any: ''}; 6 const EVENT = 'event'; 7 const FUNCTION = 'function'; 8 const CONSTRUCTOR = 'constructor'; 9 const PURE = 'pure'; 10 const VIEW = 'view'; 11 12 class ContractTransactions extends React.Component { 13 constructor(props) { 14 super(props); 15 this.state = {method: '', event: '', status: TX_STATES['Any']}; 16 } 17 18 getMethods() { 19 if (!this.props.contract.abiDefinition) { 20 return []; 21 } 22 23 return this.props.contract.abiDefinition.filter(method => ( 24 method.name !== CONSTRUCTOR && method.mutability !== VIEW && method.mutability !== PURE && method.constant !== true && method.type === FUNCTION 25 )); 26 } 27 28 getEvents() { 29 if (!this.props.contract.abiDefinition) { 30 return []; 31 } 32 return this.props.contract.abiDefinition.filter(method => method.type === EVENT); 33 } 34 35 updateState(key, value) { 36 this.setState({[key]: value}); 37 } 38 39 dataToDisplay() { 40 return this.props.contractLogs.map(contractLog => { 41 const events = this.props.contractEvents 42 .filter(contractEvent => contractEvent.transactionHash === contractLog.transactionHash) 43 .map(contractEvent => contractEvent.event); 44 contractLog.events = events; 45 return contractLog; 46 }).filter(contractLog => { 47 if (this.state.status && contractLog.status !== this.state.status) { 48 return false; 49 } 50 51 if (this.state.method || this.state.event) { 52 return this.state.method === contractLog.functionName || contractLog.events.includes(this.state.event); 53 } 54 55 return true; 56 }); 57 } 58 59 render() { 60 return ( 61 <React.Fragment> 62 <Form> 63 <Row> 64 <Col md={6}> 65 <FormGroup> 66 <Label htmlFor="functions">Functions</Label> 67 <Input type="select" name="functions" id="functions" onChange={(event) => this.updateState('method', event.target.value)} value={this.state.method}> 68 <option value=""></option> 69 {this.getMethods().map((method, index) => <option value={method.name} key={index}>{method.name}</option>)} 70 </Input> 71 </FormGroup> 72 </Col> 73 <Col md={6}> 74 <FormGroup> 75 <Label htmlFor="events">Events</Label> 76 <Input type="select" name="events" id="events" onChange={(event) => this.updateState('eveny', event.target.value)} value={this.state.event}> 77 <option value=""/> 78 {this.getEvents().map((event, index) => <option value={event.name} key={index}>{event.name}</option>)} 79 </Input> 80 </FormGroup> 81 </Col> 82 <Col> 83 <FormGroup row> 84 <Col md="3"> 85 <Label>Tx Status</Label> 86 </Col> 87 <Col md="9"> 88 {Object.keys(TX_STATES).map(key => ( 89 <FormGroup key={key} check inline> 90 <Input className="form-check-input" 91 type="radio" 92 id={key} 93 name={key} 94 value={TX_STATES[key]} 95 onChange={(event) => this.updateState('status', event.target.value)} 96 checked={TX_STATES[key] === this.state.status} /> 97 <Label check className="form-check-label" htmlFor={key}>{key}</Label> 98 </FormGroup> 99 ))} 100 </Col> 101 </FormGroup> 102 </Col> 103 </Row> 104 </Form> 105 <Row> 106 <Col className="overflow-auto"> 107 <Table> 108 <thead> 109 <tr> 110 <th>Call</th> 111 <th>Events</th> 112 <th>Gas Used</th> 113 <th>Block number</th> 114 <th>Status</th> 115 <th>Transaction hash</th> 116 </tr> 117 </thead> 118 <tbody> 119 { 120 this.dataToDisplay().map((log, index) => { 121 return ( 122 <tr key={'log-' + index}> 123 <td>{`${log.name}.${log.functionName}(${log.paramString})`}</td> 124 <td>{log.events.join(', ')}</td> 125 <td>{log.gasUsed}</td> 126 <td>{log.blockNumber}</td> 127 <td>{log.status}</td> 128 <td>{log.transactionHash}</td> 129 </tr> 130 ); 131 }) 132 } 133 </tbody> 134 </Table> 135 </Col> 136 </Row> 137 </React.Fragment> 138 ); 139 } 140 } 141 142 ContractTransactions.propTypes = { 143 contractLogs: PropTypes.array, 144 contractEvents: PropTypes.array, 145 contract: PropTypes.object.isRequired 146 }; 147 148 export default ContractTransactions; 149