Merge pull request #6 from jstefanop/dev

Merge 2.0.5
This commit is contained in:
jstefanop 2024-05-28 13:13:52 -04:00 committed by GitHub
commit 538da8ac95
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 354 additions and 195 deletions

3
.gitignore vendored
View File

@ -60,6 +60,7 @@ typings/
# dotenv environment variables file
.env
.env.staging
.env*.local
# next.js build output
@ -67,6 +68,7 @@ typings/
# sqlite
*.sqlite
*.sqlite.*
#backed
backend/apollo-miner/apollo-miner*
@ -77,3 +79,4 @@ backend/node/bitcoind
backend/node/bitcoin.conf
backend/ckpool/ckpool.conf
backend/start_swap.sh
backend/apollo-miner/mode

View File

@ -2,7 +2,8 @@ server=1
rpcuser=futurebit
rpcpassword=
daemon=0
maxconnections=32
upnp=1
uacomment=FutureBit-Apollo-Node
zmqpubhashblock=tcp://127.0.0.1:28332
#SOLO_START
zmqpubhashblock=tcp://127.0.0.1:28332
#SOLO_END

View File

@ -2,6 +2,5 @@ server=1
rpcuser=futurebit
rpcpassword=futurebit
daemon=0
maxconnections=32
upnp=1
uacomment=FutureBit-Apollo-Node

View File

@ -50,12 +50,47 @@ then
MINER_FAN_SPEED=$(cat /var/local/apollo/hwmon/fan_rpm)
fi
#Network
# Function to check if an interface is up or down
get_interface_status() {
local interface=$1
ip link show "$interface" | grep -q "state UP"
if [ $? -eq 0 ]; then
echo "true"
else
echo "false"
fi
}
# Retrieve IP, MAC and status of eth0 and wlan0 interfaces
ETH_IP=$(ip addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f 1)
ETH_MAC=$(ip link show eth0 | awk '/ether/ {print $2}')
ETH_STATUS=$(get_interface_status eth0)
WLAN_IP=$(ip addr show wlan0 | awk '/inet / {print $2}' | cut -d/ -f 1)
WLAN_MAC=$(ip link show wlan0 | awk '/ether/ {print $2}')
WLAN_STATUS=$(get_interface_status wlan0)
# Variable to track the first IP of wlx interfaces
FIRST_WLX_IP=""
FIRST_WLX_MAC=""
FIRST_WLX_STATUS=""
# Retrieve IP, MAC and status of WiFi interfaces starting with wlx
for interface in $(ip -o link show | awk -F': ' '{print $2}' | grep ^wlx); do
WLX_IP=$(ip addr show "$interface" | awk '/inet / {print $2}' | cut -d/ -f 1)
WLX_MAC=$(ip link show "$interface" | awk '/ether/ {print $2}')
WLX_STATUS=$(get_interface_status "$interface")
# If WLAN_IP is empty and FIRST_WLX_IP is not yet assigned, use WLX_IP
if [ -z "$WLAN_IP" ] && [ -z "$FIRST_WLX_IP" ] && [ -n "$WLX_IP" ]; then
FIRST_WLX_IP=$WLX_IP
FIRST_WLX_MAC=$WLX_MAC
FIRST_WLX_STATUS=$WLX_STATUS
WLAN_IP=$WLX_IP
WLAN_MAC=$WLX_MAC
WLAN_STATUS=$WLX_STATUS
fi
done
# Memory
memTotal=$(egrep '^MemTotal:' /proc/meminfo | awk '{print $2}')
@ -98,11 +133,13 @@ JSON="{
\"network\": [{
\"name\": \"eth0\",
\"address\": \"$ETH_IP\",
\"mac\": \"$ETH_MAC\"
\"mac\": \"$ETH_MAC\",
\"status\": \"$ETH_STATUS\"
}, {
\"name\": \"wlan0\",
\"address\": \"$WLAN_IP\",
\"mac\": \"$WLAN_MAC\"
\"mac\": \"$WLAN_MAC\",
\"status\": \"$WLAN_STATUS\"
}],
\"memory\":
{

View File

@ -0,0 +1,13 @@
exports.up = function (knex, Promise) {
return knex.schema.table('settings', function (t) {
t.integer('node_max_connections').defaultTo(32);
t.boolean('node_allow_lan').defaultTo(false);
});
};
exports.down = function (knex, Promise) {
return knex.schema.table('settings', function (t) {
t.dropColumn('node_max_connections');
t.dropColumn('node_allow_lan');
});
};

View File

@ -1,6 +1,6 @@
{
"name": "apolloapi-v2",
"version": "2.0.4",
"version": "2.0.5",
"main": "index.js",
"repository": "https://github.com/jstefanop/apolloapi-v2.git",
"author": "FutureBit LLC",

View File

@ -17,6 +17,7 @@ module.exports.typeDefs = `
uuid: String
version: String
date: String
comport: String
statVersion: String
versions: MinerStatsVersion
master: MinerStatsMaster
@ -62,7 +63,7 @@ module.exports.typeDefs = `
byDiff: Float
byPool: Float
byJobs: Float
solutions: Int
solutions: Float
errors: Int
errorRate: Float
chipSpeed: Float
@ -156,8 +157,8 @@ module.exports.typeDefs = `
lowCurrRst: Int
currents: [Int]
brokenPwc: Int
solutions: Int
errors: Int
solutions: Float
errors: Float
ghs: Float
errorRate: Float
chipRestarts: Int
@ -185,11 +186,11 @@ module.exports.typeDefs = `
type MinerStatsCkpool {
pool: MinerStatsCkpoolPool
users: MinerStatsCkpoolUsers
users: [MinerStatsCkpoolUsers]
}
type MinerStatsCkpoolPool {
runtime: Int
runtime: Float
lastupdate: Int
Users: Int
Workers: Int

View File

@ -23,11 +23,13 @@ module.exports.typeDefs = `
leftSidebarExtended: Boolean!
rightSidebarVisibility: Boolean!
temperatureUnit: TemperatureUnit!
powerLedOff: Boolean
nodeRpcPassword: String
nodeEnableTor: Boolean
nodeUserConf: String
nodeEnableSoloMining: Boolean
powerLedOff: Boolean
nodeMaxConnections: Int
nodeAllowLan: Boolean
}
`

View File

@ -18,11 +18,13 @@ module.exports.typeDefs = `
leftSidebarExtended: Boolean
rightSidebarVisibility: Boolean
temperatureUnit: TemperatureUnit
powerLedOff: Boolean
nodeRpcPassword: String
nodeEnableTor: Boolean
nodeUserConf: String
nodeEnableSoloMining: Boolean
powerLedOff: Boolean
nodeMaxConnections: Int
nodeAllowLan: Boolean
}
type SettingsUpdateOutput {

View File

@ -1,12 +1,8 @@
const { writeFileSync, readFileSync, existsSync } = require('fs');
const { writeFileSync, existsSync } = require('fs');
const { join } = require('path');
const crypto = require('crypto');
const { exec } = require('child_process');
const generator = require('generate-password');
const utils = require('./utils');
const { knex } = require('./db');
const fs = require('fs').promises;
const path = require('path');
const initEnvFile = async () => {
const envPath = join(__dirname, '..', '.env');
@ -30,109 +26,38 @@ const initEnvFile = async () => {
const runMigrations = async () => {
try {
console.log('Run migrations');
const resp = await knex.migrate.latest();
await createCkpoolConfigFile();
await createBitcoinConfigFile();
await runGenerateBitcoinPassword();
await knex.migrate.latest();
const [settings] = await knex('settings')
.select([
'node_rpc_password as nodeRpcPassword',
'node_enable_tor as nodeEnableTor',
'node_user_conf as nodeUserConf',
'node_enable_solo_mining as nodeEnableSoloMining',
'node_max_connections as nodeMaxConnections',
'node_allow_lan as nodeAllowLan',
])
.orderBy('created_at', 'desc')
.orderBy('id', 'desc')
.limit(1);
await utils.auth.manageBitcoinConf(settings);
await runGenerateBitcoinPassword(settings);
} catch (err) {
console.log(err);
}
};
const runGenerateBitcoinPassword = async () => {
const runGenerateBitcoinPassword = async (settings) => {
try {
console.log('Checking bitcoin password existence');
const [settings] = await knex('settings')
.select(['node_rpc_password as nodeRpcPassword'])
.orderBy('created_at', 'desc')
.orderBy('id', 'desc')
.limit(1);
if (settings && settings.nodeRpcPassword)
return console.log('Bitcoin password found');
else await utils.auth.changeNodeRpcPassword();
else await utils.auth.changeNodeRpcPassword(settings);
} catch (err) {
console.log(err);
}
};
const createCkpoolConfigFile = async () => {
const configFilePath = path.resolve(
__dirname,
'../backend/ckpool/ckpool.conf'
);
const configContent = `{
"btcd": [
{
"url": "127.0.0.1:8332",
"auth": "futurebit",
"pass": "",
"notify": true
}
],
"logdir": "/opt/apolloapi/backend/ckpool/logs"
}`;
try {
// Check if the file exists
await fs.access(configFilePath);
console.log('File ckpool.conf already exists.');
} catch (error) {
try {
// Create the file
await fs.writeFile(configFilePath, configContent, 'utf-8');
console.log('File ckpool.conf created.');
} catch (error) {
console.error(
`Error during the creation of the file ckpool.conf: ${error.message}`
);
}
} finally {
const [settings] = await knex('settings')
.select(['node_rpc_password as nodeRpcPassword'])
.orderBy('created_at', 'desc')
.orderBy('id', 'desc')
.limit(1);
if (settings && settings.nodeRpcPassword) {
exec(
`sudo sed -i 's#"pass":.*#"pass": "${settings.nodeRpcPassword}",#g' ${configFilePath}`
);
}
}
};
const createBitcoinConfigFile = async () => {
const configFilePath = path.resolve(
__dirname,
'../backend/node/bitcoin.conf'
);
const configContent = `server=1
rpcuser=futurebit
rpcpassword=
daemon=0
maxconnections=32
upnp=1
uacomment=FutureBit-Apollo-Node`;
try {
// Check if the file exists
await fs.access(configFilePath);
console.log('File bitcoin.conf already exists.');
} catch (error) {
try {
// Create the file
await fs.writeFile(configFilePath, configContent, 'utf-8');
console.log('File bitcoin.conf created.');
await utils.auth.changeNodeRpcPassword();
} catch (error) {
console.error(
`Error during the creation of the file bitcoin.conf: ${error.message}`
);
}
}
};
initEnvFile();
runMigrations().then(startServer);

View File

@ -11,7 +11,6 @@ module.exports = ({ define }) => {
})
utils.auth.changeSystemPassword(password)
await utils.auth.changeNodeRpcPassword()
} catch (err) {
console.log('ERROR', err);
}

View File

@ -1,15 +1,30 @@
const { join } = require('path');
const { exec } = require('child_process');
const fs = require('fs').promises;
const path = require('path');
const _ = require('lodash');
module.exports = ({ define }) => {
define(
'updateProgress',
async (payload, { knex, errors, utils }) => {
try {
const data = await fs.readFile(`/tmp/update_progress`);
// 1. Check if the file exists
const filePath = '/tmp/update_progress';
let fileExists = true;
try {
await fs.access(filePath, fs.constants.F_OK);
} catch (error) {
if (error.code === 'ENOENT') {
// File doesn't exist
console.log('update_progress file not found. Returning default progress.');
fileExists = false;
} else {
throw error;
}
}
if (!fileExists) {
return { value: 0 };
}
const data = await fs.readFile(filePath);
const progress = parseInt(data.toString());
return { value: progress };
} catch (error) {

View File

@ -1,10 +1,7 @@
const { join } = require('path');
const { exec } = require('child_process');
const fs = require('fs').promises;
const path = require('path');
const _ = require('lodash');
const moment = require('moment');
const { existsSync } = require('fs');
const c = require('config');
module.exports = ({ define }) => {
@ -69,40 +66,48 @@ const getCkpoolStats = async (errors, settings, pools) => {
try {
if (settings?.nodeEnableSoloMining) {
const poolUsername = pools[0] && pools[0].username;
const ckpoolPoolStatsFile = path.resolve(
__dirname,
'../../../../backend/ckpool/logs/pool/pool.status'
);
const ckpoolUsersStatsFile = path.resolve(
const ckpoolUsersStatsDir = path.resolve(
__dirname,
`../../../../backend/ckpool/logs/users/${poolUsername}`
'../../../../backend/ckpool/logs/users/'
);
if (
existsSync(ckpoolPoolStatsFile) &&
existsSync(ckpoolUsersStatsFile)
) {
await Promise.all([
(async () => {
let ckpoolPoolData = await parseFileToJsonArray(
ckpoolPoolStatsFile
);
let ckpoolUsersData = await fs.readFile(
ckpoolUsersStatsFile,
'utf8'
);
ckpoolUsersData = JSON.parse(ckpoolUsersData);
ckpoolData = {
pool: ckpoolPoolData,
users: ckpoolUsersData,
};
})(),
]);
try {
// Check if the directory exists
await fs.stat(ckpoolUsersStatsDir);
} catch (err) {
if (err.code === 'ENOENT') {
// Directory does not exist
resolve(ckpoolData); // Resolve with null data
return;
}
throw err; // Re-throw other errors
}
const filenames = await fs.readdir(ckpoolUsersStatsDir);
const usersDataPromises = filenames.map(async (filename) => {
const ckpoolUsersStatsFile = path.resolve(
ckpoolUsersStatsDir,
filename
);
const ckpoolUsersData = await fs.readFile(
ckpoolUsersStatsFile,
'utf8'
);
return JSON.parse(ckpoolUsersData);
});
const usersData = await Promise.all(usersDataPromises);
ckpoolData = {
pool: await parseFileToJsonArray(ckpoolPoolStatsFile),
users: usersData,
};
}
resolve(ckpoolData);

View File

@ -28,11 +28,13 @@ module.exports = ({ define }) => {
'left_sidebar_extended as leftSidebarExtended',
'right_sidebar_visibility as rightSidebarVisibility',
'temperature_unit as temperatureUnit',
'power_led_off as powerLedOff',
'node_rpc_password as nodeRpcPassword',
'node_enable_tor as nodeEnableTor',
'node_user_conf as nodeUserConf',
'node_enable_solo_mining as nodeEnableSoloMining',
'power_led_off as powerLedOff',
'node_max_connections as nodeMaxConnections',
'node_allow_lan as nodeAllowLan',
)
readQ.orderBy('created_at', 'desc')

View File

@ -13,11 +13,13 @@ module.exports = ({ define }) => {
'left_sidebar_extended as leftSidebarExtended',
'right_sidebar_visibility as rightSidebarVisibility',
'temperature_unit as temperatureUnit',
'power_led_off as powerLedOff',
'node_rpc_password as nodeRpcPassword',
'node_enable_tor as nodeEnableTor',
'node_user_conf as nodeUserConf',
'node_enable_solo_mining as nodeEnableSoloMining',
'power_led_off as powerLedOff',
'node_max_connections as nodeMaxConnections',
'node_allow_lan as nodeAllowLan',
])
.orderBy('created_at', 'desc')
.orderBy('id', 'desc')

View File

@ -12,11 +12,13 @@ const updateFields = {
leftSidebarExtended: 'left_sidebar_extended',
rightSidebarVisibility: 'right_sidebar_visibility',
temperatureUnit: 'temperature_unit',
powerLedOff: 'power_led_off',
nodeRpcPassword: 'node_rpc_password',
nodeEnableTor: 'node_enable_tor',
nodeUserConf: 'node_user_conf',
nodeEnableSoloMining: 'node_enable_solo_mining',
powerLedOff: 'power_led_off'
nodeMaxConnections: 'node_max_connections',
nodeAllowLan: 'node_allow_lan'
}
module.exports = ({ define }) => {

View File

@ -11,7 +11,10 @@ module.exports = ({ define }) => {
if (
oldSettings.nodeEnableTor !== newSettings.nodeEnableTor ||
oldSettings.nodeUserConf !== newSettings.nodeUserConf ||
oldSettings.nodeEnableSoloMining !== newSettings.nodeEnableSoloMining
oldSettings.nodeEnableSoloMining !== newSettings.nodeEnableSoloMining ||
oldSettings.nodeRpcPassword !== newSettings.nodeRpcPassword ||
oldSettings.nodeAllowLan !== newSettings.nodeAllowLan ||
oldSettings.nodeMaxConnections !== newSettings.nodeMaxConnections
)
await utils.auth.manageBitcoinConf(newSettings);

View File

@ -20,7 +20,7 @@ const store = loadStore({
return !['index.js', 'store.js'].includes(relativePath) && relativePath.match(/\.js$/)
}
},
logger: logger,
logger: process.env.NODE_ENV !== 'development' && logger,
methodContext: {
knex,
utils

View File

@ -6,6 +6,22 @@ const config = require('config');
const { knex } = require('./db');
const fsPromises = require('fs').promises;
const path = require('path');
const os = require('os');
const configBitcoinFilePath = path.resolve(
__dirname,
'../backend/node/bitcoin.conf'
);
const configCkpoolFilePath = path.resolve(
__dirname,
'../backend/ckpool/ckpool.conf'
);
const configCkpoolServiceFilePath = path.resolve(
__dirname,
'../backend/systemd/ckpool.service'
);
module.exports.auth = {
hashPassword(password) {
@ -23,7 +39,7 @@ module.exports.auth = {
exec(`echo 'futurebit:${password}' | sudo chpasswd`);
},
async changeNodeRpcPassword() {
async changeNodeRpcPassword(settings) {
try {
console.log('Generating and saving bitcoin password');
@ -36,28 +52,20 @@ module.exports.auth = {
node_rpc_password: password,
});
const configFilePath = path.resolve(
__dirname,
'../backend/node/bitcoin.conf'
);
await fsPromises.access(configBitcoinFilePath);
await fsPromises.access(configCkpoolFilePath);
const configCkpoolFilePath = path.resolve(
__dirname,
'../backend/ckpool/ckpool.conf'
exec(
`sudo sed -i 's/rpcpassword.*/rpcpassword=${password}/g' ${configBitcoinFilePath}`
);
exec(
`sudo sed -i s/rpcpassword.*/rpcpassword=${password}/g ${configFilePath}`
`sudo sed -i 's#"pass":.*#"pass": "${password}",#g' ${configCkpoolFilePath}`
);
exec(
`sudo sed -i 's#"pass": ""#"pass": "${password}"#g' ${configCkpoolFilePath}`
);
console.log(password, configFilePath);
exec('sudo systemctl restart node');
exec('sudo systemctl restart ckpool');
if (settings?.nodeEnableSoloMining) exec('sudo systemctl restart ckpool');
} catch (err) {
console.log('ERR changeNodeRpcPassword', err);
}
@ -73,13 +81,83 @@ module.exports.auth = {
};
},
async manageBitcoinConf(settings) {
const defaultConf = `server=1\nrpcuser=futurebit\nrpcpassword=${settings.nodeRpcPassword}\ndaemon=0\nmaxconnections=32\nupnp=1\nuacomment=FutureBit-Apollo-Node`;
let conf = defaultConf;
networkAddressWithCIDR(ipAddress, netmask) {
// Converti l'indirizzo IP e la netmask in forma binaria
const ipBinary = ipAddress
.split('.')
.map((part) => parseInt(part, 10).toString(2).padStart(8, '0'))
.join('');
const netmaskBinary = netmask
.split('.')
.map((part) => parseInt(part, 10).toString(2).padStart(8, '0'))
.join('');
if (settings.nodeEnableSoloMining) {
conf += `\n#SOLO_START\nzmqpubhashblock=tcp://127.0.0.1:28332\n#SOLO_END`;
// Applica l'operazione bitwise AND
const networkBinary = ipBinary
.split('')
.map((bit, index) => bit & netmaskBinary[index])
.join('');
// Converti il risultato in forma di stringa
const networkAddress = networkBinary
.match(/.{1,8}/g)
.map((byte) => parseInt(byte, 2))
.join('.');
// Calcola il numero di bit della netmask
const cidrPrefix = netmask
.split('.')
.reduce(
(acc, byte) =>
acc + (parseInt(byte, 10).toString(2).match(/1/g) || '').length,
0
);
return `${networkAddress}/${cidrPrefix}`;
},
getSystemNetwork() {
// Get network interface information
const interfaces = os.networkInterfaces();
let address = null;
let netmask = null;
let network = null;
// Check if wlan0 has an associated IP address
if (
interfaces['wlan0'] &&
interfaces['wlan0'].some((info) => info.family === 'IPv4')
) {
// If wlan0 has an associated IP address, use wlan0
address = interfaces['wlan0'].find(
(info) => info.family === 'IPv4'
).address;
netmask = interfaces['wlan0'].find(
(info) => info.family === 'IPv4'
).netmask;
} else if (
interfaces['eth0'] &&
interfaces['eth0'].some((info) => info.family === 'IPv4')
) {
// If wlan0 doesn't have an associated IP address but eth0 does, use eth0
address = interfaces['eth0'].find(
(info) => info.family === 'IPv4'
).address;
netmask = interfaces['eth0'].find(
(info) => info.family === 'IPv4'
).netmask;
} else {
console.log('No IP address associated with wlan0 or eth0');
}
if (address && netmask)
network = this.networkAddressWithCIDR(address, netmask);
return network;
},
async manageCkpoolConf(settings) {
try {
const ckpoolConf = {
btcd: [
{
@ -95,37 +173,107 @@ module.exports.auth = {
};
await fsPromises.writeFile(
'/opt/apolloapi/backend/ckpool/ckpool.conf',
configCkpoolFilePath,
JSON.stringify(ckpoolConf, null, 2)
);
exec(
'sudo cp /opt/app/backend/systemd/ckpool.service /etc/systemd/system/ckpool.service'
);
exec('sudo systemctl daemon-reload');
exec('sudo systemctl enable ckpool');
exec('sudo systemctl restart ckpool');
} else {
exec('sudo systemctl stop ckpool');
exec('sudo systemctl disable ckpool');
} catch (err) {
console.log('ERR manageCkpoolConf', err);
}
},
if (settings.nodeEnableTor) {
conf += `\n#TOR_START\nproxy=127.0.0.1:9050\nlisten=1\nbind=127.0.0.1\nonlynet=onion\ndnsseed=0\ndns=0\n#TOR_END`;
exec('sudo systemctl enable tor');
exec('sudo systemctl restart tor');
} else {
exec('sudo systemctl stop tor');
exec('sudo systemctl disable tor');
async manageBitcoinConf(settings) {
try {
// CHecking current conf file
const currentConf = await fsPromises.readFile(configBitcoinFilePath, 'utf8');
const currentConfBase64 = Buffer.from(currentConf).toString('base64');
const defaultConf = `server=1\nrpcuser=futurebit\nrpcpassword=${settings.nodeRpcPassword}\ndaemon=0\nupnp=1\nuacomment=FutureBit-Apollo-Node`;
let conf = defaultConf;
conf += `\n#SOLO_START\nzmqpubhashblock=tcp://127.0.0.1:28332\n#SOLO_END`;
this.manageCkpoolConf(settings);
if (settings.nodeEnableSoloMining) {
exec(
`sudo cp ${configCkpoolServiceFilePath} /etc/systemd/system/ckpool.service`
);
exec('sudo systemctl daemon-reload');
exec('sudo systemctl enable ckpool');
exec('sudo systemctl restart ckpool');
} else {
exec('sudo systemctl stop ckpool');
exec('sudo systemctl disable ckpool');
}
if (settings.nodeEnableTor) {
conf += `\n#TOR_START\nproxy=127.0.0.1:9050\nlisten=1\nbind=127.0.0.1\nonlynet=onion\ndnsseed=0\ndns=0\n#TOR_END`;
exec('sudo systemctl enable tor');
exec('sudo systemctl restart tor');
} else {
exec('sudo systemctl stop tor');
exec('sudo systemctl disable tor');
}
if (settings.nodeMaxConnections)
conf += `\nmaxconnections=${settings.nodeMaxConnections}`;
else conf += '\nmaxconnections=32';
if (settings.nodeAllowLan) {
const lanNetwork = this.getSystemNetwork();
conf += `\nrpcbind=0.0.0.0\nrpcallowip=0.0.0.0/0`;
}
if (settings.nodeUserConf) {
// Extract variable names from settings.nodeUserConf using regex
const userConfVariables = settings.nodeUserConf.match(/^[^=\r\n]+/gm);
// Extract variable names from defaultConf using regex
const defaultConfVariables = defaultConf.match(/^[^=\r\n]+/gm);
// Remove variables from settings.nodeUserConf that are also present in defaultConf
const filteredUserConfVariables = userConfVariables.filter(
(variable) => !defaultConfVariables.includes(variable)
);
if (filteredUserConfVariables.length) {
// Initialize an empty array to store formatted user configurations
const formattedUserConf = [];
// Iterate through filtered variables and format them
filteredUserConfVariables.forEach((variable) => {
// If the variable has a value, format it as "variable=value"
// Otherwise, format it as "variable"
const formattedVariable = settings.nodeUserConf.includes(
`${variable}=`
)
? `${variable}=${
settings.nodeUserConf.match(new RegExp(`${variable}=(.*)`))[1]
}`
: variable;
// Push the formatted variable to the array
formattedUserConf.push(formattedVariable);
});
// Join the formatted variables into a single string with newlines
const filteredUserConf = formattedUserConf.join('\n');
// Append the filtered user configuration to the overall configuration
conf += `\n#USER_INPUT_START\n${filteredUserConf}\n#USER_INPUT_END`;
}
}
const confBase64 = Buffer.from(conf).toString('base64');
if (currentConfBase64 === confBase64) return console.log('No changes to bitcoin.conf file');
console.log('Writing Bitcoin conf file', conf);
await fsPromises.writeFile(configBitcoinFilePath, conf);
exec('sleep 3 && sudo systemctl restart node');
} catch (err) {
console.log('ERR manageBitcoinConf', err);
}
if (settings.nodeUserConf)
conf += `\n#USER_INPUT_START\n${settings.nodeUserConf}\n#USER_INPUT_END`;
console.log('Writing Bitcoin conf file', conf);
exec(`echo "${conf}" | sudo tee /opt/apolloapi/backend/node/bitcoin.conf`);
exec('sudo systemctl restart node');
},
};