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.
Before you begin
Section titled “Before you begin”- Finish Build a Charms app — you’ll reuse that project.
- Set up a Bitcoin node on
testnet4with a funded wallet. We assumealias b=bitcoin-cliandjqis installed.
Move into your app directory and rebuild it:
cd ./my-tokenapp_bin=$(charms app build)export app_vk=$(charms app vk $app_bin)export RUST_LOG=info1. Pick a UTXO to spend
Section titled “1. Pick a UTXO to spend”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):
# choose a UTXO from your walletexport in_utxo_0=$(b listunspent | jq -r '.[0] | "\(.txid):\(.vout)"')
# the NFT's identity = SHA-256 of that UTXO idexport 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))2. Fill in the spell’s outputs
Section titled “2. Fill in the spell’s outputs”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:
export dest_0=$(charms util dest --addr $(b getnewaddress))export amount_0=20000 # sats carried by the NFT outputexport change_address=$(b getrawchangeaddress)3. Prove the spell
Section titled “3. Prove the spell”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.
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:
tx=$(echo "$out" | jq -r '.[0].bitcoin')4. Sign and broadcast
Section titled “4. Sign and broadcast”Sign with your wallet, then send it to the network:
signed=$(b signrawtransactionwithwallet "$tx" | jq -r '.hex')b sendrawtransaction "$signed"sendrawtransaction prints the txid. Your NFT is now minted on testnet4! 🎉
5. Verify
Section titled “5. Verify”Inspect the spell carried by your transaction:
charms tx show-spell --tx "$signed"You can also look the txid up on mempool.space/testnet4.
What’s next
Section titled “What’s next”- Mint tokens against your NFT, or transfer charms — see the How-to guides.
- Understand what just happened: Spells and Transactions.
- Run proving yourself: Run a prover server.