Reference
TAP reference
Terminology, the exact behaviour of Bitcoin Universe's TAP indexer around confirmation, mempool and reorgs, the concrete differences from BRC-20, and a checklist for anyone building against TAP.
Terminology
| Available balance | The part of an address's holding that can be spent by inscribing a new transfer. |
|---|---|
| Transferable balance | The part parked in live transfer inscriptions. It counts toward the holder's total but cannot be transferred again until the inscription is sent. |
| Transfer inscription | An inscription whose content is a valid token-transfer. Live until sent, consumed afterwards. |
| Consumed | A transfer inscription that has been sent and credited. It is spent for protocol purposes even though the ordinal still exists. |
| Privilege authority | The inscription named by a deployment's prv field, holding the key that authorises privileged operations on that ticker. |
| Authority bearing | An operation that only takes effect with a valid authorisation from the ticker's privilege authority. |
| Atomic amount | An amount as an integer at the deployment's decimal scale, with no decimal point. Always produced by string padding. |
| Cursed inscription | An inscription with a negative inscription number. Its ticker sits in a namespace prefixed with -. |
| Quarantine | An indexer state for a source row that cannot be interpreted safely yet, held rather than guessed at. |
| Checkpoint | A height and block hash that a read is pinned to. Reads are bracketed by checkpoint agreement so that two observations can never be mixed. |
| DMT | Digital Matter Theory. A distinct asset family carried on the tap protocol tag, indexed separately. |
Indexer semantics
Bitcoin Universe reads confirmed TAP state from an authenticated writer it operates itself, and publishes normalised batches. The behaviour below is that indexer's, not a property of TAP.
Identity pinning
The service pins its protocol, chain, network, writer identity, writer version and writer revision. It refuses to start if the configured identity differs from the code, and it stores an identity hash in its database so that a database built for another source, network, writer revision or writer version cannot be opened. Every read is bracketed by authenticated block digest checks, so a height advance or a same height block replacement aborts the operation instead of mixing two states.
Ordering and replay
Each source list has a durable offset. The raw row fingerprint, the normalised event and the output journal sequence are all stored, so replaying the same source row does not create a second event. Output cursors bind the journal sequence to the source identity, and new journal rows never change the content of an older page.
Holding back rather than guessing
- Activity for a ticker with no known deployment waits until the deployment stream has been read to its current length. Still absent, the row is quarantined instead of being scaled with a guessed decimal scale. A later deployment rewinds and retries it.
- A raw source record is capped at 256 KiB. An oversized row keeps its SHA-256 fingerprint and byte count, is quarantined, and is never interpreted.
- Holder snapshots are staged against one pinned height and hash, with an exact holder count check, and published as a manifest with ordered chunks. Reopening a snapshot job fails if the writer has advanced, so a snapshot can never mix heights.
Addresses
The source contract is Bitcoin mainnet only. A mixed case Bech32 string is rejected. Where a legacy holder row uses another valid Bitcoin network encoding, the indexer derives the identical output script and re-encodes that script as a mainnet address rather than guessing. Invalid checksums and malformed addresses fail closed. Addresses supplied by users on marketplace paths are strictly mainnet and are never rewritten.
Confirmation states
| Evidence | State |
|---|---|
| A status of pending, unconfirmed or mempool | pending |
| A confirmed flag that is false or zero | pending |
| No block height | pending |
| A block height present | confirmed |
| A status of reverted, invalid, orphaned or reorged | reverted |
| A status of failed, rejected or error | failed |
Pending does not mean seen in the mempool. Source coverage is recorded as partial with this reason: The Universe-operated TAP writer provides confirmed indexed state and authenticated block digests but no pending mempool feed. Tail checks detect confirmed replacements visible in writer lists. A consumer must not present TAP pending state as mempool visibility.
Reorg behaviour
Reorg coverage is recorded as tail replacement only. The indexer rechecks a bounded tail of each source list and emits invalidations only when replacement evidence exists, meaning a list that got shorter or a row that changed. When deployment metadata changes, affected activity is invalidated and rewound before the new decimal scale is applied. An identical event that returns after invalidation keeps its source event id and receives a new journal entry, so a downstream projection can reactivate it rather than duplicate it.
On the marketplace side, reorg reconciliation is automatic. The authority appends reorg observations, reopens or invalidates affected orders deterministically, and preserves the funding, broadcast, settlement and replacement lineage.
| Availability | Feature gated behind tapMarketplaceV1 |
|---|---|
| Execution mode | In app execution |
| Listing minimum confirmations | No numeric policy is enforced |
| Settlement minimum confirmations | 1 |
| Settlement policy | Settlement requires the exact confirmed Bitcoin transaction, the consumed TAP transfer inscription, and the buyer indexed balance at stable checkpoints. |
| Freshness policy | Every mutation is bound to stable TAP, Ord, Bitcoin Core, and complete-inventory checkpoints; deployment readiness must enforce the configured checkpoint age and lag limits. |
| Reorg policy | The authority appends reorg observations, reopens or invalidates affected orders deterministically, and preserves funding, broadcast, settlement, and replacement lineage. |
| Mutation gate | Execution requires distinct read and execution credentials, a fresh TAP readiness checkpoint, exact complete inventory, clean funding, immutable economics, and protocol-native post-sign validation. |
| Unsupported action | sell: TAP has no executable offer workflow on this marketplace surface. |
How TAP differs from BRC-20
TAP inherits BRC-20's shape: a JSON payload in an inscription, a deploy, a mint and a two step transfer. The differences are concrete rather than philosophical.
| Point | BRC-20 | TAP |
|---|---|---|
| Protocol tag | brc-20 | tap |
| Operation names | deploy, mint, transfer | token-deploy, token-mint, token-transfer |
| Ticker size | Four bytes | Up to 32 UTF-16 code units and 128 UTF-8 bytes |
| Ticker character set | Effectively four ASCII characters | Any Unicode outside the control, format and separator categories, including emoji |
| Four character tickers | The whole namespace | Not offered by the Bitcoin Universe inscribe surface, which accepts 3 characters or 5 to 32, keeping the two namespaces apart in practice |
| Extra data on a transfer | None | Optional dta, up to 512 UTF-8 bytes, with no protocol meaning |
| Delegated authority | None | A deployment may name a privilege authority in prv, and privileged operations then require its authorisation |
| Batch movement | One transfer inscription per movement | token-send moves a list of items in one authorised payload |
| Related asset families | None on the same tag | The dmt- family shares the tap tag and is indexed separately |
| Cursed inscriptions | Ignored by most indexers | Placed in a separate ticker namespace with a leading - |
| Transfer model | Inscribe then send | Inscribe then send, identical in shape |
The two step transfer is the same in both, which is why a wallet that handles BRC-20 transfer inscriptions safely usually handles TAP ones safely too. The failure mode is also the same: an unsent transfer inscription spent as change loses the parked balance.
Fees and size
- Every TAP operation is an inscription, so it costs a commit and a reveal transaction plus the witness bytes of the payload. A transfer therefore costs two inscriptions worth of fees over its life: one to create it and one ordinary send to complete it.
- Payloads are small. A minimal
token-transferis under 60 bytes. The optionaldtafield is capped at 512 UTF-8 bytes, and a long ticker adds up to 128 bytes. - Because witness data is discounted, the dominant cost for a small payload is the fixed transaction overhead rather than the payload itself. Batching many mints into one reveal is the usual way to reduce it.
- Bitcoin Universe's inscribe flow estimates transaction size as a fixed prefix plus a quarter of the payload byte length, which reflects that witness discount.
- An output holding a transfer inscription must stay above the dust limit and must be handled by an inscription aware wallet, so it cannot be consolidated the way a plain output can.
Limitations
- No mempool coverage. Bitcoin Universe's TAP source publishes confirmed state only. Pending in the normalised model means "no block evidence", not "seen in the mempool".
- Reorg detection is bounded. Only a tail of each source list is rechecked, and invalidations require positive replacement evidence. A reorganisation deeper than that tail is not detected by tail checks alone.
- Authority operations are not indexed by Bitcoin Universe. Deployments, mints, transfers and trades are normalised. Authority bearing operations are not, so no Bitcoin Universe surface can show or execute them.
- DMT is out of scope here. The
dmt-family shares thetaptag but is a separate asset family with its own indexer. - No numeric freshness policy is enforced. The registry records that checkpoint age and lag limits must be enforced by deployment configuration rather than by a value in the registry.
- Selling is not executable. Recorded reason: TAP has no executable offer workflow on this marketplace surface.
- This site does not restate upstream rules it cannot check. Where TAP defines an operation that does not appear in Bitcoin Universe's code, the field shape observed there is given and the upstream Trac documentation is the reference for the rest.
Security considerations
For holders
- An unsent transfer inscription is a bearer instrument in an ordinary output. Any wallet that can spend that output can destroy the parked balance.
- Tickers can use the full Unicode range, so visually identical tickers can be different tokens. Compare the normalised ticker, not the rendering.
- A deployment that names an authority is a standing trust decision that cannot be undone. Read
prvbefore you hold. - Pending is not settled. With no mempool feed, treat an unconfirmed TAP transfer as not having happened.
For implementers
- Parse transfer content strictly. A permissive JSON reader will accept duplicate keys, numeric amounts and trailing data, and will then disagree with every strict indexer about who owns what.
- Never use floating point for amounts. Pad and concatenate strings, and reject anything that does not match the amount grammar exactly.
- Do not infer a decimal scale. If the deployment is not known yet, hold the row rather than scaling it at zero.
- Bracket every read with a checkpoint before and after. Two reads at different heights combined into one answer is how a marketplace ends up selling a position that has already moved.
- Check the whole output, not just the protocol you care about. A TAP position can share an output with runes, rare sats and other protocols' tokens.
- Require positive evidence to invalidate. An event that stops being visible is not the same as an event that was replaced.
- Keep read credentials and execution credentials distinct, and fail closed when any dependency cannot supply its evidence.
For marketplace operators
A listing built on a TAP transfer inscription is only as sound as the agreement between the indexer, the ordinals view and Bitcoin Core at one checkpoint. Bitcoin Universe's authority fails closed on a consumed transfer inscription, stale reader state, source or schema disagreement, a tip or reorg race, incomplete inventory, a co-located inscription, runes or special sats on the output, a spent output, and insufficient confirmations. Any of those conditions treated as a warning rather than a refusal is a way to sell something twice.
Implementation checklist
Payload layer
- Reject a byte order mark rather than stripping it.
- Decode UTF-8 strictly, with no replacement characters.
- Require a single JSON object with string keys and string values only.
- Reject duplicate keys, unknown keys, trailing commas and trailing data.
- Compare
pandopexactly and case sensitively. - Cap
dtaat 512 UTF-8 bytes.
Ticker and amount layer
- Normalise to NFC lower case, and in transfer content require the written form to already match.
- Enforce 32 UTF-16 code units and 128 UTF-8 bytes.
- Reject Unicode control, format and separator characters.
- Apply the leading
-namespace for negative inscription numbers. - Enforce the amount grammar and the decimal scale, and cap the atomic value at 78 digits.
- Reject a declared decimal scale outside 0 to 18.
State layer
- Track available and transferable balances separately.
- Ignore a transfer that exceeds the available balance, without partial application.
- Consume a transfer inscription on its first credited send.
- Settle a self send back to available.
- Deduplicate by source row fingerprint so replay is harmless.
Operational layer
- Pin protocol, chain, network and source identity, and refuse to open a database built for another.
- Bracket reads with a checkpoint before and after.
- Quarantine rather than guess, and rewind when the missing evidence arrives.
- Emit invalidations only on positive replacement evidence.
- State your coverage honestly, including the absence of a mempool feed.
Test your implementation against the test vectors, and check individual payloads with the validator.