breez_sdk_core/
support.rs

1use std::time::SystemTime;
2
3use crate::error::{SdkError, SdkResult};
4use crate::{HealthCheckStatus, NodeState, Payment, ServiceHealthCheckResponse, SupportAPI};
5
6use anyhow::anyhow;
7use chrono::{DateTime, Utc};
8use sdk_common::grpc::{BreezStatusRequest, ReportPaymentFailureRequest};
9use sdk_common::prelude::BreezServer;
10use sdk_common::with_connection_retry;
11use serde::{Deserialize, Serialize};
12
13#[derive(Serialize, Deserialize)]
14struct PaymentFailureReport {
15    pub node_state: NodeState,
16    pub payment: Payment,
17}
18
19impl TryFrom<i32> for HealthCheckStatus {
20    type Error = anyhow::Error;
21
22    fn try_from(value: i32) -> Result<Self, Self::Error> {
23        match value {
24            0 => Ok(HealthCheckStatus::Operational),
25            1 => Ok(HealthCheckStatus::Maintenance),
26            2 => Ok(HealthCheckStatus::ServiceDisruption),
27            _ => Err(anyhow!("illegal value")),
28        }
29    }
30}
31
32#[tonic::async_trait]
33impl SupportAPI for BreezServer {
34    async fn service_health_check(&self) -> SdkResult<ServiceHealthCheckResponse> {
35        let mut client = self.get_support_client().await?;
36
37        let request = BreezStatusRequest {};
38        let response = with_connection_retry!(client.breez_status(request.clone()))
39            .await
40            .map_err(|e| SdkError::ServiceConnectivity {
41                err: format!("(Breez) Fetch status failed: {e}"),
42            })?;
43        let status = response.into_inner().status.try_into()?;
44        Ok(ServiceHealthCheckResponse { status })
45    }
46
47    async fn report_payment_failure(
48        &self,
49        node_state: NodeState,
50        payment: Payment,
51        lsp_id: Option<String>,
52        comment: Option<String>,
53    ) -> SdkResult<()> {
54        let mut client = self.get_support_client().await?;
55
56        let timestamp: DateTime<Utc> = SystemTime::now().into();
57        let report = PaymentFailureReport {
58            node_state: node_state.clone(),
59            payment,
60        };
61
62        let request = ReportPaymentFailureRequest {
63            sdk_version: option_env!("CARGO_PKG_VERSION")
64                .unwrap_or_default()
65                .to_string(),
66            sdk_git_hash: option_env!("SDK_GIT_HASH").unwrap_or_default().to_string(),
67            node_id: node_state.id,
68            lsp_id: lsp_id.unwrap_or_default(),
69            timestamp: timestamp.to_rfc3339(),
70            comment: comment.unwrap_or_default(),
71            report: serde_json::to_string(&report)?,
72        };
73        _ = with_connection_retry!(client.report_payment_failure(request.clone()))
74            .await
75            .map_err(|e| SdkError::ServiceConnectivity {
76                err: format!("(Breez) Report payment failure failed: {e}"),
77            })?;
78        Ok(())
79    }
80}