github cardano-foundation/cf-token-metadata-registry 2.0.0
v2.0.0

pre-release3 hours ago

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:

  1. 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.
  2. 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 with validation_errors and metadata.valid: false, so name and description are no longer guaranteed. For the closest to the old behaviour, ask with ?validation=MANDATORY_ONLY (#111).
  3. V2 metadata.valid changed meaning. It was true when name and description were present; it is now true only when the token has no validation errors at all, optional fields included (#111).
  4. 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).
  5. 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).
  6. The CIP-26 logo in the V2 metadata block is base64, as CIP-26 defines it and as standards.cip26 and V1 already returned it. It was hex (#88).
  7. Health components renamed: onchainConnection is now nodeHealth and onchainReadiness is now nodeSync (yaci-store's own indicators), in /actuator/health and in the startup, liveness and readiness groups. Update dashboards and alerts that read them (#93).
  8. CIP-113 is on in the shipped .env and .env.preprod: they set CIP113_REGISTRY_NFT_POLICY_IDS to 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_errors list (cip, sub_standard, field_name, field_category MANDATORY/OPTIONAL, code, error) on the subject and on standards.*;
    • metadata.valid is true only when there are no errors;
    • ?validation=ALL|MANDATORY_ONLY|STRICT (default ALL) 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_token table.
  • CIP-68 rich fungible tokens (label 444, prefix 001bc280) are served from the V2 API. Their image is served as metadata.logo, and description is 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_IDS is set;
    • V2 adds type (NATIVE or PROGRAMMABLE) and an extensions.cip113 block 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 PROGRAMMABLE with one MANDATORY companion_metadata error naming the missing fields (#118, #122).

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):
    • decimals range 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 a chunked_text error 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 000643b0 prefix, 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_version code (#123).
  • CIP-26:
    • subjects are stored and served in lower case;
    • a url without 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 yaci library 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 NodeHealthIndicator and NodeSyncIndicator, 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-registry instead of server-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

  • The native image cannot run in read-only mode (#90). A separate read-only native image is in #113.

Full changelog: 1.7.0...2.0.0

Don't miss a new cf-token-metadata-registry release

NewReleases is sending notifications on new releases.