pub use super::payments::MakePaymentArgs as ForwardPaymentArgs;
use super::payments::{make_payment, PaymentInfo, PaymentRecipientInfo};
use crate::alby::{
api::{
invoices::{CreateInvoiceArgs as AlbyCreateInvoiceArgs, CreateInvoiceResponse},
RequestError,
},
webhooks::AlbyInvoice,
};
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct CreateInvoiceArgs<'a> {
pub user_agent: &'a str,
pub token: &'a str,
pub payment_info: PaymentInfo,
pub recipients: Vec<PaymentRecipientInfo>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct CreateInvoiceMetadataForwardingStruct {
pub payment_info: PaymentInfo,
pub recipients: Vec<PaymentRecipientInfo>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct CreateInvoiceMetadata {
pub forwarding_data: CreateInvoiceMetadataForwardingStruct,
}
impl TryFrom<AlbyInvoice> for CreateInvoiceMetadata {
type Error = serde_json::Error;
fn try_from(invoice: AlbyInvoice) -> Result<Self, Self::Error> {
let forwarding_data = serde_json::from_value(invoice.metadata)?;
Ok(Self { forwarding_data })
}
}
pub async fn create_invoice(
args: CreateInvoiceArgs<'_>,
) -> Result<CreateInvoiceResponse, RequestError> {
let total_sats = args
.recipients
.iter()
.fold(0, |acc, recipient| acc + recipient.num_sats);
let metadata_value = serde_json::json!(CreateInvoiceMetadata {
forwarding_data: CreateInvoiceMetadataForwardingStruct {
payment_info: args.payment_info.clone(),
recipients: args.recipients,
},
});
let invoice_args = AlbyCreateInvoiceArgs {
user_agent: args.user_agent,
token: args.token,
num_sats: total_sats,
metadata: metadata_value,
description: args.payment_info.message.clone(),
payer_name: args.payment_info.sender_name.clone(),
};
crate::alby::api::invoices::create_invoice(invoice_args).await
}
pub async fn forward_payments(args: ForwardPaymentArgs<'_>) -> Result<(), RequestError> {
make_payment(ForwardPaymentArgs {
user_agent: args.user_agent,
token: args.token,
payment_info: args.payment_info.clone(),
recipients: args.recipients.clone(),
})
.await
.map(|_| ())
}
pub fn clip_recipients_at_amount(
total_sats: u64,
recipients: &[PaymentRecipientInfo],
) -> Vec<PaymentRecipientInfo> {
let mut totals_sats_sent = 0;
let mut clipped_recipients = vec![];
for recipient in recipients {
totals_sats_sent += recipient.num_sats;
if totals_sats_sent > total_sats {
break;
}
clipped_recipients.push(recipient.clone());
}
clipped_recipients
}