Creates an LXMF router bound to the given identity and Reticulum instance.
The Reticulum instance
Optionaloptions: { stampEngine?: StamperEngine } = {}
OptionalstampEngine?: StamperEngineOptional proof-of-work stamp engine to install process-wide (work doc
#45). The engine swap is global: it replaces the WebCrypto default for
every stamp operation in the process (message stamp generation, propagation
blob validation, peering), which is what a busy propagation node or heavy
sender wants. Platform packages ship ready-made engines — e.g.
nodeStamper from @reticulum/node — and omitting the option keeps the
browser-safe WebCrypto default.
Epoch seconds of the last lazy processed-id prune (0 = due immediately).
True while a syncPeers pass is running; overlapping passes skip.
Maximum announce hop count a node is auto-peered at (Python
AUTOPEER_MAXDEPTH).
Client per-transfer download limit (KB) advertised in /get requests.
Cap on peered propagation nodes (Python LXMRouter.MAX_PEERS, lxmd
default 20). Peering beyond the cap is refused; rotatePeers
makes headroom by dropping the least-useful peers.
Messages parked while their sender's identity is unknown, keyed by
hex(link_id) (or "opportunistic") → bucket of parked wire buffers.
A link's bucket is dropped when the link closes (LINKIDENTIFY can
never arrive on a dead link), re-processed when the link identifies or
an announce lands, and the total is capped at
MAX_PARKED_MESSAGES so unknown-sender floods cannot pin
memory.
Peered node destination hashes protected from rotation and culling
(Python static_peers).
The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.
Optionaloptions: boolean | AddEventListenerOptionsAnnounces the lxmf.delivery destination with the given display name.
Builds the §4.3 msgpack app_data ([name(bin8), stamp_cost, [SF_COMPRESSION]])
and attaches it to the identity so Destination.announce signs it as part
of the announce body.
Human-readable node name shown to peers.
OptionalstampCost: number | null = null
Active stamp cost (1-254), or null to advertise stamping as disabled.
Announces the lxmf.propagation destination, advertising this node to the
network. Requires enablePropagation first.
The dispatchEvent() method of the EventTarget sends an Event to the object, (synchronously) invoking the affected event listeners in the appropriate order. The normal event processing rules (including the capturing and optional bubbling phase) also apply to events dispatched manually with dispatchEvent().
Enables autopeering (matching the Python reference's lxmd autopeer): when
a lxmf.propagation
announce is heard whose advertised peering cost is ≤ maxPeeringCost, a
peering relationship is established automatically. Requires
enablePropagation (this node must itself be a propagation node to
peer).
OptionalmaxPeeringCost: number = MAX_PEERING_COST
Max advertised peering cost to auto-peer at (default MAX_PEERING_COST).
Optionaloptions: {OptionalautopeerMaxDepth?: numberMax announce hop count to auto-peer at (default AUTOPEER_MAXDEPTH).
OptionalmaxPeers?: numberOverride the peer-table cap (default MAX_PEERS).
OptionalstaticPeers?: Uint8Array<ArrayBufferLike>[]Peered destination hashes
protected from rotation and culling (Python static_peers).
Enables the propagation-node role (§5.3): creates the lxmf.propagation
destination, registers the /get message-download handler, and ingests
submitted messages received via link Resources.
The node stores propagated messages addressed to other identities and
serves them to clients over /get; messages addressed to this router's
own delivery identity are locally delivered (decrypted + dispatched as a
message event). Returns the PropagationNode for direct access
(e.g. inspecting PropagationNode.store).
Call announcePropagationNode afterwards to broadcast the node.
Optionaloptions: PropagationNodeOptions = {}Whether a message with this message id has already been delivered to local handlers, no matter which path it arrived on (matching the Python reference, keyed by message hash).
SHA-256 of the signed part (§5.5).
Ingests a paper message delivered as an lxm:// URI (LXMRouter.ingest_lxm_uri).
The URI body is base64-decoded into the paper payload, de-duplicated by its
transient_id (so re-ingesting the same QR/URI is a no-op), decrypted with
the local lxmf.delivery destination, and dispatched through the same
message event path as a network-delivered message. Paper messages always
disable stamp enforcement (LXMRouter.lxmf_propagation is_paper_message).
The sender's signature is verified when their identity is already known (recalled from a prior announce); otherwise the message is still delivered with an unverified signature, exactly like the Python reference.
The lxm:// paper message URI.
The reconstructed message, or null when
the URI is not addressed to this node (decryption fails) or was already
ingested.
Initializes the router and registers the LXMF delivery destination.
Establishes (or updates) a peering relationship with another propagation
node (LXMRouter.peer). The peer's advertised limits and costs are read
from its app_data; messages this node stores are then offered to it on the
next syncPeers.
Peer's lxmf.propagation hash.
Optionalmetadata?: Map<number, Uint8Array<ArrayBufferLike>> | nullNode metadata map.
Peer's peering cost (≤ MAX_PEERING_COST).
OptionalperSyncLimitKb?: number | nullPer-sync cumulative limit.
OptionalperTransferLimitKb?: number | nullPer-message transfer limit.
Peer's propagation stamp cost.
Peer's stamp cost flexibility.
the peer, or null if peering was rejected.
Re-processes every parked message whose sender identity may now be known (typically called after a just-validated announce made a previously- unknown identity available — first-contact opportunistic delivery).
Each entry is fed back through _processIncomingMessage: if the
identity is still unknown it is re-parked (without re-requesting the
path, guarded by alreadyParked), otherwise it is verified and
dispatched. Safe and cheap to call when nothing is parked.
Call this when a new Identity is cached (e.g., in your IDENTIFY handler). It checks if any parked messages are now ready for processing.
Pass null to re-process an opportunistic (linkless) parked message.
The removeEventListener() method of the EventTarget interface removes an event listener previously registered with EventTarget.addEventListener() from the target. The event listener to be removed is identified using a combination of the event type, the event listener function itself, and various optional options that may affect the matching process; see Matching event listeners for removal.
Optionaloptions: boolean | EventListenerOptionsPeer rotation (Python LXMRouter.rotate_peers): when the peer table is
at or over maxPeers, drop just enough of the least-useful peers
to restore ROTATION_HEADROOM_PCT headroom. Candidates are
non-static, IDLE peers: unreachable ones first, then peers that have
been offered messages but accepted none at a rate below
ROTATION_AR_MAX. Peers with nothing offered yet are spared, as
are static peers and peers still mid-sync.
count of peers dropped.
Serializes and sends an LXMF message.
Delivery method mirrors the Python reference with automated fallback:
linkId is reused (DIRECT over an existing link);fallback
("opportunistic" -> "propagation" -> "none").On a link this initiates, LINKIDENTIFY is sent once before the message DATA (Python LXMF otherwise drops packets that arrive before identify), and the link is wired to receive replies (backchannel).
OptionaloptionsOrLinkId: Sets the propagation node to submit messages to and sync from, by its
lxmf.propagation destination hash. The node's identity/app_data must be
learned from an announce before submit/sync can run.
Starts periodic re-announcement of the lxmf.delivery destination
(PROTOCOL-SPEC.md §9.7) so cached mesh paths stay fresh and peers can
reach you after transit-relay TTLs lapse.
Sets the announce app_data from displayName/stampCost (so every
periodic announce advertises the same name), then delegates to
Destination.startAnnouncing on the delivery destination — which
fires the first announce immediately and repeats every intervalMs.
This replaces the one-shot announce for the common "announce and keep announcing" case. Call stopAnnouncing to halt the loop.
Human-readable node name shown to peers.
Optionaloptions: { intervalMs?: number; stampCost?: number | null } = {}
OptionalintervalMs?: numberOverride the default cadence (clamped to the §9.7 60 s floor).
OptionalstampCost?: number | nullActive stamp cost (1-254), or null to advertise stamping as disabled.
Stops the periodic delivery-destination re-announce loop started by startAnnouncing. Safe to call when not running (no-op).
Submits a message to the configured propagation node for store-and-forward delivery (LXMF.md §5.8 / LXMessage PROPAGATED).
Packs the message into propagation form (dest_hash ‖ E(src‖sig‖payload),
§5.3), appends a propagation stamp meeting the node's advertised cost, and
sends the msgpack([time, [lxmf_data]]) container to the node as a Link
Resource. The node stores it until the recipient syncs.
Optionaloptions: { stampCost?: number } = {}
Override the stamp cost (defaults to the node's advertised cost, then PROPAGATION_COST).
Downloads messages addressed to identity from the configured propagation
node (LXMRouter.request_messages_from_propagation_node).
Drives the /get exchange: list available transient_ids, request those
not already held, decrypt + dispatch each, then ack so the node purges
them. Resolves with counts of received / duplicate messages.
The recipient identity to identify as (so the node serves our messages).
OptionalmaxMessages: number = ALL_MESSAGES
Cap on messages fetched.
Runs one outbound sync pass against every peered node. Resolves when all peers have completed (or postponed) their sync.
Overlapping passes skip: drivers call this on an interval, and a pass can legitimately outlive one interval (a slow transfer, a backlog of peers). Running two passes concurrently would sync the same peer over two links at once — the second pass is a no-op instead.
Periodic router maintenance (the Python reference's jobs-loop cleanup): prunes aged entries from the processed-transient-id dedup map. A runner calls this on its maintenance interval; the insert path also prunes lazily, so calling this is an optimization, not a requirement.
count of pruned processed-id entries.
Breaks a peering relationship (LXMRouter.unpeer).
Handles LXMF routing and message processing.
Description
LXMF Router for managing incoming and outgoing messages