Coordinator API
Integration Documentation for Sparkle Trade Coordinators
Architecture Update (v1.0.0)
Sparkle Protocol has evolved to a fully decentralized architecture.
Instead of a centralized coordinator server, v1.0.0 uses:
- Nostr Relays: Orders published as NIP-15 product events
- NIP-04 Encrypted DMs: Peer-to-peer trade negotiation
- NIP-07 Browser Wallets: Secure signing via Alby, nos2x
- Taproot Atomic Swaps: On-chain settlement without custody
Source Code & SDK (Open Source)
The complete Sparkle Protocol implementation is open source under MIT license:
- GitHub Repository: github.com/ProtocolSparkle/Sparkles-Protocol
- TypeScript SDK:
src/directory - Core swap library with PSBT construction, Taproot scripts - Reference Coordinator:
mainnet/directory - Working implementation with LND integration - Test Suite:
tests/directory - Regtest scripts, mainnet validation proofs - Browser Client:
js/sparkle-browser.js- Nostr-based serverless trading
Quick Start: git clone https://github.com/ProtocolSparkle/Sparkles-Protocol.git && npm install
1. Overview (Legacy Coordinator Model)
This page documents the original coordinator API concept. A Sparkle coordinator is a service that facilitates Lightning/Spark-based Ordinal trades. The coordinator:
- Accepts a
sparkle_checkoutobject - Validates pricing and inscription ownership
- Generates Lightning/Spark invoice
- Monitors for payment completion
- Executes on-chain Ordinal transfer
Note: This documentation describes a legacy API specification. The current implementation uses decentralized Nostr-based coordination instead.
2. API Endpoints
2.1 POST /api/checkout/prepare
Initiates a Lightning/Spark checkout for an Ordinal inscription.
Request Body
{
"p": "sparkle",
"op": "checkout",
"version": 1,
"inscription_id": "abc123...i0",
"collection_ref": "def456...i0",
"buyer": {
"ord_address": "bc1p...buyer...",
"lightning_address": "buyer@example.com"
},
"network": "spark",
"max_total_sats": 1500000,
"pricing": {
"seller_sats": 1400000,
"creator_royalty_sats": 20000,
"market_fee_sats": 30000,
"estimated_l1_fee_sats": 50000
},
"market": {
"id": "example.market",
"name": "Example Market"
},
"expiry_block": 900000
}
Response
{
"checkout_id": "chk_1234567890",
"status": "pending_payment",
"invoice": "lnbc15000000...",
"expires_at": 1234567890,
"payment_request": {
"type": "spark",
"lightning_address": "coordinator@example.com",
"amount_sats": 1500000,
"memo": "Darkita #1234 via Sparkle"
}
}
Error Responses
| Status | Description |
|---|---|
| 400 | Invalid checkout format or pricing mismatch |
| 404 | Inscription not found or not listed for sale |
| 409 | Inscription already sold or checkout in progress |
2.2 POST /api/checkout/status
Retrieves the current status of an ongoing checkout.
Request Body
{
"checkout_id": "chk_1234567890"
}
Response
{
"checkout_id": "chk_1234567890",
"status": "confirmed",
"inscription_id": "abc123...i0",
"payment": {
"received_sats": 1500000,
"confirmed_at": 1234567890
},
"transfer": {
"txid": "fedcba987654321...",
"vout": 0,
"confirmations": 2
}
}
Status Values
| Status | Description |
|---|---|
| pending_payment | Awaiting Lightning payment |
| paid | Payment received, preparing transfer |
| broadcast | Transfer transaction broadcast to network |
| confirmed | Transfer confirmed on-chain |
| failed | Checkout failed (includes reason) |
| expired | Checkout expired without payment |
2.3 GET /api/health
Health check endpoint for monitoring.
Response
{
"status": "ok",
"version": "1.0.0",
"network": "mainnet",
"lightning": {
"connected": true,
"node_id": "03abc..."
},
"bitcoin": {
"connected": true,
"block_height": 900000
}
}
3. Implementation Requirements
3.1 Validation
Coordinators MUST validate incoming checkout requests:
- Verify JSON structure matches
sparkle_checkoutspecification - Confirm
max_total_satsequals sum of pricing fields - Verify inscription ownership (seller controls UTXO)
- Validate royalty against genesis declaration
- Ensure inscription is not locked in another checkout
3.2 Lightning Integration
Coordinators MUST handle Lightning payments:
- Generate invoice for
max_total_satsamount - For Spark network: Use UMA protocol for addressing
- For ln-mainnet: Standard BOLT11 invoice
- Monitor for payment within expiry window
- Handle partial payments appropriately
3.3 Ordinal Transfer
Coordinators MUST execute on-chain transfers:
- Construct transaction with inscription input
- Output to buyer's
ord_address - Include appropriate fee for timely confirmation
- Broadcast and monitor for confirmations
- Support RBF if initial fee is insufficient
3.4 Fee Distribution
Coordinators MUST distribute funds correctly:
- Send
seller_satsto seller - Send
creator_royalty_satsto creator - Retain
market_fee_satsas coordinator fee - Use
estimated_l1_fee_satsfor on-chain transfer
4. Example Integration
// JavaScript Example
// 1. Prepare checkout
const checkout = {
p: "sparkle",
op: "checkout",
version: 1,
inscription_id: "abc123...i0",
collection_ref: "def456...i0",
buyer: {
ord_address: "bc1p...buyer...",
lightning_address: "alice@example.com"
},
network: "spark",
max_total_sats: 1500000,
pricing: {
seller_sats: 1400000,
creator_royalty_sats: 70000,
market_fee_sats: 20000,
estimated_l1_fee_sats: 10000
}
};
// 2. Send to coordinator
const response = await fetch('/api/checkout/prepare', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(checkout)
});
const { checkout_id, invoice } = await response.json();
// 3. Poll for status
const checkStatus = async () => {
const status = await fetch('/api/checkout/status', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ checkout_id })
});
const result = await status.json();
if (result.status === 'confirmed') {
console.log('Transfer complete:', result.transfer.txid);
} else if (result.status !== 'failed') {
setTimeout(checkStatus, 5000);
}
};
checkStatus();
5. Deployment Guide
Recommended: Serverless Nostr-Based Trading
The v1.0.0 architecture eliminates the need for a centralized coordinator. Trades are coordinated peer-to-peer using Nostr relays.
5.1 Serverless Setup (Recommended)
No server deployment required. Users connect directly via the Swap Interface.
- Install a Nostr browser extension: Alby, nos2x, or similar NIP-07 compatible wallet
- Install a Bitcoin wallet: Unisat, Xverse, or similar for PSBT signing
- Connect to relays: Default relays are pre-configured, or add custom relays
- Start trading: List inscriptions or browse available offers
5.2 Self-Hosted Coordinator (Advanced)
For marketplaces or high-volume traders who want dedicated infrastructure.
Prerequisites
- Node.js v18+ or Bun runtime
- LND v0.18+ with hold invoice support
- Bitcoin Core (fully synced) or Electrum server access
- PostgreSQL or SQLite for state management
Installation
# Clone the SDK repository
git clone https://github.com/ProtocolSparkle/Sparkles-Protocol.git
cd Sparkles-Protocol
# Install dependencies
npm install
# Configure environment
cp .env.example .env
# Edit .env with your LND credentials and Bitcoin RPC
# Run coordinator service
npm run coordinator
Configuration
# .env configuration
LND_MACAROON_PATH=/path/to/admin.macaroon
LND_CERT_PATH=/path/to/tls.cert
LND_HOST=localhost:10009
BITCOIN_RPC_HOST=localhost
BITCOIN_RPC_PORT=8332
BITCOIN_RPC_USER=your_user
BITCOIN_RPC_PASS=your_password
# Coordinator settings
COORDINATOR_FEE_SATS=1000
MIN_LOCKTIME_BLOCKS=6
MAX_TRADE_AMOUNT_SATS=10000000
Security Considerations
- Never expose LND admin macaroon publicly - Use invoice-only macaroon for public endpoints
- Rate limiting: Implement request throttling to prevent abuse
- HTTPS required: All production endpoints must use TLS
- Monitoring: Set up alerts for failed transactions and unusual activity
6. Coordinator Trust Model
What the Coordinator CANNOT Do
- Steal funds: The atomic swap ensures both parties are satisfied or the trade reverts
- Steal inscriptions: Inscriptions are locked in Taproot scripts controlled by buyer/seller keys
- Forge transactions: All signatures require private keys held only by the trading parties
- Modify payment amounts: Lightning invoices are cryptographically bound to the swap
What the Coordinator CAN Do (Trust Assumptions)
- Censor trades: A malicious coordinator can refuse to relay messages or match orders
- Delay settlement: The coordinator could delay relaying payment confirmations
- Front-run orders: A coordinator with trading interest could see orders before others
- Collect metadata: IP addresses, trade patterns, and timing information may be logged
Mitigations
- Multiple coordinators: Use different coordinators for different trades to reduce single-point trust
- Self-hosted option: Run your own coordinator for complete control (see Section 5.2)
- Nostr-based trading: The serverless Nostr approach eliminates centralized coordinators entirely
- Timelock protection: Sellers can always recover inscriptions after timelock expiry if trades stall
Bottom line: The coordinator facilitates trades but cannot steal. This is similar to how a Bitcoin mempool relayer can censor but not forge transactions. For maximum trustlessness, use the serverless Nostr-based swap interface.