Transceivers
FractaLedger Transceivers
Transceivers are the bridge between FractaLedger and the blockchain networks. They handle transaction broadcasting and wallet address monitoring.
Table of Contents
Overview
FractaLedger uses a flexible transceiver architecture that handles both transaction broadcasting and wallet address monitoring. This approach completely separates transaction creation/signing from the broadcasting and monitoring mechanisms, allowing you to use your existing infrastructure for blockchain interactions.

┌─────────────────────────────────────────────────────────────┐ │ FractaLedger Core │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌──────────────┐ │ │ │ Transaction │ │ Blockchain │ │ Wallet │ │ │ │ Builder │───▶│ Connector │───▶│ Manager │ │ │ └───────────────┘ └───────────────┘ └──────────────┘ │ │ │ │ └──────────────────────────────┼──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Transceiver Manager │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌──────────────┐ │ │ │ Callback │ │ Event │ │ API │ │ │ │ Method │ │ Method │ │ Method │ │ │ └───────────────┘ └───────────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Custom Transceivers │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌──────────────┐ │ │ │ Bitcoin │ │ Litecoin │ │ Dogecoin │ │ │ │ Transceiver │ │ Transceiver │ │ Transceiver │ │ │ └───────────────┘ └───────────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Blockchain Networks │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌──────────────┐ │ │ │ Bitcoin │ │ Litecoin │ │ Dogecoin │ │ │ │ Network │ │ Network │ │ Network │ │ │ └───────────────┘ └───────────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘
The transceiver architecture provides several benefits:
- Flexibility: You can choose how to broadcast transactions and monitor wallet addresses based on your specific needs.
- Extensibility: You can easily add support for new blockchains by implementing new transceivers.
- Separation of Concerns: Transaction creation/signing is separated from broadcasting and monitoring, allowing for better modularity.
- Integration: You can integrate with your existing blockchain infrastructure or third-party services.
Important Note
FractaLedger itself does not directly monitor the blockchain. Instead, it provides the infrastructure for your custom transceivers to handle blockchain monitoring. This design allows you to use your preferred blockchain interaction methods while maintaining a consistent interface within FractaLedger.
Transceiver Methods
FractaLedger supports four transceiver methods, each with its own advantages and use cases:
Callback Method
Uses a custom transceiver module to broadcast transactions and monitor wallet addresses. This method provides maximum flexibility and control.
When to Use
- You need complete control over how transactions are broadcasted
- You want to implement custom monitoring logic
- You need to integrate with specific blockchain APIs or services
Configuration Example
{
"name": "btc_wallet_1",
"network": "mainnet",
"walletAddress": "bc1q...",
"secretEnvVar": "BTC_WALLET_1_SECRET",
"transceiver": {
"method": "callback",
"callbackModule": "./transceivers/spv-transceiver.js",
"config": {
"blockchain": "bitcoin",
"network": "mainnet",
"server": "electrum.blockstream.info",
"port": 50002,
"protocol": "ssl",
"monitoringInterval": 60000,
"autoMonitor": true
}
}
}
Note: The system comes with a default SPV transceiver implementation that supports Bitcoin, Litecoin, and Dogecoin using the Electrum protocol. This is the recommended transceiver for UTXO-based blockchains.
Event Method
Emits events with transaction data and wallet address updates for external listeners. This method is useful for integrating with event-driven architectures.
When to Use
- You have an existing event-driven system
- You want to handle transaction broadcasting and monitoring in a separate process
- You need to notify multiple systems about transactions and wallet updates
Configuration Example
{
"name": "btc_wallet_2",
"network": "mainnet",
"walletAddress": "bc1q...",
"secretEnvVar": "BTC_WALLET_2_SECRET",
"transceiver": {
"method": "event",
"eventNamespace": "transactions"
}
}
Event Handling Example
const fractaledger = require('fractaledger');
// Listen for transaction broadcast events
fractaledger.events.on('transactions:broadcast', (txData) => {
console.log('Transaction to broadcast:', txData);
// Broadcast the transaction using your preferred method
// ...
// Notify FractaLedger about the broadcast result
fractaledger.events.emit('transactions:broadcast:result', {
txid: 'abcdef1234567890...',
success: true,
data: txData
});
});
// Listen for wallet monitoring events
fractaledger.events.on('transactions:monitor', (walletData) => {
console.log('Wallet to monitor:', walletData);
// Set up monitoring for the wallet using your preferred method
// ...
});
API Method
Makes transactions and wallet address updates available through API endpoints. This method is useful for web applications and services.
When to Use
- You want to handle transaction broadcasting through HTTP requests
- You have a separate service that will poll for transactions to broadcast
- You want to integrate with a web application
Configuration Example
{
"name": "btc_wallet_3",
"network": "mainnet",
"walletAddress": "bc1q...",
"secretEnvVar": "BTC_WALLET_3_SECRET",
"transceiver": {
"method": "api",
"apiEndpoint": "/api/transactions"
}
}
API Endpoints
GET /api/transactions/pending
- Get pending transactions to broadcastPOST /api/transactions/results
- Submit broadcast resultsGET /api/wallets/monitoring
- Get wallets to monitorPOST /api/wallets/:id/transactions
- Submit wallet transactions
Transaction Flow
When using the API method, the transaction flow is as follows:
- Transaction Creation: When you use endpoints like
/api/transactions/withdraw
, the system creates a transaction with the specified parameters, signs it with the wallet's private key, generates the raw transaction hex, assigns a transaction ID, and stores this information in the pending transactions map. - Transaction Retrieval: Your application retrieves pending transactions via
GET /api/transactions/pending
. - External Broadcasting: Your application is responsible for broadcasting these transactions to the blockchain network using your own infrastructure or third-party services.
- Result Submission: After broadcasting, your application reports the results back to FractaLedger via
POST /api/transactions/results
.
Return Method
Simply returns transaction data and wallet address updates without broadcasting or monitoring. This method is useful for manual broadcasting or testing.
When to Use
- You want to manually broadcast transactions
- You're testing the system without actually interacting with blockchains
- You want to inspect transaction data before broadcasting
Configuration Example
{
"name": "btc_wallet_4",
"network": "mainnet",
"walletAddress": "bc1q...",
"secretEnvVar": "BTC_WALLET_4_SECRET",
"transceiver": {
"method": "return"
}
}
Usage Example
const fractaledger = require('fractaledger');
// Create a transaction
const txData = await fractaledger.createTransaction({
fromWalletId: 'btc_wallet_4',
toAddress: 'bc1q...',
amount: 0.1,
fee: 0.0001
});
console.log('Transaction data:', txData);
// Manually broadcast the transaction using your preferred method
// ...
Wallet Monitoring
Important Note
FractaLedger does not directly monitor the blockchain. Instead, it provides the infrastructure for your custom transceivers to handle blockchain monitoring. This design allows you to use your preferred blockchain interaction methods while maintaining a consistent interface within FractaLedger.
Wallet monitoring is a critical feature that allows your application to stay synchronized with on-chain activity. The monitoring system in FractaLedger is designed to be flexible, allowing you to implement monitoring in a way that best suits your needs.
Monitoring Capabilities
The monitoring system provides the following capabilities:
- Transaction Detection: Detect incoming and outgoing transactions for monitored wallet addresses
- Balance Updates: Keep track of wallet balances based on blockchain activity
- Event Notifications: Receive notifications when transactions are detected
- Monitoring Management: Start and stop monitoring for specific wallet addresses
Monitoring Methods
FractaLedger supports several methods for monitoring wallet addresses:
Custom Transceiver Monitoring
Implement the monitorWalletAddress
and stopMonitoringWalletAddress
methods in your custom transceiver to handle monitoring using your preferred approach. You can extend the built-in SPV transceiver using the generate-transceiver.js tool.
Extending the SPV Transceiver
The system includes a built-in SPV transceiver that provides robust monitoring capabilities. You can create a local copy of this transceiver to customize it for your specific needs:
# Create a local copy of the SPV transceiver
npx fractaledger-generate-transceiver --type spv --output ./my-transceivers
This will create a copy of the SPV transceiver in your project directory that you can customize while maintaining compatibility with future updates to the FractaLedger package.
Implementation Options
- Websocket Connections: Establish persistent websocket connections to blockchain nodes or services
- Blockchain API Subscriptions: Use subscription-based APIs provided by blockchain services
- Custom Polling: Implement custom polling logic with optimized intervals
- Event-based Systems: Integrate with event-based blockchain monitoring systems
Example Implementation
async monitorWalletAddress(address, callback) {
console.log(`Starting to monitor wallet address: ${address}`);
try {
// Check if the address is already being monitored
if (this.monitoredAddresses.has(address)) {
return this.monitoredAddresses.get(address);
}
// Example: Set up a websocket connection
const ws = new WebSocket(`wss://example.com/blockchain/address/${address}`);
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'transaction') {
// Call the callback with the transaction data
callback([data.transaction]);
// Emit a transactions event
this.emit('transactions', {
address,
transactions: [data.transaction]
});
}
};
// Store the websocket connection
this.monitoringConnections.set(address, ws);
// Store the monitoring details
this.monitoredAddresses.set(address, {
address,
callback,
timestamp: Date.now(),
status: 'active',
method: 'websocket'
});
return {
address,
status: 'active',
method: 'websocket'
};
} catch (error) {
console.error(`Failed to monitor address ${address}: ${error.message}`);
throw new Error(`Failed to monitor address ${address}: ${error.message}`);
}
}
Event-based Monitoring
Use the event system to handle monitoring through external event listeners.
Event Flow
- FractaLedger emits a
monitor
event when a wallet address should be monitored - Your external system listens for these events and sets up monitoring
- When transactions are detected, your system emits
transactions
events back to FractaLedger
Example Implementation
const fractaledger = require('fractaledger');
// Listen for monitoring requests
fractaledger.events.on('monitor', (data) => {
const { address } = data;
console.log(`Setting up monitoring for address: ${address}`);
// Set up your monitoring system (e.g., websocket, API subscription)
const monitor = setupMonitoring(address);
// When transactions are detected, emit events back to FractaLedger
monitor.on('transaction', (transaction) => {
fractaledger.events.emit('transactions', {
address,
transactions: [transaction]
});
});
});
// Listen for stop monitoring requests
fractaledger.events.on('stopMonitor', (data) => {
const { address } = data;
console.log(`Stopping monitoring for address: ${address}`);
// Clean up your monitoring resources
cleanupMonitoring(address);
});
API-based Monitoring
Use API endpoints to manage monitoring and report transactions.
API Endpoints
GET /api/wallets/monitoring
- Get a list of wallet addresses to monitorPOST /api/wallets/:id/transactions
- Submit detected transactions for a wallet
Example Implementation
const axios = require('axios');
// Function to get wallets to monitor
async function getWalletsToMonitor() {
const response = await axios.get('http://localhost:3000/api/wallets/monitoring');
return response.data.wallets;
}
// Function to submit detected transactions
async function submitTransactions(walletId, transactions) {
await axios.post(`http://localhost:3000/api/wallets/${walletId}/transactions`, {
transactions
});
}
// Example monitoring loop
async function monitoringLoop() {
try {
// Get wallets to monitor
const wallets = await getWalletsToMonitor();
// Set up monitoring for each wallet
for (const wallet of wallets) {
if (!monitoredWallets.has(wallet.id)) {
console.log(`Setting up monitoring for wallet: ${wallet.id}`);
// Set up your monitoring system
const monitor = setupMonitoring(wallet.address);
// When transactions are detected, submit them to FractaLedger
monitor.on('transaction', async (transaction) => {
await submitTransactions(wallet.id, [transaction]);
});
monitoredWallets.set(wallet.id, {
wallet,
monitor
});
}
}
// Clean up monitoring for wallets that are no longer in the list
for (const [walletId, { monitor }] of monitoredWallets.entries()) {
if (!wallets.some(w => w.id === walletId)) {
console.log(`Stopping monitoring for wallet: ${walletId}`);
// Clean up your monitoring resources
cleanupMonitoring(monitor);
monitoredWallets.delete(walletId);
}
}
} catch (error) {
console.error(`Monitoring loop error: ${error.message}`);
}
// Schedule the next iteration
setTimeout(monitoringLoop, 60000);
}
// Start the monitoring loop
monitoringLoop();
Polling-based Monitoring (Fallback)
FractaLedger includes a fallback polling-based monitoring system that periodically checks for new transactions. This is used when no other monitoring method is specified.
How It Works
- FractaLedger sets up a polling interval for each monitored wallet address
- At each interval, it calls the
getTransactionHistory
method of your transceiver - It compares the results with previously seen transactions to detect new ones
- When new transactions are detected, it calls the provided callback function
Configuration
{
"name": "btc_wallet_1",
"network": "mainnet",
"walletAddress": "bc1q...",
"secretEnvVar": "BTC_WALLET_1_SECRET",
"transceiver": {
"method": "callback",
"module": "./transceivers/utxo-transceiver.js",
"config": {
"monitoringInterval": 60000 // Polling interval in milliseconds
}
}
}
Monitoring API Endpoints
FractaLedger provides API endpoints for managing wallet monitoring:
Start Monitoring a Wallet
Registers a wallet for monitoring. The actual monitoring implementation depends on the transceiver method configured for the wallet.
Stop Monitoring a Wallet
Stops monitoring a wallet address.
Get Monitored Wallets
Returns a list of wallets that are currently being monitored.
Submit Wallet Transactions
Submits detected transactions for a wallet. This endpoint is used by external monitoring systems to report transactions to FractaLedger.
Setting Up an Automatic Tunnel
An automatic tunnel or watch system between FractaLedger and your blockchain implementation allows for dynamic on-chain interactions without manual intervention. This section explains how to set up such a system.

┌─────────────────────────────────────────────────────────────┐ │ FractaLedger │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌──────────────┐ │ │ │ Transaction │ │ Transceiver │ │ Event │ │ │ │ Creation │───▶│ Manager │◀───│ Handlers │ │ │ └───────────────┘ └───────────────┘ └──────────────┘ │ │ │ │ └──────────────────────────────┼──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Automatic Tunnel │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌──────────────┐ │ │ │ Persistent │ │ Real-time │ │ Transaction │ │ │ │ Connection │◀──▶│ Monitoring │───▶│ Broadcasting │ │ │ └───────────────┘ └───────────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Blockchain Network │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌──────────────┐ │ │ │ Transactions │ │ Blocks │ │ Mempool │ │ │ │ │ │ │ │ │ │ │ └───────────────┘ └───────────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘
Components of an Automatic Tunnel
An effective automatic tunnel consists of the following components:
Persistent Connection
A long-lived connection to your blockchain node or service that stays open to receive real-time updates.
Real-time Monitoring
A mechanism to detect blockchain events (new transactions, blocks) as they happen, rather than polling at intervals.
Transaction Broadcasting
A reliable method to broadcast transactions to the blockchain network when needed.
Automatic Initialization
Logic to automatically set up monitoring when wallets are created or the system starts.
Implementation Steps
Follow these steps to implement an automatic tunnel:
Create a Custom Transceiver
Implement a custom transceiver that establishes persistent connections to your blockchain infrastructure.
// Example: Custom Bitcoin Transceiver with WebSocket connection
const { UTXOTransceiver } = require('fractaledger');
const WebSocket = require('ws');
class BitcoinWebSocketTransceiver extends UTXOTransceiver {
constructor(config = {}) {
super(config);
this.apiUrl = config.apiUrl || 'https://blockstream.info/api';
this.wsUrl = config.wsUrl || 'wss://blockstream.info/api/ws';
this.connections = new Map();
// Initialize any other required properties
this.monitoredAddresses = new Map();
this.monitoringConnections = new Map();
console.log('Bitcoin WebSocket Transceiver initialized');
}
// Implement required methods...
}
module.exports = BitcoinWebSocketTransceiver;
Implement Real-time Monitoring
Implement the monitorWalletAddress
method to establish a real-time connection for monitoring.
async monitorWalletAddress(address, callback) {
console.log(`Starting to monitor wallet address: ${address}`);
try {
// Check if the address is already being monitored
if (this.monitoredAddresses.has(address)) {
return this.monitoredAddresses.get(address);
}
// Create a WebSocket connection for this address
const ws = new WebSocket(`${this.wsUrl}/address/${address}`);
ws.onopen = () => {
console.log(`WebSocket connection established for ${address}`);
};
ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
// Process the transaction data
const transaction = {
txid: data.txid,
amount: this.calculateAmount(data, address),
timestamp: Date.now(),
confirmations: data.status.confirmed ? 1 : 0
};
// Call the callback with the transaction data
callback([transaction]);
// Emit a transactions event
this.emit('transactions', {
address,
transactions: [transaction]
});
} catch (error) {
console.error(`Error processing WebSocket message: ${error.message}`);
}
};
ws.onerror = (error) => {
console.error(`WebSocket error for ${address}: ${error.message}`);
};
ws.onclose = () => {
console.log(`WebSocket connection closed for ${address}`);
// Attempt to reconnect after a delay
setTimeout(() => {
if (this.monitoredAddresses.has(address)) {
console.log(`Attempting to reconnect WebSocket for ${address}`);
this.monitorWalletAddress(address, callback);
}
}, 5000);
};
// Store the WebSocket connection
this.monitoringConnections.set(address, ws);
// Store the monitoring details
this.monitoredAddresses.set(address, {
address,
callback,
timestamp: Date.now(),
status: 'active',
method: 'websocket'
});
return {
address,
status: 'active',
method: 'websocket'
};
} catch (error) {
console.error(`Failed to monitor address ${address}: ${error.message}`);
throw new Error(`Failed to monitor address ${address}: ${error.message}`);
}
}
Implement Transaction Broadcasting
Implement the broadcastTransaction
method to send transactions to the blockchain network.
async broadcastTransaction(txHex, metadata = {}) {
console.log(`Broadcasting transaction: ${metadata.txid || 'unknown'}`);
try {
// Use the REST API to broadcast the transaction
const response = await fetch(`${this.apiUrl}/tx`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ txHex })
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`API error: ${errorData.message || response.statusText}`);
}
const result = await response.json();
// Emit a transaction event
this.emit('transaction', {
txid: result.txid,
txHex,
metadata,
timestamp: Date.now()
});
return result.txid;
} catch (error) {
console.error(`Failed to broadcast transaction: ${error.message}`);
throw new Error(`Failed to broadcast transaction: ${error.message}`);
}
}
Implement Automatic Initialization
Configure your transceiver to automatically start monitoring when wallets are created or the system starts.
// In your transceiver configuration
{
"name": "btc_wallet_1",
"network": "mainnet",
"walletAddress": "bc1q...",
"secretEnvVar": "BTC_WALLET_1_SECRET",
"transceiver": {
"method": "callback",
"module": "./transceivers/bitcoin-websocket-transceiver.js",
"config": {
"apiUrl": "https://blockstream.info/api",
"wsUrl": "wss://blockstream.info/api/ws",
"autoMonitor": true
}
}
}
// In your transceiver's initialize method
async initialize() {
console.log('Initializing Bitcoin WebSocket Transceiver');
try {
// If autoMonitor is enabled, start monitoring the wallet address
if (this.config.autoMonitor && this.config.walletAddress) {
await this.monitorWalletAddress(this.config.walletAddress, (transactions) => {
console.log(`Detected ${transactions.length} transactions for ${this.config.walletAddress}`);
// Process the transactions
});
}
console.log('Bitcoin WebSocket Transceiver initialized successfully');
} catch (error) {
console.error(`Failed to initialize Bitcoin WebSocket Transceiver: ${error.message}`);
throw new Error(`Failed to initialize Bitcoin WebSocket Transceiver: ${error.message}`);
}
}
Handle Connection Management
Implement robust connection management to handle disconnections, reconnections, and cleanup.
async stopMonitoringWalletAddress(address) {
console.log(`Stopping monitoring for wallet address: ${address}`);
try {
// Check if the address is being monitored
if (!this.monitoredAddresses.has(address)) {
console.log(`Address ${address} is not being monitored`);
return false;
}
// Get the WebSocket connection
const ws = this.monitoringConnections.get(address);
// Close the WebSocket connection
if (ws && ws.readyState !== WebSocket.CLOSED) {
ws.close();
}
// Remove the connection from the maps
this.monitoringConnections.delete(address);
this.monitoredAddresses.delete(address);
console.log(`Stopped monitoring address ${address}`);
return true;
} catch (error) {
console.error(`Failed to stop monitoring address ${address}: ${error.message}`);
throw new Error(`Failed to stop monitoring address ${address}: ${error.message}`);
}
}
async cleanup() {
console.log('Cleaning up Bitcoin WebSocket Transceiver resources');
try {
// Close all WebSocket connections
for (const [address, ws] of this.monitoringConnections.entries()) {
if (ws && ws.readyState !== WebSocket.CLOSED) {
ws.close();
}
}
// Clear all maps
this.monitoringConnections.clear();
this.monitoredAddresses.clear();
console.log('Bitcoin WebSocket Transceiver resources cleaned up successfully');
} catch (error) {
console.error(`Failed to clean up Bitcoin WebSocket Transceiver resources: ${error.message}`);
throw new Error(`Failed to clean up Bitcoin WebSocket Transceiver resources: ${error.message}`);
}
}
Benefits of an Automatic Tunnel
Implementing an automatic tunnel provides several benefits:
- Real-time Updates: Get immediate notifications of blockchain activity
- Reduced Latency: Minimize the delay between on-chain events and system updates
- Lower Resource Usage: Avoid the overhead of frequent polling
- Better User Experience: Provide users with up-to-date information without manual refreshes
- Simplified Integration: Automate the connection between FractaLedger and your blockchain infrastructure
Considerations
When implementing an automatic tunnel, consider the following:
- Connection Stability: Implement robust error handling and reconnection logic
- Resource Management: Ensure proper cleanup of resources when connections are no longer needed
- Scalability: Consider how your solution will scale with an increasing number of monitored wallets
- Security: Ensure secure communication between your application and blockchain nodes
- Fallback Mechanisms: Implement fallback mechanisms (like polling) for when real-time connections fail