PayMe is a private subscription and payments system built on ERC-4337 account abstraction, WebAuthn passkeys, and Zama fhEVM.
This repository contains the frontend application, smart contracts, deployment scripts, and supporting documentation for the current prototype.
- Project Overview
- Implementation Status
- System Scope
- Core Technologies
- Repository Structure
- Personas and Use Cases
- Protocol Flow
- Component Interaction View
- Detailed Architecture
- Contract Design
- Data and State Model
- Merchant Subscription Operations
- API Surface
- Security and Trust Boundaries
- End-To-End Flow
- Getting Started
- Local Development
- Testing
- Developer Workflow
- Technical Notes
- Mainnet Readiness Notes
- References
PayMe covers the recurring payment flow for a customer and a merchant:
- customer wallet onboarding with passkeys
- encrypted subscription approval and first charge
- merchant plan creation and recurring billing execution
- billing failure tracking and retry/recovery handling
The current codebase is split across:
frontendfor customer and merchant routeshardhatfor smart contracts and deploymentdocsfor network and operational notesfrontend/src/lib/fhevm-sdkfor the fhEVM integration layer
Current implementation status in this repository:
- customer approval and merchant renewal flows are implemented
- merchant plan, billing, and recovery screens exist in the frontend
- the embedded checkout route is implemented
- merchant control plane is backed by PostgreSQL (Supabase) with Drizzle ORM
- customer activities and subscriptions are persisted server-side
- Sepolia is the current active network target
This repository includes:
- passkey-secured smart account onboarding
PrivateCarddeployment and subscription approval flow- merchant plan registration and billing cycle execution
- encrypted input handling through the relayer SDK
- local merchant metadata for agreements, attempts, and recovery
ERC-4337(EntryPoint,UserOperation, bundler/paymaster-compatible flow)WebAuthn/ passkeys for keyless user signing UXZama fhEVMand relayer SDK for encrypted input and decrypt workflowsPostgreSQL(Supabase) andDrizzle ORMfor merchant control plane persistenceHardhatfor deployment and contract testingNext.jsfrontend and API routes for UX + relayer-side helpers + data persistence
- README.md - root overview (this file)
- frontend/README.md - frontend app details
- hardhat/README.md - contracts and deployment
- docs/mainnet.md - Sepolia vs mainnet fhEVM flow
- docs/smart-wallet-funding-flows.md - wallet funding flows
- docs/database-plan.md - production data direction
Primary implementation surfaces:
frontend/src/app- customer + merchant route surfacesfrontend/src/app/api- API routes for merchant state, customer activities & subscriptionsfrontend/src/lib/db- Drizzle ORM schema and PostgreSQL clientfrontend/src/lib/fhevm-sdk- fhEVM integration wrapper and hooksfrontend/src/app/api/fhe/sign-user-decrypt/route.ts- decryption signature routehardhat/contracts- protocol contractshardhat/deployandhardhat/scripts- deployment and wiring scripts
Primary personas:
- customer who wants private wallet balances and private subscription approvals
- merchant who needs recurring billing and retry/recovery operations
- protocol operator/developer who needs deterministic contract and deployment behavior
Main use cases supported in this repo:
- customer creates passkey-linked smart account and private card
- merchant creates plan and shares checkout reference
- customer approves encrypted subscription and executes first payment
- merchant runs renewal charges for due subscriptions
- merchant reviews failures and retries at-risk agreements
- customer and merchant inspect activity and balances with privacy-preserving flows
Frontend and App Layer:
- Next.js app and dashboard surfaces
- Customer flows: onboarding, wallet, encrypted balance, subscriptions
- Merchant flows: plans, subscriptions, billing cycles, recovery
- Embedded checkout route for approval and first charge flow
Smart Contract Layer:
PrivateCard.sol- encrypted balances/transfers/subscription approval and renewalCardFactory.sol- one card deployment per customerSubscriptionPlanRegistry.sol- merchant plan publication and references- ERC-4337 account stack and entrypoint integration
FHE / Relayer Layer:
- Browser encryption input generation
- Relayer SDK initialization and instance creation
- User decrypt signature helper route
- Gateway/KMS relay path for decrypt and verification flows
Operational Layer:
- PostgreSQL database (Supabase) for merchant plans, subscriptions, billing cycles, and customer activities
- Drizzle ORM for type-safe schema management and migrations
- bundler submits ERC-4337 UserOperations
- optional paymaster model for sponsored gas path
- deployment scripts for contract address propagation
- environment-configured chain, relayer, contract, and database endpoints
%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor':'#0ea5e9', 'primaryTextColor':'#ffffff', 'primaryBorderColor':'#0284c7', 'lineColor':'#38bdf8', 'secondaryColor':'#1e293b', 'tertiaryColor':'#334155', 'background':'#0b1220', 'mainBkg':'#111827', 'secondBkg':'#1f2937', 'labelBackground':'#1f2937', 'labelTextColor':'#ffffff', 'actorBkg':'#111827', 'actorBorder':'#0ea5e9', 'actorTextColor':'#ffffff', 'signalColor':'#38bdf8', 'signalTextColor':'#ffffff'}}}%%
sequenceDiagram
participant User as Customer
participant Merchant as Merchant Operator
participant App as PayMe App Frontend
participant MUI as Merchant Frontend
participant Checkout as /embed/checkout
participant SDK as Zama Relayer SDK
participant AA as Smart Wallet + Bundler
participant Registry as SubscriptionPlanRegistry
participant Factory as CardFactory
participant Card as PrivateCard
participant CP as PostgreSQL (Supabase)
rect rgb(38,38,68)
Note over Merchant,Registry: STEP 0 · Merchant creates plan
Merchant->>MUI: Create/Update plan terms
MUI->>AA: submit UserOperation for plan publish
AA->>Registry: register/update plan reference
MUI->>CP: store plan metadata
end
rect rgb(20,40,70)
Note over User,Card: STEP 1 · Customer wallet and card setup
User->>App: Register/Login with passkey
App->>AA: deploy/initialize smart account
AA->>Factory: createCard()
Factory-->>Card: deploy customer card
Card-->>App: cardAddress + ownership context
end
rect rgb(20,70,45)
Note over User,Card: STEP 2 · Subscription approval and first charge
Merchant->>MUI: Share checkout link
User->>Checkout: Open merchant checkout
Checkout->>SDK: encrypt amount/allowance
SDK-->>Checkout: handles + inputProof
Checkout->>AA: submit UserOperation
AA->>Card: execute card subscription call
Checkout->>CP: register agreement and cycle metadata
end
rect rgb(70,45,20)
Note over Merchant,CP: STEP 3 · Merchant billing and recovery
Merchant->>MUI: Open billing/recovery view
MUI->>CP: read due subscriptions and retry queue
Merchant->>MUI: Trigger due charges or retries
MUI->>AA: submit renewal UserOperation(s)
AA->>Card: chargeSubscriptionRefRenewal() or pullSubscriptionWithProof()
MUI->>CP: save attempt results and next cycle state
end
Implementation notes for this flow:
SubscriptionPlanRegistrystores merchant plan references on-chain.- merchant operational state is stored in PostgreSQL (Supabase) via API routes, with Drizzle ORM as the type-safe data layer.
- checkout approval is handled by
page.tsx. - billing/retry execution is handled by
page.tsx. - data is synced to Supabase on every write; frontend reads from API first with localStorage fallback during migration.
%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor':'#a78bfa', 'primaryTextColor':'#ffffff', 'primaryBorderColor':'#8b5cf6', 'lineColor':'#a78bfa', 'secondaryColor':'#0f172a', 'tertiaryColor':'#1e293b', 'background':'#0b1020', 'mainBkg':'#111827', 'secondBkg':'#1f2937', 'labelBackground':'#1f2937', 'labelTextColor':'#ffffff'}}}%%
flowchart LR
subgraph MERCHANT["Merchant Frontend"]
MPLAN["Plans Page"]
MBILL["Billing Cycles Page"]
MREC["Recovery / Retry Actions"]
end
subgraph CUSTOMER["Customer Frontend"]
CSET["Passkey + Smart Wallet Setup"]
CBAL["Balance / Decrypt Views"]
CSUB["Checkout / Subscribe"]
end
subgraph FHE["FHE Integration"]
SDK["Relayer SDK"]
DECRYPT["/api/fhe/sign-user-decrypt"]
end
subgraph ONCHAIN["On-chain Contracts"]
SPR["SubscriptionPlanRegistry"]
CF["CardFactory"]
PC["PrivateCard"]
end
MCP["PostgreSQL (Supabase)"]
CSET --> CF
CBAL --> DECRYPT
CSUB --> SDK
CSUB --> PC
CSUB --> MCP
MPLAN --> SPR
MPLAN --> MCP
MBILL --> PC
MBILL --> MCP
MREC --> PC
MREC --> MCP
This view reflects the current repo layout:
- merchant pages update both on-chain plan/card state and sync metadata to Supabase via API
- customer checkout touches the relayer SDK, submits on-chain transaction, and persists agreement data to Supabase
- all reads go through API routes that query Supabase, with localStorage as migration-period fallback
- user authentication is passkey-driven through WebAuthn
- passkey context is used to control smart account actions
- account abstraction enables programmable signing and execution policies
- no seed phrase-first UX is required for baseline usage
- frontend prepares UserOperation payloads
- bundler handles UserOp inclusion via
EntryPoint - smart account executes downstream calls to protocol contracts
- paymaster integration is optional and can sponsor transaction costs
This separation keeps UX logic in the app layer and execution guarantees in the ERC-4337 stack.
- client-side encrypted inputs are created via relayer SDK
- proof + handle payloads are submitted to contract methods
- decrypt requests are handled through relayer/gateway verification path
- app includes a helper API route for user-decrypt typed-data signatures
This preserves confidentiality of balances and limits while retaining verifiable execution on-chain.
CardFactoryis responsible for deterministic lifecycle of user cardsPrivateCardis the core confidential payment primitiveSubscriptionPlanRegistryprovides merchant plan references and ownership- confidential token mechanics are consumed through contract integration points
- manages plans, subscriptions, billing cycles, attempts, and recovery state
- persisted in PostgreSQL (Supabase) with Drizzle ORM schema management
- computes due work, retries, and at-risk subscriptions
- API routes serve state to both merchant and customer frontends
- designed with migration-ready architecture for future indexer integration
- hold/manage confidential token logic integration
- store customer subscription approvals and refs
- execute merchant renewal pulls within authorization constraints
- emit events to support merchant-side state reconciliation
- deploy and map user card instances
- enforce one-card-per-user design assumptions when configured
- expose lookup functions for UI/service resolution
- register merchant plan records and references
- anchor plan identity on-chain
- support checkout validation and merchant plan mapping
On-chain state:
- card ownership and authorization context
- encrypted subscription authorization artifacts
- plan registration metadata and refs
- renewal execution events and settlement traces
Frontend/app state:
- session state and user identity context
- dashboard projections from contract reads and API queries
- merchant operational metadata served from PostgreSQL via API routes
Control plane state (PostgreSQL):
- plan templates (
merchant_plans) - customer agreements (
subscriptions) - billing cycles (
billing_cycles) - billing attempts (
billing_attempts) - customer activity timeline (
customer_activities) - retry and recovery indicators
Operational model implemented in this prototype:
- Plan management. Merchant creates/updates plan template and plan references used by checkout.
- Agreement registration. After customer approval, merchant-side metadata stores agreement and cycle baseline.
- Billing execution. Merchant billing views compute due agreements and submit renewal execution.
- Attempt recording. Success/failure is tracked per cycle with attempt-level records.
- Recovery workflow. Failed agreements move to recovery queue for retry according to policy.
- State visibility. Merchant dashboard surfaces active, past-due, and recovery-at-risk indicators.
Why this matters:
- gives a Stripe-like operational mental model for subscriptions
- keeps confidential payment authorization on-chain
- preserves merchant-grade observability even in prototype mode
Application API routes currently used in core flow:
/api/fhe/sign-user-decrypt- returns signer address and signs typed-data payloads for user decrypt requests
/api/users/save- persists user-linked account metadata path used by app workflows
/api/users/topup- utility path for test/development funding operations
/api/debug/deploy- debug visibility into deployment/environment wiring status
/api/merchant/[address]/state- GET/POST merchant control plane state (plans, subscriptions, cycles, attempts)
/api/customer/[address]/activities- GET/POST customer activity log
/api/customer/[address]/subscriptions- GET customer subscriptions by card address
Core client integration points:
frontend/src/app/embed/checkout/page.tsxfrontend/src/lib/fhevm-sdk/internal/fhevm.tsfrontend/src/lib/fhevm-sdk/react/useFHEEncryption.tsfrontend/src/lib/merchant/control-plane-store.ts
- passkeys authenticate user intent
- smart accounts enforce execution permissions
EntryPointpath enforces ERC-4337 validation model
- amounts/limits are encrypted before on-chain submission
- relayer/gateway path is required for decrypt workflows
- service availability of relayer components impacts user experience
- customer gives subscription authorization once per agreement
- merchant-side renewals must satisfy contract constraints
- recovery actions are tracked separately from authorization state
- canonical funds/state transitions are on-chain
- merchant operational metadata is local in prototype mode
- production migration requires durable backend + reconciliation services
- User creates/links a passkey identity.
- A smart account is initialized under ERC-4337.
CardFactorydeploys a userPrivateCard.- Card is associated with encrypted token flow and ACL path.
- Merchant publishes plan metadata and plan reference.
- Customer enters embedded checkout.
- Amount/limits are encrypted client-side via relayer SDK.
- App submits an ERC-4337 user operation to call card subscription methods.
- Contract stores encrypted approval and executes initial payment logic.
- Merchant dashboard tracks due subscriptions and billing cycles.
- Renewal pulls execute against approved subscription refs.
- Success/failure attempts are recorded.
- Past-due agreements move into recovery queue with retry policy.
- Node.js
20+ - npm
7+ - a Sepolia RPC provider key
- a funded Sepolia deployer key if you want to deploy contracts
- access to a bundler endpoint compatible with your frontend configuration
git clone https://github.com/tekuuu/PayMe.git
cd PayMeThis repository currently uses separate package installs for the frontend and Hardhat workspaces.
cd hardhat
npm install
cd ../frontend
npm installContract workspace:
- create or update
hardhat/.env - set
INFURA_API_KEY - set
PRIVATE_KEY - set any wrapper/token addresses required by the deployment scripts
Frontend workspace:
- create or update
frontend/.env.local - set
NEXT_PUBLIC_RPC_ENDPOINT - set
NEXT_PUBLIC_BUNDLER_URL - set deployed contract addresses
- set
RELAYER_PRIVATE_KEYfor the decrypt-signing route - set
DATABASE_URLpointing to a PostgreSQL instance (e.g., Supabase connection string)
For the current expected variables, use:
- fhevm.ts - fhEVM instance creation
- RelayerSDKLoader.ts - browser SDK loading
- constants.ts - SDK CDN pointer
- route.ts - decrypt signature route
- page.tsx - embedded checkout
cd hardhat
npx hardhat compilecd hardhat
npx hardhat run scripts/deploy_payme_core.ts --network sepoliaAfter deployment, propagate the relevant addresses into frontend/.env.local.
cd frontend
npm run devSuggested local validation path:
- create merchant account and customer account
- deploy/verify card creation flow for customer
- create merchant plan and open checkout link
- approve subscription with encrypted input flow
- run at least one renewal and inspect cycle/attempt state
- validate decrypt-enabled balance views and error handling
Current project-level test commands:
Contracts:
cd hardhat
npm testUseful contract commands:
cd hardhat
npx hardhat compile
npx hardhat coverageNotes:
- the Hardhat workspace now has
unitandintegrationtest directories - fhEVM-heavy flows require the Hardhat fhEVM plugin and mock environment to be available
- some private-payment execution paths depend on ACL-sensitive encrypted handles, so integration tests should focus on stable contract behavior and explicit permissioned flows
Recommended workflow for contributors:
- read this root README, then the workspace README you are modifying
- compile the Hardhat workspace before changing contract interfaces
- keep frontend contract addresses and ABI expectations aligned with contract changes
- test merchant flow changes against both customer and merchant routes
- document any new environment variables or deployment assumptions in the relevant README
When changing contracts:
- check hardhat/contracts/PrivateCard.sol
- review deployment scripts under hardhat/scripts
- verify frontend usage in frontend/src/app/embed/checkout/page.tsx and related hooks
When changing frontend confidential flows:
- review frontend/src/lib/fhevm-sdk/internal/fhevm.ts
- review frontend/src/hooks/use-confidential-token-balance.ts
- review frontend/src/app/api/fhe/sign-user-decrypt/route.ts
Important implementation notes for new developers:
- the merchant control plane is now backed by PostgreSQL (Supabase) with Drizzle ORM; browser localStorage is retained as a migration-period fallback
- all API routes read from and write to the database; frontend hooks fetch from API first, falling back to localStorage
- the frontend and contracts are tightly coupled through deployed addresses and checkout assumptions
- the active network target is Sepolia, with mainnet migration notes documented separately
- fhEVM flows require careful ACL handling when moving encrypted values across contracts
- the root README is the overview; the workspace READMEs contain lower-level setup details
- use
npx drizzle-kit pushto push schema changes ornpx drizzle-kit migrateto apply versioned migrations
The current prototype is Sepolia-first. Mainnet support requires:
- replacing Sepolia-specific SDK config and relayer endpoints
- mainnet contract deployments and address wiring
- infrastructure hardening for billing automation and observability
See docs/mainnet.md for full migration details.