pub mod eip2612;
pub mod eip3009;
pub mod permit2;
use alloy_provider::Provider;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use x402_types::chain::ChainProviderOps;
use x402_types::proto;
use x402_types::proto::v2;
use x402_types::scheme::{
X402SchemeFacilitator, X402SchemeFacilitatorBuilder, X402SchemeFacilitatorError,
};
use crate::V2Eip155Exact;
use crate::chain::Eip155MetaTransactionProvider;
use crate::v1_eip155_exact::ExactScheme;
use crate::v1_eip155_exact::facilitator::Eip155ExactError;
use crate::v2_eip155_exact::types;
impl<P> X402SchemeFacilitatorBuilder<P> for V2Eip155Exact
where
P: Eip155MetaTransactionProvider + ChainProviderOps + Send + Sync + 'static,
Eip155ExactError: From<P::Error>,
{
fn build(
&self,
provider: P,
config: Option<serde_json::Value>,
) -> Result<Box<dyn X402SchemeFacilitator>, Box<dyn std::error::Error>> {
let config: V2Eip155ExactFacilitatorConfig = config
.and_then(|config| serde_json::from_value(config).ok())
.unwrap_or_default();
Ok(Box::new(V2Eip155ExactFacilitator::new(provider, config)))
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct V2Eip155ExactFacilitatorConfig {
#[serde(default)]
pub eip2612_gas_sponsoring: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct V2Eip155ExactFacilitatorExtra {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<Vec<String>>,
}
pub struct V2Eip155ExactFacilitator<P> {
provider: P,
eip2612_gas_sponsoring: bool,
}
impl<P> V2Eip155ExactFacilitator<P> {
pub fn new(provider: P, config: V2Eip155ExactFacilitatorConfig) -> Self {
Self {
provider,
eip2612_gas_sponsoring: config.eip2612_gas_sponsoring,
}
}
}
#[async_trait::async_trait]
impl<P> X402SchemeFacilitator for V2Eip155ExactFacilitator<P>
where
P: Eip155MetaTransactionProvider + ChainProviderOps + Send + Sync,
P::Inner: Provider,
Eip155ExactError: From<P::Error>,
{
async fn verify(
&self,
request: &proto::VerifyRequest,
) -> Result<proto::VerifyResponse, X402SchemeFacilitatorError> {
let verify_request = types::FacilitatorVerifyRequest::try_from(request.clone())?;
let verify_response = match verify_request {
types::FacilitatorVerifyRequest::Eip3009 {
payment_payload,
payment_requirements,
x402_version: _,
} => {
eip3009::verify_eip3009_payment(
&self.provider,
&payment_payload,
&payment_requirements,
)
.await?
}
types::FacilitatorVerifyRequest::Permit2 {
payment_requirements,
payment_payload,
x402_version: _,
} => {
permit2::verify_permit2_payment(
&self.provider,
self.eip2612_gas_sponsoring,
&payment_payload,
&payment_requirements,
)
.await?
}
};
Ok(verify_response.into())
}
async fn settle(
&self,
request: &proto::SettleRequest,
) -> Result<proto::SettleResponse, X402SchemeFacilitatorError> {
let settle_request = types::FacilitatorSettleRequest::try_from(request.clone())?;
let settle_response = match settle_request {
types::FacilitatorSettleRequest::Eip3009 {
payment_payload,
payment_requirements,
x402_version: _,
} => {
eip3009::settle_eip3009_payment(
&self.provider,
&payment_payload,
&payment_requirements,
)
.await?
}
types::FacilitatorSettleRequest::Permit2 {
payment_requirements,
payment_payload,
x402_version: _,
} => {
permit2::settle_permit2_payment(
&self.provider,
self.eip2612_gas_sponsoring,
&payment_payload,
&payment_requirements,
)
.await?
}
};
Ok(settle_response.into())
}
async fn supported(&self) -> Result<proto::SupportedResponse, X402SchemeFacilitatorError> {
let chain_id = self.provider.chain_id();
let mut extensions = vec![];
if self.eip2612_gas_sponsoring {
extensions.push(eip2612::EXTENSION_KEY.to_string());
}
let extra = V2Eip155ExactFacilitatorExtra {
extensions: Some(extensions.clone()),
};
let extra = serde_json::to_value(extra).ok();
let kinds = vec![proto::SupportedPaymentKind {
x402_version: v2::X402Version2.into(),
scheme: ExactScheme.to_string(),
network: chain_id.clone().into(),
extra,
}];
let signers = {
let mut signers = HashMap::with_capacity(1);
signers.insert(chain_id, self.provider.signer_addresses());
signers
};
Ok(proto::SupportedResponse {
kinds,
extensions,
signers,
})
}
}