|
@@ -55,19 +55,22 @@ const DEFAULT_REPAY_QUEUE_MAX_SIZE: usize = 100;
|
|
|
struct SecondaryRepaymentQueue {
|
|
struct SecondaryRepaymentQueue {
|
|
|
queue: Arc<Mutex<VecDeque<PaymentIdentifier>>>,
|
|
queue: Arc<Mutex<VecDeque<PaymentIdentifier>>>,
|
|
|
max_size: usize,
|
|
max_size: usize,
|
|
|
- sender: tokio::sync::mpsc::Sender<(PaymentIdentifier, Amount, String)>,
|
|
|
|
|
|
|
+ sender: tokio::sync::mpsc::Sender<WaitPaymentResponse>,
|
|
|
|
|
+ unit: CurrencyUnit,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl SecondaryRepaymentQueue {
|
|
impl SecondaryRepaymentQueue {
|
|
|
fn new(
|
|
fn new(
|
|
|
max_size: usize,
|
|
max_size: usize,
|
|
|
- sender: tokio::sync::mpsc::Sender<(PaymentIdentifier, Amount, String)>,
|
|
|
|
|
|
|
+ sender: tokio::sync::mpsc::Sender<WaitPaymentResponse>,
|
|
|
|
|
+ unit: CurrencyUnit,
|
|
|
) -> Self {
|
|
) -> Self {
|
|
|
let queue = Arc::new(Mutex::new(VecDeque::new()));
|
|
let queue = Arc::new(Mutex::new(VecDeque::new()));
|
|
|
let repayment_queue = Self {
|
|
let repayment_queue = Self {
|
|
|
queue: queue.clone(),
|
|
queue: queue.clone(),
|
|
|
max_size,
|
|
max_size,
|
|
|
sender,
|
|
sender,
|
|
|
|
|
+ unit,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// Start the background secondary repayment processor
|
|
// Start the background secondary repayment processor
|
|
@@ -101,6 +104,7 @@ impl SecondaryRepaymentQueue {
|
|
|
fn start_secondary_repayment_processor(&self) {
|
|
fn start_secondary_repayment_processor(&self) {
|
|
|
let queue = self.queue.clone();
|
|
let queue = self.queue.clone();
|
|
|
let sender = self.sender.clone();
|
|
let sender = self.sender.clone();
|
|
|
|
|
+ let unit = self.unit.clone();
|
|
|
|
|
|
|
|
tokio::spawn(async move {
|
|
tokio::spawn(async move {
|
|
|
use bitcoin::secp256k1::rand::rngs::OsRng;
|
|
use bitcoin::secp256k1::rand::rngs::OsRng;
|
|
@@ -127,7 +131,13 @@ impl SecondaryRepaymentQueue {
|
|
|
if let Some(payment) = payment_to_process {
|
|
if let Some(payment) = payment_to_process {
|
|
|
// Generate a random amount for this secondary payment (same range as initial payment: 1-1000)
|
|
// Generate a random amount for this secondary payment (same range as initial payment: 1-1000)
|
|
|
let random_amount: u64 = rng.gen_range(1..=1000);
|
|
let random_amount: u64 = rng.gen_range(1..=1000);
|
|
|
- let secondary_amount = Amount::from(random_amount);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // Create amount based on unit, ensuring minimum of 1 sat worth
|
|
|
|
|
+ let secondary_amount = match &unit {
|
|
|
|
|
+ CurrencyUnit::Sat => Amount::from(random_amount),
|
|
|
|
|
+ CurrencyUnit::Msat => Amount::from(u64::max(random_amount * 1000, 1000)),
|
|
|
|
|
+ _ => Amount::from(u64::max(random_amount, 1)), // fallback
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
// Generate a unique payment identifier for this secondary payment
|
|
// Generate a unique payment identifier for this secondary payment
|
|
|
// We'll create a new payment hash by appending a timestamp and random bytes
|
|
// We'll create a new payment hash by appending a timestamp and random bytes
|
|
@@ -157,14 +167,14 @@ impl SecondaryRepaymentQueue {
|
|
|
|
|
|
|
|
// Send the payment notification using the original payment identifier
|
|
// Send the payment notification using the original payment identifier
|
|
|
// The mint will process this through the normal payment stream
|
|
// The mint will process this through the normal payment stream
|
|
|
- if let Err(e) = sender
|
|
|
|
|
- .send((
|
|
|
|
|
- payment.clone(),
|
|
|
|
|
- secondary_amount,
|
|
|
|
|
- unique_payment_id.to_string(),
|
|
|
|
|
- ))
|
|
|
|
|
- .await
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ let secondary_response = WaitPaymentResponse {
|
|
|
|
|
+ payment_identifier: payment.clone(),
|
|
|
|
|
+ payment_amount: secondary_amount,
|
|
|
|
|
+ unit: unit.clone(),
|
|
|
|
|
+ payment_id: unique_payment_id.to_string(),
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ if let Err(e) = sender.send(secondary_response).await {
|
|
|
tracing::error!(
|
|
tracing::error!(
|
|
|
"Failed to send secondary repayment notification for {:?}: {}",
|
|
"Failed to send secondary repayment notification for {:?}: {}",
|
|
|
unique_payment_id,
|
|
unique_payment_id,
|
|
@@ -181,10 +191,8 @@ impl SecondaryRepaymentQueue {
|
|
|
#[derive(Clone)]
|
|
#[derive(Clone)]
|
|
|
pub struct FakeWallet {
|
|
pub struct FakeWallet {
|
|
|
fee_reserve: FeeReserve,
|
|
fee_reserve: FeeReserve,
|
|
|
- #[allow(clippy::type_complexity)]
|
|
|
|
|
- sender: tokio::sync::mpsc::Sender<(PaymentIdentifier, Amount, String)>,
|
|
|
|
|
- #[allow(clippy::type_complexity)]
|
|
|
|
|
- receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<(PaymentIdentifier, Amount, String)>>>>,
|
|
|
|
|
|
|
+ sender: tokio::sync::mpsc::Sender<WaitPaymentResponse>,
|
|
|
|
|
+ receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<WaitPaymentResponse>>>>,
|
|
|
payment_states: Arc<Mutex<HashMap<String, MeltQuoteState>>>,
|
|
payment_states: Arc<Mutex<HashMap<String, MeltQuoteState>>>,
|
|
|
failed_payment_check: Arc<Mutex<HashSet<String>>>,
|
|
failed_payment_check: Arc<Mutex<HashSet<String>>>,
|
|
|
payment_delay: u64,
|
|
payment_delay: u64,
|
|
@@ -227,7 +235,7 @@ impl FakeWallet {
|
|
|
let incoming_payments = Arc::new(RwLock::new(HashMap::new()));
|
|
let incoming_payments = Arc::new(RwLock::new(HashMap::new()));
|
|
|
|
|
|
|
|
let secondary_repayment_queue =
|
|
let secondary_repayment_queue =
|
|
|
- SecondaryRepaymentQueue::new(repay_queue_max_size, sender.clone());
|
|
|
|
|
|
|
+ SecondaryRepaymentQueue::new(repay_queue_max_size, sender.clone(), unit.clone());
|
|
|
|
|
|
|
|
Self {
|
|
Self {
|
|
|
fee_reserve,
|
|
fee_reserve,
|
|
@@ -306,19 +314,10 @@ impl MintPayment for FakeWallet {
|
|
|
.take()
|
|
.take()
|
|
|
.ok_or(Error::NoReceiver)
|
|
.ok_or(Error::NoReceiver)
|
|
|
.unwrap();
|
|
.unwrap();
|
|
|
- let unit = self.unit.clone();
|
|
|
|
|
let receiver_stream = ReceiverStream::new(receiver);
|
|
let receiver_stream = ReceiverStream::new(receiver);
|
|
|
- Ok(Box::pin(receiver_stream.map(
|
|
|
|
|
- move |(request_lookup_id, payment_amount, payment_id)| {
|
|
|
|
|
- let wait_response = WaitPaymentResponse {
|
|
|
|
|
- payment_identifier: request_lookup_id.clone(),
|
|
|
|
|
- payment_amount,
|
|
|
|
|
- unit: unit.clone(),
|
|
|
|
|
- payment_id,
|
|
|
|
|
- };
|
|
|
|
|
- Event::PaymentReceived(wait_response)
|
|
|
|
|
- },
|
|
|
|
|
- )))
|
|
|
|
|
|
|
+ Ok(Box::pin(receiver_stream.map(move |wait_response| {
|
|
|
|
|
+ Event::PaymentReceived(wait_response)
|
|
|
|
|
+ })))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[instrument(skip_all)]
|
|
#[instrument(skip_all)]
|
|
@@ -517,16 +516,18 @@ impl MintPayment for FakeWallet {
|
|
|
}
|
|
}
|
|
|
IncomingPaymentOptions::Bolt11(bolt11_options) => {
|
|
IncomingPaymentOptions::Bolt11(bolt11_options) => {
|
|
|
let description = bolt11_options.description.unwrap_or_default();
|
|
let description = bolt11_options.description.unwrap_or_default();
|
|
|
- let amount = if unit == &CurrencyUnit::Sat {
|
|
|
|
|
- to_unit(bolt11_options.amount, unit, &CurrencyUnit::Msat)
|
|
|
|
|
- .unwrap_or(bolt11_options.amount * Amount::from(1000))
|
|
|
|
|
|
|
+ let amount = bolt11_options.amount;
|
|
|
|
|
+ let expiry = bolt11_options.unix_expiry;
|
|
|
|
|
+
|
|
|
|
|
+ // For fake invoices, always use msats regardless of unit
|
|
|
|
|
+ let amount_msat = if unit == &CurrencyUnit::Sat {
|
|
|
|
|
+ u64::from(amount) * 1000
|
|
|
} else {
|
|
} else {
|
|
|
- bolt11_options.amount
|
|
|
|
|
|
|
+ // If unit is Msat, use as-is
|
|
|
|
|
+ u64::from(amount)
|
|
|
};
|
|
};
|
|
|
- let expiry = bolt11_options.unix_expiry;
|
|
|
|
|
|
|
|
|
|
- // Since this is fake we just use the amount no matter the unit to create an invoice
|
|
|
|
|
- let invoice = create_fake_invoice(amount.into(), description.clone());
|
|
|
|
|
|
|
+ let invoice = create_fake_invoice(amount_msat, description.clone());
|
|
|
let payment_hash = invoice.payment_hash();
|
|
let payment_hash = invoice.payment_hash();
|
|
|
|
|
|
|
|
(
|
|
(
|
|
@@ -550,8 +551,9 @@ impl MintPayment for FakeWallet {
|
|
|
use bitcoin::secp256k1::rand::rngs::OsRng;
|
|
use bitcoin::secp256k1::rand::rngs::OsRng;
|
|
|
use bitcoin::secp256k1::rand::Rng;
|
|
use bitcoin::secp256k1::rand::Rng;
|
|
|
let mut rng = OsRng;
|
|
let mut rng = OsRng;
|
|
|
- let random_amount: u64 = rng.gen_range(1..=1000);
|
|
|
|
|
- random_amount.into()
|
|
|
|
|
|
|
+ let random_amount: u64 = rng.gen_range(1000..=10000);
|
|
|
|
|
+ // Use the same unit as the wallet for any-amount invoices
|
|
|
|
|
+ Amount::from(random_amount)
|
|
|
} else {
|
|
} else {
|
|
|
amount
|
|
amount
|
|
|
};
|
|
};
|
|
@@ -574,15 +576,7 @@ impl MintPayment for FakeWallet {
|
|
|
.push(response.clone());
|
|
.push(response.clone());
|
|
|
|
|
|
|
|
// Send the message after waiting for the specified duration
|
|
// Send the message after waiting for the specified duration
|
|
|
- if sender
|
|
|
|
|
- .send((
|
|
|
|
|
- payment_hash_clone.clone(),
|
|
|
|
|
- final_amount,
|
|
|
|
|
- payment_hash_clone.to_string(),
|
|
|
|
|
- ))
|
|
|
|
|
- .await
|
|
|
|
|
- .is_err()
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ if sender.send(response.clone()).await.is_err() {
|
|
|
tracing::error!("Failed to send label: {:?}", payment_hash_clone);
|
|
tracing::error!("Failed to send label: {:?}", payment_hash_clone);
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|