@@ -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 > ; 3 ] = [
@@ -17,10 +19,22 @@ pub(crate) static OHTTP_RELAYS: [Lazy<Url>; 3] = [
1719pub ( crate ) static PAYJOIN_DIR : Lazy < Url > =
1820 Lazy :: new ( || Url :: parse ( "https://payjo.in" ) . expect ( "Invalid URL" ) ) ;
1921
22+ #[ derive( Debug , Clone , PartialEq , Serialize , Deserialize ) ]
23+ pub struct Session {
24+ pub enrolled : Enrolled ,
25+ pub expiry : Duration ,
26+ }
27+
28+ impl Session {
29+ pub fn pubkey ( & self ) -> [ u8 ; 33 ] {
30+ self . enrolled . pubkey ( )
31+ }
32+ }
2033pub trait PayjoinStorage {
21- fn get_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < Option < Enrolled > , MutinyError > ;
22- fn get_payjoins ( & self ) -> Result < Vec < Enrolled > , MutinyError > ;
23- fn persist_payjoin ( & self , session : Enrolled ) -> Result < ( ) , MutinyError > ;
34+ fn get_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < Option < Session > , MutinyError > ;
35+ fn get_payjoins ( & self ) -> Result < Vec < Session > , MutinyError > ;
36+ fn persist_payjoin ( & self , session : Enrolled ) -> Result < Session , MutinyError > ;
37+ fn delete_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < ( ) , MutinyError > ;
2438}
2539
2640const PAYJOIN_KEY_PREFIX : & str = "payjoin/" ;
@@ -30,18 +44,28 @@ fn get_payjoin_key(id: &[u8; 33]) -> String {
3044}
3145
3246impl < S : MutinyStorage > PayjoinStorage for S {
33- fn get_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < Option < Enrolled > , MutinyError > {
47+ fn get_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < Option < Session > , MutinyError > {
3448 let sessions = self . get_data ( get_payjoin_key ( id) ) ?;
3549 Ok ( sessions)
3650 }
3751
38- fn get_payjoins ( & self ) -> Result < Vec < Enrolled > , MutinyError > {
39- let map: HashMap < String , Enrolled > = self . scan ( PAYJOIN_KEY_PREFIX , None ) ?;
52+ fn get_payjoins ( & self ) -> Result < Vec < Session > , MutinyError > {
53+ let map: HashMap < String , Session > = self . scan ( PAYJOIN_KEY_PREFIX , None ) ?;
4054 Ok ( map. values ( ) . map ( |v| v. to_owned ( ) ) . collect ( ) )
4155 }
4256
43- fn persist_payjoin ( & self , session : Enrolled ) -> Result < ( ) , MutinyError > {
44- self . set_data ( get_payjoin_key ( & session. pubkey ( ) ) , session, None )
57+ fn persist_payjoin ( & self , enrolled : Enrolled ) -> Result < Session , MutinyError > {
58+ let in_24_hours = crate :: utils:: now ( ) + Duration :: from_secs ( 60 * 60 * 24 ) ;
59+ let session = Session {
60+ enrolled,
61+ expiry : in_24_hours,
62+ } ;
63+ self . set_data ( get_payjoin_key ( & session. pubkey ( ) ) , session. clone ( ) , None )
64+ . map ( |_| session)
65+ }
66+
67+ fn delete_payjoin ( & self , id : & [ u8 ; 33 ] ) -> Result < ( ) , MutinyError > {
68+ self . delete ( & [ get_payjoin_key ( id) ] )
4569 }
4670}
4771
@@ -66,6 +90,7 @@ pub enum Error {
6690 ReceiverStateMachine ( String ) ,
6791 Txid ( bitcoin:: hashes:: hex:: Error ) ,
6892 Shutdown ,
93+ SessionExpired ,
6994}
7095
7196impl std:: error:: Error for Error { }
@@ -77,6 +102,7 @@ impl std::fmt::Display for Error {
77102 Error :: ReceiverStateMachine ( e) => write ! ( f, "Payjoin state machine error: {}" , e) ,
78103 Error :: Txid ( e) => write ! ( f, "Payjoin txid error: {}" , e) ,
79104 Error :: Shutdown => write ! ( f, "Payjoin stopped by application shutdown" ) ,
105+ Error :: SessionExpired => write ! ( f, "Payjoin session expired. Create a new payment request and have the sender try again." ) ,
80106 }
81107 }
82108}
0 commit comments