Replaces the blind 30s post-RLN-ready sleep in sendBytes with a poll-based wait: capture our cachedProof's merkle root, then wait until it has been present in our own rootTracker for ≥2 poll cycles (cap 180s, warn-and-publish on cap). Adaptive to the underlying chain's block cadence — solves the testnet RLN root-drift race where a 30-42s sleep wasn't enough for mix-node verifiers to poll the post-registration root, so proofs failed with "Spam protection proof verification failed" at mix entry. Non-OnchainLEZ group managers retain the 30s fallback. Bumps vendor/nwaku to pick up the OnchainLEZGroupManager.proofRoot + getPollInterval accessors this gate uses. Also drops the deprecated logos-cpp-sdk override on the nix-fetched LOGOSCORE: overriding the SDK breaks liblogos 7df6195's source (stale requestObject/onEvent shape). Plugins via logos-module-builder ship the newer SDK and are ABI-compatible with the native build.
Logos Chat
A privacy focused decentralized messaging SDK, built on the Logos Stack. Logos Chat provides permission-less, censorship-resistant communication for humans and clankers.
Quick Start
Prerequisites
Build
# Initialize submodules and dependencies
make update
# Build all targets (examples + shared library)
make all
# Run tests
make tests
Quick Tasks
Here are common tasks to get up and running. See examples/ for full examples, including pingpong.nim which demonstrates a full two-client conversation.
Initialize Client
let waku = initWakuClient(DefaultConfig())
var client = newClient(waku).get()
...
...
client.start()
Create Introduction Bundle
Introductions are single use key-bundles required by Senders to initiate a conversation. Recipients must generate them before anyone can contact them. IntroBundles contain no secrets and can be published, or transmitted over over other channels.
...
# IntroBundles are sent to other clients Out-of-Band to establish a conversation.
let intro_bundle = client.createIntroBundle()
...
Create 1:1 Chat
Once a Sender has retrieved a bundle then they can create a conversation. All conversations must have an initial message.
...
let initial_content = @[1,2,3]
# This intro_bundle must come from another client
let convo_id = await client.newPrivateConversation( intro_bundle, initial_content )
...
Receive Message
Receiving a message is accomplished by registering a callback.
...
client.onNewMessage(proc( convo: Conversation, msg: ReceivedMessage ) {.async.} =
echo convo.id(), msg.content
)
...
Send Message
...
let content = @[1,2,3]
let convo = client.getConversation( convo_id )
await client.sendMessage( content )
...
Message Flow
sequenceDiagram
participant S as Saro
participant R as Raya
Note over R,S: Discovery
R -->> S: Send intro bundle via established channel
Note over R,S: Initialization
S ->> R: PrivateV1 Invite + initial message
Note over R,S: Operation
loop Encrypted messaging
par
R ->> S: Send Message
and
S ->> R: Send Message
end
end
C Bindings
A shared library with C bindings is available:
make liblogoschat
This produces build/liblogoschat.{dylib,so,dll}. See library/liblogoschat.h and examples/cbindings/ for usage.
License
Dual-licensed under MIT and Apache 2.0.