Skip to content

Commit

Permalink
Select for bollean in interactions with smart-contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
vbaranov committed Dec 19, 2018
2 parents 77d42f3 + 99c79e0 commit fcfb3e6
Show file tree
Hide file tree
Showing 6 changed files with 39,016 additions and 39,111 deletions.
215 changes: 134 additions & 81 deletions old-ui/app/components/send/send-contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,22 @@ import abiEncoder from 'web3-eth-abi'
import Web3 from 'web3'
import copyToClipboard from 'copy-to-clipboard'

class SendTransactionInputText extends Component {
class SendTransactionField extends Component {
constructor (props) {
super(props)
this.state = {
inputVal: props.defaultValue,
val: props.defaultValue,
}
}

static propTypes = {
placeholder: PropTypes.string,
defaultValue: PropTypes.string,
defaultValue: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.bool,
]),
disabled: PropTypes.bool,
value: PropTypes.string,
onChange: PropTypes.func,
}
Expand All @@ -30,16 +35,16 @@ class SendTransactionInputText extends Component {
return (
<input
type="text"
className="input large-input"
className="input large-input output"
placeholder={this.props.placeholder}
value={this.state.inputVal}
value={this.state.val}
disabled={this.props.disabled}
onChange={(val) => {
this.setState({
inputVal: val,
})
this.props.onChange(val)
}
}
this.setState({
val,
})
this.props.onChange(val)
}}
style={{ marginTop: '5px' }}
/>
)
Expand All @@ -50,7 +55,7 @@ class SendTransactionInputSelect extends Component {
constructor (props) {
super(props)
this.state = {
inputVal: props.defaultValue,
val: props.defaultValue,
}
}

Expand All @@ -64,17 +69,17 @@ class SendTransactionInputSelect extends Component {
return (
<Select
clearable={false}
value={this.state.inputVal}
value={this.state.val}
options={[{
label: 'false',
value: false
value: 'false',
}, {
label: 'true',
value: true
value: 'true',
}]}
onChange={(opt) => {
this.setState({
inputVal: opt.value,
val: opt.value,
})
this.props.onChange(opt.value)
}
Expand All @@ -89,18 +94,21 @@ class SendTransactionScreen extends PersistentForm {
constructor (props) {
super(props)
this.state = {
web3: new Web3(global.ethereumProvider),
options: [],
abi: [],
methodSelected: props.methodSelected,
methodABI: props.methodABI,
methodInputs: [],
methodOutputs: [],
methodInputsView: [],
methodOutput: null,
methodOutputsView: [],
isConstantMethod: false,
inputValues: props.inputValues || {},
output: '',
outputValues: props.outputValues || {},
copyDisabled: true,
}

this.timerID = null
PersistentForm.call(this)
}
Expand Down Expand Up @@ -140,15 +148,16 @@ class SendTransactionScreen extends PersistentForm {
methodSelected: opt.value,
isConstantMethod: opt.metadata.constant,
methodABI: opt.metadata,
output: '',
outputValues: {},
inputValues: {},
}, () => {
this.generateMethodFieldsView(opt.metadata)
})
this.generateMethodInputsView(opt.metadata)
}}
/>
<div style={{ overflow: 'auto', maxHeight: this.state.isConstantMethod ? '120px' : '210px' }}>
{this.state.methodInputsView}
</div>
</div>
<div style={{ padding: '0 30px', overflow: 'auto', 'maxHeight': '280px' }}>
{this.state.methodInputsView}
{this.state.isConstantMethod && this.methodOutput()}
{this.buttonsSection()}
</div>
Expand All @@ -158,14 +167,14 @@ class SendTransactionScreen extends PersistentForm {

componentDidMount () {
if (this.props.methodSelected) {
this.generateMethodInputsView(this.props.methodABI)
this.generateMethodFieldsView(this.props.methodABI)
}
}

async getContractMethods () {
const contractProps = await this.props.getContract(this.props.address)
const abi = contractProps && contractProps.abi
const options = abi && abi.reduce((filtered, obj) => {
const options = abi && Array.isArray(abi) && abi.reduce((filtered, obj) => {
if (obj.type === 'function') {
filtered.push({ label: obj.name, value: obj.name, metadata: obj })
}
Expand All @@ -178,50 +187,71 @@ class SendTransactionScreen extends PersistentForm {
})
}

generateMethodInput (params, ind) {
generateMethodField (params, ind, isInput) {
const { inputValues, outputValues, web3 } = this.state
const paramName = isInput ? 'Input' : 'Output'
const defaultInputValue = (inputValues && inputValues[ind]) || ''
const defaultOutputValue = params.type === 'bool' ? outputValues && outputValues[ind] : (outputValues && outputValues[ind]) || ''
let defaultValue = isInput ? defaultInputValue : defaultOutputValue
if (Array.isArray(defaultValue)) {
defaultValue = defaultValue.join(', ')
} else if ((params.type.startsWith('uint') || params.type.startsWith('int')) && !isNaN(Number(defaultValue)) && Number(defaultValue) > 0) {
defaultValue = web3.toBigNumber(defaultValue).toFixed()
} else if (defaultValue) {
defaultValue = defaultValue.toString()
}
const label = (
<h3
key={`method_label_${ind}`}
style={{ marginTop: '10px' }}
>
{params.name || `Input ${ind + 1}`}
{params.name || `${paramName} ${ind + 1}`}
{!isInput ? <i
className="clipboard cursor-pointer"
style={{ marginLeft: '10px' }}
onClick={(e) => { copyToClipboard(defaultValue) }}
/> : null}
</h3>
)
let input
if (params.type === 'bool') {
input = (
<SendTransactionInputSelect
key={Math.random()}
ind={ind}
defaultValue={(this.props.inputValues && this.props.inputValues[ind]) || ''}
onChange={val => this.handleInputChange(val, ind)}
/>
)
let field
if (params.type === 'bool' && isInput) {
field = (
<SendTransactionInputSelect
key={Math.random()}
ind={ind}
defaultValue={defaultValue}
onChange={val => this.handleInputChange(val, params.type, ind)}
/>
)
} else {
input = (
<SendTransactionInputText
field = (
<SendTransactionField
key={Math.random()}
ind={ind}
disabled={!isInput}
placeholder={params.type}
defaultValue={(this.props.inputValues && this.props.inputValues[ind]) || ''}
onChange={e => this.handleInputChange(e.target.value, ind)}
defaultValue={defaultValue}
onChange={e => isInput ? this.handleInputChange(e.target.value, params.type, ind) : null}
/>
)
}
const inputObj = (
const fieldObj = (
<div key={`method_label_container_${ind}`}>
{label}
{input}
{field}
</div>
)
return inputObj
return fieldObj
}

handleInputChange (val, ind) {
console.log(val, ind)
handleInputChange (val, type, ind) {
const { inputValues } = this.state
if (val) {
inputValues[ind] = val
if (type === 'bool') {
inputValues[ind] = (val === 'true')
} else {
inputValues[ind] = val
}
} else {
delete inputValues[ind]
}
Expand All @@ -230,53 +260,51 @@ class SendTransactionScreen extends PersistentForm {
})
}

generateMethodInputsView (metadata) {
generateMethodFieldsView (metadata) {
this.setState({
methodInputs: [],
methodInputsView: [],
methodOutputs: [],
methodOutputsView: [],
})
const methodInputsView = []
const methodInputs = metadata && metadata.inputs
const methodOutputsView = []
const methodOutputs = metadata && metadata.outputs
methodInputs.forEach((input, ind) => {
methodInputsView.push(this.generateMethodInput(input, ind))
methodInputsView.push(this.generateMethodField(input, ind, true))
})
methodOutputs.forEach((output, ind) => {
methodOutputsView.push(this.generateMethodField(output, ind, false))
})
this.setState({
methodInputs,
methodInputsView,
methodOutputs,
methodOutputsView,
})
}

updateOutputsView () {
const methodOutputsView = []
this.state.methodOutputs.forEach((output, ind) => {
methodOutputsView.push(this.generateMethodField(output, ind, false))
})
this.setState({
methodOutputsView,
})
}

methodOutput () {
const label = (
<h2
key="method_output_label"
style={{
marginTop: '10px',
}}
>
Output
</h2>
)
const output = (
<textarea
key="method_output_value"
className="input large-input"
disabled={true}
value={this.state.output}
style={{
marginTop: '5px',
width: '100%',
height: '50px',
}}
/>
)
const outputObj = (
return (
<div>
{label}
{output}
<h3
className="flex-center"
style={{ marginTop: '10px' }}
>Output data</h3>
{this.state.methodOutputsView}
</div>
)
return outputObj
}

buttonsSection () {
Expand Down Expand Up @@ -317,9 +345,8 @@ class SendTransactionScreen extends PersistentForm {

callData = () => {
this.props.showLoadingIndication()
const { abi, methodSelected, inputValues } = this.state
const { abi, methodSelected, inputValues, methodOutputs, methodOutputsView, web3 } = this.state
const { address } = this.props
const web3 = new Web3(global.ethereumProvider)

const inputValuesArray = Object.keys(inputValues).map(key => inputValues[key])
try {
Expand All @@ -329,18 +356,44 @@ class SendTransactionScreen extends PersistentForm {
this.props.hideToast()
return this.props.displayWarning(err)
}
if (output) {
this.setState({
output,
const outputValues = {}
if (methodOutputsView.length > 1) {
output.forEach((val, ind) => {
const type = methodOutputs && methodOutputs[ind] && methodOutputs[ind].type
outputValues[ind] = this.setOutputValue(val, type)
})
} else {
const type = methodOutputs && methodOutputs[0] && methodOutputs[0].type
outputValues[0] = this.setOutputValue(output, type)
}
this.setState({
outputValues,
})
this.updateOutputsView()
})
} catch (e) {
this.props.hideToast()
return this.props.displayWarning(e)
}
}

setOutputValue = (val, type) => {
console.log(val)
if (!type) {
return val || ''
}
if (!val) {
if (type === 'bool') {
return val
}
return ''
}
if ((type.startsWith('uint') || type.startsWith('int')) && !type.endsWith('[]')) {
return val.toFixed().toString()
}
return val
}

encodeFunctionCall = () => {
const { inputValues, methodABI } = this.state
const inputValuesArray = Object.keys(inputValues).map(key => inputValues[key])
Expand Down
Loading

0 comments on commit fcfb3e6

Please sign in to comment.