A crypto payment button you drop into any website.

One tag, a few lines. No backend, no payment processor, no middleman that can freeze your funds or shut you down.

Get started See it work

What it is, and why

<peer-pay> is a single Web Component that lets visitors send you stablecoins (USDC/USDT) across several chains, straight from their wallet to yours. It's the whole integration — no SDK, no API keys, no server to run.

No middleman

No Stripe, no PayPal, no processor between you and your money — nobody who can freeze funds, take a cut, or de-platform you. Payments go peer to peer, wallet to wallet.

No backend

It's a static script. Reference our hosted bundle or self-host it. Nothing to deploy, nothing to secure, nothing that can go down.

Lightweight & self-hostable

One self-contained file, ~30 KB, with no runtime dependencies (no ethers/web3 bloat). Host it yourself and you depend on no one, not even us.

Drops in anywhere

Plain HTML, React, a no-code site builder — it's a standard custom element. A non-technical person (or their AI) can wire it up by changing one address.

Honest by design: PeerPay collects payments — it does not authorize access. The “paid” signal happens in the visitor's browser, so it's perfect for tips, donations, and honor-system payments, but it can be faked or replayed. Never gate paid features on it alone — if a payment unlocks something an attacker would profit from bypassing, re-verify the transaction on a server (or on-chain) you control.

See it work — sandbox

This demo runs against a fake wallet: click the button, approve nothing, spend nothing. You'll see the exact transaction PeerPay would send on-chain.

SANDBOX · no funds move
Click the button…

Want to restyle it and grab the snippet? Head to the Playground.

Install & use

1. Reference the library

<script src="https://peerpay.publicwerx.org/peerpay.js"></script>

One hosted bundle, no build step. Prefer to self-host? Drop the same file on your own server — it's a single static script with zero dependencies.

2. Drop in the tag

<peer-pay recipient="0xYourWallet" amount="5" theme="dark"></peer-pay>

That's the whole integration. Change 0xYourWallet to the address you want paid.

Attributes

AttributeDefaultNotes
recipientrequiredWallet that receives the payment
amount1Whole dollars (stablecoins are 6-decimal)
tokenUSDCUSDC or USDT — or USDC,USDT to let the payer choose
chainsallmantle,base,arbitrum,optimism,polygon,avalanche (first = default)
themelightlight · dark · minimal · rounded
labelTip $N TOKENButton text
qronqr="off" hides the "pay with a phone" QR (mobile / no-extension)

Theme it to match your site

peer-pay {
  --peerpay-accent: #e91e63;
  --peerpay-radius: 14px;
  --peerpay-font: 'Poppins', sans-serif;
}

Six CSS variables (--peerpay-accent · -bg · -text · -radius · -font · -width) plus ::part(button) for full control. They pierce the shadow DOM, so they just work.

Know when someone pays

document.querySelector('peer-pay')
  .addEventListener('paid', (e) => {
    // e.detail = { txHash, chain, token, amountUnits, explorer }
    // Honor-system only. Re-verify server-side before unlocking value.
  });

On mobile — pay with a phone

When a visitor has no wallet browser extension, PeerPay automatically shows a QR code (an EIP-681 payment URI) that they scan with any wallet app — no WalletConnect, no SDK, no relay server. A “📱 Pay with a phone” toggle also reveals it on desktop. Hide it entirely with qr="off".

One caveat to know: a QR / phone payment happens inside the wallet app, so it does not fire the paid event — the page can't observe it. That's fine for tips and donations; if you need confirmation, re-verify the transfer on-chain. You can try a real one in the Playground (“Test it for real”).