@@ -35,6 +35,7 @@ impl Node {
3535 } )
3636 }
3737
38+ /// Stop the node if it is currently running.
3839 pub fn stop ( & self ) -> Result < ( ) , Error > {
3940 let mut cln_client = exec ( self . get_cln_client ( ) ) ?. clone ( ) ;
4041
@@ -43,7 +44,7 @@ impl Node {
4344 // It's ok, the error here is expected and should just be
4445 // telling us that we've lost the connection. This is to
4546 // be expected on shutdown, so we clamp this to success.
46- exec ( cln_client. stop ( req) ) ;
47+ let _ = exec ( cln_client. stop ( req) ) ;
4748 Ok ( ( ) )
4849 }
4950
@@ -78,18 +79,95 @@ impl Node {
7879 Ok ( ReceiveResponse { bolt11 : res. bolt11 } )
7980 }
8081
81- fn onchain_send ( & self , req : & OnchainSendRequest ) -> Result < OnchainSendResponse , Error > {
82- unimplemented ! ( )
82+ fn send ( & self , invoice : String , amount_msat : Option < u64 > ) -> Result < SendResponse , Error > {
83+ let mut cln_client = exec ( self . get_cln_client ( ) ) ?. clone ( ) ;
84+ let req = clnpb:: PayRequest {
85+ amount_msat : match amount_msat {
86+ Some ( a) => Some ( clnpb:: Amount { msat : a } ) ,
87+ None => None ,
88+ } ,
89+
90+ bolt11 : invoice,
91+ description : None ,
92+ exclude : vec ! [ ] ,
93+ exemptfee : None ,
94+ label : None ,
95+ localinvreqid : None ,
96+ maxdelay : None ,
97+ maxfee : None ,
98+ maxfeepercent : None ,
99+ partial_msat : None ,
100+ retry_for : None ,
101+ riskfactor : None ,
102+ } ;
103+ exec ( cln_client. pay ( req) )
104+ . map_err ( |e| Error :: Rpc ( e. to_string ( ) ) )
105+ . map ( |r| r. into_inner ( ) . into ( ) )
83106 }
84- fn onchain_receive (
107+
108+ fn onchain_send (
85109 & self ,
86- addresstype : Option < AddressType > ,
87- ) -> Result < OnchainReceiveResponse , Error > {
88- unimplemented ! ( )
110+ destination : String ,
111+ amount_or_all : String ,
112+ ) -> Result < OnchainSendResponse , Error > {
113+ let mut cln_client = exec ( self . get_cln_client ( ) ) ?. clone ( ) ;
114+
115+ // Decode what the user intends to do. Either we have `all`,
116+ // or we have an amount that we can parse.
117+ let ( num, suffix) : ( String , String ) = amount_or_all. chars ( ) . partition ( |c| c. is_digit ( 10 ) ) ;
118+
119+ let num = if num. len ( ) > 0 {
120+ num. parse :: < u64 > ( ) . unwrap ( )
121+ } else {
122+ 0
123+ } ;
124+ let satoshi = match ( num, suffix. as_ref ( ) ) {
125+ ( n, "" ) | ( n, "sat" ) => clnpb:: AmountOrAll {
126+ // No value suffix, interpret as satoshis. This is an
127+ // onchain RPC method, hence the sat denomination by
128+ // default.
129+ value : Some ( clnpb:: amount_or_all:: Value :: Amount ( clnpb:: Amount {
130+ msat : n * 1000 ,
131+ } ) ) ,
132+ } ,
133+ ( n, "msat" ) => clnpb:: AmountOrAll {
134+ // No value suffix, interpret as satoshis. This is an
135+ // onchain RPC method, hence the sat denomination by
136+ // default.
137+ value : Some ( clnpb:: amount_or_all:: Value :: Amount ( clnpb:: Amount {
138+ msat : n * 1000 ,
139+ } ) ) ,
140+ } ,
141+ ( 0 , "all" ) => clnpb:: AmountOrAll {
142+ value : Some ( clnpb:: amount_or_all:: Value :: All ( true ) ) ,
143+ } ,
144+ ( _, _) => return Err ( Error :: Argument ( "amount_or_all" . to_owned ( ) , amount_or_all) ) ,
145+ } ;
146+
147+ let req = clnpb:: WithdrawRequest {
148+ destination : destination,
149+ minconf : None ,
150+ feerate : None ,
151+ satoshi : Some ( satoshi) ,
152+ utxos : vec ! [ ] ,
153+ } ;
154+
155+ exec ( cln_client. withdraw ( req) )
156+ . map_err ( |e| Error :: Rpc ( e. to_string ( ) ) )
157+ . map ( |r| r. into_inner ( ) . into ( ) )
89158 }
90159
91- fn send ( & self , invoice : String ) -> SendResponse {
92- unimplemented ! ( )
160+ fn onchain_receive ( & self ) -> Result < OnchainReceiveResponse , Error > {
161+ let mut cln_client = exec ( self . get_cln_client ( ) ) ?. clone ( ) ;
162+
163+ let req = clnpb:: NewaddrRequest {
164+ addresstype : Some ( clnpb:: newaddr_request:: NewaddrAddresstype :: All . into ( ) ) ,
165+ } ;
166+
167+ let res = exec ( cln_client. new_addr ( req) )
168+ . map_err ( |e| Error :: Rpc ( e. to_string ( ) ) ) ?
169+ . into_inner ( ) ;
170+ Ok ( res. into ( ) )
93171 }
94172}
95173
@@ -113,31 +191,92 @@ impl Node {
113191 }
114192}
115193
194+ #[ allow( unused) ]
116195#[ 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 > ,
196+ struct OnchainSendResponse {
197+ tx : Vec < u8 > ,
198+ txid : Vec < u8 > ,
199+ psbt : String ,
124200}
125201
126- #[ derive( uniffi:: Enum ) ]
127- enum AddressType {
128- BECH32 ,
129- P2TR ,
202+ impl From < clnpb:: WithdrawResponse > for OnchainSendResponse {
203+ fn from ( other : clnpb:: WithdrawResponse ) -> Self {
204+ Self {
205+ tx : other. tx ,
206+ txid : other. txid ,
207+ psbt : other. psbt ,
208+ }
209+ }
130210}
131211
212+ #[ allow( unused) ]
132213#[ derive( uniffi:: Object ) ]
133214struct OnchainReceiveResponse {
134- address : String ,
215+ bech32 : String ,
216+ p2tr : String ,
217+ }
218+
219+ impl From < clnpb:: NewaddrResponse > for OnchainReceiveResponse {
220+ fn from ( other : clnpb:: NewaddrResponse ) -> Self {
221+ OnchainReceiveResponse {
222+ bech32 : other. bech32 . unwrap_or_default ( ) ,
223+ p2tr : other. p2tr . unwrap_or_default ( ) ,
224+ }
225+ }
135226}
136227
228+ #[ allow( unused) ]
137229#[ derive( uniffi:: Object ) ]
138- struct SendResponse { }
230+ struct SendResponse {
231+ status : PayStatus ,
232+ preimage : Vec < u8 > ,
233+ amount_msat : u64 ,
234+ amount_sent_msat : u64 ,
235+ parts : u32 ,
236+ }
237+
238+ impl From < clnpb:: PayResponse > for SendResponse {
239+ fn from ( other : clnpb:: PayResponse ) -> Self {
240+ Self {
241+ status : other. status . into ( ) ,
242+ preimage : other. payment_preimage ,
243+ amount_msat : other. amount_msat . unwrap ( ) . msat ,
244+ amount_sent_msat : other. amount_sent_msat . unwrap ( ) . msat ,
245+ parts : other. parts ,
246+ }
247+ }
248+ }
139249
250+ #[ allow( unused) ]
140251#[ derive( uniffi:: Object ) ]
141252struct ReceiveResponse {
142253 bolt11 : String ,
143254}
255+
256+ #[ derive( uniffi:: Enum ) ]
257+ enum PayStatus {
258+ COMPLETE = 0 ,
259+ PENDING = 1 ,
260+ FAILED = 2 ,
261+ }
262+
263+ impl From < clnpb:: pay_response:: PayStatus > for PayStatus {
264+ fn from ( other : clnpb:: pay_response:: PayStatus ) -> Self {
265+ match other {
266+ clnpb:: pay_response:: PayStatus :: Complete => PayStatus :: COMPLETE ,
267+ clnpb:: pay_response:: PayStatus :: Failed => PayStatus :: FAILED ,
268+ clnpb:: pay_response:: PayStatus :: Pending => PayStatus :: PENDING ,
269+ }
270+ }
271+ }
272+
273+ impl From < i32 > for PayStatus {
274+ fn from ( i : i32 ) -> Self {
275+ match i {
276+ 0 => PayStatus :: COMPLETE ,
277+ 1 => PayStatus :: PENDING ,
278+ 2 => PayStatus :: FAILED ,
279+ o => panic ! ( "Unknown pay_status {}" , o) ,
280+ }
281+ }
282+ }
0 commit comments