breez_sdk_core/greenlight/
node_api.rs

1use std::cmp::{min, Reverse};
2use std::collections::{HashMap, HashSet};
3use std::iter::Iterator;
4use std::pin::Pin;
5use std::str::FromStr;
6use std::sync::atomic::{AtomicU16, Ordering};
7use std::sync::Arc;
8use std::time::{Duration, SystemTime, UNIX_EPOCH};
9
10use anyhow::{anyhow, Result};
11use ecies::symmetric::{sym_decrypt, sym_encrypt};
12use futures::{Future, Stream};
13use gl_client::credentials::{Device, Nobody};
14use gl_client::node;
15use gl_client::node::ClnClient;
16use gl_client::pb::cln::delinvoice_request::DelinvoiceStatus;
17use gl_client::pb::cln::listinvoices_invoices::ListinvoicesInvoicesStatus;
18use gl_client::pb::cln::listinvoices_request::ListinvoicesIndex;
19use gl_client::pb::cln::listpays_pays::ListpaysPaysStatus;
20use gl_client::pb::cln::listpeerchannels_channels::ListpeerchannelsChannelsState::*;
21use gl_client::pb::cln::listsendpays_request::ListsendpaysIndex;
22use gl_client::pb::cln::{
23    self, Amount, DelinvoiceRequest, GetrouteRequest, GetrouteRoute, ListchannelsRequest,
24    ListclosedchannelsClosedchannels, ListpaysPays, ListpeerchannelsChannels, ListsendpaysPayments,
25    PreapproveinvoiceRequest, SendpayRequest, SendpayRoute, WaitsendpayRequest,
26};
27use gl_client::pb::{OffChainPayment, TrampolinePayRequest};
28use gl_client::scheduler::Scheduler;
29use gl_client::signer::model::greenlight::{amount, scheduler};
30use gl_client::signer::Signer;
31use sdk_common::prelude::*;
32use serde::{Deserialize, Serialize};
33use serde_json::{json, Map, Value};
34use strum_macros::{Display, EnumString};
35use tokio::join;
36use tokio::sync::{mpsc, watch, Mutex};
37use tokio::time::{sleep, Instant, MissedTickBehavior};
38use tokio_stream::StreamExt;
39use tonic::Streaming;
40
41use crate::bitcoin::bech32::{u5, ToBase32};
42use crate::bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
43use crate::bitcoin::hashes::Hash;
44use crate::bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
45use crate::bitcoin::secp256k1::PublicKey;
46use crate::bitcoin::secp256k1::Secp256k1;
47use crate::bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey};
48use crate::bitcoin::{
49    Address, OutPoint, Script, Sequence, Transaction, TxIn, TxOut, Txid, Witness,
50};
51use crate::lightning::util::message_signing::verify;
52use crate::lightning_invoice::{RawBolt11Invoice, SignedRawBolt11Invoice};
53use crate::node_api::{CreateInvoiceRequest, FetchBolt11Result, NodeAPI, NodeError, NodeResult};
54use crate::persist::cache::NodeStateStorage;
55use crate::persist::db::SqliteStorage;
56use crate::persist::send_pays::{SendPay, SendPayStatus};
57use crate::{models::*, LspInformation};
58use crate::{NodeConfig, PrepareRedeemOnchainFundsRequest, PrepareRedeemOnchainFundsResponse};
59
60const MAX_PAYMENT_AMOUNT_MSAT: u64 = 4294967000;
61const MAX_INBOUND_LIQUIDITY_MSAT: u64 = 4000000000;
62const TRAMPOLINE_BASE_FEE_MSAT: u64 = 4000;
63const TRAMPOLINE_FEE_PPM: u64 = 5000;
64const PAYMENT_STATE_PENDING: u8 = 1;
65const PAYMENT_STATE_COMPLETE: u8 = 2;
66const PAYMENT_STATE_FAILED: u8 = 4;
67
68pub(crate) struct Greenlight {
69    sdk_config: Config,
70    signer: Mutex<Arc<Signer>>,
71    device: Device,
72    gl_client: Mutex<Option<node::Client>>,
73    node_client: Mutex<Option<ClnClient>>,
74    persister: Arc<SqliteStorage>,
75    inprogress_payments: AtomicU16,
76}
77
78#[derive(Serialize, Deserialize)]
79struct InvoiceLabel {
80    pub unix_milli: u128,
81    pub payer_amount_msat: Option<u64>,
82}
83
84#[derive(Serialize, Deserialize)]
85struct PaymentLabel {
86    pub unix_nano: u128,
87    pub trampoline: bool,
88    pub client_label: Option<String>,
89    pub amount_msat: u64,
90}
91
92impl Greenlight {
93    /// Connects to a live node using the provided seed and config.
94    /// If the node is not registered, it will try to recover it using the seed.
95    /// If the node is not created, it will register it using the provided partner credentials
96    /// or invite code
97    /// If the node is already registered and an existing credentials were found, it will try to
98    /// connect to the node using these credentials.
99    pub async fn connect(
100        config: Config,
101        seed: Vec<u8>,
102        restore_only: Option<bool>,
103        persister: Arc<SqliteStorage>,
104    ) -> NodeResult<Self> {
105        // Derive the encryption key from the seed
106        let temp_signer = Arc::new(Signer::new(
107            seed.clone(),
108            config.network.into(),
109            Nobody::new(),
110        )?);
111        let encryption_key = Self::derive_bip32_key(
112            config.network,
113            &temp_signer,
114            vec![ChildNumber::from_hardened_idx(140)?, ChildNumber::from(0)],
115        )?
116        .to_priv()
117        .to_bytes();
118        let encryption_key_slice = encryption_key.as_slice();
119
120        let register_credentials = match config.node_config.clone() {
121            NodeConfig::Greenlight { config } => config,
122        };
123
124        // Query for the existing credentials
125        let mut parsed_credentials =
126            Self::get_node_credentials(config.network, &temp_signer, persister.clone())?
127                .ok_or(NodeError::credentials("No credentials found"));
128        if parsed_credentials.is_err() {
129            info!("No credentials found, trying to recover existing node");
130            parsed_credentials = match Self::recover(config.network, seed.clone()).await {
131                Ok(creds) => Ok(creds),
132                Err(_) => {
133                    match restore_only.unwrap_or(false) {
134                        false => {
135                            // If we got here it means we failed to recover so we need to register a new node
136                            info!("Failed to recover node, registering new one");
137                            let credentials = Self::register(
138                                config.clone().network,
139                                seed.clone(),
140                                register_credentials.partner_credentials,
141                                register_credentials.invite_code,
142                            )
143                            .await?;
144                            Ok(credentials)
145                        }
146                        true => {
147                            return Err(NodeError::RestoreOnly("Node does not exist".to_string()));
148                        }
149                    }
150                }
151            }
152        }
153
154        // Persist the connection credentials for future use and return the node instance
155        match parsed_credentials {
156            Ok(creds) => {
157                let temp_scheduler = Scheduler::new(config.network.into(), creds.clone()).await?;
158                debug!("upgrading credentials");
159                let creds = creds.upgrade(&temp_scheduler, &temp_signer).await?;
160                debug!("upgrading credentials succeeded");
161                let encrypted_creds = sym_encrypt(encryption_key_slice, &creds.to_bytes());
162                match encrypted_creds {
163                    Some(c) => {
164                        persister.set_gl_credentials(c)?;
165                        Greenlight::new(config, seed, creds.clone(), persister)
166                    }
167                    None => Err(NodeError::generic("Failed to encrypt credentials")),
168                }
169            }
170            Err(_) => Err(NodeError::credentials("Failed to get gl credentials")),
171        }
172    }
173
174    fn new(
175        sdk_config: Config,
176        seed: Vec<u8>,
177        device: Device,
178        persister: Arc<SqliteStorage>,
179    ) -> NodeResult<Greenlight> {
180        let greenlight_network = sdk_config.network.into();
181        let signer = Signer::new(seed.clone(), greenlight_network, device.clone())?;
182        Ok(Greenlight {
183            sdk_config,
184            signer: Mutex::new(Arc::new(signer)),
185            device,
186            gl_client: Mutex::new(None),
187            node_client: Mutex::new(None),
188            persister,
189            inprogress_payments: AtomicU16::new(0),
190        })
191    }
192
193    async fn get_signer(&self) -> Arc<Signer> {
194        Arc::clone(&*self.signer.lock().await)
195    }
196
197    fn derive_bip32_key(
198        network: Network,
199        signer: &Arc<Signer>,
200        path: Vec<ChildNumber>,
201    ) -> NodeResult<ExtendedPrivKey> {
202        Ok(
203            ExtendedPrivKey::new_master(network.into(), &signer.bip32_ext_key())?
204                .derive_priv(&Secp256k1::new(), &path)?,
205        )
206    }
207
208    fn legacy_derive_bip32_key(
209        network: Network,
210        signer: &Arc<Signer>,
211        path: Vec<ChildNumber>,
212    ) -> NodeResult<ExtendedPrivKey> {
213        Ok(
214            ExtendedPrivKey::new_master(network.into(), &signer.legacy_bip32_ext_key())?
215                .derive_priv(&Secp256k1::new(), &path)?,
216        )
217    }
218
219    async fn register(
220        network: Network,
221        seed: Vec<u8>,
222        register_credentials: Option<GreenlightCredentials>,
223        invite_code: Option<String>,
224    ) -> Result<Device> {
225        if invite_code.is_some() && register_credentials.is_some() {
226            return Err(anyhow!("Cannot specify both invite code and credentials"));
227        }
228        let greenlight_network = network.into();
229        let creds = match register_credentials {
230            Some(creds) => {
231                debug!("registering with credentials");
232                Nobody {
233                    cert: creds.developer_cert,
234                    key: creds.developer_key,
235                    ..Default::default()
236                }
237            }
238            None => Nobody::new(),
239        };
240
241        let signer = Signer::new(seed, greenlight_network, creds.clone())?;
242        let scheduler = Scheduler::new(greenlight_network, creds).await?;
243
244        let register_res: scheduler::RegistrationResponse =
245            scheduler.register(&signer, invite_code).await?;
246
247        Ok(Device::from_bytes(register_res.creds))
248    }
249
250    async fn recover(network: Network, seed: Vec<u8>) -> Result<Device> {
251        let greenlight_network = network.into();
252        let credentials = Nobody::new();
253        let signer = Signer::new(seed, greenlight_network, credentials.clone())?;
254        let scheduler = Scheduler::new(greenlight_network, credentials).await?;
255        let recover_res: scheduler::RecoveryResponse = scheduler.recover(&signer).await?;
256
257        Ok(Device::from_bytes(recover_res.creds))
258    }
259
260    async fn get_client(&self) -> NodeResult<node::Client> {
261        let mut gl_client = self.gl_client.lock().await;
262        if gl_client.is_none() {
263            let scheduler = Scheduler::new(self.sdk_config.network.into(), self.device.clone())
264                .await
265                .map_err(|e| NodeError::ServiceConnectivity(e.to_string()))?;
266            *gl_client = Some(scheduler.node().await?);
267        }
268        Ok(gl_client.clone().unwrap())
269    }
270
271    pub(crate) async fn get_node_client(&self) -> NodeResult<node::ClnClient> {
272        let mut node_client = self.node_client.lock().await;
273        if node_client.is_none() {
274            let scheduler = Scheduler::new(self.sdk_config.network.into(), self.device.clone())
275                .await
276                .map_err(|e| NodeError::ServiceConnectivity(e.to_string()))?;
277            *node_client = Some(scheduler.node().await?);
278        }
279        Ok(node_client.clone().unwrap())
280    }
281
282    fn get_node_credentials(
283        network: Network,
284        signer: &Arc<Signer>,
285        persister: Arc<SqliteStorage>,
286    ) -> NodeResult<Option<Device>> {
287        // Derive the encryption key from the seed
288        let encryption_key = Self::derive_bip32_key(
289            network,
290            signer,
291            vec![ChildNumber::from_hardened_idx(140)?, ChildNumber::from(0)],
292        )?
293        .to_priv()
294        .to_bytes();
295        let encryption_key_slice = encryption_key.as_slice();
296
297        let legacy_encryption_key = Self::legacy_derive_bip32_key(
298            network,
299            signer,
300            vec![ChildNumber::from_hardened_idx(140)?, ChildNumber::from(0)],
301        )?
302        .to_priv()
303        .to_bytes();
304        let legacy_encryption_key_slice = legacy_encryption_key.as_slice();
305
306        match persister.get_gl_credentials()? {
307            Some(encrypted_creds) => {
308                let mut decrypted_credentials =
309                    sym_decrypt(encryption_key_slice, encrypted_creds.as_slice());
310                if decrypted_credentials.is_none() {
311                    info!("Failed to decrypt credentials, trying legacy key");
312                    decrypted_credentials =
313                        sym_decrypt(legacy_encryption_key_slice, encrypted_creds.as_slice());
314                }
315                match decrypted_credentials {
316                    Some(decrypted_creds) => {
317                        let credentials = Device::from_bytes(decrypted_creds.as_slice());
318                        if credentials.cert.is_empty() {
319                            Err(NodeError::credentials("Unable to parse credentials"))
320                        } else {
321                            Ok(Some(credentials))
322                        }
323                    }
324                    None => Err(NodeError::credentials(
325                        "Failed to decrypt credentials, seed doesn't match existing node",
326                    )),
327                }
328            }
329            None => Ok(None),
330        }
331    }
332
333    async fn fetch_outgoing_payment_with_retry(
334        client: node::ClnClient,
335        payment_hash: Vec<u8>,
336    ) -> Result<cln::ListpaysPays> {
337        let mut response = cln::ListpaysResponse::default();
338        let mut retry = 0;
339        let max_retries = 20;
340
341        while response.pays.is_empty() && retry < max_retries {
342            let req = cln::ListpaysRequest {
343                payment_hash: Some(payment_hash.clone()),
344                status: Some(cln::listpays_request::ListpaysStatus::Complete.into()),
345                ..cln::ListpaysRequest::default()
346            };
347            let mut client = client.clone();
348            response = with_connection_retry!(client.list_pays(req.clone()))
349                .await?
350                .into_inner();
351            if response.pays.is_empty() {
352                debug!("fetch outgoing payment failed, retrying in 100ms...");
353                sleep(Duration::from_millis(100)).await;
354            }
355            retry += 1;
356        }
357
358        // CLN also returns failed ListpaysPays along with the complete one
359        debug!("list_pays: {:?}", response.pays);
360        let pays: Vec<ListpaysPays> = response
361            .pays
362            .into_iter()
363            .filter(|pay| pay.status() == cln::listpays_pays::ListpaysPaysStatus::Complete)
364            .collect();
365
366        if pays.is_empty() {
367            return Err(anyhow!("Payment not found"));
368        }
369        Ok(pays[0].clone())
370    }
371
372    async fn fetch_channels_and_balance_with_retry(
373        cln_client: node::ClnClient,
374        persister: Arc<SqliteStorage>,
375        match_local_balance: bool,
376    ) -> NodeResult<(
377        Vec<cln::ListpeerchannelsChannels>,
378        Vec<cln::ListpeerchannelsChannels>,
379        Vec<String>,
380        u64,
381    )> {
382        let (mut all_channels, mut opened_channels, mut connected_peers, mut channels_balance) =
383            Greenlight::fetch_channels_and_balance(cln_client.clone()).await?;
384        if match_local_balance {
385            let node_state = persister.get_node_state()?;
386            if let Some(state) = node_state {
387                let mut retry_count = 0;
388                while state.channels_balance_msat != channels_balance && retry_count < 10 {
389                    warn!("balance matching local state is required and not yet satisfied, retrying in 100ms...");
390                    sleep(Duration::from_millis(100)).await;
391                    (
392                        all_channels,
393                        opened_channels,
394                        connected_peers,
395                        channels_balance,
396                    ) = Greenlight::fetch_channels_and_balance(cln_client.clone()).await?;
397                    retry_count += 1;
398                }
399            }
400        }
401        Ok((
402            all_channels,
403            opened_channels,
404            connected_peers,
405            channels_balance,
406        ))
407    }
408
409    async fn fetch_channels_and_balance(
410        mut client: node::ClnClient,
411    ) -> NodeResult<(
412        Vec<cln::ListpeerchannelsChannels>,
413        Vec<cln::ListpeerchannelsChannels>,
414        Vec<String>,
415        u64,
416    )> {
417        // list all channels
418        let req = cln::ListpeerchannelsRequest::default();
419        let peerchannels = with_connection_retry!(client.list_peer_channels(req.clone()))
420            .await?
421            .into_inner();
422
423        // filter only connected peers
424        let connected_peers: Vec<String> = peerchannels
425            .channels
426            .iter()
427            .filter(|channel| channel.peer_connected())
428            .filter_map(|channel| channel.peer_id.clone())
429            .map(hex::encode)
430            .collect::<HashSet<_>>()
431            .into_iter()
432            .collect();
433
434        // filter only opened channels
435        let opened_channels: Vec<cln::ListpeerchannelsChannels> = peerchannels
436            .channels
437            .iter()
438            .filter(|c| c.state() == ChanneldNormal)
439            .cloned()
440            .collect();
441
442        // calculate channels balance only from opened channels
443        let channels_balance = opened_channels
444            .iter()
445            .map(|c| Channel::from(c.clone()))
446            .map(|c| c.spendable_msat)
447            .sum::<u64>();
448        Ok((
449            peerchannels.channels,
450            opened_channels,
451            connected_peers,
452            channels_balance,
453        ))
454    }
455
456    async fn list_funds(&self) -> Result<cln::ListfundsResponse> {
457        let mut client = self.get_node_client().await?;
458        let req = cln::ListfundsRequest::default();
459        let funds: cln::ListfundsResponse = with_connection_retry!(client.list_funds(req.clone()))
460            .await?
461            .into_inner();
462        Ok(funds)
463    }
464
465    async fn on_chain_balance(&self, funds: &cln::ListfundsResponse) -> Result<u64> {
466        let on_chain_balance = funds.outputs.iter().fold(0, |a, b| {
467            if b.reserved {
468                return a;
469            }
470            a + b.amount_msat.clone().unwrap_or_default().msat
471        });
472        Ok(on_chain_balance)
473    }
474
475    async fn pending_onchain_balance(
476        &self,
477        peer_channels: &[cln::ListpeerchannelsChannels],
478    ) -> Result<u64> {
479        let pending_onchain_balance = peer_channels.iter().fold(0, |a, b| match b.state() {
480            ChanneldShuttingDown | ClosingdSigexchange | ClosingdComplete | AwaitingUnilateral
481            | FundingSpendSeen => a + b.to_us_msat.clone().unwrap_or_default().msat,
482
483            // When we  unilaterally close the channel it will get status as `AwaitingUnilateral`
484            // first, but when the closing transaction is confirmed onchain the funds receive status
485            // as `Onchain`. Though if we closed the channel we'll have to wait for the timelock to
486            // pass before the funds can be spent.
487            Onchain => {
488                if b.closer() == cln::ChannelSide::Local
489                    && b.status
490                        .last()
491                        .is_some_and(|status| status.contains("DELAYED_OUTPUT_TO_US"))
492                {
493                    a + b.to_us_msat.clone().unwrap_or_default().msat
494                } else {
495                    a
496                }
497            }
498            _ => a,
499        });
500        info!("pending_onchain_balance is {}", pending_onchain_balance);
501        Ok(pending_onchain_balance)
502    }
503
504    // Collect utxos from onchain funds
505    async fn utxos(&self, funds: cln::ListfundsResponse) -> Result<Vec<UnspentTransactionOutput>> {
506        let utxos: Vec<UnspentTransactionOutput> = funds
507            .outputs
508            .iter()
509            .map(|output| UnspentTransactionOutput {
510                txid: output.txid.clone(),
511                outnum: output.output,
512                amount_millisatoshi: output
513                    .amount_msat
514                    .as_ref()
515                    .map(|a| a.msat)
516                    .unwrap_or_default(),
517                address: output.address.clone().unwrap_or_default(),
518                reserved: output.reserved,
519            })
520            .collect();
521        Ok(utxos)
522    }
523
524    async fn build_payment_path(
525        &self,
526        route: &Vec<GetrouteRoute>,
527        first_edge: PaymentPathEdge,
528    ) -> NodeResult<PaymentPath> {
529        let client = self.get_node_client().await?;
530        let mut hops = vec![first_edge];
531
532        for hop in route {
533            let req = ListchannelsRequest {
534                short_channel_id: Some(hop.channel.clone()),
535                source: None,
536                destination: None,
537            };
538            let mut client = client.clone();
539            let hopchannels = with_connection_retry!(client.list_channels(req.clone()))
540                .await?
541                .into_inner()
542                .channels;
543
544            let first_channel = hopchannels.first().ok_or(NodeError::RouteNotFound(format!(
545                "Channel not found {}",
546                hop.channel.clone()
547            )))?;
548
549            info!("found channel in route: {:?}", first_channel);
550            hops.push(PaymentPathEdge {
551                base_fee_msat: first_channel.base_fee_millisatoshi as u64,
552                fee_per_millionth: first_channel.fee_per_millionth as u64,
553                node_id: hop.id.clone(),
554                short_channel_id: hop.channel.clone(),
555                channel_delay: first_channel.delay as u64,
556            });
557        }
558        Ok(PaymentPath { edges: hops })
559    }
560
561    async fn max_sendable_amount_from_peer(
562        &self,
563        via_peer_id: Vec<u8>,
564        via_peer_channels: Vec<ListpeerchannelsChannels>,
565        payee_node_id: Option<Vec<u8>>,
566        max_hops: u32,
567        last_hop_hint: Option<&RouteHintHop>,
568    ) -> NodeResult<Vec<MaxChannelAmount>> {
569        let mut client = self.get_node_client().await?;
570
571        // Consider the hints as part of the route. If there is a routing hint we will
572        // attempt to calculate the path until the last hop in the hint and then add
573        // the last hop to the path.
574        let (last_node, max_hops) = match last_hop_hint {
575            Some(hop) => (hex::decode(&hop.src_node_id)?, max_hops - 1),
576            None => match payee_node_id.clone() {
577                Some(node_id) => (node_id, max_hops),
578                None => {
579                    return Err(NodeError::RouteNotFound(
580                        "No payee node id or last hop hints provided, cannot calculate max amount"
581                            .to_string(),
582                    ));
583                }
584            },
585        };
586
587        // fetch a route from greenlight
588        info!(
589            "calling get_route for peer {} to node {}, max_hops: {}",
590            hex::encode(via_peer_id.clone()),
591            hex::encode(last_node.clone()),
592            max_hops - 1
593        );
594        let req = GetrouteRequest {
595            id: last_node.clone(),
596            amount_msat: Some(Amount { msat: 0 }),
597            riskfactor: 0,
598            cltv: None,
599            fromid: Some(via_peer_id.clone()),
600            fuzzpercent: Some(0),
601            exclude: vec![],
602            // we deduct the first hop that we calculate manually
603            maxhops: Some(max_hops - 1),
604        };
605        let route_result = with_connection_retry!(client.get_route(req.clone())).await;
606
607        // In case we have no route better to return no amounts for this peer's channels.
608        if let Err(e) = route_result {
609            error!(
610                "Failed to get route for peer {}: {}",
611                hex::encode(via_peer_id.clone()),
612                e
613            );
614            return Ok(vec![]);
615        }
616
617        let route_response = route_result?.into_inner();
618        info!(
619            "max_sendable_amount: route response = {:?}",
620            route_response
621                .route
622                .iter()
623                .map(|r| format!(
624                    "{{node_id: {}, channel: {}}}",
625                    hex::encode(&r.id),
626                    r.channel
627                ))
628                .collect::<Vec<_>>()
629        );
630
631        // We fetch the opened channels so can calculate max amount to send for each channel
632        let opened_channels: Vec<cln::ListpeerchannelsChannels> = via_peer_channels
633            .iter()
634            .filter(|c| c.state() == ChanneldNormal)
635            .cloned()
636            .collect();
637
638        let mut max_per_channel = vec![];
639        for c in opened_channels {
640            let chan_id = c
641                .clone()
642                .channel_id
643                .ok_or(NodeError::generic("Empty channel id"))?;
644
645            // First hop is forwarding so no fees and delays.
646            let first_edge = PaymentPathEdge {
647                base_fee_msat: 0,
648                fee_per_millionth: 0,
649                node_id: via_peer_id.clone(),
650                short_channel_id: c.clone().short_channel_id.unwrap_or_default(),
651                channel_delay: 0,
652            };
653
654            // convert the route to a payment path so we can calculate the amount to forward for each hop
655            let mut payment_path = self
656                .build_payment_path(&route_response.route, first_edge)
657                .await?;
658
659            // Add the last hop hints (if any) to the route
660            if let Some(hint) = last_hop_hint {
661                payment_path.edges.extend(vec![PaymentPathEdge {
662                    base_fee_msat: hint.fees_base_msat as u64,
663                    fee_per_millionth: hint.fees_proportional_millionths as u64,
664                    node_id: payee_node_id.clone().unwrap_or_default(),
665                    short_channel_id: hint.short_channel_id.clone(),
666                    channel_delay: hint.cltv_expiry_delta,
667                }])
668            }
669
670            info!(
671                "max_sendable_amount: route_hops = {:?}",
672                payment_path
673                    .edges
674                    .iter()
675                    .map(|e| format!(
676                        "{{node_id: {}, channel: {}}}",
677                        hex::encode(&e.node_id),
678                        e.short_channel_id
679                    ))
680                    .collect::<Vec<_>>()
681            );
682
683            // go over each hop and calculate the amount to forward.
684            let max_payment_amount =
685                payment_path.final_hop_amount(c.clone().spendable_msat.unwrap_or_default().msat);
686            max_per_channel.push(MaxChannelAmount {
687                channel_id: hex::encode(chan_id),
688                amount_msat: max_payment_amount,
689                path: payment_path,
690            });
691        }
692
693        Ok(max_per_channel)
694    }
695
696    /// Get open peer channels (private and public) as raw protobuf structs, indexed by peer pubkey
697    async fn get_open_peer_channels_pb(
698        &self,
699    ) -> NodeResult<HashMap<Vec<u8>, cln::ListpeerchannelsChannels>> {
700        let mut client = self.get_node_client().await?;
701        // Get the peer channels
702        let req = cln::ListpeerchannelsRequest::default();
703        let peer_channels = with_connection_retry!(client.list_peer_channels(req.clone()))
704            .await?
705            .into_inner();
706
707        let open_peer_channels: HashMap<Vec<u8>, cln::ListpeerchannelsChannels> = peer_channels
708            .channels
709            .into_iter()
710            .filter(|c| {
711                c.state == Some(cln::ChannelState::ChanneldNormal as i32) && c.peer_id.is_some()
712            })
713            .map(|c| (c.peer_id.clone().unwrap(), c))
714            .collect();
715        Ok(open_peer_channels)
716    }
717
718    async fn with_keep_alive<T, F>(&self, f: F) -> T
719    where
720        F: Future<Output = T>,
721    {
722        _ = self.inprogress_payments.fetch_add(1, Ordering::Relaxed);
723        let res = f.await;
724        _ = self.inprogress_payments.fetch_sub(1, Ordering::Relaxed);
725        res
726    }
727
728    // pulls transactions from greenlight based on last sync timestamp.
729    // greenlight gives us the payments via API and for received payments we are looking for settled invoices.
730    async fn pull_transactions(
731        &self,
732        sync_state: &SyncState,
733        htlc_list: Vec<Htlc>,
734    ) -> NodeResult<(SyncState, Vec<Payment>)> {
735        let (receive_payments_res, send_payments_res) = join!(
736            self.pull_receive_payments(&sync_state.list_invoices_index),
737            self.pull_send_payments(&sync_state.send_pays_index, htlc_list),
738        );
739
740        let (receive_payments, list_invoices_index) = receive_payments_res?;
741        let (send_payments, send_pays_index) = send_payments_res?;
742        let mut new_state = sync_state.clone();
743        new_state.list_invoices_index = list_invoices_index;
744        new_state.send_pays_index = send_pays_index;
745
746        let mut payments: Vec<Payment> = Vec::new();
747        payments.extend(receive_payments);
748        payments.extend(send_payments);
749
750        Ok((new_state, payments))
751    }
752
753    async fn pull_receive_payments(
754        &self,
755        state: &SyncIndex,
756    ) -> NodeResult<(Vec<Payment>, SyncIndex)> {
757        let mut client = self.get_node_client().await?;
758
759        let req = cln::ListinvoicesRequest {
760            index: Some(ListinvoicesIndex::Created.into()),
761            start: Some(state.created),
762            ..Default::default()
763        };
764        let mut clone = client.clone();
765        let created_invoices = with_connection_retry!(clone.list_invoices(req.clone()))
766            .await?
767            .into_inner();
768        let req = cln::ListinvoicesRequest {
769            index: Some(ListinvoicesIndex::Updated.into()),
770            start: Some(state.updated),
771            ..Default::default()
772        };
773
774        let updated_invoices = with_connection_retry!(client.list_invoices(req.clone()))
775            .await?
776            .into_inner();
777        let mut new_state = state.clone();
778        if let Some(last) = created_invoices.invoices.last() {
779            new_state.created = last.created_index()
780        }
781        if let Some(last) = updated_invoices.invoices.last() {
782            new_state.updated = last.updated_index()
783        }
784
785        let received_payments: NodeResult<Vec<Payment>> = created_invoices
786            .invoices
787            .into_iter()
788            .chain(updated_invoices.invoices.into_iter())
789            .filter(|i| i.status() == ListinvoicesInvoicesStatus::Paid)
790            .map(TryInto::try_into)
791            .collect();
792
793        Ok((received_payments?, new_state))
794    }
795
796    async fn pull_send_payments(
797        &self,
798        state: &SyncIndex,
799        htlc_list: Vec<Htlc>,
800    ) -> NodeResult<(Vec<Payment>, SyncIndex)> {
801        let mut client = self.get_node_client().await?;
802        let req = cln::ListsendpaysRequest {
803            index: Some(ListsendpaysIndex::Created.into()),
804            start: Some(state.created),
805            ..Default::default()
806        };
807        let mut clone = client.clone();
808        let created_send_pays = with_connection_retry!(clone.list_send_pays(req.clone()))
809            .await?
810            .into_inner();
811        let req = cln::ListsendpaysRequest {
812            index: Some(ListsendpaysIndex::Updated.into()),
813            start: Some(state.updated),
814            ..Default::default()
815        };
816        let updated_send_pays = with_connection_retry!(client.list_send_pays(req.clone()))
817            .await?
818            .into_inner();
819
820        let mut new_state = state.clone();
821        if let Some(last) = created_send_pays.payments.last() {
822            new_state.created = last.created_index()
823        }
824        if let Some(last) = updated_send_pays.payments.last() {
825            new_state.updated = last.updated_index()
826        }
827
828        let hash_groups: HashMap<_, _> = created_send_pays
829            .payments
830            .iter()
831            .chain(updated_send_pays.payments.iter())
832            .map(|p| {
833                let mut key = hex::encode(&p.payment_hash);
834                key.push('|');
835                key.push_str(&p.groupid.to_string());
836                (key, (p.payment_hash.clone(), p.groupid.to_string()))
837            })
838            .collect();
839        let hash_group_values: Vec<_> = hash_groups.values().cloned().collect();
840
841        self.persister.insert_send_pays(
842            &created_send_pays
843                .payments
844                .into_iter()
845                .map(TryInto::try_into)
846                .collect::<Result<Vec<_>, _>>()?,
847        )?;
848        self.persister.insert_send_pays(
849            &updated_send_pays
850                .payments
851                .into_iter()
852                .map(TryInto::try_into)
853                .collect::<Result<Vec<_>, _>>()?,
854        )?;
855
856        // Now all new send_pays are persisted. Retrieve the send_pays for the
857        // payment hashes, to ensure any send_pays belonging to the same payment
858        // that were not fetched in this round are also included.
859        let send_pays = self.persister.list_send_pays(&hash_group_values)?;
860
861        // Now that all send_pays belonging to all payments are here, aggregate
862        // the send_pays into payments. This is a copy of what core lightning's
863        // listpays function does under the hood.
864        let mut outbound_payments: HashMap<String, SendPayAgg> = HashMap::new();
865        for send_pay in send_pays {
866            let mut key = hex::encode(&send_pay.payment_hash);
867            key.push('|');
868            key.push_str(&send_pay.groupid);
869            let payment = outbound_payments.entry(key).or_insert(SendPayAgg {
870                state: 0,
871                created_at: send_pay.created_at,
872                payment_hash: send_pay.payment_hash,
873                bolt11: None,
874                destination: None,
875                label: None,
876                description: None,
877                preimage: None,
878                amount_sent: 0,
879                amount: Some(0),
880                num_nonfailed_parts: 0,
881            });
882            if payment.bolt11.is_none() {
883                payment.bolt11 = send_pay.bolt11;
884            }
885            if payment.destination.is_none() {
886                payment.destination = send_pay.destination;
887            }
888            if payment.description.is_none() {
889                payment.description = send_pay.description;
890            }
891            if payment.label.is_none() {
892                payment.label = send_pay.label;
893            }
894            if payment.preimage.is_none() {
895                payment.preimage = send_pay.payment_preimage;
896            }
897            if send_pay.created_at < payment.created_at {
898                payment.created_at = send_pay.created_at;
899            }
900
901            match send_pay.status {
902                SendPayStatus::Pending => {
903                    add_amount_sent(payment, send_pay.amount_sent_msat, send_pay.amount_msat);
904                    payment.num_nonfailed_parts += 1;
905                    payment.state |= PAYMENT_STATE_PENDING;
906                }
907                SendPayStatus::Failed => {
908                    payment.state |= PAYMENT_STATE_FAILED;
909                }
910                SendPayStatus::Complete => {
911                    add_amount_sent(payment, send_pay.amount_sent_msat, send_pay.amount_msat);
912                    payment.num_nonfailed_parts += 1;
913                    payment.state |= PAYMENT_STATE_COMPLETE;
914                }
915            }
916        }
917
918        let outbound_payments: Vec<Payment> = outbound_payments
919            .into_values()
920            .map(TryInto::try_into)
921            .collect::<Result<Vec<_>, _>>()?;
922        let outbound_payments = update_payment_expirations(outbound_payments, htlc_list)?;
923        Ok((outbound_payments, new_state))
924    }
925
926    async fn wait_channel_reestablished(&self, path: &PaymentPath) -> NodeResult<()> {
927        let deadline =
928            Instant::now()
929                .checked_add(Duration::from_secs(20))
930                .ok_or(NodeError::generic(
931                    "Failed to set channel establishment deadline",
932                ))?;
933
934        while Instant::now().le(&deadline) && !self.poll_channel_reestablished(path).await? {
935            tokio::time::sleep(Duration::from_millis(50)).await
936        }
937
938        Ok(())
939    }
940
941    async fn poll_channel_reestablished(&self, path: &PaymentPath) -> NodeResult<bool> {
942        let edge = match path.edges.first() {
943            Some(edge) => edge,
944            None => return Err(NodeError::generic("Channel not found")),
945        };
946        let mut client = self.get_node_client().await?;
947        let req = cln::ListpeerchannelsRequest {
948            id: Some(edge.node_id.clone()),
949        };
950        let res = with_connection_retry!(client.list_peer_channels(req.clone()))
951            .await?
952            .into_inner();
953        let channel = match res.channels.iter().find(|c| {
954            match (
955                c.alias.as_ref().and_then(|a| a.local.as_ref()),
956                c.short_channel_id.as_ref(),
957            ) {
958                (Some(alias), Some(short_channel_id)) => {
959                    *alias == edge.short_channel_id || *short_channel_id == edge.short_channel_id
960                }
961                (Some(alias), None) => *alias == edge.short_channel_id,
962                (None, Some(short_channel_id)) => *short_channel_id == edge.short_channel_id,
963                (None, None) => false,
964            }
965        }) {
966            Some(channel) => channel,
967            None => return Err(NodeError::generic("Channel not found")),
968        };
969
970        if let Some(peer_connected) = channel.peer_connected {
971            if !peer_connected {
972                return Ok(false);
973            }
974        }
975
976        if !channel
977            .status
978            .iter()
979            .any(|s| s.contains("Channel ready") || s.contains("Reconnected, and reestablished"))
980        {
981            return Ok(false);
982        }
983
984        Ok(true)
985    }
986}
987
988fn add_amount_sent(
989    agg: &mut SendPayAgg,
990    send_pay_amount_sent_msat: Option<u64>,
991    send_pay_amount_msat: Option<u64>,
992) {
993    if let Some(amount_sent_msat) = send_pay_amount_sent_msat {
994        agg.amount_sent += amount_sent_msat;
995    }
996
997    let amount_msat = match send_pay_amount_msat {
998        Some(amount_msat) => amount_msat,
999        None => {
1000            agg.amount = None;
1001            return;
1002        }
1003    };
1004
1005    if let Some(amount) = agg.amount {
1006        agg.amount = Some(amount + amount_msat);
1007    }
1008}
1009
1010#[derive(Clone, Debug, Default, Deserialize, Serialize)]
1011struct SyncIndex {
1012    pub created: u64,
1013    pub updated: u64,
1014}
1015
1016#[derive(Clone, Debug, Default, Deserialize, Serialize)]
1017struct SyncState {
1018    pub send_pays_index: SyncIndex,
1019    pub list_invoices_index: SyncIndex,
1020}
1021
1022#[tonic::async_trait]
1023impl NodeAPI for Greenlight {
1024    async fn node_credentials(&self) -> NodeResult<Option<NodeCredentials>> {
1025        Ok(Self::get_node_credentials(
1026            self.sdk_config.network,
1027            &self.get_signer().await,
1028            self.persister.clone(),
1029        )?
1030        .map(|credentials| NodeCredentials::Greenlight {
1031            credentials: GreenlightDeviceCredentials {
1032                device: credentials.to_bytes(),
1033            },
1034        }))
1035    }
1036
1037    async fn configure_node(&self, close_to_address: Option<String>) -> NodeResult<()> {
1038        match close_to_address {
1039            Some(close_to_addr) => {
1040                let mut client = self.get_client().await?;
1041                let req = gl_client::pb::GlConfig { close_to_addr };
1042                with_connection_retry!(client.configure(req.clone()))
1043                    .await
1044                    .map_err(|e| NodeError::Generic(format!("Unable to set node config: {e}")))?;
1045            }
1046            None => {
1047                let mut client = self.get_node_client().await?;
1048                let req = cln::DeldatastoreRequest {
1049                    key: vec!["glconf".to_string(), "request".to_string()],
1050                    generation: None,
1051                };
1052                with_connection_retry!(client.del_datastore(req.clone()))
1053                    .await
1054                    .map_err(|e| {
1055                        NodeError::Generic(format!("Unable to delete node config: {e}"))
1056                    })?;
1057            }
1058        }
1059        Ok(())
1060    }
1061
1062    async fn create_invoice(&self, request: CreateInvoiceRequest) -> NodeResult<String> {
1063        let mut client = self.get_node_client().await?;
1064        let label = serde_json::to_string(&InvoiceLabel {
1065            unix_milli: SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis(),
1066            payer_amount_msat: request.payer_amount_msat,
1067        })?;
1068        let cln_request = cln::InvoiceRequest {
1069            amount_msat: Some(cln::AmountOrAny {
1070                value: Some(cln::amount_or_any::Value::Amount(cln::Amount {
1071                    msat: request.amount_msat,
1072                })),
1073            }),
1074            label,
1075            description: request.description,
1076            preimage: request.preimage,
1077            deschashonly: request.use_description_hash,
1078            expiry: request.expiry.map(|e| e as u64),
1079            fallbacks: vec![],
1080            cltv: request.cltv,
1081        };
1082
1083        let res = with_connection_retry!(client.invoice(cln_request.clone()))
1084            .await?
1085            .into_inner();
1086        Ok(res.bolt11)
1087    }
1088
1089    async fn delete_invoice(&self, bolt11: String) -> NodeResult<()> {
1090        let mut client = self.get_node_client().await?;
1091        let invoice_request = cln::ListinvoicesRequest {
1092            invstring: Some(bolt11),
1093            ..Default::default()
1094        };
1095        let invoice_result = with_connection_retry!(client.list_invoices(invoice_request.clone()))
1096            .await?
1097            .into_inner();
1098        let invoice_result = invoice_result.invoices.first();
1099        let result = match invoice_result {
1100            Some(result) => result,
1101            None => return Ok(()),
1102        };
1103
1104        let status = match result.status() {
1105            ListinvoicesInvoicesStatus::Unpaid => DelinvoiceStatus::Unpaid,
1106            ListinvoicesInvoicesStatus::Paid => return Err(NodeError::InvoiceAlreadyPaid),
1107            ListinvoicesInvoicesStatus::Expired => DelinvoiceStatus::Expired,
1108        };
1109        with_connection_retry!(client.del_invoice(DelinvoiceRequest {
1110            label: result.label.clone(),
1111            status: status.into(),
1112            desconly: Some(false),
1113        }))
1114        .await?;
1115        Ok(())
1116    }
1117
1118    async fn fetch_bolt11(&self, payment_hash: Vec<u8>) -> NodeResult<Option<FetchBolt11Result>> {
1119        let mut client = self.get_node_client().await?;
1120        let request = cln::ListinvoicesRequest {
1121            payment_hash: Some(payment_hash),
1122            ..Default::default()
1123        };
1124
1125        let result = with_connection_retry!(client.list_invoices(request.clone()))
1126            .await?
1127            .into_inner()
1128            .invoices
1129            .first()
1130            .cloned()
1131            .and_then(|invoice| {
1132                invoice.bolt11.map(|bolt11| FetchBolt11Result {
1133                    bolt11,
1134                    payer_amount_msat: serde_json::from_str::<InvoiceLabel>(&invoice.label)
1135                        .map(|label| label.payer_amount_msat)
1136                        .ok()
1137                        .flatten(),
1138                })
1139            });
1140
1141        Ok(result)
1142    }
1143
1144    // implement pull changes from greenlight
1145    async fn pull_changed(
1146        &self,
1147        sync_state: Option<Value>,
1148        match_local_balance: bool,
1149    ) -> NodeResult<SyncResponse> {
1150        let sync_state: SyncState = match sync_state {
1151            Some(sync_state) => serde_json::from_value(sync_state)?,
1152            None => SyncState::default(),
1153        };
1154
1155        let client = self.get_node_client().await?;
1156
1157        // get node info
1158        let mut client_clone1 = client.clone();
1159        let node_info_future =
1160            with_connection_retry!(client_clone1.getinfo(cln::GetinfoRequest::default()));
1161
1162        // list both off chain funds and on chain fudns
1163        let funds_future = self.list_funds();
1164
1165        // Fetch closed channels from greenlight
1166        let mut client_clone2 = client.clone();
1167        let closed_channels_future = with_connection_retry!(
1168            client_clone2.list_closed_channels(cln::ListclosedchannelsRequest { id: None })
1169        );
1170
1171        // calculate the node new balance and in case the caller signals balance has changed
1172        // keep polling until the balance is updated
1173        let balance_future = Greenlight::fetch_channels_and_balance_with_retry(
1174            client.clone(),
1175            self.persister.clone(),
1176            match_local_balance,
1177        );
1178
1179        let (node_info_res, funds_res, closed_channels_res, balance_res) = tokio::join!(
1180            node_info_future,
1181            funds_future,
1182            closed_channels_future,
1183            balance_future
1184        );
1185
1186        let node_info = node_info_res?.into_inner();
1187        let funds = funds_res?;
1188        let closed_channels = closed_channels_res?.into_inner().closedchannels;
1189        let (all_channels, opened_channels, connected_peers, channels_balance) = balance_res?;
1190        let forgotten_closed_channels: NodeResult<Vec<Channel>> = closed_channels
1191            .into_iter()
1192            .filter(|cc| {
1193                all_channels
1194                    .iter()
1195                    .all(|ac| ac.funding_txid != Some(cc.funding_txid.clone()))
1196            })
1197            .map(TryInto::try_into)
1198            .collect();
1199        info!("forgotten_closed_channels {:?}", forgotten_closed_channels);
1200
1201        let mut all_channel_models: Vec<Channel> =
1202            all_channels.clone().into_iter().map(|c| c.into()).collect();
1203        all_channel_models.extend(forgotten_closed_channels?);
1204
1205        // calculate onchain balance
1206        let onchain_balance = self.on_chain_balance(&funds).await?;
1207        let pending_onchain_balance = self.pending_onchain_balance(&all_channels).await?;
1208        let utxos: Vec<UnspentTransactionOutput> = self.utxos(funds).await?;
1209
1210        // calculate payment limits and inbound liquidity
1211        let mut max_payable: u64 = 0;
1212        let mut max_receivable_single_channel: u64 = 0;
1213        let mut total_inbound_liquidity_msats: u64 = 0;
1214        opened_channels.iter().try_for_each(|c| -> Result<()> {
1215            max_payable += c
1216                .spendable_msat
1217                .as_ref()
1218                .map(|a| a.msat)
1219                .unwrap_or_default();
1220            let receivable_amount = c
1221                .receivable_msat
1222                .as_ref()
1223                .map(|a| a.msat)
1224                .unwrap_or_default();
1225            total_inbound_liquidity_msats += receivable_amount;
1226            if receivable_amount > max_receivable_single_channel {
1227                max_receivable_single_channel = receivable_amount;
1228            }
1229            Ok(())
1230        })?;
1231
1232        let max_allowed_to_receive_msats =
1233            MAX_INBOUND_LIQUIDITY_MSAT.saturating_sub(channels_balance);
1234        let node_pubkey = hex::encode(node_info.id);
1235        // construct the node state
1236        let node_state = NodeState {
1237            id: node_pubkey.clone(),
1238            block_height: node_info.blockheight,
1239            channels_balance_msat: channels_balance,
1240            onchain_balance_msat: onchain_balance,
1241            pending_onchain_balance_msat: pending_onchain_balance,
1242            utxos,
1243            max_payable_msat: max_payable,
1244            max_receivable_msat: max_allowed_to_receive_msats,
1245            max_single_payment_amount_msat: MAX_PAYMENT_AMOUNT_MSAT,
1246            max_chan_reserve_msats: channels_balance - min(max_payable, channels_balance),
1247            connected_peers,
1248            max_receivable_single_payment_amount_msat: max_receivable_single_channel,
1249            total_inbound_liquidity_msats,
1250        };
1251        let mut htlc_list: Vec<Htlc> = Vec::new();
1252        for channel in all_channel_models.clone() {
1253            htlc_list.extend(channel.htlcs);
1254        }
1255
1256        let (new_sync_state, payments) = self.pull_transactions(&sync_state, htlc_list).await?;
1257
1258        Ok(SyncResponse {
1259            sync_state: serde_json::to_value(new_sync_state)?,
1260            node_state,
1261            payments,
1262            channels: all_channel_models,
1263        })
1264    }
1265
1266    async fn send_pay(&self, bolt11: String, max_hops: u32) -> NodeResult<PaymentResponse> {
1267        let invoice = parse_invoice(&bolt11)?;
1268        let last_hop = invoice.routing_hints.first().and_then(|rh| rh.hops.first());
1269        let mut client = self.get_node_client().await?;
1270
1271        // Valid the invoice network against the config network
1272        validate_network(invoice.clone(), self.sdk_config.network)?;
1273
1274        // We first calculate for each channel the max amount to pay (at the receiver)
1275        let mut max_amount_per_channel = self
1276            .max_sendable_amount(Some(hex::decode(invoice.payee_pubkey)?), max_hops, last_hop)
1277            .await?;
1278        info!("send_pay: routes: {:?}", max_amount_per_channel);
1279
1280        // Calculate the total amount to pay
1281        let total_msat: u64 = max_amount_per_channel.iter().map(|m| m.amount_msat).sum();
1282
1283        // Sort the channels by max amount descending so we can build the route in a way that it
1284        // drains the largest channels first
1285        max_amount_per_channel.sort_by_key(|m| Reverse(m.amount_msat));
1286
1287        let amount_to_pay_msat = match invoice.amount_msat {
1288            Some(amount) => Ok(amount),
1289            None => Err(NodeError::generic("Invoice has no amount")),
1290        }?;
1291
1292        if amount_to_pay_msat > total_msat {
1293            return Err(NodeError::RouteNotFound(format!(
1294                "Amount too high, max amount is {total_msat} msat"
1295            )));
1296        }
1297
1298        // This is needed in greenlight for the signer to recognize this invoice.
1299        client
1300            .pre_approve_invoice(PreapproveinvoiceRequest {
1301                bolt11: Some(bolt11.clone()),
1302            })
1303            .await?;
1304
1305        // We need to allocate a part id for each part that we are sending.
1306        let mut part_id = 1;
1307        // The total amount we sent. i.e. what the recipient received + fees
1308        let mut amount_sent_msat = 0;
1309        // The total amount received by the recipient
1310        let mut amount_received_msat = 0;
1311        // Generate a random group_id for the payment
1312        let group_id = rand::random::<u64>();
1313
1314        // The algorithm goes over each channel and drains it until the received amount
1315        // equals to the amount to pay defined in the bolt11 invoice.
1316        for max in max_amount_per_channel {
1317            // calculating the incoming amount for the remaining amount to pay.
1318            let left_to_pay_msat = amount_to_pay_msat - amount_received_msat;
1319            // Whether we draining the whole channel balance or only what is left to pay
1320            let to_pay_msat = std::cmp::min(left_to_pay_msat, max.amount_msat);
1321
1322            // We convert our payment path to an actual route that can be sent to the node.
1323            // This requires calculating the right fees and cltv delta in each hop.
1324            let (route, sent_msat) = convert_to_send_pay_route(
1325                max.path.clone(),
1326                to_pay_msat,
1327                invoice.min_final_cltv_expiry_delta,
1328            );
1329            info!(
1330                "send_pay route to pay: {:?}, received_amount = {}",
1331                route, to_pay_msat
1332            );
1333            self.wait_channel_reestablished(&max.path).await?;
1334            // We send the part using the node API
1335            let req = SendpayRequest {
1336                route,
1337                payment_hash: hex::decode(invoice.payment_hash.clone())?,
1338                label: None,
1339                amount_msat: Some(Amount {
1340                    msat: amount_to_pay_msat,
1341                }),
1342                bolt11: Some(bolt11.clone()),
1343                payment_secret: Some(invoice.payment_secret.clone()),
1344                partid: Some(part_id),
1345                localinvreqid: None,
1346                groupid: Some(group_id),
1347            };
1348            let mut client = client.clone();
1349            with_connection_retry!(client.send_pay(req.clone())).await?;
1350            part_id += 1;
1351            amount_sent_msat += sent_msat;
1352            amount_received_msat += to_pay_msat;
1353            if amount_received_msat == amount_to_pay_msat {
1354                break;
1355            }
1356        }
1357
1358        // Now we wait for the first part to be completed as a way to wait for the payment
1359        // to complete.
1360        let req = WaitsendpayRequest {
1361            payment_hash: hex::decode(invoice.payment_hash.clone())?,
1362            partid: Some(1),
1363            timeout: Some(self.sdk_config.payment_timeout_sec),
1364            groupid: Some(group_id),
1365        };
1366        let response = self
1367            .with_keep_alive(with_connection_retry!(client.wait_send_pay(req.clone())))
1368            .await?
1369            .into_inner();
1370        Ok(PaymentResponse {
1371            payment_time: response.completed_at.unwrap_or(response.created_at as f64) as i64,
1372            amount_msat: amount_received_msat,
1373            fee_msat: amount_sent_msat - amount_received_msat,
1374            payment_hash: invoice.payment_hash,
1375            payment_preimage: hex::encode(response.payment_preimage.unwrap_or_default()),
1376        })
1377    }
1378
1379    async fn send_payment(
1380        &self,
1381        bolt11: String,
1382        amount_msat: Option<u64>,
1383        label: Option<String>,
1384    ) -> NodeResult<Payment> {
1385        let mut description = None;
1386        if !bolt11.is_empty() {
1387            let invoice = parse_invoice(&bolt11)?;
1388            validate_network(invoice.clone(), self.sdk_config.network)?;
1389            description = invoice.description;
1390        }
1391
1392        let mut client = self.get_node_client().await?;
1393        let request = cln::PayRequest {
1394            bolt11,
1395            amount_msat: amount_msat.map(|amt| cln::Amount { msat: amt }),
1396            maxfeepercent: Some(self.sdk_config.maxfee_percent),
1397            retry_for: Some(self.sdk_config.payment_timeout_sec),
1398            label,
1399            maxdelay: None,
1400            riskfactor: None,
1401            localinvreqid: None,
1402            exclude: vec![],
1403            maxfee: None,
1404            description,
1405            exemptfee: Some(cln::Amount {
1406                msat: self.sdk_config.exemptfee_msat,
1407            }),
1408        };
1409        let result: cln::PayResponse = self
1410            .with_keep_alive(with_connection_retry!(client.pay(request.clone())))
1411            .await?
1412            .into_inner();
1413
1414        // Before returning from send_payment we need to make sure it is persisted in the backend node.
1415        // We do so by polling for the payment.
1416        let payment = Self::fetch_outgoing_payment_with_retry(client, result.payment_hash).await?;
1417        payment.try_into()
1418    }
1419
1420    async fn send_trampoline_payment(
1421        &self,
1422        bolt11: String,
1423        amount_msat: u64,
1424        label: Option<String>,
1425        trampoline_node_id: Vec<u8>,
1426    ) -> NodeResult<Payment> {
1427        let invoice = parse_invoice(&bolt11)?;
1428        validate_network(invoice.clone(), self.sdk_config.network)?;
1429        let label = serde_json::to_string(&PaymentLabel {
1430            trampoline: true,
1431            client_label: label,
1432            unix_nano: SystemTime::now().duration_since(UNIX_EPOCH)?.as_nanos(),
1433            amount_msat,
1434        })?;
1435        let fee_msat =
1436            (amount_msat.saturating_mul(TRAMPOLINE_FEE_PPM) / 1_000_000) + TRAMPOLINE_BASE_FEE_MSAT;
1437        let fee_percent = ((fee_msat as f64 / amount_msat as f64) * 100.) as f32;
1438        debug!("using fee msat {} fee percent {}", fee_msat, fee_percent);
1439        let mut client = self.get_client().await?;
1440        let request = TrampolinePayRequest {
1441            bolt11,
1442            trampoline_node_id,
1443            amount_msat,
1444            label,
1445            maxdelay: u32::default(),
1446            description: String::default(),
1447            maxfeepercent: fee_percent,
1448        };
1449        let result = self
1450            .with_keep_alive(with_connection_retry!(
1451                client.trampoline_pay(request.clone())
1452            ))
1453            .await?
1454            .into_inner();
1455
1456        let client = self.get_node_client().await?;
1457
1458        // Before returning from send_payment we need to make sure it is
1459        // persisted in the backend node. We do so by polling for the payment.
1460        // TODO: Ensure this works with trampoline payments
1461        // NOTE: If this doesn't work with trampoline payments, the sync also
1462        // needs updating.
1463        let payment = Self::fetch_outgoing_payment_with_retry(client, result.payment_hash).await?;
1464        payment.try_into()
1465    }
1466
1467    async fn send_spontaneous_payment(
1468        &self,
1469        node_id: String,
1470        amount_msat: u64,
1471        extra_tlvs: Option<Vec<TlvEntry>>,
1472        label: Option<String>,
1473    ) -> NodeResult<Payment> {
1474        let mut client: node::ClnClient = self.get_node_client().await?;
1475        let request = cln::KeysendRequest {
1476            destination: hex::decode(node_id)?,
1477            amount_msat: Some(cln::Amount { msat: amount_msat }),
1478            label: label.or(Some(format!(
1479                "breez-{}",
1480                SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis()
1481            ))),
1482            extratlvs: extra_tlvs.map(|tlvs| cln::TlvStream {
1483                entries: tlvs
1484                    .into_iter()
1485                    .map(|tlv| cln::TlvEntry {
1486                        r#type: tlv.field_number,
1487                        value: tlv.value,
1488                    })
1489                    .collect(),
1490            }),
1491            routehints: None,
1492            maxfeepercent: Some(self.sdk_config.maxfee_percent),
1493            exemptfee: None,
1494            retry_for: Some(self.sdk_config.payment_timeout_sec),
1495            maxdelay: None,
1496        };
1497
1498        // Not wrapped with connection retry, in case it causes to send twice.
1499        let result = self
1500            .with_keep_alive(client.key_send(request))
1501            .await?
1502            .into_inner();
1503
1504        // Before returning from send_payment we need to make sure it is persisted in the backend node.
1505        // We do so by polling for the payment.
1506        let payment = Self::fetch_outgoing_payment_with_retry(client, result.payment_hash).await?;
1507        payment.try_into()
1508    }
1509
1510    async fn node_id(&self) -> NodeResult<String> {
1511        Ok(hex::encode(self.get_signer().await.node_id()))
1512    }
1513
1514    async fn redeem_onchain_funds(
1515        &self,
1516        to_address: String,
1517        sat_per_vbyte: u32,
1518    ) -> NodeResult<Vec<u8>> {
1519        let mut client = self.get_node_client().await?;
1520
1521        let request = cln::WithdrawRequest {
1522            feerate: Some(cln::Feerate {
1523                style: Some(cln::feerate::Style::Perkw(sat_per_vbyte * 250)),
1524            }),
1525            satoshi: Some(cln::AmountOrAll {
1526                value: Some(cln::amount_or_all::Value::All(true)),
1527            }),
1528            destination: to_address,
1529            minconf: None,
1530            utxos: vec![],
1531        };
1532
1533        Ok(with_connection_retry!(client.withdraw(request.clone()))
1534            .await?
1535            .into_inner()
1536            .txid)
1537    }
1538
1539    async fn prepare_redeem_onchain_funds(
1540        &self,
1541        req: PrepareRedeemOnchainFundsRequest,
1542    ) -> NodeResult<PrepareRedeemOnchainFundsResponse> {
1543        let funds = self.list_funds().await?;
1544        let utxos = self.utxos(funds).await?;
1545
1546        let mut amount_msat: u64 = 0;
1547        let txins: Vec<TxIn> = utxos
1548            .iter()
1549            .map(|utxo| {
1550                amount_msat += utxo.amount_millisatoshi;
1551                TxIn {
1552                    previous_output: OutPoint {
1553                        txid: Txid::from_slice(&utxo.txid).unwrap(),
1554                        vout: 0,
1555                    },
1556                    script_sig: Script::new(),
1557                    sequence: Sequence(0),
1558                    witness: Witness::default(),
1559                }
1560            })
1561            .collect();
1562
1563        let amount_sat = amount_msat / 1_000;
1564        let btc_address = Address::from_str(&req.to_address)?;
1565        let tx_out: Vec<TxOut> = vec![TxOut {
1566            value: amount_sat,
1567            script_pubkey: btc_address.payload.script_pubkey(),
1568        }];
1569        let tx = Transaction {
1570            version: 2,
1571            lock_time: crate::bitcoin::PackedLockTime(0),
1572            input: txins.clone(),
1573            output: tx_out,
1574        };
1575
1576        let witness_input_size: u64 = 110;
1577        let tx_weight = tx.strippedsize() as u64 * WITNESS_SCALE_FACTOR as u64
1578            + witness_input_size * txins.len() as u64;
1579        let fee: u64 = tx_weight * req.sat_per_vbyte as u64 / WITNESS_SCALE_FACTOR as u64;
1580        if fee >= amount_sat {
1581            return Err(NodeError::InsufficientFunds(
1582                "Insufficient funds to pay fees".to_string(),
1583            ));
1584        }
1585
1586        return Ok(PrepareRedeemOnchainFundsResponse {
1587            tx_weight,
1588            tx_fee_sat: fee,
1589        });
1590    }
1591
1592    /// Starts the signer that listens in a loop until the shutdown signal is received
1593    async fn start_signer(&self, shutdown: mpsc::Receiver<()>) {
1594        match self.get_signer().await.run_forever(shutdown).await {
1595            Ok(_) => info!("signer exited gracefully"),
1596            Err(e) => error!("signer exited with error: {e}"),
1597        }
1598    }
1599
1600    async fn start_keep_alive(&self, mut shutdown: watch::Receiver<()>) {
1601        info!("keep alive started");
1602        let mut interval = tokio::time::interval(Duration::from_secs(15));
1603        interval.set_missed_tick_behavior(MissedTickBehavior::Skip);
1604        loop {
1605            tokio::select! {
1606                  _ = shutdown.changed() => {
1607                    info!("keep alive exited");
1608                    break;
1609                  }
1610                  _ = interval.tick() => {
1611                    let inprogress_payments = self.inprogress_payments.load(Ordering::Relaxed);
1612                    if inprogress_payments == 0 {
1613                      continue
1614                    }
1615                    let client_res = self.get_node_client().await;
1616                    match client_res {
1617                      Ok(mut client) => {
1618                        let res = client.getinfo(cln::GetinfoRequest {}).await;
1619                        match res {
1620                          Ok(_) => {
1621                            info!("keep alive ping sent, in progress payments: {inprogress_payments}");
1622                          }
1623                          Err(e) => {
1624                            error!("keep alive ping failed: {e}");
1625                          }
1626                        }
1627                      }
1628                      Err(e) => {
1629                        error!("keep alive ping failed to create client: {e}");
1630                      }
1631                    }
1632                  }
1633            }
1634        }
1635    }
1636
1637    async fn connect_peer(&self, id: String, addr: String) -> NodeResult<()> {
1638        let mut client = self.get_node_client().await?;
1639        let connect_req = cln::ConnectRequest {
1640            id: format!("{id}@{addr}"),
1641            host: None,
1642            port: None,
1643        };
1644        with_connection_retry!(client.connect_peer(connect_req.clone())).await?;
1645        Ok(())
1646    }
1647
1648    async fn sign_message(&self, message: &str) -> NodeResult<String> {
1649        let (sig, recovery_id) = self
1650            .get_signer()
1651            .await
1652            .sign_message(message.as_bytes().to_vec())?;
1653        let mut complete_signature = vec![31 + recovery_id];
1654        complete_signature.extend_from_slice(&sig);
1655        Ok(zbase32::encode_full_bytes(&complete_signature))
1656    }
1657
1658    async fn check_message(
1659        &self,
1660        message: &str,
1661        pubkey: &str,
1662        signature: &str,
1663    ) -> NodeResult<bool> {
1664        let pk = PublicKey::from_str(pubkey)?;
1665        Ok(verify(message.as_bytes(), signature, &pk))
1666    }
1667
1668    async fn sign_invoice(&self, invoice: RawBolt11Invoice) -> NodeResult<String> {
1669        let hrp_bytes = invoice.hrp.to_string().as_bytes().to_vec();
1670        let data_bytes = invoice.data.to_base32();
1671
1672        // create the message for the signer
1673        let msg_type: u16 = 8;
1674        let data_len: u16 = data_bytes.len().try_into()?;
1675        let mut data_len_bytes = data_len.to_be_bytes().to_vec();
1676        let mut data_buf = data_bytes.iter().copied().map(u5::to_u8).collect();
1677
1678        let hrp_len: u16 = hrp_bytes.len().try_into()?;
1679        let mut hrp_len_bytes = hrp_len.to_be_bytes().to_vec();
1680        let mut hrp_buf = hrp_bytes.to_vec();
1681
1682        let mut buf = msg_type.to_be_bytes().to_vec();
1683        buf.append(&mut data_len_bytes);
1684        buf.append(&mut data_buf);
1685        buf.append(&mut hrp_len_bytes);
1686        buf.append(&mut hrp_buf);
1687        // Sign the invoice using the signer
1688        let raw_result = self.get_signer().await.sign_invoice(buf)?;
1689        info!(
1690            "recover id: {:?} raw = {:?}",
1691            raw_result, raw_result[64] as i32
1692        );
1693        // contruct the RecoveryId
1694        let rid = RecoveryId::from_i32(raw_result[64] as i32).expect("recovery ID");
1695        let sig = &raw_result[0..64];
1696        let recoverable_sig = RecoverableSignature::from_compact(sig, rid)?;
1697
1698        let signed_invoice: Result<SignedRawBolt11Invoice> = invoice.sign(|_| Ok(recoverable_sig));
1699        Ok(signed_invoice?.to_string())
1700    }
1701
1702    async fn close_peer_channels(&self, node_id: String) -> NodeResult<Vec<String>> {
1703        let mut client = self.get_node_client().await?;
1704        let req = cln::ListpeerchannelsRequest {
1705            id: Some(hex::decode(node_id)?),
1706        };
1707        let closed_channels = with_connection_retry!(client.list_peer_channels(req.clone()))
1708            .await?
1709            .into_inner();
1710        let mut tx_ids = vec![];
1711        for channel in closed_channels.channels {
1712            let mut should_close = false;
1713            if let Some(state) = channel.state {
1714                match cln::ChannelState::from_i32(state) {
1715                    Some(cln::ChannelState::Openingd) => should_close = true,
1716                    Some(cln::ChannelState::ChanneldAwaitingLockin) => should_close = true,
1717                    Some(cln::ChannelState::ChanneldNormal) => should_close = true,
1718                    Some(cln::ChannelState::ChanneldShuttingDown) => should_close = true,
1719                    Some(cln::ChannelState::FundingSpendSeen) => should_close = true,
1720                    Some(cln::ChannelState::DualopendOpenInit) => should_close = true,
1721                    Some(cln::ChannelState::DualopendAwaitingLockin) => should_close = true,
1722                    Some(_) => should_close = false,
1723                    None => should_close = false,
1724                }
1725            }
1726
1727            if should_close {
1728                let chan_id = channel.channel_id.ok_or(anyhow!("Empty channel id"))?;
1729                let req = cln::CloseRequest {
1730                    id: hex::encode(chan_id),
1731                    unilateraltimeout: None,
1732                    destination: None,
1733                    fee_negotiation_step: None,
1734                    wrong_funding: None,
1735                    force_lease_closed: None,
1736                    feerange: vec![],
1737                };
1738                let response = with_connection_retry!(client.close(req.clone())).await;
1739                match response {
1740                    Ok(res) => {
1741                        tx_ids.push(hex::encode(
1742                            res.into_inner()
1743                                .txid
1744                                .ok_or(anyhow!("Empty txid in close response"))?,
1745                        ));
1746                    }
1747                    Err(e) => Err(anyhow!("Empty closing channel: {e}"))?,
1748                };
1749            }
1750        }
1751        Ok(tx_ids)
1752    }
1753
1754    async fn stream_incoming_payments(
1755        &self,
1756    ) -> NodeResult<Streaming<gl_client::signer::model::greenlight::IncomingPayment>> {
1757        let mut client = self.get_client().await?;
1758        let req = gl_client::signer::model::greenlight::StreamIncomingFilter {};
1759        let stream = with_connection_retry!(client.stream_incoming(req.clone()))
1760            .await?
1761            .into_inner();
1762        Ok(stream)
1763    }
1764
1765    async fn stream_log_messages(
1766        &self,
1767    ) -> NodeResult<Streaming<gl_client::signer::model::greenlight::LogEntry>> {
1768        let mut client = self.get_client().await?;
1769        let req = gl_client::signer::model::greenlight::StreamLogRequest {};
1770        let stream = with_connection_retry!(client.stream_log(req.clone()))
1771            .await?
1772            .into_inner();
1773        Ok(stream)
1774    }
1775
1776    async fn static_backup(&self) -> NodeResult<Vec<String>> {
1777        let mut client = self.get_node_client().await?;
1778        let req = cln::StaticbackupRequest {};
1779        let res = with_connection_retry!(client.static_backup(req.clone()))
1780            .await?
1781            .into_inner();
1782        let hex_vec: Vec<String> = res.scb.into_iter().map(hex::encode).collect();
1783        Ok(hex_vec)
1784    }
1785
1786    async fn generate_diagnostic_data(&self) -> NodeResult<Value> {
1787        let all_commands = vec![
1788            NodeCommand::GetInfo.to_string(),
1789            NodeCommand::ListPeerChannels.to_string(),
1790            NodeCommand::ListFunds.to_string(),
1791            NodeCommand::ListPayments.to_string(),
1792            NodeCommand::ListInvoices.to_string(),
1793        ];
1794
1795        let mut result = Map::new();
1796        for command in all_commands {
1797            let command_name = command.clone();
1798            let res = self
1799                .execute_command(command)
1800                .await
1801                .unwrap_or_else(|e| json!({ "error": e.to_string() }));
1802            result.insert(command_name, res);
1803        }
1804        Ok(Value::Object(result))
1805    }
1806
1807    async fn execute_command(&self, command: String) -> NodeResult<Value> {
1808        let node_cmd =
1809            NodeCommand::from_str(&command).map_err(|_| anyhow!("Command not found: {command}"))?;
1810
1811        let mut client = self.get_node_client().await?;
1812        match node_cmd {
1813            NodeCommand::ListPeers => {
1814                let req = cln::ListpeersRequest::default();
1815                let resp = with_connection_retry!(client.list_peers(req.clone()))
1816                    .await?
1817                    .into_inner();
1818
1819                Ok(crate::serializer::value::to_value(&resp)?)
1820            }
1821            NodeCommand::ListPeerChannels => {
1822                let req = cln::ListpeerchannelsRequest::default();
1823                let resp = with_connection_retry!(client.list_peer_channels(req.clone()))
1824                    .await?
1825                    .into_inner();
1826                Ok(crate::serializer::value::to_value(&resp)?)
1827            }
1828            NodeCommand::ListFunds => {
1829                let req = cln::ListfundsRequest::default();
1830                let resp = with_connection_retry!(client.list_funds(req.clone()))
1831                    .await?
1832                    .into_inner();
1833                Ok(crate::serializer::value::to_value(&resp)?)
1834            }
1835            NodeCommand::ListPayments => {
1836                let req = cln::ListpaysRequest::default();
1837                let resp = with_connection_retry!(client.list_pays(req.clone()))
1838                    .await?
1839                    .into_inner();
1840                Ok(crate::serializer::value::to_value(&resp)?)
1841            }
1842            NodeCommand::ListInvoices => {
1843                let req = cln::ListinvoicesRequest::default();
1844                let resp = with_connection_retry!(client.list_invoices(req.clone()))
1845                    .await?
1846                    .into_inner();
1847
1848                Ok(crate::serializer::value::to_value(&resp)?)
1849            }
1850            NodeCommand::CloseAllChannels => {
1851                let req = cln::ListpeersRequest::default();
1852                let resp = with_connection_retry!(client.list_peers(req.clone()))
1853                    .await?
1854                    .into_inner();
1855                for p in resp.peers {
1856                    self.close_peer_channels(hex::encode(p.id)).await?;
1857                }
1858
1859                Ok(Value::String("All channels were closed".to_string()))
1860            }
1861            NodeCommand::GetInfo => {
1862                let req = cln::GetinfoRequest::default();
1863                let resp = with_connection_retry!(client.getinfo(req.clone()))
1864                    .await?
1865                    .into_inner();
1866                Ok(crate::serializer::value::to_value(&resp)?)
1867            }
1868            NodeCommand::Stop => {
1869                let req = cln::StopRequest::default();
1870                let resp = with_connection_retry!(client.stop(req.clone()))
1871                    .await?
1872                    .into_inner();
1873                Ok(crate::serializer::value::to_value(&resp)?)
1874            }
1875        }
1876    }
1877
1878    async fn max_sendable_amount<'a>(
1879        &self,
1880        payee_node_id: Option<Vec<u8>>,
1881        max_hops: u32,
1882        last_hop_hint: Option<&'a RouteHintHop>,
1883    ) -> NodeResult<Vec<MaxChannelAmount>> {
1884        let mut client = self.get_node_client().await?;
1885
1886        let mut peers = HashMap::new();
1887        let req = cln::ListpeerchannelsRequest::default();
1888        with_connection_retry!(client.list_peer_channels(req.clone()))
1889            .await?
1890            .into_inner()
1891            .channels
1892            .into_iter()
1893            .for_each(|channel| {
1894                peers
1895                    .entry(channel.peer_id().to_vec())
1896                    .or_insert(Vec::new())
1897                    .push(channel)
1898            });
1899
1900        let mut max_channel_amounts = vec![];
1901        for (peer, channels) in peers {
1902            let max_amounts_for_peer = self
1903                .max_sendable_amount_from_peer(
1904                    peer,
1905                    channels,
1906                    payee_node_id.clone(),
1907                    max_hops,
1908                    last_hop_hint,
1909                )
1910                .await?;
1911            max_channel_amounts.extend_from_slice(max_amounts_for_peer.as_slice());
1912        }
1913        Ok(max_channel_amounts)
1914    }
1915
1916    async fn derive_bip32_key(&self, path: Vec<ChildNumber>) -> NodeResult<ExtendedPrivKey> {
1917        Self::derive_bip32_key(self.sdk_config.network, &self.get_signer().await, path)
1918    }
1919
1920    async fn legacy_derive_bip32_key(&self, path: Vec<ChildNumber>) -> NodeResult<ExtendedPrivKey> {
1921        Self::legacy_derive_bip32_key(self.sdk_config.network, &self.get_signer().await, path)
1922    }
1923
1924    async fn stream_custom_messages(
1925        &self,
1926    ) -> NodeResult<Pin<Box<dyn Stream<Item = Result<CustomMessage>> + Send>>> {
1927        let stream = {
1928            let mut client = match self.get_client().await {
1929                Ok(c) => Ok(c),
1930                Err(e) => Err(anyhow!("{}", e)),
1931            }?;
1932            let req = gl_client::signer::model::greenlight::StreamCustommsgRequest {};
1933            match with_connection_retry!(client.stream_custommsg(req.clone())).await {
1934                Ok(s) => Ok(s),
1935                Err(e) => Err(anyhow!("{}", e)),
1936            }?
1937            .into_inner()
1938        };
1939
1940        Ok(Box::pin(stream.filter_map(|msg| {
1941            let msg = match msg {
1942                Ok(msg) => msg,
1943                Err(e) => return Some(Err(anyhow!("failed to receive message: {}", e))),
1944            };
1945
1946            if msg.payload.len() < 2 {
1947                debug!(
1948                    "received too short custom message payload: {:?}",
1949                    &msg.payload
1950                );
1951                return None;
1952            }
1953
1954            let msg_type = u16::from_be_bytes([msg.payload[0], msg.payload[1]]);
1955
1956            Some(Ok(CustomMessage {
1957                peer_id: msg.peer_id,
1958                message_type: msg_type,
1959                payload: msg.payload[2..].to_vec(),
1960            }))
1961        })))
1962    }
1963
1964    async fn send_custom_message(&self, message: CustomMessage) -> NodeResult<()> {
1965        let mut client = self.get_node_client().await?;
1966
1967        let mut msg = message.message_type.to_be_bytes().to_vec();
1968        msg.extend(message.payload);
1969        let req = cln::SendcustommsgRequest {
1970            msg,
1971            node_id: message.peer_id,
1972        };
1973        let resp = with_connection_retry!(client.send_custom_msg(req.clone()))
1974            .await?
1975            .into_inner();
1976        debug!("send_custom_message returned status {:?}", resp.status);
1977        Ok(())
1978    }
1979
1980    // Gets the routing hints related to all private channels that the node has
1981    async fn get_routing_hints(
1982        &self,
1983        lsp_info: &LspInformation,
1984    ) -> NodeResult<(Vec<RouteHint>, bool)> {
1985        let mut client = self.get_node_client().await?;
1986
1987        let open_peer_channels = self.get_open_peer_channels_pb().await?;
1988        let (open_peer_channels_private, open_peer_channels_public): (
1989            HashMap<Vec<u8>, ListpeerchannelsChannels>,
1990            HashMap<Vec<u8>, ListpeerchannelsChannels>,
1991        ) = open_peer_channels
1992            .into_iter()
1993            .partition(|(_, c)| c.private.unwrap_or_default());
1994        let has_public_channel = !open_peer_channels_public.is_empty();
1995
1996        let mut hints: Vec<RouteHint> = vec![];
1997
1998        // Get channels where our node is the destination
1999        let pubkey = self
2000            .persister
2001            .get_node_state()?
2002            .map(|n| n.id)
2003            .ok_or(NodeError::generic("Node info not found"))?;
2004        let req = cln::ListchannelsRequest {
2005            destination: Some(hex::decode(pubkey)?),
2006            ..Default::default()
2007        };
2008        let channels: HashMap<Vec<u8>, cln::ListchannelsChannels> =
2009            with_connection_retry!(client.list_channels(req.clone()))
2010                .await?
2011                .into_inner()
2012                .channels
2013                .into_iter()
2014                .map(|c| (c.source.clone(), c))
2015                .collect();
2016
2017        // Create a routing hint from each private channel.
2018        for (peer_id, peer_channel) in open_peer_channels_private {
2019            let peer_id_str = hex::encode(&peer_id);
2020            let optional_channel_id = peer_channel
2021                .alias
2022                .and_then(|a| a.remote)
2023                .or(peer_channel.short_channel_id);
2024
2025            if let Some(channel_id) = optional_channel_id {
2026                // The remote fee policy
2027                let maybe_policy = match channels.get(&peer_id) {
2028                    Some(channel) => Some((
2029                        channel.base_fee_millisatoshi,
2030                        channel.fee_per_millionth,
2031                        channel.delay,
2032                    )),
2033                    None if peer_id_str == lsp_info.pubkey => Some((
2034                        lsp_info.base_fee_msat as u32,
2035                        (lsp_info.fee_rate * 1000000.0) as u32,
2036                        lsp_info.time_lock_delta,
2037                    )),
2038                    _ => None,
2039                };
2040                match maybe_policy {
2041                    Some((fees_base_msat, fees_proportional_millionths, cltv_delta)) => {
2042                        debug!(
2043                            "For peer {}: remote base {} proportional {} cltv_delta {}",
2044                            peer_id_str, fees_base_msat, fees_proportional_millionths, cltv_delta,
2045                        );
2046                        let hint = RouteHint {
2047                            hops: vec![RouteHintHop {
2048                                src_node_id: peer_id_str,
2049                                short_channel_id: channel_id,
2050                                fees_base_msat,
2051                                fees_proportional_millionths,
2052                                cltv_expiry_delta: cltv_delta as u64,
2053                                htlc_minimum_msat: Some(
2054                                    peer_channel
2055                                        .minimum_htlc_in_msat
2056                                        .clone()
2057                                        .unwrap_or_default()
2058                                        .msat,
2059                                ),
2060                                htlc_maximum_msat: None,
2061                            }],
2062                        };
2063                        info!("Generating hint hop as routing hint: {:?}", hint);
2064                        hints.push(hint);
2065                    }
2066                    _ => debug!("No source channel found for peer: {:?}", peer_id_str),
2067                };
2068            }
2069        }
2070        Ok((hints, has_public_channel))
2071    }
2072
2073    async fn get_open_peers(&self) -> NodeResult<HashSet<Vec<u8>>> {
2074        let open_peer_channels = self.get_open_peer_channels_pb().await?;
2075        let open_peers: HashSet<Vec<u8>> = open_peer_channels.into_keys().collect();
2076        Ok(open_peers)
2077    }
2078}
2079
2080#[derive(Clone, PartialEq, Eq, Debug, EnumString, Display, Deserialize, Serialize)]
2081enum NodeCommand {
2082    /// Closes all channels of all peers.
2083    #[strum(serialize = "closeallchannels")]
2084    CloseAllChannels,
2085
2086    /// See <https://docs.corelightning.org/reference/lightning-getinfo>
2087    #[strum(serialize = "getinfo")]
2088    GetInfo,
2089
2090    /// See <https://docs.corelightning.org/reference/lightning-listfunds>
2091    #[strum(serialize = "listfunds")]
2092    ListFunds,
2093
2094    /// See <https://docs.corelightning.org/reference/lightning-listinvoices>
2095    #[strum(serialize = "listinvoices")]
2096    ListInvoices,
2097
2098    /// See <https://docs.corelightning.org/reference/lightning-listpays>
2099    #[strum(serialize = "listpayments")]
2100    ListPayments,
2101
2102    /// See <https://docs.corelightning.org/reference/lightning-listpeers>
2103    #[strum(serialize = "listpeers")]
2104    ListPeers,
2105
2106    /// See <https://docs.corelightning.org/reference/lightning-listpeerchannels>
2107    #[strum(serialize = "listpeerchannels")]
2108    ListPeerChannels,
2109
2110    /// Stops the node.
2111    ///
2112    /// Note that this command will return an error, as the node is stopped before it can reply.
2113    ///
2114    /// See <https://docs.corelightning.org/reference/lightning-stop>
2115    #[strum(serialize = "stop")]
2116    Stop,
2117}
2118
2119struct SendPayAgg {
2120    state: u8,
2121    created_at: u64,
2122    payment_hash: Vec<u8>,
2123    bolt11: Option<String>,
2124    destination: Option<Vec<u8>>,
2125    label: Option<String>,
2126    description: Option<String>,
2127    preimage: Option<Vec<u8>>,
2128    amount_sent: u64,
2129    amount: Option<u64>,
2130    num_nonfailed_parts: u64,
2131}
2132
2133fn update_payment_expirations(
2134    payments: Vec<Payment>,
2135    htlc_list: Vec<Htlc>,
2136) -> NodeResult<Vec<Payment>> {
2137    if htlc_list.is_empty() {
2138        return Ok(payments);
2139    }
2140
2141    let mut payments_res: Vec<Payment> = Vec::new();
2142    for mut payment in payments {
2143        if payment.status == PaymentStatus::Pending {
2144            let new_data = payment.clone().details;
2145            if let PaymentDetails::Ln { data } = new_data {
2146                for htlc in &htlc_list {
2147                    let payment_hash = hex::encode(htlc.clone().payment_hash);
2148                    if payment_hash == data.payment_hash
2149                        && data.pending_expiration_block < Some(htlc.expiry)
2150                    {
2151                        payment.details.add_pending_expiration_block(htlc.clone())
2152                    }
2153                }
2154            }
2155        }
2156        payments_res.push(payment);
2157    }
2158    info!("pending htlc payments {:?}", payments_res);
2159    Ok(payments_res)
2160}
2161
2162impl TryFrom<ListsendpaysPayments> for SendPay {
2163    type Error = NodeError;
2164
2165    fn try_from(value: ListsendpaysPayments) -> std::result::Result<Self, Self::Error> {
2166        Ok(SendPay {
2167            created_index: value
2168                .created_index
2169                .ok_or(NodeError::generic("missing created index"))?,
2170            updated_index: value.updated_index,
2171            groupid: value.groupid.to_string(),
2172            partid: value.partid,
2173            payment_hash: value.payment_hash,
2174            status: value.status.try_into()?,
2175            amount_msat: value.amount_msat.map(|a| a.msat),
2176            destination: value.destination,
2177            created_at: value.created_at,
2178            amount_sent_msat: value.amount_sent_msat.map(|a| a.msat),
2179            label: value.label,
2180            bolt11: value.bolt11,
2181            description: value.description,
2182            bolt12: value.bolt12,
2183            payment_preimage: value.payment_preimage,
2184            erroronion: value.erroronion,
2185        })
2186    }
2187}
2188
2189impl TryFrom<i32> for SendPayStatus {
2190    type Error = NodeError;
2191
2192    fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
2193        match value {
2194            0 => Ok(Self::Pending),
2195            1 => Ok(Self::Failed),
2196            2 => Ok(Self::Complete),
2197            _ => Err(NodeError::generic("invalid send_pay status")),
2198        }
2199    }
2200}
2201
2202impl TryFrom<SendPayAgg> for Payment {
2203    type Error = NodeError;
2204
2205    fn try_from(value: SendPayAgg) -> std::result::Result<Self, Self::Error> {
2206        let ln_invoice = value
2207            .bolt11
2208            .as_ref()
2209            .ok_or(InvoiceError::generic("No bolt11 invoice"))
2210            .and_then(|b| parse_invoice(b));
2211
2212        // For trampoline payments the amount_msat doesn't match the actual
2213        // amount. If it's a trampoline payment, take the amount from the label.
2214        let (payment_amount, client_label) =
2215            serde_json::from_str::<PaymentLabel>(&value.label.clone().unwrap_or_default())
2216                .ok()
2217                .and_then(|label| {
2218                    label
2219                        .trampoline
2220                        .then_some((label.amount_msat, label.client_label))
2221                })
2222                .unwrap_or((value.amount.unwrap_or_default(), value.label));
2223        let fee_msat = value.amount_sent.saturating_sub(payment_amount);
2224        let status = if value.state & PAYMENT_STATE_COMPLETE > 0 {
2225            PaymentStatus::Complete
2226        } else if value.state & PAYMENT_STATE_PENDING > 0 {
2227            PaymentStatus::Pending
2228        } else {
2229            PaymentStatus::Failed
2230        };
2231        Ok(Self {
2232            id: hex::encode(&value.payment_hash),
2233            payment_type: PaymentType::Sent,
2234            payment_time: value.created_at as i64,
2235            amount_msat: match status {
2236                PaymentStatus::Complete => payment_amount,
2237                _ => ln_invoice
2238                    .as_ref()
2239                    .map_or(0, |i| i.amount_msat.unwrap_or_default()),
2240            },
2241            fee_msat,
2242            status,
2243            error: None,
2244            description: ln_invoice
2245                .as_ref()
2246                .map(|i| i.description.clone())
2247                .unwrap_or_default(),
2248            details: PaymentDetails::Ln {
2249                data: LnPaymentDetails {
2250                    payment_hash: hex::encode(&value.payment_hash),
2251                    label: client_label.unwrap_or_default(),
2252                    destination_pubkey: ln_invoice.map_or(
2253                        value.destination.map(hex::encode).unwrap_or_default(),
2254                        |i| i.payee_pubkey,
2255                    ),
2256                    payment_preimage: value.preimage.map(hex::encode).unwrap_or_default(),
2257                    keysend: value.bolt11.is_none(),
2258                    bolt11: value.bolt11.unwrap_or_default(),
2259                    open_channel_bolt11: None,
2260                    lnurl_success_action: None,
2261                    lnurl_pay_domain: None,
2262                    lnurl_pay_comment: None,
2263                    ln_address: None,
2264                    lnurl_metadata: None,
2265                    lnurl_withdraw_endpoint: None,
2266                    swap_info: None,
2267                    reverse_swap_info: None,
2268                    pending_expiration_block: None,
2269                },
2270            },
2271            metadata: None,
2272        })
2273    }
2274}
2275
2276//pub(crate) fn offchain_payment_to_transaction
2277impl TryFrom<OffChainPayment> for Payment {
2278    type Error = NodeError;
2279
2280    fn try_from(p: OffChainPayment) -> std::result::Result<Self, Self::Error> {
2281        let ln_invoice = parse_invoice(&p.bolt11)?;
2282        Ok(Payment {
2283            id: hex::encode(p.payment_hash.clone()),
2284            payment_type: PaymentType::Received,
2285            payment_time: SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64,
2286            amount_msat: amount_to_msat(&p.amount.unwrap_or_default()),
2287            fee_msat: 0,
2288            status: PaymentStatus::Complete,
2289            error: None,
2290            description: ln_invoice.description,
2291            details: PaymentDetails::Ln {
2292                data: LnPaymentDetails {
2293                    payment_hash: hex::encode(p.payment_hash),
2294                    label: p.label,
2295                    destination_pubkey: ln_invoice.payee_pubkey,
2296                    payment_preimage: hex::encode(p.preimage),
2297                    keysend: false,
2298                    bolt11: p.bolt11,
2299                    lnurl_success_action: None, // For received payments, this is None
2300                    lnurl_pay_domain: None,     // For received payments, this is None
2301                    lnurl_pay_comment: None,    // For received payments, this is None
2302                    lnurl_metadata: None,       // For received payments, this is None
2303                    ln_address: None,
2304                    lnurl_withdraw_endpoint: None,
2305                    swap_info: None,
2306                    reverse_swap_info: None,
2307                    pending_expiration_block: None,
2308                    open_channel_bolt11: None,
2309                },
2310            },
2311            metadata: None,
2312        })
2313    }
2314}
2315
2316/// Construct a lightning transaction from an invoice
2317impl TryFrom<cln::ListinvoicesInvoices> for Payment {
2318    type Error = NodeError;
2319
2320    fn try_from(invoice: cln::ListinvoicesInvoices) -> std::result::Result<Self, Self::Error> {
2321        let ln_invoice = invoice
2322            .bolt11
2323            .as_ref()
2324            .ok_or(InvoiceError::generic("No bolt11 invoice"))
2325            .and_then(|b| parse_invoice(b))?;
2326        Ok(Payment {
2327            id: hex::encode(invoice.payment_hash.clone()),
2328            payment_type: PaymentType::Received,
2329            payment_time: invoice.paid_at.map(|i| i as i64).unwrap_or_default(),
2330            amount_msat: invoice
2331                .amount_received_msat
2332                .or(invoice.amount_msat)
2333                .map(|a| a.msat)
2334                .unwrap_or_default(),
2335            fee_msat: 0,
2336            status: PaymentStatus::Complete,
2337            error: None,
2338            description: ln_invoice.description,
2339            details: PaymentDetails::Ln {
2340                data: LnPaymentDetails {
2341                    payment_hash: hex::encode(invoice.payment_hash),
2342                    label: invoice.label,
2343                    destination_pubkey: ln_invoice.payee_pubkey,
2344                    payment_preimage: invoice
2345                        .payment_preimage
2346                        .map(hex::encode)
2347                        .unwrap_or_default(),
2348                    keysend: false,
2349                    bolt11: invoice.bolt11.unwrap_or_default(),
2350                    lnurl_success_action: None, // For received payments, this is None
2351                    lnurl_pay_domain: None,     // For received payments, this is None
2352                    lnurl_pay_comment: None,    // For received payments, this is None
2353                    lnurl_metadata: None,       // For received payments, this is None
2354                    ln_address: None,
2355                    lnurl_withdraw_endpoint: None,
2356                    swap_info: None,
2357                    reverse_swap_info: None,
2358                    pending_expiration_block: None,
2359                    open_channel_bolt11: None,
2360                },
2361            },
2362            metadata: None,
2363        })
2364    }
2365}
2366
2367impl From<ListpaysPaysStatus> for PaymentStatus {
2368    fn from(value: ListpaysPaysStatus) -> Self {
2369        match value {
2370            ListpaysPaysStatus::Pending => PaymentStatus::Pending,
2371            ListpaysPaysStatus::Complete => PaymentStatus::Complete,
2372            ListpaysPaysStatus::Failed => PaymentStatus::Failed,
2373        }
2374    }
2375}
2376
2377impl TryFrom<cln::ListpaysPays> for Payment {
2378    type Error = NodeError;
2379
2380    fn try_from(payment: cln::ListpaysPays) -> NodeResult<Self, Self::Error> {
2381        let ln_invoice = payment
2382            .bolt11
2383            .as_ref()
2384            .ok_or(InvoiceError::generic("No bolt11 invoice"))
2385            .and_then(|b| parse_invoice(b));
2386        let payment_amount_sent = payment
2387            .amount_sent_msat
2388            .clone()
2389            .map(|a| a.msat)
2390            .unwrap_or_default();
2391
2392        // For trampoline payments the amount_msat doesn't match the actual
2393        // amount. If it's a trampoline payment, take the amount from the label.
2394        let (payment_amount, client_label) = serde_json::from_str::<PaymentLabel>(payment.label())
2395            .ok()
2396            .and_then(|label| {
2397                label
2398                    .trampoline
2399                    .then_some((label.amount_msat, label.client_label))
2400            })
2401            .unwrap_or((
2402                payment
2403                    .amount_msat
2404                    .clone()
2405                    .map(|a| a.msat)
2406                    .unwrap_or_default(),
2407                payment.label.clone(),
2408            ));
2409        let status = payment.status().into();
2410
2411        Ok(Payment {
2412            id: hex::encode(payment.payment_hash.clone()),
2413            payment_type: PaymentType::Sent,
2414            payment_time: payment.completed_at.unwrap_or(payment.created_at) as i64,
2415            amount_msat: match status {
2416                PaymentStatus::Complete => payment_amount,
2417                _ => ln_invoice
2418                    .as_ref()
2419                    .map_or(0, |i| i.amount_msat.unwrap_or_default()),
2420            },
2421            fee_msat: payment_amount_sent.saturating_sub(payment_amount),
2422            status,
2423            error: None,
2424            description: ln_invoice
2425                .as_ref()
2426                .map(|i| i.description.clone())
2427                .unwrap_or_default(),
2428            details: PaymentDetails::Ln {
2429                data: LnPaymentDetails {
2430                    payment_hash: hex::encode(payment.payment_hash),
2431                    label: client_label.unwrap_or_default(),
2432                    destination_pubkey: ln_invoice.map_or(
2433                        payment.destination.map(hex::encode).unwrap_or_default(),
2434                        |i| i.payee_pubkey,
2435                    ),
2436                    payment_preimage: payment.preimage.map(hex::encode).unwrap_or_default(),
2437                    keysend: payment.bolt11.is_none(),
2438                    bolt11: payment.bolt11.unwrap_or_default(),
2439                    lnurl_success_action: None,
2440                    lnurl_pay_domain: None,
2441                    lnurl_pay_comment: None,
2442                    lnurl_metadata: None,
2443                    ln_address: None,
2444                    lnurl_withdraw_endpoint: None,
2445                    swap_info: None,
2446                    reverse_swap_info: None,
2447                    pending_expiration_block: None,
2448                    open_channel_bolt11: None,
2449                },
2450            },
2451            metadata: None,
2452        })
2453    }
2454}
2455
2456impl TryFrom<cln::PayResponse> for PaymentResponse {
2457    type Error = NodeError;
2458
2459    fn try_from(payment: cln::PayResponse) -> std::result::Result<Self, Self::Error> {
2460        let payment_amount = payment.amount_msat.unwrap_or_default().msat;
2461        let payment_amount_sent = payment.amount_sent_msat.unwrap_or_default().msat;
2462
2463        Ok(PaymentResponse {
2464            payment_time: payment.created_at as i64,
2465            amount_msat: payment_amount,
2466            fee_msat: payment_amount_sent - payment_amount,
2467            payment_hash: hex::encode(payment.payment_hash),
2468            payment_preimage: hex::encode(payment.payment_preimage),
2469        })
2470    }
2471}
2472
2473impl TryFrom<cln::KeysendResponse> for PaymentResponse {
2474    type Error = NodeError;
2475
2476    fn try_from(payment: cln::KeysendResponse) -> std::result::Result<Self, Self::Error> {
2477        let payment_amount = payment.amount_msat.unwrap_or_default().msat;
2478        let payment_amount_sent = payment.amount_sent_msat.unwrap_or_default().msat;
2479
2480        Ok(PaymentResponse {
2481            payment_time: payment.created_at as i64,
2482            amount_msat: payment_amount,
2483            fee_msat: payment_amount_sent - payment_amount,
2484            payment_hash: hex::encode(payment.payment_hash),
2485            payment_preimage: hex::encode(payment.payment_preimage),
2486        })
2487    }
2488}
2489
2490fn amount_to_msat(amount: &gl_client::pb::greenlight::Amount) -> u64 {
2491    match amount.unit {
2492        Some(amount::Unit::Millisatoshi(val)) => val,
2493        Some(amount::Unit::Satoshi(val)) => val * 1000,
2494        Some(amount::Unit::Bitcoin(val)) => val * 100000000,
2495        Some(_) => 0,
2496        None => 0,
2497    }
2498}
2499
2500/// Conversion for an open channel
2501impl From<cln::ListpeerchannelsChannels> for Channel {
2502    fn from(c: cln::ListpeerchannelsChannels) -> Self {
2503        let state = match c.state() {
2504            Openingd | ChanneldAwaitingLockin | DualopendOpenInit | DualopendAwaitingLockin => {
2505                ChannelState::PendingOpen
2506            }
2507            ChanneldNormal => ChannelState::Opened,
2508            _ => ChannelState::PendingClose,
2509        };
2510
2511        let (alias_remote, alias_local) = match c.alias {
2512            Some(a) => (a.remote, a.local),
2513            None => (None, None),
2514        };
2515
2516        Channel {
2517            short_channel_id: c.short_channel_id,
2518            state,
2519            funding_txid: c.funding_txid.map(hex::encode).unwrap_or_default(),
2520            spendable_msat: c.spendable_msat.unwrap_or_default().msat,
2521            local_balance_msat: c.to_us_msat.unwrap_or_default().msat,
2522            receivable_msat: c.receivable_msat.unwrap_or_default().msat,
2523            closed_at: None,
2524            funding_outnum: c.funding_outnum,
2525            alias_remote,
2526            alias_local,
2527            closing_txid: None,
2528            htlcs: c
2529                .htlcs
2530                .into_iter()
2531                .map(|c| Htlc::from(c.expiry.unwrap_or(0), c.payment_hash.unwrap_or_default()))
2532                .collect(),
2533        }
2534    }
2535}
2536
2537fn convert_to_send_pay_route(
2538    route: PaymentPath,
2539    to_pay_msat: u64,
2540    final_cltv_delta: u64,
2541) -> (Vec<SendpayRoute>, u64) {
2542    let mut sendpay_route = vec![];
2543    let mut to_forward = to_pay_msat;
2544    let mut cltv_delay = 0;
2545    let hops_arr = route.edges.as_slice();
2546
2547    let reverse_hops: Vec<&PaymentPathEdge> = hops_arr.iter().rev().collect();
2548
2549    // Iterating over the path in a reverse order so we can calculate
2550    // the cltv deltas and fees.
2551    for (reverse_index, hop) in reverse_hops.iter().enumerate() {
2552        //let hop = h.clone();
2553        (to_forward, cltv_delay) = match reverse_index == 0 {
2554            // last hop should not take any fees and should use the final_cltv_delta.
2555            true => (to_forward, final_cltv_delta),
2556
2557            // all other hops are forwarding therefore should take fees and increase the cltv delta.
2558            false => (
2559                reverse_hops[reverse_index - 1].amount_from_forward(to_forward),
2560                cltv_delay + reverse_hops[reverse_index - 1].channel_delay,
2561            ),
2562        };
2563
2564        sendpay_route.insert(
2565            0,
2566            SendpayRoute {
2567                amount_msat: Some(gl_client::pb::cln::Amount { msat: to_forward }),
2568                id: hop.node_id.clone(),
2569                delay: cltv_delay as u32,
2570                channel: hop.short_channel_id.clone(),
2571            },
2572        );
2573    }
2574
2575    (sendpay_route, to_forward)
2576}
2577
2578impl TryFrom<ListclosedchannelsClosedchannels> for Channel {
2579    type Error = NodeError;
2580
2581    fn try_from(
2582        c: cln::ListclosedchannelsClosedchannels,
2583    ) -> std::result::Result<Self, Self::Error> {
2584        let (alias_remote, alias_local) = match c.alias {
2585            Some(a) => (a.remote, a.local),
2586            None => (None, None),
2587        };
2588
2589        // To keep the conversion simple and fast, some closing-related fields (closed_at, closing_txid)
2590        // are left empty here in the conversion, but populated later (via chain service lookup, or DB lookup)
2591        let local_balance_msat = c
2592            .final_to_us_msat
2593            .ok_or(anyhow!("final_to_us_msat is missing"))?
2594            .msat;
2595        Ok(Channel {
2596            short_channel_id: c.short_channel_id,
2597            state: ChannelState::Closed,
2598            funding_txid: hex::encode(c.funding_txid),
2599            spendable_msat: local_balance_msat,
2600            local_balance_msat,
2601            receivable_msat: 0,
2602            closed_at: None,
2603            funding_outnum: Some(c.funding_outnum),
2604            alias_remote,
2605            alias_local,
2606            closing_txid: None,
2607            htlcs: Vec::new(),
2608        })
2609    }
2610}
2611
2612#[cfg(test)]
2613mod tests {
2614    use anyhow::Result;
2615    use gl_client::pb::cln::listpeerchannels_channels::{
2616        ListpeerchannelsChannelsState, ListpeerchannelsChannelsState::*,
2617    };
2618    use gl_client::pb::cln::Amount;
2619    use gl_client::pb::{self, cln};
2620
2621    use crate::greenlight::node_api::convert_to_send_pay_route;
2622    use crate::{models, PaymentPath, PaymentPathEdge};
2623
2624    #[test]
2625    fn test_convert_route() -> Result<()> {
2626        let path = PaymentPath {
2627            edges: vec![
2628                PaymentPathEdge {
2629                    node_id: vec![1],
2630                    short_channel_id: "807189x2048x0".into(),
2631                    channel_delay: 34,
2632                    base_fee_msat: 1000,
2633                    fee_per_millionth: 10,
2634                },
2635                PaymentPathEdge {
2636                    node_id: vec![2],
2637                    short_channel_id: "811871x2726x1".into(),
2638                    channel_delay: 34,
2639                    base_fee_msat: 0,
2640                    fee_per_millionth: 0,
2641                },
2642                PaymentPathEdge {
2643                    node_id: vec![3],
2644                    short_channel_id: "16000000x0x18087".into(),
2645                    channel_delay: 40,
2646                    base_fee_msat: 1000,
2647                    fee_per_millionth: 1,
2648                },
2649            ],
2650        };
2651
2652        let (r, sent) = convert_to_send_pay_route(path, 50000000, 144);
2653        assert_eq!(
2654            r,
2655            vec![
2656                pb::cln::SendpayRoute {
2657                    amount_msat: Some(gl_client::pb::cln::Amount { msat: 50001050 }),
2658                    id: vec![1],
2659                    delay: 218,
2660                    channel: "807189x2048x0".into(),
2661                },
2662                pb::cln::SendpayRoute {
2663                    amount_msat: Some(gl_client::pb::cln::Amount { msat: 50001050 }),
2664                    id: vec![2],
2665                    delay: 184,
2666                    channel: "811871x2726x1".into(),
2667                },
2668                pb::cln::SendpayRoute {
2669                    amount_msat: Some(gl_client::pb::cln::Amount { msat: 50000000 }),
2670                    id: vec![3],
2671                    delay: 144,
2672                    channel: "16000000x0x18087".into(),
2673                }
2674            ]
2675        );
2676        assert_eq!(sent, 50001050);
2677
2678        let path = PaymentPath {
2679            edges: vec![
2680                PaymentPathEdge {
2681                    node_id: vec![1],
2682                    short_channel_id: "807189x2048x0".into(),
2683                    channel_delay: 34,
2684                    base_fee_msat: 1000,
2685                    fee_per_millionth: 10,
2686                },
2687                PaymentPathEdge {
2688                    node_id: vec![2],
2689                    short_channel_id: "811871x2726x1".into(),
2690                    channel_delay: 34,
2691                    base_fee_msat: 0,
2692                    fee_per_millionth: 0,
2693                },
2694                PaymentPathEdge {
2695                    node_id: vec![3],
2696                    short_channel_id: "16000000x0x18087".into(),
2697                    channel_delay: 40,
2698                    base_fee_msat: 0,
2699                    fee_per_millionth: 2000,
2700                },
2701            ],
2702        };
2703        let (r, sent) = convert_to_send_pay_route(path, 50000000, 144);
2704        assert_eq!(
2705            r,
2706            vec![
2707                pb::cln::SendpayRoute {
2708                    amount_msat: Some(gl_client::pb::cln::Amount { msat: 50100000 }),
2709                    id: vec![1],
2710                    delay: 218,
2711                    channel: "807189x2048x0".into(),
2712                },
2713                pb::cln::SendpayRoute {
2714                    amount_msat: Some(gl_client::pb::cln::Amount { msat: 50100000 }),
2715                    id: vec![2],
2716                    delay: 184,
2717                    channel: "811871x2726x1".into(),
2718                },
2719                pb::cln::SendpayRoute {
2720                    amount_msat: Some(gl_client::pb::cln::Amount { msat: 50000000 }),
2721                    id: vec![3],
2722                    delay: 144,
2723                    channel: "16000000x0x18087".into(),
2724                }
2725            ]
2726        );
2727        assert_eq!(sent, 50100000);
2728
2729        Ok(())
2730    }
2731
2732    #[test]
2733    fn test_channel_states() -> Result<()> {
2734        for s in &[Openingd, ChanneldAwaitingLockin] {
2735            let c: models::Channel = cln_channel(s).into();
2736            assert_eq!(c.state, models::ChannelState::PendingOpen);
2737        }
2738
2739        let s = ChanneldNormal;
2740        let c: models::Channel = cln_channel(&s).into();
2741        assert_eq!(c.state, models::ChannelState::Opened);
2742
2743        for s in &[
2744            ChanneldShuttingDown,
2745            ClosingdSigexchange,
2746            ClosingdComplete,
2747            AwaitingUnilateral,
2748            FundingSpendSeen,
2749        ] {
2750            let c: models::Channel = cln_channel(s).into();
2751            assert_eq!(c.state, models::ChannelState::PendingClose);
2752        }
2753
2754        let c: models::Channel = cln_channel(&Onchain).into();
2755        assert_eq!(c.state, models::ChannelState::PendingClose);
2756
2757        Ok(())
2758    }
2759
2760    fn cln_channel(state: &ListpeerchannelsChannelsState) -> cln::ListpeerchannelsChannels {
2761        cln::ListpeerchannelsChannels {
2762            state: Some((*state).into()),
2763            scratch_txid: None,
2764            feerate: None,
2765            owner: None,
2766            short_channel_id: None,
2767            channel_id: None,
2768            funding_txid: None,
2769            funding_outnum: None,
2770            initial_feerate: None,
2771            last_feerate: None,
2772            next_feerate: None,
2773            next_fee_step: None,
2774            inflight: vec![],
2775            close_to: None,
2776            private: Some(true),
2777            opener: Some(0),
2778            closer: None,
2779            funding: None,
2780            to_us_msat: None,
2781            min_to_us_msat: None,
2782            max_to_us_msat: None,
2783            total_msat: Some(Amount { msat: 1_000 }),
2784            fee_base_msat: None,
2785            fee_proportional_millionths: None,
2786            dust_limit_msat: Some(Amount { msat: 10 }),
2787            max_total_htlc_in_msat: None,
2788            their_reserve_msat: None,
2789            our_reserve_msat: None,
2790            spendable_msat: Some(Amount { msat: 20_000 }),
2791            receivable_msat: Some(Amount { msat: 960_000 }),
2792            minimum_htlc_in_msat: None,
2793            minimum_htlc_out_msat: None,
2794            maximum_htlc_out_msat: None,
2795            their_to_self_delay: Some(144),
2796            our_to_self_delay: Some(144),
2797            max_accepted_htlcs: None,
2798            alias: None,
2799            status: vec![],
2800            in_payments_offered: None,
2801            in_offered_msat: None,
2802            in_payments_fulfilled: None,
2803            in_fulfilled_msat: None,
2804            out_payments_offered: None,
2805            out_offered_msat: None,
2806            out_payments_fulfilled: None,
2807            out_fulfilled_msat: None,
2808            htlcs: vec![],
2809            close_to_addr: None,
2810            peer_id: None,
2811            peer_connected: None,
2812            updates: None,
2813            ignore_fee_limits: None,
2814            lost_state: None,
2815            last_stable_connection: None,
2816        }
2817    }
2818}