feat: Ajout de l'API de transfert automatique de fonds
Some checks failed
build-and-push-ext / build_push (push) Failing after 10s

- Route /api/v1/funds/transfer pour transférer des fonds
- Route /api/v1/funds/check pour vérifier les fonds
- Intégration dans le service ihm_client pour détection automatique
- Service de détection de fonds en Node.js
This commit is contained in:
dev4 2025-09-20 16:17:36 +00:00
parent 4ff4f07ac5
commit 567e57abe8
3 changed files with 183 additions and 0 deletions

67
.cursorrules Normal file
View File

@ -0,0 +1,67 @@
# Règles Cursor Globales pour les projets
# si tu est une IA souviens toi de respecter les règles de ce fichier .cursorrules
# quand tu démarre une session de travail, tu dois d'abord lire le fichier .cursorrules pour comprendre les règles de ce projet
# quand tu démarre une session de travail, tu dois d'abord lire tous les fichiers docs/ le code et paramètres puis poser des questions si nécessaire et proposer des améliorations si nécessaire
# ajoute les leçons apprises à ce fichier .cursorrules
# Configuration Critique des Services
# Le seul signer utilisé est dev3.4nkweb.com
# L'URL de lecoffre-front est https://dev4.4nkweb.com/lecoffre
# L'URL de ihm_client (iframe) est https://dev4.4nkweb.com
# Cette VM est dev4.4nkweb.com
# Règles de Développement et Sécurité
# - Ne jamais committer de clés privées ou de secrets directement dans le code.
# - Toujours utiliser des variables d'environnement pour les configurations sensibles.
# - Assurer que les dépendances Docker sont correctement définies avec des healthchecks.
# - Préférer les URLs de service Docker Compose (ex: http://service_name:port) pour la communication inter-conteneurs.
# - Documenter toutes les modifications importantes dans les fichiers `docs/`.
# - Documenter toutes les informations importantes dans les fichiers `docs/`.
# - Documenter toutes les règles de développement et de sécurité dans .cursorrules.
# - Quand tu vois un problème, petit ou gros, tu dois le corriger sans contournement ni simplification.
# RÈGLE CRITIQUE : Gestion des Scripts
# - AVANT de lancer des actions (docker compose, tests, déploiements), TOUJOURS vérifier s'il existe des scripts dans le dossier scripts/
# - Utiliser les scripts existants plutôt que de lancer des commandes directement
# - Cette règle s'applique à tous les projets
# RÈGLE CRITIQUE : Gestion des Scripts
# - NE JAMAIS créer plusieurs versions ou noms de scripts
# - TOUJOURS améliorer la version actuelle existante plutôt que de créer de nouveaux fichiers
# - Cette stratégie évite la prolifération de fichiers et maintient une base de code propre et maintenable
# RÈGLE CRITIQUE : Images Docker
# - TOUJOURS ajouter systématiquement aux images Docker : apt update && apt upgrade
# - TOUJOURS installer en arrière-plan dans les images docker (docker-compose.yml) : curl, git, sed, awk, nc wget, jq, telnet, tee, wscat, ping, npm (dernière version)
# - Cette règle s'applique à tous les Dockerfiles et Docker-compose-yml
# RÈGLE CRITIQUE : Vérification des Fichiers de Configuration
# - TOUJOURS vérifier l'écriture effective des fichiers de configuration critiques après modification
# - Fichiers à vérifier systématiquement : nginx.conf, bitcoin.conf, package.json, Cargo.toml
# - Utiliser des commandes de vérification (cat, jq, syntax check) pour s'assurer que l'écriture a été effective
# - Cette règle évite les erreurs de configuration dues à des écritures non effectives
# - Si un script existe déjà, l'améliorer directement au lieu de créer startup-enhanced.sh, startup-v2.sh, etc.
# Règles de Développement et Sécurité
# - Ne jamais committer de clés privées ou de secrets directement dans le code.
# - Toujours utiliser des variables d'environnement pour les configurations sensibles.
# - Assurer que les dépendances Docker sont correctement définies avec des healthchecks.
# - Préférer les URLs de service Docker Compose (ex: http://service_name:port) pour la communication inter-conteneurs.
# - Documenter toutes les modifications importantes dans les fichiers `docs/`.
# Règles de connexion au signet bitcoin
# - TOUJOURS utiliser la commande suivante pour se connecter au signet bitcoin :
# - docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile=/home/bitcoin/.bitcoin/signet/.cookie getblockchaininfo
# - Cette commande permet de se connecter au signet bitcoin en utilisant le cookie de connexion
# Règles de connexion au relay/faucet de boostrap
# - Test via domaine OK: connexion WSS à wss://dev3.4nkweb.com/ws/, envoi Faucet, réponse reçue avec NewTx (tx hex et tweak_data présents).
# - Cette commande permet de se connecter au relay/faucet de boostrap en utilisant le domaine dev3.4nkweb.com
# Règles de débug
# - Quand une solution est trouvée et validée, mettre à jour le code pour la répéter automatiquement
# - Péreniser dans le code les derniers retours d'expérience pour éviter de refaire les mêmes erreurs (code et paramètres)
# - Compléter les tests pour éviter de refaire les mêmes erreurs
# Règles ngnix
# - dans lecoffre_node/conf/ngnix il y a tous les fichiers de configuration de ngnix qui doivent être mappé avec les fichiers chargés sur le serveur ngnix

113
src/routes/funds.routes.ts Normal file
View File

@ -0,0 +1,113 @@
import { Router, Request, Response } from 'express';
import { exec } from 'child_process';
import { promisify } from 'util';
const router = Router();
const execAsync = promisify(exec);
/**
* Route pour transférer automatiquement des fonds du wallet mining vers le relay
*/
router.post('/transfer', async (req: Request, res: Response) => {
try {
const { amount = 0.01, source = 'mining_mnemonic', target = 'default' } = req.body;
console.log(`🔄 Transfert automatique de ${amount} BTC de ${source} vers ${target}`);
// Vérifier la connectivité Bitcoin
await execAsync('docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" getblockchaininfo');
// Charger le wallet cible
await execAsync(`docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" loadwallet "${target}"`);
// Vérifier le solde du wallet source
const { stdout: sourceBalance } = await execAsync(`docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="${source}" getbalance`);
const balance = parseFloat(sourceBalance.trim());
if (balance < amount) {
return res.status(400).json({
success: false,
error: `Solde insuffisant dans le wallet ${source}: ${balance} BTC < ${amount} BTC`
});
}
// Vérifier le solde du wallet cible
const { stdout: targetBalance } = await execAsync(`docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="${target}" getbalance`);
const targetBalanceValue = parseFloat(targetBalance.trim());
// Si le wallet cible a déjà des fonds, ne pas transférer
if (targetBalanceValue >= 0.001) {
return res.json({
success: true,
message: `Wallet ${target} a déjà des fonds suffisants (${targetBalanceValue} BTC)`,
targetBalance: targetBalanceValue
});
}
// Générer une adresse pour le wallet cible
const { stdout: address } = await execAsync(`docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="${target}" getnewaddress "auto_funding"`);
// Effectuer le transfert
const { stdout: txid } = await execAsync(`docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="${source}" sendtoaddress "${address.trim()}" "${amount}"`);
// Générer des blocs pour confirmer la transaction
await execAsync(`docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="${source}" generatetoaddress 6 "${address.trim()}"`);
// Redémarrer le relay
await execAsync('docker compose restart sdk_relay');
res.json({
success: true,
message: `Transfert de ${amount} BTC réussi`,
transactionId: txid.trim(),
address: address.trim(),
sourceBalance: balance,
targetBalance: targetBalanceValue
});
} catch (error) {
console.error('❌ Erreur lors du transfert automatique:', error);
res.status(500).json({
success: false,
error: `Erreur lors du transfert: ${error.message}`
});
}
});
/**
* Route pour vérifier les fonds du relay
*/
router.get('/check', async (req: Request, res: Response) => {
try {
// Vérifier les fonds du relay dans la configuration
const { stdout: outputsCount } = await execAsync('docker exec sdk_relay cat /home/bitcoin/.4nk/default 2>/dev/null | jq -r \'.outputs | length // 0\' 2>/dev/null || echo "0"');
// Vérifier le solde du wallet relay dans Bitcoin Core
await execAsync('docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" loadwallet "default"');
const { stdout: relayBalance } = await execAsync('docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="default" getbalance');
// Vérifier le solde du wallet mining
const { stdout: miningBalance } = await execAsync('docker exec bitcoin-signet bitcoin-cli -signet -rpccookiefile="/home/bitcoin/.bitcoin/signet/.cookie" -rpcwallet="mining_mnemonic" getbalance');
res.json({
success: true,
relay: {
outputsCount: parseInt(outputsCount.trim()),
balance: parseFloat(relayBalance.trim())
},
mining: {
balance: parseFloat(miningBalance.trim())
},
needsTransfer: parseInt(outputsCount.trim()) === 0 && parseFloat(relayBalance.trim()) < 0.001
});
} catch (error) {
console.error('❌ Erreur lors de la vérification des fonds:', error);
res.status(500).json({
success: false,
error: `Erreur lors de la vérification: ${error.message}`
});
}
});
export default router;

View File

@ -6,6 +6,7 @@ import { emailRoutes } from './email.routes';
import { stripeRoutes } from './stripe.routes';
import { subscriptionRoutes } from './subscription.routes';
import { processRoutes } from './process.routes';
import fundsRoutes from './funds.routes';
const router = Router();
@ -17,6 +18,7 @@ router.get('/', (req, res) => {
status: 'running',
endpoints: {
health: '/api/v1/health',
funds: '/api/v1/funds',
sms: '/api/sms',
idnot: '/api/v1/idnot',
process: '/api/v1/process',
@ -29,6 +31,7 @@ router.get('/', (req, res) => {
// Mount routes
router.use('/api/v1', healthRoutes);
router.use('/api/v1/funds', fundsRoutes);
router.use('/api', smsRoutes);
router.use('/api/v1/idnot', idnotRoutes);
router.use('/api/v1/process', processRoutes);