reticulum-js
    Preparing search index...

    Module @reticulum/core

    @reticulum/core

    The zero-dependency, browser-safe core of the Reticulum Network System for JavaScript.

    Reticulum is a mesh networking stack designed for both local and wide-area networking. Reticulum applications can talk with each other over multiple different interfaces, ranging from TCP connections to LoRa radio. This allows building offline-first collaborative software that can work even when Internet infrastructure is compromised.

    @reticulum/core is the main package of the reticulum-js monorepo. It is browser-safe (no node: specifiers, no external runtime dependencies) and runs in modern browsers as well as server-side engines like Node.js and Deno. Node-only interfaces and interfaces that need external runtime dependencies live in companion packages.

    Reticulum gives several building blocks for enabling applications and users to communicate with each other:

    • Packets: raw data packets, either as-is or over an established Link
    • LXMF Messages: one-to-one structured payloads with store-and-forward capability. Think instant messaging, email, telemetry transfer
    • Request/Response: calls to services, with optional request payloads and identification. Think fetch
    • Resources: large chunkable file transport
    • Channels: bidirectional data channels with a peer

    On top of these, Reticulum handles peer discovery (via the Announce mechanism) and encryption and content signing (via Identities).

    Read the Zen of Reticulum for more information.

    Early stages, but we are able to send and receive LXMF messages, and make NomadNet page requests.

    At this point the aim is for JavaScript applications to be able to be leaf nodes in a Reticulum mesh, meaning that they will not route traffic for others. Full capability of acting as a transport node would be great to have and is on the roadmap.

    The canonical source of @reticulum/core is the rngit repository. To fetch the latest release, run:

    rngit release rns://adafb3153efd4d96d532568a5208b3b5/reticulum/reticulum-js fetch latest:all
    npm install reticulum-core-*.tgz

    You can also get @reticulum/core from NPM:

    npm install @reticulum/core
    

    The quickest way to use Reticulum.js is to attach to a local shared Reticulum instance (for example, the rnsd daemon already running on your machine), set up an identity, and exchange LXMF messages:

    import {
    fromHex,
    Identity,
    LXMessage,
    LXMRouter,
    Reticulum,
    toHex,
    } from "@reticulum/core";
    // TCP and shared-instance interfaces are Node-only — install `@reticulum/node`.
    import {
    LocalClientInterface,
    TCPClientInterface,
    } from "@reticulum/node";

    // 1. Start the engine and configure interfaces
    const rns = new Reticulum();

    const shared = await LocalClientInterface.connectToSharedInstance();
    if (shared) {
    // Shared `rnsd` daemon is auto-discovered from ~/.reticulum/config, so no
    // interface setup is needed when one is running.
    rns.addInterface(shared, true);
    } else {
    // Fall back to a direct TCP interface when no shared instance is available.
    const tcp = new TCPClientInterface({ host: "127.0.0.1", port: 42424 });
    await tcp.connect();
    rns.addInterface(tcp, true);
    }

    // 2. Create an identity for this peer (persist it between runs in real apps)
    const identity = await Identity.generate();
    identity.setAppData("reticulum-js example");

    // 3. Register the standard LXMF delivery destination and announce our presence
    const lxmf = new LXMRouter(identity, rns);
    await lxmf.init();
    await lxmf.deliveryDest.announce();

    console.log("My LXMF address:", toHex(lxmf.deliveryDest.destinationHash));

    // 4. Receive incoming messages
    lxmf.addEventListener("message", (event) => {
    const { message } = event.detail;
    console.log(`From ${toHex(message.sourceHash)}: ${message.content}`);
    });

    // 5. Send a message to a known peer LXMF address (16 bytes)
    const outgoing = new LXMessage({
    sourceHash: lxmf.deliveryDest.destinationHash,
    destinationHash: fromHex("00112233445566778899aabbccddeeff"),
    content: "Hello over Reticulum!",
    });
    await lxmf.send(outgoing, identity, null);

    The destination address is the peer's lxmf.delivery destination hash. You typically learn it from an announce or out-of-band; substitute a real 16-byte hex address before sending.

    A complete runnable version (with identity persistence and echo replies) lives in examples/lxmf_echobot.js.

    Network interfaces are not re-exported from the package main entry — import the one you need directly by subpath. The browser-safe client interfaces live in this package; Node-only interfaces live in the @reticulum/node companion.

    import { HttpPostClientInterface } from "@reticulum/core/src/interfaces/http.js";
    import { WebSocketClientInterface } from "@reticulum/core/src/interfaces/websocket.js";
    import { WebRTCInterface } from "@reticulum/core/src/interfaces/webrtc.js";

    Node-only (in @reticulum/node):

    import {
    AutoInterface,
    LocalClientInterface,
    TCPClientInterface,
    TCPServerInterface,
    HttpPostServerInterface,
    } from "@reticulum/node";

    LocalClientInterface also hosts the shared-instance endpoint discovery (getSharedInstanceEndpoint / loadConfig / parseConfigFile / resolveConfigDir, ported from the Python ~/.reticulum/config) and a static factory that discovers + connects in one call, returning a connected interface (or null if share_instance = No / unreachable) for the caller to attach:

    import { LocalClientInterface } from "@reticulum/node";

    const shared = await LocalClientInterface.connectToSharedInstance();
    if (shared) rns.addInterface(shared, true);

    LXMF messages can also be delivered completely out-of-band — printed on paper, photographed as a QR code, or shared as a string — using the paper delivery method. A paper message is encrypted to the recipient exactly like a propagated one, but instead of travelling over the network it is encoded as an lxm:// URI that the recipient ingests later:

    import { LXMFConstants, LXMessage, toHex } from "@reticulum/core";

    // Build the recipient's outbound lxmf.delivery destination from a recalled
    // identity (typically learned from an announce).
    const recipientOut = await Destination.OUT(
    "lxmf.delivery",
    DestType.SINGLE,
    recipientIdentity,
    rns,
    );

    const outgoing = new LXMessage({
    sourceHash: lxmf.deliveryDest.destinationHash,
    destinationHash: recipientOut.destinationHash,
    content: "Scanned from a QR code!",
    });

    // Produce the lxm:// URI (e.g. render it into a QR code). The encrypted
    // payload must fit within LXMFConstants.PAPER_MDU bytes (QR-code capacity).
    const uri = await outgoing.toPaperUri(identity, recipientOut);
    console.log(uri); // lxm://...

    On the receiving side, feed the URI straight into the router:

    lxmf.addEventListener("message", (event) => {
    const { message } = event.detail;
    console.log(`Paper message from ${toHex(message.sourceHash)}: ${message.content}`);
    });

    // `uri` was captured out-of-band (typed in, scanned, pasted).
    const message = await lxmf.ingestUri(uri);

    ingestUri decrypts with the local lxmf.delivery destination, dispatches the usual message event, and de-duplicates by transient_id so scanning the same QR code twice is harmless. You can also work at the LXMessage level directly with toPaperData / fromPaperData / fromPaperUri.

    Licensed under the EUPL 1.2.

    LXMFConstants
    LXStamper
    Allow
    CEType
    ContextType
    DestType
    HeaderType
    LogLevel
    MessageState
    PacketType
    ReceiptStatus
    ResourceFlag
    ResourceStatus
    StorageNamespace
    SystemMessageTypes
    TransportType
    Channel
    ChannelException
    Destination
    Envelope
    Identity
    InterfaceDiscovery
    LinkChannelOutlet
    LXMessage
    LXMRouter
    MemoryStorageAdapter
    MessageBase
    MsgPack
    Packet
    PacketReceipt
    Persistor
    Resource
    ResourceAdvertisement
    Reticulum
    StreamDataMessage
    WebRTCSignaling
    ACCEPTED_INTERFACE_TYPES
    DISCOVERABLE_TYPES
    DISCOVERY_APP_NAME
    DISCOVERY_ASPECT
    DISCOVERY_DEFAULT_STAMP_VALUE
    DISCOVERY_FLAG_ENCRYPTED
    DISCOVERY_FLAG_SIGNED
    DISCOVERY_STATUS_AVAILABLE
    DISCOVERY_STATUS_STALE
    DISCOVERY_STATUS_UNKNOWN
    DISCOVERY_THRESHOLD_REMOVE
    DISCOVERY_THRESHOLD_STALE
    DISCOVERY_THRESHOLD_UNKNOWN
    DISCOVERY_WORKBLOCK_EXPAND_ROUNDS
    LOG_LEVEL_ENV
    WEBRTC_CAPABILITY_FLAG
    WEBRTC_CHANNEL_LABEL
    WEBRTC_DEFAULT_DESTINATION_NAME
    WEBRTC_MAX_SDP_SIZE
    WEBRTC_SDP_TYPE_ANSWER
    WEBRTC_SDP_TYPE_CANDIDATE
    WEBRTC_SDP_TYPE_OFFER
    aspectNameHash
    base64ToBytes
    base64UrlToBytes
    buildDiscoveryAppData
    buildDiscoveryConfigEntry
    bytesToBase64
    bytesToBase64Url
    fromHex
    generateDiscoveryStamp
    getLogLevel
    isHostname
    isIpAddress
    openDuplex
    openReadable
    openWritable
    parseDiscoveryAnnounce
    parseLogLevel
    sanitizeDiscoveryName
    setLogLevel
    toHex