Biontbiont
Pipoke

Messaging

Pipoke has two private messaging surfaces: one-to-one direct messages and multi-member group chats. Both store only encrypted content on-chain. The chain holds ciphertext, never plaintext.

Pipoke runs on Octra Devnet today. Any fee, price, or limit referred to here is a contract setting chosen for testing. Every one is owner-settable, and mainnet values will be different. These docs describe how the mechanics work, not what the numbers are.

#Encryption

Messages are encrypted with X25519 key exchange. Encryption and decryption happen in the browser, and the private keys stay in the browser. The contracts only ever see and store ciphertext.

The chain stores ciphertext. A direct message is stored as two ciphertext blobs, one encrypted to the recipient and one encrypted to the sender, so each party can decrypt their own copy of the thread. A group message is stored as a single ciphertext, and each member holds an encrypted copy of the group key so they can read it.

Because keys never leave the browser, the protocol owner, an indexer, or anyone reading the chain sees only encrypted bytes. The plaintext exists only on the devices of the people in the conversation.

#Direct messages

Direct messages run on 8 inbox shards. PipokeRouter assigns each pair of wallets to one inbox shard, so a conversation between two wallets always lives on the same shard.

PipokeInboxShard.send_message(recipient, ct_to, ct_from)

ct_to is the message encrypted to the recipient, ct_from is the same message encrypted to the sender. Each send appends a numbered message to the pair's thread. A mark_read method records how far each side has read. You cannot DM yourself, and a recipient who has blocked you rejects the message.

Sending a direct message charges a POKE fee, split three ways like other action fees.

#Group chats

Group chats run on 8 group shards. Each group has an admin, a name, a member list, and a message log of encrypted blobs.

Method Who What it does
create_group(name, my_key_ct) Anyone Creates a group, caller becomes admin.
add_member(group_id, member, key_ct) Admin Adds a member with their encrypted group key.
remove_member / ban_member Admin Removes or bans a member.
leave_group(group_id) Member Leaves a group (the admin cannot leave).
update_member_key Admin Rotates a member's encrypted group key.
rename_group / close_group / reopen_group Admin Group management.
send_group_message(group_id, ct_msg) Member Posts an encrypted message to the group.

Each member stores their own encrypted copy of the group key (member_key_ct), which is how a member decrypts group traffic without the key ever being in plaintext on-chain. Sending a group message charges a POKE fee, split three ways like other action fees.

#Messaging always needs a wallet signature

Session keys let feed actions go through silently. Messaging is deliberately outside that. Every direct message and every group message requires a wallet signature, even when a session key is active. Messaging is a consequential, private action, so it stays gated behind an explicit wallet approval.