2121//! [`bitmask-core`](https://github.com/diba-io/bitmask-core) BDK integration. Bring your own
2222//! wallet and http client.
2323
24+ use std:: fmt:: { self , Display } ;
25+
2426use bitcoin:: hashes:: { sha256, Hash } ;
25- pub use error:: { CreateRequestError , EncapsulationError } ;
27+ pub use error:: { CreateRequestError , EncapsulationError , ImplementationError } ;
2628use error:: { InternalCreateRequestError , InternalEncapsulationError } ;
2729use ohttp:: ClientResponse ;
2830use serde:: { Deserialize , Serialize } ;
@@ -32,6 +34,7 @@ use super::error::BuildSenderError;
3234use super :: * ;
3335use crate :: hpke:: { decrypt_message_b, encrypt_message_a, HpkeSecretKey } ;
3436use crate :: ohttp:: { ohttp_decapsulate, ohttp_encapsulate} ;
37+ use crate :: persist:: { Persister , Value } ;
3538use crate :: send:: v1;
3639use crate :: uri:: { ShortId , UrlExt } ;
3740use crate :: { HpkeKeyPair , HpkePublicKey , IntoUrl , OhttpKeys , PjUri , Request } ;
@@ -64,11 +67,12 @@ impl<'a> SenderBuilder<'a> {
6467 // The minfeerate parameter is set if the contribution is available in change.
6568 //
6669 // This method fails if no recommendation can be made or if the PSBT is malformed.
67- pub fn build_recommended ( self , min_fee_rate : FeeRate ) -> Result < Sender , BuildSenderError > {
68- Ok ( Sender {
70+ pub fn build_recommended ( self , min_fee_rate : FeeRate ) -> Result < NewSender , BuildSenderError > {
71+ let sender = NewSender {
6972 v1 : self . 0 . build_recommended ( min_fee_rate) ?,
7073 reply_key : HpkeKeyPair :: gen_keypair ( ) . 0 ,
71- } )
74+ } ;
75+ Ok ( sender)
7276 }
7377
7478 /// Offer the receiver contribution to pay for his input.
@@ -90,16 +94,17 @@ impl<'a> SenderBuilder<'a> {
9094 change_index : Option < usize > ,
9195 min_fee_rate : FeeRate ,
9296 clamp_fee_contribution : bool ,
93- ) -> Result < Sender , BuildSenderError > {
94- Ok ( Sender {
97+ ) -> Result < NewSender , BuildSenderError > {
98+ let sender = NewSender {
9599 v1 : self . 0 . build_with_additional_fee (
96100 max_fee_contribution,
97101 change_index,
98102 min_fee_rate,
99103 clamp_fee_contribution,
100104 ) ?,
101105 reply_key : HpkeKeyPair :: gen_keypair ( ) . 0 ,
102- } )
106+ } ;
107+ Ok ( sender)
103108 }
104109
105110 /// Perform Payjoin without incentivizing the payee to cooperate.
@@ -109,11 +114,28 @@ impl<'a> SenderBuilder<'a> {
109114 pub fn build_non_incentivizing (
110115 self ,
111116 min_fee_rate : FeeRate ,
112- ) -> Result < Sender , BuildSenderError > {
113- Ok ( Sender {
117+ ) -> Result < NewSender , BuildSenderError > {
118+ let sender = NewSender {
114119 v1 : self . 0 . build_non_incentivizing ( min_fee_rate) ?,
115120 reply_key : HpkeKeyPair :: gen_keypair ( ) . 0 ,
116- } )
121+ } ;
122+ Ok ( sender)
123+ }
124+ }
125+
126+ #[ derive( Debug ) ]
127+ pub struct NewSender {
128+ pub ( crate ) v1 : v1:: Sender ,
129+ pub ( crate ) reply_key : HpkeSecretKey ,
130+ }
131+
132+ impl NewSender {
133+ pub fn persist < P : Persister < Sender > > (
134+ & self ,
135+ persister : & mut P ,
136+ ) -> Result < P :: Token , ImplementationError > {
137+ let sender = Sender { v1 : self . v1 . clone ( ) , reply_key : self . reply_key . clone ( ) } ;
138+ Ok ( persister. save ( sender) ?)
117139 }
118140}
119141
@@ -125,7 +147,35 @@ pub struct Sender {
125147 pub ( crate ) reply_key : HpkeSecretKey ,
126148}
127149
150+ /// Opaque key type for the sender
151+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
152+ pub struct SenderToken ( Url ) ;
153+
154+ impl Display for SenderToken {
155+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result { write ! ( f, "{}" , self . 0 ) }
156+ }
157+
158+ impl From < Sender > for SenderToken {
159+ fn from ( sender : Sender ) -> Self { SenderToken ( sender. endpoint ( ) . clone ( ) ) }
160+ }
161+
162+ impl AsRef < [ u8 ] > for SenderToken {
163+ fn as_ref ( & self ) -> & [ u8 ] { self . 0 . as_str ( ) . as_bytes ( ) }
164+ }
165+
166+ impl Value for Sender {
167+ type Key = SenderToken ;
168+
169+ fn key ( & self ) -> Self :: Key { SenderToken ( self . endpoint ( ) . clone ( ) ) }
170+ }
171+
128172impl Sender {
173+ pub fn load < P : Persister < Sender > > (
174+ token : P :: Token ,
175+ persister : & P ,
176+ ) -> Result < Self , ImplementationError > {
177+ persister. load ( token) . map_err ( ImplementationError :: from)
178+ }
129179 /// Extract serialized V1 Request and Context from a Payjoin Proposal
130180 pub fn extract_v1 ( & self ) -> ( Request , v1:: V1Context ) { self . v1 . extract_v1 ( ) }
131181
0 commit comments