upto scheme lets a seller advertise a maximum price for one request, then settle for the actual amount used. The buyer signs once for the maximum, and the server chooses a final amount that is less than or equal to that maximum.
Use upto for one-request usage metering, such as LLM token generation, bandwidth, compute time, or dynamic data queries.
Server Setup
Set the routeprice to the maximum authorized amount. In the handler, use settlement overrides to charge the actual amount.
- TypeScript (EVM)
- TypeScript (SVM)
- Go (EVM)
- Go (SVM)
- Python
Client Setup
Register theupto scheme alongside exact if your client may call both fixed-price and usage-based resources.
- TypeScript (EVM)
- TypeScript (SVM)
- Go (EVM)
- Go (SVM)
- Python
Settlement Override Formats
amount can be expressed as:
Setting the amount to
"0" means no charge for that request. On SVM, a zero-amount close still lands a transaction to release the escrowed deposit and channel rent.
EVM Implementation
upto on EVM uses Permit2 because the settled amount is not known when the buyer signs. The facilitator advertises a facilitatorAddress in the payment requirements, and the client binds the authorization to that facilitator.
SVM Implementation
upto on Solana uses the payment-channels program. The client escrows the ceiling amount in an onchain channel (open), and the server settles the actual amount with a signed voucher (settle_and_seal + distribute). The facilitator sponsors transaction fees and channel rent as a zero-share channel payee, and can always close abandoned channels to recover rent.
Every channel commits to a receiverAuthorizer (authorized_signer) that signs settlement vouchers. Pick one:
Self-managed: pass a hot Ed25519 key that does not need SOL or tokens. Facilitator-delegated: the server picks up
extra.receiverAuthorizer from the facilitator’s /supported response; the facilitator signs claim vouchers after correlating deposit and claim settles to the same authenticated caller. The server validates this at startup — if no local signer is configured and the facilitator does not advertise a valid receiverAuthorizer, initialize() fails before the first request.
For custom facilitator implementations, use UptoSvmScheme from the facilitator package. The scheme’s rent cleanup manager asynchronously seals and reclaims rent from abandoned channels:
- TypeScript
- Go
Examples
- TypeScript server example (EVM + SVM)
- TypeScript facilitator example (EVM + SVM)
- Go server example (SVM)
- Go facilitator example (SVM)