Files
cryptonote-nodejs-pool/lib/utils.js
Codex Bot 999186ab6d
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 53s
Adapt solo pool for current Peya and shared util
2026-03-21 15:08:23 +01:00

271 lines
7.4 KiB
JavaScript

/**
* Cryptonote Node.JS Pool
* https://github.com/dvandal/cryptonote-nodejs-pool
*
* Utilities functions
**/
// Load required module
let crypto = require('crypto');
let dateFormat = require('dateformat');
exports.dateFormat = dateFormat;
let cnUtil = require('cryptoforknote-util');
exports.cnUtil = cnUtil;
require('./configReader.js');
let logSystem = 'pool';
require('./exceptionWriter.js')(logSystem);
/**
* Generate random instance id
**/
exports.instanceId = function () {
return crypto.randomBytes(4);
}
/**
* Validate miner address
**/
var addressBase58Prefix = config.poolServer.pubAddressPrefix ? parseInt(config.poolServer.pubAddressPrefix) : parseInt(cnUtil.address_decode(Buffer.from(config.poolServer.poolAddress)).toString());
let integratedAddressBase58Prefix = config.poolServer.intAddressPrefix ? parseInt(config.poolServer.intAddressPrefix) : addressBase58Prefix + 1;
let subAddressBase58Prefix = config.poolServer.subAddressPrefix ? parseInt(config.poolServer.subAddressPrefix) : "N/A";
// Get address prefix
function getAddressPrefix (address) {
let addressBuffer = Buffer.from(address);
let addressPrefix = cnUtil.address_decode(addressBuffer);
if (addressPrefix) {
addressPrefix = parseInt(addressPrefix.toString());
}
if (!addressPrefix) {
addressPrefix = cnUtil.address_decode_integrated(addressBuffer);
}
return addressPrefix || null;
}
exports.getAddressPrefix = getAddressPrefix;
// Validate miner address
exports.validateMinerAddress = function (address) {
if (isPeyaEnabled()) {
return validateConfiguredAddress(address, 'peya', 'carrot');
}
if (isSalviumEnabled()) {
return validateConfiguredAddress(address, 'salvium', 'carrot');
}
let addressPrefix = getAddressPrefix(address);
if (addressPrefix === addressBase58Prefix) return true;
else if (addressPrefix === integratedAddressBase58Prefix) return true;
else if (addressPrefix === subAddressBase58Prefix) return true;
return false;
}
function characterCount (string, char) {
let re = new RegExp(char, "gi")
let matches = string.match(re)
return matches === null ? 0 : matches.length;
}
exports.characterCount = characterCount;
// Validate miner address
exports.validateChildMinerAddress = (address, index) => {
let childAddressBase58Prefix = parseInt(cnUtil.address_decode(Buffer.from(config.childPools[index].poolAddress)).toString());
let childIntegratedAddressBase58Prefix = config.poolServer.intChildAddressPrefix ? parseInt(config.childPools[index].intAddressPrefix) : childAddressBase58Prefix + 1;
let addressPrefix = getAddressPrefix(address);
if (addressPrefix === childAddressBase58Prefix) return true;
else if (addressPrefix === childIntegratedAddressBase58Prefix) return true;
return false;
}
// Return if value is an integrated address
exports.isIntegratedAddress = function (address) {
let addressPrefix = getAddressPrefix(address);
return (addressPrefix === integratedAddressBase58Prefix);
}
exports.determineRewardData = (value) => {
let calculatedData = {
'address': value,
'rewardType': 'prop'
}
if (/^solo:/i.test(value)) {
calculatedData['address'] = value.substr(5)
calculatedData['rewardType'] = 'solo'
return calculatedData
}
if (/^prop:/i.test(value)) {
calculatedData['address'] = value.substr(5)
calculatedData['rewardType'] = 'prop'
return calculatedData
}
return calculatedData
}
/**
* Cleanup special characters (fix for non latin characters)
**/
function cleanupSpecialChars (str) {
str = str.replace(/[ÀÁÂÃÄÅ]/g, "A");
str = str.replace(/[àáâãäå]/g, "a");
str = str.replace(/[ÈÉÊË]/g, "E");
str = str.replace(/[èéêë]/g, "e");
str = str.replace(/[ÌÎÏ]/g, "I");
str = str.replace(/[ìîï]/g, "i");
str = str.replace(/[ÒÔÖ]/g, "O");
str = str.replace(/[òôö]/g, "o");
str = str.replace(/[ÙÛÜ]/g, "U");
str = str.replace(/[ùûü]/g, "u");
return str.replace(/[^A-Za-z0-9\-\_+]/gi, '');
}
exports.cleanupSpecialChars = cleanupSpecialChars;
function isPeyaEnabled() {
return config.peya && config.peya.enabled === true &&
(config.coin === 'Peya' || config.coin === 'PEY' || config.symbol === 'PEY');
}
exports.isPeyaEnabled = isPeyaEnabled;
function isSalviumEnabled() {
return config.salvium && config.salvium.enabled === true &&
(config.coin === 'Salvium' || config.coin === 'SAL' || config.symbol === 'SAL' || config.symbol === 'SAL1');
}
exports.isSalviumEnabled = isSalviumEnabled;
function isAssetAwareCoin() {
return isSalviumEnabled() || isPeyaEnabled();
}
exports.isAssetAwareCoin = isAssetAwareCoin;
function getConfiguredPrefixes(sectionName, type) {
return config[sectionName] &&
config[sectionName].addressPrefixes &&
config[sectionName].addressPrefixes[type];
}
function validateConfiguredAddress(address, sectionName, type) {
if (!address) return false;
const prefixes = getConfiguredPrefixes(sectionName, type);
if (!prefixes) return false;
const addressPrefix = getAddressPrefix(address);
if (addressPrefix == null) return false;
const toInt = (v) => {
if (typeof v === 'number') return v;
if (typeof v === 'string') return parseInt(v);
return NaN;
};
return [prefixes.public, prefixes.integrated, prefixes.subaddress]
.map(toInt)
.some(prefix => !Number.isNaN(prefix) && prefix === addressPrefix);
}
exports.validateConfiguredAddress = validateConfiguredAddress;
function getPrimaryAssetSymbol() {
if (isPeyaEnabled()) {
return (config.peya && config.peya.assetSymbol) || 'PEY';
}
if (isSalviumEnabled()) {
return (config.salvium && config.salvium.assetSymbol) || 'SAL1';
}
return config.symbol;
}
exports.getPrimaryAssetSymbol = getPrimaryAssetSymbol;
function getPoolTemplateAddress() {
if (isPeyaEnabled()) {
return (config.peya && config.peya.poolAddress) || config.poolServer.poolAddress;
}
if (isSalviumEnabled()) {
return (config.salvium && config.salvium.poolAddress) ||
(config.salvium && config.salvium.carrotPoolAddress) ||
config.poolServer.poolAddress;
}
return config.poolServer.poolAddress;
}
exports.getPoolTemplateAddress = getPoolTemplateAddress;
/**
* Get readable hashrate
**/
exports.getReadableHashRate = function (hashrate) {
let i = 0;
let byteUnits = [' H', ' KH', ' MH', ' GH', ' TH', ' PH'];
while (hashrate > 1000) {
hashrate = hashrate / 1000;
i++;
}
return hashrate.toFixed(2) + byteUnits[i] + '/sec';
}
/**
* Get readable coins
**/
exports.getReadableCoins = function (coins, digits, withoutSymbol) {
let coinDecimalPlaces = config.coinDecimalPlaces || config.coinUnits.toString().length - 1;
let amount = (parseInt(coins || 0) / config.coinUnits).toFixed(digits || coinDecimalPlaces);
return amount + (withoutSymbol ? '' : (' ' + config.symbol));
}
/**
* Generate unique id
**/
exports.uid = function () {
let min = 100000000000000;
let max = 999999999999999;
let id = Math.floor(Math.random() * (max - min + 1)) + min;
return id.toString();
};
/**
* Ring buffer
**/
exports.ringBuffer = function (maxSize) {
let data = [];
let cursor = 0;
let isFull = false;
return {
append: function (x) {
if (isFull) {
data[cursor] = x;
cursor = (cursor + 1) % maxSize;
} else {
data.push(x);
cursor++;
if (data.length === maxSize) {
cursor = 0;
isFull = true;
}
}
},
avg: function (plusOne) {
let sum = data.reduce(function (a, b) {
return a + b
}, plusOne || 0);
return sum / ((isFull ? maxSize : cursor) + (plusOne ? 1 : 0));
},
size: function () {
return isFull ? maxSize : cursor;
},
clear: function () {
data = [];
cursor = 0;
isFull = false;
}
};
};