Skip to main content
Import OfflineProtocol from @offline-protocol/mesh-sdk. These signatures match v0.27.0. Read the integration guide for prerequisites and complete usage. Use one protocol instance per process. Register handlers before startup; narrow event.type inside each callback. wipePersistedState is destructive and is not a normal shutdown step. Android wake registration is documented separately.

Methods on this page

on

Registers an event listener One-shot events registered for late are replayed. An event that reached the SDK before any listener for it existed is held and delivered to the first listener that registers: but only for the one-shot tags (internet_session_superseded, mesh_stopped_by_user), which nothing else ever restates. Everything else is dropped, as it should be: a periodic event replayed after the fact would report a state that has since changed. That window is not an edge case, it is the default. The SDK subscribes to the native emitter inside its own constructor, so between new OfflineProtocol(...) and your first on(...) there is a stretch in which events arrive with nothing registered: and Android’s native redelivery of held one-shot events fires on exactly that constructor-time subscribe, landing squarely inside it. Registering synchronously right after construction keeps the window at zero and is still the right habit; this hold is what makes an await in between survivable. Replay is asynchronous (a microtask), so a handler never runs before the on(...) call that registered it has returned, and every listener registered in the same tick, including an 'all' listener added after a specific one, receives it. Delivery stays at-least-once: these events are state, not edges, and handlers must be idempotent. See docs/react-native-integration.md §6.1. returns: This instance for chaining

off

Removes an event listener returns: This instance for chaining

once

Registers a one-time event listener returns: This instance for chaining

removeAllListeners

Removes all listeners for a specific event type, or all listeners if no type specified returns: This instance for chaining

start

Starts the protocol Automatic BLE Management: When called, this method automatically starts BLE operations if BLE is enabled:
  • Starts scanning for nearby devices advertising the Offline Protocol service
  • Starts advertising this device so others can discover it
  • Begins polling for fragments to send
  • Handles incoming fragments from peers
Automatic MLS Initialization: If encryption is enabled (default: true), MLS is automatically initialized with platform-specific secure storage (iOS Keychain / Android EncryptedSharedPreferences). To disable auto-initialization, set encryption.enabled: false in the config. Permissions Required:
  • iOS: Bluetooth permissions (NSBluetoothAlwaysUsageDescription in Info.plist)
  • Android: BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT (Android 12+) or BLUETOOTH, BLUETOOTH_ADMIN, ACCESS_FINE_LOCATION (Android 11 and below)
throws: Error if protocol is already started or fails to start

stop

Stops the protocol Automatic BLE Management: When called, this method automatically stops all BLE operations:
  • Stops scanning for devices
  • Stops advertising
  • Disconnects from all connected peers
  • Cleans up BLE resources
throws: Error if protocol is not started or fails to stop

emitTestEvent

Emits a test event to verify the event system is working This is a debugging method that emits a network_metrics event with all zeros. Use this to verify that events are being delivered from Rust through the native bridge to JavaScript.

pause

Pauses the protocol (for background mode) throws: Error if protocol is not running or fails to pause

resume

Resumes the protocol from pause throws: Error if protocol is not paused or fails to resume

getState

Gets the current protocol state returns: Protocol state (Stopped, Running, or Paused) throws: Error if retrieval fails

destroy

Destroys the protocol instance and cleans up resources

wipePersistedState

Erases every byte of persisted SDK state for one account: the namespaced secure store (MLS identity, sessions, peer trust records, the Nostr signing secret, the protocol-state record key), the account’s protocol-state directory (outbox, pending queues, block list, media descriptors), and, when this account owns it, or nobody does, the pre-namespace store an upgraded install inherited from. Call this on logout and on username switch, after destroy(). The protocol persists as it works, so wiping underneath a live instance races those writes; the native side rejects the call if the account named here is the one the current instance is running. Without it, an account’s undelivered messages are restored and re-driven on the next launch for the lifetime of the outbox, and on iOS, where the Keychain outlives the app container, its identity and delivery state survive an uninstall and are adopted again after a reinstall. The account is named explicitly because destroy() clears the config the namespace would otherwise be derived from. Pass the same appId and profile the protocol was created with; any other pair names a different account and wipes nothing. Irreversible, and it rotates the account’s MLS and Nostr identities: peers holding a session with it will see a desync on next contact and re-establish from a fresh key package. Safe to call twice: a failed wipe should simply be retried. Applications that supply their own storage providers must erase their own containers: this only knows about the built-in ones.

Parameter and result types

Import these types from the same SDK package. Event payloads and configuration types are linked below.

EventListener

ProtocolState