Spell JSON Reference
Spell is the metadata added to a Bitcoin transaction to make it also a Charms transaction: spells create charms. This reference provides an explanation of each parameter in the Spell JSON format.
Structure Overview
The Spell JSON has the following top-level fields:
version: Protocol version identifierapps: Application identifiers and verification keyspublic_inputs: Public inputs for apps (optional)private_inputs: Private inputs for apps (optional) — not recorded on-chain.ins: Input UTXOs containing charmsouts: Output destinations for charms
Parameter Details
version
Protocol version number.
"version": 2Required Value: Must be 2 for the current protocol.
Spells exist on-chain with lower versions, and they are recognized by the client, but are not supported by the prover.
apps
Lists apps involved in the transaction. Each app is specified by a tag, identity and verification key.
"apps": { "$00": "n/<app_id>/<app_vk>", "$01": "t/<app_id>/<app_vk>"}$00,$01: App references within the spell (can be any unique identifier)- tag:
n— the app represents an NFT,t— the app represents a fungible token <app_id>: hex-encoded 32-byte app identity (the same for related NFTs/tokens)<app_vk>: hex-encoded 32-byte app verification key
There can be multiple apps in the same spell. Apps only different in the tag (e.g. n vs t) are considered different apps. Such apps can be related (and most likely are), for example, an NFT can manage issuance of a fungible token and carry token metadata (name, ticker symbol, description, logo, website URL, etc.) as recommended in CHIP-420.
public_inputs
Public inputs for proving the transaction against app contracts. This section is optional. It is not needed for simple transfers.
"public_inputs": { "$00": <public input data for app $00>, "$0N": <public input data for app $0N>}$00,$0N: App references (same as in theappssection). Any app from theappssection can have an entry here, but it is not required.<public input data>: Public input data required for the app’s proof generation. This data is recorded on-chain.
private_inputs
Private inputs for proving the transaction against app contracts. This section is optional. It is not needed for simple transfers.
"private_inputs": { "$00": <private input data for app $00>, "$0N": <private input data for app $0N>}$00,$0N: App references (same as in theappssection). Any app from theappssection can have an entry here, but it is not required.<private input data>: Private input data required for the app’s proof generation. This data is not recorded on-chain.
ins
Input UTXOs of the transaction. This section is required (can be an empty list — for transactions not spending any outputs with charms).
"ins": [ { "utxo_id": "<txid>:<vout>", "charms": { "$00": <charm data>, "$0m": <charm data> } }, { "utxo_id": "<source_txid>:<vout>", "charms": { "$00": <charm data>, "$0n": <charm data> } }]utxo_id: Transaction ID and output index (txid:vout) of a UTXO being spentcharms: Charms in the specified UTXO- $00, $0m, $0n: App references (same as in the
appssection). Any app from theappssection can have charms in source UTXOs. <charm data>: Depending on the app, this can be a single unsigned integer value (for fungible tokens) or a complex object (for NFTs). For example:- For fungible tokens:
<charm data>is the amount of the token in the UTXO - For NFTs:
<charm data>is an object containing metadata properties of the NFT
- For fungible tokens:
- $00, $0m, $0n: App references (same as in the
outs
Transaction outputs. This section is required (can be an empty list — for transactions not creating any outputs with charms).
"outs": [ { "address": "<destination_address>", "charms": { "$00": <charm data>, "$0m": <charm data> }, "sats": 1000 }, { "address": "<destination_address>", "charms": { "$00": <charm data>, "$0n": <charm data> }, "sats": 1000 }]address: Recipient’s Bitcoin addresscharms: Charms in the specified UTXO- $00, $0m, $0n: App references (same as in the
appssection). Any app from theappssection can have charms in source UTXOs. <charm data>: Depending on the app, this can be a single unsigned integer value (for fungible tokens) or a complex object (for NFTs). For example:- For fungible tokens:
<charm data>is the amount of the token in the UTXO, e.g.42or69000 - For NFTs:
<charm data>is an object containing metadata properties of the NFT — see CHIP-420
- For fungible tokens:
- $00, $0m, $0n: App references (same as in the
sats: Amount of satoshis to include in the output (optional, defaults to 1000, can be as low as the current dust limit)
Implementation Tips
- Retrieve the UTXO information from your wallet’s UTXO set
- Validate all values before constructing the final JSON
- Use proper JSON serialization to avoid formatting issues
![[object Object]](./src/assets/logo-charms.png)