Skip to content

Payment Channels

Payment channels are ideal for frequent API calls, allowing you to deposit once and make multiple requests without additional gas fees.

How it works & Architecture

Payment Channel Flow

For API Users

Create Payment Channel

import { ClientInterceptor } from "pipegate-sdk";
 
const pipeGate = new ClientInterceptor();
 
// Update these params with what you get from the API provider
const channelParams = {
  recipient: "0x...", // API provider's address
  duration: 2592000, // 30 days
  tokenAddress: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", // USDC
  amount: "100", // 100 USDC
};
 
const channel = await pipeGate.createPaymentChannel(channelParams);
await pipeGate.addNewChannel(channel.channelId, channel);

or If you want to use the cast CLI tool, refer to the steps here

Setup API Client

const api = axios.create({
  baseURL: "https://api.example.com",
});
 
api.interceptors.request.use(
  pipeGate.createPaymentChannelRequestInterceptor(channelId).request
);
api.interceptors.response.use(
  pipeGate.createPaymentChannelResponseInterceptor().response
);

Monitor Channel State

const channelState = pipeGate.getChannelState(channelId);
console.log("Balance:", channelState?.balance);
console.log("Expiration:", channelState?.expiration);

For API Providers

Configure Middleware

use pipegate::middleware::payment_channel::{channel::ChannelState, types::PaymentChannelConfig};
use pipegate::utils::{Address, Url, U256};
 
let rpc_url: Url = "https://base-rpc.publicnode.com".parse().unwrap();
 
let state = ChannelState::new();
let 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(),
};

Attach Middleware layer

use pipegate::middleware::payment_channel::{PaymentChannelMiddlewareLayer};
 
let app = Router::new()
    .route("/", get(root))
    .layer(PaymentChannelMiddlewareLayer::new(state, config));

Register Price in Channel Factory

Terminal
# Set your price per request (1000 = 0.001 USDC)
cast send $FACTORY_ADDRESS "register(uint256)" 1000 \
    --rpc-url $RPC_URL \
    --private-key $PRIVATE_KEY

Handle Channel Closure

// Close channel and withdraw funds
let tx_hash = close_channel(
    rpc_url,
    private_key.as_str(),
    &payment_channel,
    &signature,
    raw_body,
);

or use CLI to close the channel

Terminal
# Close the channel to withdraw 1 USDC with a nonce of 1000, along with the signature received during the API calls
cast send $FACTORY_ADDRESS "close(uint256 channelBalance,uint256 nonce,bytes calldata rawBody,bytes calldata signature)" 1000 1000 0x0 $SIGNATURE \
    --rpc-url $RPC_URL \
    --private-key $PRIVATE_KEY

Example for channel closure can be found here

Best Practices

  • Always monitor channel balance
  • Set appropriate channel duration
  • Handle channel expiration gracefully
  • Implement proper error handling