Watch-Only Node API
The Watch-Only Node API provides read-only access to Lightning Network node information without requiring node control.
Endpoints
Get Node ID
Get the node ID for a specific network.
Service: WatchOnlyNodeServiceMethod: GetNodeId
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Network to get node ID for |
Response:
| Field | Type | Description |
|---|---|---|
node_id | string | Lightning node public key |
Example Request:
TypeScript
const nodeId = await hydraGrpcClient.getNodeId({
protocol: Protocol.BITCOIN,
id: '0a03cf40' // Bitcoin Signet
})
Rust
let request = tonic::Request::new(GetNodeIdRequest {
network: Some(Network {
protocol: Protocol::Bitcoin as i32,
id: "0a03cf40".to_string(),
}),
});
let response = client.get_node_id(request).await?;
let node_id = response.into_inner().node_id;
Get Channels
Get all channels for a network.
Service: WatchOnlyNodeServiceMethod: GetChannels
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Network to query channels for |
Response:
| Field | Type | Description |
|---|---|---|
channels | Channel[] | Array of channel objects |
Channel Object:
| Field | Type | Description |
|---|---|---|
id | string | Channel identifier |
counterparty | string | Counterparty node ID |
status | ChannelStatus | Channel status |
asset_channels | map<string, AssetChannel> | Asset-specific channel data |
Example Request:
TypeScript
const channels = await hydraGrpcClient.getChannels({
protocol: Protocol.BITCOIN,
id: '0a03cf40'
})
channels.forEach(ch => {
console.log(`Channel ${ch.id} with ${ch.counterparty}`)
})
Rust
let request = tonic::Request::new(GetChannelsRequest {
network: Some(Network {
protocol: Protocol::Bitcoin as i32,
id: "0a03cf40".to_string(),
}),
});
let response = client.get_channels(request).await?;
let channels = response.into_inner().channels;
for channel in channels {
println!("Channel {} with {}", channel.id, channel.counterparty);
}
Get Channels With Counterparty
Get all channels with a specific counterparty node.
Service: WatchOnlyNodeServiceMethod: GetChannelsWithCounterparty
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Network to query |
counterparty_node_id | string | YES | Counterparty node public key |
Response:
| Field | Type | Description |
|---|---|---|
channels | Channel[] | Channels with this counterparty |
Example Request:
TypeScript
const channels = await hydraGrpcClient.getChannelsWithCounterparty({
network: {
protocol: Protocol.BITCOIN,
id: '0a03cf40'
},
counterpartyNodeId: '02abc123...'
})
Rust
let request = tonic::Request::new(GetChannelsWithCounterpartyRequest {
network: Some(Network {
protocol: Protocol::Bitcoin as i32,
id: "0a03cf40".to_string(),
}),
counterparty_node_id: "02abc123...".to_string(),
});
let response = client.get_channels_with_counterparty(request).await?;
let channels = response.into_inner().channels;
Get Channel
Get detailed information about a specific channel.
Service: WatchOnlyNodeServiceMethod: GetChannel
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Network the channel is on |
channel_id | string | YES | Channel identifier |
Response:
| Field | Type | Description |
|---|---|---|
channel | Channel | Detailed channel information |
Example Request:
TypeScript
const channel = await hydraGrpcClient.getChannel({
network: {
protocol: Protocol.BITCOIN,
id: '0a03cf40'
},
channelId: 'ch_abc123'
})
console.log(`Channel status: ${channel.status}`)
console.log(`Counterparty: ${channel.counterparty}`)
Rust
let request = tonic::Request::new(GetChannelRequest {
network: Some(Network {
protocol: Protocol::Bitcoin as i32,
id: "0a03cf40".to_string(),
}),
channel_id: "ch_abc123".to_string(),
});
let response = client.get_channel(request).await?;
let channel = response.into_inner().channel;
Get Payments
Get payment history for a network.
Service: WatchOnlyNodeServiceMethod: GetPayments
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
network | Network | YES | Network to query payments for |
Response:
| Field | Type | Description |
|---|---|---|
payments | Payment[] | Array of payment objects |
Payment Object:
| Field | Type | Description |
|---|---|---|
id | string | Payment identifier |
direction | PaymentDirection | INCOMING or OUTGOING |
status | PaymentStatus | Payment status |
amount | map<string, DecimalString> | Asset amounts |
timestamp | Timestamp | Payment timestamp |
Example Request:
TypeScript
const payments = await hydraGrpcClient.getPayments({
protocol: Protocol.BITCOIN,
id: '0a03cf40'
})
payments.forEach(payment => {
console.log(`${payment.direction} payment: ${payment.id}`)
})
Rust
let request = tonic::Request::new(GetPaymentsRequest {
network: Some(Network {
protocol: Protocol::Bitcoin as i32,
id: "0a03cf40".to_string(),
}),
});
let response = client.get_payments(request).await?;
let payments = response.into_inner().payments;
for payment in payments {
println!("{:?} payment: {}", payment.direction, payment.id);
}
Common Patterns
Monitor channel status
Rust
async fn get_active_channels(
client: &mut WatchOnlyNodeServiceClient<Channel>,
network: Network,
) -> Result<Vec<Channel>, Box<dyn std::error::Error>> {
let channels = client
.get_channels(GetChannelsRequest {
network: Some(network),
})
.await?
.into_inner()
.channels;
Ok(channels
.into_iter()
.filter(|ch| ch.status == ChannelStatus::Active as i32)
.collect())
}
Find channel with peer
Rust
async fn find_channel_with_peer(
client: &mut WatchOnlyNodeServiceClient<Channel>,
network: Network,
peer_id: String,
) -> Result<Option<Channel>, Box<dyn std::error::Error>> {
let channels = client
.get_channels_with_counterparty(GetChannelsWithCounterpartyRequest {
network: Some(network),
counterparty_node_id: peer_id,
})
.await?
.into_inner()
.channels;
Ok(channels.into_iter().next())
}
Error Handling
| Error Code | Description | Solution |
|---|---|---|
INVALID_ARGUMENT | Invalid network or channel ID | Verify parameters |
NOT_FOUND | Channel or payment not found | Check ID is correct |
UNAVAILABLE | Service temporarily unavailable | Retry with backoff |
Best Practices
- Read-only monitoring - Use this for monitoring without control
- Cache channel list - Channels don't change frequently
- Filter by status - Focus on active channels for routing
- Track payments - Monitor for payment reconciliation