@@ -2,10 +2,12 @@ use std::collections::HashMap;
22
33use crate :: error:: MutinyError ;
44use crate :: storage:: MutinyStorage ;
5+ use core:: time:: Duration ;
56use hex_conservative:: DisplayHex ;
67use once_cell:: sync:: Lazy ;
78use payjoin:: receive:: v2:: Enrolled ;
89use payjoin:: OhttpKeys ;
10+ use serde:: { Deserialize , Serialize } ;
911use url:: Url ;
1012
1113pub ( crate ) static OHTTP_RELAYS : [ Lazy < Url > ; 2 ] = [
@@ -16,10 +18,22 @@ pub(crate) static OHTTP_RELAYS: [Lazy<Url>; 2] = [
1618pub ( crate ) static PAYJOIN_DIR : Lazy < Url > =
1719 Lazy :: new ( || Url :: parse ( "https://payjo.in" ) . expect ( "Invalid URL" ) ) ;
1820
21+ #[ derive( Debug , Clone , PartialEq , Serialize , Deserialize ) ]
22+ pub struct Session {
23+ pub enrolled : Enrolled ,
24+ pub expiry : Duration ,
25+ }
26+
27+ impl Session {
28+ pub fn pubkey ( & self ) -> [ u8 ; 33 ] {
29+ self . enrolled . pubkey ( )
30+ }
31+ }
1932pub trait PayjoinStorage {
20- fn get_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < Option < Enrolled > , MutinyError > ;
21- fn get_payjoins ( & self ) -> Result < Vec < Enrolled > , MutinyError > ;
22- fn persist_payjoin ( & self , session : Enrolled ) -> Result < ( ) , MutinyError > ;
33+ fn get_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < Option < Session > , MutinyError > ;
34+ fn get_payjoins ( & self ) -> Result < Vec < Session > , MutinyError > ;
35+ fn persist_payjoin ( & self , session : Enrolled ) -> Result < Session , MutinyError > ;
36+ fn delete_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < ( ) , MutinyError > ;
2337}
2438
2539const PAYJOIN_KEY_PREFIX : & str = "payjoin/" ;
@@ -29,18 +43,28 @@ fn get_payjoin_key(id: &[u8; 33]) -> String {
2943}
3044
3145impl < S : MutinyStorage > PayjoinStorage for S {
32- fn get_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < Option < Enrolled > , MutinyError > {
46+ fn get_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < Option < Session > , MutinyError > {
3347 let sessions = self . get_data ( get_payjoin_key ( id) ) ?;
3448 Ok ( sessions)
3549 }
3650
37- fn get_payjoins ( & self ) -> Result < Vec < Enrolled > , MutinyError > {
38- let map: HashMap < String , Enrolled > = self . scan ( PAYJOIN_KEY_PREFIX , None ) ?;
51+ fn get_payjoins ( & self ) -> Result < Vec < Session > , MutinyError > {
52+ let map: HashMap < String , Session > = self . scan ( PAYJOIN_KEY_PREFIX , None ) ?;
3953 Ok ( map. values ( ) . map ( |v| v. to_owned ( ) ) . collect ( ) )
4054 }
4155
42- fn persist_payjoin ( & self , session : Enrolled ) -> Result < ( ) , MutinyError > {
43- self . set_data ( get_payjoin_key ( & session. pubkey ( ) ) , session, None )
56+ fn persist_payjoin ( & self , enrolled : Enrolled ) -> Result < Session , MutinyError > {
57+ let in_24_hours = crate :: utils:: now ( ) + Duration :: from_secs ( 60 * 60 * 24 ) ;
58+ let session = Session {
59+ enrolled,
60+ expiry : in_24_hours,
61+ } ;
62+ self . set_data ( get_payjoin_key ( & session. pubkey ( ) ) , session. clone ( ) , None )
63+ . map ( |_| session)
64+ }
65+
66+ fn delete_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < ( ) , MutinyError > {
67+ self . delete ( & [ get_payjoin_key ( id) ] )
4468 }
4569}
4670
@@ -65,6 +89,7 @@ pub enum Error {
6589 ReceiverStateMachine ( String ) ,
6690 Txid ( bitcoin:: hashes:: hex:: Error ) ,
6791 Shutdown ,
92+ SessionExpired ,
6893}
6994
7095impl std:: error:: Error for Error { }
@@ -76,6 +101,7 @@ impl std::fmt::Display for Error {
76101 Error :: ReceiverStateMachine ( e) => write ! ( f, "Payjoin state machine error: {}" , e) ,
77102 Error :: Txid ( e) => write ! ( f, "Payjoin txid error: {}" , e) ,
78103 Error :: Shutdown => write ! ( f, "Payjoin stopped by application shutdown" ) ,
104+ Error :: SessionExpired => write ! ( f, "Payjoin session expired. Create a new payment request and have the sender try again." ) ,
79105 }
80106 }
81107}
0 commit comments