support for int array types[]
This commit is contained in:
parent
2d8383d3c8
commit
b457e88cd0
127
dist/ethereum.js
vendored
127
dist/ethereum.js
vendored
@ -33,15 +33,6 @@ BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_DOWN });
|
|||||||
|
|
||||||
var ETH_PADDING = 32;
|
var ETH_PADDING = 32;
|
||||||
|
|
||||||
// TODO: make these be actually accurate instead of falling back onto JS's doubles.
|
|
||||||
var hexToDec = function (hex) {
|
|
||||||
return parseInt(hex, 16).toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
var decToHex = function (dec) {
|
|
||||||
return parseInt(dec).toString(16);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Finds first index of array element matching pattern
|
/// Finds first index of array element matching pattern
|
||||||
/// @param array
|
/// @param array
|
||||||
/// @param callback pattern
|
/// @param callback pattern
|
||||||
@ -86,55 +77,66 @@ var namedType = function (name) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var arrayType = function (type) {
|
||||||
|
return type.slice(-2) === '[]';
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Formats input value to byte representation of int
|
||||||
|
/// If value is negative, return it's two's complement
|
||||||
|
/// If the value is floating point, round it down
|
||||||
|
/// @returns right-aligned byte representation of int
|
||||||
|
var formatInputInt = function (value) {
|
||||||
|
var padding = ETH_PADDING * 2;
|
||||||
|
if (value instanceof BigNumber || typeof value === 'number') {
|
||||||
|
if (typeof value === 'number')
|
||||||
|
value = new BigNumber(value);
|
||||||
|
value = value.round();
|
||||||
|
|
||||||
|
if (value.lessThan(0))
|
||||||
|
value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1);
|
||||||
|
value = value.toString(16);
|
||||||
|
}
|
||||||
|
else if (value.indexOf('0x') === 0)
|
||||||
|
value = value.substr(2);
|
||||||
|
else if (typeof value === 'string')
|
||||||
|
value = formatInputInt(new BigNumber(value));
|
||||||
|
else
|
||||||
|
value = (+value).toString(16);
|
||||||
|
return padLeft(value, padding);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Formats input value to byte representation of string
|
||||||
|
/// @returns left-algined byte representation of string
|
||||||
|
var formatInputString = function (value) {
|
||||||
|
return web3.fromAscii(value, ETH_PADDING).substr(2);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Formats input value to byte representation of bool
|
||||||
|
/// @returns right-aligned byte representation bool
|
||||||
|
var formatInputBool = function (value) {
|
||||||
|
return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');
|
||||||
|
};
|
||||||
|
|
||||||
|
var dynamicTypeBytes = function (type, value) {
|
||||||
|
// TODO: decide what to do with array of strings
|
||||||
|
if (arrayType(type) || prefixedType('string')(type))
|
||||||
|
return formatInputInt(value.length);
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
/// Setups input formatters for solidity types
|
/// Setups input formatters for solidity types
|
||||||
/// @returns an array of input formatters
|
/// @returns an array of input formatters
|
||||||
var setupInputTypes = function () {
|
var setupInputTypes = function () {
|
||||||
|
|
||||||
/// Formats input value to byte representation of int
|
|
||||||
/// If value is negative, return it's two's complement
|
|
||||||
/// If the value is floating point, round it down
|
|
||||||
/// @returns right-aligned byte representation of int
|
|
||||||
var formatInt = function (value) {
|
|
||||||
var padding = ETH_PADDING * 2;
|
|
||||||
if (value instanceof BigNumber || typeof value === 'number') {
|
|
||||||
if (typeof value === 'number')
|
|
||||||
value = new BigNumber(value);
|
|
||||||
value = value.round();
|
|
||||||
|
|
||||||
if (value.lessThan(0))
|
|
||||||
value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1);
|
|
||||||
value = value.toString(16);
|
|
||||||
}
|
|
||||||
else if (value.indexOf('0x') === 0)
|
|
||||||
value = value.substr(2);
|
|
||||||
else if (typeof value === 'string')
|
|
||||||
value = formatInt(new BigNumber(value));
|
|
||||||
else
|
|
||||||
value = (+value).toString(16);
|
|
||||||
return padLeft(value, padding);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Formats input value to byte representation of string
|
|
||||||
/// @returns left-algined byte representation of string
|
|
||||||
var formatString = function (value) {
|
|
||||||
return web3.fromAscii(value, ETH_PADDING).substr(2);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Formats input value to byte representation of bool
|
|
||||||
/// @returns right-aligned byte representation bool
|
|
||||||
var formatBool = function (value) {
|
|
||||||
return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');
|
|
||||||
};
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{ type: prefixedType('uint'), format: formatInt },
|
{ type: prefixedType('uint'), format: formatInputInt },
|
||||||
{ type: prefixedType('int'), format: formatInt },
|
{ type: prefixedType('int'), format: formatInputInt },
|
||||||
{ type: prefixedType('hash'), format: formatInt },
|
{ type: prefixedType('hash'), format: formatInputInt },
|
||||||
{ type: prefixedType('string'), format: formatString },
|
{ type: prefixedType('string'), format: formatInputString },
|
||||||
{ type: prefixedType('real'), format: formatInt },
|
{ type: prefixedType('real'), format: formatInputInt },
|
||||||
{ type: prefixedType('ureal'), format: formatInt },
|
{ type: prefixedType('ureal'), format: formatInputInt },
|
||||||
{ type: namedType('address'), format: formatInt },
|
{ type: namedType('address'), format: formatInputInt },
|
||||||
{ type: namedType('bool'), format: formatBool }
|
{ type: namedType('bool'), format: formatInputBool }
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -156,7 +158,11 @@ var toAbiInput = function (json, methodName, params) {
|
|||||||
var method = json[index];
|
var method = json[index];
|
||||||
var padding = ETH_PADDING * 2;
|
var padding = ETH_PADDING * 2;
|
||||||
|
|
||||||
for (var i = 0; i < method.inputs.length; i++) {
|
method.inputs.forEach(function (input, index) {
|
||||||
|
bytes += dynamicTypeBytes(input.type, params[index]);
|
||||||
|
});
|
||||||
|
|
||||||
|
method.inputs.forEach(function (input, i) {
|
||||||
var typeMatch = false;
|
var typeMatch = false;
|
||||||
for (var j = 0; j < inputTypes.length && !typeMatch; j++) {
|
for (var j = 0; j < inputTypes.length && !typeMatch; j++) {
|
||||||
typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]);
|
typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]);
|
||||||
@ -166,8 +172,17 @@ var toAbiInput = function (json, methodName, params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var formatter = inputTypes[j - 1].format;
|
var formatter = inputTypes[j - 1].format;
|
||||||
bytes += (formatter ? formatter(params[i]) : params[i]);
|
var toAppend = "";
|
||||||
}
|
|
||||||
|
if (arrayType(method.inputs[i].type))
|
||||||
|
toAppend = params[i].reduce(function (acc, curr) {
|
||||||
|
return acc + formatter(curr);
|
||||||
|
}, "");
|
||||||
|
else
|
||||||
|
toAppend = formatter(params[i]);
|
||||||
|
|
||||||
|
bytes += toAppend;
|
||||||
|
});
|
||||||
return bytes;
|
return bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
4
dist/ethereum.js.map
vendored
4
dist/ethereum.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/ethereum.min.js
vendored
2
dist/ethereum.min.js
vendored
File diff suppressed because one or more lines are too long
119
lib/abi.js
119
lib/abi.js
@ -76,55 +76,66 @@ var namedType = function (name) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var arrayType = function (type) {
|
||||||
|
return type.slice(-2) === '[]';
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Formats input value to byte representation of int
|
||||||
|
/// If value is negative, return it's two's complement
|
||||||
|
/// If the value is floating point, round it down
|
||||||
|
/// @returns right-aligned byte representation of int
|
||||||
|
var formatInputInt = function (value) {
|
||||||
|
var padding = ETH_PADDING * 2;
|
||||||
|
if (value instanceof BigNumber || typeof value === 'number') {
|
||||||
|
if (typeof value === 'number')
|
||||||
|
value = new BigNumber(value);
|
||||||
|
value = value.round();
|
||||||
|
|
||||||
|
if (value.lessThan(0))
|
||||||
|
value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1);
|
||||||
|
value = value.toString(16);
|
||||||
|
}
|
||||||
|
else if (value.indexOf('0x') === 0)
|
||||||
|
value = value.substr(2);
|
||||||
|
else if (typeof value === 'string')
|
||||||
|
value = formatInputInt(new BigNumber(value));
|
||||||
|
else
|
||||||
|
value = (+value).toString(16);
|
||||||
|
return padLeft(value, padding);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Formats input value to byte representation of string
|
||||||
|
/// @returns left-algined byte representation of string
|
||||||
|
var formatInputString = function (value) {
|
||||||
|
return web3.fromAscii(value, ETH_PADDING).substr(2);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Formats input value to byte representation of bool
|
||||||
|
/// @returns right-aligned byte representation bool
|
||||||
|
var formatInputBool = function (value) {
|
||||||
|
return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');
|
||||||
|
};
|
||||||
|
|
||||||
|
var dynamicTypeBytes = function (type, value) {
|
||||||
|
// TODO: decide what to do with array of strings
|
||||||
|
if (arrayType(type) || prefixedType('string')(type))
|
||||||
|
return formatInputInt(value.length);
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
/// Setups input formatters for solidity types
|
/// Setups input formatters for solidity types
|
||||||
/// @returns an array of input formatters
|
/// @returns an array of input formatters
|
||||||
var setupInputTypes = function () {
|
var setupInputTypes = function () {
|
||||||
|
|
||||||
/// Formats input value to byte representation of int
|
|
||||||
/// If value is negative, return it's two's complement
|
|
||||||
/// If the value is floating point, round it down
|
|
||||||
/// @returns right-aligned byte representation of int
|
|
||||||
var formatInt = function (value) {
|
|
||||||
var padding = ETH_PADDING * 2;
|
|
||||||
if (value instanceof BigNumber || typeof value === 'number') {
|
|
||||||
if (typeof value === 'number')
|
|
||||||
value = new BigNumber(value);
|
|
||||||
value = value.round();
|
|
||||||
|
|
||||||
if (value.lessThan(0))
|
|
||||||
value = new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).plus(value).plus(1);
|
|
||||||
value = value.toString(16);
|
|
||||||
}
|
|
||||||
else if (value.indexOf('0x') === 0)
|
|
||||||
value = value.substr(2);
|
|
||||||
else if (typeof value === 'string')
|
|
||||||
value = formatInt(new BigNumber(value));
|
|
||||||
else
|
|
||||||
value = (+value).toString(16);
|
|
||||||
return padLeft(value, padding);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Formats input value to byte representation of string
|
|
||||||
/// @returns left-algined byte representation of string
|
|
||||||
var formatString = function (value) {
|
|
||||||
return web3.fromAscii(value, ETH_PADDING).substr(2);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Formats input value to byte representation of bool
|
|
||||||
/// @returns right-aligned byte representation bool
|
|
||||||
var formatBool = function (value) {
|
|
||||||
return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');
|
|
||||||
};
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{ type: prefixedType('uint'), format: formatInt },
|
{ type: prefixedType('uint'), format: formatInputInt },
|
||||||
{ type: prefixedType('int'), format: formatInt },
|
{ type: prefixedType('int'), format: formatInputInt },
|
||||||
{ type: prefixedType('hash'), format: formatInt },
|
{ type: prefixedType('hash'), format: formatInputInt },
|
||||||
{ type: prefixedType('string'), format: formatString },
|
{ type: prefixedType('string'), format: formatInputString },
|
||||||
{ type: prefixedType('real'), format: formatInt },
|
{ type: prefixedType('real'), format: formatInputInt },
|
||||||
{ type: prefixedType('ureal'), format: formatInt },
|
{ type: prefixedType('ureal'), format: formatInputInt },
|
||||||
{ type: namedType('address'), format: formatInt },
|
{ type: namedType('address'), format: formatInputInt },
|
||||||
{ type: namedType('bool'), format: formatBool }
|
{ type: namedType('bool'), format: formatInputBool }
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -146,7 +157,12 @@ var toAbiInput = function (json, methodName, params) {
|
|||||||
var method = json[index];
|
var method = json[index];
|
||||||
var padding = ETH_PADDING * 2;
|
var padding = ETH_PADDING * 2;
|
||||||
|
|
||||||
for (var i = 0; i < method.inputs.length; i++) {
|
/// first we iterate in search for dynamic
|
||||||
|
method.inputs.forEach(function (input, index) {
|
||||||
|
bytes += dynamicTypeBytes(input.type, params[index]);
|
||||||
|
});
|
||||||
|
|
||||||
|
method.inputs.forEach(function (input, i) {
|
||||||
var typeMatch = false;
|
var typeMatch = false;
|
||||||
for (var j = 0; j < inputTypes.length && !typeMatch; j++) {
|
for (var j = 0; j < inputTypes.length && !typeMatch; j++) {
|
||||||
typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]);
|
typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]);
|
||||||
@ -156,8 +172,17 @@ var toAbiInput = function (json, methodName, params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var formatter = inputTypes[j - 1].format;
|
var formatter = inputTypes[j - 1].format;
|
||||||
bytes += (formatter ? formatter(params[i]) : params[i]);
|
var toAppend = "";
|
||||||
}
|
|
||||||
|
if (arrayType(method.inputs[i].type))
|
||||||
|
toAppend = params[i].reduce(function (acc, curr) {
|
||||||
|
return acc + formatter(curr);
|
||||||
|
}, "");
|
||||||
|
else
|
||||||
|
toAppend = formatter(params[i]);
|
||||||
|
|
||||||
|
bytes += toAppend;
|
||||||
|
});
|
||||||
return bytes;
|
return bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -307,8 +307,14 @@ describe('abi', function() {
|
|||||||
var parser = abi.inputParser(d);
|
var parser = abi.inputParser(d);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert.equal(parser.test('hello'), "68656c6c6f000000000000000000000000000000000000000000000000000000");
|
assert.equal(
|
||||||
assert.equal(parser.test('world'), "776f726c64000000000000000000000000000000000000000000000000000000");
|
parser.test('hello'),
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
parser.test('world'),
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000005776f726c64000000000000000000000000000000000000000000000000000000"
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use proper method name', function () {
|
it('should use proper method name', function () {
|
||||||
@ -346,9 +352,34 @@ describe('abi', function() {
|
|||||||
|
|
||||||
//then
|
//then
|
||||||
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001");
|
assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001");
|
||||||
assert.equal(parser.test2('hello'), "68656c6c6f000000000000000000000000000000000000000000000000000000");
|
assert.equal(
|
||||||
|
parser.test2('hello'),
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"
|
||||||
|
);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should parse input array of ints', function () {
|
||||||
|
|
||||||
|
// given
|
||||||
|
var d = clone(description);
|
||||||
|
|
||||||
|
d[0].inputs = [
|
||||||
|
{ type: "int[]" }
|
||||||
|
];
|
||||||
|
|
||||||
|
// when
|
||||||
|
var parser = abi.inputParser(d);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert.equal(
|
||||||
|
parser.test([5, 6]),
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000002" +
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000005" +
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000006"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('outputParser', function() {
|
describe('outputParser', function() {
|
||||||
|
Loading…
Reference in New Issue
Block a user