Quick Start
Basic Setup
Your address
The device’s identity is not something your app chooses. The SDK mints an Ed25519 identity key on first run and derives a self-certifyingoff1… address from it. Peers verify an
address by re-deriving it from the key its owner presents.
null until startup completes, because the key lives in storage that is not open
before then. The identity_ready event carries the same value the moment it becomes known.
profile is a separate thing: it selects which stored identity this instance runs as, and
it never leaves the device.
Identity & Addressing
How addressing works, how to reach a peer, and how to migrate from
userId.Advanced Configuration
Protocol Lifecycle
Complete Flow Example
ProtocolState is a string enum ("Stopped", "Running", "Paused"). It held numeric
values through v0.19.0, so state === ProtocolState.Running now works where it previously
could never be true. If your app persisted a ProtocolState itself, the old numeric value
matches nothing, so treat an unrecognized persisted value as Stopped.Event Sequence Timeline
What Happens Under the Hood
On protocol.start()
- Native protocol is created (lazily; the constructor does not create it)
- MLS initializes against iOS Keychain / Android EncryptedSharedPreferences, before transports start, so a peer can never be discovered before key exchange is possible
identity_readyfires with this device’soff1…address- BLE Manager initializes, scanning for the Offline Protocol service UUID, and advertising this device with mesh metadata (degree, free slots, battery, uptime)
- Configured transports auto-enable: internet, Nostr, and Reticulum
start() throws if the protocol is already started.
On Peer Discovery
- BLE scan detects an advertisement from another device
- MeshController evaluates the candidate: connection budget (default max 4), peer score (RSSI, availability, battery, uptime, stability, load), and whether this is a cluster bridge opportunity
- If accepted, the BLE connection is established and
neighbor_discoveredfires with the peer’s canonicaloff1…address aspeer_id - If at capacity, a lower-scoring peer may be evicted to make room
On protocol.sendMessage()
- Message created with a unique ID, TTL, timestamp, and priority
message_sentfires immediately- DORS selects a transport across BLE, Wi-Fi Direct, Internet, Reticulum, and Nostr
- ACK tracking begins
- On ACK,
message_deliveredfires - On a failed attempt,
message_retryingfires with the scheduled retry time - If no transport is available,
message_deferredfires and the message is persisted to the outbox - If the relay reports the recipient unreachable,
message_undeliverablefires and the message is parked. This repeats on an escalating probe and is not terminal - Only
message_failedis terminal
On protocol.stop()
- BLE scanning and advertising stop
- All peer connections close
neighbor_lostfires for each disconnected peer- The protocol core stops
Diagnostic Events
Next Steps
Explore the configuration reference