172 lines
5.6 KiB
JavaScript
Executable File
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;
|