Skip to content

Commit

Permalink
Draft send payjoin
Browse files Browse the repository at this point in the history
  • Loading branch information
DanGould committed Jul 7, 2023
1 parent 51165d8 commit 896a6d6
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
1 change: 1 addition & 0 deletions mutiny-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ nostr-sdk = { version = "0.22.0-bitcoin-v0.29", default-features = false }
cbc = { version = "0.1", features = ["alloc"] }
aes = { version = "0.8" }
jwt-compact = { version = "0.8.0-beta.1", features = ["es256k"] }
payjoin = { version = "0.8.1", features = ["send"] }

base64 = "0.13.0"
pbkdf2 = "0.11"
Expand Down
17 changes: 17 additions & 0 deletions mutiny-core/src/nodemanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,23 @@ impl<S: MutinyStorage> NodeManager<S> {
})
}

pub async fn send_payjoin(
&self,
send_to: Address,
amount: u64,
labels: Vec<String>,
fee_rate: Option<f32>, // Why not FeeRate?
pj: String,
) -> Result<Txid, MutinyError> {
if !send_to.is_valid_for_network(self.network) {
return Err(MutinyError::IncorrectNetwork(send_to.network));
}

self.wallet
.send_payjoin(send_to, amount, labels, fee_rate, pj)
.await
}

/// Sends an on-chain transaction to the given address.
/// The amount is in satoshis and the fee rate is in sat/vbyte.
///
Expand Down
53 changes: 53 additions & 0 deletions mutiny-core/src/onchain.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use anyhow::anyhow;
use payjoin::{UriExt, PjUriExt};
use std::collections::HashSet;
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering};
Expand Down Expand Up @@ -404,6 +405,58 @@ impl<S: MutinyStorage> OnChainWallet<S> {
Ok(txid)
}

pub async fn send_payjoin(
&self,
uri: String,
amount: u64,
labels: Vec<String>,
fee_rate: Option<f32>,
) -> Result<Txid, MutinyError> {
let uri = payjoin::Uri::try_from(uri)
.expect("Invalid payjoin URI")
.require_network(self.network)
.expect("Payjoin network mismatch")
.check_pj_supported()
.expect("Payjoin not supported");

let amount = uri.amount().unwrap_or(amount);

// is this finalized?
let original_psbt = self.create_signed_psbt(uri.address, amount, Some(fee_rate))?;

let pj_params = payjoin::send::Configuration::min_fee_rate_sat_per_vb(self, fee_rate);
let (req, ctx) = uri.create_pj_request(psbt, pj_params).expect("Could not create Payjoin request");

let client = reqwest::ClientBuilder::new()
.build()
.expect("Could not build HTTP client");

let &mut res = client
.post(req.url)
.body(req.body)
.header("Content-Type", "text/plain")
.send()
.await
.expect("Payjoin request failed")
.text()
.await
.expect("Could not read Payjoin response");

let mut proposal_psbt = ctx.process_response(res).expect("Could not process Payjoin response");

// TODO add original psbt input map data in place so BDK knows which scripts to sign,
// proposal_psbt only contains the sender input outpoints, not scripts, which BDK
// does not look up

// sign and finalize payjoin
let payjoin = self.wallet.read().unwrap().sign(&mut psbt, SignOptions::default())?.extract_tx();
let txid = payjoin.txid();

self.broadcast_transaction(payjoin.clone()).await?;
log_debug!(self.logger, "Payjoin broadcast! TXID: {txid}");
Ok(txid)
}

pub fn create_sweep_psbt(
&self,
spk: Script,
Expand Down

0 comments on commit 896a6d6

Please sign in to comment.