opnet
Version:
The perfect library for building Bitcoin-based applications.
387 lines (291 loc) • 9.56 kB
Markdown
The `WebSocketRpcProvider` enables real-time communication with OPNet nodes through persistent WebSocket connections, supporting subscriptions for new blocks and epochs.
```mermaid
sequenceDiagram
participant App as Your App
participant Provider as WebSocketRpcProvider
participant Node as OPNet Node
App->>Provider: connect()
Provider->>Node: WebSocket handshake
Node-->>Provider: Connected
App->>Provider: subscribeBlocks()
Provider->>Node: Subscribe request
Node-->>Provider: Subscription confirmed
loop On New Block
Node->>Provider: Block notification
Provider->>App: Callback with block data
end
App->>Provider: disconnect()
Provider->>Node: Close connection
```
---
```typescript
import { WebSocketRpcProvider } from 'opnet';
import { networks } from '@btc-vision/bitcoin';
const provider = new WebSocketRpcProvider({
url: 'wss://regtest.opnet.org/ws',
network: networks.regtest,
});
// Wait for connection
await provider.connect();
console.log('Connected to OPNet!');
```
---
Subscribe to receive notifications when new blocks are mined. The `subscribeBlocks` method returns `Promise<void>` (not an unsubscribe function). To unsubscribe, use `provider.unsubscribe(SubscriptionType.BLOCKS)`.
```typescript
import { SubscriptionType } from 'opnet';
// Subscribe to new blocks
await provider.subscribeBlocks((block) => {
console.log('New block!');
console.log(' Block number:', block.blockNumber);
console.log(' Hash:', block.blockHash);
console.log(' Timestamp:', block.timestamp);
console.log(' TX count:', block.txCount);
});
// Later, unsubscribe
await provider.unsubscribe(SubscriptionType.BLOCKS);
```
Subscribe to epoch updates for mining. Like block subscriptions, `subscribeEpochs` returns `Promise<void>`.
```typescript
import { SubscriptionType } from 'opnet';
// Subscribe to epoch updates
await provider.subscribeEpochs((epoch) => {
console.log('Epoch update!');
console.log(' Epoch number:', epoch.epochNumber);
console.log(' Epoch hash:', epoch.epochHash);
});
// Unsubscribe when done
await provider.unsubscribe(SubscriptionType.EPOCHS);
```
---
The WebSocket provider emits various events you can listen to:
```typescript
import { WebSocketClientEvent } from 'opnet';
// Connection opened
provider.on(WebSocketClientEvent.CONNECTED, () => {
console.log('WebSocket connected');
});
// Connection closed
provider.on(WebSocketClientEvent.DISCONNECTED, () => {
console.log('WebSocket disconnected');
});
// Error occurred
provider.on(WebSocketClientEvent.ERROR, (error) => {
console.error('WebSocket error:', error);
});
// Block received
provider.on(WebSocketClientEvent.BLOCK, (block) => {
console.log('Block via event:', block.blockNumber);
});
// Epoch received
provider.on(WebSocketClientEvent.EPOCH, (epoch) => {
console.log('Epoch via event:', epoch.epochNumber);
});
```
---
```typescript
import { ConnectionState } from 'opnet';
// Check connection state
const state = provider.getState();
switch (state) {
case ConnectionState.DISCONNECTED:
console.log('Not connected');
break;
case ConnectionState.CONNECTING:
console.log('Connecting...');
break;
case ConnectionState.CONNECTED:
console.log('Connected');
break;
case ConnectionState.HANDSHAKING:
console.log('Handshaking...');
break;
case ConnectionState.READY:
console.log('Ready');
break;
case ConnectionState.RECONNECTING:
console.log('Reconnecting...');
break;
case ConnectionState.CLOSING:
console.log('Closing...');
break;
}
```
```typescript
// Connect
await provider.connect();
// Disconnect
provider.disconnect();
```
The provider automatically attempts to reconnect on connection loss:
```typescript
const provider = new WebSocketRpcProvider({
url,
network,
websocketConfig: {
maxReconnectAttempts: 10, // Max reconnection attempts (default: 10)
reconnectBaseDelay: 1000, // Base delay between attempts in ms (default: 1000)
autoReconnect: true, // Enable auto-reconnect
},
});
```
---
```typescript
interface WebSocketClientConfig {
// Connection settings
url?: string; // WebSocket URL
connectTimeout?: number; // Connection timeout (default: 10000ms)
handshakeTimeout?: number; // Handshake timeout
// Reconnection settings
maxReconnectAttempts?: number; // Default: 10
reconnectBaseDelay?: number; // Default: 1000ms
reconnectMaxDelay?: number; // Max delay between reconnect attempts
autoReconnect?: boolean; // Default: true
// Request settings
requestTimeout?: number; // Default: 30000ms
maxPendingRequests?: number; // Max pending requests
// Heartbeat
pingInterval?: number; // Default: 30000ms
}
```
```typescript
import { WebSocketRpcProvider } from 'opnet';
import { networks } from '@btc-vision/bitcoin';
const provider = new WebSocketRpcProvider({
url: 'wss://regtest.opnet.org/ws',
network: networks.regtest,
websocketConfig: {
maxReconnectAttempts: 10,
reconnectBaseDelay: 1000,
autoReconnect: true,
connectTimeout: 15000,
requestTimeout: 60000,
pingInterval: 20000,
},
});
await provider.connect();
```
---
The WebSocket provider supports all the same RPC methods as the JSON-RPC provider:
```typescript
// Block operations
const height = await provider.getBlockNumber();
const block = await provider.getBlock(height);
// Transaction operations
const tx = await provider.getTransaction('txHash');
const receipt = await provider.getTransactionReceipt('txHash');
// Contract operations
const result = await provider.call(contractAddress, calldata);
// Balance operations
const balance = await provider.getBalance('bc1q...');
```
---
```typescript
import {
WebSocketRpcProvider,
WebSocketClientEvent,
SubscriptionType,
} from 'opnet';
import { networks } from '@btc-vision/bitcoin';
async function main() {
const provider = new WebSocketRpcProvider({
url: 'wss://regtest.opnet.org/ws',
network: networks.regtest,
websocketConfig: {
autoReconnect: true,
maxReconnectAttempts: 10,
},
});
// Set up event handlers
provider.on(WebSocketClientEvent.CONNECTED, () => {
console.log('Connected!');
});
provider.on(WebSocketClientEvent.DISCONNECTED, () => {
console.log('Disconnected');
});
provider.on(WebSocketClientEvent.ERROR, (error) => {
console.error('Error:', error);
});
// Connect
await provider.connect();
// Get current state
const height = await provider.getBlockNumber();
console.log('Current block:', height);
// Subscribe to new blocks
await provider.subscribeBlocks((block) => {
console.log('New block:', block.blockNumber);
});
// Subscribe to epochs
await provider.subscribeEpochs((epoch) => {
console.log('Epoch:', epoch.epochNumber);
});
// Keep running for a while
await new Promise((resolve) => setTimeout(resolve, 60000));
// Cleanup
await provider.unsubscribe(SubscriptionType.BLOCKS);
await provider.unsubscribe(SubscriptionType.EPOCHS);
provider.disconnect();
}
main().catch(console.error);
```
---
```typescript
import { OPNetError, WebSocketErrorCode } from 'opnet';
try {
await provider.connect();
} catch (error) {
if (error instanceof OPNetError) {
switch (error.code) {
case WebSocketErrorCode.ConnectionFailed:
console.error('Could not connect to server');
break;
case WebSocketErrorCode.Timeout:
console.error('Connection timed out');
break;
case WebSocketErrorCode.ServerError:
console.error('Server error:', error.message);
break;
default:
console.error('Unknown error:', error.message);
}
}
}
```
---
1. **Handle Disconnections**: Set up reconnection handlers
2. **Unsubscribe When Done**: Always call `provider.unsubscribe()` with the appropriate `SubscriptionType`
3. **Configure Timeouts**: Adjust based on network conditions
4. **Monitor Connection State**: React to state changes
5. **Clean Disconnect**: Call `disconnect()` before exiting
```typescript
// Graceful shutdown
process.on('SIGINT', () => {
console.log('Shutting down...');
provider.disconnect();
process.exit(0);
});
```
---
- [Internal Caching](./internal-caching.md) - Provider caching behavior
- [Advanced Configuration](./advanced-configuration.md) - Error handling and retry logic
- [Epoch Operations](../epochs/overview.md) - Working with epochs
---
[← Previous: JSON-RPC Provider](./json-rpc-provider.md) | [Next: Internal Caching →](./internal-caching.md)