@@ -67,9 +67,18 @@ pub struct SessionHistory {
6767}
6868
6969impl SessionHistory {
70+ /// Fallback transaction from the session if present
71+ pub fn fallback_tx ( & self ) -> Option < bitcoin:: Transaction > {
72+ self . events . iter ( ) . find_map ( |event| match event {
73+ SessionEvent :: CreatedReplyKey ( proposal) =>
74+ Some ( proposal. v1 . psbt . clone ( ) . extract_tx_unchecked_fee_rate ( ) ) ,
75+ _ => None ,
76+ } )
77+ }
78+
7079 pub fn endpoint ( & self ) -> Option < & Url > {
7180 self . events . iter ( ) . find_map ( |event| match event {
72- SessionEvent :: V2GetContext ( ctx ) => Some ( & ctx . endpoint ) ,
81+ SessionEvent :: CreatedReplyKey ( proposal ) => Some ( & proposal . v1 . endpoint ) ,
7382 _ => None ,
7483 } )
7584 }
@@ -94,9 +103,14 @@ mod tests {
94103
95104 use super :: * ;
96105 use crate :: output_substitution:: OutputSubstitution ;
97- use crate :: send:: v2:: HpkeContext ;
106+ use crate :: persist:: test_utils:: InMemoryTestPersister ;
107+ use crate :: send:: v1:: SenderBuilder ;
108+ use crate :: send:: v2:: { HpkeContext , Sender } ;
98109 use crate :: send:: { v1, PsbtContext } ;
99- use crate :: HpkeKeyPair ;
110+ use crate :: { HpkeKeyPair , Uri , UriExt } ;
111+
112+ const PJ_URI : & str =
113+ "bitcoin:2N47mmrWXsNBvQR6k78hWJoTji57zXwNcU7?amount=0.02&pjos=0&pj=HTTPS://EXAMPLE.COM/" ;
100114
101115 #[ test]
102116 fn test_sender_session_event_serialization_roundtrip ( ) {
@@ -140,4 +154,57 @@ mod tests {
140154 assert_eq ! ( event, deserialized) ;
141155 }
142156 }
157+
158+ struct SessionHistoryExpectedOutcome {
159+ fallback_tx : Option < bitcoin:: Transaction > ,
160+ endpoint : Option < Url > ,
161+ }
162+
163+ struct SessionHistoryTest {
164+ events : Vec < SessionEvent > ,
165+ expected_session_history : SessionHistoryExpectedOutcome ,
166+ expected_sender_state : SenderTypeState ,
167+ }
168+
169+ fn run_session_history_test ( test : SessionHistoryTest ) {
170+ let persister = InMemoryTestPersister :: < SessionEvent > :: default ( ) ;
171+ for event in test. events {
172+ persister. save_event ( & event) . expect ( "In memory persister shouldn't fail" ) ;
173+ }
174+
175+ let ( sender, session_history) =
176+ replay_event_log ( & persister) . expect ( "In memory persister shouldn't fail" ) ;
177+ assert_eq ! ( sender, test. expected_sender_state) ;
178+ assert_eq ! ( session_history. fallback_tx( ) , test. expected_session_history. fallback_tx) ;
179+ assert_eq ! ( session_history. endpoint( ) . cloned( ) , test. expected_session_history. endpoint) ;
180+ }
181+
182+ #[ test]
183+ fn test_sender_session_history_with_reply_key_event ( ) {
184+ let psbt = PARSED_ORIGINAL_PSBT . clone ( ) ;
185+ let sender = SenderBuilder :: new (
186+ psbt. clone ( ) ,
187+ Uri :: try_from ( PJ_URI )
188+ . expect ( "Valid uri" )
189+ . assume_checked ( )
190+ . check_pj_supported ( )
191+ . expect ( "Payjoin to be supported" ) ,
192+ )
193+ . build_recommended ( FeeRate :: BROADCAST_MIN )
194+ . unwrap ( ) ;
195+ let reply_key = HpkeKeyPair :: gen_keypair ( ) ;
196+ let endpoint = sender. endpoint ( ) . clone ( ) ;
197+ let fallback_tx = sender. psbt . clone ( ) . extract_tx_unchecked_fee_rate ( ) ;
198+ let with_reply_key = WithReplyKey { v1 : sender, reply_key : reply_key. 0 } ;
199+ let sender = Sender { state : with_reply_key. clone ( ) } ;
200+ let test = SessionHistoryTest {
201+ events : vec ! [ SessionEvent :: CreatedReplyKey ( with_reply_key) ] ,
202+ expected_session_history : SessionHistoryExpectedOutcome {
203+ fallback_tx : Some ( fallback_tx) ,
204+ endpoint : Some ( endpoint) ,
205+ } ,
206+ expected_sender_state : SenderTypeState :: WithReplyKey ( sender) ,
207+ } ;
208+ run_session_history_test ( test) ;
209+ }
143210}
0 commit comments