var Decimal = require("decimal.js"); var config = require("./config.js"); var coins = require("./coins.js"); var coinConfig = coins[config.coin]; function redirectToConnectPageIfNeeded(req, res) { if (!req.session.host) { req.session.redirectUrl = req.originalUrl; res.redirect("/"); res.end(); return true; } return false; } function hex2ascii(hex) { var str = ""; for (var i = 0; i < hex.length; i += 2) { str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); } return str; } function splitArrayIntoChunks(array, chunkSize) { var j = array.length; var chunks = []; for (var i = 0; i < j; i += chunkSize) { chunks.push(array.slice(i, i + chunkSize)); } return chunks; } function getRandomString(length, chars) { var mask = ''; if (chars.indexOf('a') > -1) { mask += 'abcdefghijklmnopqrstuvwxyz'; } if (chars.indexOf('A') > -1) { mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; } if (chars.indexOf('#') > -1) { mask += '0123456789'; } if (chars.indexOf('!') > -1) { mask += '~`!@#$%^&*()_+-={}[]:";\'<>?,./|\\'; } var result = ''; for (var i = length; i > 0; --i) { result += mask[Math.floor(Math.random() * mask.length)]; } return result; } function formatBytes(bytesInt) { var scales = [ {val:1000000000000000, name:"PB"}, {val:1000000000000, name:"TB"}, {val:1000000000, name:"GB"}, {val:1000000, name:"MB"}, {val:1000, name:"KB"} ]; for (var i = 0; i < scales.length; i++) { var item = scales[i]; var fraction = Math.floor(bytesInt / item.val); if (fraction >= 1) { return fraction.toLocaleString() + " " + item.name; } } return Math.floor(bytesInt) + " B"; } var formatCurrencyCache = {}; function formatCurrencyAmount(amount, formatType) { if (formatCurrencyCache[formatType]) { var dec = new Decimal(amount); dec = dec.times(formatCurrencyCache[formatType].multiplier); var decimalPlaces = formatCurrencyCache[formatType].decimalPlaces; if (decimalPlaces == 0 && dec < 1) { decimalPlaces = 5; } return addThousandsSeparators(dec.toDecimalPlaces(decimalPlaces)) + " " + formatCurrencyCache[formatType].name; } for (var x = 0; x < coins[config.coin].currencyUnits.length; x++) { var currencyUnit = coins[config.coin].currencyUnits[x]; for (var y = 0; y < currencyUnit.values.length; y++) { var currencyUnitValue = currencyUnit.values[y]; if (currencyUnitValue == formatType) { formatCurrencyCache[formatType] = currencyUnit; var dec = new Decimal(amount); dec = dec.times(currencyUnit.multiplier); var decimalPlaces = currencyUnit.decimalPlaces; if (decimalPlaces == 0 && dec < 1) { decimalPlaces = 5; } return addThousandsSeparators(dec.toDecimalPlaces(decimalPlaces)) + " " + currencyUnit.name; } } } return amount; } function formatCurrencyAmountInSmallestUnits(amount) { return formatCurrencyAmount(amount, coins[config.coin].currencyUnits[coins[config.coin].currencyUnits.length - 1].name); } // ref: https://stackoverflow.com/a/2901298/673828 function addThousandsSeparators(x) { var parts = x.toString().split("."); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); return parts.join("."); } function formatExchangedCurrency(amount) { if (global.exchangeRate != null) { var dec = new Decimal(amount); dec = dec.times(global.exchangeRate); return addThousandsSeparators(dec.toDecimalPlaces(2)) + " " + coins[config.coin].exchangeRateData.exchangedCurrencyName; } return ""; } function seededRandom(seed) { var x = Math.sin(seed++) * 10000; return x - Math.floor(x); } function seededRandomIntBetween(seed, min, max) { var rand = seededRandom(seed); return (min + (max - min) * rand); } function logMemoryUsage() { var mbUsed = process.memoryUsage().heapUsed / 1024 / 1024; mbUsed = Math.round(mbUsed * 100) / 100; var mbTotal = process.memoryUsage().heapTotal / 1024 / 1024; mbTotal = Math.round(mbTotal * 100) / 100; console.log("memoryUsage: heapUsed=" + mbUsed + ", heapTotal=" + mbTotal + ", ratio=" + parseInt(mbUsed / mbTotal * 100)); } function getMinerFromCoinbaseTx(tx) { if (tx == null || tx.vin == null || tx.vin.length == 0) { return null; } if (global.miningPoolsConfig) { for (var payoutAddress in global.miningPoolsConfig.payout_addresses) { if (global.miningPoolsConfig.payout_addresses.hasOwnProperty(payoutAddress)) { if (tx.vout && tx.vout.length > 0 && tx.vout[0].scriptPubKey && tx.vout[0].scriptPubKey.addresses && tx.vout[0].scriptPubKey.addresses.length > 0) { if (tx.vout[0].scriptPubKey.addresses[0] == payoutAddress) { var minerInfo = global.miningPoolsConfig.payout_addresses[payoutAddress]; minerInfo.identifiedBy = "payout address " + payoutAddress; return minerInfo; } } } } for (var coinbaseTag in global.miningPoolsConfig.coinbase_tags) { if (global.miningPoolsConfig.coinbase_tags.hasOwnProperty(coinbaseTag)) { if (hex2ascii(tx.vin[0].coinbase).indexOf(coinbaseTag) != -1) { var minerInfo = global.miningPoolsConfig.coinbase_tags[coinbaseTag]; minerInfo.identifiedBy = "coinbase tag '" + coinbaseTag + "'"; return minerInfo; } } } } return null; } function getBlockTotalFeesFromCoinbaseTxAndBlockHeight(coinbaseTx, blockHeight) { if (coinbaseTx == null) { return 0; } var blockReward = coinConfig.blockRewardFunction(blockHeight); var totalOutput = coinbaseTx.vout[0].value; return new Decimal(totalOutput).minus(new Decimal(blockReward)); } module.exports = { redirectToConnectPageIfNeeded: redirectToConnectPageIfNeeded, hex2ascii: hex2ascii, splitArrayIntoChunks: splitArrayIntoChunks, getRandomString: getRandomString, formatBytes: formatBytes, formatCurrencyAmount: formatCurrencyAmount, formatExchangedCurrency: formatExchangedCurrency, addThousandsSeparators: addThousandsSeparators, formatCurrencyAmountInSmallestUnits: formatCurrencyAmountInSmallestUnits, seededRandom: seededRandom, seededRandomIntBetween: seededRandomIntBetween, logMemoryUsage: logMemoryUsage, getMinerFromCoinbaseTx: getMinerFromCoinbaseTx, getBlockTotalFeesFromCoinbaseTxAndBlockHeight: getBlockTotalFeesFromCoinbaseTxAndBlockHeight };