Skip to content

Channel Management

Guide for API providers on managing payment channels, including closure and withdrawals.

Channel Closure & Withdrawal

Automatic State-Based Closure (Recommended)

The new close_and_withdraw_from_state function simplifies channel closure by automatically handling state management:

use pipegate::middleware::{
    payment_channel::channel::{close_channel_from_state, ChannelState},
    PaymentsState
};
 
async fn close_and_withdraw_from_state(state: &ChannelState) -> Result<TxHash, Error> {
    let payment_state = PaymentsState::new();
    let channel_state = payment_state
        .channel_state
        .clone()
        .read()
        .await
        .as_ref()
        .unwrap()
        .clone();
 
    let rpc_url = "https://base-sepolia-rpc.publicnode.com"
        .parse()
        .unwrap();
 
    let private_key = env::var("PRIVATE_KEY")
        .expect("PRIVATE_KEY must be set");
 
    let raw_body = Bytes::from("0x");
 
    // Automatically close channel and withdraw funds from current state
    let tx_hash = close_channel_from_state(
        &channel_state,
        rpc_url,
        private_key.as_str(),
        U256::from(1), // channel_id
        raw_body,
    ).await;
 
    println!("Transaction Hash: {:?}", tx_hash);
    Ok(tx_hash)
}
Benefits of State-Based Closure:
  • Automatic Signature Handling: No need to manually track signatures
  • State Synchronization: Uses the latest channel state automatically
  • Simplified Implementation: Reduces boilerplate code
  • Error Reduction: Less chance of using outdated channel information

Manual Channel Closure (Legacy)

For manual control or when you have specific channel details:

use pipegate::middleware::payment_channel::{
    channel::{close_channel, ChannelState},
    types::PaymentChannel,
};
 
async fn close_and_withdraw_manual(
    payment_channel: PaymentChannel,
    signature: PrimitiveSignature,
    raw_body: Bytes
) -> Result<TxHash, Error> {
    let rpc_url = "https://base-sepolia-rpc.publicnode.com"
        .parse()
        .unwrap();
 
    let private_key = env::var("PRIVATE_KEY")
        .expect("PRIVATE_KEY must be set");
 
    // Close channel and withdraw funds with manual parameters
    let tx_hash = close_channel(
        rpc_url,
        private_key.as_str(),
        &payment_channel,
        &signature,
        raw_body
    ).await?;
 
    Ok(tx_hash)
}

Channel State Management

// Get channel state
let channel = state.get_channel(channel_id).await?;
 
// Check channel balance
if channel.balance < required_amount {
    return Err(AuthError::InsufficientBalance);
}
 
// Verify channel expiration
if channel.expiration < current_timestamp {
    return Err(AuthError::ChannelExpired);
}

Best Practices

  1. Use State-Based Closure
    • Prefer close_and_withdraw_from_state for automatic state management
    • Reduces complexity and potential errors
    • Automatically uses the latest channel information
  2. Regular Withdrawals
    • Monitor channel balances periodically
    • Withdraw funds before channels expire
    • Keep track of active channels
  3. Error Handling
    • Handle network errors gracefully
    • Verify transaction completion
    • Implement retry mechanisms for failed transactions
  4. Security
    • Secure private key storage (use environment variables)
    • Validate channel states before operations
    • Monitor for suspicious activity
  5. State Management
    • Be aware that server restarts will lose in-memory state
    • Consider implementing state persistence for production
    • Plan for graceful degradation when state is lost