foxy-proxy
Version:
A Proof of Capacity proxy which supports solo and pool mining upstreams.
256 lines (230 loc) • 7.93 kB
JavaScript
const chalk = require('chalk');
const crypto = require('crypto');
const fs = require('fs');
const JSONbig = require('json-bigint');
const os = require('os');
const path = require('path');
const YAML = require('js-yaml');
const util = require('./util');
const store = require('./services/store');
const eventBus = require('./services/event-bus');
const outputUtil = require('./output-util');
module.exports = class Config {
static get defaultConfig() {
return {
proxies: [{
name: 'BURST-BHD',
maxScanTime: 35,
upstreams: [{
name: 'FoxyPool BURST',
type: 'foxypool',
coin: 'BURST',
payoutAddress: 'your BURST payout address',
accountName: 'your desired name',
minerName: 'your desired miner name',
weight: 10,
color: '#4959ff',
}, {
name: 'FoxyPool BHD',
type: 'foxypool',
coin: 'BHD',
payoutAddress: 'your BHD payout address',
accountName: 'your desired name',
minerName: 'your desired miner name',
weight: 11,
color: '#f49d11',
}],
}],
listenAddr: '127.0.0.1:12345',
useMultiplePorts: false,
webAuth: {
username: 'admin',
password: 'admin',
},
logLevel: 'info',
logToFile: true,
isInstalledGlobally: true,
};
}
static logErrorAndExit(error) {
eventBus.publish('log/error', `There is an error with your config file: ${error}`);
process.exit(1);
}
constructor() {
if (process.env.CONFIG) {
this._config = JSONbig.parse(process.env.CONFIG);
this.config.listenAddr = `0.0.0.0:${process.env.PORT}`;
this.config.useMultiplePorts = false;
this.validateConfig();
return;
}
this.filePath = store.getConfigFilePath();
util.ensureFilePathExists(this.filePath);
util.ensureFilePathExists(store.getDbFilePath());
this.migrateFromJSON();
this.migrateFromLegacyLocation();
this.loadFromFile();
this.migrateToProxyConfig();
this.replacePassWithHash();
if (this.logToFile) {
util.ensureFilePathExists(path.join(this.logDir, 'proxy.log'));
}
this.validateConfig();
}
validateConfig() {
const upstreamTypesWithUrl = [
'socketio',
];
const upstreamTypesWithTargetDL = [
'socketio',
];
const validListenAddrExists = this.config.listenAddr && this.config.listenAddr.split(':').length >= 2;
if (!validListenAddrExists) {
Config.logErrorAndExit('No valid listenAddr specified!');
}
if (this.listenPort < 1 || this.listenPort > 65535) {
Config.logErrorAndExit('No valid port specified!');
}
if (this.config.webAuth && (!this.config.webAuth.username || (!this.config.webAuth.password && !this.config.webAuth.passHash))) {
Config.logErrorAndExit('No valid webAuth defined, username or password missing!');
}
if (!this.config.proxies || !Array.isArray(this.config.proxies) || this.config.proxies.length === 0) {
Config.logErrorAndExit('No proxies configured!');
}
this.proxies.forEach(proxy => {
if (!proxy.name) {
Config.logErrorAndExit('At least one proxy does not have a name!');
}
if (!proxy.upstreams || !Array.isArray(proxy.upstreams) || proxy.upstreams.length === 0) {
Config.logErrorAndExit(`Proxy ${outputUtil.getName(proxy)} does not have any upstreams!`);
}
proxy.upstreams.forEach(upstream => {
if (!upstream.name) {
Config.logErrorAndExit(`Proxy ${outputUtil.getName(proxy)}: At least one upstream does not have a name!`);
}
if ((!upstream.type || upstreamTypesWithUrl.indexOf(upstream.type) !== -1) && !upstream.url) {
Config.logErrorAndExit(`Proxy ${outputUtil.getName(proxy)}, Upstream ${outputUtil.getName(upstream)}: No url defined!`);
}
if ((!upstream.type || upstreamTypesWithTargetDL.indexOf(upstream.type) !== -1) && !upstream.targetDL && !upstream.submitProbability) {
Config.logErrorAndExit(`Proxy ${outputUtil.getName(proxy)}, Upstream ${outputUtil.getName(upstream)}: No targetDL or submitProbability defined!`);
}
if (upstream.type === 'foxypool' && (!upstream.payoutAddress && !upstream.accountKey)) {
Config.logErrorAndExit(`Proxy ${outputUtil.getName(proxy)}, Upstream ${outputUtil.getName(upstream)}: No payoutAddress defined!`);
}
if (proxy.useProfitability && !upstream.coin) {
Config.logErrorAndExit(`Proxy ${outputUtil.getName(proxy)}, Upstream ${outputUtil.getName(upstream)}: No coin defined!`);
}
});
});
}
migrateFromJSON() {
if (!fs.existsSync('config.json')) {
return;
}
eventBus.publish('log/info', 'Old config file format detected, migrating to yaml ..');
const oldConfig = JSONbig.parse(fs.readFileSync('config.json'));
fs.writeFileSync(this.filePath, YAML.dump(oldConfig));
fs.unlinkSync('config.json');
}
migrateFromLegacyLocation() {
const legacyConfig = util.getLegacyFilePath('config.yaml');
if (!fs.existsSync(legacyConfig)) {
return;
}
eventBus.publish('log/info', `Old config file location detected, migrating to ${this.filePath} ..`);
fs.writeFileSync(this.filePath, fs.readFileSync(legacyConfig));
fs.unlinkSync(legacyConfig);
}
migrateToProxyConfig() {
if (!this.config.upstreams) {
return;
}
this.config.proxies = this.config.upstreams.map(upstreamConfig => ({
name: upstreamConfig.name,
upstreams: [upstreamConfig]
}));
delete this.config.upstreams;
this.saveToFile();
}
replacePassWithHash() {
if (!this.webAuth || !this.webAuth.password) {
return;
}
this.webAuth.passHash = crypto.createHash('sha256').update(this.webAuth.password, 'utf8').digest('hex');
delete this.webAuth.password;
this.saveToFile();
}
loadFromFile() {
let file;
try {
file = fs.readFileSync(this.filePath);
} catch (err) {
eventBus.publish('log/info', `First start detected, creating the config file (${chalk.cyan(this.filePath)}), please adjust it to your preferences.\n` +
'Possible config options are available here: https://docs.foxypool.io/foxy-proxy/configuration/#configuration-options');
this.initFromObject();
this.saveToFile();
process.exit(0);
}
let configObject = null;
try {
configObject = YAML.load(file);
} catch (err) {
Config.logErrorAndExit(err);
}
this.initFromObject(configObject);
}
saveToFile() {
const yaml = YAML.dump(this.config, {
lineWidth: 140,
});
fs.writeFileSync(this.filePath, yaml);
}
initFromObject(configObject = null) {
this._config = configObject || Config.defaultConfig;
}
get useMultiplePorts() {
return this.config.useMultiplePorts;
}
get proxies() {
return this.config.proxies;
}
get listenAddr() {
return this.config.listenAddr;
}
get listenHost() {
const parts = this.config.listenAddr.split(':');
parts.pop();
return parts.join(':');
}
get listenPort() {
const parts = this.config.listenAddr.split(':');
return parseInt(parts.pop(), 10);
}
get config() {
return this._config;
}
get webAuth() {
return this.config.webAuth;
}
get logLevel() {
return this.config.logLevel;
}
get logToFile() {
return this.config.logToFile;
}
get logDir() {
return this.config.logDir || path.join(os.homedir(), '.config/foxy-proxy/logs');
}
get logMaxFiles() {
return this.config.logMaxFiles || null;
}
get transports() {
return this.config.transports || ['http'];
}
get useEcoBlockRewardsForProfitability() {
return !!this.config.useEcoBlockRewards;
}
get allowLongPolling() {
return !!this.config.allowLongPolling;
}
};