Register bitcoin.rs and lnd.rs modules in mod.rs and add route entries for bitcoin.getinfo and lnd.getinfo. Add bitcoinInfo ref and context display to AIUI useArchy.ts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
125 lines
3.9 KiB
Rust
125 lines
3.9 KiB
Rust
use super::RpcHandler;
|
|
use anyhow::{Context, Result};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Debug, Serialize)]
|
|
struct LndInfo {
|
|
alias: String,
|
|
num_active_channels: u32,
|
|
num_peers: u32,
|
|
synced_to_chain: bool,
|
|
block_height: u64,
|
|
balance_sats: i64,
|
|
channel_balance_sats: i64,
|
|
pending_open_balance: i64,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct LndGetInfoResponse {
|
|
alias: Option<String>,
|
|
num_active_channels: Option<u32>,
|
|
num_peers: Option<u32>,
|
|
synced_to_chain: Option<bool>,
|
|
block_height: Option<u64>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct LndChannelBalanceResponse {
|
|
local_balance: Option<LndAmount>,
|
|
pending_open_local_balance: Option<LndAmount>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct LndBalanceResponse {
|
|
total_balance: Option<String>,
|
|
#[allow(dead_code)]
|
|
confirmed_balance: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct LndAmount {
|
|
sat: Option<String>,
|
|
}
|
|
|
|
impl RpcHandler {
|
|
pub(super) async fn handle_lnd_getinfo(&self) -> Result<serde_json::Value> {
|
|
let macaroon_path =
|
|
"/var/lib/archipelago/lnd/data/chain/bitcoin/mainnet/admin.macaroon";
|
|
|
|
let macaroon_bytes = tokio::fs::read(macaroon_path)
|
|
.await
|
|
.context("Failed to read LND admin macaroon — is LND installed?")?;
|
|
let macaroon_hex = hex::encode(&macaroon_bytes);
|
|
|
|
let client = reqwest::Client::builder()
|
|
.timeout(std::time::Duration::from_secs(10))
|
|
.danger_accept_invalid_certs(true)
|
|
.build()
|
|
.context("Failed to create HTTP client")?;
|
|
|
|
let get_info: LndGetInfoResponse = client
|
|
.get("https://127.0.0.1:8080/v1/getinfo")
|
|
.header("Grpc-Metadata-macaroon", &macaroon_hex)
|
|
.send()
|
|
.await
|
|
.context("LND REST connection failed")?
|
|
.json()
|
|
.await
|
|
.context("Failed to parse LND getinfo response")?;
|
|
|
|
let channel_balance: LndChannelBalanceResponse = match client
|
|
.get("https://127.0.0.1:8080/v1/balance/channels")
|
|
.header("Grpc-Metadata-macaroon", &macaroon_hex)
|
|
.send()
|
|
.await
|
|
{
|
|
Ok(resp) => resp.json().await.unwrap_or(LndChannelBalanceResponse {
|
|
local_balance: None,
|
|
pending_open_local_balance: None,
|
|
}),
|
|
Err(_) => LndChannelBalanceResponse {
|
|
local_balance: None,
|
|
pending_open_local_balance: None,
|
|
},
|
|
};
|
|
|
|
let wallet_balance: LndBalanceResponse = match client
|
|
.get("https://127.0.0.1:8080/v1/balance/blockchain")
|
|
.header("Grpc-Metadata-macaroon", &macaroon_hex)
|
|
.send()
|
|
.await
|
|
{
|
|
Ok(resp) => resp.json().await.unwrap_or(LndBalanceResponse {
|
|
total_balance: None,
|
|
confirmed_balance: None,
|
|
}),
|
|
Err(_) => LndBalanceResponse {
|
|
total_balance: None,
|
|
confirmed_balance: None,
|
|
},
|
|
};
|
|
|
|
let info = LndInfo {
|
|
alias: get_info.alias.unwrap_or_default(),
|
|
num_active_channels: get_info.num_active_channels.unwrap_or(0),
|
|
num_peers: get_info.num_peers.unwrap_or(0),
|
|
synced_to_chain: get_info.synced_to_chain.unwrap_or(false),
|
|
block_height: get_info.block_height.unwrap_or(0),
|
|
balance_sats: wallet_balance
|
|
.total_balance
|
|
.and_then(|s| s.parse().ok())
|
|
.unwrap_or(0),
|
|
channel_balance_sats: channel_balance
|
|
.local_balance
|
|
.and_then(|a| a.sat.and_then(|s| s.parse().ok()))
|
|
.unwrap_or(0),
|
|
pending_open_balance: channel_balance
|
|
.pending_open_local_balance
|
|
.and_then(|a| a.sat.and_then(|s| s.parse().ok()))
|
|
.unwrap_or(0),
|
|
};
|
|
|
|
Ok(serde_json::to_value(info)?)
|
|
}
|
|
}
|