Guide

Archive CLI

Choose a portable JSON index for a website, or a self-contained archive for offline preservation.

Start with one command

bash
# Build a website index
npx @whitehash/archive project v2:13944
# Preserve one token offline
npx @whitehash/archive \
"https://www.fxhash.xyz/gentk/KT1KEa8z6vWXDJrVqtMrAeDVzsvxat3kHaCE-16333"

Choose your outcome

Start with the result you need. The index commands describe artwork for a hosted application; the archive commands collect the files needed to keep and replay it offline.

If you need to…UseYou get
Load artwork on a website--json, project, or tokenPortable JSON with normalized identities, metadata, and content-addressed URIs; not artwork bytes
Keep artwork available offlineAn identity-bearing token URL or walletA self-contained archive with artwork assets, previews, integrity data, and offline replay support

How the JSON formats align

Both index formats are designed for hosted applications, not offline preservation. They use the same normalized project and token shapes. A project index stores tokens in iterations[]; a token index stores one token at token. Missing chain metadata is written as null, never silently omitted.

For Tezos tokens, the CLI follows the gentk contract’s token_data.issuer_id back to the issuer project and loads its capture settings. For EVM tokens, the collection contract is the project ID, but capture settings remain null when the public collection/token metadata does not publish them.

FieldProject indexToken index
formatwhitehash-project-index@1whitehash-token-index@1
generatedAtISO timestampISO timestamp
projectNormalized project metadataThe same normalized project metadata
project.captureSettingsNormalized project capture configuration or nullThe same configuration when discoverable from the parent project
token dataiterations[].tokentoken
rawOriginal metadata on every tokenOriginal metadata on the token
paginationorder, complete, nextCursorNot applicable

Index a project

Tezos project IDs such as v2:13944 identify their chain automatically. For EVM projects, prefix the collection address with base: or ethereum:.

The CLI follows every discovery cursor and writes the versioned whitehash-project-index@1format. It includes normalized project data, display-ready iterations, and original token metadata for fields such as fx(params) that are not normalized yet. The project reader’s provider envelope is omitted.

Every iteration retains its canonical chain, contract, and tokenId. Use the static metadata immediately, or refresh that identity from chain when freshness matters.

bash
npx @whitehash/archive project v2:13944 \
--out ./public/monogrid.json

For a project’s market history, the market command writes listings, offers, sales, mints, and derived statistics into their own artifact. See the market history guide.

json
{
"format": "whitehash-project-index@1",
"generatedAt": "2026-07-23T12:00:00.000Z",
"order": "oldest",
"project": {
"chain": "tezos:mainnet",
"id": "v2:13944",
"name": "Monogrid 1.1",
"description": "…",
"displayUri": "ipfs://…",
"thumbnailUri": "ipfs://…",
"editions": 256,
"minted": 256,
"captureSettings": {
"mode": "VIEWPORT",
"triggerMode": "DELAY",
"gpu": false,
"resolution": { "x": 800, "y": 800 },
"delay": 2000
}
},
"iterations": [
{
"position": 1,
"token": {
"chain": "tezos:mainnet",
"contract": "KT1…",
"tokenId": "12345",
"name": "Monogrid 1.1 #0",
"description": "…",
"iterationHash": "oo…",
"artifactUri": "ipfs://…",
"displayUri": "ipfs://…",
"thumbnailUri": "ipfs://…",
"generatorUri": "ipfs://…",
"attributes": [{ "name": "Palette", "value": "Blue" }],
"assigned": true,
"metadataUri": null,
"raw": { "original": "metadata remains available here" }
}
}
],
"complete": true,
"nextCursor": null
}

Display an indexed project

Validate imported or fetched JSON before using it. Lookup is a direct array access and returns the ordinary WhitehashToken shape expected by Artwork.

tsx
import {
parseProjectIndex,
} from "@whitehash/chain-reader"
import { Artwork } from "@whitehash/ui"
const projectJson = await fetch("/monogrid.json").then(response => response.json())
const { iterations } = parseProjectIndex(projectJson)
const token = iterations[24]?.token
return token ? (
<Artwork.Root token={token}>
<Artwork.Image />
<Artwork.Live />
<Artwork.PlayButton />
</Artwork.Root>
) : null

Build a website index for one token

Paste an identity-bearing token URL with --json to write the smaller whitehash-token-index@1 format for a hosted website. This normalized JSON retains content-addressed URIs; it does not contain the artwork bytes.

bash
npx @whitehash/archive \
"https://www.fxhash.xyz/gentk/KT1KEa8z6vWXDJrVqtMrAeDVzsvxat3kHaCE-16333" \
--json \
--out ./public/token.json
# The existing coordinate form remains available:
npx @whitehash/archive token \
KT1U6EHmNxJTkvaWJ4ThczG4FSDaHC21ssvi 784640 \
--out ./public/monogrid-1.json
json
{
"format": "whitehash-token-index@1",
"generatedAt": "2026-07-23T12:00:00.000Z",
"project": {
"chain": "tezos:mainnet",
"id": "v2:13944",
"name": "monogrid 1.1 CE",
"description": "…",
"displayUri": "ipfs://QmXC…",
"thumbnailUri": "ipfs://QmTz…",
"editions": 256,
"minted": 256,
"captureSettings": {
"mode": "VIEWPORT",
"triggerMode": "DELAY",
"gpu": false,
"resolution": { "x": 800, "y": 800 },
"delay": 2000
}
},
"token": {
"chain": "tezos:mainnet",
"contract": "KT1U6EHmNxJTkvaWJ4ThczG4FSDaHC21ssvi",
"tokenId": "784640",
"name": "monogrid 1.1 CE #1",
"description": "…",
"iterationHash": "opas…",
"artifactUri": "ipfs://QmQt…",
"displayUri": "ipfs://QmfA…",
"thumbnailUri": "ipfs://QmaP…",
"generatorUri": "ipfs://QmQt…",
"attributes": [{ "name": "Style", "value": "Line" }],
"assigned": true,
"metadataUri": null,
"raw": { "original": "metadata remains available here" }
}
}

Display an indexed token

Validate the token JSON, extract its normalized token, and pass it directly to Artwork.

tsx
import {
parseTokenIndex,
} from "@whitehash/chain-reader"
import { Artwork } from "@whitehash/ui"
const json = await fetch("/monogrid-1.json").then(response => response.json())
const { project, token } = parseTokenIndex(json)
return (
<Artwork.Root token={token}>
<Artwork.Image />
<Artwork.Live />
<Artwork.PlayButton />
</Artwork.Root>
)

Refresh one token from chain

The index is an acceleration layer, not a new identity system. Resolve its token ref through the client when you need the latest reveal or metadata state.

tsx
import {
createWhitehashClient,
defaultChainReaderConfig,
tokenRef,
} from "@whitehash/chain-reader"
const ref = token ? tokenRef(token) : null
const current = ref
? await createWhitehashClient(defaultChainReaderConfig()).getToken(ref)
: null

Discover EVM iterations without an indexer

RPC mode probes the deployed fxhash collection’s supply and token-ID boundaries, constructs the verified zero- or one-based range, and hydrates those identities through on-chain tokenURI calls. A mint-event scan handles non-sequential contracts. It bypasses Blockscout for iteration discovery and produces the same index format.

bash
npx @whitehash/archive project \
base:0x50c04A6B066d659Fe2F66F6388Cf8dD394036632 \
--direct \
--out ./public/dom2.json

Preserve artwork offline

Paste an identity-bearing fxhash token URL to download IPFS CAR files or read onchfs bytes from chain, write available preview assets, and produce integrity hashes plus an offline wrapper. The identity is parsed locally without an fxhash-hosted service.

bash
npx @whitehash/archive \
"https://www.fxhash.xyz/gentk/KT1KEa8z6vWXDJrVqtMrAeDVzsvxat3kHaCE-16333"
npx @whitehash/archive verify ./whitehash-token-16333

The ordinary verify command is deterministic and offline: it checks hashes, required files, local references, and path safety. Add the explicit opt-in flag below to compare the recorded token snapshot with current public chain data.

bash
npx @whitehash/archive verify ./whitehash-token-16333 --onchain

Slug-only iteration links do not contain an on-chain identity. While the fxhash website remains available, resolve one explicitly and then run the same archive pipeline:

bash
npx @whitehash/archive \
"https://fxhash.xyz/iteration/monogrid-1.1-ce-256" \
--resolver fxhash

For collection-scale preservation, the existing wallet command uses the same archive writer and format:

bash
npx @whitehash/archive wallet tz1… \
--chains tezos \
--out ./whitehash-archive
npx @whitehash/archive verify ./whitehash-archive