Skip to content

Cast your first spell

In Build a Charms app you checked a spell locally. Now you’ll cast one for real: mint an NFT on Bitcoin testnet4 by proving the spell, signing the transaction, and broadcasting it.

Move into your app directory and rebuild it:

Terminal window
cd ./my-token
app_bin=$(charms app build)
export app_vk=$(charms app vk $app_bin)
export RUST_LOG=info

The NFT’s identity is derived from a UTXO you spend when minting. Pick one you control and record the transaction that created it (the prover needs it):

Terminal window
# choose a UTXO from your wallet
export in_utxo_0=$(b listunspent | jq -r '.[0] | "\(.txid):\(.vout)"')
# the NFT's identity = SHA-256 of that UTXO id
export app_id=$(echo -n "${in_utxo_0}" | sha256sum | cut -d' ' -f1)
# the raw transaction that produced the UTXO (a prerequisite for proving)
export prev_txs=$(b getrawtransaction $(echo $in_utxo_0 | cut -d: -f1))

The mint-nft.yaml template puts the new NFT on a fresh output. Derive the destination from a new wallet address, and set the output amount and a change address:

Terminal window
export dest_0=$(charms util dest --addr $(b getnewaddress))
export amount_0=20000 # sats carried by the NFT output
export change_address=$(b getrawchangeaddress)

Proving runs the app contract and generates the zero-knowledge proof. By default the CLI sends the request to the hosted prover at https://v15.charms.dev/spells/prove — this takes a little while.

Terminal window
out=$(cat ./spells/mint-nft.yaml | envsubst | charms spell prove \
--app-bins=$app_bin \
--prev-txs=$prev_txs \
--private-inputs=<(cat ./spells/mint-nft-private.yaml | envsubst) \
--change-address=$change_address)

charms spell prove prints a JSON array containing one unsigned Bitcoin transaction — the spell transaction, with the spell and its proof in an OP_RETURN output. Extract its hex:

Terminal window
tx=$(echo "$out" | jq -r '.[0].bitcoin')

Sign with your wallet, then send it to the network:

Terminal window
signed=$(b signrawtransactionwithwallet "$tx" | jq -r '.hex')
b sendrawtransaction "$signed"

sendrawtransaction prints the txid. Your NFT is now minted on testnet4! 🎉

Inspect the spell carried by your transaction:

Terminal window
charms tx show-spell --tx "$signed"

You can also look the txid up on mempool.space/testnet4.