**Motivations :** * transaction_id doit être un identifiant de transaction Bitcoin consultable sur mempool * Les UUID n'ont pas d'utilité pour identifier une transaction Bitcoin * Simplification de l'architecture en supprimant la logique de queue inutile **Root causes :** * transaction_id était généré comme UUID au lieu d'utiliser le txid Bitcoin * Logique de queue/job complexe pour gérer des identifiants temporaires * Réponse HTTP 202 alors que la transaction est créée immédiatement **Correctifs :** * transaction_id est maintenant directement le txid Bitcoin (64 hex) * Suppression complète de la logique de queue et de job (Map, cleanup, etc.) * Création immédiate de la transaction Bitcoin dans enqueue() * getStatus() interroge directement Bitcoin au lieu d'une Map en mémoire * Réponse HTTP 200 OK au lieu de 202 Accepted * Suppression de la dépendance uuid (plus utilisée) **Evolutions :** * API simplifiée : plus de queue, transactions créées directement * transaction_id consultable immédiatement sur mempool * Documentation complète des réponses JSON (API_RESPONSES.md) * Scripts de test mis à jour pour valider le format txid Bitcoin **Page affectées :** * src/services/AnchorQueueService.ts : refactor complet, suppression queue * src/controllers/AnchorController.ts : mise à jour pour txid, status 200 * src/index.ts : suppression cleanup périodique * test-api-ok.sh : validation format txid, status 200 * test-api.sh : validation format txid, status 200 * README.md : mise à jour exemples avec txid Bitcoin * API_RESPONSES.md : nouvelle documentation complète des réponses JSON
329 lines
7.6 KiB
Markdown
329 lines
7.6 KiB
Markdown
# LeCoffre Anchor API
|
|
|
|
API d'ancrage Bitcoin Signet pour LeCoffre.io, déployée sur `dev3.4nkweb.com`.
|
|
|
|
## 📦 Vue d'ensemble
|
|
|
|
Cette API autonome gère l'ancrage de hashes de documents sur la blockchain Bitcoin Signet. Elle est séparée du backend principal (`lecoffre-back-main`) pour:
|
|
|
|
- **Isolation**: Le nœud Bitcoin et l'API d'ancrage tournent sur un serveur dédié (dev3.4nkweb.com)
|
|
- **Performance**: Évite la surcharge du backend principal avec des opérations blockchain lentes
|
|
- **Sécurité**: Accès restreint par API key
|
|
- **Scalabilité**: Peut gérer une file d'attente d'ancrages indépendamment
|
|
|
|
## 🏗️ Architecture
|
|
|
|
```
|
|
lecoffre-back-main (local.4nkweb.com:3001)
|
|
│
|
|
├─── HTTP POST ───> lecoffre-anchor-api (dev3.4nkweb.com:3002)
|
|
│ │
|
|
│ ├─── JSON-RPC ───> Bitcoin Node (localhost:38332)
|
|
│ └─── Callback ───> lecoffre-back-main
|
|
│
|
|
└─── Continue processing...
|
|
```
|
|
|
|
## 🚀 Installation
|
|
|
|
### Prérequis
|
|
|
|
- Node.js >= 18
|
|
- Bitcoin Core node (Signet) configuré avec JSON-RPC
|
|
- Accès au fichier cookie Bitcoin (`.cookie`)
|
|
|
|
### 1. Installer les dépendances
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
### 2. Configuration
|
|
|
|
Copier `.env.example` vers `.env` et configurer:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
nano .env
|
|
```
|
|
|
|
Variables importantes:
|
|
```env
|
|
PORT=3002
|
|
API_KEY=your-secure-api-key-here # Générer avec uuidv4
|
|
BITCOIN_COOKIE_PATH=/home/bitcoin/.4nk/.cookie
|
|
CORS_ORIGINS=http://local.4nkweb.com:3001
|
|
```
|
|
|
|
### 3. Build
|
|
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
### 4. Démarrer l'API
|
|
|
|
```bash
|
|
# Production
|
|
npm start
|
|
|
|
# Développement (avec auto-reload)
|
|
npm run dev
|
|
```
|
|
|
|
## 📡 Endpoints API
|
|
|
|
### Health Check
|
|
```bash
|
|
GET /health
|
|
```
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"ok": true,
|
|
"service": "anchor-api",
|
|
"bitcoin": {
|
|
"connected": true,
|
|
"blocks": 245678
|
|
},
|
|
"timestamp": "2025-10-17T14:00:00.000Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Ancrer un document
|
|
```bash
|
|
POST /api/anchor/document
|
|
Headers:
|
|
x-api-key: your-secure-api-key
|
|
Content-Type: application/json
|
|
|
|
Body:
|
|
{
|
|
"documentUid": "uuid-of-document",
|
|
"hash": "64-char-hex-hash",
|
|
"callback_url": "http://local.4nkweb.com:3001/api/v1/anchors/callback"
|
|
}
|
|
```
|
|
|
|
**Response** (200 OK):
|
|
```json
|
|
{
|
|
"transaction_id": "7b6f473879b3993812bc5eda39d801c1fd3f918cd35c9f6d922f1c3e95db9825",
|
|
"status": "pending",
|
|
"confirmations": 0,
|
|
"block_height": null,
|
|
"txid": "7b6f473879b3993812bc5eda39d801c1fd3f918cd35c9f6d922f1c3e95db9825",
|
|
"hash": "64-char-hex-hash",
|
|
"documentUid": "uuid-of-document",
|
|
"explorer_url": "https://mempool2.4nkweb.com/fr/tx/7b6f473879b3993812bc5eda39d801c1fd3f918cd35c9f6d922f1c3e95db9825",
|
|
"context": {
|
|
"network": "Bitcoin Signet",
|
|
"explorer": "mempool2.4nkweb.com",
|
|
"api_version": "1.0.0",
|
|
"request_timestamp": "2025-11-14T10:30:00.000Z",
|
|
"document_uid": "uuid-of-document",
|
|
"hash": "64-char-hex-hash",
|
|
"status": "pending"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Note** : Le `transaction_id` est maintenant directement le `txid` Bitcoin (64 hex), consultable sur mempool.
|
|
|
|
---
|
|
|
|
### Vérifier le statut d'un ancrage
|
|
```bash
|
|
GET /api/anchor/status/:transactionId
|
|
Headers:
|
|
x-api-key: your-secure-api-key
|
|
```
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"transaction_id": "7b6f473879b3993812bc5eda39d801c1fd3f918cd35c9f6d922f1c3e95db9825",
|
|
"status": "confirmed",
|
|
"confirmations": 6,
|
|
"block_height": 245680,
|
|
"txid": "7b6f473879b3993812bc5eda39d801c1fd3f918cd35c9f6d922f1c3e95db9825",
|
|
"hash": "64-char-hex-hash",
|
|
"documentUid": "uuid-of-document",
|
|
"explorer_url": "https://mempool2.4nkweb.com/fr/tx/7b6f473879b3993812bc5eda39d801c1fd3f918cd35c9f6d922f1c3e95db9825",
|
|
"network": "signet",
|
|
"timestamp": "2025-11-14T10:25:00.000Z",
|
|
"fee": -0.00000234,
|
|
"size": 250,
|
|
"anchor_info": {
|
|
"hash": "64-char-hex-hash",
|
|
"document_uid": "uuid-of-document",
|
|
"op_return_data": "64-char-hex-hash",
|
|
"anchored_at": "2025-11-14T10:25:00.000Z",
|
|
"block_height": 245680,
|
|
"confirmations": 6,
|
|
"explorer_url": "https://mempool2.4nkweb.com/fr/tx/7b6f473879b3993812bc5eda39d801c1fd3f918cd35c9f6d922f1c3e95db9825",
|
|
"network": "signet"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Note** : Le `transaction_id` est le `txid` Bitcoin, directement consultable sur mempool.
|
|
|
|
---
|
|
|
|
### Vérifier si un hash est ancré
|
|
```bash
|
|
POST /api/anchor/verify
|
|
Headers:
|
|
x-api-key: your-secure-api-key
|
|
Content-Type: application/json
|
|
|
|
Body:
|
|
{
|
|
"hash": "64-char-hex-hash",
|
|
"txid": "bitcoin-transaction-id" # optionnel
|
|
}
|
|
```
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"verified": true,
|
|
"anchor_info": {
|
|
"transaction_id": "txid",
|
|
"block_height": 245680,
|
|
"confirmations": 6,
|
|
"timestamp": "2025-10-17T14:00:00.000Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
## 🔧 Intégration avec lecoffre-back-main
|
|
|
|
### 1. Configuration backend
|
|
|
|
Dans `lecoffre-back-main/.env`:
|
|
```env
|
|
ANCHOR_API_URL=http://dev3.4nkweb.com:3002
|
|
ANCHOR_API_KEY=your-secure-api-key
|
|
```
|
|
|
|
### 2. Modifier BitcoinSignetService
|
|
|
|
Au lieu d'appeler directement le nœud Bitcoin, faire des appels HTTP vers l'API d'ancrage:
|
|
|
|
```typescript
|
|
// Ancien (direct Bitcoin RPC)
|
|
const txid = await this.rpcCall('sendrawtransaction', [signedTx.hex]);
|
|
|
|
// Nouveau (via Anchor API)
|
|
const response = await fetch(`${ANCHOR_API_URL}/api/anchor/document`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'x-api-key': ANCHOR_API_KEY,
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
documentUid: document.uid,
|
|
hash: documentHash,
|
|
callback_url: `${LECOFFRE_BACK_URL}/api/v1/anchors/callback`
|
|
})
|
|
});
|
|
```
|
|
|
|
## 🔒 Sécurité
|
|
|
|
- **API Key**: Toutes les routes `/api/*` nécessitent un header `x-api-key`
|
|
- **CORS**: Restreint aux origines configurées
|
|
- **Rate Limiting**: 100 requêtes/minute par défaut
|
|
- **Helmet**: Headers de sécurité HTTP
|
|
|
|
## 📊 Logs
|
|
|
|
Logs écrits dans `./logs/anchor-api.log` (configurable via `LOG_FILE_PATH`).
|
|
|
|
Niveaux de log:
|
|
- `error`: Erreurs critiques
|
|
- `warn`: Avertissements
|
|
- `info`: Informations générales
|
|
- `debug`: Détails de debug
|
|
|
|
## 🛠️ Déploiement
|
|
|
|
### PM2 (production)
|
|
|
|
```bash
|
|
pm2 start dist/index.js --name lecoffre-anchor-api
|
|
pm2 save
|
|
```
|
|
|
|
### Docker (optionnel)
|
|
|
|
```dockerfile
|
|
FROM node:18-alpine
|
|
WORKDIR /app
|
|
COPY package*.json ./
|
|
RUN npm ci --only=production
|
|
COPY dist ./dist
|
|
EXPOSE 3002
|
|
CMD ["node", "dist/index.js"]
|
|
```
|
|
|
|
## 📝 Maintenance
|
|
|
|
### Architecture simplifiée
|
|
|
|
L'API ne gère plus de queue en mémoire. Les transactions Bitcoin sont créées immédiatement et le `transaction_id` retourné est directement le `txid` Bitcoin, consultable sur mempool.
|
|
|
|
### Monitoring
|
|
|
|
- Health check: `curl http://dev3.4nkweb.com:3002/health`
|
|
- PM2 logs: `pm2 logs lecoffre-anchor-api`
|
|
- Logs fichier: `tail -f logs/anchor-api.log`
|
|
|
|
## 🚨 Troubleshooting
|
|
|
|
### Erreur "Bitcoin cookie file not accessible"
|
|
|
|
```bash
|
|
# Vérifier les permissions
|
|
ls -l /home/bitcoin/.4nk/.cookie
|
|
|
|
# Donner accès au user de l'API
|
|
sudo chmod 644 /home/bitcoin/.4nk/.cookie
|
|
# OU ajouter le user au groupe bitcoin
|
|
sudo usermod -a -G bitcoin debian
|
|
```
|
|
|
|
### Erreur "No unspent outputs available"
|
|
|
|
Le wallet Bitcoin n'a pas de fonds. Envoyer des tBTC Signet au wallet:
|
|
|
|
```bash
|
|
bitcoin-cli -signet getnewaddress
|
|
# Utiliser un faucet Signet pour obtenir des tBTC
|
|
```
|
|
|
|
### Callback échoue
|
|
|
|
Vérifier que `lecoffre-back-main` est accessible depuis `dev3.4nkweb.com`:
|
|
|
|
```bash
|
|
curl -I http://local.4nkweb.com:3001/api/v1/public/health
|
|
```
|
|
|
|
## 📚 Documentation supplémentaire
|
|
|
|
- Bitcoin Signet: https://en.bitcoin.it/wiki/Signet
|
|
- Bitcoin RPC API: https://developer.bitcoin.org/reference/rpc/
|
|
- OP_RETURN: https://en.bitcoin.it/wiki/OP_RETURN
|
|
|
|
## 📞 Support
|
|
|
|
Pour toute question ou problème, consulter:
|
|
- `/todo/TODO6_IMPLEMENTATION_COMPLETE.md` (backend principal)
|
|
- Logs: `pm2 logs lecoffre-anchor-api`
|