cf-token-metadata-registry 2.0.0
2.0.0 changes what the registry serves and how it reports problems. A token that breaks its CIP is now served with its validation errors instead of being dropped, rich fungible tokens (CIP-68 label 444) and CIP-113 programmable tokens are served from the V2 API, and the on-chain indexer is hardened against untrusted datums.
Warning
2.0.0 is not backwards compatible. Every incompatible change:
- A full resync from an empty database is required. Tokens that earlier versions dropped exist nowhere yet, rows written by earlier versions have no validation errors recorded, and CIP-26 subjects are now stored in lower case with no migration for existing rows (#111, #117, #118). Migrations V3 to V7 are additive, so an old database starts, but it does not hold what 2.0.0 serves.
- V2 returns tokens it used to answer 404 for, by default (
?validation=ALL): no name or description, a CIP-68 version 0, a logo that is not a URI, chunked texts, and so on. They come withvalidation_errorsandmetadata.valid: false, sonameanddescriptionare no longer guaranteed. For the closest to the old behaviour, ask with?validation=MANDATORY_ONLY(#111). - V2
metadata.validchanged meaning. It wastruewhennameanddescriptionwere present; it is nowtrueonly when the token has no validation errors at all, optional fields included (#111). - V1 serves CIP-26 entries that break CIP-26, which it used to leave out, such as an entry without a description or with a name over 50 characters. V1 keeps its format, so it does not show their errors, and has no opt-out: a client that needs to tell them apart must use V2 (#111, ADR-019).
- Subjects are case-sensitive on lookup, and CIP-26 subjects are stored in lower case. 39 mainnet registry files are named in upper case. Their subjects now answer only in lower case, on V1 and V2; an upper-case query, which used to work for them, is a 404 (#117).
- The CIP-26 logo in the V2
metadatablock is base64, as CIP-26 defines it and asstandards.cip26and V1 already returned it. It was hex (#88). - Health components renamed:
onchainConnectionis nownodeHealthandonchainReadinessis nownodeSync(yaci-store's own indicators), in/actuator/healthand in the startup, liveness and readiness groups. Update dashboards and alerts that read them (#93). - CIP-113 is on in the shipped
.envand.env.preprod: they setCIP113_REGISTRY_NFT_POLICY_IDSto the official deployments, so a Docker Compose deployment serves CIP-113 data without opting in. Set it to empty to turn it off (#68).
New parameters and fields
| What | Where | Values | Default |
|---|---|---|---|
validation query parameter
| V2 only: GET /api/v2/subjects/{subject}, POST /api/v2/subjects/query (V1 has none)
| ALL: every indexed token. MANDATORY_ONLY: tokens without a MANDATORY error. STRICT: tokens without any error. A token left out is a 404, or missing from a batch
| ALL
|
CIP113_REGISTRY_NFT_POLICY_IDS environment variable (cip113.registry.nft.policy-ids)
| API | Comma-separated registry-node NFT policy IDs of the CIP-113 deployments to index. CIP-113 is on when it is not empty | empty (off); set in the shipped .env files
|
validation_errors response field
| V2: on the subject, standards.cip26 and standards.cip68
| A list of {cip, sub_standard, field_name, field_category, code, error}; under ?property= limited to the properties asked for
| |
type response field
| V2 subject | NATIVE or PROGRAMMABLE (CIP-113)
| |
extensions.cip113 response field
| V2 subject, for a token of a registered CIP-113 policy | The minting, transfer, third-party and unfracking logic scripts of its registry node |
Features
- Validation errors are reported, not enforced (#111, ADR-019, ADR-020):
- every CIP-26 entry and CIP-68 datum is indexed as written, with a
validation_errorslist (cip,sub_standard,field_name,field_categoryMANDATORY/OPTIONAL,code,error) on the subject and onstandards.*; metadata.validistrueonly when there are no errors;?validation=ALL|MANDATORY_ONLY|STRICT(defaultALL) chooses which tokens are returned; under?property=the errors are limited to the properties asked for;- what cannot be stored at all (an undecodable datum, an unusable CIP-26 file, an unparseable CIP-113 node, a logo over the hard size cap) is recorded in a new
invalid_tokentable.
- every CIP-26 entry and CIP-68 datum is indexed as written, with a
- CIP-68 rich fungible tokens (label 444, prefix
001bc280) are served from the V2 API. Theirimageis served asmetadata.logo, anddescriptionis optional for them, as CIP-68 says (#110, ADR-018). - CIP-113 programmable tokens (#68):
- registry nodes are indexed from the official CIP-113 deployments when
CIP113_REGISTRY_NFT_POLICY_IDSis set; - V2 adds
type(NATIVEorPROGRAMMABLE) and anextensions.cip113block with the minting, transfer, third-party and unfracking logic scripts; - a token of a registered policy without CIP-26 or CIP-68 metadata is served as
PROGRAMMABLEwith oneMANDATORYcompanion_metadataerror naming the missing fields (#118, #122).
- registry nodes are indexed from the official CIP-113 deployments when
Bug fixes
- Indexing can no longer stop the sync. An output whose CIP-68 indexing fails unexpectedly is skipped with a WARN; the rest of the block is indexed (#109).
- Hardening against untrusted on-chain input, ported from yaci-store
assets-ext(#105, #107):decimalsrange checks for CIP-26 and CIP-68;- CIP-68 version 4 nested-map datums, Plutus constructors as property values, text that is not UTF-8, several reference NFTs in one output;
- a logo size cap and a limit on how deeply a datum can be nested.
- CIP-68 rules are checked when a token is served, for the label asked for (333 or 444), instead of the label guessed when the datum was indexed. A 333 updated without its user token is no longer served as valid (#118).
- Texts given as a list of chunks (
description,url,name) are joined and served with achunked_texterror instead of being dropped; each description problem is reported once, with the label's category (#117). - What is stored:
- a datum without a user token in its transaction is stored, so RFTs whose 444 token was minted in another transaction are served (#121);
- a datum minted with a 222 NFT and no 333 or 444 token is not stored, so NFTs are not served as fungible tokens (#121);
- a datum that is not token metadata (dApp state under the
000643b0prefix, an empty map) is no longer indexed as a 333 (#117).
- CIP-68 version: every problem with a version that is present but unusable (not an integer, too large, not 1 to 4) is one
invalid_versioncode (#123). - CIP-26:
- subjects are stored and served in lower case;
- a
urlwithout a host (https:/example.com) fails validation (#117).
invalid_token: stale CIP-26 rows are deleted in a transaction. They failed for every file, with 7,982 WARNs per sync (#116).- Docker Compose: the database restarts after a host reboot. The API crash-looped without it (#116).
Dependencies
- yaci-store 2.0.4 → 2.0.7, and the
yacilibrary pinned on its own to 0.4.7. yaci 0.4.6 and earlier read a block with 128 to 255 transactions as empty; mainnet block 14,053,493 is the first one affected (#108).
Chores and maintenance
- On-chain health uses yaci-store's own
NodeHealthIndicatorandNodeSyncIndicator, so each check is reported once instead of twice (#93). - Docker images are built on pull requests (#115).
- The SonarCloud project is named
cf-token-metadata-registryinstead ofserver-base(#103). - The release-please workflow uses an access token, so a release triggers the image builds (3bd5217, 293b6f8, 0a8b15f).
Tests
- Mainnet regression suites for CIP-68 rich fungible tokens, validation errors and CIP-113 (mainnet and preprod), run against a sync from scratch: 4,726 passed, 0 failed (fae642e, #120, 3321b63).
- Integration test for a CIP-113 policy without companion metadata (#119).
- The mainnet CIP-68 fixture is corrected entry by entry against the chain, not regenerated (#120).
Documentation
- ADR-017 (superseded by ADR-019), ADR-018 (rich fungible tokens), ADR-019 (validation errors are reported, not enforced), ADR-020 (
invalid_token, CIP-113), ADR-022 (rejected: a 333/444 subject is served whether or not its user token was minted). ADR-004, ADR-010 and ADR-016 are amended.
Known issues
Full changelog: 1.7.0...2.0.0