Technical Specification
Sparkle Protocol v1.0.0 - JSON Schemas and Validation Rules
Table of Contents
1. sparkle_genesis
Collection-level metadata inscribed once per collection. This inscription acts as the canonical source for collection information.
1.1 JSON Schema
{
"p": "sparkle",
"op": "genesis",
"version": 1,
"collection": {
"name": "Darkita",
"symbol": "DARKITA",
"description": "10K PFP collection with Lightning-ready checkout.",
"supply": 10000,
"creator": {
"name": "Creator Name",
"website": "https://example.com",
"pubkey": "optional-hex-or-nostr-pubkey"
}
},
"spark": {
"enabled": true,
"networks": ["spark", "ln-mainnet"]
},
"royalties": {
"bps": 500,
"recipients": [
{
"label": "creator",
"lightning_address": "creator@example.com",
"ln_node_pubkey": "optional-ln-node-pubkey"
}
]
}
}
1.2 Field Definitions
| Field | Type | Required | Description |
|---|---|---|---|
p | string | Yes | Protocol identifier. Must be "sparkle". |
op | string | Yes | Operation type. Must be "genesis". |
version | integer | Yes | Protocol version. Currently 1. |
collection.name | string | Yes | Human-readable collection name. |
collection.symbol | string | Yes | Short uppercase ticker (3-10 characters). |
collection.supply | integer | Yes | Total number of NFTs. Soft commitment. |
spark.enabled | boolean | Yes | Lightning/Spark checkout support. |
royalties.bps | integer | No | Royalty in basis points (500 = 5%). |
1.3 Usage Notes
- Inscribe this JSON as the first inscription for your collection
- The resulting inscription ID becomes the collection reference for all child NFTs
- Indexers scan for
p: "sparkle", op: "genesis"to discover collections - Supply is a soft commitment; enforcement is social, not consensus-level
2. sparkle_child
Per-inscription metadata attached to each NFT in the collection.
2.1 JSON Schema
{
"p": "sparkle",
"op": "child",
"version": 1,
"collection_ref": "<GENESIS_INSCRIPTION_ID>",
"token": {
"id": 123,
"name": "Darkita #123"
},
"media": {
"type": "image/png",
"recursive_parents": [
"<PARENT_INSCRIPTION_ID_1>",
"<PARENT_INSCRIPTION_ID_2>"
]
},
"traits": {
"Background": "Yellow",
"Eyes": "Glowing",
"Accessory": "None"
}
}
2.2 Field Definitions
| Field | Type | Required | Description |
|---|---|---|---|
collection_ref | string | Yes | Genesis inscription ID this NFT belongs to. |
token.id | integer | Yes | 1-based index within collection (1 to supply). |
token.name | string | No | Display name for this specific NFT. |
media.type | string | No | MIME type of embedded media. |
media.recursive_parents | array | No | Parent inscription IDs for recursive art. |
traits | object | No | Key-value pairs for marketplace filtering. |
2.3 Usage Notes
- Minimal valid child requires only
collection_refandtoken.id - Recursive parents enable cost-efficient collections through trait inscription reuse
- Traits are optional but improve marketplace discovery
3. sparkle_checkout
Lightning/Spark checkout object agreed upon by wallets, markets, and coordinators before payment.
3.1 JSON Schema
{
"p": "sparkle",
"op": "checkout",
"version": 1,
"inscription_id": "<INSCRIPTION_ID_BEING_BOUGHT>",
"collection_ref": "<GENESIS_INSCRIPTION_ID>",
"buyer": {
"ord_address": "bc1p...buyer...",
"lightning_address": "buyer@example.com",
"ln_node_pubkey": "optional-ln-node-pubkey"
},
"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,
"buyer_sig": "<optional-signature>"
}
3.2 Field Definitions
| Field | Type | Required | Description |
|---|---|---|---|
inscription_id | string | Yes | Ordinal inscription being purchased. |
buyer.ord_address | string | Yes | Bitcoin address for Ordinal delivery. |
network | string | Yes | "spark" or "ln-mainnet". |
max_total_sats | integer | Yes | Maximum sats buyer agrees to pay. |
pricing.seller_sats | integer | Yes | Amount to seller. |
pricing.creator_royalty_sats | integer | Yes | Creator royalty amount. |
pricing.market_fee_sats | integer | Yes | Marketplace fee. |
pricing.estimated_l1_fee_sats | integer | Yes | Estimated on-chain fee. |
expiry_block | integer | No | Block height when checkout expires. |
4. Validation Rules
4.1 Rule 1: Sum Check
max_total_sats MUST equal the sum of all fields in pricing:
max_total_sats = seller_sats + creator_royalty_sats + market_fee_sats + estimated_l1_fee_sats
4.2 Rule 2: Royalty Check
creator_royalty_sats SHOULD be calculated based on the genesis bps value. Markets SHOULD warn if royalty exceeds genesis declaration.
4.3 Rule 3: Display Requirement
Wallets MUST display complete pricing breakdown before payment confirmation.
4.4 Rule 4: Network Match
Payment must be processed on the network specified in the network field.
5. Sparkle Swap - Trustless Atomic Swaps
TypeScript reference implementation available. All tests passing. Transaction sizes: Claim 142 vbytes, Refund 138 vbytes.
Sparkle Swap enables trustless ordinal trading using Taproot hashlock scripts. The atomic swap guarantees that either both parties get what they want, or nothing happens.
5.1 Security Model
- Non-custodial: Coordinator never holds keys or funds
- Delta-safe timelocks: Refund timeout = 2x claim window to prevent race conditions
- Buyer deposit: 1% non-refundable deposit prevents free option exploit
- Atomic: Lightning payment reveals preimage that unlocks on-chain ordinal
5.2 Taproot Script Structure
// Buyer Claim Path (hashlock)
OP_SHA256 <payment_hash> OP_EQUALVERIFY <buyer_pubkey> OP_CHECKSIG
// Seller Refund Path (timelock)
<locktime> OP_CHECKLOCKTIMEVERIFY OP_DROP <seller_pubkey> OP_CHECKSIG
5.3 Trade Flow
| Step | Actor | Action |
|---|---|---|
| 1 | Seller | Creates listing with ordinal details and price |
| 2 | Buyer | Accepts listing and pays 1% deposit via Lightning |
| 3 | Seller | Sends ordinal to Taproot escrow address |
| 4 | Buyer | Pays full price via Lightning, learns preimage |
| 5 | Buyer | Claims ordinal on-chain using preimage + signature |
5.4 Delta-Safety Guarantee
To prevent race conditions during blockchain reorgs:
- Buyer has
claimWindowBlocks(default: 144 blocks / ~24 hours) to claim after paying Lightning - Seller refund only available after
2 × claimWindowBlocks(default: 288 blocks / ~48 hours) - This 2x safety margin ensures buyer can survive mempool congestion and minor reorgs
5.5 Lightning Compatibility
Sparkle Swap is Lightning-agnostic and works with:
- LND (Lightning Labs)
- Core Lightning / CLN (Blockstream)
- Eclair (ACINQ)
- LDK (Lightning Dev Kit)
- Any BOLT-compliant Lightning implementation
6. Implementation Guidelines
6.1 For Creators
- Inscribe
sparkle_genesisJSON as first collection inscription - Record the genesis inscription ID
- Reference genesis ID in all
sparkle_childinscriptions - Set
spark.enabled: trueif supporting Lightning checkout
6.2 For Marketplaces
- Index inscriptions containing
p: "sparkle" - Build collection structures from genesis references
- Generate
sparkle_checkoutobjects for listings - Integrate with Sparkle Swap coordinator for trustless trades
6.3 For Wallets
- Parse and validate
sparkle_checkoutobjects - Display complete fee breakdown to users
- Warn if fees exceed genesis royalty declaration
- Process Lightning payments per network field
6.4 For Indexers
- Scan for inscriptions with
p: "sparkle" - Build collection graphs from
collection_refreferences - Track child counts against declared supply
- Identify Lightning-enabled collections