Private Chat
This cookbook builds a private chat on SKALE — no one can read your messages except the people in the conversation. Messages are encrypted before they ever reach the blockchain, and they stay encrypted onchain. Only the chat participants hold the keys to decrypt them.How it Works
This tutorial needs a SKALE chain that supports private transactions. The demo runs on SKALE on Base Testnet. Check Programmable Privacy Availability for which chains support this.
- Node.js 22+ and yarn/npm
- A SKALE chain with privacy support
- Basic familiarity with Solidity and TypeScript
Step 1: Clone the Project
Clone thebite-solidity repository. It contains multiple examples that demonstrate different programmable privacy features.
Fund Your Wallet: This process consumes gas tokens. Get free testnet ETH from the SKALE Base Sepolia Faucet.
Step 2: Smart Contract Overview
The contract isEncryptedMessenger.sol. It stores sessions and messages as ciphertext, and only handles plaintext inside the onDecrypt callback triggered by the protocol.
Core Data Structures:
Step 3: User Registration & Deposit System
Before a session can be created, both users register a long-term public key. The contract uses that key later to re-encrypt the shared session secret separately for each user. Registration:Step 4: Create a Session with Encrypted Transactions and CTX
This is where the chat creates a shared session key. The public half can be stored openly, but the private half is encrypted offchain and sent into the contract through CTX so it never appears as plaintext in a normal transaction. The Session Secret: A fresh ephemeral key pair is generated as the session key. The session’s public key is passed as plaintext (it is the shared session encryption key), while the private key is the secret — it must travel into the contract securely. Off-Chain (TypeScript) — Encrypt the Session Secret:encryptedSessionKeycontains the protected session private key- No single validator can decrypt it alone
- In the next block, the protocol resolves the CTX and calls
onDecrypt
Step 5: Session Callback - Re-encrypt for Each User
When the protocol callsonDecrypt, the contract immediately re-encrypts the session secret for each participant using the public key they registered earlier.
The session private key is only ever plaintext inside the
onDecrypt callback. It is never stored in readable form onchain, only as ciphertext personalized for each user.Step 6: Send Messages with Encrypted Transactions
Each message follows the same pattern. The app encrypts the message before submission, then the contract receives it through CTX. Off-Chain (TypeScript) — Encrypt the Message:Step 7: Message Callback - Re-encrypt and Store
When the message CTX resolves, the protocol callsonDecrypt with the decrypted message bytes. The contract then re-encrypts them with the session public key and stores the ciphertext.
Step 8: Read and Decrypt Messages Offchain
To read chat history, each participant first unlocks their own copy of the session key, then uses that session key to unlock stored messages. Decryption Helper for Re-encrypted Data (TypeScript):Step 9: Demo UI Setup
A minimal Next.js demo app lives indemo/. It provides a side-by-side chat interface for two server-managed demo accounts. No browser wallet is required — the server signs all transactions using private keys from .env.
Setup:
Demo Project Structure:
This demo is custodial by design — the server holds both user private keys and signs transactions on their behalf. It is intended for local testing and demonstrations only, not production use.
Step 10: Run the Application
http://localhost:3000. The UI provides two side-by-side panes (User 1 / User 2), each with:
- Deposit Credits — Pre-fund callback gas so messages don’t require attaching Gas Tokens each time
- Register — Publish your secp256k1 public key onchain (enabled after depositing)
- Create Session — Trigger the CTX that bootstraps the shared session secret (enabled once both users are registered)
- Chat Window — Messages are shown as truncated ciphertext by default; click the unlock button to decrypt them inline
- Send — Type a message and send it via CTX
sendMessage is called.
Resources:
- BITE TypeScript SDK: GitHub Repository
- bite-solidity Repository: GitHub Repository
- Programmable Privacy Introduction: Introduction
- Conditional Transactions: How CTX works
