Skip to content

Commit

Permalink
Merge pull request #494 from breez/cln-api
Browse files Browse the repository at this point in the history
Cln API
  • Loading branch information
roeierez authored Oct 2, 2023
2 parents f79ba7c + 6e2bb18 commit 744c83e
Show file tree
Hide file tree
Showing 15 changed files with 134 additions and 123 deletions.
5 changes: 2 additions & 3 deletions libs/sdk-bindings/src/breez_sdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ dictionary UnspentTransactionOutput {
u32 outnum;
u64 amount_millisatoshi;
string address;
boolean reserved;
u32 reserved_to_block;
boolean reserved;
};

dictionary NodeState {
Expand Down Expand Up @@ -522,7 +521,7 @@ enum BuyBitcoinProvider {

dictionary SweepRequest {
string to_address;
u64 fee_rate_sats_per_vbyte;
u32 fee_rate_sats_per_vbyte;
};

dictionary SweepResponse {
Expand Down
18 changes: 7 additions & 11 deletions libs/sdk-core/src/breez_services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,14 +481,12 @@ impl BreezServices {
/// Sweep on-chain funds to the specified on-chain address, with the given feerate
pub async fn sweep(&self, request: SweepRequest) -> Result<SweepResponse> {
self.start_node().await?;
let response = self
let txid = self
.node_api
.sweep(request.to_address, request.fee_rate_sats_per_vbyte)
.await?;
self.sync().await?;
Ok(SweepResponse {
txid: response.txid,
})
Ok(SweepResponse { txid })
}

/// Fetch live rates of fiat currencies
Expand Down Expand Up @@ -1236,12 +1234,10 @@ impl BreezServices {
}
Some(outnum) => {
// Find the output tx that was used to fund the channel

let outspends = self
.chain_service
.transaction_outspends(channel.funding_txid.clone())
.await?;

let maybe_block_time = outspends.get(outnum as usize)
.and_then(|outspend| outspend.status.as_ref())
.and_then(|status| status.block_time);
Expand Down Expand Up @@ -1711,14 +1707,14 @@ impl Receiver for PaymentReceiver {
let active_channel = peer
.channels
.iter()
.find(|&c| c.state == "CHANNELD_NORMAL")
.find(|&c| c.state == ChannelState::Opened)
.ok_or_else(|| SdkError::ReceivePaymentFailed {
err: "No open channel found".into(),
})?;
let hint = match active_channel.clone().alias {
Some(aliases) => aliases.remote,
_ => active_channel.clone().short_channel_id,
};
let hint = active_channel
.clone()
.alias_remote
.unwrap_or(active_channel.clone().short_channel_id);

short_channel_id = parse_short_channel_id(&hint)?;
info!("Found channel ID: {short_channel_id} {active_channel:?}");
Expand Down
2 changes: 1 addition & 1 deletion libs/sdk-core/src/bridge_generated.io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ pub struct wire_StaticBackupRequest {
#[derive(Clone)]
pub struct wire_SweepRequest {
to_address: *mut wire_uint_8_list,
fee_rate_sats_per_vbyte: u64,
fee_rate_sats_per_vbyte: u32,
}

#[repr(C)]
Expand Down
1 change: 0 additions & 1 deletion libs/sdk-core/src/bridge_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1489,7 +1489,6 @@ impl support::IntoDart for UnspentTransactionOutput {
self.amount_millisatoshi.into_dart(),
self.address.into_dart(),
self.reserved.into_dart(),
self.reserved_to_block.into_dart(),
]
.into_dart()
}
Expand Down
127 changes: 73 additions & 54 deletions libs/sdk-core/src/greenlight/node_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use bitcoin::secp256k1::Secp256k1;
use bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey};
use ecies::utils::{aes_decrypt, aes_encrypt};
use gl_client::node::ClnClient;
use gl_client::pb::amount::Unit;
use gl_client::pb::cln::listinvoices_invoices::ListinvoicesInvoicesStatus;
use gl_client::pb::cln::listpays_pays::ListpaysPaysStatus;
use gl_client::pb::cln::{
Expand All @@ -21,7 +20,7 @@ use gl_client::pb::cln::{
StaticbackupRequest,
};
use gl_client::pb::cln::{AmountOrAny, InvoiceRequest};
use gl_client::pb::{Amount, OffChainPayment, PayStatus, Peer, WithdrawResponse};
use gl_client::pb::{OffChainPayment, PayStatus};

use gl_client::pb::cln::listpeers_peers_channels::ListpeersPeersChannelsState::*;
use gl_client::scheduler::Scheduler;
Expand Down Expand Up @@ -362,18 +361,17 @@ impl NodeAPI for Greenlight {
balance_changed: bool,
) -> Result<SyncResponse> {
info!("pull changed since {}", since_timestamp);
let mut client = self.get_client().await?;
let mut node_client = self.get_node_client().await?;

// get node info
let node_info = client
.get_info(pb::GetInfoRequest::default())
let node_info = node_client
.getinfo(pb::cln::GetinfoRequest::default())
.await?
.into_inner();

// list both off chain funds and on chain fudns
let funds = client
.list_funds(pb::ListFundsRequest::default())
let funds: pb::cln::ListfundsResponse = node_client
.list_funds(pb::cln::ListfundsRequest::default())
.await?
.into_inner();
let onchain_funds = funds.outputs;
Expand Down Expand Up @@ -433,28 +431,22 @@ impl NodeAPI for Greenlight {
if b.reserved {
return a;
}
a + amount_to_msat(&b.amount.clone().unwrap_or_default())
a + b.amount_msat.clone().unwrap_or_default().msat
});

// Collect utxos from onchain funds
let utxos = onchain_funds
.iter()
.filter_map(|list_funds_output| {
list_funds_output
.output
.map(|output| UnspentTransactionOutput {
txid: output.txid.clone(),
outnum: output.output,
amount_millisatoshi: output
.amount_msat
.as_ref()
.map(|output| UnspentTransactionOutput {
txid: output.txid.clone(),
outnum: output.outnum,
amount_millisatoshi: list_funds_output
.amount
.as_ref()
.map(amount_to_msat)
.unwrap_or_default(),
address: list_funds_output.address.clone(),
reserved: list_funds_output.reserved,
reserved_to_block: list_funds_output.reserved_to_block,
})
.map(|a| a.msat)
.unwrap_or_default(),
address: output.address.clone().unwrap_or_default(),
reserved: output.reserved,
})
.collect();

Expand All @@ -479,7 +471,7 @@ impl NodeAPI for Greenlight {
})?;

let max_allowed_to_receive_msats = max(MAX_INBOUND_LIQUIDITY_MSAT - channels_balance, 0);
let node_pubkey = hex::encode(node_info.node_id);
let node_pubkey = hex::encode(node_info.id);

// construct the node state
let node_state = NodeState {
Expand Down Expand Up @@ -566,26 +558,24 @@ impl NodeAPI for Greenlight {
Ok(())
}

async fn sweep(
&self,
to_address: String,
fee_rate_sats_per_vbyte: u64,
) -> Result<WithdrawResponse> {
let mut client = self.get_client().await?;
async fn sweep(&self, to_address: String, fee_rate_sats_per_vbyte: u32) -> Result<Vec<u8>> {
let mut client = self.get_node_client().await?;

let request = pb::WithdrawRequest {
feerate: Some(pb::Feerate {
value: Some(pb::feerate::Value::Perkw(fee_rate_sats_per_vbyte * 250)),
let request = pb::cln::WithdrawRequest {
feerate: Some(pb::cln::Feerate {
style: Some(pb::cln::feerate::Style::Perkw(
fee_rate_sats_per_vbyte * 250,
)),
}),
amount: Some(Amount {
unit: Some(Unit::All(true)),
satoshi: Some(pb::cln::AmountOrAll {
value: Some(pb::cln::amount_or_all::Value::All(true)),
}),
destination: to_address,
minconf: None,
utxos: vec![],
};

Ok(client.withdraw(request).await?.into_inner())
Ok(client.withdraw(request).await?.into_inner().txid)
}

/// Starts the signer that listens in a loop until the shutdown signal is received
Expand All @@ -597,17 +587,24 @@ impl NodeAPI for Greenlight {
}

async fn list_peers(&self) -> Result<Vec<Peer>> {
let mut client = self.get_client().await?;
Ok(client
.list_peers(pb::ListPeersRequest::default())
let mut client = self.get_node_client().await?;

let res: cln::ListpeersResponse = client
.list_peers(cln::ListpeersRequest::default())
.await?
.into_inner()
.peers)
.into_inner();

let peers_models: Vec<Peer> = res.peers.into_iter().map(|p| p.into()).collect();
Ok(peers_models)
}

async fn connect_peer(&self, node_id: String, addr: String) -> Result<()> {
let mut client = self.get_client().await?;
let connect_req = pb::ConnectRequest { node_id, addr };
async fn connect_peer(&self, id: String, addr: String) -> Result<()> {
let mut client = self.get_node_client().await?;
let connect_req = pb::cln::ConnectRequest {
id: format!("{id}@{addr}"),
host: None,
port: None,
};
client.connect_peer(connect_req).await?;
Ok(())
}
Expand Down Expand Up @@ -748,9 +745,9 @@ impl NodeAPI for Greenlight {
match node_cmd {
NodeCommand::ListPeers => {
let resp = self
.get_client()
.get_node_client()
.await?
.list_peers(pb::ListPeersRequest::default())
.list_peers(pb::cln::ListpeersRequest::default())
.await?
.into_inner();
Ok(format!("{resp:?}"))
Expand All @@ -766,36 +763,36 @@ impl NodeAPI for Greenlight {
}
NodeCommand::ListFunds => {
let resp = self
.get_client()
.get_node_client()
.await?
.list_funds(pb::ListFundsRequest::default())
.list_funds(pb::cln::ListfundsRequest::default())
.await?
.into_inner();
Ok(format!("{resp:?}"))
}
NodeCommand::ListPayments => {
let resp = self
.get_client()
.get_node_client()
.await?
.list_payments(pb::ListPaymentsRequest::default())
.list_pays(pb::cln::ListpaysRequest::default())
.await?
.into_inner();
Ok(format!("{resp:?}"))
}
NodeCommand::ListInvoices => {
let resp = self
.get_client()
.get_node_client()
.await?
.list_invoices(pb::ListInvoicesRequest::default())
.list_invoices(pb::cln::ListinvoicesRequest::default())
.await?
.into_inner();
Ok(format!("{resp:?}"))
}
NodeCommand::CloseAllChannels => {
let peers_res = self
.get_client()
.get_node_client()
.await?
.list_peers(pb::ListPeersRequest::default())
.list_peers(pb::cln::ListpeersRequest::default())
.await?
.into_inner();
for p in peers_res.peers {
Expand Down Expand Up @@ -1201,6 +1198,15 @@ fn amount_to_msat(amount: &pb::Amount) -> u64 {
}
}

impl From<cln::ListpeersPeers> for Peer {
fn from(c: cln::ListpeersPeers) -> Self {
Peer {
id: c.id,
channels: c.channels.into_iter().map(|c| c.into()).collect(),
}
}
}

impl From<cln::ListpeersPeersChannels> for Channel {
fn from(c: cln::ListpeersPeersChannels) -> Self {
let state = match c.state() {
Expand All @@ -1212,6 +1218,11 @@ impl From<cln::ListpeersPeersChannels> for Channel {
_ => ChannelState::PendingClose,
};

let (alias_remote, alias_local) = match c.alias {
Some(a) => (a.remote, a.local),
None => (None, None),
};

Channel {
short_channel_id: c.short_channel_id.unwrap_or_default(),
state,
Expand All @@ -1220,6 +1231,8 @@ impl From<cln::ListpeersPeersChannels> for Channel {
receivable_msat: c.receivable_msat.unwrap_or_default().msat,
closed_at: None,
funding_outnum: c.funding_outnum,
alias_remote,
alias_local,
}
}
}
Expand All @@ -1228,6 +1241,10 @@ impl TryFrom<ListclosedchannelsClosedchannels> for Channel {
type Error = anyhow::Error;

fn try_from(c: ListclosedchannelsClosedchannels) -> std::result::Result<Self, Self::Error> {
let (alias_remote, alias_local) = match c.alias {
Some(a) => (a.remote, a.local),
None => (None, None),
};
Ok(Channel {
short_channel_id: c
.short_channel_id
Expand All @@ -1241,6 +1258,8 @@ impl TryFrom<ListclosedchannelsClosedchannels> for Channel {
receivable_msat: 0,
closed_at: None, // Don't fill at his time, because it involves a chain_service lookup
funding_outnum: Some(c.funding_outnum),
alias_remote,
alias_local,
})
}
}
Expand Down
Loading

0 comments on commit 744c83e

Please sign in to comment.