Privacy-first meetings powered by Zama's Fully Homomorphic Encryption on Ethereum
Privia is a decentralized meeting platform that ensures complete privacy through blockchain and Zama FHE technology. Host instant or scheduled meetings with end-to-end encrypted messages that remain private even on the blockchain.
Created by @altbright_
- β‘ Instant Meetings - Create and join meetings immediately
- π Scheduled Meetings - Plan meetings for future dates/times
- π Encrypted Chat - All messages encrypted with FHE
- π₯ Participant Management - Approve/reject join requests
- π― Meeting Types - Public or Private modes
- π¬ Real-time Messaging - Send and receive encrypted messages
- π Message Search - Search through chat history
- π Bulk Decryption - Decrypt all messages at once
- π€ Participant List - See who's in the meeting
- π Progress Tracking - Visual progress bars for encryption/decryption
- β In-app Guide - Comprehensive help modal
- π€ Co-host Support - Assign additional meeting moderators
- β° Start/End Meetings - Full control over meeting lifecycle
- β Waiting Room - Review and approve pending participants
- πͺ Access Control - Manage who can join your meetings
- π Meeting Stats - View participant and message counts
- π FHE Encryption - Messages encrypted using Fully Homomorphic Encryption
- π― Access Control - Only meeting participants can decrypt messages
- π Blockchain Storage - Immutable and tamper-proof on Ethereum
- π‘οΈ Decentralized - No central server storing your data
- π Wallet-based Auth - Secure authentication via Web3 wallets
# Install dependencies
npm install && cd frontend && npm install && cd ..
# Deploy contract
npx hardhat run scripts/deploySecureChat.js --network sepolia
# Configure frontend
cd frontend
cp .env.example .env
# Add your contract address to .env: VITE_SECURECHAT_CONTRACT_ADDRESS=0x...
# Run frontend
npm run dev- Connect Wallet β Connect your Web3 wallet
- New Meeting β Click "Start Meeting" for instant or "Schedule Meeting" for later
- Configure β Choose meeting type (Public/Private) and approval settings
- Share ID β Share the meeting ID with participants
- Get Meeting ID β Receive meeting ID from host
- Join β Enter meeting ID and click "Join Meeting"
- Wait for Approval β If required, wait for host to approve
- Enter Meeting β Start chatting once approved
- Send Messages β Type and send encrypted messages
- Search β Search through message history
- Manage Participants β Host can approve/reject join requests
- Add Co-hosts β Host can assign co-hosts for help managing
- End Meeting β Host can end the meeting for everyone
- Smart Contracts: Solidity 0.8.24 + Zama FHE
- Frontend: React 18 + TypeScript + Vite
- Web3: Wagmi + RainbowKit
- Styling: TailwindCSS
- Network: Ethereum Sepolia Testnet
- Encryption: fhevmjs (Zama FHE library)
Contract: SecureChat.sol
Network: Sepolia Testnet
Features:
- Instant and scheduled meetings
- Encrypted message storage
- Participant management
- Co-host functionality
- Waiting room with approval system
- π Public - Anyone can join instantly
- π Private - Requires host approval to join
Note: All messages are encrypted with FHE regardless of meeting type
- π Scheduled - Meeting planned for future
- β Active - Meeting in progress
- π Ended - Meeting completed
- β Cancelled - Meeting cancelled
// Core data structures
enum MeetingStatus { Scheduled, Active, Ended, Cancelled }
enum MeetingType { Public, Private }
enum ParticipantStatus { Pending, Approved, Rejected, Left }
struct Meeting {
uint256 id;
address host;
string title;
uint256 scheduledTime; // 0 for instant meetings
uint256 startedAt;
uint256 endedAt;
MeetingStatus status;
MeetingType meetingType;
bool requiresApproval;
uint256 participantCount;
uint256 messageCount;
}
struct Message {
uint256 id;
uint256 meetingId;
address sender;
uint256 timestamp;
bool isActive;
bool isRead;
// encrypted content stored separately as euint32
}
struct Participant {
address participantAddress;
ParticipantStatus status;
uint256 joinedAt;
bool isCoHost;
uint256 messagesRead;
}
// Key contract functions
function createInstantMeeting(string title, MeetingType type, bool requiresApproval) returns (uint256)
function scheduleMeeting(string title, uint256 scheduledTime, MeetingType type, bool requiresApproval) returns (uint256)
function joinMeeting(uint256 meetingId)
function approveParticipant(uint256 meetingId, address participant)
function sendMessage(uint256 meetingId, externalEuint128 encryptedContent, bytes proof) returns (uint256)
function endMeeting(uint256 meetingId)
function addCoHost(uint256 meetingId, address coHost)Client-side Encryption (TypeScript):
import { createInstance } from 'fhevmjs';
// Initialize FHE instance
const instance = await createInstance({ chainId, publicKey });
// Encrypt message
const messageValue = convertMessageToNumber(message);
const encrypted = await instance.encrypt128(messageValue);
// Send to contract
await contract.sendMessage(meetingId, encrypted.data, encrypted.proof);Decryption (for participants):
// Get encrypted message from contract
const encryptedMsg = await contract.getEncryptedMessage(meetingId, messageId);
// Decrypt (only works if you're a participant)
const decrypted = await instance.decrypt(address, encryptedMsg);frontend/src/
βββ pages/
β βββ ChatHomePage.tsx # Home page with meeting list
β βββ ScheduleMeetingPage.tsx # Schedule future meetings
β βββ MeetingLobbyPage.tsx # Pre-meeting lobby
β βββ ActiveMeetingPage.tsx # Active meeting with chat
βββ hooks/
β βββ useSecureChat.ts # Contract interaction hook
βββ components/
β βββ ChainGuard.tsx # Network validation
βββ config/
βββ wagmi.ts # Web3 configuration
Key Pages:
- ChatHomePage: Create/join meetings, view recent meetings
- ScheduleMeetingPage: Schedule meetings with date/time picker
- MeetingLobbyPage: Waiting room with participant list and join requests
- ActiveMeetingPage: Chat interface with real-time messaging
useSecureChat Hook Functions:
createInstantMeeting(title, type, requiresApproval)
scheduleMeeting(title, scheduledTime, type, requiresApproval)
joinMeeting(meetingId)
approveParticipant(meetingId, participant)
sendMessage(meetingId, message)
getMeeting(meetingId)
getParticipants(meetingId)
endMeeting(meetingId)# Compile contract
npx hardhat compile
# Deploy to Sepolia
npx hardhat run scripts/deploySecureChat.js --network sepolia
# Copy the deployed contract addresscd frontend
cp .env.example .env
# Edit .env and add:
# VITE_SECURECHAT_CONTRACT_ADDRESS=0x...# Development
npm run dev
# Production build
npm run build
npm run preview# Install dependencies
npm install
cd frontend && npm install && cd ..
# Run local Hardhat node
npx hardhat node
# Deploy to local network
npx hardhat run scripts/deploySecureChat.js --network localhost
# Run tests
npx hardhat testContributions welcome! Feel free to submit a Pull Request.
MIT License
- Architecture Guide - Technical architecture and system design
- Deployment Guide - Complete deployment instructions
- User Guide - Step-by-step user documentation
- Contributing - Development and contribution guidelines
Built with Zama FHE, Hardhat, and RainbowKit
@altbright_ - Follow for updates and more projects
Built with β€οΈ for private, secure communication