use std::cell::RefCell;
use std::future::Future;
use std::pin::Pin;
use std::rc::Rc;
pub struct X402Challenge {
pub to: [u8; 20],
pub value_wei: u128,
pub valid_after: u64,
pub valid_before: u64,
pub nonce: [u8; 32],
}
pub struct X402Payment {
pub from: [u8; 20],
pub signature: [u8; 65],
}
type SignerFut = Pin<Box<dyn Future<Output = Result<X402Payment, String>>>>;
type Signer = Rc<dyn Fn(X402Challenge) -> SignerFut>;
thread_local! {
static SIGNER: RefCell<Option<Signer>> = const { RefCell::new(None) };
}
pub fn install(signer: Signer) {
SIGNER.with(|s| *s.borrow_mut() = Some(signer));
}
pub async fn sign(challenge: X402Challenge) -> Result<X402Payment, String> {
let signer = SIGNER.with(|s| s.borrow().clone());
match signer {
Some(f) => f(challenge).await,
None => Err("no x402 signer installed".into()),
}
}