Sparkle Protocol SDK Documentation
Implementation Track – production-ready SDK for Lightning-atomic ordinal swaps.
Status: 100% Production Proven on Bitcoin Mainnet
The complete atomic swap mechanism has been validated on Bitcoin mainnet with real inscriptions and Lightning payments. See the Complete Proof Report for transaction details.
Proven Components:
- On-chain lock/sweep: Tested with real Darkita #1 inscription
- Lightning integration: Hold invoices, channel management, settlement
- Complete atomic swap: Payment, Preimage, Settlement flow
- Production ready: MIT licensed, open source
Developer SDK - Core Implementation Complete
Version 1.0.0 | December 2025
For Application Developers
Overview
This document describes the Sparkle Protocol SDK for JavaScript/TypeScript developers. The core Sparkle Swap library is now implemented with working Taproot atomic swap functionality. The higher-level SDK for inscriptions and coordinator integration is still in design phase.
1. Working Implementation
1.1 Install Dependencies
npm install @scure/btc-signer @noble/hashes
1.2 Create a Sparkle Swap Address
import { createSparkleSwapAddress } from './core/taproot-scripts';
import { sha256 } from '@noble/hashes/sha256';
// Generate payment hash from preimage
const preimage = new Uint8Array(32); // Your 32-byte preimage
crypto.getRandomValues(preimage);
const paymentHash = sha256(preimage);
// Create the swap address
const swapAddress = createSparkleSwapAddress({
paymentHash,
buyerPubkey: buyerCompressedPubkey, // 33 bytes
sellerPubkey: sellerCompressedPubkey, // 33 bytes
refundLocktime: currentBlockHeight + 144, // ~24 hours
network: 'testnet',
});
console.log('Swap Address:', swapAddress.address);
// Seller sends Ordinal to this address
1.3 Build Claim Transaction (Buyer)
import { buildClaimTransaction } from './core/claim-transaction';
// After Lightning payment reveals preimage
const claimTx = buildClaimTransaction({
swapAddress,
fundingTxid: 'abc123...', // TX where seller sent Ordinal
fundingVout: 0,
fundingAmount: 10000n, // satoshis
preimage, // 32 bytes - revealed by Lightning payment
buyerPrivkey, // 32 bytes
destinationAddress: 'tb1q...', // Buyer's address
feeRate: 2, // sats/vbyte
network: 'testnet',
});
console.log('Claim TX:', claimTx.txHex);
console.log('TXID:', claimTx.txid);
// Broadcast to claim the Ordinal
1.4 Build Refund Transaction (Seller)
import { buildRefundTransaction } from './core/refund-transaction';
// If buyer doesn't pay before timeout
const refundTx = buildRefundTransaction({
swapAddress,
fundingTxid: 'abc123...',
fundingVout: 0,
fundingAmount: 10000n,
sellerPrivkey, // 32 bytes
destinationAddress: 'tb1q...', // Seller's address
feeRate: 2,
network: 'testnet',
});
console.log('Refund TX:', refundTx.txHex);
console.log('Locktime:', refundTx.locktime);
// Can only broadcast after locktime passes
1.5 Taproot Script Details
The swap address uses a Taproot tree with two spending paths:
| Path | Script | Used By |
|---|---|---|
| Hashlock (Claim) | OP_SHA256 <hash> OP_EQUALVERIFY <buyer_pk> OP_CHECKSIG |
Buyer with preimage |
| Timelock (Refund) | <locktime> OP_CLTV OP_DROP <seller_pk> OP_CHECKSIG |
Seller after timeout |
1.6 Browser Integration (NIP-07 + Bitcoin Wallets)
The browser modules enable secure wallet connections without ever handling private keys:
NIP-07 Nostr Wallet (Alby, nos2x)
import { connectWallet, signEvent, encryptNip04 } from 'sparkle-protocol/browser';
// Connect via browser extension (prompts user)
const connection = await connectWallet();
if (connection.state === 'connected') {
console.log('Nostr pubkey:', connection.pubkey);
}
// Sign events (extension handles private key)
const signedEvent = await signEvent({
kind: 4,
created_at: Math.floor(Date.now() / 1000),
tags: [['p', recipientPubkey]],
content: await encryptNip04(recipientPubkey, message),
});
Bitcoin Wallet (Unisat, Xverse)
import {
detectBitcoinWallets,
connectBitcoinWallet,
signPsbt
} from 'sparkle-protocol/browser';
// Detect available wallets
const wallets = detectBitcoinWallets();
// ['unisat', 'xverse']
// Connect (prompts user)
const btcConnection = await connectBitcoinWallet('unisat');
console.log('Address:', btcConnection.accounts[0].address);
// Sign PSBT (extension handles private key)
const result = await signPsbt('unisat', psbtHex, {
autoFinalized: false
});
Unified Wallet Manager
import { SparkleWalletManager } from 'sparkle-protocol/browser';
const manager = new SparkleWalletManager((state) => {
console.log('Wallet state changed:', state);
});
// Connect both wallets
await manager.connectNostr();
await manager.connectBitcoin();
// Sign and publish Nostr events
await manager.signAndPublish(event);
// Sign Bitcoin PSBTs
const { signedPsbtHex } = await manager.signPsbt(psbtHex);
Try it live: Taproot Swap Demo
2. Future SDK Installation
2.1 NPM Package
Proposed package name: @sparkle/protocol-sdk
# Future installation command npm install @sparkle/protocol-sdk # Or with yarn yarn add @sparkle/protocol-sdk
2.2 Requirements
- Node.js v18 or higher
- Bitcoin Core RPC access (testnet or mainnet)
- Lightning Network node (LND or Core Lightning)
- Ord CLI tool installed
2. Quick Start (Conceptual)
2.1 Initialize SDK
import { SparkleClient } from '@sparkle/protocol-sdk'
// Initialize client
const sparkle = new SparkleClient({
network: 'testnet',
bitcoinRPC: {
url: 'http://localhost:18332',
username: 'your_rpc_user',
password: 'your_rpc_pass'
},
lightningNode: {
type: 'lnd',
macaroonPath: '/path/to/admin.macaroon',
tlsCertPath: '/path/to/tls.cert',
host: 'localhost:10009'
},
coordinator: 'https://coordinator.sparkleprotocol.com'
})
2.2 Create Sparkle Inscription
// Create Sparkle-compatible NFT
const inscription = await sparkle.inscribe({
file: './my-nft.png',
metadata: {
name: 'My First Sparkle NFT',
description: 'Experimental Lightning-tradeable ordinal',
lightning: {
enabled: true,
minChannelCapacity: 100000
}
},
feeRate: 10
})
console.log('Inscription ID:', inscription.id)
// Output: abc123def456...i0
2.3 List for Sale
// List inscription for Lightning-settled sale
const listing = await sparkle.list({
inscriptionId: 'abc123def456...i0',
priceSats: 100000,
expiresIn: 86400 // 24 hours in seconds
})
console.log('Listing created:', listing.id)
console.log('Share URL:', listing.url)
2.4 Buy Inscription
// Purchase inscription via Lightning
const purchase = await sparkle.buy({
listingId: 'listing_xyz',
maxPriceSats: 105000 // Allow 5% slippage
})
console.log('Purchase complete!')
console.log('TXID:', purchase.txid)
console.log('Lightning payment:', purchase.lightningPayment)
3. API Reference
3.1 SparkleClient Class
Constructor
new SparkleClient(config: ClientConfig)
ClientConfig interface:
interface ClientConfig {
network: 'mainnet' | 'testnet' | 'regtest'
bitcoinRPC: {
url: string
username: string
password: string
}
lightningNode: {
type: 'lnd' | 'cln' | 'eclair'
macaroonPath?: string // LND only
tlsCertPath?: string // LND only
host: string
port?: number
}
coordinator: string // Coordinator URL
feeRate?: number // Default fee rate (sat/vB)
}
Methods
sparkle.inscribe(options)
await sparkle.inscribe({
file: string | Buffer,
metadata: {
name?: string,
description?: string,
attributes?: object,
lightning: {
enabled: boolean,
minChannelCapacity?: number
}
},
feeRate?: number
})
Returns: Promise<Inscription>
sparkle.list(options)
await sparkle.list({
inscriptionId: string,
priceSats: number,
expiresIn?: number // seconds
})
Returns: Promise<Listing>
sparkle.buy(options)
await sparkle.buy({
listingId: string,
maxPriceSats?: number
})
Returns: Promise<Purchase>
sparkle.getInscription(id)
await sparkle.getInscription(inscriptionId: string) Returns: Promise<Inscription>
sparkle.getListings(filter)
await sparkle.getListings({
minPrice?: number,
maxPrice?: number,
limit?: number
})
Returns: Promise<Listing[]>
3.2 Type Definitions
interface Inscription {
id: string
owner: string
metadata: object
sparkleEnabled: boolean
contentType: string
contentLength: number
genesisTransaction: string
genesisHeight: number
}
interface Listing {
id: string
inscriptionId: string
seller: string
priceSats: number
status: 'active' | 'sold' | 'expired' | 'cancelled'
createdAt: number
expiresAt: number
url: string
}
interface Purchase {
id: string
listingId: string
inscriptionId: string
buyer: string
seller: string
priceSats: number
txid: string
lightningPayment: string
status: 'pending' | 'complete' | 'failed'
}
4. Advanced Usage
4.1 Custom Coordinator
// Use your own coordinator
const sparkle = new SparkleClient({
// ... other config
coordinator: 'https://my-coordinator.example.com',
coordinatorAuth: {
apiKey: 'your_api_key'
}
})
4.2 Batch Inscriptions
// Inscribe multiple files at once
const inscriptions = await sparkle.batchInscribe({
files: [
{ path: './nft1.png', metadata: { name: 'NFT #1' } },
{ path: './nft2.png', metadata: { name: 'NFT #2' } },
{ path: './nft3.png', metadata: { name: 'NFT #3' } }
],
feeRate: 10
})
console.log('Inscribed:', inscriptions.length, 'NFTs')
4.3 Trade Monitoring
// Monitor trade status
sparkle.on('trade:initiated', (trade) => {
console.log('Trade initiated:', trade.id)
})
sparkle.on('trade:payment', (trade) => {
console.log('Lightning payment sent:', trade.lightningPayment)
})
sparkle.on('trade:complete', (trade) => {
console.log('Trade complete! TXID:', trade.txid)
})
sparkle.on('trade:failed', (trade, error) => {
console.error('Trade failed:', error.message)
})
4.4 Wallet Integration
// Get wallet balance
const balance = await sparkle.wallet.balance()
console.log('Ordinals:', balance.ordinals)
console.log('Cardinal sats:', balance.cardinal)
// Get wallet address
const address = await sparkle.wallet.address()
console.log('Receive address:', address)
// List wallet inscriptions
const inscriptions = await sparkle.wallet.inscriptions()
console.log('You own:', inscriptions.length, 'inscriptions')
5. Coordinator API (For Coordinator Operators)
5.1 Running a Coordinator
import { SparkleCoordinator } from '@sparkle/coordinator'
const coordinator = new SparkleCoordinator({
network: 'testnet',
lightningNode: {
type: 'lnd',
macaroonPath: '/path/to/admin.macaroon',
tlsCertPath: '/path/to/tls.cert'
},
bitcoinRPC: {
url: 'http://localhost:18332',
username: 'user',
password: 'pass'
},
port: 3000,
feePercent: 0.5 // 0.5% coordinator fee
})
await coordinator.start()
console.log('Coordinator running on port 3000')
5.2 Coordinator Configuration
interface CoordinatorConfig {
network: 'mainnet' | 'testnet'
lightningNode: LightningNodeConfig
bitcoinRPC: BitcoinRPCConfig
port: number
feePercent: number
maxTradeValue?: number
htlcTimeout?: number // blocks
requireKYC?: boolean
bondAmount?: number // sats
reputationThreshold?: number
}
6. Error Handling
6.1 Common Errors
try {
await sparkle.buy({ listingId: 'xyz' })
} catch (error) {
if (error instanceof SparkleError) {
switch (error.code) {
case 'INSUFFICIENT_FUNDS':
console.error('Not enough sats in Lightning channel')
break
case 'LISTING_EXPIRED':
console.error('Listing has expired')
break
case 'COORDINATOR_OFFLINE':
console.error('Coordinator is not responding')
break
case 'HTLC_TIMEOUT':
console.error('Lightning payment timed out')
break
case 'INSCRIPTION_ALREADY_SOLD':
console.error('Inscription was sold to another buyer')
break
default:
console.error('Unknown error:', error.message)
}
}
}
6.2 Error Codes Reference
| Error Code | Description | Recovery |
|---|---|---|
| INSUFFICIENT_FUNDS | Not enough Lightning channel capacity | Open larger channel or top up |
| LISTING_EXPIRED | Listing time window closed | Find another listing |
| COORDINATOR_OFFLINE | Cannot reach coordinator | Retry or use different coordinator |
| HTLC_TIMEOUT | Lightning payment timed out | Funds automatically refunded |
| INVALID_INSCRIPTION | Inscription not Sparkle-compatible | Check metadata format |
7. Testing
7.1 Testnet Example
import { SparkleClient } from '@sparkle/protocol-sdk'
// Initialize for testnet
const sparkle = new SparkleClient({
network: 'testnet',
bitcoinRPC: { /*...*/ },
lightningNode: { /*...*/ },
coordinator: 'https://testnet-coordinator.sparkleprotocol.com'
})
// Test inscription
const inscription = await sparkle.inscribe({
file: './test-nft.png',
metadata: {
name: 'Test NFT',
lightning: { enabled: true }
}
})
console.log('Test inscription created:', inscription.id)
7.2 Mock Coordinator
import { MockCoordinator } from '@sparkle/protocol-sdk/testing'
// Use mock coordinator for local testing
const sparkle = new SparkleClient({
network: 'regtest',
coordinator: new MockCoordinator({
simulateDelay: 100, // ms
failureRate: 0.1 // 10% failure rate for testing
})
})
8. Best Practices
8.1 Security
- Never share RPC credentials: Keep bitcoin.conf secure
- Use macaroons properly: Limit LND macaroon permissions
- Verify inscriptions: Always check metadata before buying
- Test on testnet first: Never jump straight to mainnet
- Monitor Lightning channels: Ensure sufficient liquidity
8.2 Performance
- Batch inscriptions when possible
- Cache inscription metadata locally
- Use connection pooling for RPC calls
- Implement exponential backoff for retries
- Monitor Lightning channel health
8.3 User Experience
- Show clear fee breakdowns (inscription + Lightning + coordinator)
- Display HTLC timeout clearly to buyers
- Provide estimated settlement times
- Handle errors gracefully with user-friendly messages
- Show real-time trade status updates
9. Contributing
- Add support for additional Lightning implementations (Eclair, etc.)
- Improve error handling and retry logic
- Build UI components (React, Vue, etc.)
- Write comprehensive tests
- Improve documentation with more examples
- Add TypeScript type definitions
10. SDK Development Roadmap
- Phase 1: Core protocol implementation [COMPLETE]
- Taproot script generation
- Claim transaction builder
- Refund transaction builder
- Cryptographic verification tests
- Phase 2: Lightning integration (In Progress)
- Lightning invoice generation
- HTLC coordination
- Phase 3: Testing & debugging (~150 hours)
- Phase 4: Documentation & examples (~50 hours)
Remaining work: Lightning integration, coordinator API, inscription management.
11. Support & Resources
11.1 Documentation
- Whitepaper - Protocol overview
- Implementation Guide - Step-by-step setup
- Technical Analysis - Detailed spec
11.2 Community
- GitHub: github.com/ProtocolSparkle/Sparkles-Protocol
- X / Twitter: @SparkleProtocol
- Issues: Report bugs or suggest features