Розробка сервісу інскрипцій на Bitcoin
Ordinals та інскрипції перевернули уявлення про те, що можна зберігати в Bitcoin. Технічно це не смарт-контракти та не токени в EVM-смислі — це дані, вбудовані в witness частину SegWit-транзакцій та прив'язані до конкретних сатоші через протокол нумерації Ordinals. Якщо хочете сервіс для мінту, трансфера або відображення інскрипцій — це окрема інфраструктурна задача, не розв'язна стандартними Bitcoin-бібліотеками.
Як працюють інскрипції на рівні протоколу
Інскрипція створюється через commit-reveal паттерн із двох транзакцій:
Commit TX: створює P2TR (Pay-to-Taproot, BIP-341) output, скрипт якого містить дані інскрипції в envelope — спеціальному форматі всередині Tapscript:
OP_FALSE
OP_IF
OP_PUSH "ord" # маркер протоколу
OP_PUSH 1 # field: content-type
OP_PUSH "image/png"
OP_PUSH 0 # field: content
OP_PUSH <data_chunk_1>
OP_PUSH <data_chunk_2> # дані чанками по 520 байт
...
OP_ENDIF
<pubkey> OP_CHECKSIG
Дані знаходяться всередину OP_IF...OP_ENDIF гілки, яка ніколи не виконується — це робить їх witness data, а не виконуваним кодом. Лімит на witness дані: ~400KB на транзакцію (після Taproot зняття обмежень на witness розмір).
Reveal TX: витрачає commit output, розкриваючи скрипт та вбудовуючи дані інскрипції в блокчейн.
Інскрипція прив'язується до першого сатоші першого input'а reveal транзакції за правилами Ordinals ordinal theory.
Архітектура сервісу
Компоненти
Bitcoin нода — обов'язкова, без неї не обійтися. Bitcoind з txindex=1 для пошуку транзакцій по hash. Для роботи з Ordinals потрібен також ord індексатор (https://github.com/ordinals/ord) — окремий процес, який синхронізує свою SQLite базу зі станом ноди. Альтернатива: Hiro Ordinals API або OrdinalsBot API — якщо не хочете утримувати власну інфраструктуру.
Wallet management. Кожен користувач отримує Bitcoin адресу (P2TR — taproot, починається з bc1p). Бібліотеки: bitcoinjs-lib (JavaScript/TypeScript), rust-bitcoin (Rust), python-bitcoinlib. Для HD-гаманців — BIP-32/84/86 деривація.
Fee estimation. Комісії в Bitcoin волатильні. Сервіс повинен використовувати актуальні fee rates: estimatesmartfee через RPC або зовнішні API (mempool.space API, Blockstream API). Для інскрипцій з великими даними fee — основна стаття затрат: при 50 sat/vByte та 200KB інскрипції — ~0.1 BTC.
Flow створення інскрипції
import * as bitcoin from 'bitcoinjs-lib';
import { ECPairFactory } from 'ecpair';
import * as ecc from 'tiny-secp256k1';
const ECPair = ECPairFactory(ecc);
async function createInscription(
content: Buffer,
contentType: string,
feeRate: number, // sat/vByte
recipientAddress: string,
): Promise<{ commitTx: string; revealTx: string }> {
const keypair = ECPair.makeRandom({ network: bitcoin.networks.bitcoin });
// Будуємо envelope скрипт
const envelope = bitcoin.script.compile([
bitcoin.opcodes.OP_FALSE,
bitcoin.opcodes.OP_IF,
Buffer.from('ord'),
bitcoin.opcodes.OP_1,
Buffer.from(contentType),
bitcoin.opcodes.OP_0,
// дані розбиваються на чанки по 520 байт
...chunkData(content, 520),
bitcoin.opcodes.OP_ENDIF,
keypair.publicKey.slice(1), // x-only pubkey для Taproot
bitcoin.opcodes.OP_CHECKSIG,
]);
// Створюємо P2TR output з інскрипцією в tapscript
const scriptTree = { output: envelope };
const p2tr = bitcoin.payments.p2tr({
internalPubkey: keypair.publicKey.slice(1),
scriptTree,
network: bitcoin.networks.bitcoin,
});
// Commit TX відправляє кошти на p2tr.address
// Reveal TX витрачає цей output, розкриваючи скрипт
// ...
}
PSBT та підписання
Для користувацьких гаманців (Unisat, Xverse, OKX Wallet) транзакції будуються як PSBT (Partially Signed Bitcoin Transaction, BIP-174) та передаються гаманцю на підписання:
const psbt = new bitcoin.Psbt({ network: bitcoin.networks.bitcoin });
psbt.addInput({
hash: utxo.txid,
index: utxo.vout,
witnessUtxo: {
script: p2tr.output!,
value: utxo.value,
},
tapLeafScript: [{
leafVersion: 0xc0,
script: envelope,
controlBlock: p2tr.witness![p2tr.witness!.length - 1],
}],
});
psbt.addOutput({
address: recipientAddress,
value: 546, // dust limit
});
// Серіалізація для передачі в гаманець
const psbtBase64 = psbt.toBase64();
Робота з існуючими інскрипціями
Індексування та пошук
Ordinals ord індексатор надає JSON API (ord server):
# Інскрипції по адресі
GET /inscriptions/{address}
# Конкретна інскрипція
GET /inscription/{inscription_id}
# Sat з номером
GET /sat/{sat_number}
Для production з високою навантаженням: власний індексатор поверх ord бази (SQLite або PostgreSQL міграція) + кеш на Redis.
Трансфер інскрипцій
Трансфер — звичайна Bitcoin транзакція, яка витрачає UTXO, що містить інскрипцію. Критично важливо: не змішувати звичайні UTXOs з UTXOs-носіями інскрипцій при формуванні inputs транзакції — інакше інскрипція буде знищена (burned). Це називається inscription burning та відбувається якщо inscribed sat попадає в позицію де ordinal theory вважає його витраченим.
Правило безпеки: завжди перевіряйте UTXO через ord API перед використанням як input.
Формати та обмеження
Розмір: теоретично до ~4MB (ліміт блоку), практично до ~380KB для надійного включення в блок.
Content types: довільний MIME-тип. Стандартні: image/png, image/webp, text/plain;charset=utf-8, application/json, text/html;charset=utf-8 (recursive inscriptions).
Recursive inscriptions: інскрипція може посилатися на іншу через /content/{inscription_id}. Використовується для on-chain generative art.
BRC-20: JSON інскрипції зі спеціальним форматом ({"p":"brc-20","op":"deploy",...}). Не валідуються нодою — тільки індексаторами. При розробці BRC-20 інтеграції потрібно розуміти що консенсус по правилам — off-chain.
Стек та сроки
| Компонент | Технологія |
|---|---|
| Нода | Bitcoin Core 26+ з txindex=1 |
| Ordinals індексатор | ord 0.18+ |
| Backend | TypeScript/Node.js + bitcoinjs-lib |
| Wallet інтеграція | Unisat API / Xverse Provider API |
| Fee estimation | mempool.space API |
| База даних | PostgreSQL (метаданні) + Redis (кеш) |
Базовий сервіс (мінт + трансфер + перегляд колекції): 3-4 тижні. Підтримка BRC-20, recursive inscriptions, маркетплейс-функціональність — окрема оцінка.







