The first open wallet-to-wallet (W2W) communication protocol - a non-commercial, decentralized private messaging application built on Solana blockchain using the Anchor framework. Created by the Cherry.fun team, STEM Protocol enables secure, peer-to-peer encrypted messaging with on-chain invitation and acceptance mechanisms.
STEM stands for Solana Trusted Encrypted Messaging - a protocol that provides secure, decentralized communication between Solana wallets. Think of it as the "stem" that connects different "cherries" (wallets) in the Solana ecosystem, enabling direct wallet-to-wallet messaging without intermediaries.
- First Open W2W Protocol: Pioneering wallet-to-wallet communication on Solana
- Non-Commercial: Free to use and deploy (only Solana transaction fees apply)
- Privacy-First: End-to-end encrypted messaging with on-chain verification
- Decentralized: No central servers or intermediaries required
- Self-Hosted: Can be deployed locally for complete control
- Frontend: Vue 3 + TypeScript + Vite
- Blockchain: Solana (Anchor Framework)
- Smart Contract: Rust (Anchor)
- Deployment: Docker + Nginx
- CI/CD: GitHub Actions
stem-proto/
βββ app/ # Frontend Vue.js application
β βββ src/
β β βββ components/ # Vue components
β β βββ composables/ # Vue composables (wallet, stem integration)
β β βββ pages/ # Vue router pages
β β βββ utils/ # Utilities and constants
β β βββ router/ # Vue router configuration
β βββ Dockerfile # Frontend containerization
β βββ package.json # Frontend dependencies
βββ programs/
β βββ cherry-chat/ # Solana program (smart contract)
β βββ src/lib.rs # Main program logic
β βββ Cargo.toml # Rust dependencies
βββ tests/ # Integration tests
βββ migrations/ # Deployment scripts
βββ Anchor.toml # Anchor configuration
βββ Cargo.toml # Workspace configuration
Note: STEM Protocol is completely free to use and deploy. The only costs are standard Solana network transaction fees for on-chain operations like registration, invitations, and message sending.
- Node.js 18+ and npm/yarn
- Rust and Cargo
- Solana CLI tools
- Anchor CLI
- Docker (for deployment)
-
Clone and Install Dependencies
git clone <repository-url> cd stem-proto # Install frontend dependencies cd app && npm install # Install Rust dependencies cargo build
-
Start Local Solana Validator
solana-test-validator
-
Deploy Smart Contract
# Build and deploy the program anchor build anchor deploy # Run tests anchor test
-
Start Frontend Development Server
cd app npm run dev -
Access Application
- Open http://localhost:5173
- Connect with Phantom wallet or use local wallet
Create .env file in the app/ directory:
VITE_RPC_URL=http://localhost:8899
VITE_WS_URL=ws://localhost:8900# Set to localnet for development
solana config set --url localhost
# Create a new wallet for testing
solana-keygen new --outfile ~/.config/solana/id.jsonTraditional messaging apps rely on centralized servers and user accounts. STEM Protocol eliminates these dependencies by enabling direct communication between Solana wallets. This approach provides:
- True Decentralization: No central authority controls your communications
- Identity Verification: Wallet ownership proves identity without personal data
- Censorship Resistance: No single point of failure or control
- Privacy: No server logs or data collection
- Interoperability: Works with any Solana wallet
- Wallet Registration: Users register their wallet on-chain
- Peer Invitation: Send chat invitations to other users
- Chat Management: Accept/reject invitations to establish connections
- Private Messaging: Send encrypted messages in private chats
- Real-time Updates: Live chat updates via WebSocket connections
- Connect Wallet: User connects Phantom or local wallet
- Register: First-time users register their wallet on-chain
- Invite Peers: Send invitations by entering peer's public key
- Accept/Reject: Respond to incoming invitations
- Chat: Exchange messages with accepted peers
BjheWDpSQGu1VmY1MHQPzvyBZDWvAnfrnw55mHr33BRB
- Purpose: Stores user's peer list and invitation status
- Seeds:
["wallet_descriptor", user_pubkey] - Data: List of peers with their status (Invited, Requested, Accepted, Rejected)
- Purpose: Stores encrypted chat messages between two users
- Seeds:
["private_chat", chat_hash] - Data: Messages, timestamps, and participant wallets
- Creates a new
WalletDescriptoraccount for the user - Required for all other operations
- Sends invitation from payer to invitee
- Updates both users' descriptor accounts
- Sets peer status to
Invited/Requested
- Accepts a pending invitation
- Creates
PrivateChataccount - Sets peer status to
Accepted - Validates chat hash for security
- Rejects a pending invitation
- Sets peer status to
Rejected
- Sends message in private chat
- Validates sender is chat participant
- Stores message with timestamp
fn get_hash(a: Pubkey, b: Pubkey) -> [u8; 32] {
// Deterministic hash based on sorted public keys
// Ensures same chat account for both participants
}- Only chat participants can send messages
- Invitation validation prevents unauthorized access
- Hash verification ensures chat integrity
# Run all tests
anchor test
# Run specific test file
anchor test tests/cherry-chat.ts- Integration tests in
tests/cherry-chat.ts - Tests cover all program instructions
- Includes error case validation
cd app
docker build . -t cherry-chat:latestdocker run --rm -p 8080:80 cherry-chat:latestThe project uses GitHub Actions for automated deployment:
- Build: Creates Docker image with commit hash tag
- Push: Uploads to GitLab container registry
- Deploy: SSH to production VM and updates container
Production deployment requires these secrets:
REGISTRY_USERNAME/REGISTRY_PASSWORD: GitLab registry credentialsREGISTRY_PATH: Container registry pathVM_HOST: Production server hostnameVM_SSH_KEY: SSH private key for deployment
- Smart Contract: Modify
programs/cherry-chat/src/lib.rs - Frontend: Update Vue components and composables
- Testing: Add integration tests
- Deploy: Use Anchor for program updates
- Rust: Follow Rust formatting standards (
cargo fmt) - TypeScript: Use ESLint and Prettier
- Vue: Follow Vue 3 Composition API patterns
# Solana program logs
solana logs <program_id>
# Frontend development
cd app && npm run dev
# Smart contract debugging
anchor test --skip-lintclass Stem {
// Initialize and load user data
async init(): Promise<Stem>
// Create transaction for wallet registration
async createRegisterTx(): Promise<Transaction>
// Create invitation transaction
async createInviteTx(invitee: PublicKey): Promise<Transaction>
// Create acceptance transaction
async createAcceptTx(invitee: PublicKey): Promise<Transaction>
// Create rejection transaction
async createRejectTx(invitee: PublicKey): Promise<Transaction>
// Create message sending transaction
async createSendMessageTx(invitee: PublicKey, message: string): Promise<Transaction>
}stem.on('onStatusUpdated', (isRegistered: boolean) => {})
stem.on('onChatsUpdated', (chats: Map<string, PeerAccount>) => {})
stem.on('onChatUpdated', ({ pubkey, chat }) => {})- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open Pull Request
- Write tests for new features
- Update documentation for API changes
- Follow existing code patterns
- Ensure all tests pass before submitting PR
This project is licensed under the MIT License - see the LICENSE file for details.
- Issues: Create GitHub issue for bugs or feature requests
- Documentation: Check this README and inline code comments
- Community: Join our Discord/Telegram for discussions
- Cherry.fun - The team behind STEM Protocol
- Solana Documentation
- Anchor Framework
- Vue.js Documentation
- Project Repository
STEM Protocol is developed and maintained by the Cherry.fun team as a contribution to the Solana ecosystem. This project demonstrates the potential for truly decentralized communication protocols that prioritize privacy, security, and user sovereignty.