use std::collections::HashMap;
use crate::facilitator::Facilitator;
use crate::proto;
use crate::proto::PaymentVerificationError;
use crate::scheme::{SchemeRegistry, X402SchemeFacilitatorError};
pub struct FacilitatorLocal<A> {
handlers: A,
}
impl<A> FacilitatorLocal<A> {
pub fn new(handlers: A) -> Self {
FacilitatorLocal { handlers }
}
}
impl Facilitator for FacilitatorLocal<SchemeRegistry> {
type Error = FacilitatorLocalError;
async fn verify(
&self,
request: &proto::VerifyRequest,
) -> Result<proto::VerifyResponse, Self::Error> {
let handler = request
.scheme_handler_slug()
.and_then(|slug| self.handlers.by_slug(&slug))
.ok_or(FacilitatorLocalError::Verification(
PaymentVerificationError::UnsupportedScheme.into(),
))?;
let response = handler
.verify(request)
.await
.map_err(FacilitatorLocalError::Verification)?;
Ok(response)
}
async fn settle(
&self,
request: &proto::SettleRequest,
) -> Result<proto::SettleResponse, Self::Error> {
let handler = request
.scheme_handler_slug()
.and_then(|slug| self.handlers.by_slug(&slug))
.ok_or(FacilitatorLocalError::Verification(
PaymentVerificationError::UnsupportedScheme.into(),
))?;
let response = handler
.settle(request)
.await
.map_err(FacilitatorLocalError::Settlement)?;
Ok(response)
}
async fn supported(&self) -> Result<proto::SupportedResponse, Self::Error> {
let mut kinds = vec![];
let mut signers = HashMap::new();
for provider in self.handlers.values() {
let supported = provider.supported().await.ok();
if let Some(mut supported) = supported {
kinds.append(&mut supported.kinds);
for (chain_id, signer_addresses) in supported.signers {
signers.entry(chain_id).or_insert(signer_addresses);
}
}
}
Ok(proto::SupportedResponse {
kinds,
extensions: Vec::new(),
signers,
})
}
}
#[derive(Debug, thiserror::Error)]
pub enum FacilitatorLocalError {
#[error(transparent)]
Verification(X402SchemeFacilitatorError),
#[error(transparent)]
Settlement(X402SchemeFacilitatorError),
}