TAP Protocol
TAP is an Ordinals metaprotocol for fungible tokens and token-backed state on Bitcoin L1. Tokens are deployed, minted and moved with inscriptions, and an internal account layer adds mass sends, signed authorities, locks, staking, sales, AMM pools and more.
This page explains how the protocol works, what the TAP Wallet can do, and where the code lives. The full, normative rules are in the TAP Protocol specification on GitHub; if anything here differs from it, the specification wins.
How TAP works
TAP has two layers:
| Layer | Purpose |
|---|---|
| External token layer | Deploy, mint, and inscribe transferable token balances. |
| Internal action layer | Tap confirmed inscriptions that update account state without moving a transferable inscription. This layer powers mass sends, trades, authorities, locks, staking, sales, AMM pools, perp groups, and privileged mints. |
Inscriptions and tapping
Every TAP operation is a JSON inscription with "p": "tap" and an op field. Indexers read the inscriptions in Bitcoin order and apply the rules of the specification, so every indexer arrives at the same balances.
An inscription is tapped when it is sent back to the account that owns or controls the action. Tapping is how an account confirms an internal action. Some signed authority redeems do not need tapping by the submitter, because the authority's signature is the authorization.
Each account has a balance, a transferable amount (inscribed but not yet sent) and locked amounts. What an account can spend is its available balance: balance − transferable − locked, minus any open obligations.
Tickers and amounts
- Ticker comparisons are case insensitive; indexers store tickers in lowercase. Tickers are measured in visible Unicode characters.
- Before block
861576, valid tickers have 3 or 5 to 32 visible characters. From block861576, 1 to 32. - Amounts are parsed against the token's decimals and stored in atomic units.
decdefaults to 18; an override from 0 to 17 can be set at deploy. DMT deployments use 0 decimals. - Amounts are unsigned decimal strings without commas, signs or exponents. Fractional digits beyond the token's decimals are truncated toward zero.
- From block
885588,max,limandamtmust be JSON strings, not numbers.
Activation heights
Protocol changes take effect at fixed Bitcoin block heights. On mainnet these heights are part of consensus:
| Feature | Height |
|---|---|
| TAP index start | 779832 |
| TAP protocol start | 801993 |
| DMT support | 817705 |
| Jubilee handling | 824544 |
| Privilege authorities | 841682 |
| Full ticker length range | 861576 |
| Value stringify gate | 885588 |
| DMT NAT miner rewards | 885588 |
| Token authority whitelist fix | 916233 |
| Miner reward shield | 941848 |
| Miner reward transfer execution shield | 942002 |
| Token locks, delegated locks, certified control, staking, sales, AMM authorities, conditional obligations, perp groups | 952317 |
| token-trade sunset | 954543 |
Token operations
The external layer works with three inscriptions: deploy a token, mint it, and inscribe transfers.
Deploy
{
"p": "tap",
"op": "token-deploy",
"tick": "tap",
"max": "21000000",
"lim": "1000",
"dec": "18"
}
tickandmaxare required.lim(the per-mint limit) anddecare optional.- A ticker can be deployed only once in its normalized (lowercase) form.
- A deployment can carry
dtametadata (a string up to 512 bytes) andprvto bind minting to a privilege authority.
Mint
{
"p": "tap",
"op": "token-mint",
"tick": "tap",
"amt": "1000"
}
- A mint cannot exceed the remaining supply or the mint limit.
- If the deployment names a privilege authority, the mint must carry a valid
prvsignature from it.
Transfer
A classic transfer takes two steps: inscribe a transfer inscription, then send that inscription to the receiver.
{
"p": "tap",
"op": "token-transfer",
"tick": "tap",
"amt": "100"
}
- The owner must have enough available balance when the transfer inscription is created; the amount then counts as transferable.
- Sending the inscription to another address moves the tokens to that address.
- For a one-transaction alternative, see 1-TX transfers.
824544, new cursed inscriptions are invalid. Older cursed tokens are addressed with a leading dash in their ticker (for example -tap).Account operations
Internal operations update account state after tapping. They do not need a separate transferable inscription per recipient.
token-send
Sends one or more token amounts from the tapped account in a single inscription.
{
"p": "tap",
"op": "token-send",
"items": [
{ "tick": "tap", "amt": "10000", "address": "bc1p9lpne8pnzq87dpygtqdd9vd3w28fknwwgv362xff9zv4ewxg6was504w20" },
{ "tick": "edg", "amt": "50", "address": "bc1p063utyzvjuhkn0g06l5xq6e9nv6p4kjh5yxrwsr94de5zfhrj7csns0aj4" }
]
}
- Every item needs
tick,amtandaddress, and can carrydtametadata. - Each amount spends available balance only. Invalid items are skipped; valid ones are credited.
Blocking transferables
block-transferables stops future incoming transfer inscriptions for an account; unblock-transferables turns them back on. This protects accounts that rely on authority balances or signed actions. Existing transferables stay valid.
{ "p": "tap", "op": "block-transferables" }
token-trade (retired)
token-trade created direct token-to-token trades. It is deprecated: from mainnet block 954543 it accepts no new create, fill or cancel actions. Historical state before that height is preserved. New integrations use authority-based locks, delegated execution, obligations, AMM authorities or marketplace-level settlement instead.
Authorities (token-auth)
token-auth lets an account create an authority and later execute signed redeems from it. It is the base for signed decisions that settle on chain, and it is what makes one-transaction transfers possible. An authority is identified by the inscription id of its tapped creation inscription.
Create and cancel
{
"p": "tap",
"op": "token-auth",
"sig": { "v": "0", "r": "…", "s": "…" },
"hash": "0f30c22be2f46e819538ca1281aadb82d3928cae5a699cade80013c5b14871e4",
"salt": "0.25991027744263695",
"auth": ["tap"]
}
authlists the tickers the authority may move. An empty list means every token held by the account.- The creation inscription must be tapped by the authority account. The signature is secp256k1 over
sha256(JSON.stringify(auth) + salt)and can be used once. - Cancel with
{"p": "tap", "op": "token-auth", "cancel": "<authority inscription id>"}, tapped by the same account. Cancelling stops new exposure (new redeems, locks, stakes, pool actions), but never blocks claims, refunds or exits of positions that already exist.
Redeems and 1-TX transfers
A redeem is signed by the authority and can be inscribed by anyone. Its items are processed like token-send from the authority account, and it needs no tapping by the submitter.
{
"p": "tap",
"op": "token-auth",
"sig": { "v": "1", "r": "…", "s": "…" },
"hash": "82e2b0d098dcdab820ff866b011250af8841a6b59cedd7164bb94b63d2598de9",
"salt": "0.46074583388095514",
"redeem": {
"auth": "<authority inscription id>",
"items": [
{ "tick": "tap", "amt": "546", "address": "bc1p9lpne8pnzq87dpygtqdd9vd3w28fknwwgv362xff9zv4ewxg6was504w20" }
],
"data": ""
}
}
- The redeem's public key must match the authority's creation key, and each signature works only once.
- If the authority lists tickers, every item must use one of them.
Redeem actions
A redeem can carry an actions array instead of, or next to, items (from block 952317). Actions are authority-signed operations evaluated in order; if one fails, the whole redeem fails and nothing is written.
| Family | Actions | What it enables |
|---|---|---|
| Locks | lock, claim, refund | HTLC swaps, timed releases, escrow and OTC settlement. A claim pays the claim target; after refund_after a refund returns the full amount. |
| Delegated execution | execute, execute-action, cancel-delegation | The authority pre-signs a template once; a later filler supplies the final values within the signed limits. |
| Allocations | al on a lock | Split claim proceeds to additional targets, such as fees or rewards. |
| Staking | auth-cfg (k: "stk"), stake, claim-rwd, unstake | Staking pools with weighted tiers and reward accounting. |
| Sales | auth-cfg (k: "sale"), fund-sale, contribute, finalize-sale, claim-sale, refund-sale … | Launches, capped and allowlisted sales with refunds and treasury payout. |
| AMM pools | auth-cfg (k: "amm"), add-liq, rm-liq, swap, sync-ext | Constant-product pools with LP shares for TAP/TAP, and TAP/external pools using attested reserve snapshots. |
| Obligations | ob-open, ob-claim, ob-refund, ob-final | Conditional obligations for account escrow, authority-backed settlement and AMM reserve settlement. |
| Perp groups | perp-policy, perp-open-group, perp-join, perp-settle … | Isolated, fixed-lifetime margin groups with TAP collateral only. |
Each family has exact field shapes and invariants in the specification.
Privilege authorities (privilege-auth)
privilege-auth lets a project or authority sign mint permissions and content-hash verifications (from block 841682). A token deployed with prv can only be minted with a valid signature from that privilege authority, which lets projects control who mints and how much.
DMT, Bitmap and BRC-20
- DMT tokens: TAP supports Digital Matter Theory elements for block field 4 (height), 10 (nonce) and 11 (bits), with
dmt-deployanddmt-mint. See the DMT specification. From block861576, Blockdrops for DMT UNATs and Bitmaps are supported. - DMT NAT miner rewards: from block
885588, NAT is credited to miners from each block's coinbase outputs, in proportion to their BTC value. Miner reward addresses have incoming transferables disabled from block941848; they can turn them on withunblock-transferables. - Bitmap: TAP indexers track Bitmap inscriptions under Bitmap rules.
- BRC-20 deployments: BRC-20 deployments from block
779832to861575that carry the built-in privilege authority are indexed, so those tickers can be used in TAP flows. Only deployments are indexed, not BRC-20 mints or transfers.
TAP Wallet
The TAP Wallet is a browser extension for TAP tokens, Bitcoin, Ordinals and the Trac Network. Install it from the Chrome Web Store.
What the wallet can do
Turn on 1-TX Transfers
Many TAP apps pay with 1-TX transfers. Turning them on is a one-time step that covers all your tokens:
- Open TAP Wallet, then Settings → Manage Authority.
- Press Create Authority. It applies to all tokens. Approve the small Bitcoin fee for the authority inscription.
- When it is ready, press Tap and approve the self-send.
- Wait until it shows Tapped. From then on, 1-TX Transfer appears next to your tokens and apps can request one-transaction payments.
You can cancel the authority later from the same screen. Cancelling stops new transfers through it but never blocks claims or refunds of positions that already exist.
For developers
The wallet injects window.tapprotocol into web pages. Every call that signs or spends opens an approval in the wallet.
| Area | Methods |
|---|---|
| Connect and read | requestAccounts, getAccounts, getNetwork, switchNetwork, getVersion, getPublicKey, getBalance, getInscriptions, getBitcoinUtxos, disconnect |
| Sign | signMessage, signData, signPsbt, signPsbts |
| Send | sendBitcoin, sendInscription, sendTapTransfer, pushTx, pushPsbt |
| TAP transfers | inscribeTransfer, singleTxTransfer |
| Authorities and actions | createTapAuthority, createGlobalTapAuthority, getCurrentAuthority, getAuthorityStatus, hasActiveAuthority, redeemTapActions, signTapDelegation, getTapActionOrderResult |
| Bitcoin HTLC | createBtcHtlcLock, claimBtcHtlc, refundBtcHtlc, decodeBtcHtlc |
For the Trac Network the wallet also injects window.tracnetwork with requestAccount, getAddress, getBalance, getNetwork, switchNetwork, getPublicKey, signMessage, sendTNK, buildTracTx, signTracTx and pushTracTx.
const tap = window.tapprotocol;
const [address] = await tap.requestAccounts();
const authority = await tap.getCurrentAuthority(); // null until 1-TX Transfers are on
const { txid } = await tap.singleTxTransfer([
{ tick: 'tap', amt: '10', address: 'bc1p…' }
]);
Indexers and data
Indexers must produce the same accepted and rejected state for the same ordered inscription stream. Every rule change is gated by an activation height, amounts follow the decimal and string rules, and invalid shapes are rejected before any state is written. You can read TAP data or run your own index:
ord client, with a REST API for current and historic state.Code and links
| What | Where |
|---|---|
| TAP Protocol specification | github.com/Trac-Systems/tap-protocol-specs |
| ord-tap indexer | github.com/Trac-Systems/ord-tap |
| TAP reader | github.com/Trac-Systems/tap-reader |
| TAP writer for ord-tap | github.com/Trac-Systems/tap-writer-ordtap |
| TAP Wallet | Chrome Web Store |
| DMT specification | digital-matter-theory.gitbook.io |