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

Commit

Permalink
Fix labeling
Browse files Browse the repository at this point in the history
  • Loading branch information
benthecarman committed Feb 5, 2024
1 parent 6285c56 commit e0553ec
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 43 deletions.
37 changes: 15 additions & 22 deletions mutiny-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1204,18 +1204,16 @@ impl<S: MutinyStorage> MutinyWallet<S> {
.get(federation_id)
.ok_or(MutinyError::NotFound)?;

let labels = vec![SWAP_LABEL.to_string()];

// if the user provided amount, this is easy
if let Some(amt) = amount {
let (inv, fee) = self.node_manager.create_invoice(amt).await?;
self.storage.set_invoice_labels(
inv.bolt11.clone().expect("just created"),
vec![SWAP_LABEL.to_string()],
)?;
let (inv, fee) = self
.node_manager
.create_invoice(amt, labels.clone())
.await?;
let pay_res = fedimint_client
.pay_invoice(
inv.bolt11.expect("create inv had one job"),
vec![SWAP_LABEL.to_string()],
)
.pay_invoice(inv.bolt11.expect("create inv had one job"), labels.clone())
.await?;
let total_fees_paid = pay_res.fees_paid.unwrap_or(0) + fee;

Expand All @@ -1239,7 +1237,10 @@ impl<S: MutinyStorage> MutinyWallet<S> {
log_debug!(self.logger, "max spendable: {}", amt);

// try to get an invoice for this exact amount
let (inv, fee) = self.node_manager.create_invoice(amt).await?;
let (inv, fee) = self
.node_manager
.create_invoice(amt, labels.clone())
.await?;

// check if we can afford that invoice
let inv_amt = inv.amount_sats.ok_or(MutinyError::BadAmountError)?;
Expand All @@ -1253,22 +1254,15 @@ impl<S: MutinyStorage> MutinyWallet<S> {
// if invoice amount changed, create a new invoice
let (inv_to_pay, fee) = if first_invoice_amount != inv_amt {
self.node_manager
.create_invoice(first_invoice_amount)
.create_invoice(first_invoice_amount, labels.clone())
.await?
} else {
(inv.clone(), fee)
};
self.storage.set_invoice_labels(
inv_to_pay.bolt11.clone().expect("just created"),
vec![SWAP_LABEL.to_string()],
)?;

log_debug!(self.logger, "attempting payment from fedimint client");
let first_invoice_res = fedimint_client
.pay_invoice(
inv_to_pay.bolt11.expect("create inv had one job"),
vec![SWAP_LABEL.to_string()],
)
.pay_invoice(inv_to_pay.bolt11.expect("create inv had one job"), labels)
.await?;

let remaining_balance = fedimint_client.get_balance().await?;
Expand Down Expand Up @@ -1362,9 +1356,8 @@ impl<S: MutinyStorage> MutinyWallet<S> {
}

// Fallback to node_manager invoice creation if no federation invoice created
let (inv, _fee) = self.node_manager.create_invoice(amount).await?;
self.storage
.set_invoice_labels(inv.bolt11.clone().expect("just created"), labels)?;
let (inv, _fee) = self.node_manager.create_invoice(amount, labels).await?;

Ok(inv)
}

Expand Down
50 changes: 42 additions & 8 deletions mutiny-core/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,7 @@ impl<S: MutinyStorage> Node<S> {
&self,
amount_sat: u64,
route_hints: Option<Vec<PhantomRouteHints>>,
labels: Vec<String>,
) -> Result<(Bolt11Invoice, u64), MutinyError> {
match self.lsp_client.as_ref() {
Some(lsp) => {
Expand Down Expand Up @@ -1093,6 +1094,7 @@ impl<S: MutinyStorage> Node<S> {
Some(amount_minus_fee),
Some(lsp_fee.fee_amount_msat),
route_hints,
labels,
)
.await?;

Expand Down Expand Up @@ -1129,8 +1131,13 @@ impl<S: MutinyStorage> Node<S> {
AnyLsp::Lsps(client) => {
if has_inbound_capacity {
Ok((
self.create_internal_invoice(Some(amount_sat), None, route_hints)
.await?,
self.create_internal_invoice(
Some(amount_sat),
None,
route_hints,
labels,
)
.await?,
0,
))
} else {
Expand All @@ -1147,6 +1154,7 @@ impl<S: MutinyStorage> Node<S> {
invoice.clone(),
Some(amount_sat * 1_000),
Some(lsp_fee.fee_amount_msat),
labels,
)
.await?;

Expand All @@ -1163,7 +1171,7 @@ impl<S: MutinyStorage> Node<S> {
}
}
None => Ok((
self.create_internal_invoice(Some(amount_sat), None, route_hints)
self.create_internal_invoice(Some(amount_sat), None, route_hints, labels)
.await?,
0,
)),
Expand All @@ -1175,6 +1183,7 @@ impl<S: MutinyStorage> Node<S> {
amount_sat: Option<u64>,
fee_amount_msat: Option<u64>,
route_hints: Option<Vec<PhantomRouteHints>>,
labels: Vec<String>,
) -> Result<Bolt11Invoice, MutinyError> {
let amount_msat = amount_sat.map(|s| s * 1_000);
// Set description to empty string to make smallest possible invoice/QR code
Expand Down Expand Up @@ -1228,7 +1237,7 @@ impl<S: MutinyStorage> Node<S> {
MutinyError::InvoiceCreationFailed
})?;

self.save_invoice_payment_info(invoice.clone(), amount_msat, fee_amount_msat)
self.save_invoice_payment_info(invoice.clone(), amount_msat, fee_amount_msat, labels)
.await?;

log_info!(self.logger, "SUCCESS: generated invoice: {invoice}");
Expand All @@ -1241,6 +1250,7 @@ impl<S: MutinyStorage> Node<S> {
invoice: Bolt11Invoice,
amount_msat: Option<u64>,
fee_amount_msat: Option<u64>,
labels: Vec<String>,
) -> Result<(), MutinyError> {
let last_update = utils::now().as_secs();
let payment_hash = PaymentHash(invoice.payment_hash().into_inner());
Expand All @@ -1265,6 +1275,8 @@ impl<S: MutinyStorage> Node<S> {
MutinyError::InvoiceCreationFailed
})?;

self.persister.storage.set_invoice_labels(invoice, labels)?;

Ok(())
}

Expand Down Expand Up @@ -2473,7 +2485,10 @@ mod tests {

let amount_sats = 1_000;

let invoice = node.create_invoice(amount_sats, None).await.unwrap().0;
let (invoice, _) = node
.create_invoice(amount_sats, None, vec![])
.await
.unwrap();

assert_eq!(invoice.amount_milli_satoshis(), Some(amount_sats * 1000));
match invoice.description() {
Expand Down Expand Up @@ -2504,7 +2519,7 @@ mod tests {
let storage = MemoryStorage::default();
let node = create_node(storage).await;

let invoice = node.create_invoice(10_000, None).await.unwrap().0;
let invoice = node.create_invoice(10_000, None, vec![]).await.unwrap().0;

let result = node
.pay_invoice_with_timeout(&invoice, None, None, vec![])
Expand Down Expand Up @@ -2599,6 +2614,7 @@ mod tests {
#[cfg(target_arch = "wasm32")]
mod wasm_test {
use crate::event::{MillisatAmount, PaymentInfo};
use crate::labels::LabelStorage;
use crate::storage::MemoryStorage;
use crate::test_utils::create_node;
use crate::HTLCStatus;
Expand Down Expand Up @@ -2626,8 +2642,13 @@ mod wasm_test {
let now = crate::utils::now().as_secs();

let amount_sats = 1_000;
let label = "test".to_string();
let labels = vec![label.clone()];

let invoice = node.create_invoice(amount_sats, None).await.unwrap().0;
let (invoice, _) = node
.create_invoice(amount_sats, None, labels.clone())
.await
.unwrap();

assert_eq!(invoice.amount_milli_satoshis(), Some(amount_sats * 1000));
match invoice.description() {
Expand All @@ -2649,16 +2670,29 @@ mod wasm_test {
assert_eq!(from_storage.amount_sats, Some(amount_sats));
assert_eq!(from_storage.status, HTLCStatus::Pending);
assert_eq!(from_storage.fees_paid, None);
assert_eq!(from_storage.labels, labels.clone());
assert!(from_storage.inbound);
assert!(from_storage.last_updated >= now);

// check labels

let invoice_labels = storage.get_invoice_labels().unwrap();
assert_eq!(invoice_labels.len(), 1);
assert_eq!(invoice_labels.get(&invoice).cloned(), Some(labels));

let label_item = storage.get_label("test").unwrap().unwrap();

assert!(label_item.last_used_time >= now);
assert!(label_item.addresses.is_empty());
assert_eq!(label_item.invoices, vec![invoice]);
}

#[test]
async fn test_fail_own_invoice() {
let storage = MemoryStorage::default();
let node = create_node(storage).await;

let invoice = node.create_invoice(10_000, None).await.unwrap().0;
let invoice = node.create_invoice(10_000, None, vec![]).await.unwrap().0;

let result = node
.pay_invoice_with_timeout(&invoice, None, None, vec![])
Expand Down
10 changes: 8 additions & 2 deletions mutiny-core/src/nodemanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1369,7 +1369,11 @@ impl<S: MutinyStorage> NodeManager<S> {
///
/// If the manager has more than one node it will create a phantom invoice.
/// If there is only one node it will create an invoice just for that node.
pub async fn create_invoice(&self, amount: u64) -> Result<(MutinyInvoice, u64), MutinyError> {
pub async fn create_invoice(
&self,
amount: u64,
labels: Vec<String>,
) -> Result<(MutinyInvoice, u64), MutinyError> {
let nodes = self.nodes.lock().await;
let use_phantom = nodes.len() > 1 && self.lsp_config.is_none();
if nodes.len() == 0 {
Expand All @@ -1392,7 +1396,9 @@ impl<S: MutinyStorage> NodeManager<S> {
} else {
return Err(MutinyError::WalletOperationFailed);
};
let invoice = first_node.create_invoice(amount, route_hints).await?;
let invoice = first_node
.create_invoice(amount, route_hints, labels)
.await?;

Ok((invoice.0.into(), invoice.1))
}
Expand Down
19 changes: 8 additions & 11 deletions mutiny-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,20 +1087,17 @@ impl MutinyWallet {
let activity = self.inner.node_manager.get_label_activity(&label).await?;
let mut activity: Vec<ActivityItem> = activity.into_iter().map(|a| a.into()).collect();

// add contact to the activity item if it is one
let Some(contact) = self.inner.node_manager.get_contact(&label)? else {
return Ok(JsValue::from_serde(&activity)?);
// add contact to the activity item it has one, otherwise return the activity list
let contact = match self.inner.node_manager.get_contact(&label)? {
Some(contact) => contact,
None => return Ok(JsValue::from_serde(&activity)?),
};

// if we have a contact, add it to the activity item, remove it as a label
// This is the same as we do in get_activity
for a in activity.iter_mut() {
// find labels that have a contact and add them to the item
for a_label in a.labels.iter() {
if label == *a_label {
a.contacts
.push(TagItem::from((a_label.clone(), contact.clone())));
}
}
// remove labels that have the contact to prevent duplicates
a.contacts
.push(TagItem::from((label.clone(), contact.clone())));
a.labels.retain(|l| l != &label);
}

Expand Down

0 comments on commit e0553ec

Please sign in to comment.