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
onoffonceremoveAllListenersstartstopemitTestEventpauseresumegetStatedestroywipePersistedState
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 chainingonce
Registers a one-time event listener returns: This instance for chainingremoveAllListeners
Removes all listeners for a specific event type, or all listeners if no type specified returns: This instance for chainingstart
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
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)
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
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 pauseresume
Resumes the protocol from pause throws: Error if protocol is not paused or fails to resumegetState
Gets the current protocol state returns: Protocol state (Stopped, Running, or Paused) throws: Error if retrieval failsdestroy
Destroys the protocol instance and cleans up resourceswipePersistedState
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, afterdestroy(). 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.

