Skip to content

Commit 75af5ec

Browse files
committed
sdk: Implement the stop() method
1 parent 2c8e370 commit 75af5ec

File tree

5 files changed

+133
-8
lines changed

5 files changed

+133
-8
lines changed

Taskfile.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ tasks:
3434
deps:
3535
- ci-build
3636
cmds:
37+
- task: sdk:test
3738
- task: clientpy:check
3839
- task: testing:check
3940
- task: clnvm:check

libs/gl-plugin/src/requests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,10 @@ impl From<crate::pb::LspInvoiceRequest> for LspInvoiceRequest {
250250
impl TypedRequest for LspInvoiceRequest {
251251
type Response = super::responses::InvoiceResponse;
252252
fn method(&self) -> &str {
253-
// TODO Rename after the CLN rename has been deployed.
253+
// TODO Rename after the CLN rename has been deployed.
254254
// "lsps-lsps2-invoice"
255-
"lsps-jitchannel"
256-
}
255+
"lsps-jitchannel"
256+
}
257257
}
258258

259259
impl TypedRequest for LspGetinfoRequest {

libs/gl-sdk/src/credentials.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ impl Credentials {
1919
inner: DeviceCredentials::from_bytes(raw),
2020
})
2121
}
22+
23+
pub(crate) fn save(&self) -> Result<Vec<u8>, Error> {
24+
Ok(self.inner.to_bytes())
25+
}
2226
}

libs/gl-sdk/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ pub enum Error {
1414
#[error("The passphrase you provided fails the checksum")]
1515
PhraseCorrupted(),
1616

17+
#[error("Error calling the rpc: {0}")]
18+
Rpc(String),
19+
1720
#[error("Generic error: {0}")]
1821
Other(String),
1922
}

libs/gl-sdk/src/node.rs

Lines changed: 122 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
use crate::{Error, credentials::Credentials};
2-
use gl_client::node::Node as ClientNode;
1+
use crate::{credentials::Credentials, util::exec, Error};
32
use gl_client::credentials::NodeIdProvider;
3+
use gl_client::node::{Client as GlClient, ClnClient, Node as ClientNode};
4+
5+
use gl_client::pb::cln as clnpb;
6+
use tokio::sync::OnceCell;
47

58
/// The `Node` is an RPC stub representing the node running in the
69
/// cloud. It is the main entrypoint to interact with the node.
7-
#[derive(uniffi::Object)]
10+
#[derive(uniffi::Object, Clone)]
811
#[allow(unused)]
912
pub struct Node {
1013
inner: ClientNode,
14+
cln_client: OnceCell<ClnClient>,
15+
gl_client: OnceCell<GlClient>,
1116
}
1217

1318
#[uniffi::export]
@@ -18,9 +23,121 @@ impl Node {
1823
.inner
1924
.node_id()
2025
.map_err(|_e| Error::UnparseableCreds())?;
21-
let client = ClientNode::new(node_id, credentials.inner.clone())
26+
let inner = ClientNode::new(node_id, credentials.inner.clone())
2227
.expect("infallible client instantiation");
2328

24-
Ok(Node { inner: client })
29+
let cln_client = OnceCell::const_new();
30+
let gl_client = OnceCell::const_new();
31+
Ok(Node {
32+
inner,
33+
cln_client,
34+
gl_client,
35+
})
36+
}
37+
38+
pub fn stop(&self) -> Result<(), Error> {
39+
let mut cln_client = exec(self.get_cln_client())?.clone();
40+
41+
let req = clnpb::StopRequest {};
42+
43+
// It's ok, the error here is expected and should just be
44+
// telling us that we've lost the connection. This is to
45+
// be expected on shutdown, so we clamp this to success.
46+
exec(cln_client.stop(req));
47+
Ok(())
48+
}
49+
50+
/// Receive an off-chain payment.
51+
///
52+
/// This method generates a request for a payment, also called an
53+
/// invoice, that encodes all the information, including amount
54+
/// and destination, for a prospective sender to send a lightning
55+
/// payment. The invoice includes negotiation of an LSPS2 / JIT
56+
/// channel, meaning that if there is no channel sufficient to
57+
/// receive the requested funds, the node will negotiate an
58+
/// opening, and when/if executed the payment will cause a channel
59+
/// to be created, and the incoming payment to be forwarded.
60+
fn receive(
61+
&self,
62+
label: String,
63+
description: String,
64+
amount_msat: Option<u64>,
65+
) -> Result<ReceiveResponse, Error> {
66+
let mut gl_client = exec(self.get_gl_client())?.clone();
67+
68+
let req = gl_client::pb::LspInvoiceRequest {
69+
amount_msat: amount_msat.unwrap_or_default(),
70+
description: description,
71+
label: label,
72+
lsp_id: "".to_owned(),
73+
token: "".to_owned(),
74+
};
75+
let res = exec(gl_client.lsp_invoice(req))
76+
.map_err(|s| Error::Rpc(s.to_string()))?
77+
.into_inner();
78+
Ok(ReceiveResponse { bolt11: res.bolt11 })
79+
}
80+
81+
fn onchain_send(&self, req: &OnchainSendRequest) -> Result<OnchainSendResponse, Error> {
82+
unimplemented!()
83+
}
84+
fn onchain_receive(
85+
&self,
86+
addresstype: Option<AddressType>,
87+
) -> Result<OnchainReceiveResponse, Error> {
88+
unimplemented!()
89+
}
90+
91+
fn send(&self, invoice: String) -> SendResponse {
92+
unimplemented!()
93+
}
94+
}
95+
96+
// Not exported through uniffi
97+
impl Node {
98+
async fn get_gl_client<'a>(&'a self) -> Result<&'a GlClient, Error> {
99+
let inner = self.inner.clone();
100+
self.gl_client
101+
.get_or_try_init(|| async { inner.schedule::<GlClient>().await })
102+
.await
103+
.map_err(|e| Error::Rpc(e.to_string()))
104+
}
105+
106+
async fn get_cln_client<'a>(&'a self) -> Result<&'a ClnClient, Error> {
107+
let inner = self.inner.clone();
108+
109+
self.cln_client
110+
.get_or_try_init(|| async { inner.schedule::<ClnClient>().await })
111+
.await
112+
.map_err(|e| Error::Rpc(e.to_string()))
25113
}
26114
}
115+
116+
#[derive(uniffi::Object)]
117+
struct OnchainSendResponse {}
118+
119+
#[derive(uniffi::Object)]
120+
struct OnchainSendRequest {
121+
label: String,
122+
description: String,
123+
amount_msat: Option<u64>,
124+
}
125+
126+
#[derive(uniffi::Enum)]
127+
enum AddressType {
128+
BECH32,
129+
P2TR,
130+
}
131+
132+
#[derive(uniffi::Object)]
133+
struct OnchainReceiveResponse {
134+
address: String,
135+
}
136+
137+
#[derive(uniffi::Object)]
138+
struct SendResponse {}
139+
140+
#[derive(uniffi::Object)]
141+
struct ReceiveResponse {
142+
bolt11: String,
143+
}

0 commit comments

Comments
 (0)