Node

What this indexer is reading, and how to point it at a real Zcash node instead.

Running a real node

ZRC-20 lives in transparent outputs, so any fully validating Zcash node can see everything this tool needs. There are two, and the choice matters: Zebra validates and serves blocks but has no wallet, so it can read inscriptions and not write them. zcashd has a transparent wallet, so it can do both.

zcashd — read and write
The one to pick if you want to inscribe. Its transparent wallet signs the transactions this app builds.
~/.zcash/zcash.conf
server=1
rpcuser=zrc20
rpcpassword=change-me-to-something-random
rpcport=8232
rpcallowip=127.0.0.1
txindex=1

# Relay the OP_RETURN outputs inscriptions live in.
datacarrier=1
datacarriersize=80
Point this app at it
export ZRC20_NETWORK=mainnet
export ZRC20_RPC_URL=http://127.0.0.1:8232
export ZRC20_RPC_USER=zrc20
export ZRC20_RPC_PASSWORD=change-me-to-something-random
export ZRC20_START_HEIGHT=2800000
npm run dev

txindex=1 is what lets the node answer getrawtransaction for any transaction, which the indexer needs when a block response only lists txids.

Zebra — read only
Lighter and actively developed, but it has no wallet, so this app can index through it and not inscribe.
zebrad.toml
[rpc]
listen_addr = "127.0.0.1:8232"

[state]
cache_dir = "/var/lib/zebrad"
Point this app at it
export ZRC20_NETWORK=mainnet
export ZRC20_RPC_URL=http://127.0.0.1:8232
npm run dev

Zebra does not attribute outputs to addresses in its RPC replies, so this indexer decodes the scripts itself. Balances come out the same either way.

Regtest — the honest middle ground
A real zcashd running real consensus on a private chain you control. Everything works end to end, and blocks arrive when you ask for them.
Start it with Docker
docker compose -f docker/zcashd-regtest.yml up -d
docker compose -f docker/zcashd-regtest.yml exec zcashd \
  zcash-cli -regtest generate 101
Point this app at it
export ZRC20_NETWORK=regtest
export ZRC20_RPC_URL=http://127.0.0.1:18232
export ZRC20_RPC_USER=zrc20
export ZRC20_RPC_PASSWORD=zrc20
export ZRC20_START_HEIGHT=0
npm run dev

Mainnet needs tens of gigabytes and hours of syncing before you see your first block. Regtest needs neither, and unlike the built-in devnet it exercises the real consensus rules — including whether your OP_RETURN actually relays.

Checking a claim yourself

Every balance on this site is recomputed from blocks, so any of it can be checked against the node directly. If a site claims a token exists and this sequence comes back empty, the token does not exist on Zcash.

Read the envelope out of a transaction
# Pull the raw transaction and look at its outputs.
zcash-cli getrawtransaction <txid> 1 | jq '.vout[].scriptPubKey.asm'

# An inscription is an OP_RETURN whose pushed data is UTF-8 JSON.
zcash-cli getrawtransaction <txid> 1 \
  | jq -r '.vout[] | select(.scriptPubKey.type=="nulldata") | .scriptPubKey.hex' \
  | tail -c +5 | xxd -r -p