relay-management.ts raw
1 export type TRelayApprovalStatus = 'pending' | 'approved' | 'rejected'
2 export type TRelayDirection = 'outbox' | 'inbox' | 'both'
3 export type TOutboxMode = 'automatic' | 'managed'
4
5 /** Per-network stats for a single relay, keyed by the client's external IP. */
6 export interface TNetworkRelayStats {
7 publishSuccess: number
8 publishFailure: number
9 fetchSuccess: number
10 fetchFailure: number
11 lastSeen: number
12 }
13
14 /** Full relay entry with per-network stats and approval state. */
15 export interface TRelayEntry {
16 url: string
17 direction: TRelayDirection
18 /** Relay resolved IPv4 as dotted-quad string (e.g. "1.2.3.4"), or null if unresolved */
19 relayIp: string | null
20 /** Per-network stats: key = client external IP hex (8 hex chars for IPv4) */
21 networkStats: Map<string, TNetworkRelayStats>
22 /** User manually excluded (discretionary, independent of stats or approval) */
23 manualExclude: boolean
24 /** Approval status in managed mode */
25 status: TRelayApprovalStatus
26 /** Why this relay was discovered (e.g. "write relay for npub1abc...") */
27 reason: string
28 addedAt: number
29 updatedAt: number
30 }
31
32 /**
33 * Binary sync format for relay stats data.
34 *
35 * Per-entry layout:
36 * [1 byte] URL length (max 255)
37 * [N bytes] URL (UTF-8)
38 * [1 byte] flags: direction(2) | status(2) | manualExclude(1) | reserved(3)
39 * [4 bytes] relay resolved IPv4 (0.0.0.0 if unresolved)
40 * [1 byte] network stats count (K)
41 * K times (12 bytes each):
42 * [4 bytes] client external IPv4
43 * [2 bytes] publishSuccess (uint16, capped 65535)
44 * [2 bytes] publishFailure (uint16)
45 * [2 bytes] fetchSuccess (uint16)
46 * [2 bytes] fetchFailure (uint16)
47 */
48 export const DIRECTION_BITS: Record<TRelayDirection, number> = {
49 outbox: 0b00,
50 inbox: 0b01,
51 both: 0b10
52 }
53
54 export const STATUS_BITS: Record<TRelayApprovalStatus, number> = {
55 pending: 0b00,
56 approved: 0b01,
57 rejected: 0b10
58 }
59
60 export const DIRECTION_FROM_BITS: TRelayDirection[] = ['outbox', 'inbox', 'both', 'outbox']
61 export const STATUS_FROM_BITS: TRelayApprovalStatus[] = ['pending', 'approved', 'rejected', 'pending']
62
63 /** Auto-disable threshold: 99% failure rate */
64 export const AUTO_DISABLE_FAILURE_RATE = 0.99
65 /** Minimum attempts before auto-disable can trigger */
66 export const AUTO_DISABLE_MIN_ATTEMPTS = 10
67