diff --git a/js/src/modals/DeployContract/DetailsStep/detailsStep.js b/js/src/modals/DeployContract/DetailsStep/detailsStep.js index 3c6371d39..06b5a85bb 100644 --- a/js/src/modals/DeployContract/DetailsStep/detailsStep.js +++ b/js/src/modals/DeployContract/DetailsStep/detailsStep.js @@ -15,8 +15,11 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; +import { MenuItem } from 'material-ui'; -import { AddressSelect, Form, Input, RadioButtons } from '../../../ui'; +import { AddressSelect, Form, Input, Select } from '../../../ui'; +import { validateAbi } from '../../../util/validation'; +import { parseAbiType } from '../../../util/abi'; export default class DetailsStep extends Component { static contextTypes = { @@ -25,12 +28,14 @@ export default class DetailsStep extends Component { static propTypes = { accounts: PropTypes.object.isRequired, - inputTypeValues: PropTypes.array.isRequired, onFromAddressChange: PropTypes.func.isRequired, onNameChange: PropTypes.func.isRequired, onDescriptionChange: PropTypes.func.isRequired, - onInputTypeChange: PropTypes.func.isRequired, + onAbiChange: PropTypes.func.isRequired, + onCodeChange: PropTypes.func.isRequired, + onParamsChange: PropTypes.func.isRequired, + onInputsChange: PropTypes.func.isRequired, fromAddress: PropTypes.string, fromAddressError: PropTypes.string, @@ -38,7 +43,11 @@ export default class DetailsStep extends Component { nameError: PropTypes.string, description: PropTypes.string, descriptionError: PropTypes.string, - inputType: PropTypes.object, + abi: PropTypes.string, + abiError: PropTypes.string, + code: PropTypes.string, + codeError: PropTypes.string, + readOnly: PropTypes.bool }; @@ -46,9 +55,39 @@ export default class DetailsStep extends Component { readOnly: false }; + state = { + solcOutput: '', + contracts: {}, + selectedContractIndex: 0 + } + + componentDidMount () { + const { abi, code } = this.props; + + if (abi) { + this.onAbiChange(abi); + this.setState({ solcOutput: abi }); + } + + if (code) { + this.onCodeChange(code); + } + } + render () { - const { accounts } = this.props; - const { fromAddress, fromAddressError, name, nameError, description, descriptionError } = this.props; + const { + accounts, + readOnly, + + fromAddress, fromAddressError, + name, nameError, + description, descriptionError, + abiError, + code, codeError + } = this.props; + + const { solcOutput, contracts } = this.state; + const solc = contracts && Object.keys(contracts).length > 0; return (
@@ -74,34 +113,99 @@ export default class DetailsStep extends Component { value={ description } onChange={ this.onDescriptionChange } /> - { this.renderChooseInputType() } + { this.renderContractSelect() } + + + +
); } - renderChooseInputType () { - const { readOnly } = this.props; + renderContractSelect () { + const { contracts } = this.state; - if (readOnly) { + if (!contracts || Object.keys(contracts).length === 0) { return null; } - const { inputTypeValues, inputType } = this.props; + const { selectedContractIndex } = this.state; + const contractsItems = Object.keys(contracts).map((name, index) => ( + + { name } + + )); return ( -
-
-

Choose how ABI and Bytecode will be entered

- -
+ ); } + onContractChange = (event, index) => { + const { contracts } = this.state; + const contractName = Object.keys(contracts)[index]; + const contract = contracts[contractName]; + + const { abi, bin } = contract; + const code = /^0x/.test(bin) ? bin : `0x${bin}`; + + this.setState({ selectedContractIndex: index }, () => { + this.onAbiChange(abi); + this.onCodeChange(code); + }); + } + + onSolcChange = (event, value) => { + // Change triggered only if valid + if (this.props.abiError) { + return null; + } + + this.onSolcSubmit(value); + } + + onSolcSubmit = (value) => { + try { + const solcParsed = JSON.parse(value); + + if (!solcParsed || !solcParsed.contracts) { + throw new Error('Wrong solc output'); + } + + this.setState({ contracts: solcParsed.contracts }, () => { + this.onContractChange(null, 0); + }); + } catch (e) { + this.setState({ contracts: null }); + this.onAbiChange(value); + } + + this.setState({ solcOutput: value }); + } + onFromAddressChange = (event, fromAddress) => { const { onFromAddressChange } = this.props; @@ -120,8 +224,35 @@ export default class DetailsStep extends Component { onDescriptionChange(description); } - onInputTypeChange = (inputType, index) => { - const { onInputTypeChange } = this.props; - onInputTypeChange(inputType, index); + onAbiChange = (abi) => { + const { api } = this.context; + const { onAbiChange, onParamsChange, onInputsChange } = this.props; + const { abiError, abiParsed } = validateAbi(abi, api); + + if (!abiError) { + const { inputs } = abiParsed + .find((method) => method.type === 'constructor') || { inputs: [] }; + + const params = []; + + inputs.forEach((input) => { + const param = parseAbiType(input.type); + params.push(param.default); + }); + + onParamsChange(params); + onInputsChange(inputs); + } else { + onParamsChange([]); + onInputsChange([]); + } + + onAbiChange(abi); + } + + onCodeChange = (code) => { + const { onCodeChange } = this.props; + + onCodeChange(code); } } diff --git a/js/src/modals/DeployContract/ParametersStep/parametersStep.js b/js/src/modals/DeployContract/ParametersStep/parametersStep.js index ab9a20d05..7916c9f5a 100644 --- a/js/src/modals/DeployContract/ParametersStep/parametersStep.js +++ b/js/src/modals/DeployContract/ParametersStep/parametersStep.js @@ -30,10 +30,8 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; -import { MenuItem } from 'material-ui'; -import { Form, Input, TypedInput, Select } from '../../../ui'; -import { validateAbi } from '../../../util/validation'; +import { Form, TypedInput } from '../../../ui'; import { parseAbiType } from '../../../util/abi'; import styles from '../deployContract.css'; @@ -45,133 +43,24 @@ export default class ParametersStep extends Component { static propTypes = { accounts: PropTypes.object.isRequired, - inputType: PropTypes.object.isRequired, - - onAbiChange: PropTypes.func.isRequired, - onCodeChange: PropTypes.func.isRequired, onParamsChange: PropTypes.func.isRequired, - abi: PropTypes.string, - abiError: PropTypes.string, - code: PropTypes.string, - codeError: PropTypes.string, + inputs: PropTypes.array, params: PropTypes.array, - paramsError: PropTypes.array, - - readOnly: PropTypes.bool + paramsError: PropTypes.array }; - static defaultProps = { - readOnly: false - }; - - state = { - inputs: [], - solcOutput: '', - contracts: {}, - selectedContractIndex: 0 - } - - componentDidMount () { - const { abi, code } = this.props; - - if (abi) { - this.onAbiChange(abi); - } - - if (code) { - this.onCodeChange(code); - } - } - render () { - const { abi, abiError, code, codeError, readOnly, inputType } = this.props; - - const manualInput = inputType.key === 'MANUAL'; - return (
- { this.renderFromSOLC() } - - - { this.renderConstructorInputs() }
); } - renderFromSOLC () { - const { inputType } = this.props; - - if (inputType.key !== 'SOLC') { - return null; - } - - const { solcOutput, contracts } = this.state; - const error = contracts && Object.keys(contracts).length - ? null - : 'enter a valid solc output'; - - return ( -
-

To get solc output, you can use this command:

- solc --combined-json abi,bin Contract.sol | xclip -selection c - - { this.renderContractSelect() } -
- ); - } - - renderContractSelect () { - const { contracts } = this.state; - - if (!contracts || Object.keys(contracts).length === 0) { - return null; - } - - const { selectedContractIndex } = this.state; - const contractsItems = Object.keys(contracts).map((name, index) => ( - - { name } - - )); - - return ( - - ); - } - renderConstructorInputs () { const { accounts, params, paramsError } = this.props; - const { inputs } = this.state; + const { inputs } = this.props; if (!inputs || !inputs.length) { return null; @@ -207,76 +96,10 @@ export default class ParametersStep extends Component { ); } - onContractChange = (event, index) => { - const { contracts } = this.state; - const contractName = Object.keys(contracts)[index]; - const contract = contracts[contractName]; - - const { abi, bin } = contract; - const code = /^0x/.test(bin) ? bin : `0x${bin}`; - - this.setState({ selectedContractIndex: index }, () => { - this.onAbiChange(abi); - this.onCodeChange(code); - }); - } - - onSolcChange = (event, value) => { - try { - const solcParsed = JSON.parse(value); - - if (!solcParsed && !solcParsed.contracts) { - throw new Error('Wrong solc output'); - } - - this.setState({ contracts: solcParsed.contracts }, () => { - this.onContractChange(null, 0); - }); - } catch (e) { - this.setState({ contracts: null }); - this.onAbiChange(''); - this.onCodeChange(''); - } - - this.setState({ solcOutput: value }); - } - onParamChange = (index, value) => { const { params, onParamsChange } = this.props; params[index] = value; onParamsChange(params); } - - onAbiChange = (abi) => { - const { api } = this.context; - const { onAbiChange, onParamsChange } = this.props; - const { abiError, abiParsed } = validateAbi(abi, api); - - if (!abiError) { - const { inputs } = abiParsed - .find((method) => method.type === 'constructor') || { inputs: [] }; - - const params = []; - - inputs.forEach((input) => { - const param = parseAbiType(input.type); - params.push(param.default); - }); - - onParamsChange(params); - this.setState({ inputs }); - } else { - onParamsChange([]); - this.setState({ inputs: [] }); - } - - onAbiChange(abi); - } - - onCodeChange = (code) => { - const { onCodeChange } = this.props; - - onCodeChange(code); - } } diff --git a/js/src/modals/DeployContract/deployContract.js b/js/src/modals/DeployContract/deployContract.js index db12cf911..55e3166e8 100644 --- a/js/src/modals/DeployContract/deployContract.js +++ b/js/src/modals/DeployContract/deployContract.js @@ -32,23 +32,10 @@ import { ERROR_CODES } from '../../api/transport/error'; const STEPS = { CONTRACT_DETAILS: { title: 'contract details' }, CONTRACT_PARAMETERS: { title: 'contract parameters' }, - DEPLOYMENT: { title: 'deployment' }, + DEPLOYMENT: { title: 'deployment', waiting: true }, COMPLETED: { title: 'completed' } }; -const CONTRACT_INPUT_TYPES = [ - { - key: 'MANUAL', - label: 'Manually', - description: 'Manual input of the ABI and the bytecode' - }, - { - key: 'SOLC', - label: 'From solc', - description: 'Parse the ABI and the bytecode from solc output' - } -]; - export default class DeployContract extends Component { static contextTypes = { api: PropTypes.object.isRequired, @@ -82,7 +69,7 @@ export default class DeployContract extends Component { nameError: ERRORS.invalidName, params: [], paramsError: [], - inputType: CONTRACT_INPUT_TYPES[0], + inputs: [], deployState: '', deployError: null, @@ -116,24 +103,30 @@ export default class DeployContract extends Component { } render () { - const { step, deployError, rejected } = this.state; + const { step, deployError, rejected, inputs } = this.state; const realStep = Object.keys(STEPS).findIndex((k) => k === step); const realSteps = deployError || rejected ? null - : Object.values(STEPS).map((s) => s.title); + : Object.keys(STEPS) + .filter((k) => k !== 'CONTRACT_PARAMETERS' || inputs.length > 0) + .map((k) => STEPS[k]); const title = realSteps ? null : (deployError ? 'deployment failed' : 'rejected'); + const waiting = realSteps + ? realSteps.map((s, i) => s.waiting ? i : false).filter((v) => v !== false) + : null; + return ( s.title) : null } title={ title } - waiting={ realSteps ? [2] : null } + waiting={ waiting } visible scroll> { this.renderStep() } @@ -143,8 +136,7 @@ export default class DeployContract extends Component { renderDialogActions () { const { deployError, abiError, codeError, nameError, descriptionError, fromAddressError, fromAddress, step } = this.state; - const isDetailsValid = !nameError && !fromAddressError && !descriptionError; - const isParametersValid = !abiError && !codeError; + const isValid = !nameError && !fromAddressError && !descriptionError && !abiError && !codeError; const cancelBtn = (