🤝How It Works

Architecture

Smart Contract (Base L2)
       |
Backend API (Express + PostgreSQL)
       |
       +-- Frontend (Next.js on Vercel)
       +-- Discord Bot
       +-- Telegram Bot
       +-- SDK (npm package)

Payment Flow

Subscriber pays $10 USDC
  |
  +-> 95% ($9.50) --> Creator's wallet
  +-> 5%  ($0.50) --> Platform wallet
  1. Creator registers on-chain with a monthly USDC price

  2. Subscriber calls subscribe(creator, months) on the contract

  3. USDC is split automatically: 95% to creator, 5% platform fee

  4. Subscription expiration timestamp is stored on-chain

  5. Backend indexer picks up the event within 30 seconds

  6. Access is granted through Discord, Telegram, SDK, or API

circle-info

The smart contract is the source of truth. The backend indexes events for fast queries, but on-chain data always wins.

Access Control Methods

Method
How It Works
Best For

Discord

Bot assigns/removes roles based on sub status

Community servers

Telegram

Bot manages private group access

Private alpha groups

SDK

checkAccess() reads the contract directly

Custom apps/sites

API

GET /api/gate/check with your API key

Backend integrations

Widget

Embeddable subscribe form for any website

Landing pages/blogs

Subscription Lifecycle

circle-exclamation
  • subscribe() — creates a new subscription (reverts if already active)

  • renew() — extends an existing or expired subscription

  • Maximum 12 months per transaction

  • Manual renewal only (no auto-charge, no recurring payments)

Event Indexer

The backend runs a background indexer that:

  1. Polls the blockchain every 30 seconds

  2. Fetches all contract events in a single RPC call per chunk

  3. Writes events to PostgreSQL (append-only subscription_events table)

  4. Updates materialized projections (subscriptions_current, creator_metrics)

  5. Uses a cursor (indexer_state) to track progress

  6. Has exponential backoff on rate limits (429 errors)

  7. Prevents overlapping syncs with an in-memory lock

The frontend can trigger an immediate sync after a transaction via POST /api/index/sync.

Was this helpful?