|
|
@ -55,56 +55,52 @@ var padLeft = function (string, chars) { |
|
|
|
return new Array(chars - string.length + 1).join("0") + string; |
|
|
|
return new Array(chars - string.length + 1).join("0") + string; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Setups input formatters for solidity types
|
|
|
|
|
|
|
|
/// @returns an array of input formatters
|
|
|
|
var setupInputTypes = function () { |
|
|
|
var setupInputTypes = function () { |
|
|
|
|
|
|
|
|
|
|
|
var prefixedType = function (prefix) { |
|
|
|
var prefixedType = function (prefix) { |
|
|
|
return function (type, value) { |
|
|
|
return function (type, value) { |
|
|
|
var expected = prefix; |
|
|
|
return type.indexOf(prefix) === 0; |
|
|
|
if (type.indexOf(expected) !== 0) { |
|
|
|
}; |
|
|
|
return false; |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var padding = 32; // override as per the new ABI.
|
|
|
|
var namedType = function (name, formatter) { |
|
|
|
|
|
|
|
return function (type, value) { |
|
|
|
|
|
|
|
return type === name; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
if (prefix === "string") |
|
|
|
var formatInt = function (value) { |
|
|
|
return web3.fromAscii(value, padding).substr(2); |
|
|
|
var padding = 32 * 2; |
|
|
|
if (typeof value === "number") |
|
|
|
if (typeof value === 'number') |
|
|
|
value = value.toString(16); |
|
|
|
value = value.toString(16); |
|
|
|
else if (typeof value === "string") |
|
|
|
|
|
|
|
value = web3.toHex(value);
|
|
|
|
|
|
|
|
else if (value.indexOf('0x') === 0) |
|
|
|
else if (value.indexOf('0x') === 0) |
|
|
|
value = value.substr(2); |
|
|
|
value = value.substr(2); |
|
|
|
|
|
|
|
else if (typeof value === 'string') |
|
|
|
|
|
|
|
value = value.toHex(value); |
|
|
|
else |
|
|
|
else |
|
|
|
value = (+value).toString(16); |
|
|
|
value = (+value).toString(16); |
|
|
|
return padLeft(value, padding * 2); |
|
|
|
return padLeft(value, padding); |
|
|
|
}; |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var namedType = function (name, formatter) { |
|
|
|
var formatString = function (value) { |
|
|
|
return function (type, value) { |
|
|
|
return web3.fromAscii(value, 32).substr(2); |
|
|
|
if (type !== name) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var padding = 32; //override as per the new ABI.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return padLeft(formatter ? formatter(value) : value, padding * 2); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var formatBool = function (value) { |
|
|
|
var formatBool = function (value) { |
|
|
|
return value ? '0x1' : '0x0'; |
|
|
|
return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0'); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
return [ |
|
|
|
return [ |
|
|
|
prefixedType('uint'), |
|
|
|
{ type: prefixedType('uint'), format: formatInt }, |
|
|
|
prefixedType('int'), |
|
|
|
{ type: prefixedType('int'), format: formatInt }, |
|
|
|
prefixedType('hash'), |
|
|
|
{ type: prefixedType('hash'), format: formatInt }, |
|
|
|
prefixedType('string'), |
|
|
|
{ type: prefixedType('string'), format: formatString },
|
|
|
|
prefixedType('real'), |
|
|
|
{ type: prefixedType('real'), format: formatInt }, |
|
|
|
prefixedType('ureal'), |
|
|
|
{ type: prefixedType('ureal'), format: formatInt }, |
|
|
|
namedType('address'), |
|
|
|
{ type: namedType('address') }, |
|
|
|
namedType('bool', formatBool), |
|
|
|
{ type: namedType('bool'), format: formatBool } |
|
|
|
]; |
|
|
|
]; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -119,65 +115,73 @@ var toAbiInput = function (json, methodName, params) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var method = json[index]; |
|
|
|
var method = json[index]; |
|
|
|
|
|
|
|
var padding = 32 * 2; |
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < method.inputs.length; i++) { |
|
|
|
for (var i = 0; i < method.inputs.length; i++) { |
|
|
|
var found = false; |
|
|
|
var typeMatch = false; |
|
|
|
for (var j = 0; j < inputTypes.length && !found; j++) { |
|
|
|
for (var j = 0; j < inputTypes.length && !typeMatch; j++) { |
|
|
|
found = inputTypes[j](method.inputs[i].type, params[i]); |
|
|
|
typeMatch = inputTypes[j].type(method.inputs[i].type, params[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!found) { |
|
|
|
if (!typeMatch) { |
|
|
|
console.error('unsupported json type: ' + method.inputs[i].type); |
|
|
|
console.error('input parser does not support type: ' + method.inputs[i].type); |
|
|
|
} |
|
|
|
} |
|
|
|
bytes += found; |
|
|
|
|
|
|
|
|
|
|
|
var formatter = inputTypes[j - 1].format; |
|
|
|
|
|
|
|
bytes += (formatter ? formatter(params[i]) : params[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
return bytes; |
|
|
|
return bytes; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Setups output formaters for solidity types
|
|
|
|
|
|
|
|
/// @returns an array of output formatters
|
|
|
|
var setupOutputTypes = function () { |
|
|
|
var setupOutputTypes = function () { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @param expected type prefix (string)
|
|
|
|
|
|
|
|
/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false
|
|
|
|
var prefixedType = function (prefix) { |
|
|
|
var prefixedType = function (prefix) { |
|
|
|
return function (type) { |
|
|
|
return function (type) { |
|
|
|
var expected = prefix; |
|
|
|
var expected = prefix; |
|
|
|
if (type.indexOf(expected) !== 0) { |
|
|
|
return type.indexOf(expected) === 0; |
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var padding = 32; // override as per the new ABI.
|
|
|
|
|
|
|
|
return padding * 2; |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @param expected type name (string)
|
|
|
|
|
|
|
|
/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false
|
|
|
|
var namedType = function (name) { |
|
|
|
var namedType = function (name) { |
|
|
|
return function (type) { |
|
|
|
return function (type) { |
|
|
|
var padding = 32; // override as per the new ABI.
|
|
|
|
return name === type; |
|
|
|
return name === type ? padding * 2 : -1; |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @returns input bytes formatted to int
|
|
|
|
var formatInt = function (value) { |
|
|
|
var formatInt = function (value) { |
|
|
|
return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value); |
|
|
|
return value.length <= 8 ? +parseInt(value, 16) : hexToDec(value); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @returns input bytes formatted to hex
|
|
|
|
var formatHash = function (value) { |
|
|
|
var formatHash = function (value) { |
|
|
|
return "0x" + value; |
|
|
|
return "0x" + value; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @returns input bytes formatted to bool
|
|
|
|
var formatBool = function (value) { |
|
|
|
var formatBool = function (value) { |
|
|
|
return value === '1' ? true : false; |
|
|
|
return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @returns input bytes formatted to ascii string
|
|
|
|
var formatString = function (value) { |
|
|
|
var formatString = function (value) { |
|
|
|
return web3.toAscii(value); |
|
|
|
return web3.toAscii(value); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
return [ |
|
|
|
return [ |
|
|
|
{ padding: prefixedType('uint'), format: formatInt }, |
|
|
|
{ type: prefixedType('uint'), format: formatInt }, |
|
|
|
{ padding: prefixedType('int'), format: formatInt }, |
|
|
|
{ type: prefixedType('int'), format: formatInt }, |
|
|
|
{ padding: prefixedType('hash'), format: formatHash }, |
|
|
|
{ type: prefixedType('hash'), format: formatHash }, |
|
|
|
{ padding: prefixedType('string'), format: formatString }, |
|
|
|
{ type: prefixedType('string'), format: formatString }, |
|
|
|
{ padding: prefixedType('real'), format: formatInt }, |
|
|
|
{ type: prefixedType('real'), format: formatInt }, |
|
|
|
{ padding: prefixedType('ureal'), format: formatInt }, |
|
|
|
{ type: prefixedType('ureal'), format: formatInt }, |
|
|
|
{ padding: namedType('address') }, |
|
|
|
{ type: namedType('address') }, |
|
|
|
{ padding: namedType('bool'), format: formatBool } |
|
|
|
{ type: namedType('bool'), format: formatBool } |
|
|
|
]; |
|
|
|
]; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -194,14 +198,16 @@ var fromAbiOutput = function (json, methodName, output) { |
|
|
|
|
|
|
|
|
|
|
|
var result = []; |
|
|
|
var result = []; |
|
|
|
var method = json[index]; |
|
|
|
var method = json[index]; |
|
|
|
|
|
|
|
var padding = 32 * 2; |
|
|
|
for (var i = 0; i < method.outputs.length; i++) { |
|
|
|
for (var i = 0; i < method.outputs.length; i++) { |
|
|
|
var padding = -1; |
|
|
|
var typeMatch = false; |
|
|
|
for (var j = 0; j < outputTypes.length && padding === -1; j++) { |
|
|
|
for (var j = 0; j < outputTypes.length && !typeMatch; j++) { |
|
|
|
padding = outputTypes[j].padding(method.outputs[i].type); |
|
|
|
typeMatch = outputTypes[j].type(method.outputs[i].type); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (padding === -1) { |
|
|
|
if (!typeMatch) { |
|
|
|
// not found output parsing
|
|
|
|
// not found output parsing
|
|
|
|
|
|
|
|
console.error('output parser does not support type: ' + method.outputs[i].type); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
var res = output.slice(0, padding); |
|
|
|
var res = output.slice(0, padding); |
|
|
@ -213,6 +219,8 @@ var fromAbiOutput = function (json, methodName, output) { |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @param json abi for contract
|
|
|
|
|
|
|
|
/// @returns input parser object for given json abi
|
|
|
|
var inputParser = function (json) { |
|
|
|
var inputParser = function (json) { |
|
|
|
var parser = {}; |
|
|
|
var parser = {}; |
|
|
|
json.forEach(function (method) { |
|
|
|
json.forEach(function (method) { |
|
|
@ -225,6 +233,8 @@ var inputParser = function (json) { |
|
|
|
return parser; |
|
|
|
return parser; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @param json abi for contract
|
|
|
|
|
|
|
|
/// @returns output parser for given json abi
|
|
|
|
var outputParser = function (json) { |
|
|
|
var outputParser = function (json) { |
|
|
|
var parser = {}; |
|
|
|
var parser = {}; |
|
|
|
json.forEach(function (method) { |
|
|
|
json.forEach(function (method) { |
|
|
@ -236,6 +246,9 @@ var outputParser = function (json) { |
|
|
|
return parser; |
|
|
|
return parser; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @param json abi for contract
|
|
|
|
|
|
|
|
/// @param method name for which we want to get method signature
|
|
|
|
|
|
|
|
/// @returns (promise) contract method signature for method with given name
|
|
|
|
var methodSignature = function (json, name) { |
|
|
|
var methodSignature = function (json, name) { |
|
|
|
var method = json[findMethodIndex(json, name)]; |
|
|
|
var method = json[findMethodIndex(json, name)]; |
|
|
|
var result = name + '('; |
|
|
|
var result = name + '('; |
|
|
|