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

Commit 570cdc7

Browse files
Cleanup and handle tags without persisting first
1 parent 4d15602 commit 570cdc7

3 files changed

Lines changed: 61 additions & 79 deletions

File tree

mutiny-core/src/federation.rs

Lines changed: 50 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ use crate::{
1111
storage::{
1212
delete_transaction_details, get_transaction_details, list_payment_info,
1313
persist_payment_info, persist_transaction_details, MutinyStorage, VersionedValue,
14-
TRANSACTION_DETAILS_PREFIX_KEY,
1514
},
1615
utils::sleep,
1716
HTLCStatus, MutinyInvoice, DEFAULT_PAYMENT_TIMEOUT,
1817
};
18+
use crate::{labels::LabelStorage, storage::TRANSACTION_DETAILS_PREFIX_KEY};
1919
use async_lock::RwLock;
2020
use async_trait::async_trait;
2121
use bdk_chain::ConfirmationTime;
@@ -428,14 +428,14 @@ impl<S: MutinyStorage> FederationClient<S> {
428428
.map(|(h, _i)| h.0),
429429
);
430430

431-
// pending on chain operations
432-
let pending_wallet_txids = self
431+
// confirmed on chain operations
432+
let confirmed_wallet_txids = self
433433
.storage
434434
.scan::<TransactionDetails>(TRANSACTION_DETAILS_PREFIX_KEY, None)?
435435
.into_iter()
436436
.filter(|(_k, v)| match v.confirmation_time {
437-
ConfirmationTime::Unconfirmed { .. } => true, // return all unconfirmed transactions
438-
_ => false, // skip confirmed transactions
437+
ConfirmationTime::Unconfirmed { .. } => false, // skip unconfirmed transactions
438+
ConfirmationTime::Confirmed { .. } => true, // return all confirmed transactions
439439
})
440440
.map(|(_h, i)| i.internal_id)
441441
.collect::<HashSet<Txid>>();
@@ -472,7 +472,8 @@ impl<S: MutinyStorage> FederationClient<S> {
472472
.map_err(|_| MutinyError::ChainAccessFailed)
473473
.expect("should convert");
474474

475-
if pending_wallet_txids.contains(&internal_id) {
475+
// if already confirmed, no reason to subscribe
476+
if !confirmed_wallet_txids.contains(&internal_id) {
476477
self.subscribe_operation(entry, key.operation_id);
477478
}
478479
} else {
@@ -574,23 +575,13 @@ impl<S: MutinyStorage> FederationClient<S> {
574575
.get_deposit_address(fedimint_core::time::now() + PEG_IN_TIMEOUT_YEAR, ())
575576
.await?;
576577

577-
let internal_id = Txid::from_slice(&op_id.0).map_err(|_| MutinyError::ChainAccessFailed)?;
578-
579-
// persist the data we can while we wait for the transaction to come from fedimint
580-
let pending_transaction_details = TransactionDetails {
581-
transaction: None,
582-
txid: None,
583-
internal_id,
584-
received: 0,
585-
sent: 0,
586-
fee: None,
587-
confirmation_time: ConfirmationTime::Unconfirmed {
588-
last_seen: now().as_secs(),
589-
},
590-
labels,
591-
};
578+
let address = Address::from_str(&address.to_string())
579+
.expect("should convert")
580+
.assume_checked();
592581

593-
persist_transaction_details(&self.storage, &pending_transaction_details)?;
582+
// persist the labels
583+
self.storage
584+
.set_address_labels(address.clone(), labels.clone())?;
594585

595586
// subscribe
596587
let operation = self
@@ -601,9 +592,7 @@ impl<S: MutinyStorage> FederationClient<S> {
601592
.expect("just created it");
602593
self.subscribe_operation(operation, op_id);
603594

604-
Ok(Address::from_str(&address.to_string())
605-
.expect("should convert")
606-
.assume_checked())
595+
Ok(address)
607596
}
608597

609598
/// Get the balance of this federation client in sats
@@ -732,7 +721,7 @@ impl<S: MutinyStorage> FederationClient<S> {
732721
amount: u64,
733722
labels: Vec<String>,
734723
) -> Result<Txid, MutinyError> {
735-
let address = bitcoin30_to_bitcoin29_address(send_to);
724+
let address = bitcoin30_to_bitcoin29_address(send_to.clone());
736725

737726
let btc_amount = fedimint_ln_common::bitcoin::Amount::from_sat(amount);
738727

@@ -760,11 +749,14 @@ impl<S: MutinyStorage> FederationClient<S> {
760749
confirmation_time: ConfirmationTime::Unconfirmed {
761750
last_seen: now().as_secs(),
762751
},
763-
labels,
752+
labels: labels.clone(),
764753
};
765754

766755
persist_transaction_details(&self.storage, &pending_transaction_details)?;
767756

757+
// persist the labels
758+
self.storage.set_address_labels(send_to, labels)?;
759+
768760
// subscribe
769761
let operation = self
770762
.fedimint_client
@@ -1301,24 +1293,25 @@ async fn process_operation_until_timeout<S: MutinyStorage>(
13011293
} else if module_type == WalletCommonInit::KIND.as_str() {
13021294
let wallet_meta: WalletOperationMeta = entry.meta();
13031295
let wallet_module = Arc::new(fedimint_client.get_first_module::<WalletClientModule>());
1304-
let internal_id = Txid::from_slice(&operation_id.0)
1305-
.map_err(|_| MutinyError::ChainAccessFailed)
1306-
.expect("should convert");
1307-
let stored_transaction_details = get_transaction_details(&storage, internal_id, &logger);
1308-
if stored_transaction_details.is_none() {
1309-
log_warn!(logger, "could not find transaction details: {internal_id}")
1310-
}
13111296

13121297
match wallet_meta.variant {
13131298
fedimint_wallet_client::WalletOperationMetaVariant::Deposit {
1314-
address: _,
1299+
address,
13151300
expires_at: _,
13161301
} => {
13171302
match wallet_module.subscribe_deposit_updates(operation_id).await {
13181303
Ok(o) => {
1304+
let labels = match storage.get_address_labels() {
1305+
Ok(l) => l.get(&address.to_string()).cloned(),
1306+
Err(e) => {
1307+
log_warn!(logger, "could not get labels: {e}");
1308+
None
1309+
}
1310+
};
1311+
13191312
process_onchain_deposit_outcome(
13201313
o,
1321-
stored_transaction_details,
1314+
labels.unwrap_or_default(),
13221315
operation_id,
13231316
storage,
13241317
esplora,
@@ -1334,16 +1327,24 @@ async fn process_operation_until_timeout<S: MutinyStorage>(
13341327
};
13351328
}
13361329
fedimint_wallet_client::WalletOperationMetaVariant::Withdraw {
1337-
address: _,
1330+
address,
13381331
amount,
13391332
fee,
13401333
change: _,
13411334
} => {
13421335
match wallet_module.subscribe_withdraw_updates(operation_id).await {
13431336
Ok(o) => {
1337+
let labels = match storage.get_address_labels() {
1338+
Ok(l) => l.get(&address.to_string()).cloned(),
1339+
Err(e) => {
1340+
log_warn!(logger, "could not get labels: {e}");
1341+
None
1342+
}
1343+
};
1344+
13441345
process_onchain_withdraw_outcome(
13451346
o,
1346-
stored_transaction_details,
1347+
labels.unwrap_or_default(),
13471348
amount,
13481349
fee.amount(),
13491350
operation_id,
@@ -1479,7 +1480,7 @@ where
14791480
#[allow(clippy::too_many_arguments)]
14801481
async fn process_onchain_withdraw_outcome<S: MutinyStorage>(
14811482
stream_or_outcome: UpdateStreamOrOutcome<fedimint_wallet_client::WithdrawState>,
1482-
original_transaction_details: Option<TransactionDetails>,
1483+
labels: Vec<String>,
14831484
amount: fedimint_ln_common::bitcoin::Amount,
14841485
fee: fedimint_ln_common::bitcoin::Amount,
14851486
operation_id: OperationId,
@@ -1489,10 +1490,7 @@ async fn process_onchain_withdraw_outcome<S: MutinyStorage>(
14891490
stop: Arc<AtomicBool>,
14901491
logger: Arc<MutinyLogger>,
14911492
) {
1492-
let labels = original_transaction_details
1493-
.as_ref()
1494-
.map(|o| o.labels.clone())
1495-
.unwrap_or_default();
1493+
let internal_id = Txid::from_slice(&operation_id.0).expect("should convert");
14961494

14971495
let mut s = stream_or_outcome.into_stream();
14981496

@@ -1520,7 +1518,6 @@ async fn process_onchain_withdraw_outcome<S: MutinyStorage>(
15201518
WithdrawState::Succeeded(txid) => {
15211519
log_info!(logger, "Withdraw successful: {txid}");
15221520

1523-
let internal_id = Txid::from_slice(&operation_id.0).expect("should convert");
15241521
let txid = Txid::from_slice(&txid).expect("should convert");
15251522
let updated_transaction_details = TransactionDetails {
15261523
transaction: None,
@@ -1550,16 +1547,14 @@ async fn process_onchain_withdraw_outcome<S: MutinyStorage>(
15501547
WithdrawState::Failed(e) => {
15511548
log_error!(logger, "Transaction failed: {e}");
15521549

1553-
// if we have the original transaction details, delete it
1554-
if let Some(t) = original_transaction_details {
1555-
match delete_transaction_details(&storage, &t) {
1556-
Ok(_) => {
1557-
log_info!(logger, "Transaction deleted");
1558-
},
1559-
Err(e) => {
1560-
log_error!(logger, "Error deleting transaction: {e}");
1561-
},
1562-
}
1550+
// Delete the pending tx if it failed
1551+
match delete_transaction_details(&storage, internal_id) {
1552+
Ok(_) => {
1553+
log_info!(logger, "Transaction deleted");
1554+
},
1555+
Err(e) => {
1556+
log_error!(logger, "Error deleting transaction: {e}");
1557+
},
15631558
}
15641559

15651560
break;
@@ -1632,19 +1627,14 @@ async fn subscribe_onchain_confirmation_check<S: MutinyStorage>(
16321627
#[allow(clippy::too_many_arguments)]
16331628
async fn process_onchain_deposit_outcome<S: MutinyStorage>(
16341629
stream_or_outcome: UpdateStreamOrOutcome<fedimint_wallet_client::DepositState>,
1635-
original_transaction_details: Option<TransactionDetails>,
1630+
labels: Vec<String>,
16361631
operation_id: OperationId,
16371632
storage: S,
16381633
esplora: Arc<AsyncClient>,
16391634
timeout: Option<u64>,
16401635
stop: Arc<AtomicBool>,
16411636
logger: Arc<MutinyLogger>,
16421637
) {
1643-
let labels = original_transaction_details
1644-
.as_ref()
1645-
.map(|o| o.labels.clone())
1646-
.unwrap_or_default();
1647-
16481638
let mut s = stream_or_outcome.into_stream();
16491639

16501640
// break out after sleep time or check stop signal
@@ -1734,18 +1724,6 @@ async fn process_onchain_deposit_outcome<S: MutinyStorage>(
17341724
fedimint_wallet_client::DepositState::Failed(e) => {
17351725
log_error!(logger, "Transaction failed: {e}");
17361726

1737-
// if we have the original transaction details, delete it
1738-
if let Some(t) = original_transaction_details {
1739-
match delete_transaction_details(&storage, &t) {
1740-
Ok(_) => {
1741-
log_info!(logger, "Transaction deleted");
1742-
},
1743-
Err(e) => {
1744-
log_error!(logger, "Error deleting transaction: {e}");
1745-
},
1746-
}
1747-
}
1748-
17491727
break;
17501728
}
17511729
}

mutiny-core/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2062,7 +2062,10 @@ impl<S: MutinyStorage> MutinyWallet<S> {
20622062
}
20632063
}
20642064

2065-
async fn create_address(&self, labels: Vec<String>) -> Result<bitcoin::Address, MutinyError> {
2065+
pub async fn create_address(
2066+
&self,
2067+
labels: Vec<String>,
2068+
) -> Result<bitcoin::Address, MutinyError> {
20662069
// Attempt to create federation invoice if available
20672070
let federation_ids = self.list_federation_ids().await?;
20682071
if !federation_ids.is_empty() {

mutiny-core/src/storage.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -926,19 +926,20 @@ pub(crate) fn persist_transaction_details<S: MutinyStorage>(
926926
Ok(())
927927
}
928928

929+
// Deletes the transaction detail and removes the pending index if it exists
929930
pub(crate) fn delete_transaction_details<S: MutinyStorage>(
930931
storage: &S,
931-
transaction_details: &TransactionDetails,
932+
txid: Txid,
932933
) -> Result<(), MutinyError> {
933-
let key = transaction_details_key(transaction_details.internal_id);
934+
let key = transaction_details_key(txid);
934935
storage.delete(&[key.clone()])?;
935936

936-
// delete from index
937+
// delete the pending index item, if it exists
937938
let index = storage.activity_index();
938939
let mut index = index.try_write()?;
939-
index.insert(IndexItem {
940-
timestamp: None,
941-
key,
940+
index.remove(&IndexItem {
941+
timestamp: None, // timestamp would be None for Unconfirmed
942+
key: key.clone(),
942943
});
943944

944945
Ok(())

0 commit comments

Comments
 (0)