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