Self-hosted crypto paywall for digital downloads. Sell any file for USDC (or any ERC-20) with automatic on-chain verification - no Stripe, no PayPal, no accounts, no middleman. Payments land directly in your wallet.
git clone https://github.com/ShavitR/cryptopaywall && cd cryptopaywall
node bin/prepare.js your-product.zip --name "My Product" --price "$9 USDC"Paste the printed variables into the Vercel deploy button below. Done - share your storefront URL.
Or skip deploying entirely with a Payment Link: one URL, hosted checkout, any wallet.
Live demo: SubSniff store - a real product sold through this exact code.
No deployment needed if you host this repo anywhere: build an instant hosted checkout for any wallet with one URL:
https://your-deployment.vercel.app/api/link?to=0xYOUR_WALLET&amount=9&chain=base&name=My%20Product
Buyers see a clean checkout page (price, QR, your address), pay in USDC on the chains you enable (ethereum, base, polygon), paste their transaction hash, and get on-chain-verified confirmation. Optional params: redirect (send verified buyers to your success page with a signed receipt token), token (any ERC-20 contract), decimals.
This is CryptoPaywall's answer to Stripe Payment Links: self-serve, stateless, no account.
Public and simple, like everything here: the core engine is free forever (MIT), the Pro Pack is $19 one-time (webhooks + manual links + future Pro updates). Full breakdown in PRICING.md.
buyer sends USDC to your wallet (any supported chain)
|
v
buyer pastes the tx hash on your storefront page
|
v
/api/unlock -> eth_getTransactionReceipt via public RPCs
verifies: tx succeeded, ERC-20 Transfer event,
correct token contract, YOUR address as recipient,
amount >= your minimum
|
v
HMAC-signed 24h download token -> /api/download streams the file
No database. No API keys. Nothing to trust but the chain.
- Prepare your environment variables with the built-in helper (run from this repo):
node bin/prepare.js your-product.zip --name "My Product" --price "$9 USDC"It base64-encodes the file and prints every variable ready to paste - including a generated PAYWALL_SECRET and a default 3-chain CHAINS config.
- Click the Deploy button above (free Vercel account needed).
- Fill in the environment variables:
| Variable | Required | Meaning |
|---|---|---|
MERCHANT_ADDRESS |
yes | Your wallet address (receives payments) |
PRODUCT_NAME |
yes | Display name + download filename |
PAYWALL_SECRET |
yes* | Random string used to sign download links (*required for production) |
PRODUCT_ZIP_B64 |
yes | Base64 of the file you are selling |
CHAINS |
one of* | JSON array of accepted chains, e.g. [{"name":"Base","token":"0x8335...2913","decimals":6,"minWei":"1000000","rpcs":["https://mainnet.base.org"]}] |
TOKEN_CONTRACT |
one of* | Single-chain mode: ERC-20 contract, e.g. USDC 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
TOKEN_DECIMALS |
with single-chain | 6 for USDC/USDT, 18 for most tokens |
MIN_ACCEPT_UNITS |
no | Smallest payment that unlocks (base units). Default 1 |
PRICE_LABEL |
no | Text like $9 USDC shown as suggested price |
RPC_URLS |
no | Comma-separated JSON-RPC endpoints for single-chain mode |
* Set either CHAINS (multi-chain, recommended - accept USDC on Ethereum AND Base AND Polygon so buyers pay cents in gas instead of dollars) or the single-chain trio. Example multi-chain value:
[
{"name":"Ethereum","token":"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48","decimals":6,"rpcs":["https://ethereum-rpc.publicnode.com"]},
{"name":"Base","token":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","decimals":6,"rpcs":["https://base-rpc.publicnode.com"]}
]- Set a strong
PAYWALL_SECRET(e.g. two GUIDs concatenated). - Done - share your storefront URL.
npm test11 unit tests cover the verification core: qualifying payments, below-minimum rejection, wrong recipient, wrong token, failed transactions, multi-chain routing (payment found on a later chain, none anywhere, RPC errors surviving), and token signing/tampering/expiry.
- Verification is per-transaction-hash; the same hash can unlock again within the token window. For high-value files, add rate limiting or one-time tokens.
- Public RPCs can rate-limit under heavy traffic; set your own node or paid endpoint in
rpcs/RPC_URLSfor scale. - The download is served from the deployment itself (
PRODUCT_ZIP_B64). Keep files under ~4 MB, or point/api/downloadat object storage for larger assets. - EVM chains only (anything speaking Ethereum JSON-RPC where your token lives).
MIT