Skip to content

Commit 5caadd0

Browse files
authored
[FEATURE] Support arrays (#13)
* draft * implement arrrays * lint
1 parent cf48428 commit 5caadd0

File tree

3 files changed

+113
-61
lines changed

3 files changed

+113
-61
lines changed

README.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,36 @@
33

44
A quick online tool to abi-encode constructor arguments used in solidity. The encoded data can be used to deploy the contract or verify the contract on Etherscan : https://ropsten.etherscan.io/verifyContract
55

6+
## Usage
7+
### Encode
8+
- Add the value types, each seperated by a comma
9+
- Add the values to match the number of types entered, each seperated by a comma `,` (No spaces), using square brakets `[]` to wrap arrays
10+
```
11+
Types:
12+
address,uint256,address[],uint256[]
13+
14+
Values:
15+
0x0000000000000000000000000000000000000000,5,[0xEC66d98e5a7DdBFEA66345ceA8626B5403AF1315,0xD6FAcd899F03C4aFce389ea51D73e8FD7D8A53E2,0x8c3720060f8cFDf8b8d4DA5698F4f51a48A0828a,0x9a9e6588AF6d1bC42572B0E3c3D2F827dabA64Ac,0x4A7a9f1Ac903A94f8Ed8E91BD0c7B5307d29EC18],[40,12,12,12,24]
16+
```
17+
18+
### Decode
19+
- Add the value types, each seperated by a comma
20+
- Add the encoded data to be decoded
21+
22+
```
23+
Types:
24+
address,uint256,address[],uint256[]
25+
26+
Encoded data:
27+
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000ec66d98e5a7ddbfea66345cea8626b5403af1315000000000000000000000000d6facd899f03c4afce389ea51d73e8fd7d8a53e20000000000000000000000008c3720060f8cfdf8b8d4da5698f4f51a48a0828a0000000000000000000000009a9e6588af6d1bc42572b0e3c3d2f827daba64ac0000000000000000000000004a7a9f1ac903a94f8ed8e91bd0c7b5307d29ec1800000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000018
28+
```
29+
630
## url
7-
[Live](https://adibas03.github.io/online-ethereum-abi-encoder-decoder/)
31+
[Live / Demo](https://adibas03.github.io/online-ethereum-abi-encoder-decoder/)
832

933
## Contribute
34+
https://github.com/adibas03/online-ethereum-abi-encoder-decoder/issues
35+
36+
## Contribution
1037
Buy me a Coffe or a Beer
1138
Ethereum: **0x965D1C9987BD2c34e151E63d60AFf8E9dB6b1561**

src/pages/decode.js

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,11 @@ class Decoder extends Component{
1515
constructor(props) {
1616
super(props);
1717

18-
//Hanle binds
19-
this.handleChange = this.handleChange.bind(this);
20-
this.handleClick = this.handleClick.bind(this);
21-
this.handleRequestClose = this.handleRequestClose.bind(this);
18+
//Handle binds
2219
this.decodeData = this.decodeData.bind(this);
2320

24-
this.testRegExp = this.testRegExp.bind(this);
25-
this.validateType = this.validateType.bind(this);
26-
this.typesSet = this.typesSet.bind(this);
2721
this.typeUpdated = this.typeUpdated.bind(this);
2822
this.valueUpdated = this.valueUpdated.bind(this);
29-
this.formFilled = this.formFilled.bind(this);
30-
this.errorExists = this.errorExists.bind(this);
3123

3224
this.state = {
3325
types : "",
@@ -118,17 +110,27 @@ class Decoder extends Component{
118110
Log(types,value);
119111

120112
let decoded = this.abiCoder.decode(types, value);
121-
decoded = decoded.map(function(d){
122-
return d.toString();
123-
});
113+
114+
decoded = this.parseDecoded(decoded);
124115
Log(decoded);
116+
125117
this.setState({ decoded: decoded.join(",") });
126118
}
127119
catch(e){
128120
throw new Error(e);
129121
}
130122
}
131123

124+
parseDecoded (toParse) {
125+
const that = this;
126+
return toParse.map(function(d){
127+
return (typeof d === "object" && d.length !== undefined) ?
128+
JSON.stringify(that.parseDecoded(d)).replace(/"/g,"")
129+
:
130+
d.toString();
131+
});
132+
}
133+
132134
formFilled () {
133135
return this.state.types && this.state.value;
134136
}
@@ -141,22 +143,14 @@ class Decoder extends Component{
141143
return false;
142144
}
143145

144-
handleRequestClose () {
145-
this.setState({
146-
open: false,
147-
});
148-
}
149-
150-
handleClick () {
151-
this.setState({
152-
open: true,
153-
});
154-
}
155-
156146
handleChange (name, event) {
157147
this.setState({ [name]: event.target.value,submitted: false });
158148
}
159149

150+
selectTarget (clickEvent) {
151+
clickEvent.target.select();
152+
}
153+
160154
render(){
161155
const { classes } = this.props;
162156

@@ -214,10 +208,13 @@ class Decoder extends Component{
214208
shrink: true,
215209
}}
216210
value={this.state.decoded}
217-
disabled
218211
helperText="Decodecoded Abi arguments"
219212
fullWidth
220213
margin="normal"
214+
variant="filled"
215+
readOnly={true}
216+
onClick={this.selectTarget}
217+
onFocus={this.selectTarget}
221218
/>
222219
</FormControl>
223220
</Card>}

src/pages/encode.js

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import React, { Component } from "react";
22
import PropTypes from "prop-types";
33

4+
import Button from "@material-ui/core/Button";
45
import Card from "@material-ui/core/Card";
56
import FormControl from "@material-ui/core/FormControl";
6-
import Button from "@material-ui/core/Button";
77
import TextField from "@material-ui/core/TextField";
88

9+
910
import ethers from "ethers";
1011
import ValidTypes from "../config/types";
1112
import { suffixed } from "../config/types";
@@ -15,19 +16,11 @@ class Encoder extends Component{
1516
constructor(props) {
1617
super(props);
1718

18-
//Hanle binds
19-
this.handleChange = this.handleChange.bind(this);
20-
this.handleClick = this.handleClick.bind(this);
21-
this.handleRequestClose = this.handleRequestClose.bind(this);
19+
//Handle binds
2220
this.encodeData = this.encodeData.bind(this);
2321

24-
this.testRegExp = this.testRegExp.bind(this);
25-
this.validateType = this.validateType.bind(this);
26-
this.typesSet = this.typesSet.bind(this);
2722
this.typeUpdated = this.typeUpdated.bind(this);
2823
this.valueUpdated = this.valueUpdated.bind(this);
29-
this.formFilled = this.formFilled.bind(this);
30-
this.errorExists = this.errorExists.bind(this);
3124

3225
this.state = {
3326
types : "",
@@ -40,14 +33,18 @@ class Encoder extends Component{
4033
this.abiCoder = new ethers.utils.AbiCoder();
4134
}
4235

43-
44-
testRegExp (search, array) {
45-
let found = 0;
46-
array.forEach(function(a){
47-
if(new RegExp(a).test(search) && search.trim().match(new RegExp(a)).index === 0)
48-
found++;
36+
parseForEncode (values) {
37+
const matched = this.matchRegExpValues(values);
38+
39+
return matched.map((val) => {
40+
if (this.testArrayRegExpValues(val)) {
41+
val = this.stripArray(val);
42+
}
43+
if (this.testRegExpValues(val)) {
44+
val = this.parseForEncode(val);
45+
}
46+
return val;
4947
});
50-
return found;
5148
}
5249

5350
validateType (self) {
@@ -61,13 +58,16 @@ class Encoder extends Component{
6158
});
6259

6360
vals.forEach(function(v,id){
64-
if(!(id === vals.length-1 && v === "" ))
61+
if(id === vals.length-1 && v === "") {
62+
return;
63+
} else {
6564
if(that.testRegExp(v,array) < 1){
6665
clean = false;
6766
let error = {};error["types"] = true;
6867
let state = {error:Object.assign(that.state.error,error)};
6968
return that.setState(state);
7069
}
70+
}
7171
});
7272
if(clean){
7373
let error = {};error["types"] = false;
@@ -79,8 +79,10 @@ class Encoder extends Component{
7979
validateValue (self) {
8080
if(!self && this.state.values.length === 0 && !this.state.submitted)
8181
return;
82-
let vals = this.state.values.split(","),error = {};
83-
if(vals.length !== this.state.types.split(",").length )
82+
83+
let error = {};
84+
const matchedValues = this.matchRegExpValues(this.state.values) || [];
85+
if(this.state.types.split(",").length !== matchedValues.length)
8486
error["values"] = true;
8587
else
8688
error["values"] = false;
@@ -89,6 +91,35 @@ class Encoder extends Component{
8991
return this.setState(state);
9092
}
9193

94+
stripArray(value) {
95+
const regEx = new RegExp(/^\[|\]$/gi);
96+
return value.replace(regEx,"");
97+
}
98+
99+
matchRegExpValues (values) {
100+
const regEx = new RegExp(/(\[[0-9a-zA-Z,]+\]|[0-9a-zA-Z]+)/gi);
101+
return values.match(regEx);
102+
}
103+
104+
testRegExp (search, array) {
105+
let found = 0;
106+
array.forEach(function(a){
107+
if(new RegExp(a).test(search) && search.trim().match(new RegExp(a)).index === 0)
108+
found++;
109+
});
110+
return found;
111+
}
112+
113+
testRegExpValues (values) {
114+
const regEx = new RegExp(/(,+)/gi);
115+
return regEx.test(values);
116+
}
117+
118+
testArrayRegExpValues (values) {
119+
const regEx = new RegExp(/\[.*\]/gi);
120+
return regEx.test(values);
121+
}
122+
92123
typesSet () {
93124
let types = this.state.types;
94125
if(!types || types.length<1)
@@ -126,13 +157,15 @@ class Encoder extends Component{
126157
return;
127158
try{
128159
let types = this.state.types.split(",");
129-
let values = this.state.values.split(",");
160+
let values = this.parseForEncode(this.state.values);
130161

131162
Log(types,values);
132163

133164
if(types.length !== values.length)
134165
throw new Error("Types/values mismatch");
135166
let encoded = this.abiCoder.encode(types, values);
167+
Log(encoded);
168+
136169
this.setState({ encoded: encoded.substring(2) });
137170
}
138171
catch(e){
@@ -152,22 +185,14 @@ class Encoder extends Component{
152185
return false;
153186
}
154187

155-
handleRequestClose () {
156-
this.setState({
157-
open: false,
158-
});
159-
}
160-
161-
handleClick () {
162-
this.setState({
163-
open: true,
164-
});
165-
}
166-
167188
handleChange (name, event) {
168189
this.setState({ [name]: event.target.value,submitted: false });
169190
}
170191

192+
selectTarget (clickEvent) {
193+
clickEvent.target.select();
194+
}
195+
171196
render(){
172197
const { classes } = this.props;
173198

@@ -201,7 +226,7 @@ class Encoder extends Component{
201226
error={this.state.error.values}
202227
onChange={this.valueUpdated}
203228
onKeyUp={this.valueUpdated}
204-
helperText="Add the values to match the number of types indicated above, each seperated by a comma (No spaces)"
229+
helperText="Add the values to match the number of types indicated above, each seperated by a comma (No spaces), use [ ] to wrap array"
205230
fullWidth
206231
margin="normal"
207232
/>
@@ -224,10 +249,13 @@ class Encoder extends Component{
224249
shrink: true,
225250
}}
226251
value={this.state.encoded}
227-
disabled
228252
helperText="Abi encoded arguments"
229253
fullWidth
230254
margin="normal"
255+
variant="filled"
256+
readOnly={true}
257+
onClick={this.selectTarget}
258+
onFocus={this.selectTarget}
231259
/>
232260
</FormControl>
233261
</Card>}

0 commit comments

Comments
 (0)