@nostrwatch/auditor
v0.0.1
Published
Nostr relay auditor — runs NIP conformance tests against any relay.
Readme
@nostrwatch/auditor
Nostr relay auditor — runs NIP conformance tests against any relay.
Overview
@nostrwatch/auditor tests Nostr relays (WebSocket servers that store and forward signed events) for protocol conformance. Given a relay URL, it runs a battery of NIP (Nostr Implementation Possibility — numbered protocol specifications) test suites and returns a structured result indicating which NIPs the relay supports correctly. Use it to benchmark new relays, validate relay upgrades, or power relay-health dashboards.
Auditor is a library — it runs tests but does not store results. Pair it with @nostrwatch/route66 for persistent relay monitoring or @nostrwatch/nocap for low-level relay connection checks.
Installation
pnpm add @nostrwatch/auditorOr with npm:
npm install @nostrwatch/auditorQuick Start
import {Auditor} from '@nostrwatch/auditor'
const auditor = new Auditor({nips: new Set(['Nip01', 'Nip11'])})
await auditor.detectSupportedNips('wss://relay.damus.io')
const result = await auditor.test('wss://relay.damus.io')
console.log(result)
// { relay: 'wss://relay.damus.io', pass: true, passrate: 0.875, suites: {...} }API
Auditor
class Auditor {
constructor(conf?: IAuditorConf)
detectSupportedNips(relay: string): Promise<void>
test(relay: string): Promise<IAuditorResult>
run(relay: string): Promise<IAuditorResult>
addSuite(suite: string, options?: any): void
removeSuite(suite: string): void
abort(): void
get result(): IAuditorResult
get suites(): Set<string>
}constructor(conf?)
Creates a new Auditor instance. If no configuration is passed, the Nip01 suite runs by default.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| nips | Set<string> | new Set(['Nip01']) | Suite names to run (e.g., 'Nip01', 'Nip11') |
| options | Record<string, any> | {} | Per-suite options keyed by suite name |
detectSupportedNips(relay)
Fetches the relay's NIP-11 info document and adds matching NIP suites to the configured suite set. Call this before test() to automatically test only the NIPs the relay claims to support.
test(relay)
Runs all configured NIP suites against the relay URL and returns an IAuditorResult. Equivalent to run().
run(relay)
Alias for test().
addSuite(suite, options?)
Adds a NIP suite by name. Suite names use the format 'NipXX' (e.g., 'Nip42'). Only suites with known test manifests are added; unknown names are silently ignored.
removeSuite(suite)
Removes a NIP suite from the configured set.
abort()
Emits an abort signal to all active suites. Use when you need to cancel an in-progress test run.
IAuditorConf
interface IAuditorConf {
nips: Set<string>
options: Record<string, any>
}IAuditorResult
interface IAuditorResult {
relay: string
pass: boolean
passrate: number
reason: string
suites: Record<string, ISuiteResult>
}| Field | Type | Description |
|-------|------|-------------|
| relay | string | The relay URL that was tested |
| pass | boolean | true if all non-skipped suites passed |
| passrate | number | Fraction of non-skipped suites that passed (0–1) |
| suites | Record<string, ISuiteResult> | Per-suite results keyed by suite name |
Supported NIP Suites
| Suite name | NIP | Description |
|------------|-----|-------------|
| Nip01 | NIP-01 | Basic relay protocol (filters, subscriptions, event publishing) |
| Nip02 | NIP-02 | Contact list events |
| Nip11 | NIP-11 | Relay information document |
| Nip22 | NIP-22 | Comment events |
| Nip42 | NIP-42 | Authentication of clients to relays |
| Nip50 | NIP-50 | Search capability |
| Nip65 | NIP-65 | Relay list metadata |
| Nip77 | NIP-77 | Negentropy syncing |
SuiteTest pattern
Individual NIP tests extend SuiteTest and implement a test() method that uses a behavior assertion helper:
import {SuiteTest, type ISuiteTest} from '@nostrwatch/auditor'
export class FilterLimit extends SuiteTest implements ISuiteTest {
readonly slug: string = 'FilterLimit'
limit: number = 1
get filters() {
return [{limit: this.limit}]
}
test({behavior}) {
behavior.toEqual(this.totalEvents, this.limit, 'returned correct number of events')
behavior.toBeOk(this.totalEvents > 0, 'returned at least one event')
}
}Known Limitations
- Incomplete filter range testing: Ambiguity handling in filter range selection is unimplemented (TODO in
FilterRange.ts). Filter range selection for timestamp-based queries may produce incorrect ranges in edge cases. No workaround is available at this time. See CONCERNS.md — Incomplete Filter Range Testing.
Agent Skills
No agent skills defined yet for this package.
Related Packages
@nostrwatch/nocap— low-level relay connection primitives; auditor builds on nocap adapters internally@nostrwatch/nip66— NIP-66 event types; audit results can be published as NIP-66 relay status events@nostrwatch/route66— persistent relay monitoring that uses auditor for health checks
