# P2NS API Usage Examples This document provides practical examples for using the P2NS Admin API. ## Table of Contents - [Basic Operations](#basic-operations) - [Domain Management](#domain-management) - [Holesail Management](#holesail-management) - [Local DNS Records](#local-dns-records) - [Certificate Management](#certificate-management) - [WebSocket Examples](#websocket-examples) - [Error Handling](#error-handling) ## Basic Operations ### Health Check ```bash # Liveness probe curl -k https://p2ns.admin/api/health # Readiness probe curl -k https://p2ns.admin/api/health?probe=readiness ``` ### Get System Status ```bash curl -k https://p2ns.admin/api/status ``` ### Get Metrics ```bash curl -k https://p2ns.admin/api/stats ``` ## Domain Management ### Add a Domain ```bash curl -k -X POST https://p2ns.admin/api/add-domain \ -H "Content-Type: application/json" \ -d '{ "domain": "example.tld", "hash": "hs://s00084bf87dfa89a3048fb081c0e6207eb5a", "ssl": false }' ``` ### List All Domains ```bash curl -k https://p2ns.admin/api/resolved-domains ``` ### Remove a Domain ```bash curl -k -X POST https://p2ns.admin/api/remove-domain \ -H "Content-Type: application/json" \ -d '{ "domain": "example.tld" }' ``` ## Holesail Management ### Create a Holesail Server ```bash curl -k -X POST https://p2ns.admin/api/holesail-create \ -H "Content-Type: application/json" \ -d '{ "name": "my-server", "port": 8080, "host": "0.0.0.0", "secure": true, "udp": false, "log": 1, "domain": "example.tld" }' ``` ### List Holesail Servers ```bash curl -k https://p2ns.admin/api/holesail-servers ``` ### Restart a Holesail Server ```bash curl -k -X POST https://p2ns.admin/api/holesail-restart \ -H "Content-Type: application/json" \ -d '{ "id": "abc123" }' ``` ### Create a Holesail Client ```bash curl -k -X POST https://p2ns.admin/api/holesail-client-create \ -H "Content-Type: application/json" \ -d '{ "domain": "example.tld", "key": "hs://s00084bf87dfa89a3048fb081c0e6207eb5a", "port": 8080, "protocol": "tcp" }' ``` ## Local DNS Records ### Add an A Record ```bash curl -k -X POST https://p2ns.admin/api/add-local-dns \ -H "Content-Type: application/json" \ -d '{ "name": "local.example", "type": "A", "ttl": 3600, "data": "192.168.1.100" }' ``` ### Add an MX Record ```bash curl -k -X POST https://p2ns.admin/api/add-local-dns \ -H "Content-Type: application/json" \ -d '{ "name": "mail.example", "type": "MX", "ttl": 3600, "preference": 10, "exchange": "mx.example.com" }' ``` ### Add an SRV Record ```bash curl -k -X POST https://p2ns.admin/api/add-local-dns \ -H "Content-Type: application/json" \ -d '{ "name": "_service._tcp.example", "type": "SRV", "ttl": 3600, "priority": 0, "weight": 5, "port": 8080, "target": "server.example.com" }' ``` ### Update a DNS Record ```bash curl -k -X POST https://p2ns.admin/api/update-local-dns \ -H "Content-Type: application/json" \ -d '{ "index": 0, "record": { "name": "local.example", "type": "A", "ttl": 7200, "data": "192.168.1.101" } }' ``` ### Delete a DNS Record ```bash curl -k -X POST https://p2ns.admin/api/delete-local-dns \ -H "Content-Type: application/json" \ -d '{ "index": 0 }' ``` ## Certificate Management ### Generate a Certificate ```bash curl -k -X POST https://p2ns.admin/api/generate-cert \ -H "Content-Type: application/json" \ -d '{ "domain": "example.tld" }' ``` ### Get Certificate Details ```bash curl -k "https://p2ns.admin/api/cert-details?domain=example.tld" ``` ### Regenerate Certificate ```bash curl -k -X POST https://p2ns.admin/api/regenerate-cert \ -H "Content-Type: application/json" \ -d '{ "domain": "example.tld" }' ``` ### Regenerate Root CA ```bash curl -k -X POST https://p2ns.admin/api/regenerate-ca ``` ## WebSocket Examples ### JavaScript/Node.js ```javascript const WebSocket = require('ws'); const ws = new WebSocket('wss://p2ns.admin/ws', { rejectUnauthorized: false // Accept self-signed certificate }); ws.on('open', () => { console.log('Connected to P2NS WebSocket'); }); ws.on('message', (data) => { const message = JSON.parse(data); console.log('Received:', message); switch (message.type) { case 'log': console.log(`[${message.level}] ${message.message}`); break; case 'update-database': console.log('Database updated, refresh domains'); break; case 'update-peers': console.log('Peers updated'); break; } }); ws.on('error', (error) => { console.error('WebSocket error:', error); }); ws.on('close', () => { console.log('WebSocket closed'); }); ``` ### Python ```python import asyncio import websockets import ssl import json async def connect_p2ns(): ssl_context = ssl.create_default_context() ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE uri = "wss://p2ns.admin/ws" async with websockets.connect(uri, ssl=ssl_context) as websocket: print("Connected to P2NS WebSocket") async for message in websocket: data = json.loads(message) print(f"Received: {data}") if data['type'] == 'log': print(f"[{data['level']}] {data['message']}") elif data['type'] == 'update-database': print("Database updated") asyncio.run(connect_p2ns()) ``` ## Error Handling ### Handling Rate Limits ```javascript async function makeRequest(url, options) { try { const response = await fetch(url, options); if (response.status === 429) { const retryAfter = response.headers.get('Retry-After'); console.log(`Rate limited. Retry after ${retryAfter} seconds`); await new Promise(resolve => setTimeout(resolve, retryAfter * 1000)); return makeRequest(url, options); // Retry } if (!response.ok) { const error = await response.text(); throw new Error(error); } return await response.json(); } catch (error) { console.error('Request failed:', error); throw error; } } ``` ### Handling Connection Errors ```javascript async function robustRequest(url, options, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { const response = await fetch(url, options); if (response.ok) { return await response.json(); } throw new Error(`HTTP ${response.status}`); } catch (error) { if (i === maxRetries - 1) throw error; await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); } } } ``` ## Troubleshooting ### Certificate Issues If you encounter certificate errors: ```bash # On macOS, trust the CA manually: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ./certs/ca.cert.pem # On Linux (system store + NSS for Chrome — requires libnss3-tools): sudo cp ./certs/ca.cert.pem /usr/local/share/ca-certificates/p2ns-ca.crt sudo update-ca-certificates mkdir -p ~/.pki/nssdb certutil -d sql:$HOME/.pki/nssdb -D -n "P2NS CA" 2>/dev/null || true certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "P2NS CA" -i ./certs/ca.cert.pem # On Windows (PowerShell as Administrator): certutil -addstore -f "ROOT" .\certs\ca.cert.pem ``` ### DNS Resolution Issues Test DNS resolution: ```bash # Query P2P domain dig @127.0.0.1 example.tld # Query with specific type dig @127.0.0.1 example.tld AAAA # Query local DNS record dig @127.0.0.1 local.example A ``` ### Connection Issues Check if services are running: ```bash # Check health curl -k https://p2ns.admin/api/health # Check status curl -k https://p2ns.admin/api/status # View logs via WebSocket or admin interface ``` ## Backup Operations ### List All Backups ```bash curl -k https://p2ns.admin/api/backups ``` ### Create Manual Backup ```bash curl -k -X POST https://p2ns.admin/api/backups/create ``` ### Restore from Backup ```bash curl -k -X POST https://p2ns.admin/api/backups/restore \ -H "Content-Type: application/json" \ -d '{ "backupName": "backup-20240101-000000" }' ``` ### Get Backup Metadata ```bash curl -k https://p2ns.admin/api/backups/backup-20240101-000000/metadata ``` ### Delete Backup ```bash curl -k -X DELETE https://p2ns.admin/api/backups/backup-20240101-000000 ``` ## Diagnostics Examples ### DNS Lookup ```bash # A record curl -k -X POST https://p2ns.admin/api/diagnostics/dns-lookup \ -H "Content-Type: application/json" \ -d '{ "domain": "example.com", "type": "A" }' # MX record curl -k -X POST https://p2ns.admin/api/diagnostics/dns-lookup \ -H "Content-Type: application/json" \ -d '{ "domain": "example.com", "type": "MX" }' ``` ### Ping (Non-streaming) ```bash curl -k -X POST https://p2ns.admin/api/diagnostics/ping \ -H "Content-Type: application/json" \ -d '{ "target": "8.8.8.8", "count": 4 }' ``` ### Ping (Streaming) ```bash curl -k -X POST https://p2ns.admin/api/diagnostics/ping \ -H "Content-Type: application/json" \ -d '{ "target": "8.8.8.8", "count": 4, "stream": true }' ``` ### Traceroute ```bash curl -k -X POST https://p2ns.admin/api/diagnostics/traceroute \ -H "Content-Type: application/json" \ -d '{ "target": "8.8.8.8", "stream": true }' ``` ### Connection Test ```bash curl -k -X POST https://p2ns.admin/api/diagnostics/connection-test \ -H "Content-Type: application/json" \ -d '{ "domain": "example.com", "port": 443 }' ``` ### Bandwidth Information ```bash curl -k https://p2ns.admin/api/diagnostics/bandwidth ``` ## Stats and Metrics Examples ### Get Current Stats ```bash curl -k https://p2ns.admin/api/stats ``` ### Get Historical Metrics ```bash # Last hour curl -k "https://p2ns.admin/api/stats/historical?minutes=60" # Last 24 hours curl -k "https://p2ns.admin/api/stats/historical?minutes=1440" ``` ### JavaScript Stats Monitoring ```javascript // One-shot HTTP load (admin UI uses this once on tab open) async function getStatsOnce() { const response = await fetch('https://p2ns.admin/api/stats'); return response.json(); } // Live updates via WebSocket (preferred) const ws = new WebSocket('wss://p2ns.admin/ws'); ws.onopen = () => ws.send(JSON.stringify({ type: 'subscribe-stats' })); ws.onmessage = (ev) => { const msg = JSON.parse(ev.data); if (msg.type === 'stats-snapshot') { console.log('Core RPC:', msg.stats?.core?.summary); console.log('Plugin RPC protocols:', msg.stats?.pluginRpc?.totalProtocols); } }; ``` ### Tail logs over WebSocket ```javascript const ws = new WebSocket('wss://p2ns.admin/ws'); ws.onopen = () => { ws.send(JSON.stringify({ type: 'subscribe-log', channel: 'dns', lines: 500 })); }; ws.onmessage = (ev) => { const msg = JSON.parse(ev.data); if (msg.type === 'file-log' && msg.channel === 'dns') console.log(msg.message); }; ``` ## Consensus Examples ### Get Sidecar Status ```bash curl -k https://p2ns.admin/api/consensus/status ``` ### Get Consensus State for a Domain ```bash curl -k https://p2ns.admin/api/consensus/example.tld ``` ### Get Consensus Metrics ```bash curl -k https://p2ns.admin/api/consensus/metrics ``` ### Force Consensus Recalculation ```bash # Recalculate all domains curl -k -X POST https://p2ns.admin/api/consensus/recalculate # Recalculate specific domain curl -k -X POST https://p2ns.admin/api/consensus/recalculate/example.tld ``` ### JavaScript: Monitor Consensus State ```javascript async function getConsensusState(domain) { const response = await fetch(`https://p2ns.admin/api/consensus/${encodeURIComponent(domain)}`); const state = await response.json(); console.log(`Domain: ${domain}`); console.log(`Status: ${state.status}`); console.log(`Quorum Met: ${state.quorumMet}`); console.log(`Vote Counts:`, state.voteCounts); if (state.status === 'resolved') { console.log(`Resolved Hash: ${state.hash}`); console.log(`Winner: ${state.resolvedClaimant}`); } else if (state.status === 'insufficient_quorum') { console.log(`Need ${state.minVotes} votes, have ${state.totalVotes}`); } else if (state.status === 'tie') { console.log('Tie detected, tie-breaker applied'); } return state; } // Check consensus for a domain getConsensusState('example.tld'); ``` ### JavaScript: Monitor Consensus Metrics ```javascript async function getConsensusMetrics() { const response = await fetch('https://p2ns.admin/api/consensus/metrics'); const metrics = await response.json(); console.log('Total Resolutions:', metrics.resolutions); console.log('Quorum Failures:', metrics.quorumFailures); console.log('Ties:', metrics.ties); console.log('Total Votes:', metrics.totalVotes); console.log('Avg Votes per Domain:', metrics.avgVotesPerDomain); // Per-domain statistics metrics.domainResolutions.forEach(({ domain, resolved, failed }) => { console.log(`${domain}: ${resolved} resolved, ${failed} failed`); }); return metrics; } // Get metrics every minute setInterval(getConsensusMetrics, 60000); ``` ### JavaScript: Monitor Domain Resolution Status ```javascript async function monitorDomainResolution(domain, interval = 5000) { const checkStatus = async () => { const state = await getConsensusState(domain); if (state.status === 'resolved') { console.log(`✓ ${domain} is resolved: ${state.hash}`); return true; // Resolved, stop monitoring } else { console.log(`⏳ ${domain} status: ${state.status}`); if (state.status === 'insufficient_quorum') { console.log(` Need ${state.minVotes} votes, have ${state.totalVotes}`); } return false; // Not resolved, continue monitoring } }; // Check immediately const resolved = await checkStatus(); if (resolved) return; // Continue checking at interval const timer = setInterval(async () => { const resolved = await checkStatus(); if (resolved) { clearInterval(timer); } }, interval); return timer; } // Monitor a domain until it's resolved monitorDomainResolution('example.tld'); ``` ### Python: Consensus State Monitoring ```python import requests import time def get_consensus_state(domain): url = f"https://p2ns.admin/api/consensus/{domain}" response = requests.get(url, verify=False) return response.json() def get_consensus_status(): url = "https://p2ns.admin/api/consensus/status" response = requests.get(url, verify=False) return response.json() def get_consensus_metrics(): url = "https://p2ns.admin/api/consensus/metrics" response = requests.get(url, verify=False) return response.json() # Get consensus state state = get_consensus_state("example.tld") print(f"Status: {state['status']}") print(f"Quorum Met: {state['quorumMet']}") print(f"Vote Counts: {state['voteCounts']}") # Check sidecar health status = get_consensus_status() print(f"Sidecar ready: {status['ready']}, bootstrap: {status['bootstrapComplete']}") # Get metrics metrics = get_consensus_metrics() print(f"Total Resolutions: {metrics['resolutions']}") print(f"Quorum Failures: {metrics['quorumFailures']}") if metrics.get('sidecar'): print(f"Sidecar domains: {metrics['sidecar']['domainCount']}") ``` ### Force Recalculation After Network Changes ```javascript async function forceRecalculation(domain = null) { const endpoint = domain ? `/api/consensus/recalculate/${encodeURIComponent(domain)}` : '/api/consensus/recalculate'; const response = await fetch(`https://p2ns.admin${endpoint}`, { method: 'POST' }); const result = await response.json(); console.log(result.message); return result; } // Recalculate all domains (useful after network topology changes) await forceRecalculation(); // Recalculate specific domain (useful after adding/removing claims) await forceRecalculation('example.tld'); ``` ## Advanced Examples ### Batch Domain Addition ```javascript const domains = [ { domain: 'example1.tld', hash: 'hs://...', ssl: false }, { domain: 'example2.tld', hash: 'hs://...', ssl: true }, { domain: 'example3.tld', hash: 'hs://...', ssl: false } ]; for (const { domain, hash, ssl } of domains) { await fetch('https://p2ns.admin/api/add-domain', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domain, hash, ssl: ssl || false }) }); } ``` ### Monitoring System Health ```javascript async function monitorHealth() { const response = await fetch('https://p2ns.admin/api/health?probe=readiness'); const health = await response.json(); if (health.status !== 'healthy') { console.warn('System is degraded:', health); // Send alert, etc. } return health; } // Monitor every 30 seconds setInterval(monitorHealth, 30000); ```