Code projects
A code project is an ABX contract whose content is a program. Its output follows the determinism
contract, (content, params, environment) -> output.
Two custody modes
- Directory. The code is an off-chain build directory with an
index.htmlentry, on IPFS, Arweave, or a URL. The on-chain surface is thecodecollection field, which holds a locator only, never inline bytes. - Template. The code is stored on-chain in chunks, through the On-Chain Script and Dependencies extensions. Dependency index 0 is the runtime, by convention. A generator assembles the dependencies in order, injects the token data, and concatenates the script chunks.
tokenData
The program receives one flat object, tokenData. It is the contract-scope and token-scope
parameters merged, with token scope winning, and read-time hook entries applied last. Each value is
decoded to its canonical string form.
{
"chainId": 1,
"contractAddress": "0x1a2b...",
"tokenId": "42",
"seed": "0x9f31...",
"palette": "#0e1a40",
"density": "0.85"
}
chainId, contractAddress, tokenId, and seed are reserved keys. seed is present only when a
seed source assigned it. The serialization is canonical: JSON, keys sorted, no insignificant
whitespace, UTF-8, because it is hashed as part of an effect's inputs.
tokenData reaches the program three ways: injected as a window.abxTokenData global (template, or a
resolver-served directory), carried in the URL as a base64 abx query parameter (directory, budgeted
at about 8 KB), or passed to a render node as input. A runtime companion, abx.js, resolves the token
data from the injected global, then the query parameter, then RPC. It also exposes abx.traits({...})
to report traits and abx.done() to signal that output is complete. abx.js is a convention, not
protocol.
Seeds
Mint-time randomness is configuration, through the Seed Source extension. A contract stores a
seed-source address; at mint it calls IAbxSeedSource.seed(tokenId, to) and stores the result as the
token's seed parameter. The canonical source is AbxSeedSource, one shared pseudorandom source per
chain. A project can point at any contract that satisfies the interface, such as a commit-reveal or an
artist-curated source. A seed is settled once assigned, and immutable unless a parameter schema
authorizes reconfiguration.
On-chain rendering
The canonical field renderer, AbxGenerator, produces the animation field for both custody modes:
- Template branch. With script chunks present, it emits a full HTML document: the token data,
abx.js, the dependencies in order, and the script chunks. It is chain-complete when every dependency resolves to on-chain bytes. - Directory branch. With a
codefield present, it emits a locator with the token data in the query string, served through a gateway.
onChainStatus(token) reports which branch was taken, whether the project is chain-complete, and any
unresolved dependency references. A static image cannot be produced on-chain, because rendering a
program to a PNG needs a browser.
Traits
Traits have two homes. By default they are computed at render time: the script reports them with
abx.traits(...), and the render effect captures and stores them off-chain. A project can instead put
traits on-chain by setting the attributes field to a renderer representation, so a field renderer
computes them. When both exist, they are unioned, and the on-chain value wins on a trait_type
conflict.
How metadata is derived
animation_url: an explicitanimationfield wins; otherwise, if code is present and not suppressed, the resolver's live-view route; otherwise it is omitted.image: an explicitimagefield wins; otherwise the latest boundrender.imageeffect output; otherwise a deterministic placeholder.
Until an effect produces render.image, the token shows the deterministic placeholder. When a project renders is the artist's choice.