use crate::blinded_path::message::{AsyncPaymentsContext, BlindedMessagePath};
use crate::io;
use crate::ln::msgs::DecodeError;
use crate::offers::static_invoice::StaticInvoice;
use crate::onion_message::messenger::{MessageSendInstructions, Responder, ResponseInstruction};
use crate::onion_message::packet::OnionMessageContents;
use crate::prelude::*;
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
const OFFER_PATHS_REQ_TLV_TYPE: u64 = 75540;
const OFFER_PATHS_TLV_TYPE: u64 = 75542;
const SERVE_INVOICE_TLV_TYPE: u64 = 75544;
const INVOICE_PERSISTED_TLV_TYPE: u64 = 75546;
const HELD_HTLC_AVAILABLE_TLV_TYPE: u64 = 72;
const RELEASE_HELD_HTLC_TLV_TYPE: u64 = 74;
pub trait AsyncPaymentsMessageHandler {
fn handle_offer_paths_request(
&self, message: OfferPathsRequest, context: AsyncPaymentsContext,
responder: Option<Responder>,
) -> Option<(OfferPaths, ResponseInstruction)>;
fn handle_offer_paths(
&self, message: OfferPaths, context: AsyncPaymentsContext, responder: Option<Responder>,
) -> Option<(ServeStaticInvoice, ResponseInstruction)>;
fn handle_serve_static_invoice(
&self, message: ServeStaticInvoice, context: AsyncPaymentsContext,
responder: Option<Responder>,
);
fn handle_static_invoice_persisted(
&self, message: StaticInvoicePersisted, context: AsyncPaymentsContext,
);
fn handle_held_htlc_available(
&self, message: HeldHtlcAvailable, context: AsyncPaymentsContext,
responder: Option<Responder>,
) -> Option<(ReleaseHeldHtlc, ResponseInstruction)>;
fn handle_release_held_htlc(&self, message: ReleaseHeldHtlc, context: AsyncPaymentsContext);
fn release_pending_messages(&self) -> Vec<(AsyncPaymentsMessage, MessageSendInstructions)> {
vec![]
}
}
#[derive(Clone, Debug)]
pub enum AsyncPaymentsMessage {
OfferPathsRequest(OfferPathsRequest),
OfferPaths(OfferPaths),
ServeStaticInvoice(ServeStaticInvoice),
StaticInvoicePersisted(StaticInvoicePersisted),
HeldHtlcAvailable(HeldHtlcAvailable),
ReleaseHeldHtlc(ReleaseHeldHtlc),
}
#[derive(Clone, Debug)]
pub struct OfferPathsRequest {
pub invoice_slot: u16,
}
#[derive(Clone, Debug)]
pub struct OfferPaths {
pub paths: Vec<BlindedMessagePath>,
pub paths_absolute_expiry: Option<u64>,
}
#[derive(Clone, Debug)]
pub struct ServeStaticInvoice {
pub invoice: StaticInvoice,
pub forward_invoice_request_path: BlindedMessagePath,
}
#[derive(Clone, Debug)]
pub struct StaticInvoicePersisted {}
#[derive(Clone, Debug)]
pub struct HeldHtlcAvailable {}
#[derive(Clone, Debug)]
pub struct ReleaseHeldHtlc {}
impl OnionMessageContents for OfferPaths {
fn tlv_type(&self) -> u64 {
OFFER_PATHS_TLV_TYPE
}
#[cfg(c_bindings)]
fn msg_type(&self) -> String {
"Offer Paths".to_string()
}
#[cfg(not(c_bindings))]
fn msg_type(&self) -> &'static str {
"Offer Paths"
}
}
impl OnionMessageContents for ServeStaticInvoice {
fn tlv_type(&self) -> u64 {
SERVE_INVOICE_TLV_TYPE
}
#[cfg(c_bindings)]
fn msg_type(&self) -> String {
"Serve Static Invoice".to_string()
}
#[cfg(not(c_bindings))]
fn msg_type(&self) -> &'static str {
"Serve Static Invoice"
}
}
impl OnionMessageContents for ReleaseHeldHtlc {
fn tlv_type(&self) -> u64 {
RELEASE_HELD_HTLC_TLV_TYPE
}
#[cfg(c_bindings)]
fn msg_type(&self) -> String {
"Release Held HTLC".to_string()
}
#[cfg(not(c_bindings))]
fn msg_type(&self) -> &'static str {
"Release Held HTLC"
}
}
impl_writeable_tlv_based!(OfferPathsRequest, {
(0, invoice_slot, required),
});
impl_writeable_tlv_based!(OfferPaths, {
(0, paths, required_vec),
(2, paths_absolute_expiry, option),
});
impl_writeable_tlv_based!(ServeStaticInvoice, {
(0, invoice, required),
(2, forward_invoice_request_path, required),
});
impl_writeable_tlv_based!(StaticInvoicePersisted, {});
impl_writeable_tlv_based!(HeldHtlcAvailable, {});
impl_writeable_tlv_based!(ReleaseHeldHtlc, {});
impl AsyncPaymentsMessage {
pub fn is_known_type(tlv_type: u64) -> bool {
match tlv_type {
OFFER_PATHS_REQ_TLV_TYPE
| OFFER_PATHS_TLV_TYPE
| SERVE_INVOICE_TLV_TYPE
| INVOICE_PERSISTED_TLV_TYPE
| HELD_HTLC_AVAILABLE_TLV_TYPE
| RELEASE_HELD_HTLC_TLV_TYPE => true,
_ => false,
}
}
}
impl OnionMessageContents for AsyncPaymentsMessage {
fn tlv_type(&self) -> u64 {
match self {
Self::OfferPathsRequest(_) => OFFER_PATHS_REQ_TLV_TYPE,
Self::OfferPaths(msg) => msg.tlv_type(),
Self::ServeStaticInvoice(msg) => msg.tlv_type(),
Self::StaticInvoicePersisted(_) => INVOICE_PERSISTED_TLV_TYPE,
Self::HeldHtlcAvailable(_) => HELD_HTLC_AVAILABLE_TLV_TYPE,
Self::ReleaseHeldHtlc(msg) => msg.tlv_type(),
}
}
#[cfg(c_bindings)]
fn msg_type(&self) -> String {
match &self {
Self::OfferPathsRequest(_) => "Offer Paths Request".to_string(),
Self::OfferPaths(msg) => msg.msg_type(),
Self::ServeStaticInvoice(msg) => msg.msg_type(),
Self::StaticInvoicePersisted(_) => "Static Invoice Persisted".to_string(),
Self::HeldHtlcAvailable(_) => "Held HTLC Available".to_string(),
Self::ReleaseHeldHtlc(msg) => msg.msg_type(),
}
}
#[cfg(not(c_bindings))]
fn msg_type(&self) -> &'static str {
match &self {
Self::OfferPathsRequest(_) => "Offer Paths Request",
Self::OfferPaths(msg) => msg.msg_type(),
Self::ServeStaticInvoice(msg) => msg.msg_type(),
Self::StaticInvoicePersisted(_) => "Static Invoice Persisted",
Self::HeldHtlcAvailable(_) => "Held HTLC Available",
Self::ReleaseHeldHtlc(msg) => msg.msg_type(),
}
}
}
impl Writeable for AsyncPaymentsMessage {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
match self {
Self::OfferPathsRequest(message) => message.write(w),
Self::OfferPaths(message) => message.write(w),
Self::ServeStaticInvoice(message) => message.write(w),
Self::StaticInvoicePersisted(message) => message.write(w),
Self::HeldHtlcAvailable(message) => message.write(w),
Self::ReleaseHeldHtlc(message) => message.write(w),
}
}
}
impl ReadableArgs<u64> for AsyncPaymentsMessage {
fn read<R: io::Read>(r: &mut R, tlv_type: u64) -> Result<Self, DecodeError> {
match tlv_type {
OFFER_PATHS_REQ_TLV_TYPE => Ok(Self::OfferPathsRequest(Readable::read(r)?)),
OFFER_PATHS_TLV_TYPE => Ok(Self::OfferPaths(Readable::read(r)?)),
SERVE_INVOICE_TLV_TYPE => Ok(Self::ServeStaticInvoice(Readable::read(r)?)),
INVOICE_PERSISTED_TLV_TYPE => Ok(Self::StaticInvoicePersisted(Readable::read(r)?)),
HELD_HTLC_AVAILABLE_TLV_TYPE => Ok(Self::HeldHtlcAvailable(Readable::read(r)?)),
RELEASE_HELD_HTLC_TLV_TYPE => Ok(Self::ReleaseHeldHtlc(Readable::read(r)?)),
_ => Err(DecodeError::InvalidValue),
}
}
}