Channel
High-frequency off-chain payments
The channel intent enables high-frequency, pay-as-you-go payments over unidirectional payment channels on Stellar. Clients deposit tokens into an on-chain contract reserve and sign off-chain cumulative commitments as they consume resources. The server verifies commitments via contract simulation–no per-request on-chain transactions–and closes the channel to settle the final balance.
Payment channels reduce payment verification to a single contract simulation per request, making it possible to meter and bill at the granularity of individual LLM tokens, API calls, or bytes transferred.
How it works
A payment channel has four phases:
Open
The client deploys a one-way-channel smart contract with a commitment key and an asset deposit. This creates a payment channel between the client (funder) and server (recipient). The channel contract holds the deposited tokens on-chain.
Session
The client signs ed25519 cumulative commitment amounts as service is consumed. Each commitment authorizes "I have now consumed up to X total." The server verifies the commitment signature by simulating prepare_commitment on the channel contract and checks that the cumulative amount is higher than the previous commitment.
Commitment verification requires a single contract simulation per request. This is what enables per-token LLM billing without significant latency overhead.
Integration
Closing the channel
The server closes the channel by submitting the highest cumulative commitment amount and signature on-chain. The close function is exported from the server package:
import { close } from '@stellar/mpp/channel/server'
import { Keypair } from '@stellar/stellar-sdk'
const txHash = await close({
channel: 'CABC...', // channel contract address
amount: 2000000n, // cumulative amount in base units (bigint)
signature: lastCommitmentSignature, // Uint8Array
feePayer: { envelopeSigner: Keypair.fromSecret('S...') },
network: 'stellar:testnet',
})Monitoring channels
Use getChannelState to query the on-chain state of a channel, and watchChannel to poll for contract events:
import { getChannelState, watchChannel } from '@stellar/mpp/channel/server'
// Query current state
const state = await getChannelState({
channel: 'CABC...',
rpcUrl: 'https://soroban-testnet.stellar.org',
})
// Watch for events (close, refund, top_up)
const stop = watchChannel({
channel: 'CABC...',
rpcUrl: 'https://soroban-testnet.stellar.org',
onEvent(event) {
console.log(event.type, event.data)
},
})
// Stop watching
stop()Channel contract
Payment channels use the one-way-channel smart contract for on-chain deposits, commitment verification, and settlement.
The contract lifecycle: Open (deploy + deposit) -> Off-chain payments (signed commitments) -> Settle (partial withdrawal) -> Close (final settlement) or Close Start -> Refund (funder reclaims after waiting period).
Commitment signatures use ed25519 over XDR-encoded ScVal::Map containing the amount, channel address, domain separator (chancmmt), and network ID–preventing replay across channels and networks.