Client
Handle 402 responses automatically
The Fetch extension trait adds .send_with_payment() to any reqwest::RequestBuilder—when a server returns 402, it parses the Challenge, signs a stablecoin transfer, and retries with the Credential.
Quick start
use mpp::client::{Fetch, TempoProvider};
use mpp::PrivateKeySigner;
let signer = PrivateKeySigner::random();
let provider = TempoProvider::new(signer, "https://rpc.tempo.xyz")?;
let response = reqwest::Client::new()
.get("https://api.example.com/paid")
.send_with_payment(&provider)
.await?;
println!("Status: {}", response.status());When the server returns 402, send_with_payment:
- Parses the Challenge from the
WWW-Authenticateheader - Calls
provider.pay()to sign a stablecoin transfer - Retries the request with the Credential in the
Authorizationheader
TempoProvider
TempoProvider signs TIP-20 stablecoin transfers on the Tempo blockchain.
use mpp::client::TempoProvider;
use mpp::PrivateKeySigner;
let signer: PrivateKeySigner = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
.parse()?;
let provider = TempoProvider::new(signer, "https://rpc.tempo.xyz")?;With client ID
Attach an identifier to transactions for attribution:
let provider = TempoProvider::new(signer, "https://rpc.tempo.xyz")?
.with_client_id("my-app");Middleware
For automatic 402 handling on all requests, use PaymentMiddleware with reqwest-middleware. Requires the middleware feature.
mpp = { version = "0.1", features = ["tempo", "client", "middleware"] }use mpp::client::{PaymentMiddleware, TempoProvider};
use reqwest_middleware::ClientBuilder;
let provider = TempoProvider::new(signer, "https://rpc.tempo.xyz")?;
let client = ClientBuilder::new(reqwest::Client::new())
.with(PaymentMiddleware::new(provider))
.build();
// All requests through this client handle 402 automatically
let response = client.get("https://api.example.com/paid").send().await?;Multiple providers
MultiProvider wraps multiple payment providers and picks the right one based on the challenge's method and intent:
use mpp::client::{MultiProvider, TempoProvider};
let provider = MultiProvider::new()
.with(TempoProvider::new(signer, "https://rpc.tempo.xyz")?);
let response = reqwest::Client::new()
.get("https://api.example.com/paid")
.send_with_payment(&provider)
.await?;Custom provider
Implement the PaymentProvider trait to add support for custom payment methods:
use mpp::client::PaymentProvider;
use mpp::{PaymentChallenge, PaymentCredential, PaymentPayload, MppError};
#[derive(Clone)]
struct MyProvider;
impl PaymentProvider for MyProvider {
fn supports(&self, method: &str, intent: &str) -> bool {
method == "my_network" && intent == "charge"
}
async fn pay(
&self,
challenge: &PaymentChallenge,
) -> Result<PaymentCredential, MppError> {
let echo = challenge.to_echo();
Ok(PaymentCredential::new(echo, PaymentPayload::hash("0x...")))
}
}Key types
| Type | Description |
|---|---|
Fetch (PaymentExt) | Extension trait that adds send_with_payment to reqwest::RequestBuilder |
MultiProvider | Wraps multiple providers, routes by method and intent |
PaymentMiddleware | reqwest-middleware for automatic 402 handling |
PaymentProvider | Trait for custom payment method implementations |
TempoProvider | Signs Tempo stablecoin transfers |