output parser string support

pull/272/merge
Marek Kotewicz 10 years ago
parent b457e88cd0
commit 1e2c1ae98a
  1. 129
      dist/ethereum.js
  2. 4
      dist/ethereum.js.map
  3. 2
      dist/ethereum.min.js
  4. 128
      lib/abi.js
  5. 71
      test/abi.parsers.js

129
dist/ethereum.js vendored

@ -158,6 +158,7 @@ var toAbiInput = function (json, methodName, params) {
var method = json[index]; var method = json[index];
var padding = ETH_PADDING * 2; var padding = ETH_PADDING * 2;
/// first we iterate in search for dynamic
method.inputs.forEach(function (input, index) { method.inputs.forEach(function (input, index) {
bytes += dynamicTypeBytes(input.type, params[index]); bytes += dynamicTypeBytes(input.type, params[index]);
}); });
@ -186,57 +187,63 @@ var toAbiInput = function (json, methodName, params) {
return bytes; return bytes;
}; };
/// Setups output formaters for solidity types /// Formats input right-aligned input bytes to int
/// @returns an array of output formatters /// @returns right-aligned input bytes formatted to int
var setupOutputTypes = function () { var formatOutputInt = function (value) {
// check if it's negative number
// it it is, return two's complement
var firstBit = new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1);
if (firstBit === '1') {
return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);
}
return new BigNumber(value, 16);
};
/// Formats input right-aligned input bytes to int /// Formats big right-aligned input bytes to uint
/// @returns right-aligned input bytes formatted to int /// @returns right-aligned input bytes formatted to uint
var formatInt = function (value) { var formatOutputUInt = function (value) {
// check if it's negative number return new BigNumber(value, 16);
// it it is, return two's complement };
var firstBit = new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1);
if (firstBit === '1') {
return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);
}
return new BigNumber(value, 16);
};
/// Formats big right-aligned input bytes to uint /// @returns right-aligned input bytes formatted to hex
/// @returns right-aligned input bytes formatted to uint var formatOutputHash = function (value) {
var formatUInt = function (value) { return "0x" + value;
return new BigNumber(value, 16); };
};
/// @returns right-aligned input bytes formatted to hex /// @returns right-aligned input bytes formatted to bool
var formatHash = function (value) { var formatOutputBool = function (value) {
return "0x" + value; return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;
}; };
/// @returns right-aligned input bytes formatted to bool /// @returns left-aligned input bytes formatted to ascii string
var formatBool = function (value) { var formatOutputString = function (value) {
return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; return web3.toAscii(value);
}; };
/// @returns left-aligned input bytes formatted to ascii string /// @returns right-aligned input bytes formatted to address
var formatString = function (value) { var formatOutputAddress = function (value) {
return web3.toAscii(value); return "0x" + value.slice(value.length - 40, value.length);
}; };
/// @returns right-aligned input bytes formatted to address var dynamicBytesLength = function (type) {
var formatAddress = function (value) { if (arrayType(type) || prefixedType('string')(type))
return "0x" + value.slice(value.length - 40, value.length); return ETH_PADDING * 2;
}; return 0;
};
/// Setups output formaters for solidity types
/// @returns an array of output formatters
var setupOutputTypes = function () {
return [ return [
{ type: prefixedType('uint'), format: formatUInt }, { type: prefixedType('uint'), format: formatOutputUInt },
{ type: prefixedType('int'), format: formatInt }, { type: prefixedType('int'), format: formatOutputInt },
{ type: prefixedType('hash'), format: formatHash }, { type: prefixedType('hash'), format: formatOutputHash },
{ type: prefixedType('string'), format: formatString }, { type: prefixedType('string'), format: formatOutputString },
{ type: prefixedType('real'), format: formatInt }, { type: prefixedType('real'), format: formatOutputInt },
{ type: prefixedType('ureal'), format: formatInt }, { type: prefixedType('ureal'), format: formatOutputInt },
{ type: namedType('address'), format: formatAddress }, { type: namedType('address'), format: formatOutputAddress },
{ type: namedType('bool'), format: formatBool } { type: namedType('bool'), format: formatOutputBool }
]; ];
}; };
@ -259,22 +266,44 @@ var fromAbiOutput = function (json, methodName, output) {
var result = []; var result = [];
var method = json[index]; var method = json[index];
var padding = ETH_PADDING * 2; var padding = ETH_PADDING * 2;
for (var i = 0; i < method.outputs.length; i++) {
var dynamicPartLength = method.outputs.reduce(function (acc, curr) {
return acc + dynamicBytesLength(curr.type);
}, 0);
var dynamicPart = output.slice(0, dynamicPartLength);
output = output.slice(dynamicPartLength);
method.outputs.forEach(function (out, i) {
var typeMatch = false; var typeMatch = false;
for (var j = 0; j < outputTypes.length && !typeMatch; j++) { for (var j = 0; j < outputTypes.length && !typeMatch; j++) {
typeMatch = outputTypes[j].type(method.outputs[i].type); typeMatch = outputTypes[j].type(method.outputs[i].type);
} }
if (!typeMatch) { if (!typeMatch) {
// not found output parsing
console.error('output parser does not support type: ' + method.outputs[i].type); console.error('output parser does not support type: ' + method.outputs[i].type);
continue;
} }
var res = output.slice(0, padding);
var formatter = outputTypes[j - 1].format; var formatter = outputTypes[j - 1].format;
result.push(formatter ? formatter(res) : ("0x" + res)); if (arrayType(method.outputs[i].type)) {
output = output.slice(padding); var size = formatOutputUInt(dynamicPart.slice(0, padding));
} dynamicPart = dynamicPart.slice(padding);
var array = [];
for (var k = 0; k < size; k++) {
array.push(formatter(output.slice(0, padding)));
output = output.slice(padding);
}
result.push(array);
}
else if (prefixedType('string')(method.outputs[i].type)) {
dynamicPart = dynamicPart.slice(padding);
result.push(formatter(output.slice(0, padding)));
output = output.slice(padding);
} else {
result.push(formatter(output.slice(0, padding)));
output = output.slice(padding);
}
});
return result; return result;
}; };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -186,57 +186,63 @@ var toAbiInput = function (json, methodName, params) {
return bytes; return bytes;
}; };
/// Setups output formaters for solidity types /// Formats input right-aligned input bytes to int
/// @returns an array of output formatters /// @returns right-aligned input bytes formatted to int
var setupOutputTypes = function () { var formatOutputInt = function (value) {
// check if it's negative number
// it it is, return two's complement
var firstBit = new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1);
if (firstBit === '1') {
return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);
}
return new BigNumber(value, 16);
};
/// Formats input right-aligned input bytes to int /// Formats big right-aligned input bytes to uint
/// @returns right-aligned input bytes formatted to int /// @returns right-aligned input bytes formatted to uint
var formatInt = function (value) { var formatOutputUInt = function (value) {
// check if it's negative number return new BigNumber(value, 16);
// it it is, return two's complement };
var firstBit = new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1);
if (firstBit === '1') {
return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);
}
return new BigNumber(value, 16);
};
/// Formats big right-aligned input bytes to uint /// @returns right-aligned input bytes formatted to hex
/// @returns right-aligned input bytes formatted to uint var formatOutputHash = function (value) {
var formatUInt = function (value) { return "0x" + value;
return new BigNumber(value, 16); };
};
/// @returns right-aligned input bytes formatted to hex /// @returns right-aligned input bytes formatted to bool
var formatHash = function (value) { var formatOutputBool = function (value) {
return "0x" + value; return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;
}; };
/// @returns right-aligned input bytes formatted to bool /// @returns left-aligned input bytes formatted to ascii string
var formatBool = function (value) { var formatOutputString = function (value) {
return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; return web3.toAscii(value);
}; };
/// @returns left-aligned input bytes formatted to ascii string /// @returns right-aligned input bytes formatted to address
var formatString = function (value) { var formatOutputAddress = function (value) {
return web3.toAscii(value); return "0x" + value.slice(value.length - 40, value.length);
}; };
/// @returns right-aligned input bytes formatted to address var dynamicBytesLength = function (type) {
var formatAddress = function (value) { if (arrayType(type) || prefixedType('string')(type))
return "0x" + value.slice(value.length - 40, value.length); return ETH_PADDING * 2;
}; return 0;
};
/// Setups output formaters for solidity types
/// @returns an array of output formatters
var setupOutputTypes = function () {
return [ return [
{ type: prefixedType('uint'), format: formatUInt }, { type: prefixedType('uint'), format: formatOutputUInt },
{ type: prefixedType('int'), format: formatInt }, { type: prefixedType('int'), format: formatOutputInt },
{ type: prefixedType('hash'), format: formatHash }, { type: prefixedType('hash'), format: formatOutputHash },
{ type: prefixedType('string'), format: formatString }, { type: prefixedType('string'), format: formatOutputString },
{ type: prefixedType('real'), format: formatInt }, { type: prefixedType('real'), format: formatOutputInt },
{ type: prefixedType('ureal'), format: formatInt }, { type: prefixedType('ureal'), format: formatOutputInt },
{ type: namedType('address'), format: formatAddress }, { type: namedType('address'), format: formatOutputAddress },
{ type: namedType('bool'), format: formatBool } { type: namedType('bool'), format: formatOutputBool }
]; ];
}; };
@ -259,22 +265,44 @@ var fromAbiOutput = function (json, methodName, output) {
var result = []; var result = [];
var method = json[index]; var method = json[index];
var padding = ETH_PADDING * 2; var padding = ETH_PADDING * 2;
for (var i = 0; i < method.outputs.length; i++) {
var dynamicPartLength = method.outputs.reduce(function (acc, curr) {
return acc + dynamicBytesLength(curr.type);
}, 0);
var dynamicPart = output.slice(0, dynamicPartLength);
output = output.slice(dynamicPartLength);
method.outputs.forEach(function (out, i) {
var typeMatch = false; var typeMatch = false;
for (var j = 0; j < outputTypes.length && !typeMatch; j++) { for (var j = 0; j < outputTypes.length && !typeMatch; j++) {
typeMatch = outputTypes[j].type(method.outputs[i].type); typeMatch = outputTypes[j].type(method.outputs[i].type);
} }
if (!typeMatch) { if (!typeMatch) {
// not found output parsing
console.error('output parser does not support type: ' + method.outputs[i].type); console.error('output parser does not support type: ' + method.outputs[i].type);
continue;
} }
var res = output.slice(0, padding);
var formatter = outputTypes[j - 1].format; var formatter = outputTypes[j - 1].format;
result.push(formatter ? formatter(res) : ("0x" + res)); if (arrayType(method.outputs[i].type)) {
output = output.slice(padding); var size = formatOutputUInt(dynamicPart.slice(0, padding));
} dynamicPart = dynamicPart.slice(padding);
var array = [];
for (var k = 0; k < size; k++) {
array.push(formatter(output.slice(0, padding)));
output = output.slice(padding);
}
result.push(array);
}
else if (prefixedType('string')(method.outputs[i].type)) {
dynamicPart = dynamicPart.slice(padding);
result.push(formatter(output.slice(0, padding)));
output = output.slice(padding);
} else {
result.push(formatter(output.slice(0, padding)));
output = output.slice(padding);
}
});
return result; return result;
}; };

@ -40,9 +40,9 @@ describe('abi', function() {
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal( assert.equal(
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)),
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000");
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003");
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000");
@ -71,9 +71,9 @@ describe('abi', function() {
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal( assert.equal(
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)),
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000");
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003");
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000");
@ -101,9 +101,9 @@ describe('abi', function() {
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal( assert.equal(
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)),
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000");
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003");
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000");
@ -134,9 +134,9 @@ describe('abi', function() {
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal( assert.equal(
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)),
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000");
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003");
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000");
@ -166,9 +166,9 @@ describe('abi', function() {
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal( assert.equal(
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)),
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000");
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003");
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000");
@ -199,9 +199,9 @@ describe('abi', function() {
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal( assert.equal(
parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)),
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
); );
assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000");
assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003");
assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000");
@ -396,8 +396,18 @@ describe('abi', function() {
var parser = abi.outputParser(d); var parser = abi.outputParser(d);
// then // then
assert.equal(parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000")[0], 'hello'); assert.equal(
assert.equal(parser.test("0x776f726c64000000000000000000000000000000000000000000000000000000")[0], 'world'); parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000")[0],
'hello'
);
assert.equal(
parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"776f726c64000000000000000000000000000000000000000000000000000000")[0],
'world'
);
}); });
@ -644,12 +654,21 @@ describe('abi', function() {
// then // then
assert.equal( assert.equal(
parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[0], parser.test("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000" +
"776f726c64000000000000000000000000000000000000000000000000000000")[0],
'hello' 'hello'
); );
assert.equal( assert.equal(
parser.test("0x68656c6c6f000000000000000000000000000000000000000000000000000000776f726c64000000000000000000000000000000000000000000000000000000")[1], parser.test("0x" +
'world'); "0000000000000000000000000000000000000000000000000000000000000005" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000" +
"776f726c64000000000000000000000000000000000000000000000000000000")[1],
'world'
);
}); });
@ -689,7 +708,11 @@ describe('abi', function() {
//then //then
assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1);
assert.equal(parser.test2("0x68656c6c6f000000000000000000000000000000000000000000000000000000")[0], "hello"); assert.equal(parser.test2("0x" +
"0000000000000000000000000000000000000000000000000000000000000005" +
"68656c6c6f000000000000000000000000000000000000000000000000000000")[0],
"hello"
);
}); });

Loading…
Cancel
Save