1use std::collections::HashSet;
2use std::pin::Pin;
3
4use anyhow::Result;
5use serde_json::Value;
6use tokio::sync::{mpsc, watch};
7use tokio_stream::Stream;
8use tonic::Streaming;
9
10use sdk_common::prelude::*;
11
12use crate::{
13 bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey},
14 lightning_invoice::RawBolt11Invoice,
15 persist::error::PersistError,
16 CustomMessage, LnUrlAuthError, LspInformation, MaxChannelAmount, NodeCredentials, Payment,
17 PaymentResponse, PrepareRedeemOnchainFundsRequest, PrepareRedeemOnchainFundsResponse,
18 RouteHint, RouteHintHop, SyncResponse, TlvEntry,
19};
20
21pub type NodeResult<T, E = NodeError> = Result<T, E>;
22
23#[derive(Debug, thiserror::Error)]
24pub enum NodeError {
25 #[error("{0}")]
26 Credentials(String),
27
28 #[error("{0}")]
29 Generic(String),
30
31 #[error(transparent)]
32 InvalidInvoice(#[from] InvoiceError),
33
34 #[error("{0}")]
35 InvoiceExpired(String),
36
37 #[error("{0}")]
38 InvoiceNoDescription(String),
39
40 #[error("{0}")]
41 InvoicePreimageAlreadyExists(String),
42
43 #[error("{0}")]
44 PaymentFailed(String),
45
46 #[error("{0}")]
47 PaymentTimeout(String),
48
49 #[error(transparent)]
50 Persistance(#[from] PersistError),
51
52 #[error("{0}")]
53 RestoreOnly(String),
54
55 #[error("{0}")]
56 RouteTooExpensive(String),
57
58 #[error("{0}")]
59 RouteNotFound(String),
60
61 #[error("{0}")]
62 ServiceConnectivity(String),
63
64 #[error("{0}")]
65 InsufficientFunds(String),
66}
67
68impl NodeError {
69 pub(crate) fn credentials(err: &str) -> Self {
70 Self::Credentials(err.to_string())
71 }
72
73 pub(crate) fn generic(err: &str) -> Self {
74 Self::Generic(err.to_string())
75 }
76}
77
78impl From<NodeError> for sdk_common::prelude::LnUrlError {
79 fn from(value: NodeError) -> Self {
80 match value {
81 NodeError::InvalidInvoice(err) => Self::InvalidInvoice(format!("{err}")),
82 NodeError::ServiceConnectivity(err) => Self::ServiceConnectivity(err),
83 _ => Self::Generic(value.to_string()),
84 }
85 }
86}
87
88impl From<NodeError> for LnUrlAuthError {
89 fn from(value: NodeError) -> Self {
90 match value {
91 NodeError::ServiceConnectivity(err) => Self::ServiceConnectivity { err },
92 _ => Self::Generic {
93 err: value.to_string(),
94 },
95 }
96 }
97}
98
99pub struct CreateInvoiceRequest {
100 pub amount_msat: u64,
101 pub description: String,
102 pub payer_amount_msat: Option<u64>,
103 pub preimage: Option<Vec<u8>>,
104 pub use_description_hash: Option<bool>,
105 pub expiry: Option<u32>,
106 pub cltv: Option<u32>,
107}
108
109pub struct FetchBolt11Result {
110 pub bolt11: String,
111 pub payer_amount_msat: Option<u64>,
112}
113
114#[tonic::async_trait]
116pub trait NodeAPI: Send + Sync {
117 async fn node_credentials(&self) -> NodeResult<Option<NodeCredentials>>;
118 async fn configure_node(&self, close_to_address: Option<String>) -> NodeResult<()>;
119 async fn create_invoice(&self, request: CreateInvoiceRequest) -> NodeResult<String>;
120 async fn fetch_bolt11(&self, payment_hash: Vec<u8>) -> NodeResult<Option<FetchBolt11Result>>;
122 async fn pull_changed(
123 &self,
124 sync_state: Option<Value>,
125 match_local_balance: bool,
126 ) -> NodeResult<SyncResponse>;
127 async fn send_payment(
129 &self,
130 bolt11: String,
131 amount_msat: Option<u64>,
132 label: Option<String>,
133 ) -> NodeResult<Payment>;
134 async fn send_spontaneous_payment(
135 &self,
136 node_id: String,
137 amount_msat: u64,
138 extra_tlvs: Option<Vec<TlvEntry>>,
139 label: Option<String>,
140 ) -> NodeResult<Payment>;
141 async fn send_trampoline_payment(
142 &self,
143 bolt11: String,
144 amount_msat: u64,
145 label: Option<String>,
146 trampoline_node_id: Vec<u8>,
147 ) -> NodeResult<Payment>;
148 async fn node_id(&self) -> NodeResult<String>;
149
150 async fn send_pay(&self, bolt11: String, max_hops: u32) -> NodeResult<PaymentResponse>;
154
155 async fn max_sendable_amount(
157 &self,
158 payee_node_id: Option<Vec<u8>>,
159 max_hops: u32,
160 last_hop: Option<&RouteHintHop>,
161 ) -> NodeResult<Vec<MaxChannelAmount>>;
162 async fn redeem_onchain_funds(
163 &self,
164 to_address: String,
165 sat_per_vbyte: u32,
166 ) -> NodeResult<Vec<u8>>;
167 async fn prepare_redeem_onchain_funds(
168 &self,
169 req: PrepareRedeemOnchainFundsRequest,
170 ) -> NodeResult<PrepareRedeemOnchainFundsResponse>;
171 async fn start_signer(&self, shutdown: mpsc::Receiver<()>);
172 async fn start_keep_alive(&self, shutdown: watch::Receiver<()>);
173 async fn connect_peer(&self, node_id: String, addr: String) -> NodeResult<()>;
174 async fn sign_invoice(&self, invoice: RawBolt11Invoice) -> NodeResult<String>;
175 async fn close_peer_channels(&self, node_id: String) -> NodeResult<Vec<String>>;
176 async fn stream_incoming_payments(
177 &self,
178 ) -> NodeResult<Streaming<gl_client::signer::model::greenlight::IncomingPayment>>;
179 async fn stream_log_messages(
180 &self,
181 ) -> NodeResult<Streaming<gl_client::signer::model::greenlight::LogEntry>>;
182 async fn static_backup(&self) -> NodeResult<Vec<String>>;
183 async fn execute_command(&self, command: String) -> NodeResult<Value>;
184 async fn generate_diagnostic_data(&self) -> NodeResult<Value>;
185 async fn sign_message(&self, message: &str) -> NodeResult<String>;
186 async fn check_message(&self, message: &str, pubkey: &str, signature: &str)
187 -> NodeResult<bool>;
188 async fn send_custom_message(&self, message: CustomMessage) -> NodeResult<()>;
189 async fn stream_custom_messages(
190 &self,
191 ) -> NodeResult<Pin<Box<dyn Stream<Item = Result<CustomMessage>> + Send>>>;
192
193 async fn derive_bip32_key(&self, path: Vec<ChildNumber>) -> NodeResult<ExtendedPrivKey>;
195 async fn legacy_derive_bip32_key(&self, path: Vec<ChildNumber>) -> NodeResult<ExtendedPrivKey>;
196
197 async fn get_routing_hints(
200 &self,
201 lsp_info: &LspInformation,
202 ) -> NodeResult<(Vec<RouteHint>, bool)>;
203 async fn get_open_peers(&self) -> NodeResult<HashSet<Vec<u8>>>;
205}