Parrhesia.API.Events (parrhesia v0.16.1)

Copy Markdown

Canonical event publish, query, and count API.

This is the main in-process API for working with Nostr events. It applies the same core validation and policy checks used by the relay edge, but without going through a socket or HTTP transport.

All public functions expect opts[:context] to contain a Parrhesia.API.RequestContext. That context drives authorization, caller attribution, and downstream policy behavior.

publish/2 intentionally returns {:ok, %PublishResult{accepted: false}} for policy and storage rejections so callers can mirror relay OK semantics without treating a rejected event as a process error.

Summary

Functions

Counts events matching the given filters.

Paginates stored events for a single filter using keyset cursors.

Validates, authorizes, persists, and fans out an event.

Batch variant of publish/2 for trusted sync paths that have already received a page of remote events in one transport frame.

Queries stored events plus any dynamic NIP-43 events visible to the caller.

Queries events and returns NIP-67 EOSE completeness hints for the same visible result set.

Functions

count(filters, opts \\ [])

@spec count(
  [map()],
  keyword()
) :: {:ok, non_neg_integer() | map()} | {:error, term()}

Counts events matching the given filters.

Required options:

Supported options:

  • :validate_filters? - skips filter validation when false
  • :authorize_read? - skips read policy checks when false
  • :options - when set to a map, returns a NIP-45-style payload instead of a bare integer

When opts[:options] is a map, the result shape is %{"count" => count, "approximate" => false}. If opts[:options]["hll"] is true and the feature is enabled, an "hll" field is included.

paginate(filter, opts \\ [])

@spec paginate(
  map(),
  keyword()
) :: {:ok, [map()]} | {:error, term()}

Paginates stored events for a single filter using keyset cursors.

Unlike query/2, this bypasses NIP-01 newest-first ordering and any dynamic NIP-43 expansion; it returns the persisted-event slice that strictly satisfies the keyset bounds in the requested order. Intended for the Parrhesia SYNC-PAGE wire frame.

Required options:

Supported options:

  • :order - :asc (default) or :desc
  • :limit - max events returned (caller is responsible for capping)
  • :after_key, :until_key - {created_at, event_id_hex} keyset bounds
  • :validate_filters?, :authorize_read? - same semantics as query/2

publish(event, opts \\ [])

@spec publish(
  map(),
  keyword()
) :: {:ok, Parrhesia.API.Events.PublishResult.t()} | {:error, term()}

Validates, authorizes, persists, and fans out an event.

Required options:

Supported options:

  • :max_event_bytes - overrides the configured max encoded event size
  • :role, :path, :private_key, :configured_private_key - forwarded to the NIP-43 helper flow

Return semantics:

  • {:ok, %PublishResult{accepted: true}} for accepted events
  • {:ok, %PublishResult{accepted: false}} for rejected or duplicate events
  • {:error, :invalid_context} only when the call itself is malformed

publish_many(events, opts \\ [])

@spec publish_many(
  [map()],
  keyword()
) :: {:ok, [Parrhesia.API.Events.PublishResult.t()]} | {:error, term()}

Batch variant of publish/2 for trusted sync paths that have already received a page of remote events in one transport frame.

Untrusted callers still run full event validation. Trusted sync callers skip duplicate signature/hash/future-timestamp validation because the source Parrhesia node already validated before storage. Regular persisted events are inserted with a storage-level batch operation and dispatched as a batch. Control and ephemeral events fall back to publish/2 because their side effects are not bulk-safe.

query(filters, opts \\ [])

@spec query(
  [map()],
  keyword()
) :: {:ok, [map()]} | {:error, term()}

Queries stored events plus any dynamic NIP-43 events visible to the caller.

Required options:

Supported options:

  • :max_filter_limit - overrides the configured per-filter limit
  • :validate_filters? - skips filter validation when false
  • :authorize_read? - skips read policy checks when false

The skip flags are primarily for internal composition, such as Parrhesia.API.Stream. External callers should normally leave them enabled.

query_with_eose_hints(filters, opts \\ [])

@spec query_with_eose_hints(
  [map()],
  keyword()
) :: {:ok, [map()], [String.t()]} | {:error, term()}

Queries events and returns NIP-67 EOSE completeness hints for the same visible result set.

The hint check widens each effective limit by one and compares the visible result count. If widening reveals more events than were sent, the relay advertises "more"; otherwise it advertises "finish".