TAPProtocol documentation

Test vectors

TAP test vectors

Every vector on this page is taken from the test suite of Bitcoin Universe's TAP indexer, not invented for documentation. If your implementation agrees with all of them, it agrees with the indexer that Bitcoin Universe runs.

How to read these

Unless a vector says otherwise, the content is being checked as a TAP token-transfer, at inscription number 1, with a maximum content size of 8192 bytes. The decimal scale used for amount conversion is stated per vector. Rule identifiers point into the specification.

You can paste any of these into the validator and watch the same decision being made.

Accepted vectors

Accepted

A-1. Whitespace, mixed case ticker, optional data

 { "p" : "tap", "op":"token-transfer", "tick":"Tร„P", "amt":"1.25", "dta":"evidence" } 
Indexed ticker
tรคp
Amount
1.25
Shows
Whitespace is allowed around and between tokens. The ticker is folded to NFC lower case. dta is accepted and carries no meaning.
Rules
EN-4, EN-14, TK-1
Accepted

A-2. Negative inscription number

{"p":"tap","op":"token-transfer","tick":"tapx","amt":"1"}
Inscription number
-1
Indexed ticker
-tapx
Shows
A cursed inscription's ticker is placed in its own namespace with a single leading hyphen, so it cannot collide with the ticker of the same name on an ordinary inscription.
Rules
TK-6, CA-6
Accepted

A-3. Ticker at the exact UTF-16 limit

{"p":"tap","op":"token-transfer","tick":"๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€","amt":"1"}
Ticker length
16 characters, 32 UTF-16 code units, 64 UTF-8 bytes
Shows
The ticker limit is measured in UTF-16 code units, not in characters. An astral character such as an emoji counts as two, so sixteen of them exactly fill the limit.
Rules
TK-2, TK-3
Accepted

A-4. Optional data at exactly 512 UTF-8 bytes

Two forms of the same limit, both accepted:

  • dta of 512 ASCII characters, which is 512 UTF-8 bytes.
  • dta of 256 repetitions of รฉ, which is also 512 UTF-8 bytes.
Shows
The dta cap is measured in UTF-8 bytes, not in characters. A two byte character costs two.
Rules
EN-14

Amount conversions

Amounts are converted to atomic integers by string padding at the deployment's decimal scale.

VectorAmountScaleOutcome
A-51.25412500
A-618100000000
A-7080
A-8000

Rejected: payload shape

Rejected

R-1. Duplicate field

{"p":"tap","p":"tap","op":"token-transfer","tick":"tapx","amt":"1"}
Outcome
Not a transfer. The field p appears twice.
Why it matters
A permissive JSON reader keeps the last value silently. Two implementations reading the same inscription would then disagree about what it said.
Rule
EN-7
Rejected

R-2. Unknown field

{"p":"tap","op":"token-transfer","tick":"tapx","amt":"1","extra":"x"}
Outcome
Not a transfer. Only p, op, tick, amt and dta are permitted.
Rule
EN-8
Rejected

R-3. Nested value

{"p":"tap","op":"token-transfer","tick":"tapx","amt":{"value":"1"}}
Outcome
Not a transfer. Every value must be a JSON string.
Rule
EN-6
Rejected

R-4. Numeric amount

{"p":"tap","op":"token-transfer","tick":"tapx","amt":1}
Outcome
Not a transfer. A JSON number is rejected even though it looks unambiguous.
Why it matters
JSON numbers have no fixed precision. Accepting them invites two readers to disagree at the eighteenth decimal place.
Rules
EN-6, AM-3
Rejected

R-5. Trailing comma

{"p":"tap","op":"token-transfer","tick":"tapx","amt":"1",}
Outcome
Not a transfer.
Rule
EN-11
Rejected

R-6. Data after the object

{"p":"tap","op":"token-transfer","tick":"tapx","amt":"1"}{}
Outcome
Not a transfer. The content must be exactly one object.
Rule
EN-12

Rejected: encoding

Rejected

R-7. Byte order mark

The bytes EF BB BF followed by an otherwise valid transfer:

EF BB BF 7B 22 70 22 3A 22 74 61 70 22 ...
Outcome
Not a transfer. A byte order mark is a rejection, not something to strip before parsing.
Why it matters
Text editors add one silently. Stripping it would make two byte sequences produce the same operation.
Rule
EN-2
Rejected

R-8. Not valid UTF-8

FF FE
Outcome
Not a transfer. The decoder is strict and does not substitute replacement characters.
Rule
EN-3

Rejected: ticker

Rejected

R-9. Ticker over the UTF-16 limit

A ticker of 20 astral characters, which is 20 characters but 40 UTF-16 code units:

{"p":"tap","op":"token-transfer","tick":"๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€๐Ÿ˜€","amt":"1"}
Outcome
Not a transfer. The ticker fails the ticker rule at 40 UTF-16 code units against a limit of 32.
Contrast with
Vector A-3, where 16 of the same character fit exactly.
Rule
TK-2

Rejected: amount

Rejected

R-10. Leading zero

Amount
01 at a decimal scale of 0
Outcome
Rejected. The integer part may not carry a leading zero.
Rule
AM-4
Rejected

R-11. More precision than the deployment allows

Amount
1.001 at a decimal scale of 2
Outcome
Rejected. Three fractional digits against a scale of two. The amount is not rounded or truncated.
Rule
AM-5
Rejected

R-12. Amount supplied as a number

Amount
The JSON number 1 at a decimal scale of 0
Outcome
Rejected. The amount converter requires an exact string.
Rule
AM-3
Rejected

R-13. Amount beyond the atomic range

Amount
The digit 1 repeated 79 times, at a decimal scale of 0
Outcome
Rejected. The atomic value may be at most 78 digits.
Rule
AM-7
Rejected

R-14. Optional data over the byte cap

Two forms of the same failure, both rejected:

  • dta of 257 repetitions of รฉ, which is 514 UTF-8 bytes.
  • dta of 513 ASCII characters, which is 513 UTF-8 bytes.
Outcome
Rejected. The cap is 512 UTF-8 bytes, and one byte over is enough.
Contrast with
Vector A-4, where both forms land exactly on 512.
Rule
EN-14

Rejected: deployment and holder records

Rejected

R-15. Decimal scale out of range

Declared scale
19
Outcome
The deployment is rejected. Token decimals must be between 0 and 18.
Rule
AM-2
Rejected

R-16. Negative holder balance

Record
A holder row whose balance is below zero
Outcome
Rejected. A balance can never be negative, and the indexer refuses the record rather than clamping it.
Rule
AM-8
Rejected

R-17. Mixed case Bech32 address

Record
An address that is neither wholly lower case nor wholly upper case
Outcome
Rejected. Mixed case Bech32 is invalid by construction, and the indexer will not normalise it into something acceptable.
Rule
CA-5

Rule coverage

Which rules these vectors exercise, and which ones need chain state rather than a payload to test.

RulesCovered by
EN-2, EN-3R-7, R-8
EN-4, EN-11, EN-12A-1, R-5, R-6
EN-6, EN-7, EN-8R-1, R-2, R-3, R-4
EN-14A-4, R-14
TK-1, TK-2, TK-3, TK-6A-1, A-2, A-3, R-9
AM-2 to AM-8A-5 to A-8, R-10 to R-13, R-15, R-16
CA-5R-17
ST-3 to ST-7Needs chain state. Exercise these against a live index rather than a payload.
AU-1 to AU-5Not covered here. Bitcoin Universe's TAP indexer does not index authority bearing operations, so this site publishes no authority vectors it cannot verify.