Skip to content

Server Integration

This guide covers setting up PipeGate middleware in your Rust server application.

Installation

Install pipegate crate from crates.io:

Terminal
cargo add pipegate

Or

Add the required dependencies to your Cargo.toml:

[dependencies]
pipegate = { version = "0.5.0" }
axum = "0.7"

Axum v0.8.0 has breaking changes. The pipegte tower-based middleware layers is not yet supported in the latest version.

Basic Server Setup

use axum::{routing::get, Router};
use pipegate::middleware::payment_channel::{PaymentChannelMiddlewareLayer, channel::ChannelState, types::PaymentChannelConfig};
use pipegate::utils::{Address, U256};
 
#[tokio::main]
async fn main() {
    // Configure RPC endpoint
    let rpc_url = "https://base-sepolia-rpc.publicnode.com"
        .parse()
        .unwrap();
 
    // Initialize channel state
    let state = ChannelState::new();
 
    // Payment channel configuration
    let payment_channel_config = PaymentChannelConfig {
        recipient: Address::from_str("YOUR_ADDRESS").unwrap(),
        token_address: Address::from_str("USDC_ADDRESS").unwrap(),
        amount: U256::from(1000), // 0.001 USDC in this case
        rpc_url: rpc_url.to_string(),
    };
 
    // Create router with middleware
    let app = Router::new()
        .route("/", get(root))
        .layer(PaymentChannelMiddlewareLayer::new(state, conf));
 
    // Start server
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
        .await
        .unwrap();
 
    println!("Server running on http://0.0.0.0:3000");
    axum::serve(listener, app).await.unwrap();
}
 
async fn root() -> &'static str {
    "Hello, World!"
}

Configuration Options

Environment Variables

use std::env;
use dotenv::dotenv;
 
dotenv().ok();
 
let rpc_url = env::var("RPC_URL")
    .unwrap_or_else(|_| "https://base-sepolia-rpc.publicnode.com".to_string());

Payment Settings

// For payment channels
let payment_channel_config = PaymentChannelConfig {
    recipient: Address::from_str("YOUR_ADDRESS").unwrap(),
    token_address: Address::from_str("USDC_ADDRESS").unwrap(),
    amount: U256::from(1000), // 0.001 USDC each call
    rpc_url: rpc_url.to_string(),
};
 
// For one-time payments
let onetime_config = OneTimePaymentConfig {
    recipient: Address::from_str("YOUR_ADDRESS").unwrap(),
    token_address: Address::from_str("USDC_ADDRESS").unwrap(),
    amount: U256::from(1000000), // 1 USDC each call
    period: U256::from(3600), // Access until 1 hour post payment
    rpc_url: rpc_url.to_string(),
};
 
// For streams
let stream_config = StreamsConfig {
    recipient: Address::from_str("YOUR_ADDRESS").unwrap(),
    token_address: Address::from_str("USDC_ADDRESS").unwrap(),
    amount: "761035007610".parse().unwrap(), // 2 USDC/month
    cfa_forwarder: cfa_address,
    rpc_url: rpc_url.to_string(),
};

Error Handling

use pipegate::errors::AuthError;
 
async fn protected_route() -> Result<String, AuthError> {
    // Your route logic
    Ok("Protected data".to_string())
}
 
// Error handling middleware
async fn handle_error(err: AuthError) -> (StatusCode, String) {
    match err {
        AuthError::InsufficientBalance => {
            (StatusCode::PAYMENT_REQUIRED, "Insufficient balance".to_string())
        }
        AuthError::InvalidSignature => {
            (StatusCode::UNAUTHORIZED, "Invalid signature".to_string())
        }
        _ => (StatusCode::INTERNAL_SERVER_ERROR, "Server error".to_string())
    }
}

Multiple Payment Methods

You can support multiple payment methods by combining middlewares:

let app = Router::new()
    .route("/channel", get(channel_route))
    .route("/onetime", get(onetime_route))
    .route("/stream", get(stream_route))
    .layer(PipegateMiddlewareLayer::new(channel_state, channel_config))
    .layer(OnetimePaymentMiddlewareLayer::new(onetime_config))
    .layer(StreamMiddlewareLayer::new(stream_config, stream_state));

Monitoring & Logging

use tracing::{info, error};
 
// Initialize logging
tracing_subscriber::fmt()
    .with_max_level(Level::INFO)
    .init();
 
// Log payment events
info!("Payment received: {} USDC", amount);
error!("Payment verification failed: {}", err);