W3MSG Protocol Abstraction Layer
The Protocol Abstraction Layer is the core component of the W3MSG SDK that provides a unified interface for Web3 messaging protocols. It abstracts the complexity of different messaging protocols (XMTP, Push Protocol) behind a single, consistent API.
🏗️ Architecture Overview
The Protocol Abstraction Layer follows a modular, extensible design with the following key components:
┌─────────────────────────────────────────────────────────────┐
│ W3MSG SDK Core │
├─────────────────────────────────────────────────────────────┤
│ Protocol Abstraction Layer │
├─────────────────┬─────────────────┬─────────────────────────┤
│ XMTP Protocol │ Push Protocol │ Future Protocols │
│ Wrapper │ Wrapper │ (Extensible) │
└─────────────────┴─────────────────┴─────────────────────────┘
Core Components
- MessageProtocol Abstract Class: Base interface for all protocol implementations
- Protocol Wrappers: XMTP and Push Protocol implementations
- Protocol Manager: Intelligent protocol selection and switching
- Error Normalization: Unified error handling across protocols
- Retry Manager: Robust retry logic with multiple backoff strategies
- Health Monitor: Real-time protocol health monitoring
- Circuit Breaker: Fault tolerance and automatic failover
🚀 Quick Start
Basic Setup
import { W3MSGSDK } from '@w3msg/sdk';
import { ethers } from 'ethers';
// Initialize with wallet
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const w3msg = new W3MSGSDK({
signer,
protocols: ['xmtp', 'push'],
config: {
environment: 'production',
retryPolicy: 'network',
healthMonitoring: true
}
});
await w3msg.initialize();
Sending Messages
// Send a chat message via XMTP
const result = await w3msg.send({
to: '0x742d35Cc6634C0532925a3b8D900b5dF5D7F3E8a',
content: 'Hello from W3MSG!',
type: 'chat'
});
// Send a notification via Push Protocol
const notification = await w3msg.send({
to: '0x742d35Cc6634C0532925a3b8D900b5dF5D7F3E8a',
content: {
title: 'New Message',
body: 'You have received a new message'
},
type: 'notification'
});
🔧 Core Interfaces
MessageProtocol Abstract Class
The base class that all protocol implementations must extend:
abstract class MessageProtocol {
abstract name: string;
abstract initialize(config: ProtocolConfig): Promise<void>;
abstract connect(): Promise<void>;
abstract disconnect(): Promise<void>;
abstract sendMessage(params: SendMessageParams): Promise<MessageResult>;
abstract startListening(callback: MessageCallback): Promise<() => void>;
abstract stopListening(): Promise<void>;
abstract getConversations(): Promise<Conversation[]>;
abstract performHealthCheck(): Promise<ProtocolHealthStatus>;
abstract getCapabilities(): ProtocolCapabilities;
}
Protocol Configuration
interface ProtocolConfig {
signer: Signer;
environment: 'development' | 'staging' | 'production';
apiKeys?: Record<string, string>;
endpoints?: Record<string, string>;
features?: {
encryption?: boolean;
groupChat?: boolean;
fileAttachments?: boolean;
};
}
Message Types
interface SendMessageParams {
to: string;
content: string | MessageContent;
type?: 'chat' | 'notification';
conversationId?: string;
metadata?: Record<string, any>;
}
interface MessageContent {
title?: string;
body: string;
image?: string;
cta?: string;
url?: string;
}
interface MessageResult {
id: string;
status: 'sent' | 'pending' | 'failed';
timestamp: number;
protocol: string;
metadata?: Record<string, any>;
}
🔄 Protocol Switching
The Protocol Manager automatically selects the best protocol based on multiple factors:
Selection Criteria
interface ProtocolSelectionStrategy {
healthWeight: number; // 40% - Protocol health status
preferenceWeight: number; // 30% - User preferences
featureWeight: number; // 20% - Feature compatibility
latencyWeight: number; // 10% - Response time
minHealthScore: number; // Minimum health threshold
maxLatencyMs: number; // Maximum acceptable latency
}
Automatic Failover
// Configure automatic failover
const w3msg = new W3MSGSDK({
signer,
protocols: ['xmtp', 'push'],
switchingStrategy: {
healthWeight: 0.4,
preferenceWeight: 0.3,
featureWeight: 0.2,
latencyWeight: 0.1
},
circuitBreaker: {
failureThreshold: 5,
recoveryTimeout: 30000,
halfOpenRetries: 3
}
});
// Listen for protocol switches
w3msg.on('protocol:switched', (event) => {
console.log(`Switched from ${event.from} to ${event.to}`, event.reason);
});
🛠️ Error Handling
Normalized Error System
All protocol errors are normalized into a consistent format:
interface ProtocolError extends Error {
category: ErrorCategory;
severity: ErrorSeverity;
protocol: string;
method: string;
timestamp: number;
recovery?: ErrorRecovery;
context: ErrorContext;
}
enum ErrorCategory {
NETWORK = 'NETWORK',
AUTHENTICATION = 'AUTHENTICATION',
PROTOCOL_INIT = 'PROTOCOL_INIT',
MESSAGE_SEND = 'MESSAGE_SEND',
RATE_LIMIT = 'RATE_LIMIT',
BROWSER_UNSUPPORTED = 'BROWSER_UNSUPPORTED',
VC_VERIFICATION = 'VC_VERIFICATION'
}
enum ErrorSeverity {
LOW = 'LOW',
MEDIUM = 'MEDIUM',
HIGH = 'HIGH',
CRITICAL = 'CRITICAL'
}
Error Recovery Strategies
try {
await w3msg.send(message);
} catch (error) {
if (error instanceof ProtocolError) {
console.log(`Error category: ${error.category}`);
console.log(`Severity: ${error.severity}`);
// Check if recovery is possible
if (error.recovery?.canRetry) {
console.log(`Retrying in ${error.recovery.retryAfterMs}ms`);
// Automatic retry will be handled by RetryManager
}
// Check for fallback options
if (error.recovery?.fallbackAvailable) {
console.log('Fallback protocol available');
}
}
}
🔄 Retry Logic
Built-in Retry Strategies
The Retry Manager supports multiple backoff strategies:
enum BackoffStrategy {
EXPONENTIAL = 'exponential', // 1s, 2s, 4s, 8s, 16s
LINEAR = 'linear', // 1s, 2s, 3s, 4s, 5s
FIXED = 'fixed', // 1s, 1s, 1s, 1s, 1s
EXPONENTIAL_JITTER = 'exponential_jitter', // With randomization
POLYNOMIAL = 'polynomial' // 1s, 4s, 9s, 16s, 25s
}
Custom Retry Policies
import { retryManager } from '@w3msg/sdk';
// Create custom retry policy
const customPolicy: RetryPolicy = {
maxRetries: 5,
baseDelay: 1000,
backoffStrategy: BackoffStrategy.EXPONENTIAL_JITTER,
timeoutMs: 30000,
shouldRetry: (error) => {
// Custom retry condition
return error.category === ErrorCategory.NETWORK ||
error.category === ErrorCategory.RATE_LIMIT;
}
};
// Use with retry manager
const result = await retryManager.execute(
async () => await protocol.sendMessage(params),
customPolicy
);
📊 Health Monitoring
Real-time Health Metrics
import { healthMonitor } from '@w3msg/sdk';
// Get protocol health status
const health = healthMonitor.getProtocolHealth('xmtp');
console.log({
isHealthy: health?.isHealthy,
latency: health?.latency,
errorCount: health?.errorCount,
uptime: health?.uptime,
features: health?.features
});
// Get health trends
const trends = healthMonitor.getHealthTrend('xmtp');
console.log({
trend: trends?.trend, // 'improving' | 'stable' | 'degrading'
confidence: trends?.confidence,
issues: trends?.issues,
recommendations: trends?.recommendations
});
// Generate health report
const report = healthMonitor.generateHealthReport();
console.log({
overallHealth: report.overallHealth, // 'healthy' | 'degraded' | 'unhealthy'
protocolCount: report.protocolCount,
healthyCount: report.healthyCount,
protocols: report.protocols
});
Health Events
// Listen for health events
healthMonitor.on('health:protocol_checked', (event) => {
console.log(`${event.protocolName}: ${event.isHealthy ? 'healthy' : 'unhealthy'}`);
});
healthMonitor.on('health:alert_created', (alert) => {
if (alert.severity === 'HIGH' || alert.severity === 'CRITICAL') {
console.warn(`Health Alert: ${alert.message}`);
}
});
🌐 Browser Compatibility
Compatibility Detection
import { BrowserCompatibility } from '@w3msg/sdk';
// Check browser compatibility
const compatibility = BrowserCompatibility.getInstance();
console.log('Browser Info:', {
name: compatibility.getBrowser().name,
version: compatibility.getBrowser().version,
platform: compatibility.getPlatform(),
isSupported: compatibility.isW3MSGCompatible()
});
// Check specific features
const features = compatibility.getWebAPISupport();
console.log('Web API Support:', {
webCrypto: features.webCrypto,
serviceWorker: features.serviceWorker,
pushManager: features.pushManager,
localStorage: features.localStorage
});
// Get compatibility report
const report = compatibility.getW3MSGCompatibilityReport();
console.log('Compatibility Issues:', report.issues);
console.log('Recommendations:', report.recommendations);
Browser-Specific Handling
// Handle browser limitations
if (!compatibility.hasFeature('pushManager')) {
console.warn('Push notifications not supported');
// Disable push protocol or provide alternative
}
if (!compatibility.hasFeature('serviceWorker')) {
console.warn('Service workers not supported');
// Use polling instead of push for real-time updates
}
🔄 Protocol Migration
Version Management
import { MigrationManager } from '@w3msg/sdk';
const migrationManager = MigrationManager.getInstance();
// Check if migration is needed
const needsMigration = await migrationManager.needsMigration('xmtp');
if (needsMigration) {
console.log('XMTP protocol migration required');
// Get migration plan
const plan = await migrationManager.createMigrationPlan('xmtp');
console.log(`Migration steps: ${plan.steps.length}`);
console.log(`Estimated time: ${plan.estimatedTimeMs}ms`);
// Execute migration
await migrationManager.executeMigration('xmtp', {
onProgress: (progress) => {
console.log(`Migration progress: ${progress.percentage}%`);
},
onStepComplete: (step) => {
console.log(`Completed step: ${step.name}`);
}
});
}
🎯 Advanced Features
Circuit Breaker Pattern
import { CircuitBreaker } from '@w3msg/sdk';
// Create circuit breaker for a protocol
const breaker = CircuitBreaker.createForProtocol('xmtp');
// Monitor circuit state
breaker.on('stateChange', (newState, oldState) => {
console.log(`Circuit breaker state changed: ${oldState} → ${newState}`);
});
// Use circuit breaker
const result = await breaker.execute(async () => {
return await protocol.sendMessage(params);
});
Event System
// Protocol events
w3msg.on('protocol:registered', (event) => {
console.log(`Protocol registered: ${event.protocolName}`);
});
w3msg.on('protocol:switched', (event) => {
console.log(`Switched to ${event.to} (reason: ${event.reason})`);
});
// Message events
w3msg.on('message:sent', (event) => {
console.log(`Message sent: ${event.messageId}`);
});
w3msg.on('message:received', (event) => {
console.log(`Message received from ${event.from}`);
});
// Health events
w3msg.on('health:alert', (alert) => {
if (alert.severity === 'CRITICAL') {
// Handle critical health issues
}
});
📚 Next Steps
- API Reference - Complete API documentation
- Usage Examples - Practical implementation examples
- Error Handling Guide - Comprehensive error handling patterns
- Migration Guide - Protocol migration and upgrade procedures
- Troubleshooting Guide - Common issues and solutions
🤝 Contributing
The Protocol Abstraction Layer is designed to be extensible. To add support for new protocols:
- Extend the
MessageProtocolabstract class - Implement all required methods
- Register with the
ProtocolManager - Add protocol-specific error mappings
- Update documentation
See the Contributing Guide for more details.