The Liquid Asset Registry is Blockstream's official registry for assets issued on the Liquid sidechain. Built with FastAPI and PostgreSQL, it supports asset registration and discovery, signed issuer updates, admin governance, and append-only audit history while retaining compatibility with the legacy v1 API.
The Python API implementation lives under registry_api/, database migrations
under migrations/, and the generated API specification in openapi.yaml.
New registrations at POST /v2/assets must include contract.version: 2
(a JSON integer) and a non-null contract.initial_issuer_pubkey. Legacy
registration at POST / uses contract version 0; migrated legacy assets
retain that version in v2 responses. See the
versioning model for details.
The repository also includes a TypeScript SDK for Node.js and modern browsers. It provides typed clients for the v2 and legacy-compatible APIs, along with helpers for signing registrations and issuer actions. See the SDK README for installation and usage.
Domain verification is a registry acceptance check performed at registration time.
Audit entries record the registry's decision and accepted action payloads. They do not, by themselves, provide independently verifiable proof that the domain served the challenge at that time. Consumers who need that stronger guarantee would need an additional witness, transparency, DNSSEC, zkTLS, or notary-style proof system outside the current baseline API.
Start PostgreSQL and the API container:
docker compose up -dApply migrations:
ASSET_REGISTRY_DATABASE_URL=postgresql+psycopg://asset_registry:asset_registry@127.0.0.1:5433/asset_registry \
.venv/bin/alembic upgrade headRun the test suite without live PostgreSQL-backed tests:
.venv/bin/python -m pytestRun the full live PostgreSQL-backed test suite:
ASSET_REGISTRY_TEST_DATABASE_URL=postgresql+psycopg://asset_registry:asset_registry@127.0.0.1:5433/asset_registry \
.venv/bin/pytestRegenerate the OpenAPI snapshot after changing routes or schemas:
.venv/bin/python scripts/generate_openapi.py
.venv/bin/python scripts/generate_openapi.py --checkFastAPI and Pydantic are the source of truth. Do not edit openapi.yaml manually.
Schema upgrades use local history and never call Esplora. Older v2 registrations
may have no saved issuance references. After applying all migrations, fetch and
verify those missing references explicitly using the configured
ASSET_REGISTRY_ESPLORA_URL and ASSET_REGISTRY_DATABASE_URL:
.venv/bin/python -m registry_api.issuance_backfill --dry-run --limit 10
.venv/bin/python -m registry_api.issuance_backfillThe dry run makes network requests but writes nothing. The command checks the preserved registration contract hash, updates both response caches, and preserves asset timestamps and audit actions. Failures are logged per asset and yield a nonzero exit status; reruns retry missing references and skip completed assets. Conflicts with existing references are reported without overwriting them.
Revision 0017 also reconciles recoverable legacy contract data for databases
that already applied older 0014/issuance-reference implementations. Review migration warnings
for unresolvable rows; data erased from every historical source requires recovery
from a trusted backup or original listing.
V2 asset responses expose an approved icon as a registry-relative,
content-addressed URL under icon.href; assets without an approved icon return
icon: null. Resolve the URL against the registry base URL and cache the linked
PNG freely: hashed icon responses use immutable caching, and publishing a
replacement produces a new URL.
GET /v2/assets/{asset_id}/icon provides a stable per-asset URL that redirects
to the current content-addressed icon. The legacy /icons.json endpoint remains
available for clients that need a bulk Base64 map.
Legacy contracts may retain arbitrary extra fields for v1 compatibility; native v2 contracts remain strict. Validation bounds legacy input as follows:
- The canonical serialized
contractobject is limited to 4096 bytes by default.ASSET_REGISTRY_LEGACY_CONTRACT_MAX_BYTEScan temporarily raise this limit during a migration or shadow-write rollout. - A legacy contract may contain at most 32 extra fields, with each serialized extra-field value limited to 2048 bytes.
- The complete legacy registration request is limited to 16384 bytes.
See configuration for the related deployment settings.
AGENTS.md- repo guidance for coding agents.ARCHITECTURE.md- service design, trust boundaries, and compatibility model.CONTRIBUTING.md- contribution workflow and development checks.SECURITY.md- private vulnerability-reporting instructions.schema.md- database schema notes.docs/configuration.md- environment variables.docs/deployment.md- deployment notes.plans/- implementation plans and sequencing notes.openapi.yaml- generated OpenAPI snapshot for SDKs, reviews, and releases.
Licensed under the MIT License.