Ordinals Minting Service Development
Ordinals is an inscription protocol on Bitcoin proposed by Casey Rodarmor in 2023. Each satoshi is numbered in mining order (ordinal theory), and arbitrary data is inscribed in the transaction's witness section via OP_FALSE OP_IF <data> OP_ENDIF envelope. This isn't smart contracts — it's data inscribed on-chain in Bitcoin. Developing a mass-minting service for Ordinals requires deep understanding of Bitcoin's UTXO model, which fundamentally differs from Ethereum's account model.
UTXO Model: Why It's More Complex Than It Seems
UTXO Management — The Core Problem
In Ethereum you have address → balance. In Bitcoin — a set of UTXOs (Unspent Transaction Outputs), each must be explicitly used as an input in the next transaction. An inscription is tied to a specific UTXO (precisely, the first satoshi of that UTXO — "cardinal" sat).
First mistake in mass minting: UTXO consolidation without considering inscriptions. A standard Bitcoin wallet may automatically combine small UTXOs for fee optimization. If consolidation takes a UTXO with an inscription as input — the inscription goes to output with correct routing (if lucky) or gets lost in dust (if error). An Ordinals wallet must distinguish between "cardinal UTXO" (with inscription) and "plain UTXO" (for payments).
Dust Limit and Padding
An inscription is created in a reveal transaction that spends a commit UTXO. The reveal transaction output — is the UTXO carrying the inscription. This output must be >= Bitcoin dust limit (546 satoshi for P2WPKH, 330 for P2TR). If you batch and try to save by sending inscription to 0 satoshi output — the transaction won't pass through mempool (non-standard output).
Practice: each inscribed output = 546–1000 satoshi (depends on user requirements). When minting 1,000 inscriptions this is 0.546–1 BTC just for "attaching" dust to each inscription.
Commit-Reveal Scheme and Timing
An Ordinals inscription is created in two steps:
Commit transaction — P2TR output with tapscript containing inscription data in locked script. Published to mempool.
Reveal transaction — spends the commit output, revealing tapscript with data. After commit confirmation (minimum 1 block) you can publish reveal.
For mass minting: thousands of commit transactions can be prepared in parallel. Reveal transactions — sequentially after each commit confirmation. With ~10 minute blocktimes and congested mempool — this can stretch for hours. You need a queue with state: PENDING_COMMIT → COMMITTED → PENDING_REVEAL → INSCRIBED.
Service Architecture
Backend: Node.js + bitcoinjs-lib
Main library for Bitcoin transaction work — bitcoinjs-lib. For Taproot/Ordinals — P2TR support starting from v6.x. Alternative: @scure/btc-signer — more modern API with types.
For Bitcoin node interaction — bitcoin-core RPC or public Esplora API (Mempool.space, Blockstream). For production: own Bitcoin Core node with txindex=1 — independent of external services, critical under high load.
| Component | Technology |
|---|---|
| Transaction builder | bitcoinjs-lib v6 / @scure/btc-signer |
| UTXO management | PostgreSQL (tracked UTXOs) |
| Bitcoin node | Bitcoin Core RPC or Esplora API |
| Fee estimation | mempool.space API (real-time sat/vbyte) |
| Job queue | BullMQ (commit/reveal pipeline) |
| Payment processing | BIP-21 URI + on-chain detection |
Fee Calculation
Bitcoin fee = fee_rate (sat/vByte) × transaction_size (vBytes). Reveal transaction size depends on inscription data size: 1 vByte ≈ 4 witness weight units. 100KB inscription in witness = ~25,000 vByte. At 50 sat/vByte = 1,250,000 satoshi = ~0.0125 BTC per inscription.
Service must:
- Get current fee rate from mempool.space (endpoint
/api/v1/fees/recommended) - Calculate exact transaction size before assembly (via
psbt.toBase64().lengthestimation) - Show user total cost = inscription fee + miner fee + service fee
- Have
feeRate multiplierfor priority (1.0x economy, 1.5x standard, 2.0x fast)
Batch Inscriptions: One Transaction vs. Multiple
One reveal can contain several inscriptions if packed into one tapscript via concatenation in envelope. This reduces overhead: one transaction instead of N, shared commit. Downside: if reveal doesn't confirm (stuck in mempool) — all inscriptions from batch wait together. For commercial service, often better to use separate transactions with independent status.
User Interface
File upload: drag-and-drop, support WebP/PNG/GIF/MP4/HTML (inscription can contain any MIME types). Preview and fee calculation before payment. BTC address for payment with QR code. Real-time status via WebSocket: detecting payment → commit sent → commit confirmed → reveal sent → inscribed. Link to ordinals.com or ord.io for viewing inscription after completion.
Security and Edge Cases
RBF (Replace-By-Fee) — user may try to replace payment transaction. Wait for minimum 1 confirmation before publishing commit.
Orphaned commits — reveal wasn't published, commit spent by another transaction. Rare, but happens with UTXO management errors. Need reconciliation process: check status of each commit UTXO on blockchain.
Content filtering — service should have policy regarding illegal content. Hash-based blacklist at upload stage.
Development Process
Analysis (1–2 days). Target audience (single inscriptions / bulk / API for other projects), BRC-20 support or plain Ordinals only.
Development (1–2 weeks). Bitcoin transaction builder + job queue + payment detection + frontend.
Testing. Testnet4 (current Bitcoin testnet) for complete end-to-end commit-reveal pipeline testing.
Deployment. VPS with Bitcoin Core node (requires ~600GB SSD), dockerized backend, monitoring pending jobs.
Timeline Estimates
Basic single inscription service — 1–1.5 weeks. Bulk minting with dashboard and API — 2–3 weeks.
Cost is calculated after analyzing scale and functionality requirements.







