CCDExplorer is the open-source Concordium blockchain explorer that powers ccdexplorer.io, the public API, and the user-facing Notification Bot. The codebase collects on-chain data straight from a Concordium node, enriches it through background services, and serves it via FastAPI applications for browsers, bots, and programmatic clients.
- Comprehensive Concordium coverage – blocks, transactions, accounts, smart contracts, and modules are indexed in real time, with every-block workers tracking chain health, new accounts, and new or upgraded contracts/modules.
- Developer-friendly API – FastAPI-powered endpoints expose raw chain data alongside derived metrics for integrations, trading dashboards, or research. Public Swagger docs are available at /docs, with schemas derived from the gRPC definitions that the components share.
- Notifications and user tools – the notification bot lets users subscribe to account, contract, or chain events directly from ccdexplorer.io, backed by the same services that drive the explorer frontend.
- On-chain analytics – scheduled jobs compute data sets such as transactions by type, per-project usage, unique address counts, daily holder & limit statistics, and realized price series to give Concordium participants contextual insights.
- Polylith monorepo – the repository uses Polylith for Python to keep components, bases, and projects isolated yet composable, making it easy to reuse bricks across services.
flowchart TD
subgraph EXT[Concordium]
chain[(Nodes 2x mainet, 2x testnet)]
%% web((Explorer Users))
%% botusers((Telegram / Email Users))
end
subgraph CORE[Core Infrastructure]
mongo[(MongoDB 3 Member Replica Set)]
redis[(Redis + Celery Broker)]
tooter[(Apprise Notifications)]
end
subgraph INGEST[Real-time Ingestion]
heartbeat[Heartbeat]
analyzer[Block Analyzer]
end
subgraph MICRO[Microservices]
ms_accounts[MS Accounts]
ms_events[MS Events & Impacted]
ms_indexers[MS Indexers]
ms_instances[MS Instances]
ms_modules[MS Modules]
ms_metadata[MS Metadata]
ms_token[MS Token Accounting]
ms_plt[MS PLT]
%% ms_bot_sender[MS Bot Sender]
end
subgraph ANALYTICS[Analytics]
accounts[Accounts Retrieval]
dag_nightrunner[Dagster Nightrunner]
dag_recurring[Dagster Recurring]
dag_paydays[Dagster Paydays]
end
subgraph Pipelines[Analytics & Events]
INGEST[Real-time Ingestion]
MICRO[Microservices]
ANALYTICS[Analytics]
end
subgraph APPS[User-facing]
api[API]
site[Site]
bot[Bot]
end
chain --> ANALYTICS --> mongo
chain --> INGEST --> mongo
analyzer --> redis
chain --> api
chain --> MICRO
redis --> MICRO --> mongo
MICRO <--> mongo
mongo --> api --> site
api --> bot
redis <--> api
bot --> tooter
Key Polylith bricks live under projects/ (deployable services) and components/ (shared code). Below is the actual layout currently in use:
| Path | Description |
|---|---|
projects/ccdexplorer_site |
FastAPI + Jinja application serving the public explorer UI via the ccdexplorer.ccdexplorer_site base. |
projects/ccdexplorer_api |
FastAPI service that exposes the documented REST API backed by direct Concordium node queries and MongoDB. |
projects/ccdexplorer_bot |
Telegram/email notification bot and user settings backend. |
projects/accounts_retrieval |
Batch job that snapshots accounts/tokens per day straight from the node and stores CSV + Mongo states for analytics. |
projects/heartbeat |
Real-time finalized-block listener that writes blocks/transactions into MongoDB and tags senders. |
projects/ms_block_analyser |
Celery worker that fans out each block to downstream queues (indexers, events_and_impacted, contract, module_deployed, etc.). |
projects/ms_accounts |
Consumer for the account_creation queue that enriches and stores every new address in all_account_addresses. |
projects/ms_events_and_impacts |
Processes each transaction to persist logged events plus all impacted accounts/contracts/public keys. |
projects/ms_indexers |
Builds Mongo indexes such as transfers, memoed transfers, contract touches, and module usage for fast querying. |
projects/ms_instances |
Tracks contract initialization/upgrades, enriches metadata via gRPC, and links contracts to known projects. |
projects/ms_modules |
Handles module deployments: fetches Wasm binaries, extracts entrypoints, runs Concordium-client verification, and updates module overviews. |
projects/ms_metadata |
Fetches CIS-2 metadata URLs discovered in token events and stores parsed token metadata + token-address state. |
projects/ms_plt |
Processes protocol-level token (PLT) transactions emitted by the chain so PLT stats stay current. |
projects/ms_token_accounting |
Maintains CIS token holdings by consuming logged events and updating tokens_token_addresses_v2 / tokens_links_v3. |
projects/ms_bot_sender |
Dedicated Celery worker that actually delivers notification payloads to Telegram or email (used by the bot + notifier). |
projects/dagster_nightrunner |
Dagster code location for nightly analytics jobs such as realized prices, transactions-by-type/contents, and account graphs. |
projects/dagster_recurring |
Dagster code location for recurring maintenance jobs (memos, impacted address top lists, node stats, token-accounting backfills). |
projects/dagster_paydays |
Dagster code location focused on payday-related jobs; packaged for deployment with Dagster gRPC. |
| Path | Description |
|---|---|
components/ccdexplorer/grpc_client |
Concordium gRPC/protobuf definitions plus the typed client used across services. |
components/ccdexplorer/celery_app |
Central Celery application wiring, task result helpers, and worker bootstrap logic. |
components/ccdexplorer/domain |
Domain models for Concordium accounts, credentials, CIS events, Mongo document types, etc. |
components/ccdexplorer/mongodb |
MongoDB client wrappers (MongoDB, MongoMotor) and typed collection helpers. |
components/ccdexplorer/env |
Settings loader that centralizes environment variables (node endpoints, Redis, API keys, etc.). |
components/ccdexplorer/concordium_client |
Thin wrapper around concordium-client CLI for module verification and node diagnostics. |
components/ccdexplorer/cis |
Parser/executor for CIS-2/3/5 contracts that decodes logged events and token metadata. |
components/ccdexplorer/cns |
Concordium Name Service helper that interprets CNS events/actions and maps domain ownership. |
components/ccdexplorer/ccdscan |
Small GraphQL client for CCDScan so we can cross-check node data (blocks, baker stats, delegators). |
components/ccdexplorer/schema_parser |
Re-export of the schema parser used to interpret smart-contract schemas. |
components/ccdexplorer/site_user |
Pydantic models for explorer users, linked accounts, and notification preferences. |
components/ccdexplorer/tooter |
Notification transport hub (Telegram relays, Fastmail emails) plus enums for notifier channels. |
components/ccdexplorer/wasm_decoder |
WebAssembly parsing helpers (wadze) leveraged by module verification and metadata extraction. |
See the documentation for a deeper dive into each brick and service.
- Install dependencies
uv sync
- Configure environment – copy
.env.sampleto.envand set a Concordium node endpoint and CCDExplorer API key (keys are domain-scoped, so match the API base you target). - Run the explorer site
uvicorn projects.site.asgi:app --loop asyncio --host 0.0.0.0 --port 8000
- Run the public API
uvicorn projects.api.asgi:app --loop asyncio --port 7000
- Execute tests & formatting
just test # pytest with coverage just lint # ruff linting just format # ruff formatting
A Dockerfile is also provided if you prefer containerized builds of the site or API.
The full architecture, component glossary, and deployment details live at docs.ccdexplorer.io. The documentation mirrors the Polylith structure and links to project-specific guides (site, API, bot, timed services, and every-block workers).
Issues and pull requests are welcome. Please open a discussion for larger changes so we can ensure compatibility with the production explorer and downstream services. When contributing:
- keep bricks reusable across projects,
- add tests alongside new functionality,
- run
just lintandjust testbefore submitting.
Thanks for helping grow the Concordium ecosystem!