Pricing
Price a route in solana_pay_kit — typed USD amounts, the Gate.build DSL, a Pricing registry, fee splits, and dynamic per-request pricing.
A gate is a frozen value object built with Gate.build: an amount, an ordered list of accepted protocols, and zero or more named fees. The amount is a Price from usd(...).
Amounts
from solana_pay_kit import usd, Stablecoin
usd("0.10") # $0.10, default settlement (USDC)
usd("0.10", Stablecoin.USDC, Stablecoin.PYUSD) # narrow/order the settlement assetsThe Gate DSL
from solana_pay_kit import Gate, Protocol, usd
# Simple. Customer pays $0.10, pay_to nets $0.10.
Gate.build(name="report", amount=usd("0.10"), description="Premium report")
# x402-only.
Gate.build(name="api_call", amount=usd("0.001"), accept=(Protocol.X402,))
# Stripe-Connect "application fee": customer pays $10.00, SELLER nets $9.70,
# PLATFORM nets $0.30. x402 auto-disabled (fees need MPP).
Gate.build(name="marketplace_sale", amount=usd("10.00"),
pay_to=SELLER, fee_within={PLATFORM: usd("0.30")})
# Surcharge: customer pays $10.50, SELLER nets $10.00, PLATFORM nets $0.50.
Gate.build(name="ticket", amount=usd("10.00"),
pay_to=SELLER, fee_on_top={PLATFORM: usd("0.50")})fee_within carves a fee out of the amount (the recipient nets less); fee_on_top adds a surcharge on top (the customer pays more, the recipient nets full).
Registry and inline
Lift multiple gates into a Pricing subclass and reference them by name, or pass a bare price for a one-off:
from solana_pay_kit import Pricing
class Catalog(Pricing):
def __init__(self):
defaults = {"default_pay_to": solana_pay_kit.config().effective_recipient()}
self.report = Gate.build(name="report", amount=usd("0.10"), **defaults)
catalog = Catalog()
@app.get("/report")
@require_payment("report", pricing=catalog)
def report(): ...
# Inline: skip the registry, pass a price directly.
@app.get("/oneoff")
@require_payment(usd("0.25"))
def oneoff(): ...Dynamic pricing
@gate("tiered")
def tiered(request):
return usd("5.00") if request.args.get("tier") == "premium" else usd("0.10")Boot-time validations raise ConfigurationError (or a subclass): pay_to is required, a fee recipient must differ from pay_to, fees share one denomination with the amount, sum(fee_within) <= amount, and a fee-bearing gate cannot be accept=(Protocol.X402,) (raises ProtocolIncompatibleError).