Merge pull request #81 from ethers/arraySupport
constants should be before array contents, fixes #30
This commit is contained in:
commit
fd85749764
41
lib/abi.js
41
lib/abi.js
|
@ -21,7 +21,7 @@
|
|||
* @date 2014
|
||||
*/
|
||||
|
||||
var web3 = require('./web3');
|
||||
var web3 = require('./web3');
|
||||
var utils = require('./utils');
|
||||
var types = require('./types');
|
||||
var c = require('./const');
|
||||
|
@ -40,11 +40,11 @@ var arrayType = function (type) {
|
|||
var dynamicTypeBytes = function (type, value) {
|
||||
// TODO: decide what to do with array of strings
|
||||
if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length.
|
||||
return f.formatInputInt(value.length);
|
||||
return f.formatInputInt(value.length);
|
||||
return "";
|
||||
};
|
||||
|
||||
var inputTypes = types.inputTypes();
|
||||
var inputTypes = types.inputTypes();
|
||||
|
||||
/// Formats input params to bytes
|
||||
/// @param abi contract method inputs
|
||||
|
@ -52,8 +52,10 @@ var inputTypes = types.inputTypes();
|
|||
/// @returns bytes representation of input params
|
||||
var formatInput = function (inputs, params) {
|
||||
var bytes = "";
|
||||
var toAppendConstant = "";
|
||||
var toAppendArrayContent = "";
|
||||
|
||||
/// first we iterate in search for dynamic
|
||||
/// first we iterate in search for dynamic
|
||||
inputs.forEach(function (input, index) {
|
||||
bytes += dynamicTypeBytes(input.type, params[index]);
|
||||
});
|
||||
|
@ -68,17 +70,17 @@ var formatInput = function (inputs, params) {
|
|||
}
|
||||
|
||||
var formatter = inputTypes[j - 1].format;
|
||||
var toAppend = "";
|
||||
|
||||
if (arrayType(inputs[i].type))
|
||||
toAppend = params[i].reduce(function (acc, curr) {
|
||||
toAppendArrayContent += params[i].reduce(function (acc, curr) {
|
||||
return acc + formatter(curr);
|
||||
}, "");
|
||||
else
|
||||
toAppend = formatter(params[i]);
|
||||
|
||||
bytes += toAppend;
|
||||
toAppendConstant += formatter(params[i]);
|
||||
});
|
||||
|
||||
bytes += toAppendConstant + toAppendArrayContent;
|
||||
|
||||
return bytes;
|
||||
};
|
||||
|
||||
|
@ -88,14 +90,14 @@ var dynamicBytesLength = function (type) {
|
|||
return 0;
|
||||
};
|
||||
|
||||
var outputTypes = types.outputTypes();
|
||||
var outputTypes = types.outputTypes();
|
||||
|
||||
/// Formats output bytes back to param list
|
||||
/// @param contract abi method outputs
|
||||
/// @param bytes representtion of output
|
||||
/// @returns array of output params
|
||||
/// @param bytes representtion of output
|
||||
/// @returns array of output params
|
||||
var formatOutput = function (outs, output) {
|
||||
|
||||
|
||||
output = output.slice(2);
|
||||
var result = [];
|
||||
var padding = c.ETH_PADDING * 2;
|
||||
|
@ -103,7 +105,7 @@ var formatOutput = function (outs, output) {
|
|||
var dynamicPartLength = outs.reduce(function (acc, curr) {
|
||||
return acc + dynamicBytesLength(curr.type);
|
||||
}, 0);
|
||||
|
||||
|
||||
var dynamicPart = output.slice(0, dynamicPartLength);
|
||||
output = output.slice(dynamicPartLength);
|
||||
|
||||
|
@ -124,13 +126,13 @@ var formatOutput = function (outs, output) {
|
|||
dynamicPart = dynamicPart.slice(padding);
|
||||
var array = [];
|
||||
for (var k = 0; k < size; k++) {
|
||||
array.push(formatter(output.slice(0, padding)));
|
||||
array.push(formatter(output.slice(0, padding)));
|
||||
output = output.slice(padding);
|
||||
}
|
||||
result.push(array);
|
||||
}
|
||||
else if (types.prefixedType('string')(outs[i].type)) {
|
||||
dynamicPart = dynamicPart.slice(padding);
|
||||
dynamicPart = dynamicPart.slice(padding);
|
||||
result.push(formatter(output.slice(0, padding)));
|
||||
output = output.slice(padding);
|
||||
} else {
|
||||
|
@ -148,14 +150,14 @@ var formatOutput = function (outs, output) {
|
|||
var inputParser = function (json) {
|
||||
var parser = {};
|
||||
json.forEach(function (method) {
|
||||
var displayName = utils.extractDisplayName(method.name);
|
||||
var displayName = utils.extractDisplayName(method.name);
|
||||
var typeName = utils.extractTypeName(method.name);
|
||||
|
||||
var impl = function () {
|
||||
var params = Array.prototype.slice.call(arguments);
|
||||
return formatInput(method.inputs, params);
|
||||
};
|
||||
|
||||
|
||||
if (parser[displayName] === undefined) {
|
||||
parser[displayName] = impl;
|
||||
}
|
||||
|
@ -172,7 +174,7 @@ var outputParser = function (json) {
|
|||
var parser = {};
|
||||
json.forEach(function (method) {
|
||||
|
||||
var displayName = utils.extractDisplayName(method.name);
|
||||
var displayName = utils.extractDisplayName(method.name);
|
||||
var typeName = utils.extractTypeName(method.name);
|
||||
|
||||
var impl = function (output) {
|
||||
|
@ -207,4 +209,3 @@ module.exports = {
|
|||
signatureFromAscii: signatureFromAscii,
|
||||
eventSignatureFromAscii: eventSignatureFromAscii
|
||||
};
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ describe('abi', function() {
|
|||
d[0].inputs = [
|
||||
{ type: "uint" }
|
||||
];
|
||||
|
||||
|
||||
// when
|
||||
var parser = abi.inputParser(d);
|
||||
|
||||
|
@ -37,7 +37,7 @@ describe('abi', function() {
|
|||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001");
|
||||
assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a");
|
||||
assert.equal(
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
);
|
||||
assert.equal(
|
||||
|
@ -67,7 +67,7 @@ describe('abi', function() {
|
|||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001");
|
||||
assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a");
|
||||
assert.equal(
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
);
|
||||
assert.equal(
|
||||
|
@ -80,7 +80,7 @@ describe('abi', function() {
|
|||
assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003");
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should parse input uint256', function() {
|
||||
|
||||
// given
|
||||
|
@ -97,7 +97,7 @@ describe('abi', function() {
|
|||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001");
|
||||
assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a");
|
||||
assert.equal(
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
);
|
||||
assert.equal(
|
||||
|
@ -108,7 +108,7 @@ describe('abi', function() {
|
|||
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003");
|
||||
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003");
|
||||
|
||||
|
||||
});
|
||||
|
||||
it('should parse input int', function() {
|
||||
|
@ -119,7 +119,7 @@ describe('abi', function() {
|
|||
d[0].inputs = [
|
||||
{ type: "int" }
|
||||
];
|
||||
|
||||
|
||||
// when
|
||||
var parser = abi.inputParser(d);
|
||||
|
||||
|
@ -130,7 +130,7 @@ describe('abi', function() {
|
|||
assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe");
|
||||
assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0");
|
||||
assert.equal(
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
);
|
||||
assert.equal(
|
||||
|
@ -162,7 +162,7 @@ describe('abi', function() {
|
|||
assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe");
|
||||
assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0");
|
||||
assert.equal(
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
);
|
||||
assert.equal(
|
||||
|
@ -177,7 +177,7 @@ describe('abi', function() {
|
|||
});
|
||||
|
||||
it('should parse input int256', function() {
|
||||
|
||||
|
||||
// given
|
||||
var d = clone(description);
|
||||
|
||||
|
@ -195,7 +195,7 @@ describe('abi', function() {
|
|||
assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe");
|
||||
assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0");
|
||||
assert.equal(
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
);
|
||||
assert.equal(
|
||||
|
@ -206,11 +206,11 @@ describe('abi', function() {
|
|||
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003");
|
||||
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003");
|
||||
|
||||
|
||||
});
|
||||
|
||||
it('should parse input bool', function() {
|
||||
|
||||
|
||||
// given
|
||||
var d = clone(description);
|
||||
|
||||
|
@ -235,14 +235,14 @@ describe('abi', function() {
|
|||
d[0].inputs = [
|
||||
{ type: "hash" }
|
||||
];
|
||||
|
||||
|
||||
// when
|
||||
var parser = abi.inputParser(d);
|
||||
|
||||
// then
|
||||
assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1");
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse input hash256', function() {
|
||||
|
||||
|
@ -272,7 +272,7 @@ describe('abi', function() {
|
|||
|
||||
// when
|
||||
var parser = abi.inputParser(d);
|
||||
|
||||
|
||||
// then
|
||||
assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1");
|
||||
});
|
||||
|
@ -285,17 +285,17 @@ describe('abi', function() {
|
|||
d[0].inputs = [
|
||||
{ type: "address" }
|
||||
];
|
||||
|
||||
|
||||
// when
|
||||
var parser = abi.inputParser(d)
|
||||
|
||||
|
||||
// then
|
||||
assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1");
|
||||
|
||||
});
|
||||
|
||||
it('should parse input string', function () {
|
||||
|
||||
|
||||
// given
|
||||
var d = clone(description);
|
||||
|
||||
|
@ -308,7 +308,7 @@ describe('abi', function() {
|
|||
|
||||
// then
|
||||
assert.equal(
|
||||
parser.test('hello'),
|
||||
parser.test('hello'),
|
||||
"000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"
|
||||
);
|
||||
assert.equal(
|
||||
|
@ -318,7 +318,7 @@ describe('abi', function() {
|
|||
});
|
||||
|
||||
it('should use proper method name', function () {
|
||||
|
||||
|
||||
// given
|
||||
var d = clone(description);
|
||||
d[0].name = 'helloworld(int)';
|
||||
|
@ -334,9 +334,9 @@ describe('abi', function() {
|
|||
assert.equal(parser.helloworld['int'](1), "0000000000000000000000000000000000000000000000000000000000000001");
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should parse multiple methods', function () {
|
||||
|
||||
|
||||
// given
|
||||
var d = [{
|
||||
name: "test",
|
||||
|
@ -356,14 +356,14 @@ describe('abi', function() {
|
|||
//then
|
||||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001");
|
||||
assert.equal(
|
||||
parser.test2('hello'),
|
||||
parser.test2('hello'),
|
||||
"000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
it('should parse input array of ints', function () {
|
||||
|
||||
|
||||
// given
|
||||
var d = clone(description);
|
||||
|
||||
|
@ -377,14 +377,91 @@ describe('abi', function() {
|
|||
// then
|
||||
assert.equal(
|
||||
parser.test([5, 6]),
|
||||
"0000000000000000000000000000000000000000000000000000000000000002" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000005" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000002" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000005" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000006"
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse an array followed by an int', function () {
|
||||
|
||||
// given
|
||||
var d = clone(description);
|
||||
|
||||
d[0].inputs = [
|
||||
{ type: "int[]" },
|
||||
{ type: "int" }
|
||||
];
|
||||
|
||||
// when
|
||||
var parser = abi.inputParser(d);
|
||||
|
||||
// then
|
||||
assert.equal(
|
||||
parser.test([5, 6], 3),
|
||||
"0000000000000000000000000000000000000000000000000000000000000002" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000003" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000005" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000006"
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse an int followed by an array', function () {
|
||||
|
||||
// given
|
||||
var d = clone(description);
|
||||
|
||||
d[0].inputs = [
|
||||
{ type: "int" },
|
||||
{ type: "int[]" }
|
||||
];
|
||||
|
||||
// when
|
||||
var parser = abi.inputParser(d);
|
||||
|
||||
// then
|
||||
assert.equal(
|
||||
parser.test(3, [5, 6]),
|
||||
"0000000000000000000000000000000000000000000000000000000000000002" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000003" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000005" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000006"
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse mixture of arrays and ints', function () {
|
||||
|
||||
// given
|
||||
var d = clone(description);
|
||||
|
||||
d[0].inputs = [
|
||||
{ type: "int" },
|
||||
{ type: "int[]" },
|
||||
{ type: "int" },
|
||||
{ type: "int[]" }
|
||||
];
|
||||
|
||||
// when
|
||||
var parser = abi.inputParser(d);
|
||||
|
||||
// then
|
||||
assert.equal(
|
||||
parser.test(3, [5, 6, 1, 2], 7, [8, 9]),
|
||||
"0000000000000000000000000000000000000000000000000000000000000004" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000002" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000003" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000007" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000005" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000006" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000001" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000002" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000008" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000009"
|
||||
);
|
||||
});
|
||||
|
||||
it('should parse input real', function () {
|
||||
|
||||
|
||||
// given
|
||||
var d = clone(description);
|
||||
|
||||
|
@ -396,15 +473,15 @@ describe('abi', function() {
|
|||
var parser = abi.inputParser(d);
|
||||
|
||||
// then
|
||||
assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000");
|
||||
assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000");
|
||||
assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000");
|
||||
assert.equal(parser.test([-1]), "ffffffffffffffffffffffffffffffff00000000000000000000000000000000");
|
||||
|
||||
assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000");
|
||||
assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000");
|
||||
assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000");
|
||||
assert.equal(parser.test([-1]), "ffffffffffffffffffffffffffffffff00000000000000000000000000000000");
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should parse input ureal', function () {
|
||||
|
||||
|
||||
// given
|
||||
var d = clone(description);
|
||||
|
||||
|
@ -416,12 +493,11 @@ describe('abi', function() {
|
|||
var parser = abi.inputParser(d);
|
||||
|
||||
// then
|
||||
assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000");
|
||||
assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000");
|
||||
assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000");
|
||||
|
||||
assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000");
|
||||
assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000");
|
||||
assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000");
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue