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
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.
dtais accepted and carries no meaning. - Rules
- EN-4, EN-14, TK-1
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
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
A-4. Optional data at exactly 512 UTF-8 bytes
Two forms of the same limit, both accepted:
dtaof 512 ASCII characters, which is 512 UTF-8 bytes.dtaof 256 repetitions ofรฉ, which is also 512 UTF-8 bytes.
- Shows
- The
dtacap 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.
| Vector | Amount | Scale | Outcome |
|---|---|---|---|
| A-5 | 1.25 | 4 | 12500 |
| A-6 | 1 | 8 | 100000000 |
| A-7 | 0 | 8 | 0 |
| A-8 | 0 | 0 | 0 |
Rejected: payload shape
R-1. Duplicate field
{"p":"tap","p":"tap","op":"token-transfer","tick":"tapx","amt":"1"}
- Outcome
- Not a transfer. The field
pappears 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
R-2. Unknown field
{"p":"tap","op":"token-transfer","tick":"tapx","amt":"1","extra":"x"}
- Outcome
- Not a transfer. Only
p,op,tick,amtanddtaare permitted. - Rule
- EN-8
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
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
R-5. Trailing comma
{"p":"tap","op":"token-transfer","tick":"tapx","amt":"1",}
- Outcome
- Not a transfer.
- Rule
- EN-11
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
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
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
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
R-10. Leading zero
- Amount
01at a decimal scale of 0- Outcome
- Rejected. The integer part may not carry a leading zero.
- Rule
- AM-4
R-11. More precision than the deployment allows
- Amount
1.001at 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
R-12. Amount supplied as a number
- Amount
- The JSON number
1at a decimal scale of 0 - Outcome
- Rejected. The amount converter requires an exact string.
- Rule
- AM-3
R-13. Amount beyond the atomic range
- Amount
- The digit
1repeated 79 times, at a decimal scale of 0 - Outcome
- Rejected. The atomic value may be at most 78 digits.
- Rule
- AM-7
R-14. Optional data over the byte cap
Two forms of the same failure, both rejected:
dtaof 257 repetitions ofรฉ, which is 514 UTF-8 bytes.dtaof 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
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
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
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.
| Rules | Covered by |
|---|---|
| EN-2, EN-3 | R-7, R-8 |
| EN-4, EN-11, EN-12 | A-1, R-5, R-6 |
| EN-6, EN-7, EN-8 | R-1, R-2, R-3, R-4 |
| EN-14 | A-4, R-14 |
| TK-1, TK-2, TK-3, TK-6 | A-1, A-2, A-3, R-9 |
| AM-2 to AM-8 | A-5 to A-8, R-10 to R-13, R-15, R-16 |
| CA-5 | R-17 |
| ST-3 to ST-7 | Needs chain state. Exercise these against a live index rather than a payload. |
| AU-1 to AU-5 | Not covered here. Bitcoin Universe's TAP indexer does not index authority bearing operations, so this site publishes no authority vectors it cannot verify. |