mirror of https://github.com/status-im/web3.js.git
solidity abi refactor in progress
This commit is contained in:
parent
271b00f069
commit
d643d06b78
|
@ -26,6 +26,7 @@ var c = require('../utils/config');
|
|||
var types = require('./types');
|
||||
var f = require('./formatters');
|
||||
var solUtils = require('./utils');
|
||||
var SolidityInputParam = f.SolidityInputParam;
|
||||
|
||||
/**
|
||||
* throw incorrect type error
|
||||
|
@ -48,22 +49,7 @@ var isArrayType = function (type) {
|
|||
return type.slice(-2) === '[]';
|
||||
};
|
||||
|
||||
/**
|
||||
* This method should be called to return dynamic type length in hex
|
||||
*
|
||||
* @method dynamicTypeBytes
|
||||
* @param {String} type
|
||||
* @param {String|Array} dynamic type
|
||||
* @return {String} length of dynamic type in hex or empty string if type is not dynamic
|
||||
*/
|
||||
var dynamicTypeBytes = function (type, value) {
|
||||
// TODO: decide what to do with array of strings
|
||||
if (isArrayType(type) || type === 'bytes')
|
||||
return f.formatInputInt(value.length);
|
||||
return "";
|
||||
};
|
||||
|
||||
var inputTypes = types.inputTypes();
|
||||
//var inputTypes = types.inputTypes();
|
||||
|
||||
/**
|
||||
* Formats input params to bytes
|
||||
|
@ -74,40 +60,13 @@ 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
|
||||
inputs.forEach(function (input, index) {
|
||||
bytes += dynamicTypeBytes(input.type, params[index]);
|
||||
});
|
||||
|
||||
inputs.forEach(function (input, i) {
|
||||
/*jshint maxcomplexity:5 */
|
||||
var typeMatch = false;
|
||||
for (var j = 0; j < inputTypes.length && !typeMatch; j++) {
|
||||
typeMatch = inputTypes[j].type(inputs[i].type, params[i]);
|
||||
}
|
||||
if (!typeMatch) {
|
||||
throwTypeError(inputs[i].type);
|
||||
}
|
||||
|
||||
var formatter = inputTypes[j - 1].format;
|
||||
|
||||
if (isArrayType(inputs[i].type))
|
||||
toAppendArrayContent += params[i].reduce(function (acc, curr) {
|
||||
return acc + formatter(curr);
|
||||
}, "");
|
||||
else if (inputs[i].type === 'bytes')
|
||||
toAppendArrayContent += formatter(params[i]);
|
||||
else
|
||||
toAppendConstant += formatter(params[i]);
|
||||
});
|
||||
|
||||
bytes += toAppendConstant + toAppendArrayContent;
|
||||
|
||||
return bytes;
|
||||
//var result =
|
||||
return inputs.map(function (input, index) {
|
||||
return types.sf.formatInput(input.type, params[index]);
|
||||
}).reduce(function (acc, solidityParam) {
|
||||
acc.append(solidityParam);
|
||||
return acc;
|
||||
}, new SolidityInputParam()).encode();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,22 @@ var BigNumber = require('bignumber.js');
|
|||
var utils = require('../utils/utils');
|
||||
var c = require('../utils/config');
|
||||
|
||||
var SolidityInputParam = function (value, prefix, suffix) {
|
||||
this.prefix = prefix || '';
|
||||
this.value = value || '';
|
||||
this.suffix = suffix || '';
|
||||
};
|
||||
|
||||
SolidityInputParam.prototype.append = function (param) {
|
||||
this.prefix += param.prefix;
|
||||
this.value += param.value;
|
||||
this.suffix += param.suffix;
|
||||
};
|
||||
|
||||
SolidityInputParam.prototype.encode = function () {
|
||||
return this.prefix + this.value + this.suffix;
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats input value to byte representation of int
|
||||
* If value is negative, return it's two's complement
|
||||
|
@ -36,7 +52,8 @@ var c = require('../utils/config');
|
|||
var formatInputInt = function (value) {
|
||||
var padding = c.ETH_PADDING * 2;
|
||||
BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);
|
||||
return utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);
|
||||
var result = utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);
|
||||
return new SolidityInputParam(result);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -47,7 +64,8 @@ var formatInputInt = function (value) {
|
|||
* @returns {String} left-algined byte representation of string
|
||||
*/
|
||||
var formatInputString = function (value) {
|
||||
return utils.fromAscii(value, c.ETH_PADDING).substr(2);
|
||||
var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);
|
||||
return new SolidityInputParam('', formatInputInt(value.length).value, result);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -58,7 +76,8 @@ var formatInputString = function (value) {
|
|||
* @returns {String} right-aligned byte representation bool
|
||||
*/
|
||||
var formatInputBool = function (value) {
|
||||
return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');
|
||||
var result = '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');
|
||||
return new SolidityInputParam(result);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -70,7 +89,7 @@ var formatInputBool = function (value) {
|
|||
* @returns {String} byte representation of real
|
||||
*/
|
||||
var formatInputReal = function (value) {
|
||||
return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));
|
||||
return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -193,6 +212,7 @@ module.exports = {
|
|||
formatOutputHash: formatOutputHash,
|
||||
formatOutputBool: formatOutputBool,
|
||||
formatOutputString: formatOutputString,
|
||||
formatOutputAddress: formatOutputAddress
|
||||
formatOutputAddress: formatOutputAddress,
|
||||
SolidityInputParam: SolidityInputParam
|
||||
};
|
||||
|
||||
|
|
|
@ -20,7 +20,10 @@
|
|||
* @date 2015
|
||||
*/
|
||||
|
||||
var BigNumber = require('bignumber.js');
|
||||
var utils = require('../utils/utils');
|
||||
var f = require('./formatters');
|
||||
var SolidityInputParam = f.SolidityInputParam;
|
||||
|
||||
/// @param expected type prefix (string)
|
||||
/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false
|
||||
|
@ -38,21 +41,6 @@ var namedType = function (name) {
|
|||
};
|
||||
};
|
||||
|
||||
/// Setups input formatters for solidity types
|
||||
/// @returns an array of input formatters
|
||||
var inputTypes = function () {
|
||||
|
||||
return [
|
||||
{ type: prefixedType('uint'), format: f.formatInputInt },
|
||||
{ type: prefixedType('int'), format: f.formatInputInt },
|
||||
{ type: prefixedType('bytes'), format: f.formatInputString },
|
||||
{ type: prefixedType('real'), format: f.formatInputReal },
|
||||
{ type: prefixedType('ureal'), format: f.formatInputReal },
|
||||
{ type: namedType('address'), format: f.formatInputInt },
|
||||
{ type: namedType('bool'), format: f.formatInputBool }
|
||||
];
|
||||
};
|
||||
|
||||
/// Setups output formaters for solidity types
|
||||
/// @returns an array of output formatters
|
||||
var outputTypes = function () {
|
||||
|
@ -68,10 +56,73 @@ var outputTypes = function () {
|
|||
];
|
||||
};
|
||||
|
||||
var SolidityType = function (name, inputFormatter, outputFormatter) {
|
||||
this.name = name;
|
||||
this.inputFormatter = inputFormatter;
|
||||
this.outputFormatter = outputFormatter;
|
||||
};
|
||||
|
||||
SolidityType.prototype.isType = function (name) {
|
||||
return this.name === name || (name.indexOf(this.name) === 0 && name.slice(this.name.length) === '[]');
|
||||
};
|
||||
|
||||
SolidityType.prototype.formatInput = function (param) {
|
||||
if (utils.isArray(param)) {
|
||||
var self = this;
|
||||
return param.map(function (p) {
|
||||
return self.inputFormatter(p);
|
||||
}).reduce(function (acc, current) {
|
||||
acc.suffix += current.value;
|
||||
acc.prefix += current.prefix;
|
||||
// TODO: suffix not supported = it's required for nested arrays;
|
||||
return acc;
|
||||
}, new SolidityInputParam('', f.formatInputInt(param.length).value));
|
||||
}
|
||||
return this.inputFormatter(param);
|
||||
};
|
||||
|
||||
var SolidityPrefixedType = function () {
|
||||
SolidityType.apply(this, arguments);
|
||||
};
|
||||
|
||||
SolidityPrefixedType.prototype = Object.create(SolidityType.prototype);
|
||||
|
||||
SolidityPrefixedType.prototype.isType = function (name) {
|
||||
// TODO better type detection!
|
||||
return name.indexOf(this.name) === 0;
|
||||
};
|
||||
|
||||
var SolidityFormatter = function (types) {
|
||||
this.types = types;
|
||||
};
|
||||
|
||||
SolidityFormatter.prototype.formatInput = function (type, param) {
|
||||
var solidityType = this.types.filter(function (t) {
|
||||
return t.isType(type);
|
||||
})[0];
|
||||
|
||||
if (!solidityType) {
|
||||
throw Error('invalid solidity type!: ' + type);
|
||||
}
|
||||
|
||||
return solidityType.formatInput(param);
|
||||
};
|
||||
|
||||
var sf = new SolidityFormatter([
|
||||
new SolidityType('address', f.formatInputInt),
|
||||
new SolidityType('bool', f.formatInputBool),
|
||||
new SolidityPrefixedType('int', f.formatInputInt),
|
||||
new SolidityPrefixedType('uint', f.formatInputInt),
|
||||
new SolidityPrefixedType('bytes', f.formatInputString),
|
||||
new SolidityPrefixedType('real', f.formatInputReal),
|
||||
new SolidityPrefixedType('ureal', f.formatInputReal)
|
||||
]);
|
||||
|
||||
module.exports = {
|
||||
sf: sf,
|
||||
prefixedType: prefixedType,
|
||||
namedType: namedType,
|
||||
inputTypes: inputTypes,
|
||||
//inputTypes: inputTypes,
|
||||
outputTypes: outputTypes
|
||||
};
|
||||
|
||||
|
|
|
@ -469,10 +469,10 @@ describe('lib/solidity/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");
|
||||
|
||||
});
|
||||
|
||||
|
@ -489,9 +489,9 @@ describe('lib/solidity/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");
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ describe('lib/web3/event', function () {
|
|||
assert.equal(result.address, address);
|
||||
assert.equal(result.topics.length, 2);
|
||||
assert.equal(result.topics[0], signature);
|
||||
assert.equal(result.topics[1], '0x' + f.formatInputInt(4));
|
||||
assert.equal(result.topics[1], '0x' + f.formatInputInt(4).encode());
|
||||
assert.equal(result.fromBlock, options.fromBlock);
|
||||
assert.equal(result.toBlock, options.toBlock);
|
||||
|
||||
|
@ -102,8 +102,8 @@ describe('lib/web3/event', function () {
|
|||
assert.equal(result.address, address);
|
||||
assert.equal(result.topics.length, 2);
|
||||
assert.equal(result.topics[0], signature);
|
||||
assert.equal(result.topics[1][0], f.formatInputInt(4));
|
||||
assert.equal(result.topics[1][1], f.formatInputInt(69));
|
||||
assert.equal(result.topics[1][0], f.formatInputInt(4).encode());
|
||||
assert.equal(result.topics[1][1], f.formatInputInt(69).encode());
|
||||
assert.equal(result.fromBlock, options.fromBlock);
|
||||
assert.equal(result.toBlock, options.toBlock);
|
||||
|
||||
|
|
Loading…
Reference in New Issue