const _ = require('lodash');
const utf8 = require('utf8');
class Utils {
/**
* Parameter check at the beginning of a function
* Throw errors if required keys are missing in params object
* @param {string} methodName Function name used for error message
* @param {object} params params object
* @param {array} required Array of key strings in params, e.g. ['resultNames', 'sender']
* @param {func} validators Custom functions used to validate params
* @return {}
*/
static paramsCheck(methodName, params, required, validators) {
if (_.isUndefined(params)) {
throw new Error(`params is undefined in params of ${methodName} expected: ${_.isEmpty(required)
? undefined : required.join(',')}`);
}
if (required) {
if (_.isArray(required)) {
_.each(required, (value) => {
if (_.isUndefined(params[value])) {
throw new Error(`${value} is undefined in params of ${methodName}`);
}
});
} else if (_.isUndefined(params[required])) {
throw new Error(`${required} is undefined in params of ${methodName}`);
}
}
if (!_.isEmpty(validators)) {
_.each(validators, (validFunc, key) => {
// Check whether each validator is a function
if (typeof validFunc !== 'function') {
throw new Error('validators are defined but not functions ...');
}
// Check whether key defined in validator is in params
if (_.indexOf(params, key) < 0) {
throw new Error(`${key} in validator is not found in params.`);
}
// Run validator funcs and check result
// If result === 'undefined', pass otherwise throw error with message
const error = validFunc(params[key], key);
if (error instanceof Error) {
throw new Error(`validation for ${key} failed message:${error.message}`);
}
});
}
}
/**
* Validate format string and append '0x' to it if there's not one.
* @param {string} value Hex string to format
* @return {string}
*/
static appendHexPrefix(value) {
if (_.startsWith(value, '0x')) {
return value;
}
return `0x${value}`;
}
/**
* Removes the '0x' hex prefix if necessary.
* @param str The string to remove the prefix from.
* @return The str without the hex prefix.
*/
static trimHexPrefix(str) {
if (str && str.indexOf('0x') === 0) {
return str.slice(2);
}
return str;
}
/**
* Breaks down a string by {length} and returns an array of string
* @param {string} Input string
* @param {number} Length of each chunk.
* @return {array} broken-down string array
*/
static chunkString(str, length) {
return str.match(new RegExp(`.{1,${length}}`, 'g'));
}
/**
* Should be called to get utf8 from it's hex representation
*
* @method toUtf8
* @param {String} string in hex
* @returns {String} ascii string representation of hex value
*/
static toUtf8(hex) {
let i = 0;
if (hex.substring(0, 2) === '0x') {
i = 2;
}
let str = '';
for (;i < hex.length; i += 2) {
const code = parseInt(hex.substr(i, 2), 16);
if (code === 0) { break; }
str += String.fromCharCode(code);
}
return utf8.decode(str);
}
/**
* Should be called to get hex representation (prefixed by 0x) of utf8 string
* @method fromUtf8
* @param {String} string
* @param {Number} optional padding
* @returns {String} hex representation of input string
*/
static fromUtf8(str) {
const string = utf8.encode(str);
let hex = '';
for (let i = 0; i < string.length; i++) {
const code = string.charCodeAt(i);
if (code === 0) {
break;
}
const n = code.toString(16);
hex += n.length < 2 ? `0${n}` : n;
}
return `0x${hex}`;
}
/**
* Returns true if given string is valid json object
* @method isJson
* @param {String}
* @return {Boolean}
*/
static isJson(str) {
try {
return !!JSON.parse(str);
} catch (e) {
return false;
}
}
/**
* Returns true if given string is valid ecochain address
* @method isEcoAddress
* @param {String}
* @return {Boolean}
*/
static isEcoAddress(address) {
if (_.isUndefined(address)) {
return false;
}
if (_.size(address) !== 34) {
return false;
}
if (!address.startsWith('e') && !address.startsWith('E')) {
return false;
}
return true;
}
}
module.exports = Utils;