TAP Node
A high-performance, asynchronous node implementation for the Transaction Authorization Protocol (TAP). This crate provides a complete node infrastructure for managing TAP agents, routing messages, and coordinating secure financial transactions.
Overview
The TAP Node acts as a central hub for TAP communications, managing multiple agents, processing messages, and coordinating the transaction lifecycle. It is designed for high-throughput environments, with support for concurrent message processing, event-driven architecture, and robust error handling.
Key Features
- Multi-Agent Management: Register and manage multiple TAP agents with different roles and capabilities
- Message Processing Pipeline: Process messages through configurable middleware chains
- Message Routing: Intelligently route messages to the appropriate agent based on DID addressing
- Concurrent Processing: Scale to high throughput with worker pools for message processing
- Event Publishing: Comprehensive event system for monitoring and reacting to node activities
- Flexible Message Delivery: Send messages via HTTP or WebSockets with robust error handling
- Cross-Platform Support: Native and WASM environments for both HTTP and WebSocket transports
- DID Resolution: Resolve DIDs for message verification and routing
- Configurable Components: Customize node behavior with pluggable components
- Thread-Safe Design: Safely share the node across threads with appropriate synchronization
- WASM Compatibility: Optional WASM support for browser environments
- Per-Agent Storage: Agent-specific SQLite databases with automatic isolation:
- Each agent gets its own dedicated storage instance at
~/.tap/{sanitized_did}/transactions.db - Transaction tracking for Transfer and Payment messages
- Complete audit trail of all incoming/outgoing messages
- Multi-agent transaction storage ensuring all involved agents receive transaction data
- Each agent gets its own dedicated storage instance at
- Multi-Recipient Message Delivery: Full DIDComm specification compliance:
- Messages delivered to ALL recipients specified in the
tofield - Storage logging to all recipient agents' databases
- Proper handling of multi-party transactions and communications
- Messages delivered to ALL recipients specified in the
Installation
Add the crate to your Cargo.toml:
[]
= { = "../tap-node" }
= { = "../tap-agent" }
= { = "../tap-msg" }
# Optional features
= { = "../tap-node", = ["native"] } # Enable HTTP support
= { = "../tap-node", = ["websocket"] } # Enable WebSocket support
= { = "../tap-node", = ["native-with-websocket"] } # Enable both HTTP and WebSocket
= { = "../tap-node", = ["wasm"] } # Enable WASM support
= { = "../tap-node", = ["wasm-with-websocket"] } # Enable WASM with WebSocket
= { = "../tap-node", = ["storage"] } # Enable persistent storage (enabled by default)
Architecture
The TAP Node is built with a modular architecture:
┌─────────────────────────────────────────────────────────────────────┐
│ TAP Node │
├───────────────┬───────────────┬─────────────────┬───────────────────┤
│ Agent Registry│ Message Router│ Event Bus │ AgentStorageManager│
├───────────────┼───────────────┼─────────────────┼───────────────────┤
│ Message │ Processor Pool│ DID Resolver │ Per-Agent Storage │
│ Processors │ │ │ Isolation │
└───────────────┴───────────────┴─────────────────┴───────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐
│ TAP Agent │ │ TAP Agent │ │ TAP Agent │ │ ~/.tap/{did}/ │
│ Agent A │ │ Agent B │ │ Agent C │ │ transactions.db │
└───────────────┘ └───────────────┘ └───────────────┘ └─────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐
│ SQLite DB │ │ SQLite DB │ │ SQLite DB │ │ Multi-Recipient │
│ Agent A │ │ Agent B │ │ Agent C │ │ Message Delivery│
└───────────────┘ └───────────────┘ └───────────────┘ └─────────────────┘
Usage
Basic Setup
use ;
use ;
use ;
use MultiResolver;
use Arc;
use Duration;
async
Processing Messages
use PlainMessage;
use json;
// Receive and process an incoming message
async
// Send a message from one agent to multiple recipients
async
// Example: Creating a multi-recipient message
async
Event Handling and Logging
The TAP Node includes a powerful event system with configurable logging capabilities:
use Arc;
use async_trait;
use ;
use ;
use ;
// Create a TAP Node with event logging enabled
let mut config = default;
config.event_logger = Some;
// Initialize node with event logging
let node = new;
// Create a custom event subscriber
;
// Subscribe to events
async
Event Logger Configuration
The event logger supports different destinations:
// Log to console
let config = EventLoggerConfig ;
// Log to file with rotation
let config = EventLoggerConfig ;
// Custom logging function
let custom_logger = new;
let config = EventLoggerConfig ;
Custom Message Processors
You can create custom message processors to extend the node's capabilities:
use async_trait;
use Result;
use MessageProcessor;
use PlainMessage;
;
Message Transport
TAP Node provides multiple options for sending messages between nodes:
HTTP Message Sender
For standard request-response communication patterns:
use ;
// Create an HTTP sender with default settings
let sender = new;
// Create with custom settings (timeout and retries)
let sender = with_options;
// Send a packed message to recipients
sender.send.await?;
WebSocket Message Sender
For real-time bidirectional communication:
use ;
// Create a WebSocket sender with default settings
let sender = new;
// Create with custom settings
let sender = with_options;
// Send a message over an established WebSocket connection
sender.send.await?;
Key benefits of the WebSocket transport:
- Persistent connections for lower latency
- Bidirectional communication
- Connection state awareness
- Reduced overhead for frequent messages
Per-Agent Storage Architecture
The TAP Node features a sophisticated per-agent storage system using SQLite databases. This architecture provides complete data isolation between agents while ensuring all involved parties receive relevant transaction data.
Key Features
- Agent-Specific Databases: Each agent gets its own SQLite database at
~/.tap/{sanitized_did}/transactions.db - Multi-Agent Transaction Storage: Transactions are automatically stored in ALL involved agents' databases
- Multi-Recipient Message Delivery: Messages are delivered to ALL recipients specified in the
tofield - Complete Message Audit Trail: All incoming and outgoing messages logged per agent
- Automatic Storage Initialization: Agent storage created automatically during registration
Storage Configuration
Configure per-agent storage when creating the node:
use ;
use PathBuf;
// Use default TAP root (~/.tap) for per-agent storage
let config = NodeConfig ;
// Or specify a custom TAP root directory
let config = NodeConfig ;
// Agent storage locations:
// - Default: ~/.tap/{sanitized_did}/transactions.db
// - Custom: /custom/tap/root/{sanitized_did}/transactions.db
Accessing Stored Data
use MessageDirection;
// Access agent-specific storage
if let Some = node.agent_storage_manager
// Access legacy centralized storage (if available)
if let Some = node.storage
Storage Features
- Agent Isolation: Each agent has its own dedicated SQLite database
- Multi-Agent Transactions: Transactions automatically stored in all involved agents' databases
- Multi-Recipient Delivery: Messages delivered to ALL recipients in the
tofield - Async Database Operations: Built on SQLx for native async support
- Automatic Migration: Database schema is automatically created and migrated on startup
- Dual-Table Design: Separate tables for transactions and message audit trail per agent
- Append-Only Design: All data is immutable for compliance and auditing
- SQLite WAL Mode: Optimized for concurrent reads and writes
- Connection Pooling: SQLx connection pool for efficient database access per agent
- JSON Column Support: Message content stored as validated JSON
- WASM Compatibility: Storage is automatically disabled in WASM builds
- Duplicate Handling: Duplicate messages are silently ignored (idempotent)
- Directory Management: Automatic creation of agent-specific directories
Database Schema
The storage system maintains two tables:
transactions Table
Business logic for Transfer and Payment messages:
- Transaction ID and type (Transfer/Payment)
- Sender and recipient DIDs
- Thread ID for conversation tracking
- Full message content stored in JSON column type
- Status tracking (pending/confirmed/failed/cancelled/reverted)
- Timestamps for creation and updates
messages Table
Complete audit trail of all messages:
- Message ID and type (all TAP message types)
- Direction (incoming/outgoing)
- Sender and recipient DIDs
- Thread IDs (including parent threads)
- Full message content stored in JSON column type
- Creation timestamp
Disabling Storage
To disable storage (for example, in memory-only deployments):
[]
= { = "../tap-node", = false, = ["native"] }
Integration with Other Crates
The TAP Node integrates with the TAP ecosystem:
- tap-agent: Provides the agent implementation used by the node
- tap-msg: Defines the message types and formats
- tap-caip: Handles chain-agnostic identifiers used in transactions
- tap-http: Can be used to create HTTP endpoints for the node
- tap-wasm: Enables WASM compatibility for browser environments
Performance Considerations
The TAP Node is designed for high performance:
- Use processor pools for concurrent message processing
- Configure worker counts based on your hardware
- Consider message validation trade-offs
- Use appropriate channel capacities for your workload
- Profile your specific use case for optimal settings
Examples
The package includes several examples:
benches/stress_test.rs- Benchmark of node performance with different message loadsexamples/http_message_flow.rs- Example of using HTTP for message deliveryexamples/websocket_message_flow.rs- Example of using WebSockets for real-time communication
Run examples with:
# Run with HTTP support
# Run with WebSocket support
License
This crate is licensed under the terms of the MIT license.