Skip to content

A PageRank-based reputation system for Nostr

Notifications You must be signed in to change notification settings

CodyTseng/fayan

Repository files navigation

Fayan (法眼)

Warning

This project is currently under active development.

Fayan (法眼), meaning "Dharma Eye" in Chinese, represents the ability to perceive truth and distinguish authenticity from deception. This project uses TrustRank and PageRank algorithms to identify spam accounts in the Nostr network.

A TrustRank & PageRank based reputation system for Nostr.

Features

  • Outbox Model Support - Accurately retrieves users' latest follow lists by querying their preferred relays
  • Low Memory Footprint - Optimized for minimal resource consumption
  • SQLite Storage - Lightweight and portable database backend

API

Method Path Description
GET /users/{pubkeyOrNpub} Query single user
POST /users Batch query users
GET /search?q=... Search users by name

Official server: https://fayan.jumble.social/

Query Single User

GET /users/{pubkeyOrNpub}

Supports both hex pubkey and npub format.

Response Fields:

Field Type Description
pubkey string User public key (hex)
rank int Rank (lower is better)
percentile int Percentile (0-100)
followers int Number of followers
following int Number of following

Response Example:

{
  "pubkey": "hex_pubkey",
  "rank": 123,
  "percentile": 95,
  "followers": 1000,
  "following": 50
}

Batch Query Users

POST /users

Request body:

{
	"pubkeys": ["pubkey1", "npub1...", ...]
}

Up to 100 pubkeys per request.

Response Structure:

Key Value Type Description
pubkey/npub UserResponse User info object

Response Example:

{
  "pubkey1": {
    "pubkey": "hex_pubkey1",
    "rank": 1,
    "percentile": 100,
    "followers": 5000,
    "following": 10
  },
  "npub1...": {
    "pubkey": "hex_pubkey2",
    "rank": 123,
    "percentile": 95,
    "followers": 1000,
    "following": 50
  }
}

Error Response Format

All endpoints return the following format on error:

{
  "error": "Bad Request",
  "message": "Detailed error message"
}

Search Users

GET /search?q={query}&limit={limit}

Search for users by name, display name, or NIP-05 identifier. Results are sorted by reputation rank.

Note: This feature is disabled by default. Enable it in config.yaml by setting search.enabled: true.

Query Parameters:

Parameter Type Required Default Description
q string Yes - Search query
limit int No 20 Max results to return (max 100)
offset int No 0 Results to skip (max 1000)

Response Fields:

Field Type Description
event object Raw Nostr kind 0 event
pubkey string User public key (hex)
rank int Rank (lower is better)
percentile int Percentile (0-100)
followers int Number of followers
following int Number of following

Response Example:

[
  {
    "event": {
      "id": "...",
      "pubkey": "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681",
      "created_at": 1704067200,
      "kind": 0,
      "tags": [],
      "content": "{\"name\":\"xxx\",\"about\":\"...\",\"picture\":\"...\"}",
      "sig": "..."
    },
    "pubkey": "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681",
    "rank": 1,
    "percentile": 100,
    "followers": 1000,
    "following": 10
  }
]

How to Run

Docker Compose (Recommended)

# Copy example config files
cp config.example.yaml config.yaml
cp docker-compose.example.yml docker-compose.yml

# Start services
docker compose up --build

This will build the frontend, embed it into the API binary, and start both crawler and API services. The web UI and API are available at http://localhost:9090.

Local Build & Run

Prerequisites:

  • Go 1.24+
  • Node.js 20+ (for frontend)

Option 1: Using build script

# Copy example config file
cp config.example.yaml config.yaml

# Build everything (frontend + Go binaries)
./build.sh

# Run crawler
./fayan-crawler

# Run API server in another terminal
./fayan-api

Option 2: Manual build

# Copy example config file
cp config.example.yaml config.yaml

# Build frontend
cd web
npm install
npm run build
cd ..

# Copy frontend assets to embed directory
cp -r web/dist/* cmd/api/static/

# Build Go binaries
go build -o fayan-crawler ./cmd/crawler/main.go
go build -o fayan-api ./cmd/api/main.go

# Run crawler
./fayan-crawler

# Run API server in another terminal
./fayan-api

Configuration

Copy config.example.yaml to config.yaml and modify as needed. The example files are tracked by git while your local config files are ignored, making it easier to pull updates.

Search Configuration

The user search feature is disabled by default. To enable it, add the following to your config.yaml:

search:
  enabled: true # Enable user search feature
  top_percentile: 50 # Only index users in top X% reputation (default: 50)

The top_percentile setting controls which users' profiles are stored in the search index. Lower values mean stricter filtering, which reduces database size but may exclude more users from search results.

Project Structure

fayan/
├── cmd/
│   ├── api/           # API server with embedded frontend
│   │   ├── main.go
│   │   └── static/    # Embedded frontend files (built from web/)
│   └── crawler/       # Network crawler
├── internal/
│   ├── api/           # API handlers and middleware
│   ├── cache/         # In-memory caching
│   ├── crawler/       # Crawler logic
│   ├── ranking/       # PageRank/TrustRank algorithms
│   └── repository/    # SQLite storage layer
├── web/               # React frontend source
├── build.sh           # Build script for frontend + Go binaries
├── Dockerfile         # Multi-stage Docker build
└── docker-compose.example.yml

License

MIT License

About

A PageRank-based reputation system for Nostr

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •