4NK_env/scripts/lecoffre_node/funds/funds_detector_service.js
LeCoffre Deployment 43a05a2742 clean
2025-09-25 12:19:35 +00:00

172 lines
5.6 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* Service de détection et transfert automatique de fonds
* Ce service surveille les applications et transfère automatiquement des fonds
* quand un manque de fonds est détecté
*/
const { spawn, exec } = require('child_process');
const fs = require('fs');
const path = require('path');
class FundsDetectorService {
constructor() {
this.isRunning = false;
this.checkInterval = 30000; // 30 secondes
this.minFundsThreshold = 0.001; // 0.001 BTC = 100,000 sats
this.transferAmount = 0.01; // 0.01 BTC = 1,000,000 sats
this.logFile = '/tmp/funds_detector.log';
}
log(message) {
const timestamp = new Date().toISOString();
const logMessage = `[${timestamp}] ${message}\n`;
console.log(logMessage.trim());
fs.appendFileSync(this.logFile, logMessage);
}
async checkRelayFunds() {
try {
// Vérifier les fonds du relay dans la configuration
const outputsCount = await this.getRelayOutputsCount();
this.log(`Relay outputs count: ${outputsCount}`);
// Vérifier le solde du wallet relay dans Bitcoin Core
const relayBalance = await this.getRelayBalance();
this.log(`Relay balance: ${relayBalance} BTC`);
// Si le relay n'a pas de fonds, déclencher le transfert
if (outputsCount === 0 && parseFloat(relayBalance) < this.minFundsThreshold) {
this.log(`⚠️ Fonds insuffisants détectés. Lancement du transfert automatique...`);
await this.transferFunds();
return true;
}
this.log(`✅ Fonds suffisants (outputs: ${outputsCount}, balance: ${relayBalance} BTC)`);
return false;
} catch (error) {
this.log(`❌ Erreur lors de la vérification des fonds: ${error.message}`);
return false;
}
}
async getRelayOutputsCount() {
return new Promise((resolve, reject) => {
exec('docker exec sdk_relay cat /home/bitcoin/.4nk/default 2>/dev/null | jq -r \'.outputs | length // 0\' 2>/dev/null || echo "0"', (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
resolve(parseInt(stdout.trim()) || 0);
}
});
});
}
async getRelayBalance() {
return new Promise((resolve, reject) => {
exec('docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="default" getbalance 2>/dev/null || echo "0"', (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
resolve(parseFloat(stdout.trim()) || 0);
}
});
});
}
async transferFunds() {
try {
this.log(`🔄 Transfert de ${this.transferAmount} BTC...`);
// Charger le wallet relay
await this.execCommand('docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" loadwallet "default" > /dev/null 2>&1 || true');
// Générer une adresse pour le relay
const relayAddress = await this.execCommand('docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="default" getnewaddress "relay_funding" 2>/dev/null');
this.log(`Adresse générée: ${relayAddress}`);
// Effectuer le transfert
const txid = await this.execCommand(`docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="mining_mnemonic" sendtoaddress "${relayAddress}" "${this.transferAmount}" 2>/dev/null`);
this.log(`Transaction ID: ${txid}`);
// Générer des blocs pour confirmer
await this.execCommand(`docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="mining_mnemonic" generatetoaddress 6 "${relayAddress}" > /dev/null 2>&1`);
// Redémarrer le relay
this.log(`🔄 Redémarrage du relay...`);
await this.execCommand('docker compose restart sdk_relay');
this.log(`✅ Transfert de fonds réussi et relay redémarré`);
return true;
} catch (error) {
this.log(`❌ Erreur lors du transfert: ${error.message}`);
return false;
}
}
async execCommand(command) {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
resolve(stdout.trim());
}
});
});
}
async start() {
if (this.isRunning) {
this.log('Service déjà en cours d\'exécution');
return;
}
this.isRunning = true;
this.log('🚀 Démarrage du service de détection des fonds');
this.log(`Seuil minimum: ${this.minFundsThreshold} BTC`);
this.log(`Montant de transfert: ${this.transferAmount} BTC`);
this.log(`Intervalle de vérification: ${this.checkInterval / 1000} secondes`);
const checkLoop = async () => {
if (!this.isRunning) return;
try {
await this.checkRelayFunds();
} catch (error) {
this.log(`❌ Erreur dans la boucle de vérification: ${error.message}`);
}
setTimeout(checkLoop, this.checkInterval);
};
// Démarrer la boucle de vérification
checkLoop();
}
stop() {
this.isRunning = false;
this.log('🛑 Arrêt du service de détection des fonds');
}
}
// Gestion des signaux pour un arrêt propre
process.on('SIGINT', () => {
console.log('\n🛑 Arrêt du service...');
process.exit(0);
});
process.on('SIGTERM', () => {
console.log('\n🛑 Arrêt du service...');
process.exit(0);
});
// Démarrer le service si ce script est exécuté directement
if (require.main === module) {
const service = new FundsDetectorService();
service.start();
}
module.exports = FundsDetectorService;