Skip to content

ponkssol/Breakpot_earn

Repository files navigation

BreakPot

Break bricks. Hit jackpots. Earn crypto.

Backend audit rules and guidelines

Use this checklist when reviewing or hardening the server-side surface (backend/ local Express app and api/ serverless HTTP handlers). Treat both as one logical backend: behavior and security assumptions must stay aligned.

Scope and consistency

  • Dual entrypoints: Local dev uses backend/server.js; production HTTP API lives under api/*.js. Any change to routes, validation, limits, or Solana flows should be reflected in both places unless intentionally documented otherwise.
  • Single source of truth: Prefer shared logic in backend/services, backend/utils, and backend/db.js; avoid duplicating business rules only in api/ without the same checks in the Express path (or vice versa).
  • Environment: Verify required secrets only exist server-side (DATABASE_URL, PRIVATE_KEY, SOLANA_RPC_URL, TOKEN_MINT_ADDRESS, etc.). Never log or return raw secrets, key material, or full connection strings in responses or client-visible errors.

Security

  • Authentication model: Public endpoints accept a wallet_address string; there is no cryptographic proof of wallet ownership on submit/claim in the default flow. Audit any new endpoint that moves funds or changes persistent state: document trust boundaries and whether spoofing a wallet address is an accepted risk or mitigated elsewhere.
  • Private keys: Reward/signing keys must only run on the server. Confirm no PRIVATE_KEY (or equivalent) is bundled in the frontend build or exposed via VITE_* variables.
  • Input validation: All externally supplied fields must pass the same validation as in backend/services/validationService.js (wallet format, score bounds, optional IDs). Reject malformed input with 4xx, not 5xx.
  • Rate limiting and abuse: submit-score is rate-limited per wallet (and IP fallback). When adding write endpoints, define per-identity and per-IP limits and document them in this README.
  • Dependencies: Periodically run npm audit and review high/critical findings; pin or upgrade risky transitive dependencies when fixing production issues.
  • Headers and CORS: Local server uses helmet and cors; serverless handlers should not weaken security headers without a documented reason.

Data and database

  • Migrations: Schema changes belong in backend/schema.sql and/or numbered files under backend/migrations/. Audit that production databases have applied every migration and that constraints match application assumptions (e.g. score caps, claim columns).
  • SQL: Use parameterized queries only (backend/db.js pattern). No string-concatenated user input into SQL.
  • Integrity: Claim/submit flows should avoid double-claim and inconsistent state; review markClaimed, idempotency, and transaction ordering (e.g. build Solana tx before marking claimed where that pattern is used).

Solana and payouts

  • RPC reliability: Handle RPC/mint/ATA failures without corrupting DB state; users should be able to retry when appropriate.
  • Transaction semantics: Document who pays fees, partial signing vs co-signing, and what the client is expected to sign. Any new path that broadcasts from the server must be reviewed for replay, amount correctness, and destination addresses.
  • Economics: Reward calculation (rewardTokensFromScoreRow and related) must match product rules; audit for overflow, rounding, and maximum payout bounds.

Observability and operations

  • Errors: Prefer stable error / code fields for clients; avoid leaking stack traces or internal paths in production responses.
  • Health: Confirm /health (or equivalent) for the local server and any deploy probes stay lightweight and unauthenticated only if acceptable for your threat model.
  • Logging: Log structured, non-sensitive context (request id, route, outcome); redact wallet addresses if policy requires minimal PII retention.

Release checklist (short)

  1. Env vars documented and set on the server (and local .env from .env.example).
  2. Migrations applied to the target database.
  3. Submit score + claim + any new endpoints manually tested against staging RPC and DB.
  4. No secret or private key in repo, client bundle, or public logs.

This project uses one codebase for the frontend and backend API:

  • Frontend: React + Vite + TailwindCSS + Phaser + Solana Wallet Adapter (Phantom)
  • Backend API: serverless HTTP routes (/api) + PostgreSQL (Neon) + @solana/web3.js + @solana/spl-token

Features

  • Brick breaker with unified pointer controls (mouse and touch drag)
  • Live score at the top center
  • Random jackpot brick per game:
    • Value 1000
    • Blink animation
    • White outline
    • Light transparency
  • Full black background, white UI (minimal)
  • Gameplay only after the wallet is connected
  • Game over panel:
    • Score
    • Submit score
    • Claim
  • API: submit score + claim SPL reward (serialized transaction)

Structure

  • src/game Phaser logic
  • src/components UI / wallet / game container
  • src/pages main React page
  • api serverless API for production deploy
  • backend/routes API routes
  • backend/controllers API controllers
  • backend/services DB / validation / Solana

Setup

  1. Install dependencies:
npm install
  1. Copy env:
cp .env.example .env
  1. Create tables in Neon/PostgreSQL:
-- run the contents of backend/schema.sql
  1. Run the backend:
npm run dev:backend
  1. Run the frontend (another terminal):
npm run dev:frontend

Defaults: frontend http://localhost:5173, backend http://localhost:3001.

Single-project server deploy

  1. Connect this repository to your host as one project (frontend + API).
  2. Add environment variables:
    • SOLANA_RPC_URL
    • PRIVATE_KEY
    • TOKEN_MINT_ADDRESS
    • DATABASE_URL
    • VITE_SOLANA_RPC_URL
  3. Deploy. Frontend and API share one origin:
    • Frontend: https://your-domain.com
    • API: https://your-domain.com/api/submit-score and /api/claim

The frontend uses relative /api/... paths, so you do not need a separate API base URL.

API

POST /api/submit-score

Body:

{
  "wallet_address": "....",
  "score": 120
}

Validation:

  • Max score up to PostgreSQL INT max (app-enforced); use backend/migrations/001_relax_score_max.sql if upgrading from an old 2000 cap
  • Rate limit: 5 requests / minute / wallet

POST /api/claim

Body:

{
  "wallet_address": "....",
  "score_id": "optional-uuid"
}

Logic:

  • Resolve the unclaimed score row (by score_id or latest unclaimed)
  • Reward is whole tokens 1:1 with the stored score (see rewardTokensFromScoreRow)
  • Mark the row claimed
  • Build a partially signed SPL transfer; user signs in Phantom
  • Return serializedTransaction as base64

Security notes

  • Never expose the reward wallet private key to the frontend
  • The user still signs the transaction in Phantom
  • Transaction fee payer is the user wallet

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages