Skip to content
This repository was archived by the owner on Feb 3, 2025. It is now read-only.

Commit aa4aab5

Browse files
committed
Persist payjoin sessions
1 parent 9eb5f94 commit aa4aab5

3 files changed

Lines changed: 56 additions & 1 deletion

File tree

mutiny-core/src/lib.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
type_alias_bounds
99
)]
1010
extern crate core;
11+
extern crate payjoin as pj;
1112

1213
pub mod auth;
1314
mod chain;
@@ -30,6 +31,7 @@ mod node;
3031
pub mod nodemanager;
3132
pub mod nostr;
3233
mod onchain;
34+
mod payjoin;
3335
mod peermanager;
3436
pub mod scorer;
3537
pub mod sql;
@@ -46,6 +48,7 @@ pub use crate::gossip::{GOSSIP_SYNC_TIME_KEY, NETWORK_GRAPH_KEY, PROB_SCORER_KEY
4648
pub use crate::keymanager::generate_seed;
4749
pub use crate::ldkstorage::{CHANNEL_MANAGER_KEY, MONITORS_PREFIX_KEY};
4850

51+
use crate::payjoin::PayjoinStorage;
4952
use crate::storage::{MutinyStorage, DEVICE_ID_KEY, EXPECTED_NETWORK_KEY, NEED_FULL_SYNC_KEY};
5053
use crate::{auth::MutinyAuthClient, logging::MutinyLogger};
5154
use crate::{error::MutinyError, nostr::ReservedProfile};
@@ -661,6 +664,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
661664
// when we restart, gen a new session id
662665
self.node_manager = Arc::new(nm_builder.build().await?);
663666
NodeManager::start_sync(self.node_manager.clone());
667+
NodeManager::resume_payjoins(self.node_manager.clone());
664668

665669
Ok(())
666670
}
@@ -929,7 +933,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
929933
.await
930934
.unwrap();
931935

932-
let mut enroller = payjoin::receive::v2::Enroller::from_relay_config(
936+
let mut enroller = pj::receive::v2::Enroller::from_relay_config(
933937
PAYJOIN_DIR,
934938
&ohttp_config_base64,
935939
OHTTP_RELAYS[0], // TODO pick ohttp relay at random
@@ -948,6 +952,10 @@ impl<S: MutinyStorage> MutinyWallet<S> {
948952
.process_res(ohttp_response.as_ref(), context)
949953
.map_err(|e| anyhow!("parse error {}", e))
950954
.unwrap();
955+
self.node_manager
956+
.storage
957+
.persist_payjoin(enrolled.clone())
958+
.unwrap();
951959
let pj_uri = enrolled.fallback_target();
952960
log_debug!(self.logger, "{pj_uri}");
953961
let wallet = self.node_manager.wallet.clone();

mutiny-core/src/nodemanager.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::event::{HTLCStatus, PaymentInfo};
22
use crate::labels::LabelStorage;
33
use crate::logging::LOGGING_KEY;
4+
use crate::payjoin::PayjoinStorage;
45
use crate::utils::{sleep, spawn};
56
use crate::ActivityItem;
67
use crate::MutinyWalletConfig;
@@ -688,6 +689,19 @@ impl<S: MutinyStorage> NodeManager<S> {
688689
Ok(())
689690
}
690691

692+
/// Starts a background task to poll payjoin sessions to attempt receiving.
693+
pub(crate) fn resume_payjoins(nm: Arc<NodeManager<S>>) {
694+
let all = nm.storage.get_payjoins().unwrap_or_default();
695+
for payjoin in all {
696+
let wallet = nm.wallet.clone();
697+
let stop = nm.stop.clone();
698+
utils::spawn(async move {
699+
let pj_txid = Self::receive_payjoin(wallet, stop, payjoin).await.unwrap();
700+
log::info!("Received payjoin txid: {}", pj_txid);
701+
});
702+
}
703+
}
704+
691705
/// Creates a background process that will sync the wallet with the blockchain.
692706
/// This will also update the fee estimates every 10 minutes.
693707
pub fn start_sync(nm: Arc<NodeManager<S>>) {

mutiny-core/src/payjoin.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use crate::error::MutinyError;
2+
use crate::storage::MutinyStorage;
3+
use bitcoin::hashes::hex::ToHex;
4+
use payjoin::receive::v2::Enrolled;
5+
use std::collections::HashMap;
6+
7+
pub trait PayjoinStorage {
8+
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Enrolled>, MutinyError>;
9+
fn get_payjoins(&self) -> Result<Vec<Enrolled>, MutinyError>;
10+
fn persist_payjoin(&self, session: Enrolled) -> Result<(), MutinyError>;
11+
}
12+
13+
const PAYJOIN_KEY_PREFIX: &str = "payjoin/";
14+
15+
fn get_payjoin_key(id: &[u8; 33]) -> String {
16+
format!("{PAYJOIN_KEY_PREFIX}{}", id.to_hex())
17+
}
18+
19+
impl<S: MutinyStorage> PayjoinStorage for S {
20+
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Enrolled>, MutinyError> {
21+
let sessions = self.get_data(get_payjoin_key(id))?;
22+
Ok(sessions)
23+
}
24+
25+
fn get_payjoins(&self) -> Result<Vec<Enrolled>, MutinyError> {
26+
let map: HashMap<String, Enrolled> = self.scan(PAYJOIN_KEY_PREFIX, None)?;
27+
Ok(map.values().map(|v| v.to_owned()).collect())
28+
}
29+
30+
fn persist_payjoin(&self, session: Enrolled) -> Result<(), MutinyError> {
31+
self.set_data(get_payjoin_key(&session.pubkey()), session, None)
32+
}
33+
}

0 commit comments

Comments
 (0)