Skip to content

Commit aaa554b

Browse files
committed
add encodeParamsV2ByABI & decodeParamsV2ByABI tests
1 parent c61f395 commit aaa554b

8 files changed

+268
-143
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ yarn-error.log
99
.vscode/
1010
.idea/
1111
example/
12+
test/lib/dist/

src/lib/transactionBuilder.js

+38-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import TronWeb from 'index';
22
import utils from 'utils';
33
import {AbiCoder} from 'utils/ethersUtils';
4-
import { encodeParamsV2 } from 'utils/abi';
54
import Validator from 'paramValidator';
65
import {ADDRESS_PREFIX_REGEX} from 'utils/address';
76
import injectpromise from 'injectpromise';
7+
import { encodeParamsV2ByABI } from 'utils/abi';
88

99
let self;
1010

@@ -826,16 +826,50 @@ export default class TransactionBuilder {
826826
owner_address: toHex(issuerAddress)
827827
};
828828

829+
829830
if (functionSelector && utils.isString(functionSelector)) {
830831
functionSelector = functionSelector.replace('/\s*/g', '');
831832
if (parameters.length) {
833+
const abiCoder = new AbiCoder();
834+
let types = [];
835+
const values = [];
836+
837+
for (let i = 0; i < parameters.length; i++) {
838+
let {type, value} = parameters[i];
839+
840+
if (!type || !utils.isString(type) || !type.length)
841+
return callback('Invalid parameter type provided: ' + type);
842+
843+
if (type === 'address')
844+
value = toHex(value).replace(ADDRESS_PREFIX_REGEX, '0x');
845+
else if (type.match(/^([^\x5b]*)(\x5b|$)/)[0] === 'address[')
846+
value = value.map(v => toHex(v).replace(ADDRESS_PREFIX_REGEX, '0x'));
847+
848+
types.push(type);
849+
values.push(value);
850+
}
851+
832852
try {
833-
parameters = encodeParamsV2([...parameters])
834-
} catch(ex) {
835-
return callback(ex);
853+
// workaround for unsupported trcToken type
854+
types = types.map(type => {
855+
if (/trcToken/.test(type)) {
856+
type = type.replace(/trcToken/, 'uint256')
857+
}
858+
return type
859+
})
860+
861+
parameters = abiCoder.encode(types, values).replace(/^(0x)/, '');
862+
863+
} catch (ex) {
864+
return callback(ex);
836865
}
837866
} else parameters = '';
838867

868+
// work for abiv2 if passed the function abi in options
869+
if(options.funcABIV2) {
870+
parameters = encodeParamsV2ByABI(options.funcABIV2, options.parametersV2)
871+
}
872+
839873
if (options.shieldedParameter && utils.isString(options.shieldedParameter)) {
840874
parameters = options.shieldedParameter.replace(/^(0x)/, '');
841875
}

src/utils/abi.js

+67-112
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function deepCopy(target) {
3232
const newTarget = _isArray(target) ? [] : {};
3333

3434
Object.keys(target).forEach(key =>
35-
newTarget[key] = target[key] instanceof Object ? deepCopy(target[key]) : target[key]
35+
newTarget[key] = target[key] instanceof Object && !target[key]._isBigNumber ? deepCopy(target[key]) : target[key]
3636
);
3737

3838
return newTarget;
@@ -83,110 +83,16 @@ export function encodeParams(types, values) {
8383
return abiCoder.encode(types, values);
8484
}
8585

86-
export function encodeParamsV2(parameters) {
87-
const formatParams = (_params) => {
88-
const types = [];
89-
const values = [];
90-
const getBaseType = (type) => {
91-
if (!type || !_isString(type) || !type.length)
92-
throw new Error("Invalid parameter type provided: " + type);
93-
94-
return type.match(/^([^\x5b]*)(\x5b|$)/)[0];
95-
}
96-
97-
const getTypes = (_obj) => {
98-
if (_isArray(_obj)) {
99-
return _obj.map(function (_) {
100-
return getTypes(_);
101-
});
102-
}
103-
104-
let { type, value } = _obj;
105-
const baseType = getBaseType(type);
106-
switch (baseType) {
107-
case "trcToken":
108-
case "trcToken[":
109-
type = type.replace(/trcToken/, "uint256");
110-
break;
111-
case "tuple":
112-
type = `tuple(${getTypes(value).join(",")})`;
113-
break;
114-
case "tuple[":
115-
type = `tuple(${getTypes(value[0]).join(
116-
","
117-
)})${type.replace(/tuple/, "")}`;
118-
break;
119-
default:
120-
break;
121-
}
122-
123-
return type;
124-
}
125-
126-
const getValues = (_obj) => {
127-
if (_isArray(_obj)) {
128-
return _obj.map(function (_) {
129-
return getValues(_);
130-
});
131-
}
132-
133-
const getHexAddress = (_addr) => {
134-
if (_isArray(_addr)) {
135-
return _addr.map((_) => {
136-
return getHexAddress(_);
137-
});
138-
}
139-
140-
return TronWeb.address.toHex(_addr).replace(ADDRESS_PREFIX_REGEX, "0x");
141-
}
142-
143-
const getTupleValue = (_value) => {
144-
if (_isArray(_value)) {
145-
return _value.map((_) => {
146-
return getTupleValue(_);
147-
});
148-
}
149-
150-
return getValues(_value);
151-
}
152-
153-
let { type, value } = _obj;
154-
155-
const baseType = getBaseType(type);
156-
switch (baseType) {
157-
case "address":
158-
case "address[":
159-
value = getHexAddress(value);
160-
break;
161-
case "tuple":
162-
case "tuple[":
163-
value = getTupleValue(value);
164-
break;
165-
default:
166-
break;
167-
}
168-
169-
return value;
170-
}
171-
172-
_params.forEach((_) => {
173-
types.push(getTypes(_));
174-
values.push(getValues(_));
175-
});
176-
177-
return { types, values };
178-
}
179-
180-
const { types, values } = formatParams(parameters);
181-
console.log(JSON.stringify(types), JSON.stringify(values), abiCoder.encode(types, values).replace(/^(0x)/, ""),'result')
182-
return abiCoder.encode(types, values).replace(/^(0x)/, "");
183-
}
184-
18586
function extractSize (type) {
18687
const size = type.match(/([a-zA-Z0-9])(\[.*\])/);
18788
return size ? size[2] : '';
18889
}
18990

91+
function extractSizeDimensions (type) {
92+
const size = extractSize(type)
93+
return (size.match(/\]\[/g) || []).length + 1;
94+
}
95+
19096
export function encodeParamsV2ByABI(funABI, args) {
19197
const types = [];
19298

@@ -210,6 +116,33 @@ export function encodeParamsV2ByABI(funABI, args) {
210116
}
211117
}
212118

119+
const convertAddresses = addrArr => {
120+
if (Array.isArray(addrArr)) {
121+
addrArr.forEach((addrs, i) => {
122+
addrArr[i] = convertAddresses(addrs);
123+
});
124+
return addrArr;
125+
} else {
126+
return _addressToHex(addrArr)
127+
}
128+
};
129+
130+
const mapTuple = (components, args, dimension) => {
131+
if (dimension > 1) {
132+
if (args.length) {
133+
args.forEach(arg => {
134+
mapTuple(components, arg, dimension - 1);
135+
});
136+
}
137+
} else {
138+
if (args.length && dimension) {
139+
args.forEach(arg => {
140+
encodeArgs(components, arg);
141+
});
142+
}
143+
}
144+
};
145+
213146
const encodeArgs = (inputs = [], args) => {
214147
if (inputs.length)
215148
inputs.forEach((input, i) => {
@@ -218,13 +151,11 @@ export function encodeParamsV2ByABI(funABI, args) {
218151
if (args[i])
219152
if (type === 'address') args[i] = _addressToHex(args[i]);
220153
else if (type.match(/^([^\x5b]*)(\x5b|$)/)[0] === 'address[')
221-
args[i] = args[i].map(v => _addressToHex(v));
154+
convertAddresses(args[i])
222155
else if (type.indexOf('tuple') === 0)
223156
if (extractSize(type)) {
224-
if (args[i].length)
225-
args[i].forEach(arg => {
226-
encodeArgs(input.components, arg);
227-
});
157+
const dimension = extractSizeDimensions(type);
158+
mapTuple(input.components, args[i], dimension);
228159
} else encodeArgs(input.components, args[i]);
229160
});
230161
};
@@ -250,7 +181,6 @@ export function encodeParamsV2ByABI(funABI, args) {
250181
return abiCoder.encode(types, args);
251182
}
252183

253-
254184
export function decodeParamsV2ByABI(funABI, data) {
255185
const convertTypeNames = (types) => {
256186
for (let i = 0; i < types.length; i++) {
@@ -260,6 +190,33 @@ export function decodeParamsV2ByABI(funABI, data) {
260190
}
261191
}
262192

193+
const convertAddresses = addrArr => {
194+
if (Array.isArray(addrArr)) {
195+
addrArr.forEach((addrs, i) => {
196+
addrArr[i] = convertAddresses(addrs);
197+
});
198+
return addrArr;
199+
} else {
200+
return TronWeb.address.toHex(addrArr)
201+
}
202+
};
203+
204+
const mapTuple = (components, args, dimension) => {
205+
if (dimension > 1) {
206+
if (args.length) {
207+
args.forEach(arg => {
208+
mapTuple(components, arg, dimension - 1);
209+
});
210+
}
211+
} else {
212+
if (args.length && dimension) {
213+
args.forEach(arg => {
214+
decodeResult(components, arg);
215+
});
216+
}
217+
}
218+
};
219+
263220
const buildFullTypeNameDefinition = (typeDef) => {
264221
if (typeDef && typeDef.type.indexOf('tuple') === 0 && typeDef.components) {
265222
const innerTypes = typeDef.components.map((innerType) => { return buildFullTypeNameDefinition(innerType) });
@@ -283,15 +240,13 @@ export function decodeParamsV2ByABI(funABI, data) {
283240
if(name) result[name] = TronWeb.address.toHex(result[name]);
284241
}
285242
else if (type.match(/^([^\x5b]*)(\x5b|$)/)[0] === 'address[') {
286-
result[i] = result[i].map(v => TronWeb.address.toHex(v));
287-
if(name) result[name] = result[name].map(v => TronWeb.address.toHex(v));
243+
convertAddresses(result[i])
244+
if(name) convertAddresses(result[name])
288245
}
289246
else if (type.indexOf('tuple') === 0)
290247
if (extractSize(type)) {
291-
if (result[i].length)
292-
result[i].forEach(res => {
293-
decodeResult(output.components, res);
294-
});
248+
const dimension = extractSizeDimensions(type);
249+
mapTuple(output.components, result[i], dimension);
295250
} else decodeResult(output.components, result[i]);
296251
});
297252
};

src/utils/ethersUtils.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const SigningKey = utils.SigningKey;
99
const AbiCoder = utils.AbiCoder;
1010
const Interface = utils.Interface;
1111
const FormatTypes = utils.FormatTypes;
12+
const arrayify = utils.arrayify;
1213

1314
export {
1415
keccak256,
@@ -19,5 +20,6 @@ export {
1920
SigningKey,
2021
AbiCoder,
2122
Interface,
22-
FormatTypes
23+
FormatTypes,
24+
arrayify
2325
};
38.7 KB
Binary file not shown.
72 KB
Binary file not shown.

test/testcases/src/disk-utils.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ function loadTests(tag) {
1515
return JSON.parse(zlib.gunzipSync(fs.readFileSync(filename)).toString());
1616
}
1717

18+
function loadTestsJSON(tag) {
19+
let filename = path.resolve(__dirname, '../', tag + '.json');
20+
return JSON.parse(fs.readFileSync(filename).toString());
21+
// let filename = path.resolve(__dirname, '../', tag + '.json');
22+
// return JSON.parse(fs.readFileSync(filename)).toString();
23+
}
24+
1825
function loadData(filename) {
1926
return fs.readFileSync(path.resolve(__dirname, filename));
2027
}
@@ -31,5 +38,6 @@ module.exports = {
3138
saveTests,
3239
loadTests,
3340
loadData,
34-
saveJson
41+
saveJson,
42+
loadTestsJSON
3543
}

0 commit comments

Comments
 (0)