use std::fmt::{self, Debug, Formatter};
use std::future::Future;
use std::pin::Pin;
use compact_str::CompactString;
use r402_protocol::{ChainId, ClientError, PaymentRequired, PaymentRequirements, SchemeId};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DefaultAssetInfo {
pub asset: CompactString,
pub decimals: u32,
pub symbol: CompactString,
pub asset_transfer_method: Option<CompactString>,
}
impl DefaultAssetInfo {
#[must_use]
pub fn new(
asset: impl Into<CompactString>,
decimals: u32,
symbol: impl Into<CompactString>,
) -> Self {
Self {
asset: asset.into(),
decimals,
symbol: symbol.into(),
asset_transfer_method: None,
}
}
#[must_use]
pub fn with_asset_transfer_method(mut self, method: impl Into<CompactString>) -> Self {
self.asset_transfer_method = Some(method.into());
self
}
}
pub trait SchemeClient: SchemeId + Send + Sync {
fn accept(&self, payment_required: &PaymentRequired) -> Vec<PaymentCandidate>;
fn find_default_asset(&self, asset: &str, network: &ChainId) -> Option<DefaultAssetInfo>;
}
pub struct PaymentCandidate {
pub chain_id: ChainId,
pub asset: CompactString,
pub amount: CompactString,
pub scheme: CompactString,
pub pay_to: CompactString,
pub requirements: PaymentRequirements,
pub signer: Box<dyn PaymentCandidateSigner>,
}
impl Debug for PaymentCandidate {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("PaymentCandidate")
.field("chain_id", &self.chain_id)
.field("asset", &self.asset)
.field("amount", &self.amount)
.field("scheme", &self.scheme)
.field("pay_to", &self.pay_to)
.finish_non_exhaustive()
}
}
impl PaymentCandidate {
pub async fn sign(&self) -> Result<String, ClientError> {
self.signer.sign_payment().await
}
}
pub trait PaymentCandidateSigner: Send + Sync {
fn sign_payment<'a>(
&'a self,
) -> Pin<Box<dyn Future<Output = Result<String, ClientError>> + Send + 'a>>;
}