1
- import { Button , Card , Row , Col , Form , Input , InputNumber } from 'antd'
2
- import React , { useState , useCallback } from 'react'
1
+ import { Button , Card , Row , Col , Form , Input , InputNumber , Select } from 'antd'
2
+ import React , { useState , useCallback , useEffect } from 'react'
3
3
import styled from 'styled-components'
4
4
5
5
import { useDrizzle , useDrizzleState } from '../bootstrap/drizzle-react-hooks'
@@ -78,6 +78,12 @@ const StyledInputNumber = styled(InputNumber)`
78
78
79
79
const AddTx = Form . create ( ) ( ( { form } ) => {
80
80
const [ txs , setTxs ] = useState ( [ ] )
81
+ // Selected Contract State
82
+ const [ abi , setContractABI ] = useState ( [ ] )
83
+ const [ address , setContractAddress ] = useState ( '' )
84
+ const [ methodSelected , setMethodSelected ] = useState ( '' )
85
+ const [ methodInputs , setMethodInputs ] = useState ( [ ] )
86
+
81
87
const { drizzle, useCacheCall, useCacheSend } = useDrizzle ( )
82
88
const drizzleState = useDrizzleState ( drizzleState => ( {
83
89
balance : drizzle . web3 . utils . toBN (
@@ -100,6 +106,13 @@ const AddTx = Form.create()(({ form }) => {
100
106
const _newValues = {
101
107
...values
102
108
}
109
+
110
+ if ( ! _newValues . data && methodSelected ) {
111
+ const contractInstance = new drizzle . web3 . eth . Contract ( abi , address )
112
+ const _data = contractInstance . methods [ methodSelected ] ( ...methodInputs ) . encodeABI ( )
113
+ _newValues . data = _data
114
+ }
115
+
103
116
_newValues . amount = drizzle . web3 . utils . toWei ( String ( Number ( _newValues . amount ) ) )
104
117
txs . push ( _newValues )
105
118
setTxs (
@@ -112,6 +125,13 @@ const AddTx = Form.create()(({ form }) => {
112
125
} )
113
126
}
114
127
128
+ const resetContractState = ( ) => {
129
+ setContractABI ( '' )
130
+ setContractAddress ( '' )
131
+ setMethodSelected ( '' )
132
+ setMethodInputs ( [ ] )
133
+ }
134
+
115
135
const removeTxFromSet = ( itemIndex ) => {
116
136
const txsCopy = [ ...txs ]
117
137
txsCopy . splice ( itemIndex , 1 )
@@ -135,6 +155,46 @@ const AddTx = Form.create()(({ form }) => {
135
155
}
136
156
}
137
157
158
+ const getContractABI = async ( a ) => {
159
+ if ( a !== address ) {
160
+ const network = await drizzle . web3 . eth . net . getId ( )
161
+ let uri
162
+ switch ( network ) {
163
+ case 1 :
164
+ uri = `https://api.etherscan.io/api?module=contract&action=getabi&address=${ a } `
165
+ break
166
+ case 42 :
167
+ uri = `https://api-kovan.etherscan.io/api?module=contract&action=getabi&address=${ a } `
168
+ break
169
+ default :
170
+ break
171
+ }
172
+ if ( uri ) {
173
+ const abiQuery = await fetch (
174
+ uri
175
+ ) . then ( response => response . json ( ) )
176
+ if ( abiQuery . status === "1" ) {
177
+ setContractABI ( JSON . parse ( abiQuery . result ) )
178
+ setContractAddress ( a )
179
+ } else {
180
+ setContractABI ( '' )
181
+ setContractAddress ( '' )
182
+ }
183
+ }
184
+ }
185
+ }
186
+
187
+ let contractInstance
188
+ if ( address && abi . length ) {
189
+ contractInstance = new drizzle . web3 . eth . Contract ( abi , address )
190
+ }
191
+
192
+ let methodInputsList
193
+ if ( methodSelected ) {
194
+ methodInputsList = abi . filter ( a => a . name === methodSelected ) [ 0 ] . inputs
195
+
196
+ }
197
+
138
198
return (
139
199
< Form
140
200
onSubmit = { e => {
@@ -184,7 +244,7 @@ const AddTx = Form.create()(({ form }) => {
184
244
}
185
245
]
186
246
} ) (
187
- < StyledInput type = "text" placeholder = { 'To Address' } />
247
+ < StyledInput type = "text" placeholder = { 'To Address' } onChange = { ( e ) => getContractABI ( e . target . value ) } />
188
248
) }
189
249
</ Form . Item >
190
250
< Form . Item >
@@ -239,22 +299,81 @@ const AddTx = Form.create()(({ form }) => {
239
299
/>
240
300
) }
241
301
</ Form . Item >
242
- < Form . Item >
243
- { form . getFieldDecorator ( 'data' , {
244
- rules : [
245
- {
246
- message : "Data required (use 0x for no data)" ,
247
- validator : ( _ , _value , callback ) => {
248
- if ( ! _value || _value . length < 1 )
249
- return callback ( true )
250
- callback ( )
251
- }
252
- }
253
- ]
254
- } ) (
255
- < StyledTextArea type = "text" placeholder = { 'Data' } />
256
- ) }
257
- </ Form . Item >
302
+ {
303
+ contractInstance ? (
304
+ < Form . Item >
305
+ < Input . Group >
306
+ < Form . Item
307
+ name = { [ 'method' , 'methodName' ] }
308
+ noStyle
309
+ >
310
+ < Select placeholder = "Select Function" style = { { width : '100%' } } onChange = { ( value ) => {
311
+ setMethodSelected ( value )
312
+ }
313
+ } >
314
+ {
315
+ abi . map ( ( abiItem , i ) => {
316
+ if ( ! abiItem . constant ) {
317
+ return (
318
+ < Select . Option
319
+ value = { abiItem . name }
320
+ >
321
+ { abiItem . name }
322
+ </ Select . Option >
323
+ )
324
+ }
325
+ } )
326
+ }
327
+ </ Select >
328
+ </ Form . Item >
329
+ {
330
+ methodSelected ? (
331
+ < div >
332
+ {
333
+ methodInputsList . map ( ( field , i ) => {
334
+ return (
335
+ < Form . Item
336
+ name = { [ 'method' , field . name ] }
337
+ >
338
+ < Input
339
+ key = { field . name }
340
+ type = "text"
341
+ placeholder = { field . name }
342
+ onChange = { ( val ) => {
343
+ const _inputs = [ ...methodInputs ]
344
+ _inputs . splice ( i , 1 , val . target . value )
345
+ setMethodInputs ( _inputs )
346
+ } }
347
+ />
348
+ </ Form . Item >
349
+ )
350
+ } )
351
+ }
352
+ </ div >
353
+ )
354
+ : ''
355
+ }
356
+ </ Input . Group >
357
+ </ Form . Item >
358
+ ) : (
359
+ < Form . Item >
360
+ { form . getFieldDecorator ( 'data' , {
361
+ rules : [
362
+ {
363
+ message : "Data required (use 0x for no data)" ,
364
+ validator : ( _ , _value , callback ) => {
365
+ if ( ! _value || _value . length < 1 )
366
+ return callback ( true )
367
+ callback ( )
368
+ }
369
+ }
370
+ ]
371
+ } ) (
372
+ < StyledTextArea type = "text" placeholder = { 'Data' } />
373
+ ) }
374
+ </ Form . Item >
375
+ )
376
+ }
258
377
</ Col >
259
378
</ Row >
260
379
</ BackgrounCard >
0 commit comments