Beta 7 with some repo names changed.

This commit is contained in:
Luis Fernando Molina committed 2020-11-15 13:05:19 +01:00
1 parent 0f7b40cca7
commit 963c19493a
3408 files changed
+462217 -15516

No files matched your search

+442
View File
@@ -0,0 +1,442 @@
/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file utils.js
* @author Marek Kotewicz <marek@parity.io>
* @author Fabian Vogelsteller <fabian@ethereum.org>
* @date 2017
*/
var _ = require('underscore');
var ethjsUnit = require('ethjs-unit');
var utils = require('./utils.js');
var soliditySha3 = require('./soliditySha3.js');
var randombytes = require('randombytes');
var BN = require('bn.js');
/**
* Fires an error in an event emitter and callback and returns the eventemitter
*
* @method _fireError
* @param {Object} error a string, a error, or an object with {message, data}
* @param {Object} emitter
* @param {Function} reject
* @param {Function} callback
* @param {any} optionalData
* @return {Object} the emitter
*/
var _fireError = function (error, emitter, reject, callback, optionalData) {
/*jshint maxcomplexity: 10 */
// add data if given
if(_.isObject(error) && !(error instanceof Error) && error.data) {
if(_.isObject(error.data) || _.isArray(error.data)) {
error.data = JSON.stringify(error.data, null, 2);
}
error = error.message +"\n"+ error.data;
}
if(_.isString(error)) {
error = new Error(error);
}
if (_.isFunction(callback)) {
callback(error, optionalData);
}
if (_.isFunction(reject)) {
// suppress uncatched error if an error listener is present
// OR suppress uncatched error if an callback listener is present
if (
emitter &&
(_.isFunction(emitter.listeners) &&
emitter.listeners('error').length) || _.isFunction(callback)
) {
emitter.catch(function(){});
}
// reject later, to be able to return emitter
setTimeout(function () {
reject(error);
}, 1);
}
if(emitter && _.isFunction(emitter.emit)) {
// emit later, to be able to return emitter
setTimeout(function () {
emitter.emit('error', error, optionalData);
emitter.removeAllListeners();
}, 1);
}
return emitter;
};
/**
* Should be used to create full function/event name from json abi
*
* @method _jsonInterfaceMethodToString
* @param {Object} json
* @return {String} full function/event name
*/
var _jsonInterfaceMethodToString = function (json) {
if (_.isObject(json) && json.name && json.name.indexOf('(') !== -1) {
return json.name;
}
return json.name + '(' + _flattenTypes(false, json.inputs).join(',') + ')';
};
/**
* Should be used to flatten json abi inputs/outputs into an array of type-representing-strings
*
* @method _flattenTypes
* @param {bool} includeTuple
* @param {Object} puts
* @return {Array} parameters as strings
*/
var _flattenTypes = function(includeTuple, puts)
{
// console.log("entered _flattenTypes. inputs/outputs: " + puts)
var types = [];
puts.forEach(function(param) {
if (typeof param.components === 'object') {
if (param.type.substring(0, 5) !== 'tuple') {
throw new Error('components found but type is not tuple; report on GitHub');
}
var suffix = '';
var arrayBracket = param.type.indexOf('[');
if (arrayBracket >= 0) { suffix = param.type.substring(arrayBracket); }
var result = _flattenTypes(includeTuple, param.components);
// console.log("result should have things: " + result)
if(_.isArray(result) && includeTuple) {
// console.log("include tuple word, and its an array. joining...: " + result.types)
types.push('tuple(' + result.join(',') + ')' + suffix);
}
else if(!includeTuple) {
// console.log("don't include tuple, but its an array. joining...: " + result)
types.push('(' + result.join(',') + ')' + suffix);
}
else {
// console.log("its a single type within a tuple: " + result.types)
types.push('(' + result + ')');
}
} else {
// console.log("its a type and not directly in a tuple: " + param.type)
types.push(param.type);
}
});
return types;
};
/**
* Returns a random hex string by the given bytes size
*
* @param {Number} size
* @returns {string}
*/
var randomHex = function(size) {
return '0x' + randombytes(size).toString('hex');
};
/**
* Should be called to get ascii from it's hex representation
*
* @method hexToAscii
* @param {String} hex
* @returns {String} ascii string representation of hex value
*/
var hexToAscii = function(hex) {
if (!utils.isHexStrict(hex))
throw new Error('The parameter must be a valid HEX string.');
var str = "";
var i = 0, l = hex.length;
if (hex.substring(0, 2) === '0x') {
i = 2;
}
for (; i < l; i+=2) {
var code = parseInt(hex.substr(i, 2), 16);
str += String.fromCharCode(code);
}
return str;
};
/**
* Should be called to get hex representation (prefixed by 0x) of ascii string
*
* @method asciiToHex
* @param {String} str
* @returns {String} hex representation of input string
*/
var asciiToHex = function(str) {
if(!str)
return "0x00";
var hex = "";
for(var i = 0; i < str.length; i++) {
var code = str.charCodeAt(i);
var n = code.toString(16);
hex += n.length < 2 ? '0' + n : n;
}
return "0x" + hex;
};
/**
* Returns value of unit in Wei
*
* @method getUnitValue
* @param {String} unit the unit to convert to, default ether
* @returns {BN} value of the unit (in Wei)
* @throws error if the unit is not correct:w
*/
var getUnitValue = function (unit) {
unit = unit ? unit.toLowerCase() : 'ether';
if (!ethjsUnit.unitMap[unit]) {
throw new Error('This unit "'+ unit +'" doesn\'t exist, please use the one of the following units' + JSON.stringify(ethjsUnit.unitMap, null, 2));
}
return unit;
};
/**
* Takes a number of wei and converts it to any other ether unit.
*
* Possible units are:
* SI Short SI Full Effigy Other
* - kwei femtoether babbage
* - mwei picoether lovelace
* - gwei nanoether shannon nano
* - -- microether szabo micro
* - -- milliether finney milli
* - ether -- --
* - kether -- grand
* - mether
* - gether
* - tether
*
* @method fromWei
* @param {Number|String} number can be a number, number string or a HEX of a decimal
* @param {String} unit the unit to convert to, default ether
* @return {String|Object} When given a BN object it returns one as well, otherwise a number
*/
var fromWei = function(number, unit) {
unit = getUnitValue(unit);
if(!utils.isBN(number) && !_.isString(number)) {
throw new Error('Please pass numbers as strings or BN objects to avoid precision errors.');
}
return utils.isBN(number) ? ethjsUnit.fromWei(number, unit) : ethjsUnit.fromWei(number, unit).toString(10);
};
/**
* Takes a number of a unit and converts it to wei.
*
* Possible units are:
* SI Short SI Full Effigy Other
* - kwei femtoether babbage
* - mwei picoether lovelace
* - gwei nanoether shannon nano
* - -- microether szabo micro
* - -- microether szabo micro
* - -- milliether finney milli
* - ether -- --
* - kether -- grand
* - mether
* - gether
* - tether
*
* @method toWei
* @param {Number|String|BN} number can be a number, number string or a HEX of a decimal
* @param {String} unit the unit to convert from, default ether
* @return {String|Object} When given a BN object it returns one as well, otherwise a number
*/
var toWei = function(number, unit) {
unit = getUnitValue(unit);
if(!utils.isBN(number) && !_.isString(number)) {
throw new Error('Please pass numbers as strings or BN objects to avoid precision errors.');
}
return utils.isBN(number) ? ethjsUnit.toWei(number, unit) : ethjsUnit.toWei(number, unit).toString(10);
};
/**
* Converts to a checksum address
*
* @method toChecksumAddress
* @param {String} address the given HEX address
* @return {String}
*/
var toChecksumAddress = function (address) {
if (typeof address === 'undefined') return '';
if(!/^(0x)?[0-9a-f]{40}$/i.test(address))
throw new Error('Given address "'+ address +'" is not a valid Ethereum address.');
address = address.toLowerCase().replace(/^0x/i,'');
var addressHash = utils.sha3(address).replace(/^0x/i,'');
var checksumAddress = '0x';
for (var i = 0; i < address.length; i++ ) {
// If ith character is 8 to f then make it uppercase
if (parseInt(addressHash[i], 16) > 7) {
checksumAddress += address[i].toUpperCase();
} else {
checksumAddress += address[i];
}
}
return checksumAddress;
};
/**
* Returns -1 if a<b, 1 if a>b; 0 if a == b.
* For more details on this type of function, see
* developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
*
* @method compareBlockNumbers
*
* @param {String|Number|BN} a
*
* @param {String|Number|BN} b
*
* @returns {Number} -1, 0, or 1
*/
var compareBlockNumbers = function(a, b) {
if (a == b) {
return 0;
} else if (("genesis" == a || "earliest" == a || 0 == a) && ("genesis" == b || "earliest" == b || 0 == b)) {
return 0;
} else if ("genesis" == a || "earliest" == a) {
// b !== a, thus a < b
return -1;
} else if ("genesis" == b || "earliest" == b) {
// b !== a, thus a > b
return 1;
} else if (a == "latest") {
if (b == "pending") {
return -1;
} else {
// b !== ("pending" OR "latest"), thus a > b
return 1;
}
} else if (b === "latest") {
if (a == "pending") {
return 1;
} else {
// b !== ("pending" OR "latest"), thus a > b
return -1
}
} else if (a == "pending") {
// b (== OR <) "latest", thus a > b
return 1;
} else if (b == "pending") {
return -1;
} else {
let bnA = new BN(a);
let bnB = new BN(b);
if(bnA.lt(bnB)) {
return -1;
} else if(bnA.eq(bnB)) {
return 0;
} else {
return 1;
}
}
};
module.exports = {
_fireError: _fireError,
_jsonInterfaceMethodToString: _jsonInterfaceMethodToString,
_flattenTypes: _flattenTypes,
// extractDisplayName: extractDisplayName,
// extractTypeName: extractTypeName,
randomHex: randomHex,
_: _,
BN: utils.BN,
isBN: utils.isBN,
isBigNumber: utils.isBigNumber,
isHex: utils.isHex,
isHexStrict: utils.isHexStrict,
sha3: utils.sha3,
sha3Raw: utils.sha3Raw,
keccak256: utils.sha3,
soliditySha3: soliditySha3.soliditySha3,
soliditySha3Raw: soliditySha3.soliditySha3Raw,
encodePacked: soliditySha3.encodePacked,
isAddress: utils.isAddress,
checkAddressChecksum: utils.checkAddressChecksum,
toChecksumAddress: toChecksumAddress,
toHex: utils.toHex,
toBN: utils.toBN,
bytesToHex: utils.bytesToHex,
hexToBytes: utils.hexToBytes,
hexToNumberString: utils.hexToNumberString,
hexToNumber: utils.hexToNumber,
toDecimal: utils.hexToNumber, // alias
numberToHex: utils.numberToHex,
fromDecimal: utils.numberToHex, // alias
hexToUtf8: utils.hexToUtf8,
hexToString: utils.hexToUtf8,
toUtf8: utils.hexToUtf8,
utf8ToHex: utils.utf8ToHex,
stringToHex: utils.utf8ToHex,
fromUtf8: utils.utf8ToHex,
hexToAscii: hexToAscii,
toAscii: hexToAscii,
asciiToHex: asciiToHex,
fromAscii: asciiToHex,
unitMap: ethjsUnit.unitMap,
toWei: toWei,
fromWei: fromWei,
padLeft: utils.leftPad,
leftPad: utils.leftPad,
padRight: utils.rightPad,
rightPad: utils.rightPad,
toTwosComplement: utils.toTwosComplement,
isBloom: utils.isBloom,
isUserEthereumAddressInBloom: utils.isUserEthereumAddressInBloom,
isContractAddressInBloom: utils.isContractAddressInBloom,
isTopic: utils.isTopic,
isTopicInBloom: utils.isTopicInBloom,
isInBloom: utils.isInBloom,
compareBlockNumbers: compareBlockNumbers
};
+275
View File
@@ -0,0 +1,275 @@
/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file soliditySha3.js
* @author Fabian Vogelsteller <fabian@ethereum.org>
* @date 2017
*/
var _ = require('underscore');
var BN = require('bn.js');
var utils = require('./utils.js');
var _elementaryName = function (name) {
/*jshint maxcomplexity:false */
if (name.startsWith('int[')) {
return 'int256' + name.slice(3);
} else if (name === 'int') {
return 'int256';
} else if (name.startsWith('uint[')) {
return 'uint256' + name.slice(4);
} else if (name === 'uint') {
return 'uint256';
} else if (name.startsWith('fixed[')) {
return 'fixed128x128' + name.slice(5);
} else if (name === 'fixed') {
return 'fixed128x128';
} else if (name.startsWith('ufixed[')) {
return 'ufixed128x128' + name.slice(6);
} else if (name === 'ufixed') {
return 'ufixed128x128';
}
return name;
};
// Parse N from type<N>
var _parseTypeN = function (type) {
var typesize = /^\D+(\d+).*$/.exec(type);
return typesize ? parseInt(typesize[1], 10) : null;
};
// Parse N from type[<N>]
var _parseTypeNArray = function (type) {
var arraySize = /^\D+\d*\[(\d+)\]$/.exec(type);
return arraySize ? parseInt(arraySize[1], 10) : null;
};
var _parseNumber = function (arg) {
var type = typeof arg;
if (type === 'string') {
if (utils.isHexStrict(arg)) {
return new BN(arg.replace(/0x/i,''), 16);
} else {
return new BN(arg, 10);
}
} else if (type === 'number') {
return new BN(arg);
} else if (utils.isBigNumber(arg)) {
return new BN(arg.toString(10));
} else if (utils.isBN(arg)) {
return arg;
} else {
throw new Error(arg +' is not a number');
}
};
var _solidityPack = function (type, value, arraySize) {
/*jshint maxcomplexity:false */
var size, num;
type = _elementaryName(type);
if (type === 'bytes') {
if (value.replace(/^0x/i,'').length % 2 !== 0) {
throw new Error('Invalid bytes characters '+ value.length);
}
return value;
} else if (type === 'string') {
return utils.utf8ToHex(value);
} else if (type === 'bool') {
return value ? '01' : '00';
} else if (type.startsWith('address')) {
if(arraySize) {
size = 64;
} else {
size = 40;
}
if(!utils.isAddress(value)) {
throw new Error(value +' is not a valid address, or the checksum is invalid.');
}
return utils.leftPad(value.toLowerCase(), size);
}
size = _parseTypeN(type);
if (type.startsWith('bytes')) {
if(!size) {
throw new Error('bytes[] not yet supported in solidity');
}
// must be 32 byte slices when in an array
if(arraySize) {
size = 32;
}
if (size < 1 || size > 32 || size < value.replace(/^0x/i,'').length / 2 ) {
throw new Error('Invalid bytes' + size +' for '+ value);
}
return utils.rightPad(value, size * 2);
} else if (type.startsWith('uint')) {
if ((size % 8) || (size < 8) || (size > 256)) {
throw new Error('Invalid uint'+size+' size');
}
num = _parseNumber(value);
if (num.bitLength() > size) {
throw new Error('Supplied uint exceeds width: ' + size + ' vs ' + num.bitLength());
}
if(num.lt(new BN(0))) {
throw new Error('Supplied uint '+ num.toString() +' is negative');
}
return size ? utils.leftPad(num.toString('hex'), size/8 * 2) : num;
} else if (type.startsWith('int')) {
if ((size % 8) || (size < 8) || (size > 256)) {
throw new Error('Invalid int'+size+' size');
}
num = _parseNumber(value);
if (num.bitLength() > size) {
throw new Error('Supplied int exceeds width: ' + size + ' vs ' + num.bitLength());
}
if(num.lt(new BN(0))) {
return num.toTwos(size).toString('hex');
} else {
return size ? utils.leftPad(num.toString('hex'), size/8 * 2) : num;
}
} else {
// FIXME: support all other types
throw new Error('Unsupported or invalid type: ' + type);
}
};
var _processSolidityEncodePackedArgs = function (arg) {
/*jshint maxcomplexity:false */
if(_.isArray(arg)) {
throw new Error('Autodetection of array types is not supported.');
}
var type, value = '';
var hexArg, arraySize;
// if type is given
if (_.isObject(arg) && (arg.hasOwnProperty('v') || arg.hasOwnProperty('t') || arg.hasOwnProperty('value') || arg.hasOwnProperty('type'))) {
type = arg.hasOwnProperty('t') ? arg.t : arg.type;
value = arg.hasOwnProperty('v') ? arg.v : arg.value;
// otherwise try to guess the type
} else {
type = utils.toHex(arg, true);
value = utils.toHex(arg);
if (!type.startsWith('int') && !type.startsWith('uint')) {
type = 'bytes';
}
}
if ((type.startsWith('int') || type.startsWith('uint')) && typeof value === 'string' && !/^(-)?0x/i.test(value)) {
value = new BN(value);
}
// get the array size
if(_.isArray(value)) {
arraySize = _parseTypeNArray(type);
if(arraySize && value.length !== arraySize) {
throw new Error(type +' is not matching the given array '+ JSON.stringify(value));
} else {
arraySize = value.length;
}
}
if (_.isArray(value)) {
hexArg = value.map(function (val) {
return _solidityPack(type, val, arraySize).toString('hex').replace('0x','');
});
return hexArg.join('');
} else {
hexArg = _solidityPack(type, value, arraySize);
return hexArg.toString('hex').replace('0x','');
}
};
/**
* Hashes solidity values to a sha3 hash using keccak 256
*
* @method soliditySha3
* @return {Object} the sha3
*/
var soliditySha3 = function () {
/*jshint maxcomplexity:false */
var args = Array.prototype.slice.call(arguments);
var hexArgs = _.map(args, _processSolidityEncodePackedArgs);
// console.log(args, hexArgs);
// console.log('0x'+ hexArgs.join(''));
return utils.sha3('0x'+ hexArgs.join(''));
};
/**
* Hashes solidity values to a sha3 hash using keccak 256 but does return the hash of value `null` instead of `null`
*
* @method soliditySha3Raw
* @return {Object} the sha3
*/
var soliditySha3Raw = function () {
return utils.sha3Raw('0x'+ _.map(Array.prototype.slice.call(arguments), _processSolidityEncodePackedArgs).join(''));
};
/**
* Encode packed args to hex
*
* @method encodePacked
* @return {String} the hex encoded arguments
*/
var encodePacked = function () {
/*jshint maxcomplexity:false */
var args = Array.prototype.slice.call(arguments);
var hexArgs = _.map(args, _processSolidityEncodePackedArgs);
return '0x'+ hexArgs.join('').toLowerCase();
};
module.exports = {
soliditySha3: soliditySha3,
soliditySha3Raw: soliditySha3Raw,
encodePacked: encodePacked
};
+542
View File
@@ -0,0 +1,542 @@
/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file utils.js
* @author Fabian Vogelsteller <fabian@ethereum.org>
* @date 2017
*/
var _ = require('underscore');
var BN = require('bn.js');
var numberToBN = require('number-to-bn');
var utf8 = require('utf8');
var Hash = require("eth-lib/lib/hash");
var ethereumBloomFilters = require('ethereum-bloom-filters');
/**
* Returns true if object is BN, otherwise false
*
* @method isBN
* @param {Object} object
* @return {Boolean}
*/
var isBN = function (object) {
return BN.isBN(object);
};
/**
* Returns true if object is BigNumber, otherwise false
*
* @method isBigNumber
* @param {Object} object
* @return {Boolean}
*/
var isBigNumber = function (object) {
return object && object.constructor && object.constructor.name === 'BigNumber';
};
/**
* Takes an input and transforms it into an BN
*
* @method toBN
* @param {Number|String|BN} number, string, HEX string or BN
* @return {BN} BN
*/
var toBN = function(number){
try {
return numberToBN.apply(null, arguments);
} catch(e) {
throw new Error(e + ' Given value: "'+ number +'"');
}
};
/**
* Takes and input transforms it into BN and if it is negative value, into two's complement
*
* @method toTwosComplement
* @param {Number|String|BN} number
* @return {String}
*/
var toTwosComplement = function (number) {
return '0x'+ toBN(number).toTwos(256).toString(16, 64);
};
/**
* Checks if the given string is an address
*
* @method isAddress
* @param {String} address the given HEX address
* @return {Boolean}
*/
var isAddress = function (address) {
// check if it has the basic requirements of an address
if (!/^(0x)?[0-9a-f]{40}$/i.test(address)) {
return false;
// If it's ALL lowercase or ALL upppercase
} else if (/^(0x|0X)?[0-9a-f]{40}$/.test(address) || /^(0x|0X)?[0-9A-F]{40}$/.test(address)) {
return true;
// Otherwise check each case
} else {
return checkAddressChecksum(address);
}
};
/**
* Checks if the given string is a checksummed address
*
* @method checkAddressChecksum
* @param {String} address the given HEX address
* @return {Boolean}
*/
var checkAddressChecksum = function (address) {
// Check each case
address = address.replace(/^0x/i,'');
var addressHash = sha3(address.toLowerCase()).replace(/^0x/i,'');
for (var i = 0; i < 40; i++ ) {
// the nth letter should be uppercase if the nth digit of casemap is 1
if ((parseInt(addressHash[i], 16) > 7 && address[i].toUpperCase() !== address[i]) || (parseInt(addressHash[i], 16) <= 7 && address[i].toLowerCase() !== address[i])) {
return false;
}
}
return true;
};
/**
* Should be called to pad string to expected length
*
* @method leftPad
* @param {String} string to be padded
* @param {Number} chars that result string should have
* @param {String} sign, by default 0
* @returns {String} right aligned string
*/
var leftPad = function (string, chars, sign) {
var hasPrefix = /^0x/i.test(string) || typeof string === 'number';
string = string.toString(16).replace(/^0x/i,'');
var padding = (chars - string.length + 1 >= 0) ? chars - string.length + 1 : 0;
return (hasPrefix ? '0x' : '') + new Array(padding).join(sign ? sign : "0") + string;
};
/**
* Should be called to pad string to expected length
*
* @method rightPad
* @param {String} string to be padded
* @param {Number} chars that result string should have
* @param {String} sign, by default 0
* @returns {String} right aligned string
*/
var rightPad = function (string, chars, sign) {
var hasPrefix = /^0x/i.test(string) || typeof string === 'number';
string = string.toString(16).replace(/^0x/i,'');
var padding = (chars - string.length + 1 >= 0) ? chars - string.length + 1 : 0;
return (hasPrefix ? '0x' : '') + string + (new Array(padding).join(sign ? sign : "0"));
};
/**
* Should be called to get hex representation (prefixed by 0x) of utf8 string
*
* @method utf8ToHex
* @param {String} str
* @returns {String} hex representation of input string
*/
var utf8ToHex = function(str) {
str = utf8.encode(str);
var hex = "";
// remove \u0000 padding from either side
str = str.replace(/^(?:\u0000)*/,'');
str = str.split("").reverse().join("");
str = str.replace(/^(?:\u0000)*/,'');
str = str.split("").reverse().join("");
for(var i = 0; i < str.length; i++) {
var code = str.charCodeAt(i);
// if (code !== 0) {
var n = code.toString(16);
hex += n.length < 2 ? '0' + n : n;
// }
}
return "0x" + hex;
};
/**
* Should be called to get utf8 from it's hex representation
*
* @method hexToUtf8
* @param {String} hex
* @returns {String} ascii string representation of hex value
*/
var hexToUtf8 = function(hex) {
if (!isHexStrict(hex))
throw new Error('The parameter "'+ hex +'" must be a valid HEX string.');
var str = "";
var code = 0;
hex = hex.replace(/^0x/i,'');
// remove 00 padding from either side
hex = hex.replace(/^(?:00)*/,'');
hex = hex.split("").reverse().join("");
hex = hex.replace(/^(?:00)*/,'');
hex = hex.split("").reverse().join("");
var l = hex.length;
for (var i=0; i < l; i+=2) {
code = parseInt(hex.substr(i, 2), 16);
// if (code !== 0) {
str += String.fromCharCode(code);
// }
}
return utf8.decode(str);
};
/**
* Converts value to it's number representation
*
* @method hexToNumber
* @param {String|Number|BN} value
* @return {String}
*/
var hexToNumber = function (value) {
if (!value) {
return value;
}
if (_.isString(value) && !isHexStrict(value)) {
throw new Error('Given value "'+value+'" is not a valid hex string.');
}
return toBN(value).toNumber();
};
/**
* Converts value to it's decimal representation in string
*
* @method hexToNumberString
* @param {String|Number|BN} value
* @return {String}
*/
var hexToNumberString = function (value) {
if (!value) return value;
if (_.isString(value) && !isHexStrict(value)) {
throw new Error('Given value "'+value+'" is not a valid hex string.');
}
return toBN(value).toString(10);
};
/**
* Converts value to it's hex representation
*
* @method numberToHex
* @param {String|Number|BN} value
* @return {String}
*/
var numberToHex = function (value) {
if (_.isNull(value) || _.isUndefined(value)) {
return value;
}
if (!isFinite(value) && !isHexStrict(value)) {
throw new Error('Given input "'+value+'" is not a number.');
}
var number = toBN(value);
var result = number.toString(16);
return number.lt(new BN(0)) ? '-0x' + result.substr(1) : '0x' + result;
};
/**
* Convert a byte array to a hex string
*
* Note: Implementation from crypto-js
*
* @method bytesToHex
* @param {Array} bytes
* @return {String} the hex string
*/
var bytesToHex = function(bytes) {
for (var hex = [], i = 0; i < bytes.length; i++) {
/* jshint ignore:start */
hex.push((bytes[i] >>> 4).toString(16));
hex.push((bytes[i] & 0xF).toString(16));
/* jshint ignore:end */
}
return '0x'+ hex.join("");
};
/**
* Convert a hex string to a byte array
*
* Note: Implementation from crypto-js
*
* @method hexToBytes
* @param {string} hex
* @return {Array} the byte array
*/
var hexToBytes = function(hex) {
hex = hex.toString(16);
if (!isHexStrict(hex)) {
throw new Error('Given value "'+ hex +'" is not a valid hex string.');
}
hex = hex.replace(/^0x/i,'');
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
};
/**
* Auto converts any given value into it's hex representation.
*
* And even stringifys objects before.
*
* @method toHex
* @param {String|Number|BN|Object|Buffer} value
* @param {Boolean} returnType
* @return {String}
*/
var toHex = function (value, returnType) {
/*jshint maxcomplexity: false */
if (isAddress(value)) {
return returnType ? 'address' : '0x'+ value.toLowerCase().replace(/^0x/i,'');
}
if (_.isBoolean(value)) {
return returnType ? 'bool' : value ? '0x01' : '0x00';
}
if (Buffer.isBuffer(value)) {
return '0x' + value.toString('hex');
}
if (_.isObject(value) && !isBigNumber(value) && !isBN(value)) {
return returnType ? 'string' : utf8ToHex(JSON.stringify(value));
}
// if its a negative number, pass it through numberToHex
if (_.isString(value)) {
if (value.indexOf('-0x') === 0 || value.indexOf('-0X') === 0) {
return returnType ? 'int256' : numberToHex(value);
} else if(value.indexOf('0x') === 0 || value.indexOf('0X') === 0) {
return returnType ? 'bytes' : value;
} else if (!isFinite(value)) {
return returnType ? 'string' : utf8ToHex(value);
}
}
return returnType ? (value < 0 ? 'int256' : 'uint256') : numberToHex(value);
};
/**
* Check if string is HEX, requires a 0x in front
*
* @method isHexStrict
* @param {String} hex to be checked
* @returns {Boolean}
*/
var isHexStrict = function (hex) {
return ((_.isString(hex) || _.isNumber(hex)) && /^(-)?0x[0-9a-f]*$/i.test(hex));
};
/**
* Check if string is HEX
*
* @method isHex
* @param {String} hex to be checked
* @returns {Boolean}
*/
var isHex = function (hex) {
return ((_.isString(hex) || _.isNumber(hex)) && /^(-0x|0x)?[0-9a-f]*$/i.test(hex));
};
/**
* Returns true if given string is a valid Ethereum block header bloom.
*
* @method isBloom
* @param {String} bloom encoded bloom filter
* @return {Boolean}
*/
var isBloom = function (bloom) {
return ethereumBloomFilters.isBloom(bloom);
};
/**
* Returns true if the ethereum users address is part of the given bloom
* note: false positives are possible.
*
* @method isUserEthereumAddressInBloom
* @param {String} ethereumAddress encoded bloom filter
* @param {String} bloom ethereum addresss
* @return {Boolean}
*/
var isUserEthereumAddressInBloom = function (bloom, ethereumAddress) {
return ethereumBloomFilters.isUserEthereumAddressInBloom(bloom, ethereumAddress);
};
/**
* Returns true if the contract address is part of the given bloom
* note: false positives are possible.
*
* @method isUserEthereumAddressInBloom
* @param {String} bloom encoded bloom filter
* @param {String} contractAddress contract addresss
* @return {Boolean}
*/
var isContractAddressInBloom = function (bloom, contractAddress) {
return ethereumBloomFilters.isContractAddressInBloom(bloom, contractAddress);
};
/**
* Returns true if given string is a valid log topic.
*
* @method isTopic
* @param {String} topic encoded topic
* @return {Boolean}
*/
var isTopic = function (topic) {
return ethereumBloomFilters.isTopic(topic);
};
/**
* Returns true if the topic is part of the given bloom
* note: false positives are possible.
*
* @method isTopicInBloom
* @param {String} bloom encoded bloom filter
* @param {String} topic encoded topic
* @return {Boolean}
*/
var isTopicInBloom = function (bloom, topic) {
return ethereumBloomFilters.isTopicInBloom(bloom, topic);
};
/**
* Returns true if the value is part of the given bloom
* note: false positives are possible.
*
* @method isInBloom
* @param {String} bloom encoded bloom filter
* @param {String | Uint8Array} topic encoded value
* @return {Boolean}
*/
var isInBloom = function (bloom, topic) {
return ethereumBloomFilters.isInBloom(bloom, topic);
};
/**
* Hashes values to a sha3 hash using keccak 256
*
* To hash a HEX string the hex must have 0x in front.
*
* @method sha3
* @return {String} the sha3 string
*/
var SHA3_NULL_S = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470';
var sha3 = function (value) {
if (isBN(value)) {
value = value.toString();
}
if (isHexStrict(value) && /^0x/i.test((value).toString())) {
value = hexToBytes(value);
}
var returnValue = Hash.keccak256(value); // jshint ignore:line
if(returnValue === SHA3_NULL_S) {
return null;
} else {
return returnValue;
}
};
// expose the under the hood keccak256
sha3._Hash = Hash;
/**
* @method sha3Raw
*
* @param value
*
* @returns {string}
*/
var sha3Raw = function(value) {
value = sha3(value);
if (value === null) {
return SHA3_NULL_S;
}
return value;
};
module.exports = {
BN: BN,
isBN: isBN,
isBigNumber: isBigNumber,
toBN: toBN,
isAddress: isAddress,
isBloom: isBloom,
isUserEthereumAddressInBloom: isUserEthereumAddressInBloom,
isContractAddressInBloom: isContractAddressInBloom,
isTopic: isTopic,
isTopicInBloom: isTopicInBloom,
isInBloom: isInBloom,
checkAddressChecksum: checkAddressChecksum,
utf8ToHex: utf8ToHex,
hexToUtf8: hexToUtf8,
hexToNumber: hexToNumber,
hexToNumberString: hexToNumberString,
numberToHex: numberToHex,
toHex: toHex,
hexToBytes: hexToBytes,
bytesToHex: bytesToHex,
isHex: isHex,
isHexStrict: isHexStrict,
leftPad: leftPad,
rightPad: rightPad,
toTwosComplement: toTwosComplement,
sha3: sha3,
sha3Raw: sha3Raw
};