WoT Oracle
Query directed follow distance and public mute evidence over HTTP. Version 0.3.0, with no extension required.
What It Does
The Oracle indexes kind-3 follows and public pubkey entries from kind-10000 mute lists received through configured relays. Coverage is limited to those indexed events. Follow distance and mute evidence remain separate; the API does not combine them into a trust score.
Example: If Alice follows Bob, and Bob follows Carol, then the distance from Alice to Carol is 2 hops.
Release capabilities
API Endpoints
Illustrative responses using synthetic 64-character hexadecimal pubkeys. Actual results depend on indexed events. See the API reference for all endpoints, including /mutes, /trust and /ready.
GET /distance
Query the social distance between two pubkeys.
GET /distance?from=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&to=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&max_hops=3{
"from": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"to": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"hops": 2,
"path_count": 1,
"mutual_follow": false
}POST /distance/batch
Query distances from one pubkey to multiple targets.
POST /distance/batch
Content-Type: application/json
{
"from": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"targets": [
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
],
"max_hops": 3
}{
"from": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"results": [
{
"from": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"to": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"hops": 2,
"path_count": 1,
"mutual_follow": false
}
]
}GET /stats
Get statistics about the indexed graph.
GET /stats{
"node_count": 3,
"edge_count": 2,
"nodes_with_follows": 2,
"mute_edge_count": 0,
"nodes_with_mute_lists": 1,
"sync": {
"running": true,
"ready": false,
"last_event_received_at": 0,
"last_persisted_at": 0,
"persisted_events": 0,
"lagged_notifications": 0,
"persistence_errors": 0,
"coverage": "configured_relays_only"
},
"cache": {
"size": 0,
"capacity": 10000,
"ttl_secs": 300
},
"locks": {
"write_lock_count": 0,
"write_lock_avg_us": 0,
"write_lock_max_us": 0,
"read_lock_count": 0,
"read_lock_avg_us": 0,
"read_lock_max_us": 0
}
}GET /health
Process liveness and release version. Use /ready to check ingestion readiness.
GET /health{
"status": "healthy",
"version": "0.3.0"
}Self-Hosting
Examples use v0.3.0. Docker and Compose publish on localhost:8080. Public deployments need a reverse proxy that replaces client-IP headers. Native builds need Rust 1.93, pkg-config and OpenSSL development libraries.
Docker (Recommended)
Docker Compose
From source (Rust 1.93)
Configuration
Environment variables below show native binary defaults. The Docker image uses /app/data/wot.db; Compose publishes to loopback by default. Cache size is bounded to 100–100000, TTL to 10–3600 seconds, and the rate limit to 1–1000 requests/minute.
| Variable | Default | Description |
|---|---|---|
RELAYS | wss://relay.damus.io,wss://nos.lol,wss://relay.primal.net/,wss://relay.mostr.pub/ | Comma-separated relay URLs |
HTTP_PORT | 8080 | Server port |
DB_PATH | wot.db | SQLite database location |
RATE_LIMIT_PER_MINUTE | 100 | Query throttle per IP |
CACHE_SIZE | 10000 | Maximum entries in the Moka query cache |
CACHE_TTL_SECS | 300 | Cache expiration (5 min) |
Architecture
Graph Storage
In-memory graph for fast traversal, backed by SQLite for persistence. Syncs continuously from configured Nostr relays.
Pathfinding
Bidirectional breadth-first search computes shortest directed follow paths. Runtime depends on graph size, branching and search depth.
Caching
Moka query cache with configurable capacity and TTL. Entries are invalidated when the graph revision changes. Latency depends on the deployment and workload.
Rate Limiting
Per-IP rate limiting protects the service from abuse. Configurable limits for different deployment scenarios.
Public Instance
A public instance is available for development and testing:
https://wot-oracle.mappingbitcoin.comLimits depend on deployment settings. Handle HTTP 429 with backoff. Graph-query saturation returns 503; /health and /ready remain available outside the data-endpoint limiter.
Open Source
Written in Rust. MIT licensed. Self-host for your community or contribute improvements.