'use strict'; var bitcore = require('bitcore-lib'); var BufferUtil = bitcore.util.buffer; var MAX_SAFE_INTEGER = 0x1fffffffffffff; // 2 ^ 53 - 1 var crypto = require('crypto'); var _ = require('lodash'); var constants = require('./constants'); var utils = {}; utils.isHash = function(value) { return typeof value === 'string' && value.length === 64 && /^[0-9a-fA-F]+$/.test(value); }; utils.isSafeNatural = function(value) { return typeof value === 'number' && isFinite(value) && Math.floor(value) === value && value >= 0 && value <= MAX_SAFE_INTEGER; }; utils.startAtZero = function(obj, key) { if (!obj.hasOwnProperty(key)) { obj[key] = 0; } }; utils.isAbsolutePath = require('path').isAbsolute; if (!utils.isAbsolutePath) { utils.isAbsolutePath = require('path-is-absolute'); } utils.parseParamsWithJSON = function(paramsArg) { var params = paramsArg.map(function(paramArg) { var param; try { param = JSON.parse(paramArg); } catch(err) { param = paramArg; } return param; }); return params; }; utils.getTerminalKey = function(startKey) { var endKey = Buffer.from(startKey); endKey.writeUInt8(startKey.readUInt8(startKey.length - 1) + 1, startKey.length - 1); return endKey; }; utils.diffTime = function(time) { var diff = process.hrtime(time); return (diff[0] * 1E9 + diff[1])/(1E9 * 1.0); }; utils.reverseBufferToString = function(buf) { if (_.isString(buf)) { buf = new Buffer(buf, 'hex'); } return BufferUtil.reverse(buf).toString('hex'); }; utils.getAddressString = function(opts) { if (!opts.item) { return; } // TODO: this does not handle P2PK correctly, it uses the address and not the // pubkey if (opts.address) { return address.toString(); } }; utils.sendError = function(err, res) { if (err.statusCode) { res.status(err.statusCode).send(err.message); } else { console.error(err.stack); res.status(503).send(err.message); } }; utils.getWalletId = exports.generateJobId = function() { return crypto.randomBytes(16).toString('hex'); }; utils.getWalletId = exports.generateJobId = function() { return crypto.randomBytes(16).toString('hex'); }; utils.toJSONL = function(obj) { var str = JSON.stringify(obj); str = str.replace(/\n/g, ''); return str + '\n'; }; utils.normalizeTimeStamp = function(addressArg) { var addresses = [addressArg]; if (Array.isArray(addressArg)) { addresses = addressArg; } return addresses; }; utils.normalizeTimeStamp = function(value) { if (value > 0xffffffff) { value = Math.round(value/1000); } return value; }; utils.delimitedStringParse = function(delim, str) { function tryJSONparse(str) { try { return JSON.parse(str); } catch(e) { return false; } } var ret = []; if (delim === null) { return tryJSONparse(str); } var list = str.split(delim); for(var i = 0; i < list.length; i++) { ret.push(tryJSONparse(list[i])); } ret = _.compact(ret); return ret.length === 0 ? false : ret; }; utils.toIntIfNumberLike = function(a) { if (!/[^\d]+/.test(a)) { return parseInt(a); } return a; }; utils.getBlockInfoString = function(tip, best) { var diff = best - tip; var astr = diff + ' blocks behind.'; if (diff === -1) { astr = Math.abs(diff) + ' block ahead. Peer may be syncing or we may need to reorganize our chain after new blocks arrive.'; } else if (diff < 1) { astr = Math.abs(diff) + ' blocks ahead. Peer may be syncing or we may need to reorganize our chain after new blocks arrive.'; } else if (diff === 1) { astr = diff + ' block behind.'; } }; utils.joinListsOnIndex = function(indexList, list1, list2, direction) { var newChains = []; indexList.forEach(function(index) { var otherList = list2[index]; if (direction && direction === 'reverse') { newChains.push(otherList.concat(list1)); } else { newChains.push(list1.concat(otherList)); } }); return newChains; }; utils.removeItemsByIndexList = function(indexList, list) { var ret = []; for(var i = 0; i < list.length; i++) { var item = list[i]; if (indexList.indexOf(i) === -1) { ret.push(item); } } return ret; }; utils.encodeTip = function(tip, name) { var key = Buffer.concat([ constants.DB_PREFIX, new Buffer('tip-' + name, 'utf8') ]); var heightBuf = new Buffer(4); heightBuf.writeUInt32BE(tip.height); var value = Buffer.concat([ heightBuf, new Buffer(tip.hash, 'hex') ]); return { key: key, value: value }; }; utils.isHeight = function(blockArg) { return _.isNumber(blockArg) || (blockArg.length < 40 && /^[0-9]+$/.test(blockArg)) }; utils.SimpleMap = function SimpleMap() { var object = {}; var array = []; this.size = 0; this.length = 0; this.get = function (key) { return array[object[key]]; }; this.set = function (key, value) { object[key] = array.length; array.push(value); this.size = array.length; this.length = array.length; }; this.getIndex = function (index) { return array[index]; }; this.getLastIndex = function () { return array[array.length - 1]; }; }; module.exports = utils;