Skip to content

Commit

Permalink
Try mutiny2mutiny offers
Browse files Browse the repository at this point in the history
  • Loading branch information
benthecarman committed Oct 27, 2023
1 parent f4f9d87 commit 6209c60
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 10 deletions.
73 changes: 63 additions & 10 deletions mutiny-core/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use crate::utils::get_monitor_version;
use bitcoin::util::bip32::ExtendedPrivKey;
use lightning::events::bump_transaction::{BumpTransactionEventHandler, Wallet};
use lightning::ln::PaymentSecret;
use lightning::offers::offer::Offer;
use lightning::offers::offer::{Offer, Quantity};
use lightning::onion_message::OnionMessenger as LdkOnionMessenger;
use lightning::sign::{EntropySource, InMemorySigner, NodeSigner, Recipient};
use lightning::util::config::MaxDustHTLCExposure;
Expand Down Expand Up @@ -944,6 +944,43 @@ impl<S: MutinyStorage> Node<S> {
Ok(invoice)
}

pub async fn create_offer(
&self,
amount_sat: Option<u64>,
labels: Vec<String>,
) -> Result<Offer, MutinyError> {
// wait for first sync to complete
for _ in 0..60 {
// check if we've been stopped
if self.stop.load(Ordering::Relaxed) {
return Err(MutinyError::NotRunning);
}

if let Ok(true) = self.persister.storage.has_done_first_sync() {
break;
}

sleep(1_000).await;
}

let mut builder = self
.channel_manager
.create_offer_builder("".to_string())
.supported_quantity(Quantity::Unbounded);

if let Some(amount_sats) = amount_sat {
builder = builder.amount_msats(amount_sats * 1_000);
}

let offer = builder.build()?;

self.persister
.storage
.set_invoice_labels(offer.to_string(), labels)?;

Ok(offer)
}

pub fn get_invoice(&self, invoice: &Bolt11Invoice) -> Result<MutinyInvoice, MutinyError> {
self.get_invoice_by_hash(invoice.payment_hash())
}
Expand Down Expand Up @@ -1225,16 +1262,32 @@ impl<S: MutinyStorage> Node<S> {
getrandom::getrandom(&mut bytes).map_err(|_| MutinyError::SeedGenerationFailed)?;
let payment_id = PaymentId(bytes);

let quantity = match quantity {
None => {
if offer.expects_quantity() {
Some(1)
} else {
None
}
}
Some(q) => Some(q),
};

let amount_msats = amt_sats.map(|a| a * 1_000);
self.channel_manager.pay_for_offer(
&offer,
quantity,
amount_msats,
payer_note,
payment_id,
Self::retry_strategy(),
None,
)?;
self.channel_manager
.pay_for_offer(
&offer,
quantity,
amount_msats,
payer_note,
payment_id,
Self::retry_strategy(),
None,
)
.map_err(|e| {
log_error!(self.logger, "failed to make payment: {e:?}");
e
})?;

// persist and label offer after calling pay_for_offer, it only fails if we can't initiate a payment

Expand Down
14 changes: 14 additions & 0 deletions mutiny-core/src/nodemanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1662,6 +1662,20 @@ impl<S: MutinyStorage> NodeManager<S> {
Ok(invoice.into())
}

/// Creates a lightning offer. The amount should be in satoshis.
/// If no amount is provided, the offer will be created with no amount.
pub async fn create_offer(
&self,
from_node: &PublicKey,
amount: Option<u64>,
labels: Vec<String>,
) -> Result<Offer, MutinyError> {
let node = self.get_node(from_node).await?;
let offer = node.create_offer(amount, labels).await?;

Ok(offer)
}

/// Pays a lightning invoice from the selected node.
/// An amount should only be provided if the invoice does not have an amount.
/// The amount should be in satoshis.
Expand Down
21 changes: 21 additions & 0 deletions mutiny-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,27 @@ impl MutinyWallet {
.into())
}

/// Creates a lightning offer. The amount should be in satoshis.
/// If no amount is provided, the offer will be created with no amount.
#[wasm_bindgen]
pub async fn create_offer(
&self,
from_node: String,
amount: Option<u64>,
labels: &JsValue, /* Vec<String> */
) -> Result<String, MutinyJsError> {
let from_node = PublicKey::from_str(&from_node)?;
let labels: Vec<String> = labels
.into_serde()
.map_err(|_| MutinyJsError::InvalidArgumentsError)?;
Ok(self
.inner
.node_manager
.create_offer(&from_node, amount, labels)
.await?
.to_string())
}

/// Pays a lightning invoice from the selected node.
/// An amount should only be provided if the invoice does not have an amount.
/// The amount should be in satoshis.
Expand Down

0 comments on commit 6209c60

Please sign in to comment.