Inspiration

Stripe charges 2.9% + $0.30 per transaction. PayPal takes 2.2% + $0.30. For a digital artist selling 150 prints a month at $50 each, that's $174 disappearing every month — just to move money.

Meanwhile, Solana settles a transaction in ~400ms for $0.00025. The technology to fix this has existed for years. The developer-friendly infrastructure to actually use it hasn't.

That gap is why Blew exists.

We didn't build Blew because crypto payments are trendy. We built it because every time a small creator, freelancer, or online store processes a payment today, they're silently taxed by infrastructure that hasn't meaningfully improved in 15 years. Web2 payment processors were designed for a world before blockchains. Merchants are still paying for that legacy — literally.


What it does

Blew is a drop-in Solana payment widget that lets any merchant accept crypto payments on their website in under 5 minutes.

import { BlewWidget } from '@blew/widget'

<BlewWidget
  merchantId="your_merchant_id"
  amount={50}
  token="SOL"
  onSuccess={(data) => fulfillOrder(data.paymentId)}
  onError={(err) => handleError(err)}
/>

That's the entire integration. Everything else — wallet connection, blockchain confirmation, webhook delivery, retry logic, dashboard — is handled by Blew.

The full payment lifecycle, in 15 seconds:

  1. Customer clicks "Pay with Crypto" → Blew modal appears
  2. Customer connects their Phantom wallet (one click)
  3. Customer approves the transaction in their wallet
  4. Solana confirms the transaction on-chain (~5–10s)
  5. Blew verifies the signature via RPC, updates payment status
  6. HMAC-signed webhook fires to merchant's backend
  7. Merchant fulfills the order automatically
  8. Customer sees a success screen with their blockchain proof

No 2–3 day clearing windows. No chargeback disputes. No 2.9% cut taken by a middleman.

For merchants, Blew provides:

  • A React widget (@blew/widget) that embeds into any checkout page
  • A REST API for payment lifecycle management
  • A merchant dashboard with revenue charts, transaction history, and webhook logs
  • Signed webhook delivery with automatic retry (exponential backoff, up to 5 attempts)
  • SOL and USDC support out of the box

How we built it

Blew is a Turborepo monorepo with three independent packages that compose into a full payment system:

@blew/types

The shared TypeScript contract layer. Both the widget and the API import from here, so the PaymentResponse, TransactionStatus, WebhookPayload, and every other interface is defined once and never duplicated. This was the first thing we built — getting the types right made everything else faster.

@blew/widget (React + Vite + Tailwind)

A self-contained React component that handles the entire client-side payment UX. Key implementation decisions:

  • Props-driven: all behavior controlled by the parent; no internal routing or global state
  • Encapsulated styles: Tailwind scoped to the widget so it never bleeds into the host site's CSS
  • useTransaction hook: polls the Blew API for confirmation status with smart exponential backoff (2s → 4s → 8s → 16s cap), so we're not hammering the RPC endpoint during high traffic
  • useWallet hook: wraps Phantom wallet connection, keeping wallet lifecycle concerns separate from payment logic
  • Ships as both ESM and CommonJS so it works in any build system

@blew/api (Next.js + Prisma + PostgreSQL + Solana Web3.js)

The backend is a Next.js app handling everything from merchant auth to blockchain verification. The payment flow on the server side:

  1. POST /api/payments authenticates the merchant via API key, creates a temporary Solana account to receive funds (so each payment has a unique destination), records a pending payment in PostgreSQL with a 5-minute expiry
  2. The widget polls GET /api/payments/[id] — the handler queries the Solana RPC for the transaction signature and updates status to confirmed once finality is reached
  3. On confirmation, lib/background-jobs.ts fires a webhook to the merchant's registered URL, signs the payload with HMAC-SHA256 using their webhook secret, and schedules retries if delivery fails
  4. GET /api/dashboard/stats and /chart aggregate transaction data for the merchant dashboard

Auth uses API keys on all payment endpoints and JWT for the dashboard session. Every API response goes through a standardized response formatter so error shapes are consistent across the entire API surface.

Database schema (PostgreSQL + Prisma): Merchant, Payment, WebhookLog, ApiKey — with indexes on [merchantId, status, createdAt] for dashboard query performance.


Challenges we ran into

The temporary account problem. Solana payments need a destination address. We initially considered routing all payments to the merchant's wallet directly, but that makes verification ambiguous — how do you tell which payment is which when multiple customers are paying the same address simultaneously? We moved to generating ephemeral keypairs per payment, which makes confirmation deterministic and eliminates collision entirely.

Webhook reliability. A confirmed blockchain transaction means nothing if the merchant's server is down when the webhook fires. We built a retry system with exponential backoff and a WebhookLog table that tracks every attempt, response code, and timestamp — so merchants can diagnose exactly what happened on any delivery. This turned out to be one of the most important features for merchant trust.

Monorepo build order. With three packages that have cross-dependencies, getting the Turbo pipeline right so @blew/types always compiles before @blew/api and @blew/widget took more iteration than expected. The payoff was zero duplicated type definitions across the entire codebase.

Widget isolation. Embedding a third-party React component into an arbitrary merchant website means you're at the mercy of whatever CSS they're running. We spent real time ensuring Blew's styles are fully scoped and the widget renders correctly regardless of the host site's stylesheet.


Accomplishments that we're proud of

  • 15-second end-to-end payment from customer click to merchant webhook delivery — including blockchain confirmation
  • A widget so simple that integration is a copy-paste, not a project
  • Zero-dependency payment verification: we check the Solana RPC ourselves, we don't trust the client
  • Webhook signing with HMAC-SHA256 — merchants can cryptographically verify every event Blew sends them
  • A real merchant dashboard that shows revenue trends, per-transaction details, webhook delivery status, and SOL volume over time

What we learned

Blockchain infrastructure is ready. The gap isn't the chain — Solana is fast, cheap, and reliable. The gap is the developer experience layer on top of it.

Building Blew taught us that abstracting Web3 complexity is a product problem, not a technical one. The hard part isn't connecting to Solana — it's designing a system where a developer who knows nothing about crypto can integrate crypto payments in an afternoon, and a merchant who knows nothing about blockchains can read their payment dashboard and understand it immediately.

We also learned to build for failure first. The webhook retry system, the exponential backoff in the widget, the payment expiry logic — none of these are the happy path. But they're what separates a demo from a real payment system that merchants can actually trust with their revenue.


What's next for Blew

  • USDC-first mode: stablecoin payments for merchants who want USD-denominated receipts without volatility exposure
  • No-wallet checkout: generate a Solana pay QR that any mobile wallet can scan, removing the browser extension requirement
  • Fiat offramp integration: let merchants auto-convert SOL to USD via exchange APIs, so they never have to think about price exposure
  • Multi-chain support: abstract the widget interface so the same <BlewWidget /> component can route to Solana, Ethereum L2s, or other chains based on merchant config
  • Subscription billing: recurring payment schedules on-chain for SaaS businesses and creator subscriptions
  • SDK for non-React: vanilla JS and Vue adapters so Blew isn't React-exclusive

The infrastructure is built. The widget works. The next step is making Blew the default way developers think about accepting crypto payments — not as a blockchain project, but as a payment product that happens to be faster, cheaper, and more transparent than anything that came before it.

Built With

Share this project:

Updates

Submission history