Skip to content

Presets & self-test

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' }))
OptionRequired?Notes
chainrequiredEVM ('base', 'bnb', …) or a non-EVM family name.
amountrequiredThe fixed price, e.g. '0.05'.
payTorequiredYour receiving address, with no private key (receiving needs only the address).
tokendefault 'USDC'A symbol, 'native', or a custom { address, decimals }.
…restoptionalAny 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.

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.