A QDN topology viewer and data-collection pipeline for Qortium Previewnet. The
viewer ships as qdn://APP/Network/Network; its current and historical data is
published separately under DATABASE/Network/Network and
SNAPSHOT/Network/Network.
The React viewer currently provides:
- an interactive chain/QDN-data graph with pan, zoom, reset, and node focus;
- filters for I2P/IP chain and data connections;
- node, link, country, and Core-version summaries with detail modals;
- country flags and version rings, with details for the selected node;
- snapshot-history navigation with a slider, older/newer controls, and Left/Right Arrow keyboard shortcuts;
- durable historical-snapshot URLs that participate in Home Back/Forward navigation while keeping the latest snapshot at the canonical app URL;
- visible QDN download progress with a bounded readiness wait and readable node errors;
- bundled sample data when published QDN data cannot be loaded;
- a Developers workspace with copyable schemas, resource examples, reader behavior, and collector/publication boundaries.
The app loads latest.json, index.json, and historical snapshot files from
DATABASE/Network/Network through Qortium Home's qdnRequest bridge. In a plain
browser it performs the same read-only requests against
http://127.0.0.1:24891 by default. Set VITE_QORTIUM_NODE_API_URL to use a
different development node.
Before reading the database, Network requests GET_QDN_RESOURCE_STATUS with
build: true and waits up to 90 seconds for READY, polling every 3 seconds.
Nodes can know about a publication before all its chunks are downloaded. The
viewer shows that progress, cancels superseded waits, and offers Refresh or a
different host node if availability does not recover. Qortal Core/Hub errors
are normalized from their structured error objects into readable messages.
Historical links use ?snapshot=YYYYMMDDTHHMMSSZ, matching an indexed file at
snapshots/<snapshotId>.json. The bounded DATABASE history currently retains
the newest 1,000 snapshots, so a sufficiently old link can eventually fall back
to the latest retained record after its snapshot is pruned.
The viewer supports Classic and Modern QDN UI styles, along with Home theme, accent, and text-size settings. It does not define a Fun style.
Build the Qortal artifact with npm run build:qortal (dist-qortal/). Its
publisher identity is APP/xnetwork/default and it reads
DATABASE/xnetwork/Network. It shows the same Qortium topology, not Qortal
peers. The normal npm run build remains the Qortium artifact in dist/.
Each artifact records its hosting network in qortium-app.json. Deployment
configuration selects both the data identity and bridge (qdnRequest on
Qortium, lexical/window qortalRequest on Qortal). Do not choose the network
from bridge presence: Home exposes both. Do not publish the Qortium artifact
to Qortal or the Qortal artifact to Qortium. Plain-browser Qortal development
uses local port 12391, configurable with VITE_QORTAL_NODE_API_URL.
Developers navigation is omitted in the Qortal artifact. Direct Developers aliases and Back/Forward normalize to Network while retaining valid snapshot selection, other query parameters and fragments. The Qortium reference stays available. Both deployments retain the Qortium topology heading.
Open qdn://APP/Network/Network?view=developers or choose Developers in
main navigation. The English reference opens without an account or topology
fetch. view=developer and view=reference normalize to view=developers.
An accompanying valid snapshot is retained for returning to Network;
workspace navigation preserves other query parameters and fragments, and
participates in Back/Forward history. Graph arrow shortcuts are inactive in
Developers. Code blocks remain selectable when clipboard access is unavailable.
The reference imports the viewer's resource/path/size constants from
src/networkContract.ts. Focused tests check its examples with the viewer
parser/graph model and against the Python producer's schema and retention
constants. Update
the reference alongside public-contract changes; it documents current behavior,
including shallow viewer validation and separate DATABASE/SNAPSHOT transactions.
The app is at QAVS 1.4.4: 1.4 is the minimum Qortium platform level and the
patch number is the app release. vite.config.ts reads package.json, injects
the visible version badge, and emits dist/qortium-app.json with the name
Network and the current version during every build.
npm install
npm run dev
npm test
npm run build
npm run previewPublish a built viewer to the default Previewnet identity:
npm run qdn:publishThe publisher reads dist/, uses the local Core at
http://127.0.0.1:24891, and defaults to
~/qortium/git/qortium-core/preview/secrets/initial-minting-accounts.json.
Overrides use the QORTIUM_NETWORK_ prefix. The render URL is
http://127.0.0.1:24891/render/APP/Network/Network.
See dual QDN publishing for opt-in Qortal configuration, legacy state migration, per-destination receipts, recovery and the separate Qortal app publication command.
Generate a current snapshot, SVG, and the QDN payload directories with:
python3 tools/network-topology-data.py --no-pngThe collector starts from the configured seed nodes, then breadth-first probes
reachable peers through their public read-only APIs. It deduplicates by host and
node ID, treats missing edges as unknown rather than disconnected, and supports
--no-discover, --max-hops, --max-nodes, --api-port,
--probe-timeout, and --probe-workers.
Collection uses /admin/info, /admin/status, /peers, and /peers/data; it
does not inspect private node state. The defaults allow four discovery hops, at
most 250 queried nodes, public API port 24891, a five-second probe timeout,
and 12 concurrent probe workers. --max-extra-peers separately limits how many
non-operator peers are drawn. A reachable node becomes an observer in its own
right, so the resulting topology can include non-seed and multi-hop links rather
than making every connection appear to terminate at a seed.
I2P-only peers cannot be probed over a clearnet API. When Core's
recordPeerExchange setting is enabled, the collector also reads recent
peer-exchange.jsonl records from each seed and adds approximate gossip-derived
I2P edges. The seed configuration defaults that remote path to
qortium/preview/peer-exchange.jsonl relative to the VPS account home; this is
the deployed seed layout, not the local source checkout. Use --no-gossip,
--gossip-window-hours, or --gossip-tail-lines to control this input.
Clearnet IPv4 nodes receive offline country lookups from the vendored
tools/geoip-ipv4-country.bin.gz; no peer IP is sent to an external geolocation
service. Rebuild the table with:
python3 tools/build_geoip_ipv4.pyDefault outputs are:
target/preview-topology/preview-topology.jsontarget/preview-topology/preview-topology.svgtarget/qdn-topology-data/qdn-resources.jsontarget/qdn-topology-data/DATABASE/Network/Networktarget/qdn-topology-data/SNAPSHOT/Network/Network
The DATABASE payload contains latest.json, index.json, individual files
under snapshots/, and a compact topology record. The tool retains at most
1,000 historical DATABASE records. The SNAPSHOT payload is the point-in-time
resource for the current run. qdn-resources.json records both resource
directories for the publishing scripts.
After generating payloads, publish both data resources or the viewer and data together:
npm run qdn:publish:data
npm run qdn:publish:allqdn:publish:data publishes both DATABASE/Network/Network and
SNAPSHOT/Network/Network. The shared publish helper uses the current local
development default
~/qortium/git/qortium-core/preview/secrets/initial-minting-accounts.json.
npm run qdn:collect
npm run qdn:auto-publish -- --dry-run
npm run qdn:auto-publishqdn:collect adds one snapshot to target/preview-topology and prunes archived
files older than 14 days by default. qdn:auto-publish considers archived
records after the last selected timestamp, rejects records with collection
errors or seed-height disagreement, selects the strongest eligible record, and
publishes the DATABASE resource only. Its default minimum gap is eight hours.
The production rootless systemd collector/publisher setup is documented in
deploy/README.md. The timers publish data only; viewer code
is still published manually with npm run qdn:publish.