Presets & self-test
The fastest way to accept a payment
Section titled “The fastest way to accept a payment”The presets are named sugar over createPaymentGate:
say what you’re selling instead of wiring a gate. Each one resolves to a standard gate, so the
402 it builds is byte-identical to the hand-written equivalent: no new wire, no new behaviour,
just less to type and a clearer mental model. token defaults to USDC; every other
createPaymentGate option (onPaid, exact, receipts, discovery, isUsed/markUsed, …) still
works.
createPaywall: a fixed price for a resource
Section titled “createPaywall: a fixed price for a resource”The API / SaaS / premium-content case: one resource, one price.
import { createPaywall, toWorker } from '@piprail/sdk'
const gate = createPaywall({ chain: 'base', amount: '0.05', payTo: '0xYourWallet' })// token defaults to USDC. Drive it with any adapter:export default toWorker(gate, () => Response.json({ report: 'unlocked' }))| Option | Required? | Notes |
|---|---|---|
chain | required | EVM ('base', 'bnb', …) or a non-EVM family name. |
amount | required | The fixed price, e.g. '0.05'. |
payTo | required | Your receiving address, with no private key (receiving needs only the address). |
token | default 'USDC' | A symbol, 'native', or a custom { address, decimals }. |
| …rest | optional | Any other createPaymentGate option (onPaid, exact, receipts, …). |
createTipJar: pay what you want (≥ a minimum)
Section titled “createTipJar: pay what you want (≥ a minimum)”The creator / tip / donation case. The gate is priced at min, and the on-chain verify rejects only
an under-payment (amount_too_low), so a payer can always give more. The minimum is a floor,
not a fixed price.
import { createTipJar } from '@piprail/sdk'
const gate = createTipJar({ chain: 'base', min: '1.00', payTo: '0xYourWallet' })// accepts any payment ≥ 1.00 USDC.gate.selfTest(): “did I wire this right?”
Section titled “gate.selfTest(): “did I wire this right?””A read-only config check that never throws and never signs or sends. It resolves the gate’s
rails (the same lazy resolution the first challenge() does) and reports what it would charge, or
why it can’t. Perfect for a startup assertion or an npm run verify script before you deploy.
const result = await gate.selfTest()// {// ok: true,// rails: [{ network: 'eip155:8453', asset: '0x833…', symbol: 'USDC',// decimals: 6, amount: '0.05', payTo: '0x…', schemes: ['onchain-proof'] }],// warnings: [],// }
if (!result.ok) throw new Error(`Gate misconfigured: ${result.error}`)A malformed payTo, an unknown token, or an unresolvable chain returns { ok: false, error }, never
an exception. A custom token with no built-in symbol is surfaced as a non-fatal warning.
Driving the gate
Section titled “Driving the gate”A preset returns the same PaymentGate
as createPaymentGate, so drive it with the built-in
framework adapters: toFetchHandler for any fetch
runtime (Next.js, Netlify, Bun, Deno, Hono, Vercel, …) or toWorker for Cloudflare, or
requirePayment for Express.