diff --git a/src/monero/subscriptions.rs b/src/monero/subscriptions.rs index 04aa275..6e19135 100644 --- a/src/monero/subscriptions.rs +++ b/src/monero/subscriptions.rs @@ -25,7 +25,12 @@ use crate::models::{ }, users::queries::get_user_by_id, }; -use super::wallet::{send_monero, DEFAULT_ACCOUNT, MoneroError}; +use super::wallet::{ + get_subaddress_balance, + send_monero, + DEFAULT_ACCOUNT, + MoneroError, +}; const INVOICE_TIMEOUT: i64 = 30 * 60; // 30 minutes @@ -108,17 +113,14 @@ pub async fn check_monero_subscriptions( for invoice in paid_invoices { let address = Address::from_str(&invoice.payment_address)?; let address_index = wallet_client.get_address_index(address).await?; - let balance_data = wallet_client.get_balance( - address_index.major, - Some(vec![address_index.minor]), + let balance_data = get_subaddress_balance( + &wallet_client, + &address_index, ).await?; - let unlocked_balance = if let [subaddress_data] = &balance_data.per_subaddress[..] { - subaddress_data.unlocked_balance - } else { - return Err(MoneroError::OtherError("invalid response from wallet")); - }; - if unlocked_balance == Amount::ZERO { - // Not ready for forwarding + if balance_data.balance != balance_data.unlocked_balance || + balance_data.balance == Amount::ZERO + { + // Don't forward payment until all outputs are unlocked continue; }; let sender = get_profile_by_id(db_client, &invoice.sender_id).await?; diff --git a/src/monero/wallet.rs b/src/monero/wallet.rs index 9e5fc1b..795da50 100644 --- a/src/monero/wallet.rs +++ b/src/monero/wallet.rs @@ -1,13 +1,15 @@ use monero_rpc::{ RpcClient, + SubaddressBalanceData, SweepAllArgs, TransferPriority, WalletClient, }; use monero_rpc::monero::{ + cryptonote::subaddress::Index, + util::address::Error as AddressError, Address, Amount, - util::address::Error as AddressError, }; use crate::config::MoneroConfig; @@ -64,6 +66,18 @@ fn get_single_item(items: Vec) -> Result { } } +pub async fn get_subaddress_balance( + wallet_client: &WalletClient, + subaddress_index: &Index, +) -> Result { + let balance_data = wallet_client.get_balance( + subaddress_index.major, + Some(vec![subaddress_index.minor]), + ).await?; + let subaddress_data = get_single_item(balance_data.per_subaddress)?; + Ok(subaddress_data) +} + /// http://monerotoruzizulg5ttgat2emf4d6fbmiea25detrmmy7erypseyteyd.onion/resources/developer-guides/wallet-rpc.html#sweep_all pub async fn send_monero( wallet_client: &WalletClient,