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);