Get your program decoded
The explorer turns raw instruction bytes into human-readable instruction names, typed arguments, and labelled accounts by reading your program's on-chain IDL. Arch programs are built with Satellite, Arch's Anchor-compatible framework: its CLI is invoked as anchor and its IDL follows the Anchor 0.30+ spec. So when you see anchor commands below, you are using Satellite's tooling — the names line up on purpose. Publish the IDL on-chain and the explorer decodes your instructions automatically; there is nothing to submit to the explorer itself.
What "decoded" means
Decoding here is IDL-driven — it is not decompilation or disassembly of your bytecode. With a published IDL, the explorer maps the 8-byte instruction discriminators to instruction names, Borsh-decodes each instruction's arguments against the IDL types, and labels every account by its role. Without an IDL, the explorer can only show the raw instruction bytes.
Prerequisites
- Your program is declared with the
#[program]macro. - The IDL build feature is enabled in your program's
Cargo.toml(see below). - You have not enabled the
no-idlfeature — it strips the on-chain IDL instructions, leaving nothing for the explorer to fetch.
Enable the IDL build feature
[features]
# Enables emitting the on-chain IDL when you build.
idl-build = ["satellite-lang/idl-build"]
# Do NOT enable `no-idl` — it strips the IDL instructions from your program,
# which means the explorer has nothing to fetch and decode.
# no-idl = []Step 1 — Build the IDL
Building emits the IDL JSON under target/idl/:
# Build the program and emit the IDL to target/idl/<program_name>.json
anchor build
# Or build just the IDL to an explicit path
anchor idl build -o target/idl/my_program.jsonStep 2 — Deploy the program
Deploy your program bytecode as usual. Gotcha: deploying does not publish the IDL on-chain — that is a separate step.
# Deploy the program bytecode.
# NOTE: this does NOT publish the IDL on-chain — see the next step.
anchor deployStep 3 — Publish the IDL on-chain
The first time, initialize the IDL account. The wallet that signs this becomes the IDL authority and is required for future upgrades.
# Publish the IDL on-chain for the first time.
# The wallet that signs this becomes the IDL authority.
anchor idl init <PROGRAM_ID> --filepath target/idl/my_program.jsonTo update the IDL later, upgrade it in place:
# Update the on-chain IDL after a change (must be the IDL authority).
anchor idl upgrade <PROGRAM_ID> --filepath target/idl/my_program.jsonOptional — Sanity checks
Confirm what is actually published before relying on it:
# Compare your local IDL against what is published on-chain.
anchor verify <PROGRAM_ID>
# Download the IDL currently stored on-chain.
anchor idl fetch <ADDRESS>What gets stored on-chain
For the curious: the IDL lives in a deterministically-derived account. The base is find_program_address([], program_id), and the IDL account itself is create_with_seed(base, "anchor:idl", program_id). The account layout is a 44-byte header — an 8-byte discriminator, a 32-byte authority, and a 4-byte length — followed by the zlib-compressed IDL JSON. The publishing wallet becomes the IDL authority (needed for future upgrades), and the compressed IDL is capped at roughly 60 KB.
How the explorer picks it up
Once the IDL account exists on-chain, the explorer resolves it automatically on demand: it derives the IDL account address, fetches it over RPC, inflates the compressed JSON, validates it, and caches it. After that, any transaction touching your program shows decoded instructions. There is no submission or registration step with the explorer — publishing the IDL on-chain is enough.
You can also read the cached IDL directly via the REST API:
GET /api/v1/{network}/programs/{program_id}/idlSee the REST API reference for authentication and base URLs.
Next steps
After publishing, open your program's page in the explorer — or any transaction that calls it — to see decoded instructions with named arguments and labelled accounts.