Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added possibility to invoke with multiple arguments #122

Merged
merged 11 commits into from
Jun 19, 2018
15 changes: 15 additions & 0 deletions src/app/containers/SendInvoke/SendInvoke.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,18 @@
width: 200px;
margin: auto;
}

.btn {
flex-grow: 1;
order: 2;
}

.argsWrapper {
margin-top: -30px;
display: flex;
flex-direction: row;
padding-top: 20px;
align-items: baseline;
flex-wrap: wrap;
justify-content: space-between;
}
87 changes: 55 additions & 32 deletions src/app/containers/SendInvoke/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,14 @@ import withLoginCheck from '../../components/Login/withLoginCheck'
account: state.account,
}))

/*
Test call ...
{
scriptHash: 'b3a14d99a3fb6646c78bf2f4e2f25a7964d2956a',
operation: 'putvalue',
arg1: 'test',
arg2: '1',
assetType: 'GAS',
assetAmount: '.00025'
}
*/
class SendInvoke extends Component {
state = {
loading: false,
errorMsg: '',
txid: '',
args: [''],
assetType: 'GAS',
assetAmount: '0.00025',
}

_handleTextFieldChange = e => {
Expand All @@ -47,6 +39,23 @@ class SendInvoke extends Component {
})
}

_handleArgChange = (id, e) => {
const myArgs = this.state.args
myArgs[id] = e.target.value

this.setState({ args: myArgs })
}

_handleAddArgument = e => {
e.preventDefault()
this.setState({ args: this.state.args.concat(['']) })
}

_handleRemoveArg = (id, e) => {
e.preventDefault()
this.setState({ args: this.state.args.filter((s, idx) => id !== idx) })
}

handleSubmit = event => {
event.preventDefault()
const { selectedNetworkId, networks, account } = this.props
Expand Down Expand Up @@ -81,7 +90,6 @@ class SendInvoke extends Component {
}
})
.catch(e => {
console.log('e', e)
this.setState({
loading: false,
errorMsg: 'Invoke failed',
Expand All @@ -93,7 +101,7 @@ class SendInvoke extends Component {
const { loading, txid, errorMsg } = this.state

return (
<div>
<React.Fragment>
<form onSubmit={ this.handleSubmit } style={ { paddingTop: '35px' } } className={ tempStyle.tempFormStyle }>
<TextField
type='text'
Expand All @@ -109,25 +117,35 @@ class SendInvoke extends Component {
id='operation'
onChange={ this._handleTextFieldChange }
/>
<TextField
type='text'
placeholder='Argument 1'
value={ this.state.arg1 }
id='arg1'
onChange={ this._handleTextFieldChange }
/>
<TextField
type='text'
placeholder='Argument 2'
value={ this.state.arg2 }
id='arg2'
onChange={ this._handleTextFieldChange }
/>

<div className={ style.argsWrapper } style={ { marginBottom: '-20px' } }>
{this.state.args.map((arg, idx) => (
<React.Fragment>
<TextField
style={ { flexGrow: 1, order: 1 } }
type='text'
key={ `input-${idx + 1}` }
placeholder={ `Argument #${idx + 1}` }
value={ arg }
id={ `Argument #${idx + 1} name` }
onChange={ (event) => this._handleArgChange(idx, event) }
/>
<Button
key={ `btn-${idx + 1}` }
raised
ripple
style={ { flexGrow: 0, order: 0 } }
onClick={ (event) => this._handleRemoveArg(idx, event) }>
-
</Button>
</React.Fragment>
))}
</div>
<TextField
type='text'
placeholder='Amount'
value={ this.state.amount }
id='amount'
value={ this.state.assetAmount }
id='assetAmount'
onChange={ this._handleTextFieldChange }
/>
<Select
Expand All @@ -150,9 +168,14 @@ class SendInvoke extends Component {
},
] }
/>
<Button raised ripple disabled={ this.state.loading }>
<div className={ style.argsWrapper } style={ { marginTop: '0px' } }>

<Button className={ style.btn } style={ { marginLeft: 2, order: 3 } } raised ripple onClick={ this._handleAddArgument }>Add
Argument</Button>
<Button className={ style.btn } style={ { marginRight: 2 } } raised ripple disabled={ this.state.loading }>
Invoke
</Button>
</Button>
</div>
</form>

{txid && (
Expand All @@ -162,7 +185,7 @@ class SendInvoke extends Component {
)}
{loading && <div className={ style.statusBox }>Loading...</div>}
{errorMsg !== '' && <div className={ style.statusBox }>ERROR: {errorMsg}</div>}
</div>
</React.Fragment>
)
}
}
Expand Down
28 changes: 15 additions & 13 deletions src/app/utils/neonWrappers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Neon, { api } from '@cityofzion/neon-js'
import Neon, { u, wallet } from '@cityofzion/neon-js'
import { toNumber } from './math'

export function callInvoke (networkUrl, account, input) {
Expand All @@ -7,30 +7,32 @@ export function callInvoke (networkUrl, account, input) {
reject(new Error('Invalid asset type specified'))
}

const txArgs = [input.arg1, input.arg2]
const args = []
txArgs.forEach((arg) => {
if (arg) {
args.push(arg)
}
})

const myAccount = Neon.create.account(account.wif)

const parsedArgs = input.args.map(arg => {
if (wallet.isAddress(arg)) return u.reverseHex(wallet.getScriptHashFromAddress(arg))
if (typeof arg === 'string') return u.str2hexstring(arg)
if (typeof arg === 'number') return u.int2hex(arg)
})

const config = {
net: networkUrl,
privateKey: myAccount.privateKey,
script: Neon.create.script({
scriptHash: input.scriptHash,
operation: input.operation,
args: parsedArgs,
}),
address: myAccount.address,
privateKey: myAccount.privateKey,
intents: [{
assetId: Neon.CONST.ASSET_ID[input.assetType],
value: toNumber(input.amount),
value: toNumber(input.assetAmount),
scriptHash: input.scriptHash,
}],
script: { scriptHash: input.scriptHash, operation: input.operation, args: args },
gas: 0,
}

api.doInvoke(config)
Neon.doInvoke(config)
.then(res => resolve(res))
.catch(e => reject(e))
})
Expand Down