Skip to content

Commit

Permalink
chore: nicer CLN error parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
michael1011 committed Jan 2, 2025
1 parent 730e26b commit 8bc9fa9
Showing 1 changed file with 49 additions and 1 deletion.
50 changes: 49 additions & 1 deletion boltzr/src/lightning/cln/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::lightning::cln::cln_rpc::{
ListconfigsResponse,
};
use alloy::hex;
use anyhow::anyhow;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::fs;
Expand Down Expand Up @@ -76,7 +77,8 @@ impl Cln {
recurrence_label: None,
recurrence_counter: None,
})
.await?;
.await
.map_err(Self::parse_error)?;

Ok(res.into_inner().invoice)
}
Expand All @@ -93,6 +95,34 @@ impl Cln {
.await?;
Ok(res.into_inner())
}

fn parse_error(status: tonic::Status) -> anyhow::Error {
let mut msg = status.message();

const MESSAGE_PREFIXES: &[&str] = &["message: \"", "message\":\"", "message\\\":\\\""];
const MESSAGE_SUFFIXES: &[&str] = &["\", data:", "\\\"}", "\"}"];

'outer: loop {
for prefix in MESSAGE_PREFIXES {
if let Some(start) = msg.find(prefix) {
for suffix in MESSAGE_SUFFIXES {
if let Some(end) = msg.rfind(suffix) {
msg = &msg[start + prefix.len()..end];
continue 'outer;
}
}
}
}

break;
}

if msg.is_empty() {
return anyhow!("{}", status.code().to_string());
}

anyhow!(msg.to_owned())
}
}

#[async_trait]
Expand Down Expand Up @@ -137,3 +167,21 @@ impl BaseClient for Cln {
Ok(())
}
}

#[cfg(test)]
mod test {
use super::*;
use rstest::*;

#[rstest]
#[case("Error calling method Xpay: RpcError { code: Some(203), message: \"Destination said it doesn't know invoice: incorrect_or_unknown_payment_details\", data: None }", "Destination said it doesn't know invoice: incorrect_or_unknown_payment_details")]
#[case("Failed: could not route or connect directly to 02ead25af6e0271c5167d6fd05545d2d538995ce3e16ad780a1010fc4e91522202: {\"code\":400,\"message\":\"Unable to connect, no address known for peer\"}", "Unable to connect, no address known for peer")]
#[case("Error calling method FetchInvoice: RpcError { code: Some(1003), message: \"Failed: could not route or connect directly to 02ee337aec2b12fef609a57d1c32834fe3107d315acaf8f5206ccf94dc2a9baa8c: {\"code\":400,\"message\":\"Unable to connect, no address known for peer\"}\", data: None }", "Unable to connect, no address known for peer")]
#[case("Error calling method FetchInvoice: RpcError { code: Some(1003), message: \"Failed: could not route or connect directly to 02ee337aec2b12fef609a57d1c32834fe3107d315acaf8f5206ccf94dc2a9baa8c: {\\\"code\\\":400,\\\"message\\\":\\\"Unable to connect, no address known for peer\\\"}\", data: None }", "Unable to connect, no address known for peer")]
#[case("gRPC error", "gRPC error")]
#[case("", "The operation was cancelled")]
fn test_parse_error(#[case] msg: &str, #[case] expected: &str) {
let error = Cln::parse_error(tonic::Status::new(tonic::Code::Cancelled, msg));
assert_eq!(error.to_string(), expected);
}
}

0 comments on commit 8bc9fa9

Please sign in to comment.