Bubl

Developer Docs

This page documents how to integrate payments, connect wallets, and use the APIs in this app.

API endpoints

All endpoints are under the Next.js App Router. Unless noted, endpoints return JSON.

  • Auth
    • /api/auth/signup POST: body { email, password, name? } — creates user, sets httpOnly session cookie.
    • /api/auth/login POST: body { email, password } — verifies credentials, sets session cookie.
    • /api/auth/me GET: returns current user or null.
    • /api/auth/logout POST: clears session.
  • Payment requests
    • /api/requests POST: create a request. Body fields:
      • amountUsd string (required; > 0).
      • chainFamily string (e.g. "Solana").
      • chainLabel string (e.g. "Solana").
      • walletLabel string (e.g. "Phantom").
      • payeeAddress string (required for Solana).
      • note string ≤ 140 chars (optional).
      • singleUse boolean (default true; if signed in and set to false, creates reusable link).
      • slug string (optional; name for reusable links; sanitized and unique).
      For Solana, the server calculates amountCrypto and amountAtomic (lamports) using a price from CoinGecko with a fallback. Returns the created object and a link like /pay/:id.
    • /api/requests/{id} GET: returns a payment request.
    • /api/requests/{id} POST: mark paid; body { txHash, payerAddress? }.
    • /api/requests/history GET: query recent requests; supports q, limit, offset, withHash.
    • /api/requests/latest GET: latest paid requests (limit 1–10 via limit).
    • /api/requests/latest-note GET: latest request that has a note.
  • Payments helpers
    • /api/payments/mark-pending POST: body { id, txHash, payerAddress? } — set status to pending.
    • /api/payments/mark-confirmed POST: body { id, txHash } — set status to paid.
    • /api/payments/monitor GET: server-side checker for pending Solana txs; transitions to paid if confirmed.
  • Links (reusable)
    • /api/links GET: list your links (requires session). Query type: sticky (default), solo, or all.
    • /api/links POST: create a reusable link for signed-in user. Body includes title, amountUsd, chain/wallet labels, etc.
    • /api/links/{slug} DELETE: delete a reusable link (slug or id), requires session.
  • Solana
    • /api/solana/rpc POST: transparent proxy to server-side RPC (HELIUS_RPC_URL or SOLANA_RPC_URL).
    • /api/solana/verify POST: signature verify. Body { address, msgBase64, sigBase64 }{ ok: boolean }.
    • /api/pay/verify GET: verifies signed paylink query params using HMAC secret PAYLINK_HMAC_SECRET.
    • /api/price/native GET: demo native-per-USD price endpoint.
  • Account metrics
    • /api/account/metrics GET: requires session; returns counts and deltas for dashboard KPIs.

Solana smart contract

This repo includes an optional fee-splitting Anchor program for native SOL:

  • Program ID: 7rAnjqHaEvXdyREsJMWoo9CBV3KCycsES3fKfJMGXbQD (see p2p_fee_sol/programs/p2p_fee_sol/src/lib.rs).
  • Instruction pay_with_fee_sol(amount: u64, fee_bps: u16) splits lamports: fee goes to treasury, net to payee. Max fee is enforced by config PDA seeds = ["cfg"].
  • Client builds the instruction with buildPayWithFeeSolIx in src/lib/solana-fee-program.ts.

If env vars NEXT_PUBLIC_FEE_PROGRAM_ID, NEXT_PUBLIC_TREASURY_ADDRESS, and NEXT_PUBLIC_FEE_BPS are set, the payer flow uses the program; otherwise it falls back to a simple SystemProgram transfer.

Wallet connection

  • Adapters: Phantom, Solflare, WalletConnect (Reown) via src/app/solana-providers.tsx.
  • RPC: Browsers point to /api/solana/rpc proxy to avoid exposing server RPC keys. Optional NEXT_PUBLIC_SOLANA_WS for websockets.
  • WalletConnect metadata: Uses NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID and NEXT_PUBLIC_APP_URL for universal return links.
  • Send flow: See SolanaPayer. It builds and sends a transaction, marks pending, polls confirmation, then marks paid.

Webhook and callback examples

The app uses simple callback endpoints instead of push webhooks. You can poll /api/requests/{id} or leverage /api/payments/monitor for Solana confirmations on the server.

POST /api/requests/{id} Body: { "txHash": "<signature>", "payerAddress": "<base58>" } GET /api/requests/{id} → { id, amountUsd, status: "pending" | "paid", txHash?, ... }

Integration flow

  • Create a request via POST /api/requests with the payee address and USD amount.
  • Present the payer UI at /pay/{id}. For Solana, the component renders a connect and send button via wallet-adapter.
  • On send, the client calls /api/payments/mark-pending with the transaction signature.
  • The client polls or waits for confirmation; on success, it calls /api/payments/mark-confirmed or updates via /api/requests/{id} POST.
  • Optionally, run /api/payments/monitor on a schedule to confirm any pending Solana payments server-side.

Telegram bots can follow the same flow by generating the link and opening /pay/{id} in a Web App or by sending a deep link to the user; confirmations are read via the APIs above.

Custodial vs. non‑custodial

  • Non‑custodial by default: The payer signs and submits transactions directly from their wallet. The app never holds private keys.
  • Optional fee program: If configured, fee‑on‑top is enforced on‑chain by the program; still non‑custodial.
  • Server data: Only payment metadata and public addresses are stored in Postgres.

Security and compliance

  • Sessions: httpOnly JWT cookie (AUTH_JWT_SECRET) with HS256; validated server-side.
  • RPC proxy: Browser calls go through /api/solana/rpc to avoid exposing HELIUS_RPC_URL/SOLANA_RPC_URL.
  • Signature verify: /api/solana/verify uses ed25519 to validate signatures.
  • Paylink integrity: Optional HMAC (PAYLINK_HMAC_SECRET) for signed query params via /api/pay/verify.
  • Input validation: Zod validation in endpoints; Solana addresses base58/32-byte checked.
  • Data: Prisma with parameterized queries; indices on frequently filtered fields.
  • Compliance: This app is a non‑custodial payment link frontend. If operating as a hosted service, assess your jurisdiction for VASP/Money Services requirements, KYC/AML obligations, and terms for Web3 wallets.

Environment

Public NEXT_PUBLIC_APP_URL NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID NEXT_PUBLIC_SOLANA_RPC NEXT_PUBLIC_SOLANA_WS NEXT_PUBLIC_FEE_PROGRAM_ID NEXT_PUBLIC_TREASURY_ADDRESS NEXT_PUBLIC_FEE_BPS Server-only DATABASE_URL HELIUS_RPC_URL / SOLANA_RPC_URL AUTH_JWT_SECRET PAYLINK_HMAC_SECRET (optional) WALLET_ENCRYPTION_KEY (reserved)
See also home and the payer page at /pay/[id].