1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//! # LNSocket
//!
//! `lnsocket` is a minimal, async Lightning Network socket library built on `tokio`.
//! It implements the BOLT 8 Noise handshake and typed Lightning wire framing, and
//! it stays out of your way: no global state, no TLS, no heavy deps.
//!
//! ## What this crate gives you
//! - **`LNSocket`** – connect over TCP, perform Noise (act1/2/3), and read/write typed BOLT#1 messages.
//! - **`CommandoClient`** – a small client for Core Lightning **Commando** over a live `LNSocket`,
//! with a background pump, **auto-reconnect**, and **retry/resend** semantics.
//!
//! ## Design philosophy
//! - Keep the transport tight and explicit. You own key management, policies, and backpressure.
//! - Avoid surprises: I/O errors return an `Error` that carries **`io::ErrorKind`** only.
//!
//! ## Quick starts
//!
//! ### Low-level: just a Lightning socket
//! ```no_run
//! use bitcoin::secp256k1::{SecretKey, PublicKey, rand};
//! use lnsocket::{LNSocket, ln::msgs};
//! # async fn demo(their_pubkey: PublicKey) -> Result<(), lnsocket::Error> {
//! let our_key = SecretKey::new(&mut rand::thread_rng());
//! let mut sock = LNSocket::connect_and_init(our_key, their_pubkey, "node.example.com:9735").await?;
//! sock.write(&msgs::Ping { ponglen: 4, byteslen: 8 }).await?;
//! let _msg = sock.read().await?; // e.g. expect a Pong
//! # Ok(()) }
//! ```
//!
//! ### Higher-level: Commando over LNSocket
//! ```no_run
//! use bitcoin::secp256k1::{SecretKey, PublicKey, rand};
//! use lnsocket::{LNSocket, CommandoClient};
//! use serde_json::json;
//! # async fn demo(their_pubkey: PublicKey, rune: &str) -> Result<(), lnsocket::Error> {
//! let key = SecretKey::new(&mut rand::thread_rng());
//! let sock = LNSocket::connect_and_init(key, their_pubkey, "ln.example.com:9735").await?;
//!
//! // Spawns a background pump task. IDs are generated internally.
//! let commando = CommandoClient::spawn(sock, rune);
//!
//! // Simple call with crate defaults (30s timeout, auto-reconnect, retry up to 3 times).
//! let info = commando.call("getinfo", json!({})).await?;
//! println!("getinfo: {}", info);
//! # Ok(()) }
//! ```
//!
//! ## Footguns & non-goals
//! - No built-in keepalives/backpressure – handle in your app.
//! - Reconnection logic lives in `CommandoClient`, **not** `LNSocket`.
//! - `LNSocket::perform_init` performs a minimal `init` exchange by design.
pub use bitcoin;
pub use ;
pub use ;
pub use LNSocket;
/// IO utilities public only for use by in-crate macros. These should not be used externally
///
/// This is not exported to bindings users as it is not intended for public consumption.