Commit 592cddcf authored by yann300's avatar yann300

coding standard

parent b4d7d8c4
node_modules
npm-debug.log
...@@ -20,12 +20,13 @@ ...@@ -20,12 +20,13 @@
}, },
"devDependencies": { "devDependencies": {
"babel-preset-react": "^6.5.0", "babel-preset-react": "^6.5.0",
"babelify": "^7.2.0" "babelify": "^7.2.0",
"standard": "^7.0.1"
}, },
"scripts": { "scripts": {
"install": "npm install --save react react-dom; npm install -g browserify; npm install --save babelify babel-preset-react; npm install web3",
"start_node": "eth --rpccorsdomain \"*\" -j -v 0", "start_node": "eth --rpccorsdomain \"*\" -j -v 0",
"build": "mkdir -p build; browserify -t [ babelify --presets [ react ] ] src/index.js -o build/app.js" "build": "mkdir -p build; browserify -t [ babelify --presets [ react ] ] src/index.js -o build/app.js",
"test" : "standard"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
...@@ -36,5 +37,8 @@ ...@@ -36,5 +37,8 @@
"bugs": { "bugs": {
"url": "https://github.com/ethereum/remix/issues" "url": "https://github.com/ethereum/remix/issues"
}, },
"homepage": "https://github.com/ethereum/remix#readme" "homepage": "https://github.com/ethereum/remix#readme",
"standard": {
"global": ["web3"]
}
} }
var React = require('react'); var React = require('react')
var BasicPanel = require('./basicPanel') var BasicPanel = require('./basicPanel')
var Sticker = require('./sticker') var Sticker = require('./sticker')
var ButtonNavigator = require('./vmTraceButtonNavigator') var ButtonNavigator = require('./vmTraceButtonNavigator')
var codeUtils = require('./codeUtils') var codeUtils = require('./codeUtils')
var style = require('./basicStyles') var style = require('./basicStyles')
var Slider = require('./slider'); var Slider = require('./slider')
module.exports = React.createClass({ module.exports = React.createClass({
getInitialState: function () {
return {
currentSelected: -1, // current selected item in the vmTrace
selectedInst: -1, // current selected item in the contract assembly code
currentAddress: null,
currentStack: null,
currentLevels: null,
currentStorage: null,
currentMemory: null,
currentCallData: null,
currentStepInfo: null,
codes: {}, // assembly items instructions list by contract addesses
instructionsIndexByBytesOffset: {}, // mapping between bytes offset and instructions index.
callStack: {}
}
},
getInitialState: function() getDefaultProps: function () {
{ return {
return { vmTrace: null
currentSelected: -1, // current selected item in the vmTrace }
selectedInst: -1, // current selected item in the contract assembly code },
currentAddress: null,
currentStack: null, render: function () {
currentLevels: null, return (
currentStorage: null, <div style={this.props.vmTrace === null ? style.hidden : style.display}>
currentMemory: null, <div style={style.container}>
currentCallData: null, <span style={style.address}>Current code: {this.state.currentAddress}</span>
currentStepInfo: null, </div>
codes: {}, // assembly items instructions list by contract addesses <div style={style.container}>
instructionsIndexByBytesOffset: {}, // mapping between bytes offset and instructions index. <Slider
callStack: {} ref='slider'
}; onChange={this.selectState}
}, min='0'
max={this.props.vmTrace ? this.props.vmTrace.length : 0} />
getDefaultProps: function() <ButtonNavigator
{ vmTraceLength={this.props.vmTrace ? this.props.vmTrace.length : 0}
return { step={this.state.currentSelected}
vmTrace: null stepIntoBack={this.stepIntoBack}
}; stepIntoForward={this.stepIntoForward}
}, stepOverBack={this.stepOverBack}
stepOverForward={this.stepOverForward} />
render: function() </div>
{ <div style={style.container}>
return ( <table>
<div style={this.props.vmTrace === null ? style.hidden : style.display} > <tbody>
<div style={style.container}><span style={style.address}>Current code: {this.state.currentAddress}</span></div> <tr>
<div style={style.container}> <td>
<Slider ref="slider" onChange={this.selectState} min="0" max={this.props.vmTrace ? this.props.vmTrace.length : 0}/> <select
<ButtonNavigator size='10'
vmTraceLength={this.props.vmTrace ? this.props.vmTrace.length : 0} step={this.state.currentSelected} stepIntoBack={this.stepIntoBack} ref='itemsList'
stepIntoForward={this.stepIntoForward} stepOverBack={this.stepOverBack} stepOverForward={this.stepOverForward} /> style={style.instructionsList}
</div> value={this.state.selectedInst}>
<div style={style.container}> {this.renderAssemblyItems()}
<table> </select>
<tbody> <div style={Object.assign(style.inline, style.sticker)}>
<tr> <Sticker data={this.state.currentStepInfo} />
<td> </div>
<select size="10" ref='itemsList' style={style.instructionsList} value={this.state.selectedInst}> </td>
{ this.renderAssemblyItems() } <td>
</select> <BasicPanel name='CallData' data={this.state.currentCallData} />
<div style={Object.assign(style.inline, style.sticker)}> </td>
<Sticker data={this.state.currentStepInfo} /> </tr>
</div> <tr>
</td> <td>
<td> <BasicPanel name='Stack' data={this.state.currentStack} />
<BasicPanel name="CallData" data={this.state.currentCallData} /> </td>
</td> <td>
</tr> <BasicPanel name='CallStack' data={this.state.currentCallStack} />
<tr> </td>
<td> </tr>
<BasicPanel name="Stack" data={this.state.currentStack} /> <tr>
</td> <td>
<td> <BasicPanel name='Storage' data={this.state.currentStorage} renderRow={this.renderStorageRow} />
<BasicPanel name="CallStack" data={this.state.currentCallStack} /> </td>
</td> <td>
</tr> <BasicPanel name='Memory' data={this.state.currentMemory} renderRow={this.renderMemoryRow} />
<tr> </td>
<td> </tr>
<BasicPanel name="Storage" data={this.state.currentStorage} renderRow={this.renderStorageRow} /> </tbody>
</td> </table>
<td> </div>
<BasicPanel name="Memory" data={this.state.currentMemory} renderRow={this.renderMemoryRow} /> </div>
</td> )
</tr> },
</tbody>
</table> renderStorageRow: function (data) {
</div> var ret = []
</div> if (data) {
); for (var key in data) {
}, ret.push(
<tr key={key}>
renderStorageRow: function(data) <td>
{ {key}
var ret = [] </td>
if (data) <td>
{ {data[key]}
for (var key in data) </td>
ret.push(<tr key={key} ><td>{key}</td><td>{data[key]}</td></tr>) </tr>)
} }
return ret }
}, return ret
},
renderMemoryRow: function(data)
{ renderMemoryRow: function (data) {
var ret = [] var ret = []
if (data) if (data) {
{ for (var key in data) {
for (var key in data) var memSlot = data[key]
{ ret.push(
var memSlot = data[key] <tr key={key}>
ret.push(<tr key={key} ><td>{memSlot.address}</td><td>{memSlot.content.raw}</td><td>{memSlot.content.ascii}</td></tr>) <td>
} {memSlot.address}
} </td>
return ret <td>
}, {memSlot.content.raw}
</td>
resolveAddress: function(address) <td>
{ {memSlot.content.ascii}
if (!this.state.codes[address]) </td>
{ </tr>)
var hexCode = web3.eth.getCode(address) }
var code = codeUtils.nameOpCodes(new Buffer(hexCode.substring(2), 'hex')) }
this.state.codes[address] = code[0] return ret
this.state.instructionsIndexByBytesOffset[address] = code[1] },
}
}, resolveAddress: function (address) {
if (!this.state.codes[address]) {
renderAssemblyItems: function() var hexCode = web3.eth.getCode(address)
{ var code = codeUtils.nameOpCodes(new Buffer(hexCode.substring(2), 'hex'))
if (this.props.vmTrace) this.state.codes[address] = code[0]
{ this.state.instructionsIndexByBytesOffset[address] = code[1]
return this.state.codes[this.state.currentAddress].map(function(item, i) }
{ },
return <option key={i} value={i} >{item}</option>;
}); renderAssemblyItems: function () {
} if (this.props.vmTrace) {
}, return this.state.codes[this.state.currentAddress].map(function (item, i) {
return <option key={i} value={i}>{item}</option>
componentWillReceiveProps: function (nextProps) })
{ }
if (!nextProps.vmTrace) },
return
this.buildCallStack(nextProps.vmTrace) componentWillReceiveProps: function (nextProps) {
this.setState({"currentSelected": -1}) if (!nextProps.vmTrace) {
this.updateState(nextProps, 0) return
}, }
this.buildCallStack(nextProps.vmTrace)
buildCallStack: function(vmTrace) this.setState({'currentSelected': -1})
{ this.updateState(nextProps, 0)
if (!vmTrace) },
return
var callStack = [] buildCallStack: function (vmTrace) {
var depth = -1 if (!vmTrace) {
for (var k = 0; k < vmTrace.length; k++) return
{ }
var trace = vmTrace[k] var callStack = []
if (trace.depth === undefined || trace.depth === depth) var depth = -1
continue for (var k = 0; k < vmTrace.length; k++) {
if (trace.depth > depth) var trace = vmTrace[k]
callStack.push(trace.address) // new context if (trace.depth === undefined || trace.depth === depth) {
else if (trace.depth < depth) continue
callStack.pop() // returning from context }
depth = trace.depth if (trace.depth > depth) {
this.state.callStack[k] = callStack.slice(0) callStack.push(trace.address) // new context
} } else if (trace.depth < depth) {
}, callStack.pop() // returning from context
}
updateState: function(props, vmTraceIndex) depth = trace.depth
{ this.state.callStack[k] = callStack.slice(0)
if (!props.vmTrace || !props.vmTrace[vmTraceIndex]) }
return },
var previousIndex = this.state.currentSelected
var stateChanges = {} updateState: function (props, vmTraceIndex) {
if (!props.vmTrace || !props.vmTrace[vmTraceIndex]) {
if (props.vmTrace[vmTraceIndex].stack) // there's always a stack return
{ }
var stack = props.vmTrace[vmTraceIndex].stack var previousIndex = this.state.currentSelected
stack.reverse() var stateChanges = {}
stateChanges["currentStack"] = stack
} if (props.vmTrace[vmTraceIndex].stack) { // there's always a stack
var stack = props.vmTrace[vmTraceIndex].stack
var currentAddress = this.state.currentAddress stack.reverse()
var addressIndex = this.shouldUpdateStateProperty("address", vmTraceIndex, previousIndex, props.vmTrace) stateChanges['currentStack'] = stack
if (addressIndex > -1) }
{
currentAddress = props.vmTrace[addressIndex].address var currentAddress = this.state.currentAddress
this.resolveAddress(currentAddress) var addressIndex = this.shouldUpdateStateProperty('address', vmTraceIndex, previousIndex, props.vmTrace)
Object.assign(stateChanges, { "currentAddress": currentAddress }) if (addressIndex > -1) {
} currentAddress = props.vmTrace[addressIndex].address
this.resolveAddress(currentAddress)
var depthIndex = this.shouldUpdateStateProperty("depth", vmTraceIndex, previousIndex, props.vmTrace) Object.assign(stateChanges, { 'currentAddress': currentAddress })
if (depthIndex > -1) }
Object.assign(stateChanges, { "currentCallStack": this.state.callStack[depthIndex] })
var depthIndex = this.shouldUpdateStateProperty('depth', vmTraceIndex, previousIndex, props.vmTrace)
var storageIndex = this.shouldUpdateStateProperty("storage", vmTraceIndex, previousIndex, props.vmTrace) if (depthIndex > -1) {
if (storageIndex > -1) Object.assign(stateChanges, { 'currentCallStack': this.state.callStack[depthIndex] })
Object.assign(stateChanges, { "currentStorage": props.vmTrace[storageIndex].storage }) }
var memoryIndex = this.shouldUpdateStateProperty("memory", vmTraceIndex, previousIndex, props.vmTrace) var storageIndex = this.shouldUpdateStateProperty('storage', vmTraceIndex, previousIndex, props.vmTrace)
if (memoryIndex > -1) if (storageIndex > -1) {
Object.assign(stateChanges, { "currentMemory": this.formatMemory(props.vmTrace[memoryIndex].memory, 16) }) Object.assign(stateChanges, { 'currentStorage': props.vmTrace[storageIndex].storage })
}
var callDataIndex = this.shouldUpdateStateProperty("calldata", vmTraceIndex, previousIndex, props.vmTrace)
if (callDataIndex > -1) var memoryIndex = this.shouldUpdateStateProperty('memory', vmTraceIndex, previousIndex, props.vmTrace)
Object.assign(stateChanges, { "currentCallData": [props.vmTrace[callDataIndex].calldata] }) if (memoryIndex > -1) {
Object.assign(stateChanges, { 'currentMemory': this.formatMemory(props.vmTrace[memoryIndex].memory, 16) })
stateChanges["selectedInst"] = this.state.instructionsIndexByBytesOffset[currentAddress][props.vmTrace[vmTraceIndex].pc] }
stateChanges["currentSelected"] = vmTraceIndex
var callDataIndex = this.shouldUpdateStateProperty('calldata', vmTraceIndex, previousIndex, props.vmTrace)
stateChanges["currentStepInfo"] = [ if (callDataIndex > -1) {
"Current Step: " + props.vmTrace[vmTraceIndex].steps, Object.assign(stateChanges, { 'currentCallData': [props.vmTrace[callDataIndex].calldata] })
"Adding Memory: " + (props.vmTrace[vmTraceIndex].memexpand ? props.vmTrace[vmTraceIndex].memexpand : ""), }
"Step Cost: " + props.vmTrace[vmTraceIndex].gascost,
"Remaining Gas: " + props.vmTrace[vmTraceIndex].gas stateChanges['selectedInst'] = this.state.instructionsIndexByBytesOffset[currentAddress][props.vmTrace[vmTraceIndex].pc]
] stateChanges['currentSelected'] = vmTraceIndex
this.refs.slider.setValue(vmTraceIndex)
this.setState(stateChanges) stateChanges['currentStepInfo'] = [
}, 'Current Step: ' + props.vmTrace[vmTraceIndex].steps,
'Adding Memory: ' + (props.vmTrace[vmTraceIndex].memexpand ? props.vmTrace[vmTraceIndex].memexpand : ''),
shouldUpdateStateProperty: function(vmTraceName, nextIndex, previousIndex, vmTrace) 'Step Cost: ' + props.vmTrace[vmTraceIndex].gascost,
{ 'Remaining Gas: ' + props.vmTrace[vmTraceIndex].gas
var propIndex = -1 ]
if (previousIndex + 1 === nextIndex) this.refs.slider.setValue(vmTraceIndex)
propIndex = nextIndex this.setState(stateChanges)
else },
propIndex = this.retrieveLastSeenProperty(nextIndex, vmTraceName, vmTrace)
shouldUpdateStateProperty: function (vmTraceName, nextIndex, previousIndex, vmTrace) {
if (propIndex > -1 && vmTrace[propIndex][vmTraceName] !== undefined) var propIndex = -1
return propIndex if (previousIndex + 1 === nextIndex) {
else propIndex = nextIndex
return -1 } else {
}, propIndex = this.retrieveLastSeenProperty(nextIndex, vmTraceName, vmTrace)
}
retrieveLastSeenProperty: function(currentIndex, propertyName, vmTrace)
{ if (propIndex > -1 && vmTrace[propIndex][vmTraceName] !== undefined) {
var index = currentIndex return propIndex
while (index > 0) } else {
{ return -1
if (vmTrace[index][propertyName]) }
break },
index--
} retrieveLastSeenProperty: function (currentIndex, propertyName, vmTrace) {
return index var index = currentIndex
}, while (index > 0) {
if (vmTrace[index][propertyName]) {
stepIntoBack: function() break
{ }
this.moveSelection(-1) index--
}, }
return index
stepIntoForward: function() },
{
this.moveSelection(1) stepIntoBack: function () {
}, this.moveSelection(-1)
},
stepOverBack: function()
{ stepIntoForward: function () {
if (this.isReturnInstruction(this.state.currentSelected - 1)) this.moveSelection(1)
this.stepOutBack(); },
else
this.moveSelection(-1); stepOverBack: function () {
}, if (this.isReturnInstruction(this.state.currentSelected - 1)) {
this.stepOutBack()
stepOverForward: function() } else {
{ this.moveSelection(-1)
if (this.isCallInstruction(this.state.currentSelected)) }
this.stepOutForward(); },
else
this.moveSelection(1); stepOverForward: function () {
}, if (this.isCallInstruction(this.state.currentSelected)) {
this.stepOutForward()
isCallInstruction: function(index) } else {
{ this.moveSelection(1)
var state = this.props.vmTrace[index]; }
return state.instname === "CALL" || state.instname === "CALLCODE" || state.instname === "CREATE" || state.instname === "DELEGATECALL" },
},
isCallInstruction: function (index) {
isReturnInstruction: function(index) var state = this.props.vmTrace[index]
{ return state.instname === 'CALL' || state.instname === 'CALLCODE' || state.instname === 'CREATE' || state.instname === 'DELEGATECALL'
var state = this.props.vmTrace[index]; },
return state.instname === "RETURN"
}, isReturnInstruction: function (index) {
var state = this.props.vmTrace[index]
stepOutBack: function() return state.instname === 'RETURN'
{ },
var i = this.state.currentSelected - 1;
var depth = 0; stepOutBack: function () {
while (--i >= 0) var i = this.state.currentSelected - 1
{ var depth = 0
if (this.isCallInstruction(i)) while (--i >= 0) {
{ if (this.isCallInstruction(i)) {
if (depth == 0) if (depth === 0) {
break; break
else } else {
depth--; depth--
} }
else if (this.isReturnInstruction(i)) } else if (this.isReturnInstruction(i)) {
depth++; depth++
}
} }
this.selectState(i); this.selectState(i)
}, },
stepOutForward: function() stepOutForward: function () {
{ var i = this.state.currentSelected
var i = this.state.currentSelected var depth = 0
var depth = 0 while (++i < this.props.vmTrace.length) {
while (++i < this.props.vmTrace.length) if (this.isReturnInstruction(i)) {
{ if (depth === 0) {
if (this.isReturnInstruction(i)) break
{ } else {
if (depth == 0) depth--
break }
else } else if (this.isCallInstruction(i)) {
depth-- depth++
} }
else if (this.isCallInstruction(i)) }
depth++ this.selectState(i + 1)
} },
this.selectState(i + 1);
}, moveSelection: function (incr) {
this.selectState(this.state.currentSelected + incr)
moveSelection: function(incr) },
{
this.selectState(this.state.currentSelected + incr) selectState: function (index) {
}, this.updateState(this.props, index)
},
selectState: function(index)
{ formatMemory: function (mem, width) {
this.updateState(this.props, index) var ret = []
}, for (var k = 0; k < mem.length; k += (width * 2)) {
var memory = mem.substr(k, width * 2)
formatMemory: function(mem, width) ret.push({
{ address: web3.toHex(k),
var ret = [] content: this.tryAsciiFormat(memory)
for (var k = 0; k < mem.length; k += (width * 2)) })
{ }
var memory = mem.substr(k, width * 2) return ret
ret.push({ },
address: web3.toHex(k),
content: this.tryAsciiFormat(memory) tryAsciiFormat: function (memorySlot) {
}) var ret = { ascii: '', raw: '' }
} for (var k = 0; k < memorySlot.length; k += 2) {
return ret var raw = memorySlot.substr(k, 2)
}, var ascii = web3.toAscii(raw)
if (ascii === String.fromCharCode(0)) {
tryAsciiFormat: function(memorySlot) ret.ascii += '?'
{ } else {
var ret = { ascii: "", raw: "" } ret.ascii += ascii
for (var k = 0; k < memorySlot.length; k += 2) }
{ ret.raw += ' ' + raw
var raw = memorySlot.substr(k, 2) }
var ascii = web3.toAscii(raw) return ret
if (ascii === String.fromCharCode(0)) }
ret.ascii += "?"
else
ret.ascii += ascii
ret.raw += " " + raw
}
return ret
}
}) })
var React = require('react'); var React = require('react')
var style = require('./basicStyles') var style = require('./basicStyles')
module.exports = React.createClass({ module.exports = React.createClass({
getDefaultProps: function () {
return {
data: null,
name: null,
renderRow: null
}
},
getDefaultProps: function() render: function () {
{ return (
return { <div style={style.panel.container}>
data: null, <div style={style.panel.title}>
name: null, {this.props.name}
renderRow: null </div>
}; <div style={style.panel.tableContainer}>
}, <table style={style.panel.table}>
<tbody>
{this.renderItems()}
</tbody>
</table>
</div>
</div>
)
},
render: function() renderItems: function () {
{ if (!this.props.data) {
return ( return []
<div style={style.panel.container}> }
<div style={style.panel.title} >{this.props.name}</div> if (!this.props.renderRow) {
<div style={style.panel.tableContainer} > var ret = []
<table style={style.panel.table}> for (var key in this.props.data) {
<tbody> ret.push(
{this.renderItems()} <tr key={key}>
</tbody> <td>
</table> {this.props.data[key]}
</div> </td>
</div> </tr>)
); }
}, return ret
} else {
renderItems: function() return this.props.renderRow(this.props.data)
{ }
if (!this.props.data) }
return []
if (!this.props.renderRow)
{
var ret = []
for (var key in this.props.data)
ret.push(<tr key={key} ><td>{this.props.data[key]}</td></tr>)
return ret
}
else
return this.props.renderRow(this.props.data)
}
}) })
module.exports = { module.exports = {
wrapper: wrapper: {
{ 'fontFamily': 'arial,sans-serif'
'fontFamily': "arial,sans-serif" },
}, container: {
container: 'margin': '10px',
{ 'padding': '5px'
'margin': '10px', },
'padding': '5px' address: {
}, 'fontStyle': 'italic'
address: },
{ instructionsList: {
'fontStyle': 'italic' 'width': '320px'
}, },
instructionsList: transactionInfo: {
{ 'marginTop': '5px'
'width': "320px" },
}, panel: {
transactionInfo: container: {
{ 'border': '1px solid',
'marginTop': '5px' 'width': '600px'
}, },
panel: tableContainer: {
{ 'height': '150px',
container: 'overflowY': 'auto'
{ },
'border': '1px solid', table: {
'width': '600px' 'padding': '5px'
}, },
tableContainer: title: {
{ 'padding': '5px',
'height': '150px', 'fontStyle': 'italic'
'overflowY': 'auto' }
}, },
table: hidden: {
{ 'display': 'none'
'padding': '5px' },
}, display: {
title: 'display': 'block'
{ },
'padding': '5px', sticker: {
'fontStyle': 'italic' 'verticalAlign': 'top',
} 'margin': '5px'
}, },
hidden: inline: {
{ 'display': 'inline-block'
'display': 'none' }
}, }
display:
{
'display': 'block'
},
sticker:
{
'verticalAlign': 'top',
'margin': '5px'
},
inline:
{
'display': 'inline-block'
}
}
\ No newline at end of file
var opcodes = require('./opcodes') var opcodes = require('./opcodes')
module.exports = { module.exports = {
nameOpCodes: function (raw) {
var pushData = ''
var codeMap = {}
var code = []
nameOpCodes: function (raw) for (var i = 0; i < raw.length; i++) {
{ var pc = i
var pushData = '' var curOpCode = opcodes(raw[pc], false).name
var codeMap = {} codeMap[i] = code.length
var code = [] // no destinations into the middle of PUSH
if (curOpCode.slice(0, 4) === 'PUSH') {
var jumpNum = raw[pc] - 0x5f
pushData = raw.slice(pc + 1, pc + jumpNum + 1)
i += jumpNum
}
for (var i = 0; i < raw.length; i++) code.push(this.pad(pc, this.roundLog(raw.length, 10)) + ' ' + curOpCode + ' ' + pushData.toString('hex'))
{ pushData = ''
var pc = i }
var curOpCode = opcodes(raw[pc], false).name return [ code, codeMap ]
codeMap[i] = code.length },
// no destinations into the middle of PUSH
if (curOpCode.slice(0, 4) === 'PUSH')
{
var jumpNum = raw[pc] - 0x5f
pushData = raw.slice(pc + 1, pc + jumpNum + 1)
i += jumpNum
}
code.push(this.pad(pc, this.roundLog(raw.length, 10)) + ' ' + curOpCode + ' ' + pushData.toString('hex'))
pushData = ''
}
return [ code, codeMap ]
},
pad: function (num, size) { pad: function (num, size) {
var s = num + '' var s = num + ''
while (s.length < size) s = '0' + s while (s.length < size) s = '0' + s
return s return s
}, },
log: function (num, base) { log: function (num, base) {
return Math.log(num) / Math.log(base) return Math.log(num) / Math.log(base)
}, },
roundLog: function (num, base) { roundLog: function (num, base) {
return Math.ceil(this.log(num, base)) return Math.ceil(this.log(num, base))
} }
} }
\ No newline at end of file
var React = require('react'); var React = require('react')
var TxBrowser = require('./txBrowser'); var TxBrowser = require('./txBrowser')
var VmTraceManager = require('./vmTraceManager'); var VmTraceManager = require('./vmTraceManager')
var VmTraceBrowser = require('./vmTraceBrowser'); var VmTraceBrowser = require('./vmTraceBrowser')
var style = require('./basicStyles') var style = require('./basicStyles')
module.exports = React.createClass({ module.exports = React.createClass({
getInitialState: function() { getInitialState: function () {
return {vmTrace: null, state: "", currentStep: -1} return {vmTrace: null, state: '', currentStep: -1}
}, },
render: function() { render: function () {
return ( return (
<div style={style.wrapper} > <div style={style.wrapper}>
<h1 style={style.container} >Eth Debugger</h1> <h1 style={style.container}>Eth Debugger</h1>
<TxBrowser onNewTxRequested={this.retrieveVmTrace} /> <TxBrowser onNewTxRequested={this.retrieveVmTrace} />
<div style={style.container} >{this.state.state}</div> <div style={style.container}>
<VmTraceBrowser vmTrace={this.state.vmTrace} /> {this.state.state}
</div> </div>
); <VmTraceBrowser vmTrace={this.state.vmTrace} />
}, </div>
)
},
retrieveVmTrace: function(blockNumber, txNumber) retrieveVmTrace: function (blockNumber, txNumber) {
{ this.setState({state: 'loading...'})
this.setState({state: "loading..."}) var deb = this
var deb = this VmTraceManager.retrieveVmTrace(blockNumber, txNumber, function (error, result) {
VmTraceManager.retrieveVmTrace(blockNumber, txNumber, function(error, result) if (error) {
{ console.log(error)
deb.setState({vmTrace: result, state: ""}); } else {
}) deb.setState({vmTrace: result, state: ''})
} }
}); })
}
})
var ReactDOM = require('react-dom'); var ReactDOM = require('react-dom')
var React = require('react'); var React = require('react')
var Web3 = require('web3'); var Web3 = require('web3')
var Web3Admin = require('./web3Admin') var Web3Admin = require('./web3Admin')
web3 = new Web3(); var web3 = new Web3()
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'))
Web3Admin.extend(web3); Web3Admin.extend(web3)
var Debugger = require('./debugger'); var Debugger = require('./debugger')
ReactDOM.render( ReactDOM.render(
<Debugger/>, <Debugger />,
document.getElementById('app') document.getElementById('app')
); )
...@@ -175,4 +175,4 @@ module.exports = function (op, full) { ...@@ -175,4 +175,4 @@ module.exports = function (op, full) {
} }
return {name: opcode, fee: code[1], in: code[2], out: code[3], dynamic: code[4], async: code[5]} return {name: opcode, fee: code[1], in: code[2], out: code[3], dynamic: code[4], async: code[5]}
} }
\ No newline at end of file
var React = require('react'); var React = require('react')
var style = require('./sliderStyles') var style = require('./sliderStyles')
module.exports = React.createClass({ module.exports = React.createClass({
propTypes: {
onChange: React.PropTypes.func.isRequired
},
propTypes: { getDefaultProps: function () {
onChange: React.PropTypes.func.isRequired, return {
}, min: 0,
max: 500
getDefaultProps: function () { }
return { },
min: 0,
max: 500
};
},
render: function () { render: function () {
return ( return (
<div> <div>
<input ref="rule" style={style.rule} type="range" min={this.props.min} max={this.props.max} onMouseUp={this.onMouseUp} /> <input
</div> ref='rule'
); style={style.rule}
}, type='range'
min={this.props.min}
max={this.props.max}
onMouseUp={this.onMouseUp} />
</div>
)
},
onMouseUp: function (event) { onMouseUp: function (event) {
this.props.onChange(parseInt(this.refs.rule.value)) this.props.onChange(parseInt(this.refs.rule.value))
}, },
setValue: function (value) { setValue: function (value) {
var diff = value - this.refs.rule.value var diff = value - this.refs.rule.value
if (diff > 0) if (diff > 0) {
this.refs.rule.stepUp(diff) this.refs.rule.stepUp(diff)
else } else {
this.refs.rule.stepDown(Math.abs(diff)) this.refs.rule.stepDown(Math.abs(diff))
} }
}
}) })
module.exports = { module.exports = {
rule: rule: {
{ 'width': '600px'
'width': '600px', },
}, runner: {
runner: 'position': 'absolute',
{ 'width': '16px',
'position': 'absolute', 'height': '16px',
'width': '16px', 'margin': '0',
'height': '16px', 'padding': '0',
'margin': '0', 'overflow': 'hidden',
'padding': '0', 'border': '1px solid #a4bed4',
'overflow': 'hidden', 'background-color': '#f1f7ff'
'border': '1px solid #a4bed4', }
'background-color': '#f1f7ff' }
}
}
\ No newline at end of file
var React = require('react'); var React = require('react')
var style = require('./basicStyles')
module.exports = React.createClass({ module.exports = React.createClass({
getDefaultProps: function () {
return {
data: null
}
},
getDefaultProps: function() render: function () {
{ return (
return { <div>
data: null, <table>
}; <tbody>
}, {this.renderItems()}
</tbody>
</table>
</div>
)
},
render: function() renderItems: function () {
{ if (this.props.data) {
return ( var ret = []
<div> for (var key in this.props.data) {
<table><tbody> ret.push(
{this.renderItems()} <tr key={key}>
</tbody></table> <td>
</div> {this.props.data[key]}
); </td>
}, </tr>)
}
renderItems: function() return ret
{ }
return null
if (this.props.data) }
{
var ret = []
for (var key in this.props.data)
ret.push(<tr key={key}><td>{this.props.data[key]}</td></tr>)
return ret
}
return null
},
}) })
var React = require('react'); var React = require('react')
var style = require('./basicStyles') var style = require('./basicStyles')
module.exports = React.createClass({ module.exports = React.createClass({
propTypes: { propTypes: {
onNewTxRequested: React.PropTypes.func.isRequired, onNewTxRequested: React.PropTypes.func.isRequired
}, },
getInitialState: function() { getInitialState: function () {
return {blockNumber: "1382256", txNumber: "1", from: "", to: "", hash: ""} return {blockNumber: '1382256', txNumber: '1', from: '', to: '', hash: ''}
}, },
submit: function() submit: function () {
{ var tx = web3.eth.getTransactionFromBlock(this.state.blockNumber, this.state.txNumber)
var tx = web3.eth.getTransactionFromBlock(this.state.blockNumber, this.state.txNumber) if (tx) {
if (tx) this.setState({from: tx.from, to: tx.to, hash: tx.hash})
this.setState({from: tx.from, to: tx.to, hash: tx.hash}) }
this.props.onNewTxRequested(this.state.blockNumber, parseInt(this.state.txNumber)) this.props.onNewTxRequested(this.state.blockNumber, parseInt(this.state.txNumber))
}, },
updateBlockN: function(ev) {
this.state.blockNumber = ev.target.value;
},
updateTxN: function(ev) {
this.state.txNumber = ev.target.value;
},
render: function() { updateBlockN: function (ev) {
return ( this.state.blockNumber = ev.target.value
<div style={style.container} > },
<input onChange={this.updateBlockN} type="text" placeholder= {"Block number or hash (default 1382256)" + this.state.blockNumber}></input>
<input onChange={this.updateTxN} type="text" placeholder={"Transaction Number (default 1) " + this.state.txNumber}></input> updateTxN: function (ev) {
<button onClick={this.submit}>Get</button> this.state.txNumber = ev.target.value
<div style={style.transactionInfo}> },
<div>Hash: {this.state.hash}</div>
<div>From: {this.state.from}</div> render: function () {
<div>To: {this.state.to}</div> return (
</div> <div style={style.container}>
</div> <input onChange={this.updateBlockN} type='text' placeholder={'Block number or hash (default 1382256)' + this.state.blockNumber}></input>
); <input onChange={this.updateTxN} type='text' placeholder={'Transaction Number (default 1) ' + this.state.txNumber}></input>
} <button onClick={this.submit}>
Get
</button>
<div style={style.transactionInfo}>
<div>
Hash:
{this.state.hash}
</div>
<div>
From:
{this.state.from}
</div>
<div>
To:
{this.state.to}
</div>
</div>
</div>
)
}
}) })
var React = require('react'); var React = require('react')
var AssemblyItemsBrowser = require('./assemblyItemsBrowser'); var AssemblyItemsBrowser = require('./assemblyItemsBrowser')
module.exports = React.createClass({ module.exports = React.createClass({
render: function () {
render: function() { return (
return ( <div>
<div> <AssemblyItemsBrowser vmTrace={this.props.vmTrace} />
<AssemblyItemsBrowser vmTrace={this.props.vmTrace} /> </div>
</div> )
) }
}, })
});
var React = require('react'); var React = require('react')
module.exports = React.createClass({ module.exports = React.createClass({
propTypes: {
propTypes: { stepIntoBack: React.PropTypes.func.isRequired,
stepIntoBack: React.PropTypes.func.isRequired, stepIntoForward: React.PropTypes.func.isRequired,
stepIntoForward: React.PropTypes.func.isRequired, stepOverBack: React.PropTypes.func.isRequired,
stepOverBack: React.PropTypes.func.isRequired, stepOverForward: React.PropTypes.func.isRequired
stepOverForward: React.PropTypes.func.isRequired, },
},
render: function () {
render: function() { return (
return ( <div>
<div> <button onClick={this.props.stepIntoBack} disabled={this.checkButtonState(-1)}>
<button onClick={this.props.stepIntoBack} disabled={this.checkButtonState(-1)} >Step Into Back</button> Step Into Back
<button onClick={this.props.stepOverBack} disabled={this.checkButtonState(-1)} >Step Over Back</button> </button>
<button onClick={this.props.stepOverForward} disabled={this.checkButtonState(1)} >Step Over Forward</button> <button onClick={this.props.stepOverBack} disabled={this.checkButtonState(-1)}>
<button onClick={this.props.stepIntoForward} disabled={this.checkButtonState(1)} >Step Into Forward</button> Step Over Back
</div> </button>
); <button onClick={this.props.stepOverForward} disabled={this.checkButtonState(1)}>
}, Step Over Forward
</button>
checkButtonState: function(incr) <button onClick={this.props.stepIntoForward} disabled={this.checkButtonState(1)}>
{ Step Into Forward
if (incr === -1) </button>
return this.props.step === 0 ? "disabled" : "" </div>
else if (incr === 1) )
return this.props.step >= this.props.vmTraceLength - 1 ? "disabled" : "" },
},
}) checkButtonState: function (incr) {
\ No newline at end of file if (incr === -1) {
return this.props.step === 0 ? 'disabled' : ''
} else if (incr === 1) {
return this.props.step >= this.props.vmTraceLength - 1 ? 'disabled' : ''
}
}
})
module.exports = { module.exports = {
retrieveVmTrace: function(blockNumber, txNumber, callBack) { retrieveVmTrace: function (blockNumber, txNumber, callBack) {
web3.debug.trace(blockNumber, parseInt(txNumber), function(error, result) web3.debug.trace(blockNumber, parseInt(txNumber), function (error, result) {
{ callBack(error, result)
callBack(error, result) })
}); }
}
} }
module.exports = { module.exports = {
extend: function(web3) { extend: function (web3) {
// ADMIN
web3._extend({
property: 'admin',
methods: [
new web3._extend.Method({
name: 'addPeer',
call: 'admin_addPeer',
params: 1,
inputFormatter: [web3._extend.utils.fromDecimal],
outputFormatter: web3._extend.formatters.formatOutputBool
}),
new web3._extend.Method({
name: 'exportChain',
call: 'admin_exportChain',
params: 1,
inputFormatter: [null],
outputFormatter: function (obj) { return obj }
}),
new web3._extend.Method({
name: 'importChain',
call: 'admin_importChain',
params: 1,
inputFormatter: [null],
outputFormatter: function (obj) { return obj }
}),
new web3._extend.Method({
name: 'verbosity',
call: 'admin_verbosity',
params: 1,
inputFormatter: [web3._extend.utils.formatInputInt],
outputFormatter: web3._extend.formatters.formatOutputBool
}),
new web3._extend.Method({
name: 'setSolc',
call: 'admin_setSolc',
params: 1,
inputFormatter: [null],
outputFormatter: web3._extend.formatters.formatOutputString
}),
new web3._extend.Method({
name: 'startRPC',
call: 'admin_startRPC',
params: 4,
inputFormatter: [null, web3._extend.utils.formatInputInteger, null, null],
outputFormatter: web3._extend.formatters.formatOutputBool
}),
new web3._extend.Method({
name: 'stopRPC',
call: 'admin_stopRPC',
params: 0,
inputFormatter: [],
outputFormatter: web3._extend.formatters.formatOutputBool
}),
new web3._extend.Method({
name: 'vmTrace',
call: 'admin_eth_vmTrace',
inputFormatter: [null, null, null],
params: 3
})
],
properties: [
new web3._extend.Property({
name: 'nodeInfo',
getter: 'admin_nodeInfo',
outputFormatter: web3._extend.formatters.formatOutputString
}),
new web3._extend.Property({
name: 'peers',
getter: 'admin_peers',
outputFormatter: function (obj) { return obj }
}),
new web3._extend.Property({
name: 'datadir',
getter: 'admin_datadir',
outputFormatter: web3._extend.formatters.formatOutputString
}),
new web3._extend.Property({
name: 'chainSyncStatus',
getter: 'admin_chainSyncStatus',
outputFormatter: function (obj) { return obj }
})
]
})
// ADMIN // DEBUG
web3._extend({ web3._extend({
property: 'admin', property: 'debug',
methods: methods: [
[ new web3._extend.Method({
new web3._extend.Method({ name: 'trace',
name: 'addPeer', call: 'debug_trace',
call: 'admin_addPeer', inputFormatter: [null, null],
params: 1, params: 2
inputFormatter: [web3._extend.utils.fromDecimal], }),
outputFormatter: web3._extend.formatters.formatOutputBool new web3._extend.Method({
}), name: 'printBlock',
new web3._extend.Method({ call: 'debug_printBlock',
name: 'exportChain', params: 1,
call: 'admin_exportChain', inputFormatter: [web3._extend.formatters.formatInputInt],
params: 1, outputFormatter: web3._extend.formatters.formatOutputString
inputFormatter: [null], }),
outputFormatter: function(obj) { return obj; } new web3._extend.Method({
}), name: 'getBlockRlp',
new web3._extend.Method({ call: 'debug_getBlockRlp',
name: 'importChain', params: 1,
call: 'admin_importChain', inputFormatter: [web3._extend.formatters.formatInputInt],
params: 1, outputFormatter: web3._extend.formatters.formatOutputString
inputFormatter: [null], }),
outputFormatter: function(obj) { return obj; } new web3._extend.Method({
}), name: 'setHead',
new web3._extend.Method({ call: 'debug_setHead',
name: 'verbosity', params: 1,
call: 'admin_verbosity', inputFormatter: [web3._extend.formatters.formatInputInt],
params: 1, outputFormatter: web3._extend.formatters.formatOutputBool
inputFormatter: [web3._extend.utils.formatInputInt], }),
outputFormatter: web3._extend.formatters.formatOutputBool new web3._extend.Method({
}), name: 'processBlock',
new web3._extend.Method({ call: 'debug_processBlock',
name: 'setSolc', params: 1,
call: 'admin_setSolc', inputFormatter: [web3._extend.formatters.formatInputInt],
params: 1, outputFormatter: function (obj) { return obj }
inputFormatter: [null], }),
outputFormatter: web3._extend.formatters.formatOutputString new web3._extend.Method({
}), name: 'seedHash',
new web3._extend.Method({ call: 'debug_seedHash',
name: 'startRPC', params: 1,
call: 'admin_startRPC', inputFormatter: [web3._extend.formatters.formatInputInt],
params: 4, outputFormatter: web3._extend.formatters.formatOutputString
inputFormatter: [null,web3._extend.utils.formatInputInteger,null,null], }),
outputFormatter: web3._extend.formatters.formatOutputBool new web3._extend.Method({
}), name: 'dumpBlock',
new web3._extend.Method({ call: 'debug_dumpBlock',
name: 'stopRPC', params: 1,
call: 'admin_stopRPC', inputFormatter: [web3._extend.formatters.formatInputInt],
params: 0, outputFormatter: function (obj) { return obj }
inputFormatter: [], })
outputFormatter: web3._extend.formatters.formatOutputBool ],
}), properties: []
new web3._extend.Method({ })
name: 'vmTrace',
call: 'admin_eth_vmTrace',
inputFormatter: [null, null, null],
params: 3
}),
],
properties:
[
new web3._extend.Property({
name: 'nodeInfo',
getter: 'admin_nodeInfo',
outputFormatter: web3._extend.formatters.formatOutputString
}),
new web3._extend.Property({
name: 'peers',
getter: 'admin_peers',
outputFormatter: function(obj) { return obj; }
}),
new web3._extend.Property({
name: 'datadir',
getter: 'admin_datadir',
outputFormatter: web3._extend.formatters.formatOutputString
}),
new web3._extend.Property({
name: 'chainSyncStatus',
getter: 'admin_chainSyncStatus',
outputFormatter: function(obj) { return obj; }
})
]
});
// DEBUG // MINER
web3._extend({ web3._extend({
property: 'debug', property: 'miner',
methods: methods: [
[ new web3._extend.Method({
new web3._extend.Method({ name: 'start',
name: 'trace', call: 'miner_start',
call: 'debug_trace', params: 1,
params: 1, inputFormatter: [web3._extend.formatters.formatInputInt],
inputFormatter: [null, null], outputFormatter: web3._extend.formatters.formatOutputBool
params: 2 }),
}), new web3._extend.Method({
new web3._extend.Method({ name: 'stop',
name: 'printBlock', call: 'miner_stop',
call: 'debug_printBlock', params: 1,
params: 1, inputFormatter: [web3._extend.formatters.formatInputInt],
inputFormatter: [web3._extend.formatters.formatInputInt], outputFormatter: web3._extend.formatters.formatOutputBool
outputFormatter: web3._extend.formatters.formatOutputString }),
}), new web3._extend.Method({
new web3._extend.Method({ name: 'setExtra',
name: 'getBlockRlp', call: 'miner_setExtra',
call: 'debug_getBlockRlp', params: 1,
params: 1, inputFormatter: [web3._extend.utils.formatInputString],
inputFormatter: [web3._extend.formatters.formatInputInt], outputFormatter: web3._extend.formatters.formatOutputBool
outputFormatter: web3._extend.formatters.formatOutputString }),
}), new web3._extend.Method({
new web3._extend.Method({ name: 'setGasPrice',
name: 'setHead', call: 'miner_setGasPrice',
call: 'debug_setHead', params: 1,
params: 1, inputFormatter: [web3._extend.utils.formatInputString],
inputFormatter: [web3._extend.formatters.formatInputInt], outputFormatter: web3._extend.formatters.formatOutputBool
outputFormatter: web3._extend.formatters.formatOutputBool }),
}), new web3._extend.Method({
new web3._extend.Method({ name: 'startAutoDAG',
name: 'processBlock', call: 'miner_startAutoDAG',
call: 'debug_processBlock', params: 0,
params: 1, inputFormatter: [],
inputFormatter: [web3._extend.formatters.formatInputInt], outputFormatter: web3._extend.formatters.formatOutputBool
outputFormatter: function(obj) { return obj; } }),
}), new web3._extend.Method({
new web3._extend.Method({ name: 'stopAutoDAG',
name: 'seedHash', call: 'miner_stopAutoDAG',
call: 'debug_seedHash', params: 0,
params: 1, inputFormatter: [],
inputFormatter: [web3._extend.formatters.formatInputInt], outputFormatter: web3._extend.formatters.formatOutputBool
outputFormatter: web3._extend.formatters.formatOutputString }),
}) , new web3._extend.Method({
new web3._extend.Method({ name: 'makeDAG',
name: 'dumpBlock', call: 'miner_makeDAG',
call: 'debug_dumpBlock', params: 1,
params: 1, inputFormatter: [web3._extend.formatters.inputDefaultBlockNumberFormatter],
inputFormatter: [web3._extend.formatters.formatInputInt], outputFormatter: web3._extend.formatters.formatOutputBool
outputFormatter: function(obj) { return obj; } })
}) ],
], properties: [
properties: new web3._extend.Property({
[ name: 'hashrate',
] getter: 'miner_hashrate',
}); outputFormatter: web3._extend.utils.toDecimal
})
]
})
// MINER // NETWORK
web3._extend({ web3._extend({
property: 'miner', property: 'network',
methods: methods: [
[ new web3._extend.Method({
new web3._extend.Method({ name: 'addPeer',
name: 'start', call: 'net_addPeer',
call: 'miner_start', params: 1,
params: 1, inputFormatter: [web3._extend.utils.formatInputString],
inputFormatter: [web3._extend.formatters.formatInputInt], outputFormatter: web3._extend.formatters.formatOutputBool
outputFormatter: web3._extend.formatters.formatOutputBool }),
}), new web3._extend.Method({
new web3._extend.Method({ name: 'getPeerCount',
name: 'stop', call: 'net_peerCount',
call: 'miner_stop', params: 0,
params: 1, inputFormatter: [],
inputFormatter: [web3._extend.formatters.formatInputInt], outputFormatter: web3._extend.formatters.formatOutputString
outputFormatter: web3._extend.formatters.formatOutputBool })
}), ],
new web3._extend.Method({ properties: [
name: 'setExtra', new web3._extend.Property({
call: 'miner_setExtra', name: 'listening',
params: 1, getter: 'net_listening',
inputFormatter: [web3._extend.utils.formatInputString], outputFormatter: web3._extend.formatters.formatOutputBool
outputFormatter: web3._extend.formatters.formatOutputBool }),
}), new web3._extend.Property({
new web3._extend.Method({ name: 'peerCount',
name: 'setGasPrice', getter: 'net_peerCount',
call: 'miner_setGasPrice', outputFormatter: web3._extend.utils.toDecimal
params: 1, }),
inputFormatter: [web3._extend.utils.formatInputString], new web3._extend.Property({
outputFormatter: web3._extend.formatters.formatOutputBool name: 'peers',
}), getter: 'net_peers',
new web3._extend.Method({ outputFormatter: function (obj) { return obj }
name: 'startAutoDAG', }),
call: 'miner_startAutoDAG', new web3._extend.Property({
params: 0, name: 'version',
inputFormatter: [], getter: 'net_version',
outputFormatter: web3._extend.formatters.formatOutputBool outputFormatter: web3._extend.formatters.formatOutputString
}), })
new web3._extend.Method({ ]
name: 'stopAutoDAG', })
call: 'miner_stopAutoDAG',
params: 0,
inputFormatter: [],
outputFormatter: web3._extend.formatters.formatOutputBool
}),
new web3._extend.Method({
name: 'makeDAG',
call: 'miner_makeDAG',
params: 1,
inputFormatter: [web3._extend.formatters.inputDefaultBlockNumberFormatter],
outputFormatter: web3._extend.formatters.formatOutputBool
})
],
properties:
[
new web3._extend.Property({
name: 'hashrate',
getter: 'miner_hashrate',
outputFormatter: web3._extend.utils.toDecimal
})
]
});
// NETWORK
web3._extend({
property: 'network',
methods:
[
new web3._extend.Method({
name: 'addPeer',
call: 'net_addPeer',
params: 1,
inputFormatter: [web3._extend.utils.formatInputString],
outputFormatter: web3._extend.formatters.formatOutputBool
}),
new web3._extend.Method({
name: 'getPeerCount',
call: 'net_peerCount',
params: 0,
inputFormatter: [],
outputFormatter: web3._extend.formatters.formatOutputString
})
],
properties:
[
new web3._extend.Property({
name: 'listening',
getter: 'net_listening',
outputFormatter: web3._extend.formatters.formatOutputBool
}),
new web3._extend.Property({
name: 'peerCount',
getter: 'net_peerCount',
outputFormatter: web3._extend.utils.toDecimal
}),
new web3._extend.Property({
name: 'peers',
getter: 'net_peers',
outputFormatter: function(obj) { return obj; }
}),
new web3._extend.Property({
name: 'version',
getter: 'net_version',
outputFormatter: web3._extend.formatters.formatOutputString
})
]
});
// TX POOL
web3._extend({
property: 'txpool',
methods:
[
],
properties:
[
new web3._extend.Property({
name: 'status',
getter: 'txpool_status',
outputFormatter: function(obj) { return obj; }
})
]
});
}
};
// TX POOL
web3._extend({
property: 'txpool',
methods: [],
properties: [
new web3._extend.Property({
name: 'status',
getter: 'txpool_status',
outputFormatter: function (obj) { return obj }
})
]
})
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment