@@ -208,9 +208,13 @@ pub async fn run(config: Config, pool: SqlitePool, http: reqwest::Client) {
208208/// Build or refresh the PIVK cache when the merchant set changes.
209209/// Compares merchant IDs (not just count) so additions, deletions,
210210/// or replacements all trigger a rebuild.
211+ /// When `fee_ufvk` is set, a synthetic "__platform_fee__" entry is
212+ /// appended so settlement invoice payments to `fee_address` are
213+ /// decrypted and matched like any other invoice.
211214fn refresh_key_cache < ' a > (
212215 cache : & ' a mut Option < KeyCache > ,
213216 merchants : & [ crate :: merchants:: Merchant ] ,
217+ fee_ufvk : Option < & str > ,
214218) -> & ' a [ ( String , decrypt:: CachedKeys ) ] {
215219 let current_ids: Vec < String > = merchants. iter ( ) . map ( |m| m. id . clone ( ) ) . collect ( ) ;
216220
@@ -220,13 +224,19 @@ fn refresh_key_cache<'a>(
220224 } ;
221225
222226 if needs_refresh {
223- let mut keys = Vec :: with_capacity ( merchants. len ( ) ) ;
227+ let mut keys = Vec :: with_capacity ( merchants. len ( ) + 1 ) ;
224228 for m in merchants {
225229 match decrypt:: prepare_keys ( & m. ufvk ) {
226230 Ok ( k) => keys. push ( ( m. id . clone ( ) , k) ) ,
227231 Err ( e) => tracing:: warn!( merchant_id = %m. id, error = %e, "Failed to prepare PIVK" ) ,
228232 }
229233 }
234+ if let Some ( ufvk) = fee_ufvk {
235+ match decrypt:: prepare_keys ( ufvk) {
236+ Ok ( k) => keys. push ( ( "__platform_fee__" . to_string ( ) , k) ) ,
237+ Err ( e) => tracing:: warn!( error = %e, "Failed to prepare fee wallet PIVK" ) ,
238+ }
239+ }
230240 tracing:: info!( merchants = keys. len( ) , "PIVK cache refreshed" ) ;
231241 * cache = Some ( KeyCache {
232242 merchant_ids : current_ids,
@@ -287,11 +297,12 @@ async fn scan_mempool(
287297 }
288298
289299 let merchants = crate :: merchants:: get_all_merchants ( pool, & config. encryption_key ) . await ?;
290- if merchants. is_empty ( ) {
300+ let fee_ufvk = config. fee_ufvk . as_deref ( ) ;
301+ if merchants. is_empty ( ) && fee_ufvk. is_none ( ) {
291302 return Ok ( ( ) ) ;
292303 }
293304
294- let cached_keys = refresh_key_cache ( key_cache, & merchants) ;
305+ let cached_keys = refresh_key_cache ( key_cache, & merchants, fee_ufvk ) ;
295306
296307 let mempool_txids = mempool:: fetch_mempool_txids ( http, & config. cipherscan_api_url ) . await ?;
297308
@@ -418,11 +429,12 @@ async fn process_ws_mempool_tx(
418429 }
419430
420431 let merchants = crate :: merchants:: get_all_merchants ( pool, & config. encryption_key ) . await ?;
421- if merchants. is_empty ( ) {
432+ let fee_ufvk = config. fee_ufvk . as_deref ( ) ;
433+ if merchants. is_empty ( ) && fee_ufvk. is_none ( ) {
422434 return Ok ( ( ) ) ;
423435 }
424436
425- let cached_keys = refresh_key_cache ( key_cache, & merchants) ;
437+ let cached_keys = refresh_key_cache ( key_cache, & merchants, fee_ufvk ) ;
426438 let invoice_index = matching:: InvoiceIndex :: build ( & pending) ;
427439
428440 let mut invoice_totals: HashMap < String , ( invoices:: Invoice , i64 ) > = HashMap :: new ( ) ;
@@ -579,7 +591,7 @@ async fn scan_blocks(
579591 }
580592
581593 let merchants = crate :: merchants:: get_all_merchants ( pool, & config. encryption_key ) . await ?;
582- let cached_keys = refresh_key_cache ( key_cache, & merchants) ;
594+ let cached_keys = refresh_key_cache ( key_cache, & merchants, config . fee_ufvk . as_deref ( ) ) ;
583595 let block_txids =
584596 blocks:: fetch_block_txids ( http, & config. cipherscan_api_url , start_height, batch_end)
585597 . await ?;
0 commit comments