feat: amélioration du script de démarrage et ajout des tests

- Amélioration du script start.sh pour une meilleure robustesse
- Suppression des dépendances critiques pour permettre le démarrage même si certains services ne sont pas prêts
- Ajout de vérifications WebSocket pour les relays
- Correction de la fonction hexToBlob pour gérer correctement les types ArrayBuffer
- Ajout de tests unitaires pour les fonctions de conversion hex
- Configuration Jest pour les tests
- Mise à jour de la documentation d'intégration avec 4NK_node
- Amélioration du .gitignore pour exclure les dépendances temporaires
This commit is contained in:
Nicolas Cantu 2025-08-25 20:29:24 +02:00
parent cb6826495a
commit 71b18a315f
10 changed files with 5320 additions and 2134 deletions

31
.gitignore vendored
View File

@ -4,4 +4,33 @@ Cargo.lock
node_modules/
dist/
.vscode
public/ssl/
public/ssl/
# Temporary dependencies
temp-deps/
# Test coverage
coverage/
# Environment files
.env
.env.local
.env.production
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# Editor directories and files
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@ -17,18 +17,31 @@ et ce projet adhère au [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Système de pairing entre utilisateurs
- Gestion des documents et signatures
- Chat en temps réel entre membres
- Tests unitaires pour les fonctions de conversion hex
- Documentation d'intégration avec 4NK_node
### Changed
- Migration vers la branche `docker-support`
- Optimisation du build Docker multi-stage
- Amélioration des performances de compilation
- Modernisation de l'interface utilisateur
- Amélioration du script de démarrage pour une meilleure robustesse
- Suppression des dépendances critiques pour permettre le démarrage même si certains services ne sont pas prêts
- Ajout de vérifications WebSocket pour les relays
### Fixed
- Correction des erreurs de compilation WASM
- Résolution des problèmes de dépendances TypeScript
- Correction des imports manquants dans sdk_client
- Amélioration de la gestion des erreurs
- Correction de la fonction `hexToBlob` pour gérer correctement les types ArrayBuffer
- Amélioration de la gestion des erreurs de connexion
- Correction des timeouts de démarrage
### Technical
- Ajout de tests pour les fonctions de conversion hex
- Mise à jour de la documentation d'intégration
- Amélioration des logs de démarrage
## [1.0.0] - 2025-08-25

View File

@ -1,305 +1,223 @@
# Intégration de l'Interface Utilisateur dans 4NK_node
# Intégration avec 4NK_node
Ce document décrit le processus d'intégration de l'interface utilisateur `ihm_client` dans l'infrastructure `4NK_node`.
## Vue d'ensemble
## 🎯 Objectif
Ce document décrit l'intégration de `ihm_client` dans l'infrastructure `4NK_node` et les modifications apportées pour assurer une connectivité optimale avec les services backend.
Intégrer l'interface utilisateur web dans le conteneur `4NK_node` pour fournir une interface graphique complète pour :
- Gestion des paiements silencieux
- Interaction avec les relais sdk_relay
- Monitoring de l'infrastructure Bitcoin
- Interface utilisateur pour les fonctionnalités 4NK
## Architecture d'intégration
## 📁 Fichiers d'Intégration
### Services connectés
- **SDK Relays** : Connexion WebSocket pour la synchronisation
- **Bitcoin Core** : API RPC pour les opérations blockchain
- **Blindbit Oracle** : API pour les oracles
- **Tor Proxy** : Proxy pour la confidentialité
### Nouveaux Fichiers Créés
### Ports et URLs
- Interface utilisateur : `http://localhost:8080`
- SDK Relay 1 : `ws://localhost:8090` (WebSocket)
- SDK Relay 2 : `ws://localhost:8092` (WebSocket)
- SDK Relay 3 : `ws://localhost:8094` (WebSocket)
- Bitcoin Core RPC : `http://localhost:18443`
- Blindbit Oracle : `http://localhost:8000`
- `Dockerfile.4nk-node` - Dockerfile optimisé pour l'intégration
- `nginx.4nk-node.conf` - Configuration nginx adaptée à 4NK_node
- `start-4nk-node.sh` - Script de démarrage avec vérification des services
- `docker-compose.4nk-node.yml` - Configuration Docker Compose
- `INTEGRATION_4NK_NODE.md` - Cette documentation
## Modifications du script de démarrage
## 🏗️ Architecture d'Intégration
### Changements principaux
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ ihm_client │ │ sdk_relay_1 │ │ sdk_relay_2 │
│ (Port 8080) │◄──►│ (Port 8090) │◄──►│ (Port 8091) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ ▼ ▼
│ ┌─────────────────┐ ┌─────────────────┐
│ │ sdk_relay_3 │ │ Bitcoin │
│ │ (Port 8092) │ │ (Port 18443) │
│ └─────────────────┘ └─────────────────┘
│ │ │
│ ▼ ▼
│ ┌─────────────────┐ ┌─────────────────┐
└─────────────►│ Blindbit │ │ Tor │
│ (Port 8000) │ │ (Port 9050) │
└─────────────────┘ └─────────────────┘
```
## 🚀 Démarrage Rapide
### 1. Prérequis
- Docker et Docker Compose installés
- Réseau `btcnet` créé (via 4NK_node)
- Services 4NK_node en cours d'exécution
### 2. Intégration dans 4NK_node
Le script `start.sh` a été modifié pour améliorer la robustesse et la connectivité :
#### 1. Vérification WebSocket des relays
```bash
# Depuis le répertoire 4NK_node
cd 4NK_node
# Ajouter le service ihm_client au docker-compose.yml
# Copier les fichiers d'intégration depuis ihm_client
cp ../ihm_client/Dockerfile.4nk-node ./ihm_client/
cp ../ihm_client/nginx.4nk-node.conf ./ihm_client/
cp ../ihm_client/start-4nk-node.sh ./ihm_client/
# Ajouter le service au docker-compose.yml principal
# Vérification WebSocket des relays (optionnel)
check_websocket "sdk_relay WebSocket" "$SDK_RELAY_WS_URL"
```
### 3. Configuration du docker-compose.yml principal
Ajouter le service suivant au `docker-compose.yml` de 4NK_node :
```yaml
ihm_client:
build:
context: ./ihm_client
dockerfile: Dockerfile.4nk-node
container_name: 4nk-ihm-client
ports:
- "8080:80"
environment:
- SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
- SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
- BITCOIN_RPC_URL=http://bitcoin:18443
- BLINDBIT_URL=http://blindbit:8000
volumes:
- ihm_client_logs:/var/log/nginx
networks:
- btcnet
depends_on:
- sdk_relay_1
- sdk_relay_2
- sdk_relay_3
restart: unless-stopped
```
### 4. Démarrage
#### 2. Suppression des dépendances critiques
- Les vérifications HTTP des relays ont été supprimées
- Les attentes critiques de Bitcoin Core et Blindbit ont été remplacées par des vérifications informatives
- L'interface utilisateur démarre maintenant même si certains services ne sont pas encore prêts
#### 3. Configuration dynamique
```bash
# Redémarrer l'infrastructure complète
./restart_4nk_node.sh
# Génération de la configuration dynamique
cat > /usr/share/nginx/html/config.js << EOF
window.ENV_CONFIG = {
SDK_RELAY_WS_URL: '$SDK_RELAY_WS_URL',
SDK_RELAY_HTTP_URL: '$SDK_RELAY_HTTP_URL',
BITCOIN_RPC_URL: '$BITCOIN_RPC_URL',
BLINDBIT_URL: '$BLINDBIT_URL',
ENVIRONMENT: '4nk-node'
};
EOF
```
# Ou démarrer uniquement l'interface
## Fonctionnalités de connectivité
### Reconnexion automatique
L'interface utilisateur gère automatiquement :
- La reconnexion aux WebSockets des relays
- La gestion des déconnexions temporaires
- La récupération après panne de service
### Gestion des erreurs
- Tentatives de reconnexion avec backoff exponentiel
- Logs détaillés pour le diagnostic
- Dégradation gracieuse en cas d'indisponibilité de service
## Tests de connectivité
### Test manuel des WebSockets
```bash
# Depuis le conteneur ihm_client
nc -z sdk_relay_1 8090
nc -z sdk_relay_2 8090
nc -z sdk_relay_3 8090
```
### Test de l'interface utilisateur
```bash
# Test HTTP
curl -s http://localhost:8080 | head -10
# Test de santé
curl -s http://localhost:8080/health
```
## Monitoring et logs
### Logs du conteneur
```bash
# Voir les logs de démarrage
docker logs 4nk-ihm-client
# Suivre les logs en temps réel
docker logs -f 4nk-ihm-client
```
### Métriques de santé
- Vérification périodique de nginx
- Statut des connexions WebSocket
- Disponibilité des services backend
## Dépannage
### Problèmes courants
#### 1. Interface utilisateur non accessible
```bash
# Vérifier le statut du conteneur
docker ps | grep ihm_client
# Vérifier les logs
docker logs 4nk-ihm-client --tail=20
```
#### 2. Connexion WebSocket échouée
```bash
# Vérifier la connectivité réseau
docker exec 4nk-ihm-client nc -z sdk_relay_1 8090
# Vérifier les logs des relays
docker logs sdk_relay_1 --tail=10
```
#### 3. Services backend indisponibles
```bash
# Vérifier Bitcoin Core
curl -s --user bitcoin:bitcoin http://localhost:18443
# Vérifier Blindbit
curl -s http://localhost:8000/health
```
### Solutions
#### Redémarrage du service
```bash
# Redémarrer ihm_client
docker-compose restart ihm_client
# Reconstruire et redémarrer
docker-compose build ihm_client
docker-compose up -d ihm_client
```
## 🔧 Configuration
### Variables d'Environnement
| Variable | Défaut | Description |
|----------|--------|-------------|
| `SDK_RELAY_WS_URL` | `ws://sdk_relay_1:8090` | URL WebSocket du relais principal |
| `SDK_RELAY_HTTP_URL` | `http://sdk_relay_1:8091` | URL HTTP de l'API du relais |
| `BITCOIN_RPC_URL` | `http://bitcoin:18443` | URL RPC de Bitcoin Core |
| `BLINDBIT_URL` | `http://blindbit:8000` | URL du service Blindbit |
### Ports
| Port | Service | Description |
|------|---------|-------------|
| 8080 | HTTP | Interface utilisateur principale |
| 3003 | Dev | Serveur de développement (optionnel) |
### Volumes
| Volume | Description |
|--------|-------------|
| `ihm_client_logs` | Logs nginx |
| `ihm_client_data` | Données persistantes |
## 🔌 Connectivité
### Services Intégrés
1. **sdk_relay WebSocket** (`/ws/`)
- Communication temps réel
- Synchronisation des données
- Notifications
2. **sdk_relay HTTP API** (`/api/`)
- Endpoints REST
- Gestion des paiements
- Configuration
3. **Bitcoin Core RPC** (`/bitcoin/`)
- Accès aux données blockchain
- Gestion des transactions
- Monitoring
4. **Blindbit** (`/blindbit/`)
- Filtres de paiements silencieux
- Services de validation
## 🧪 Tests d'Intégration
### Test de Connectivité
#### Nettoyage complet
```bash
# Test de l'interface principale
curl -f http://localhost:8080
# Arrêter tous les services
docker-compose down
# Test de l'API sdk_relay
curl -f http://localhost:8080/api/health
# Nettoyer les volumes (optionnel)
docker-compose down -v
# Test WebSocket
wscat -c ws://localhost:8080/ws/
# Redémarrer
docker-compose up -d
```
### Test de Fonctionnalités
## Configuration avancée
### Variables d'environnement
```bash
# Vérifier les logs
docker logs 4nk-ihm-client
# Tester la santé du conteneur
docker exec 4nk-ihm-client wget -q -O- http://localhost
# Vérifier la configuration
docker exec 4nk-ihm-client cat /usr/share/nginx/html/config.js
SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
BITCOIN_RPC_URL=http://bitcoin:18443
BLINDBIT_URL=http://blindbit:8000
```
## 🔍 Monitoring
### Personnalisation du script
Le script `start.sh` peut être modifié pour :
- Ajouter des vérifications de santé personnalisées
- Modifier les timeouts de connexion
- Ajouter des métriques de performance
### Logs
## Sécurité
```bash
# Logs en temps réel
docker logs -f 4nk-ihm-client
# Logs nginx
docker exec 4nk-ihm-client tail -f /var/log/nginx/ihm_client_access.log
docker exec 4nk-ihm-client tail -f /var/log/nginx/ihm_client_error.log
```
### Métriques
- **Disponibilité** : Healthcheck automatique
- **Performance** : Logs nginx avec métriques
- **Erreurs** : Logs d'erreur centralisés
## 🛠️ Développement
### Mode Développement
```bash
# Démarrer en mode développement
docker-compose -f docker-compose.4nk-node.yml up -d
# Rebuild après modifications
docker-compose -f docker-compose.4nk-node.yml build --no-cache ihm_client
```
### Debugging
```bash
# Accès au conteneur
docker exec -it 4nk-ihm-client sh
# Vérifier la configuration nginx
docker exec 4nk-ihm-client nginx -t
# Tester les services
docker exec 4nk-ihm-client wget -q -O- http://sdk_relay_1:8091/health
```
## 🔒 Sécurité
### Headers de Sécurité
- `X-Frame-Options: SAMEORIGIN`
- `X-Content-Type-Options: nosniff`
- `X-XSS-Protection: 1; mode=block`
- `Referrer-Policy: strict-origin-when-cross-origin`
### Isolation réseau
- L'interface utilisateur est isolée dans le réseau Docker `btcnet`
- Communication sécurisée entre conteneurs
- Pas d'exposition directe des services backend
### Authentification
- Bitcoin Core utilise l'authentification par cookie
- Les WebSockets des relays sont sécurisés
- L'interface utilisateur gère l'authentification côté client
- Bitcoin RPC : Authentification basique
- API sdk_relay : CORS configuré
- WebSocket : Validation des connexions
## 📊 Performance
## Performance
### Optimisations
- Connexions WebSocket persistantes
- Mise en cache des données fréquemment utilisées
- Compression des données transmises
- **Cache statique** : Assets avec expiration 1 an
- **Compression** : Nginx gzip activé
- **Proxy** : Connexions persistantes
- **Healthcheck** : Monitoring automatique
### Métriques
- Temps de réponse de l'interface
- Latence des WebSockets
- Utilisation des ressources
### Ressources
## Maintenance
- **CPU** : 0.5-1 core
- **RAM** : 256-512 MB
- **Stockage** : 100-200 MB
### Mises à jour
```bash
# Mettre à jour l'image
docker-compose pull ihm_client
## 🚨 Dépannage
# Reconstruire avec les dernières modifications
docker-compose build ihm_client
```
### Problèmes Courants
### Sauvegarde
```bash
# Sauvegarder la configuration
docker cp 4nk-ihm-client:/usr/share/nginx/html/config.js ./backup/
1. **Service non accessible**
```bash
# Vérifier les logs de démarrage
docker logs 4nk-ihm-client
# Sauvegarder les logs
docker logs 4nk-ihm-client > ./backup/ihm_client.log
```
# Vérifier la connectivité réseau
docker exec 4nk-ihm-client ping sdk_relay_1
```
## Support
2. **Erreurs nginx**
```bash
# Vérifier la configuration
docker exec 4nk-ihm-client nginx -t
# Redémarrer nginx
docker exec 4nk-ihm-client nginx -s reload
```
3. **Problèmes de build**
```bash
# Nettoyer et rebuilder
docker-compose down
docker system prune -f
docker-compose build --no-cache ihm_client
```
## 📈 Évolution
### Prochaines Étapes
1. **Intégration complète** dans 4NK_node
2. **Tests automatisés** d'intégration
3. **Monitoring avancé** avec métriques
4. **Interface d'administration** pour 4NK_node
5. **Documentation utilisateur** complète
### Améliorations Futures
- **Interface d'administration** pour gérer l'infrastructure
- **Dashboard de monitoring** en temps réel
- **Gestion des utilisateurs** et permissions
- **API REST** pour l'automatisation
- **Interface mobile** responsive
---
**Note** : Cette intégration est conçue pour être transparente et non intrusive dans l'infrastructure 4NK_node existante.
Pour toute question ou problème lié à l'intégration :
1. Consulter les logs du conteneur
2. Vérifier la connectivité réseau
3. Tester les services backend individuellement
4. Consulter la documentation de `4NK_node`

31
jest.config.js Normal file
View File

@ -0,0 +1,31 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
roots: ['<rootDir>/src', '<rootDir>/tests'],
testMatch: [
'**/__tests__/**/*.ts',
'**/?(*.)+(spec|test).ts'
],
transform: {
'^.+\\.ts$': 'ts-jest',
},
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.d.ts',
'!src/main.ts',
'!src/vite-env.d.ts'
],
coverageDirectory: 'coverage',
coverageReporters: ['text', 'lcov', 'html'],
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
moduleNameMapping: {
'^@/(.*)$': '<rootDir>/src/$1',
'^pkg/(.*)$': '<rootDir>/pkg/$1'
},
testTimeout: 10000,
globals: {
'ts-jest': {
tsconfig: 'tsconfig.json'
}
}
};

4914
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,11 @@
"description": "",
"main": "dist/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"test:unit": "jest --testPathPattern=tests/unit",
"test:integration": "jest --testPathPattern=tests/integration",
"build_wasm": "./scripts/setup-remote-deps.sh",
"cleanup_deps": "./scripts/cleanup-deps.sh",
"start": "vite --host 0.0.0.0",
@ -18,10 +22,16 @@
"license": "ISC",
"devDependencies": {
"@rollup/plugin-typescript": "^12.1.1",
"@types/jest": "^29.5.12",
"@types/node": "^20.11.24",
"@vitejs/plugin-vue": "^5.0.5",
"copy-webpack-plugin": "^12.0.2",
"html-webpack-plugin": "^5.6.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"prettier": "^3.3.3",
"rimraf": "^6.0.1",
"ts-jest": "^29.1.2",
"ts-loader": "^9.5.1",
"typescript": "^5.3.3",
"vite": "^5.4.11",

View File

@ -1,24 +0,0 @@
[package]
name = "sdk_client"
version = "0.1.0"
edition = "2021"
[lib]
name = "sdk_client"
crate-type = ["lib", "cdylib"]
[dependencies]
anyhow = "1.0"
serde = { version = "1.0.188", features = ["derive"] }
serde_json = "1.0"
wasm-bindgen = "0.2.91"
getrandom = { version="0.2.12", features = ["js"] }
wasm-logger = "0.2.0"
rand = "0.8.5"
tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" }
# sdk_common = { path = "../sdk_common" }
sdk_common = { git = "https://git.4nkweb.com/4nk/sdk_common.git", branch = "docker-support", features = ["blindbit-wasm"] }
serde-wasm-bindgen = "0.6.5"
[dev-dependencies]
wasm-bindgen-test = "0.3"

File diff suppressed because it is too large Load Diff

61
tests/setup.ts Normal file
View File

@ -0,0 +1,61 @@
// Configuration globale pour les tests Jest
// Mock pour les modules WASM
jest.mock('pkg/sdk_client', () => ({
__esModule: true,
default: {
init: jest.fn().mockResolvedValue(undefined),
hash_value: jest.fn().mockReturnValue('mock_hash'),
get_merkle_proof: jest.fn().mockReturnValue({ proof: 'mock_proof' }),
validate_merkle_proof: jest.fn().mockReturnValue(true),
generate_sp_wallet: jest.fn().mockReturnValue({ wallet: 'mock_wallet' }),
lock_freezed_utxos: jest.fn().mockReturnValue(true),
scan_blocks: jest.fn().mockReturnValue([]),
set_new_device: jest.fn().mockReturnValue(true),
lock_local_device: jest.fn().mockReturnValue(true),
LOCAL_DEVICE: 'mock_device'
}
}));
// Mock pour les variables d'environnement
process.env.VITE_JWT_SECRET_KEY = 'test-secret-key';
// Mock pour les APIs Web
global.fetch = jest.fn();
// Mock pour les WebSockets
global.WebSocket = jest.fn().mockImplementation(() => ({
send: jest.fn(),
close: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
readyState: 1
}));
// Mock pour localStorage
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
};
global.localStorage = localStorageMock;
// Mock pour sessionStorage
const sessionStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
};
global.sessionStorage = sessionStorageMock;
// Configuration des timeouts
jest.setTimeout(10000);
// Nettoyage après chaque test
afterEach(() => {
jest.clearAllMocks();
localStorageMock.clear();
sessionStorageMock.clear();
});

View File

@ -0,0 +1,83 @@
describe('Services - Hex Conversion', () => {
let services: Services;
beforeEach(() => {
services = new Services();
});
describe('hexToBlob', () => {
it('should convert hex string to blob correctly', () => {
const hexString = '48656c6c6f20576f726c64'; // "Hello World" in hex
const blob = services.hexToBlob(hexString);
expect(blob).toBeInstanceOf(Blob);
expect(blob.type).toBe('application/octet-stream');
expect(blob.size).toBe(11); // "Hello World" is 11 bytes
});
it('should handle empty hex string', () => {
const hexString = '';
const blob = services.hexToBlob(hexString);
expect(blob).toBeInstanceOf(Blob);
expect(blob.size).toBe(0);
});
it('should handle single byte hex string', () => {
const hexString = '41'; // 'A' in hex
const blob = services.hexToBlob(hexString);
expect(blob).toBeInstanceOf(Blob);
expect(blob.size).toBe(1);
});
});
describe('hexToUInt8Array', () => {
it('should convert hex string to Uint8Array correctly', () => {
const hexString = '48656c6c6f20576f726c64'; // "Hello World" in hex
const uint8Array = services.hexToUInt8Array(hexString);
expect(uint8Array).toBeInstanceOf(Uint8Array);
expect(uint8Array.length).toBe(11);
expect(uint8Array[0]).toBe(72); // 'H' ASCII
expect(uint8Array[10]).toBe(100); // 'd' ASCII
});
it('should throw error for odd length hex string', () => {
const hexString = '48656c6c6f20576f726c6'; // Odd length
expect(() => {
services.hexToUInt8Array(hexString);
}).toThrow('Invalid hex string: length must be even');
});
it('should handle empty hex string', () => {
const hexString = '';
const uint8Array = services.hexToUInt8Array(hexString);
expect(uint8Array).toBeInstanceOf(Uint8Array);
expect(uint8Array.length).toBe(0);
});
});
describe('blobToHex', () => {
it('should convert blob to hex string correctly', async () => {
const testData = new Uint8Array([72, 101, 108, 108, 111]); // "Hello"
const blob = new Blob([testData], { type: 'text/plain' });
const hexString = await services.blobToHex(blob);
expect(hexString).toBe('48656c6c6f');
});
it('should handle empty blob', async () => {
const blob = new Blob([], { type: 'text/plain' });
const hexString = await services.blobToHex(blob);
expect(hexString).toBe('');
});
});
});