@@ -11,7 +11,7 @@ use ldk_node::payment::{ConfirmationStatus, PaymentDirection, PaymentStatus};
1111use log:: info;
1212use orange_sdk:: { Event , PaymentInfo , PaymentType , TxStatus , WalletError } ;
1313use std:: sync:: Arc ;
14- use std:: time:: Duration ;
14+ use std:: time:: { Duration , SystemTime , UNIX_EPOCH } ;
1515
1616mod test_utils;
1717
@@ -85,6 +85,67 @@ async fn test_receive_to_trusted() {
8585 . await ;
8686}
8787
88+ #[ tokio:: test( flavor = "multi_thread" ) ]
89+ #[ test_log:: test]
90+ async fn test_trusted_receive_keeps_backend_settle_time ( ) {
91+ test_utils:: run_test ( |params| async move {
92+ let wallet = Arc :: clone ( & params. wallet ) ;
93+ let third_party = Arc :: clone ( & params. third_party ) ;
94+
95+ // Disable rebalancing before the payment exists so the rebalancer does not
96+ // stamp a discovery time when it first observes the receive.
97+ wallet. set_rebalance_enabled ( false ) . await ;
98+
99+ let recv_amt = Amount :: from_sats ( 100 ) . unwrap ( ) ;
100+ assert ! ( recv_amt < wallet. get_tunables( ) . trusted_balance_limit) ;
101+
102+ let uri = wallet. get_single_use_receive_uri ( Some ( recv_amt) ) . await . unwrap ( ) ;
103+ assert ! ( uri. from_trusted) ;
104+ let payment_id = third_party. bolt11_payment ( ) . send ( & uri. invoice , None ) . unwrap ( ) ;
105+
106+ let p = Arc :: clone ( & third_party) ;
107+ test_utils:: wait_for_condition ( "payer payment success" , || {
108+ let res = p. payment ( & payment_id) . is_some_and ( |p| p. status == PaymentStatus :: Succeeded ) ;
109+ async move { res }
110+ } )
111+ . await ;
112+
113+ test_utils:: wait_for_condition ( "wallet balance update after receive" , || async {
114+ wallet. get_balance ( ) . await . unwrap ( ) . available_balance ( ) > Amount :: ZERO
115+ } )
116+ . await ;
117+
118+ // The backend has recorded the settle time ~now. Sleep so any later
119+ // discovery stamp lands a clearly later wall-clock time, then mark that
120+ // boundary just before we let the rebalancer run.
121+ tokio:: time:: sleep ( Duration :: from_secs ( 3 ) ) . await ;
122+ let enabled_at = SystemTime :: now ( ) . duration_since ( UNIX_EPOCH ) . unwrap ( ) ;
123+
124+ // Re-enable rebalancing and drain the PaymentReceived event. Handling the
125+ // event triggers the rebalancer, which observes the payment for the first
126+ // time and stamps its discovery time (>= enabled_at). Give the spawned
127+ // rebalance check a moment to record it.
128+ wallet. set_rebalance_enabled ( true ) . await ;
129+ let event = test_utils:: wait_next_event ( & wallet) . await ;
130+ assert ! ( matches!( event, Event :: PaymentReceived { .. } ) ) ;
131+ tokio:: time:: sleep ( Duration :: from_secs ( 3 ) ) . await ;
132+
133+ let txs = wallet. list_transactions ( ) . await . unwrap ( ) ;
134+ assert_eq ! ( txs. len( ) , 1 ) ;
135+ let tx = txs. into_iter ( ) . next ( ) . unwrap ( ) ;
136+
137+ // Must be the backend settle time (recorded ~3s before we re-enabled),
138+ // strictly earlier than the discovery stamp written at/after `enabled_at`.
139+ assert ! (
140+ tx. time_since_epoch < enabled_at,
141+ "expected backend settle time, got discovery stamp: {:?} >= {:?}" ,
142+ tx. time_since_epoch,
143+ enabled_at
144+ ) ;
145+ } )
146+ . await ;
147+ }
148+
88149#[ tokio:: test( flavor = "multi_thread" ) ]
89150#[ test_log:: test]
90151async fn test_pay_from_trusted ( ) {
0 commit comments