Documentation Index
Fetch the complete documentation index at: https://mintlify.com/jlucaso1/whatsapp-rust/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide covers implementing custom backends for storage, network transport, and HTTP operations in whatsapp-rust. The library uses trait-based abstractions to allow full customization.Storage Backend Architecture
The storage backend is split into four domain-grouped traits:- SignalStore - Signal protocol cryptography (identities, sessions, keys)
- AppSyncStore - WhatsApp app state synchronization
- ProtocolStore - WhatsApp Web protocol alignment (SKDM, LID mapping, device registry)
- DeviceStore - Device persistence operations
\1
Backend Trait
Any type implementing all four traits automatically implementsBackend:
Implementing a Custom Storage Backend
Step 1: Define Your Store
Step 2: Implement SignalStore
Handle Signal protocol cryptographic operations:\1
Step 3: Implement AppSyncStore
Handle WhatsApp app state synchronization:\1
Step 4: Implement ProtocolStore
Handle WhatsApp Web protocol alignment:\1
Step 5: Implement DeviceStore
Handle device data persistence:\1
Using Your Custom Backend
Custom Transport Backend
Transport Trait
Implement theTransport trait for custom network transports:
\1
Transport Factory
ImplementTransportFactory to create transport instances:
\1
Transport Events
Custom HTTP Client
Implement theHttpClient trait for custom HTTP operations:
SQLite Reference Implementation
The library includes a full SQLite implementation you can use as reference: See\1
Key Features
- Diesel ORM with migrations
- Connection pooling (r2d2)
- WAL mode for concurrency
- Prepared statements for performance
- Transaction support
- Database snapshotting for debugging
Using SQLite Store
Best Practices
// ✅ Good: Use connection pool
let pool = Pool::new(config)?;
let backend = MyCustomStore::new(pool);
// ❌ Bad: Create connections per operation
let backend = MyCustomStore::new(connection_string);
use wacore::store::error::{Result, StoreError};
async fn load_session(&self, address: &str) -> Result<Option<Vec<u8>>> {
match self.connection.query("SELECT ...", &[address]).await {
Ok(row) => Ok(Some(row.get(0))),
Err(e) if is_not_found(&e) => Ok(None),
Err(e) => Err(StoreError::Database(e.to_string())),
}
}
async fn put_mutation_macs(
&self,
name: &str,
version: u64,
mutations: &[AppStateMutationMAC],
) -> Result<()> {
let tx = self.connection.begin_transaction().await?;
for mutation in mutations {
tx.execute("INSERT ...", &[...]).await?;
}
tx.commit().await?;
Ok(())
}
Next Steps
- Sending Messages - Use your custom backend
- Receiving Messages - Store received messages
- Group Management - Store group metadata