@@ -10,7 +10,10 @@ use crate::ffi::orange::Event;
1010use crate :: ffi:: orange:: config:: { Tunables , WalletConfig } ;
1111use crate :: ffi:: orange:: error:: { InitFailure , WalletError } ;
1212use crate :: { impl_from_core_type, impl_into_core_type} ;
13+
14+ use std:: pin:: Pin ;
1315use std:: sync:: Arc ;
16+ use std:: task:: { Context , Poll } ;
1417
1518/// Represents the balances of the wallet, including available and pending balances.
1619#[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord , uniffi:: Object ) ]
@@ -85,52 +88,82 @@ impl SingleUseReceiveUri {
8588impl_from_core_type ! ( OrangeSingleUseReceiveUri , SingleUseReceiveUri ) ;
8689impl_into_core_type ! ( SingleUseReceiveUri , OrangeSingleUseReceiveUri ) ;
8790
91+ // This is basically the `async-compat` utility that UniFFI uses under
92+ // the hood for its `async_runtime = "tokio"` attribute, except it lets
93+ // us use our own runtime to avoid the redundant runtimes implicit in
94+ // the `async-compat` single-threaded runtime.
95+ pin_project_lite:: pin_project! {
96+ struct RTPoller <T > {
97+ #[ pin]
98+ inner: T ,
99+ rt: Arc <tokio:: runtime:: Runtime >,
100+ }
101+ }
102+
103+ impl < T > RTPoller < T > {
104+ fn new ( inner : T , rt : Arc < tokio:: runtime:: Runtime > ) -> Self {
105+ Self { inner, rt }
106+ }
107+ }
108+
109+ impl < T : Future > Future for RTPoller < T > {
110+ type Output = T :: Output ;
111+
112+ fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
113+ let _guard = self . rt . enter ( ) ;
114+ self . project ( ) . inner . poll ( cx)
115+ }
116+ }
117+
88118#[ derive( Clone , uniffi:: Object ) ]
89119pub struct Wallet {
90120 inner : Arc < OrangeWallet > ,
91- _rt : Arc < tokio:: runtime:: Runtime > ,
121+ rt : Arc < tokio:: runtime:: Runtime > ,
92122}
93123
94- #[ uniffi:: export( async_runtime = "tokio" ) ]
124+ #[ uniffi:: export]
95125impl Wallet {
96126 #[ uniffi:: constructor]
97- pub fn new ( config : WalletConfig ) -> Result < Self , InitFailure > {
98- let rt = Arc :: new ( tokio:: runtime:: Builder :: new_multi_thread ( ) . enable_all ( ) . build ( ) ?) ;
127+ pub async fn new ( config : WalletConfig ) -> Result < Self , InitFailure > {
128+ let rt = Arc :: new (
129+ tokio:: runtime:: Builder :: new_multi_thread ( ) . worker_threads ( 2 ) . enable_all ( ) . build ( ) ?,
130+ ) ;
99131
100132 let config: OrangeWalletConfig = config. try_into ( ) ?;
101133
102- let inner = rt . block_on ( async move { OrangeWallet :: new ( config) . await } ) ?;
134+ let inner = RTPoller :: new ( OrangeWallet :: new ( config) , Arc :: clone ( & rt ) ) . await ?;
103135
104- Ok ( Wallet { inner : Arc :: new ( inner) , _rt : rt } )
136+ Ok ( Wallet { inner : Arc :: new ( inner) , rt } )
105137 }
106138
107139 pub fn node_id ( & self ) -> String {
108140 self . inner . node_id ( ) . to_string ( )
109141 }
110142
111143 pub async fn get_balance ( & self ) -> Result < Balances , WalletError > {
112- let balance = self . inner . get_balance ( ) . await ?;
144+ let balance = RTPoller :: new ( self . inner . get_balance ( ) , Arc :: clone ( & self . rt ) ) . await ?;
113145 Ok ( balance. into ( ) )
114146 }
115147
116- pub async fn is_connected_to_lsp ( & self ) -> bool {
148+ pub fn is_connected_to_lsp ( & self ) -> bool {
117149 self . inner . is_connected_to_lsp ( )
118150 }
119151
120152 /// Sets whether the wallet should automatically rebalance from trusted/onchain to lightning.
121153 pub async fn set_rebalance_enabled ( & self , value : bool ) {
122- self . inner . set_rebalance_enabled ( value) . await
154+ RTPoller :: new ( self . inner . set_rebalance_enabled ( value) , Arc :: clone ( & self . rt ) ) . await
123155 }
124156
125157 /// Whether the wallet should automatically rebalance from trusted/onchain to lightning.
126158 pub async fn get_rebalance_enabled ( & self ) -> bool {
127- self . inner . get_rebalance_enabled ( ) . await
159+ RTPoller :: new ( self . inner . get_rebalance_enabled ( ) , Arc :: clone ( & self . rt ) ) . await
128160 }
129161
130162 pub async fn list_transactions (
131163 & self ,
132164 ) -> Result < Vec < std:: sync:: Arc < crate :: ffi:: orange:: Transaction > > , WalletError > {
133- let transactions = self . inner . list_transactions ( ) . await ?;
165+ let transactions =
166+ RTPoller :: new ( self . inner . list_transactions ( ) , Arc :: clone ( & self . rt ) ) . await ?;
134167 Ok ( transactions. into_iter ( ) . map ( |tx| std:: sync:: Arc :: new ( tx. into ( ) ) ) . collect ( ) )
135168 }
136169
@@ -144,7 +177,11 @@ impl Wallet {
144177 pub async fn parse_payment_instructions (
145178 & self , instructions : String ,
146179 ) -> Result < PaymentInstructions , ParseError > {
147- let result = self . inner . parse_payment_instructions ( & instructions) . await ?;
180+ let result = RTPoller :: new (
181+ self . inner . parse_payment_instructions ( & instructions) ,
182+ Arc :: clone ( & self . rt ) ,
183+ )
184+ . await ?;
148185 Ok ( result. into ( ) )
149186 }
150187
@@ -159,7 +196,7 @@ impl Wallet {
159196 pub async fn pay (
160197 & self , payment_info : Arc < PaymentInfo > ,
161198 ) -> Result < super :: PaymentId , WalletError > {
162- let id = self . inner . pay ( & payment_info. 0 ) . await ?;
199+ let id = RTPoller :: new ( self . inner . pay ( & payment_info. 0 ) , Arc :: clone ( & self . rt ) ) . await ?;
163200 Ok ( id. into ( ) )
164201 }
165202
@@ -170,18 +207,26 @@ impl Wallet {
170207 pub async fn estimate_fee (
171208 & self , payment_info : Arc < PaymentInfo > ,
172209 ) -> Result < Arc < Amount > , WalletError > {
173- let fee = self . inner . estimate_fee ( & payment_info. 0 . instructions ) . await ;
210+ let fee = RTPoller :: new (
211+ self . inner . estimate_fee ( & payment_info. 0 . instructions ) ,
212+ Arc :: clone ( & self . rt ) ,
213+ )
214+ . await ;
174215 Ok ( Arc :: new ( fee. into ( ) ) )
175216 }
176217
177218 pub async fn stop ( & self ) {
178- self . inner . stop ( ) . await
219+ RTPoller :: new ( self . inner . stop ( ) , Arc :: clone ( & self . rt ) ) . await
179220 }
180221
181222 pub async fn get_single_use_receive_uri (
182223 & self , amount : Option < Arc < Amount > > ,
183224 ) -> Result < SingleUseReceiveUri , WalletError > {
184- let uri = self . inner . get_single_use_receive_uri ( amount. map ( |a| a. 0 ) ) . await ?;
225+ let uri = RTPoller :: new (
226+ self . inner . get_single_use_receive_uri ( amount. map ( |a| a. 0 ) ) ,
227+ Arc :: clone ( & self . rt ) ,
228+ )
229+ . await ?;
185230 Ok ( uri. into ( ) )
186231 }
187232
@@ -192,7 +237,7 @@ impl Wallet {
192237
193238 /// List our current channels
194239 pub async fn close_channels ( & self ) -> Result < ( ) , WalletError > {
195- self . inner . close_channels ( ) . await ?;
240+ RTPoller :: new ( self . inner . close_channels ( ) , Arc :: clone ( & self . rt ) ) . await ?;
196241 Ok ( ( ) )
197242 }
198243
@@ -230,7 +275,7 @@ impl Wallet {
230275 /// **Caution:** Users must handle events as quickly as possible to prevent a large event backlog,
231276 /// which can increase the memory footprint of [`crate::Wallet`].
232277 pub async fn next_event_async ( & self ) -> Event {
233- self . inner . next_event_async ( ) . await . into ( )
278+ RTPoller :: new ( self . inner . next_event_async ( ) , Arc :: clone ( & self . rt ) ) . await . into ( )
234279 }
235280
236281 /// Returns the next event in the event queue.
0 commit comments