**Motivations:** - Mettre à jour la documentation pour refléter les nouvelles fonctionnalités UTXO - Documenter les nouvelles routes API - Expliquer les fonctionnalités de pagination, tri et consolidation **Root causes:** - La documentation n'était pas à jour avec les nouvelles fonctionnalités - Les nouvelles routes API n'étaient pas documentées - Les utilisateurs n'étaient pas informés des nouvelles capacités **Correctifs:** - Mise à jour de learn.html avec section sur la gestion des UTXOs - Ajout de la documentation des nouvelles routes API dans api-docs.html - Mise à jour de docs/DASHBOARD.md avec les nouvelles fonctionnalités **Evolutions:** - learn.html : Section sur la gestion des UTXOs (pagination, tri, consolidation, capacité d'ancrage) - api-docs.html : Documentation des routes : - GET /api/utxo/list : Liste des UTXOs avec compteurs - GET /api/utxo/small-info : Infos sur les petits UTXOs - POST /api/utxo/consolidate : Consolidation des petits UTXOs - Documentation de l'erreur "too-long-mempool-chain" (503) - docs/DASHBOARD.md : Mise à jour de la section UTXO avec pagination, tri, consolidation, capacité d'ancrage restante **Pages affectées:** - signet-dashboard/public/learn.html: Section gestion des UTXOs - signet-dashboard/public/api-docs.html: Documentation des nouvelles routes API et erreur too-long-mempool-chain - docs/DASHBOARD.md: Mise à jour fonctionnalités UTXO et endpoints
1250 lines
54 KiB
HTML
1250 lines
54 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Documentation API d'Ancrage - Bitcoin Ancrage</title>
|
||
<link rel="stylesheet" href="styles.css">
|
||
<style>
|
||
.api-docs-section {
|
||
margin-bottom: 40px;
|
||
}
|
||
|
||
.endpoint-card {
|
||
background: var(--card-background);
|
||
padding: 30px;
|
||
border-radius: 10px;
|
||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.endpoint-header {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
padding-bottom: 15px;
|
||
border-bottom: 2px solid var(--border-color);
|
||
}
|
||
|
||
.method-badge {
|
||
display: inline-block;
|
||
padding: 5px 15px;
|
||
border-radius: 5px;
|
||
font-weight: bold;
|
||
font-size: 0.9em;
|
||
margin-right: 15px;
|
||
min-width: 70px;
|
||
text-align: center;
|
||
}
|
||
|
||
.method-get {
|
||
background: #28a745;
|
||
color: white;
|
||
}
|
||
|
||
.method-post {
|
||
background: #007bff;
|
||
color: white;
|
||
}
|
||
|
||
.endpoint-path {
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 1.2em;
|
||
color: var(--primary-color);
|
||
font-weight: bold;
|
||
}
|
||
|
||
.endpoint-description {
|
||
margin: 20px 0;
|
||
color: var(--text-color);
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.endpoint-params {
|
||
margin: 20px 0;
|
||
}
|
||
|
||
.endpoint-params h4 {
|
||
color: var(--primary-color);
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.param-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin: 15px 0;
|
||
}
|
||
|
||
.param-table th,
|
||
.param-table td {
|
||
padding: 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid var(--border-color);
|
||
}
|
||
|
||
.param-table th {
|
||
background: #f5f5f5;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.param-name {
|
||
font-family: 'Courier New', monospace;
|
||
color: var(--primary-color);
|
||
font-weight: bold;
|
||
}
|
||
|
||
.param-required {
|
||
color: var(--error-color);
|
||
font-weight: bold;
|
||
}
|
||
|
||
.param-optional {
|
||
color: #666;
|
||
}
|
||
|
||
.code-block {
|
||
background: #1e1e1e;
|
||
color: #d4d4d4;
|
||
padding: 20px;
|
||
border-radius: 5px;
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 0.9em;
|
||
line-height: 1.6;
|
||
overflow-x: auto;
|
||
margin: 20px 0;
|
||
}
|
||
|
||
.code-block pre {
|
||
margin: 0;
|
||
white-space: pre-wrap;
|
||
word-wrap: break-word;
|
||
}
|
||
|
||
.response-example {
|
||
margin: 20px 0;
|
||
}
|
||
|
||
.response-example h4 {
|
||
color: var(--primary-color);
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.info-box {
|
||
background: #e7f3ff;
|
||
border-left: 4px solid #2196F3;
|
||
padding: 15px;
|
||
margin: 20px 0;
|
||
border-radius: 5px;
|
||
}
|
||
|
||
.warning-box {
|
||
background: #fff3cd;
|
||
border-left: 4px solid #ffc107;
|
||
padding: 15px;
|
||
margin: 20px 0;
|
||
border-radius: 5px;
|
||
}
|
||
|
||
.error-box {
|
||
background: #f8d7da;
|
||
border-left: 4px solid #dc3545;
|
||
padding: 15px;
|
||
margin: 20px 0;
|
||
border-radius: 5px;
|
||
}
|
||
|
||
.auth-section {
|
||
background: var(--card-background);
|
||
padding: 30px;
|
||
border-radius: 10px;
|
||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.copy-button {
|
||
background: var(--primary-color);
|
||
color: white;
|
||
border: none;
|
||
padding: 8px 15px;
|
||
border-radius: 5px;
|
||
cursor: pointer;
|
||
font-size: 0.9em;
|
||
margin-top: 10px;
|
||
transition: background 0.3s;
|
||
}
|
||
|
||
.copy-button:hover {
|
||
background: #e0820d;
|
||
}
|
||
|
||
.status-code {
|
||
display: inline-block;
|
||
padding: 3px 8px;
|
||
border-radius: 3px;
|
||
font-size: 0.85em;
|
||
font-weight: bold;
|
||
margin-right: 10px;
|
||
}
|
||
|
||
.status-200 {
|
||
background: #28a745;
|
||
color: white;
|
||
}
|
||
|
||
.status-400 {
|
||
background: #ffc107;
|
||
color: #000;
|
||
}
|
||
|
||
.status-401 {
|
||
background: #dc3545;
|
||
color: white;
|
||
}
|
||
|
||
.status-402 {
|
||
background: #ff9800;
|
||
color: white;
|
||
}
|
||
|
||
.status-500 {
|
||
background: #dc3545;
|
||
color: white;
|
||
}
|
||
|
||
.status-503 {
|
||
background: #ff9800;
|
||
color: white;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<a href="/" class="back-link">← Retour au Dashboard</a>
|
||
|
||
<header>
|
||
<h1>Documentation API d'Ancrage</h1>
|
||
<p class="subtitle">API REST pour ancrer et vérifier des documents sur Bitcoin Signet, et utiliser le faucet</p>
|
||
</header>
|
||
|
||
<main>
|
||
<!-- Section Authentification -->
|
||
<section class="api-docs-section">
|
||
<div class="auth-section">
|
||
<h2>🔐 Authentification</h2>
|
||
<p>Toutes les requêtes vers l'API d'ancrage (sauf les endpoints publics) nécessitent une clé API dans le header <code>X-API-Key</code>.</p>
|
||
|
||
<div class="code-block">
|
||
<pre>X-API-Key: votre-clé-api-ici</pre>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<p><strong>Endpoints publics (sans authentification) :</strong></p>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li><code>GET /health</code> - Vérification de santé (API d'ancrage)</li>
|
||
<li><code>GET /api/anchor/locked-utxos</code> - Liste des UTXO verrouillés</li>
|
||
<li><code>GET /health</code> - Vérification de santé (API faucet)</li>
|
||
</ul>
|
||
<p style="margin-top: 10px;"><strong>Endpoints nécessitant une clé API :</strong></p>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li><code>POST /api/anchor/document</code> - Ancrer un document</li>
|
||
<li><code>POST /api/anchor/verify</code> - Vérifier un hash</li>
|
||
<li><code>POST /api/faucet/request</code> - Demander des sats</li>
|
||
<li><code>POST /api/watermark/document</code> - Ajouter un filigrane et ancrer un document</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="warning-box">
|
||
<p><strong>⚠️ Important :</strong> Conservez votre clé API secrète et ne la partagez jamais publiquement.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Endpoint: Health -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<div class="endpoint-header">
|
||
<span class="method-badge method-get">GET</span>
|
||
<span class="endpoint-path">/health</span>
|
||
</div>
|
||
|
||
<div class="endpoint-description">
|
||
<p>Vérifie l'état de santé de l'API. Cet endpoint est public et ne nécessite pas d'authentification.</p>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK)</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"ok": true,
|
||
"service": "anchor-api",
|
||
"bitcoin": {
|
||
"connected": true,
|
||
"blocks": 12345
|
||
},
|
||
"timestamp": "2026-01-25T12:00:00.000Z"
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (503 Service Unavailable) - Bitcoin non connecté</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"ok": false,
|
||
"service": "anchor-api",
|
||
"error": "Bitcoin RPC connection failed",
|
||
"timestamp": "2026-01-25T12:00:00.000Z"
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Endpoint: Anchor Document -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<div class="endpoint-header">
|
||
<span class="method-badge method-post">POST</span>
|
||
<span class="endpoint-path">/api/anchor/document</span>
|
||
</div>
|
||
|
||
<div class="endpoint-description">
|
||
<p>Ancre un document sur la blockchain Bitcoin Signet en créant une transaction qui inclut le hash du document dans un OP_RETURN.</p>
|
||
</div>
|
||
|
||
<div class="endpoint-params">
|
||
<h4>Paramètres (Body JSON)</h4>
|
||
<table class="param-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Paramètre</th>
|
||
<th>Type</th>
|
||
<th>Requis</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td class="param-name">hash</td>
|
||
<td>string</td>
|
||
<td><span class="param-required">Oui</span></td>
|
||
<td>Hash SHA256 du document en hexadécimal (64 caractères)</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">documentUid</td>
|
||
<td>string</td>
|
||
<td><span class="param-optional">Non</span></td>
|
||
<td>Identifiant optionnel du document (pour le logging)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Exemple de requête</h4>
|
||
<div class="code-block">
|
||
<pre>curl -X POST https://certificator.4nkweb.com/api/anchor/document \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: votre-clé-api" \
|
||
-d '{
|
||
"hash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
|
||
"documentUid": "doc-12345"
|
||
}'</pre>
|
||
</div>
|
||
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK)</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"txid": "abc123def456...",
|
||
"status": "pending",
|
||
"confirmations": 0,
|
||
"block_height": null
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Codes de statut possibles</h4>
|
||
<ul style="margin-left: 20px;">
|
||
<li><span class="status-code status-200">200</span> Succès - Transaction créée et envoyée au mempool</li>
|
||
<li><span class="status-code status-400">400</span> Requête invalide - Hash manquant ou format incorrect</li>
|
||
<li><span class="status-code status-401">401</span> Non autorisé - Clé API manquante ou invalide</li>
|
||
<li><span class="status-code status-402">402</span> Solde insuffisant - Pas assez de fonds pour créer la transaction</li>
|
||
<li><span class="status-code status-503">503</span> Service indisponible - Erreur "too-long-mempool-chain" (trop d'ancêtres non confirmés)</li>
|
||
<li><span class="status-code status-500">500</span> Erreur serveur - Erreur interne lors de la création de la transaction</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="error-box">
|
||
<h4>Exemple d'erreur (402 Payment Required)</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"error": "Insufficient Balance",
|
||
"message": "Insufficient balance to create anchor transaction"
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="error-box">
|
||
<h4>Exemple d'erreur (503 Service Unavailable) - Too Long Mempool Chain</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"error": "Service Unavailable",
|
||
"message": "too-long-mempool-chain, too many unconfirmed ancestors [limit: 25]"
|
||
}</pre>
|
||
</div>
|
||
<p style="margin-top: 10px;">Cette erreur se produit lorsque l'API tente d'utiliser un UTXO non confirmé qui a trop d'ancêtres non confirmés dans le mempool. Bitcoin Core limite la chaîne d'ancêtres à 25 transactions pour éviter les attaques par spam.</p>
|
||
<p><strong>Solution :</strong> L'API utilise maintenant uniquement des UTXOs confirmés (au moins 1 confirmation) pour éviter cette erreur. Attendez qu'un bloc soit miné pour que les UTXOs soient confirmés.</p>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>ℹ️ Gestion des UTXOs</h4>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>L'API utilise uniquement des UTXOs <strong>confirmés</strong> (au moins 1 confirmation) pour éviter les erreurs "too-long-mempool-chain"</li>
|
||
<li>Les UTXOs non confirmés sont automatiquement exclus de la sélection</li>
|
||
<li>Chaque transaction d'ancrage provisionne automatiquement 7 UTXOs de 2500 sats pour les ancrages futurs</li>
|
||
<li>Les UTXOs provisionnés deviendront utilisables après confirmation dans un bloc</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Endpoint: Verify -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<div class="endpoint-header">
|
||
<span class="method-badge method-post">POST</span>
|
||
<span class="endpoint-path">/api/anchor/verify</span>
|
||
</div>
|
||
|
||
<div class="endpoint-description">
|
||
<p>Vérifie si un hash est ancré sur la blockchain Bitcoin Signet. Recherche dans les transactions OP_RETURN pour trouver le hash.</p>
|
||
</div>
|
||
|
||
<div class="endpoint-params">
|
||
<h4>Paramètres (Body JSON)</h4>
|
||
<table class="param-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Paramètre</th>
|
||
<th>Type</th>
|
||
<th>Requis</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td class="param-name">hash</td>
|
||
<td>string</td>
|
||
<td><span class="param-required">Oui</span></td>
|
||
<td>Hash SHA256 à vérifier (64 caractères hex)</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">txid</td>
|
||
<td>string</td>
|
||
<td><span class="param-optional">Non</span></td>
|
||
<td>ID de transaction optionnel pour accélérer la recherche</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Exemple de requête</h4>
|
||
<div class="code-block">
|
||
<pre>curl -X POST https://certificator.4nkweb.com/api/anchor/verify \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: votre-clé-api" \
|
||
-d '{
|
||
"hash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
|
||
"txid": "abc123def456..."
|
||
}'</pre>
|
||
</div>
|
||
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK) - Hash trouvé</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"found": true,
|
||
"txid": "abc123def456...",
|
||
"block_height": 12345,
|
||
"confirmations": 100,
|
||
"timestamp": "2026-01-25T10:00:00.000Z"
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK) - Hash non trouvé</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"found": false,
|
||
"txid": null,
|
||
"block_height": null,
|
||
"confirmations": null,
|
||
"timestamp": null
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Codes de statut possibles</h4>
|
||
<ul style="margin-left: 20px;">
|
||
<li><span class="status-code status-200">200</span> Succès - Vérification effectuée</li>
|
||
<li><span class="status-code status-400">400</span> Requête invalide - Hash manquant ou format incorrect</li>
|
||
<li><span class="status-code status-401">401</span> Non autorisé - Clé API manquante ou invalide</li>
|
||
<li><span class="status-code status-500">500</span> Erreur serveur - Erreur interne lors de la vérification</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Endpoint: Locked UTXOs -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<div class="endpoint-header">
|
||
<span class="method-badge method-get">GET</span>
|
||
<span class="endpoint-path">/api/anchor/locked-utxos</span>
|
||
</div>
|
||
|
||
<div class="endpoint-description">
|
||
<p>Retourne la liste des UTXO actuellement verrouillés par le mutex de l'API. Cet endpoint est public et ne nécessite pas d'authentification.</p>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Exemple de requête</h4>
|
||
<div class="code-block">
|
||
<pre>curl -X GET https://certificator.4nkweb.com/api/anchor/locked-utxos</pre>
|
||
</div>
|
||
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK)</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"locked": [
|
||
{
|
||
"txid": "abc123def456...",
|
||
"vout": 0
|
||
},
|
||
{
|
||
"txid": "def456abc123...",
|
||
"vout": 1
|
||
}
|
||
],
|
||
"count": 2
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Endpoint: Faucet Request -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<div class="endpoint-header">
|
||
<span class="method-badge method-post">POST</span>
|
||
<span class="endpoint-path">/api/faucet/request</span>
|
||
</div>
|
||
|
||
<div class="endpoint-description">
|
||
<p>Demande des sats (testnet coins) via le faucet. Distribue 50 000 sats (0.0005 BTC) par défaut sur une adresse Bitcoin Signet valide. Nécessite une clé API valide dans le header <code>x-api-key</code>.</p>
|
||
</div>
|
||
|
||
<div class="endpoint-params">
|
||
<h4>Paramètres (Body JSON)</h4>
|
||
<table class="param-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Paramètre</th>
|
||
<th>Type</th>
|
||
<th>Requis</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td class="param-name">address</td>
|
||
<td>string</td>
|
||
<td><span class="param-required">Oui</span></td>
|
||
<td>Adresse Bitcoin Signet valide (commence par <code>tb1</code>, <code>bcrt1</code>, <code>2</code> ou <code>3</code>)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Exemple de requête</h4>
|
||
<div class="code-block">
|
||
<pre>curl -X POST https://certificator.4nkweb.com/api/faucet/request \
|
||
-H "Content-Type: application/json" \
|
||
-H "x-api-key: votre-clé-api" \
|
||
-d '{
|
||
"address": "tb1qwe0nv3s0ewedd63w20r8kwnv22uw8dp2tnj3qc"
|
||
}'</pre>
|
||
</div>
|
||
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK)</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"success": true,
|
||
"txid": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890",
|
||
"address": "tb1qwe0nv3s0ewedd63w20r8kwnv22uw8dp2tnj3qc",
|
||
"amount": 0.0005,
|
||
"amount_sats": 50000,
|
||
"status": "pending",
|
||
"confirmations": 0,
|
||
"block_height": null
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Codes de statut possibles</h4>
|
||
<ul style="margin-left: 20px;">
|
||
<li><span class="status-code status-200">200</span> Succès - Transaction créée et envoyée au mempool</li>
|
||
<li><span class="status-code status-400">400</span> Requête invalide - Adresse manquante ou format incorrect</li>
|
||
<li><span class="status-code status-401">401</span> Non autorisé - Clé API manquante ou invalide</li>
|
||
<li><span class="status-code status-503">503</span> Service indisponible - Solde insuffisant dans le wallet du faucet</li>
|
||
<li><span class="status-code status-500">500</span> Erreur serveur - Erreur interne lors de la création de la transaction</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="error-box">
|
||
<h4>Exemple d'erreur (401 Unauthorized)</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"error": "Unauthorized",
|
||
"message": "Invalid or missing API key"
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="error-box">
|
||
<h4>Exemple d'erreur (503 Service Unavailable)</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"error": "Insufficient Balance",
|
||
"message": "Insufficient balance to send coins"
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>ℹ️ Notes importantes</h4>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>Le montant par défaut est de 50 000 sats (0.0005 BTC)</li>
|
||
<li>L'adresse doit être une adresse Bitcoin Signet valide</li>
|
||
<li>La transaction est envoyée au mempool immédiatement</li>
|
||
<li>Le statut "pending" signifie que la transaction est dans le mempool mais pas encore confirmée</li>
|
||
<li>Les confirmations augmentent à mesure que les blocs sont minés</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Endpoint: Watermark Document -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<div class="endpoint-header">
|
||
<span class="method-badge method-post">POST</span>
|
||
<span class="endpoint-path">/api/watermark/document</span>
|
||
</div>
|
||
|
||
<div class="endpoint-description">
|
||
<p>Ajoute un filigrane à un document, le convertit en PDF, et l'ancre sur la blockchain Bitcoin Signet. Les fichiers sont automatiquement scannés avec ClamAV avant traitement.</p>
|
||
</div>
|
||
|
||
<div class="endpoint-params">
|
||
<h4>Paramètres (Body JSON)</h4>
|
||
<table class="param-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Paramètre</th>
|
||
<th>Type</th>
|
||
<th>Requis</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td class="param-name">apiKey</td>
|
||
<td>string</td>
|
||
<td><span class="param-required">Oui</span></td>
|
||
<td>Clé API pour l'authentification (peut aussi être dans le header <code>X-API-Key</code>)</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">fileData</td>
|
||
<td>string</td>
|
||
<td><span class="param-optional">Conditionnel</span></td>
|
||
<td>Fichier encodé en base64 (requis si <code>textContent</code> n'est pas fourni)</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">fileName</td>
|
||
<td>string</td>
|
||
<td><span class="param-optional">Non</span></td>
|
||
<td>Nom du fichier (requis si <code>fileData</code> est fourni)</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">mimeType</td>
|
||
<td>string</td>
|
||
<td><span class="param-optional">Non</span></td>
|
||
<td>Type MIME du fichier (requis si <code>fileData</code> est fourni)</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">textContent</td>
|
||
<td>string</td>
|
||
<td><span class="param-optional">Conditionnel</span></td>
|
||
<td>Contenu texte à convertir en PDF (requis si <code>fileData</code> n'est pas fourni)</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">watermarkOptions</td>
|
||
<td>object</td>
|
||
<td><span class="param-required">Oui</span></td>
|
||
<td>Options de filigrane (voir détails ci-dessous)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>Structure de watermarkOptions</h4>
|
||
<table class="param-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Paramètre</th>
|
||
<th>Type</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td class="param-name">enabled</td>
|
||
<td>boolean</td>
|
||
<td>Doit être <code>true</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">text</td>
|
||
<td>string</td>
|
||
<td>Texte libre du filigrane (optionnel)</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">signature</td>
|
||
<td>string</td>
|
||
<td>Signature cryptographique (optionnel)</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">depositor</td>
|
||
<td>string</td>
|
||
<td>Nom du dépositaire (optionnel)</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">dateUTC</td>
|
||
<td>boolean</td>
|
||
<td>Ajouter la date UTC dans le filigrane</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">dateLocal</td>
|
||
<td>boolean</td>
|
||
<td>Ajouter la date locale dans le filigrane</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">blockNumber</td>
|
||
<td>boolean</td>
|
||
<td>Ajouter le numéro de bloc dans le filigrane</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">blockHash</td>
|
||
<td>boolean</td>
|
||
<td>Ajouter le hash du bloc dans le filigrane</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">documentHash</td>
|
||
<td>boolean</td>
|
||
<td>Ajouter le hash du document d'origine dans le filigrane</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Exemple de requête</h4>
|
||
<div class="code-block">
|
||
<pre>curl -X POST https://watermark.certificator.4nkweb.com/api/watermark/document \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: votre-clé-api" \
|
||
-d '{
|
||
"apiKey": "votre-clé-api",
|
||
"fileData": "base64_encoded_file_data",
|
||
"fileName": "document.pdf",
|
||
"mimeType": "application/pdf",
|
||
"watermarkOptions": {
|
||
"enabled": true,
|
||
"text": "Document confidentiel",
|
||
"depositor": "John Doe",
|
||
"dateUTC": true,
|
||
"dateLocal": true,
|
||
"blockNumber": true,
|
||
"documentHash": true
|
||
}
|
||
}'</pre>
|
||
</div>
|
||
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK)</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"success": true,
|
||
"antivirusScan": {
|
||
"scanned": true,
|
||
"clean": true,
|
||
"infected": false,
|
||
"viruses": [],
|
||
"error": null
|
||
},
|
||
"original": {
|
||
"txid": "abc123def456...",
|
||
"status": "pending",
|
||
"confirmations": 0,
|
||
"hash": "a1b2c3d4e5f6...",
|
||
"file": {
|
||
"name": "document.pdf",
|
||
"extension": "pdf",
|
||
"data": "base64_encoded_pdf"
|
||
}
|
||
},
|
||
"watermarked": {
|
||
"txid": "def456abc123...",
|
||
"status": "pending",
|
||
"confirmations": 0,
|
||
"hash": "b2c3d4e5f6a1...",
|
||
"file": {
|
||
"name": "document.pdf",
|
||
"extension": "pdf",
|
||
"data": "base64_encoded_pdf"
|
||
}
|
||
},
|
||
"certificate": {
|
||
"name": "certificat-document.pdf",
|
||
"extension": "pdf",
|
||
"data": "base64_encoded_pdf"
|
||
},
|
||
"merged": {
|
||
"name": "document-avec-certificat.pdf",
|
||
"extension": "pdf",
|
||
"data": "base64_encoded_pdf"
|
||
}
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Codes de statut possibles</h4>
|
||
<ul style="margin-left: 20px;">
|
||
<li><span class="status-code status-200">200</span> Succès - Document filigrané et ancré</li>
|
||
<li><span class="status-code status-400">400</span> Requête invalide - Fichier infecté, paramètres manquants ou incorrects</li>
|
||
<li><span class="status-code status-401">401</span> Non autorisé - Clé API manquante ou invalide</li>
|
||
<li><span class="status-code status-500">500</span> Erreur serveur - Erreur interne lors du traitement</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="error-box">
|
||
<h4>Exemple d'erreur (400 Bad Request) - Fichier infecté</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"error": "Bad Request",
|
||
"message": "File contains viruses",
|
||
"viruses": ["Trojan.Example"],
|
||
"antivirusScan": {
|
||
"scanned": true,
|
||
"clean": false,
|
||
"infected": true,
|
||
"viruses": ["Trojan.Example"],
|
||
"error": null
|
||
}
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>ℹ️ Notes importantes</h4>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>Tous les fichiers sont automatiquement scannés avec ClamAV avant traitement</li>
|
||
<li>Les fichiers infectés sont rejetés avec une erreur 400</li>
|
||
<li>Si ClamAV est indisponible, le traitement continue en mode dégradé (antivirusScan.scanned = false)</li>
|
||
<li>Le résultat inclut 4 fichiers PDF : original, filigrané, certificat, et fusionné (filigrané + certificat)</li>
|
||
<li>Les fichiers sont retournés en base64 dans le champ <code>data</code></li>
|
||
<li>Les TXID sont des liens cliquables vers mempool.4nkweb.com dans les résultats</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Endpoint: ClamAV Scan -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<div class="endpoint-header">
|
||
<span class="method-badge method-post">POST</span>
|
||
<span class="endpoint-path">/api/scan/buffer</span>
|
||
</div>
|
||
|
||
<div class="endpoint-description">
|
||
<p>Scanne un buffer de données (base64) pour détecter les virus avec ClamAV. Cette API est utilisée en interne par l'API filigrane.</p>
|
||
<p><strong>Base URL :</strong> <code>https://antivir.certificator.4nkweb.com</code></p>
|
||
</div>
|
||
|
||
<div class="endpoint-params">
|
||
<h4>Paramètres (Body JSON)</h4>
|
||
<table class="param-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Paramètre</th>
|
||
<th>Type</th>
|
||
<th>Requis</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td class="param-name">data</td>
|
||
<td>string</td>
|
||
<td><span class="param-required">Oui</span></td>
|
||
<td>Données encodées en base64 à scanner</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="param-name">filename</td>
|
||
<td>string</td>
|
||
<td><span class="param-optional">Non</span></td>
|
||
<td>Nom du fichier (pour le logging)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Exemple de requête</h4>
|
||
<div class="code-block">
|
||
<pre>curl -X POST https://antivir.certificator.4nkweb.com/api/scan/buffer \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"data": "base64_encoded_data",
|
||
"filename": "document.pdf"
|
||
}'</pre>
|
||
</div>
|
||
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK) - Fichier propre</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"clean": true,
|
||
"infected": false,
|
||
"viruses": [],
|
||
"filename": "document.pdf",
|
||
"size": 12345
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK) - Fichier infecté</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"clean": false,
|
||
"infected": true,
|
||
"viruses": ["Trojan.Example"],
|
||
"filename": "document.pdf",
|
||
"size": 12345
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Codes de statut possibles</h4>
|
||
<ul style="margin-left: 20px;">
|
||
<li><span class="status-code status-200">200</span> Succès - Scan effectué (fichier propre ou infecté)</li>
|
||
<li><span class="status-code status-400">400</span> Requête invalide - Données manquantes ou format incorrect</li>
|
||
<li><span class="status-code status-503">503</span> Service indisponible - ClamAV non disponible</li>
|
||
<li><span class="status-code status-500">500</span> Erreur serveur - Erreur interne lors du scan</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>ℹ️ Notes importantes</h4>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>Cette API est principalement utilisée en interne par l'API filigrane</li>
|
||
<li>Le port fixe est 3023</li>
|
||
<li>Si ClamAV est indisponible, l'API retourne une erreur 503</li>
|
||
<li>Les fichiers sont scannés en mémoire (pas de fichiers temporaires sur disque)</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Endpoint: UTXO List -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<div class="endpoint-header">
|
||
<span class="method-badge method-get">GET</span>
|
||
<span class="endpoint-path">/api/utxo/list</span>
|
||
</div>
|
||
|
||
<div class="endpoint-description">
|
||
<p>Obtient la liste complète des UTXOs du wallet, catégorisés par type (bloc rewards, ancrages, changes, frais).</p>
|
||
<p><strong>Base URL :</strong> <code>https://dashboard.certificator.4nkweb.com</code></p>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Exemple de requête</h4>
|
||
<div class="code-block">
|
||
<pre>curl -X GET https://dashboard.certificator.4nkweb.com/api/utxo/list</pre>
|
||
</div>
|
||
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK)</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"blocRewards": [...],
|
||
"anchors": [...],
|
||
"changes": [...],
|
||
"fees": [...],
|
||
"counts": {
|
||
"blocRewards": 10,
|
||
"anchors": 150,
|
||
"changes": 25,
|
||
"fees": 5,
|
||
"total": 190,
|
||
"availableForAnchor": 180,
|
||
"confirmedAvailableForAnchor": 175
|
||
}
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>ℹ️ Notes importantes</h4>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>Seuls les UTXOs avec au moins 1 confirmation sont retournés (pour éviter les erreurs "too-long-mempool-chain")</li>
|
||
<li><code>availableForAnchor</code> : Nombre d'UTXOs disponibles pour l'ancrage (> 2000 sats, non dépensés, non verrouillés)</li>
|
||
<li><code>confirmedAvailableForAnchor</code> : Nombre d'UTXOs confirmés disponibles pour l'ancrage</li>
|
||
<li>Les UTXOs sont triés par montant décroissant par défaut</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Endpoint: Small UTXOs Info -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<div class="endpoint-header">
|
||
<span class="method-badge method-get">GET</span>
|
||
<span class="endpoint-path">/api/utxo/small-info</span>
|
||
</div>
|
||
|
||
<div class="endpoint-description">
|
||
<p>Obtient les informations sur les UTXOs de moins de 2500 sats disponibles pour consolidation (nombre et montant total).</p>
|
||
<p><strong>Base URL :</strong> <code>https://dashboard.certificator.4nkweb.com</code></p>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Exemple de requête</h4>
|
||
<div class="code-block">
|
||
<pre>curl -X GET https://dashboard.certificator.4nkweb.com/api/utxo/small-info</pre>
|
||
</div>
|
||
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK)</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"count": 45,
|
||
"totalAmount": 0.0001125,
|
||
"totalSats": 11250
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>ℹ️ Notes importantes</h4>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>Seuls les UTXOs confirmés (< 2500 sats, non dépensés, non verrouillés) sont comptés</li>
|
||
<li><code>count</code> : Nombre d'UTXOs disponibles pour consolidation</li>
|
||
<li><code>totalAmount</code> : Montant total en BTC</li>
|
||
<li><code>totalSats</code> : Montant total en satoshis</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Endpoint: Consolidate UTXOs -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<div class="endpoint-header">
|
||
<span class="method-badge method-post">POST</span>
|
||
<span class="endpoint-path">/api/utxo/consolidate</span>
|
||
</div>
|
||
|
||
<div class="endpoint-description">
|
||
<p>Consolide tous les UTXOs de moins de 2500 sats en un seul gros UTXO. Cette opération optimise le wallet en réduisant le nombre de petits UTXOs.</p>
|
||
<p><strong>Base URL :</strong> <code>https://dashboard.certificator.4nkweb.com</code></p>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Exemple de requête</h4>
|
||
<div class="code-block">
|
||
<pre>curl -X POST https://dashboard.certificator.4nkweb.com/api/utxo/consolidate</pre>
|
||
</div>
|
||
<button class="copy-button" onclick="copyCode(this)">📋 Copier</button>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (200 OK) - Succès</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"success": true,
|
||
"txid": "a1b2c3d4e5f6...",
|
||
"inputCount": 45,
|
||
"totalInputAmount": 0.0001125,
|
||
"changeAmount": 0.0001025,
|
||
"estimatedFee": 0.00001
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Réponse (500) - Erreur</h4>
|
||
<div class="code-block">
|
||
<pre>{
|
||
"success": false,
|
||
"error": "No small UTXOs available for consolidation"
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="response-example">
|
||
<h4>Codes de statut possibles</h4>
|
||
<ul style="margin-left: 20px;">
|
||
<li><span class="status-code status-200">200</span> Succès - Consolidation effectuée</li>
|
||
<li><span class="status-code status-500">500</span> Erreur - Aucun UTXO disponible ou erreur lors de la consolidation</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>ℹ️ Notes importantes</h4>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>Seuls les UTXOs confirmés de moins de 2500 sats sont consolidés</li>
|
||
<li>Les UTXOs verrouillés ou déjà dépensés sont exclus</li>
|
||
<li>La transaction est envoyée au mempool immédiatement</li>
|
||
<li>Le montant consolidé est retourné comme change (moins les frais estimés)</li>
|
||
<li>Cette opération optimise le wallet en réduisant le nombre de petits UTXOs</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Section Informations -->
|
||
<section class="api-docs-section">
|
||
<div class="endpoint-card">
|
||
<h2>ℹ️ Informations Complémentaires</h2>
|
||
|
||
<div class="info-box">
|
||
<h4>Format du Hash</h4>
|
||
<p>Le hash doit être un hash SHA256 en format hexadécimal, exactement 64 caractères.</p>
|
||
<div class="code-block">
|
||
<pre>Exemple valide: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
|
||
Longueur: 64 caractères
|
||
Format: hexadécimal (0-9, a-f, A-F)</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>Format de la Transaction</h4>
|
||
<p>Les transactions d'ancrage incluent :</p>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>Un output OP_RETURN contenant "ANCHOR:" suivi du hash</li>
|
||
<li>Un output d'ancrage de 2500 sats</li>
|
||
<li>7 outputs de provisionnement de 2500 sats chacun</li>
|
||
<li>Un output de change (si nécessaire)</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>Base URLs</h4>
|
||
<p>Les APIs sont accessibles aux adresses suivantes :</p>
|
||
<div class="code-block">
|
||
<pre>API d'Ancrage : https://certificator.4nkweb.com
|
||
API Filigrane : https://watermark.certificator.4nkweb.com
|
||
API ClamAV : https://antivir.certificator.4nkweb.com</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="info-box">
|
||
<h4>Ports fixes</h4>
|
||
<p>Tous les ports sont fixes et ne peuvent pas être modifiés :</p>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>API d'Ancrage : Port 3010</li>
|
||
<li>API Faucet : Port 3021</li>
|
||
<li>API Filigrane : Port 3022</li>
|
||
<li>API ClamAV : Port 3023</li>
|
||
<li>Dashboard : Port 3020</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="warning-box">
|
||
<h4>⚠️ Notes importantes</h4>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>Les transactions sont envoyées au mempool immédiatement</li>
|
||
<li>Le statut "pending" signifie que la transaction est dans le mempool mais pas encore confirmée</li>
|
||
<li>Les confirmations augmentent à mesure que les blocs sont minés</li>
|
||
<li>En cas d'erreur 402 (Solde insuffisant), vous devez approvisionner le wallet de l'API</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<footer>
|
||
<p>Bitcoin Ancrage Dashboard - Équipe 4NK</p>
|
||
<a href="https://git.4nkweb.com/4nk/anchorage_layer_simple.git" target="_blank" rel="noopener noreferrer" class="git-link" title="Voir le code source sur Git">
|
||
<svg class="git-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
|
||
<path d="M23.546 10.93L13.067.452c-.604-.603-1.582-.603-2.188 0L8.708 2.627l2.76 2.76c.645-.215 1.379-.07 1.889.441.516.515.658 1.258.438 1.9l2.658 2.66c.645-.223 1.387-.083 1.9.435.721.72.721 1.884 0 2.604-.719.719-1.881.719-2.6 0-.539-.541-.674-1.337-.404-1.996L12.86 8.955v6.525c.176.086.342.203.488.348.713.721.713 1.883 0 2.6-.719.721-1.884.721-2.599 0-.72-.719-.72-1.879 0-2.598.182-.18.387-.316.605-.406V8.835c-.217-.091-.424-.222-.6-.401-.545-.545-.676-1.342-.396-2.011L7.636 3.7.45 10.881c-.6.605-.6 1.584 0 2.189l10.48 10.477c.604.604 1.582.604 2.186 0l10.43-10.43c.605-.603.605-1.582 0-2.187"/>
|
||
</svg>
|
||
</a>
|
||
</footer>
|
||
</div>
|
||
|
||
<script>
|
||
function copyCode(button) {
|
||
const codeBlock = button.previousElementSibling;
|
||
const code = codeBlock.querySelector('pre')?.textContent || codeBlock.textContent;
|
||
|
||
navigator.clipboard.writeText(code).then(() => {
|
||
const originalText = button.textContent;
|
||
button.textContent = '✅ Copié !';
|
||
setTimeout(() => {
|
||
button.textContent = originalText;
|
||
}, 2000);
|
||
}).catch(err => {
|
||
console.error('Erreur lors de la copie:', err);
|
||
alert('Erreur lors de la copie. Veuillez sélectionner et copier manuellement.');
|
||
});
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|