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