Skip to content

Repository files navigation

CreloPay App Guide

This README is a living guide for the app structure and payment form behavior. We will keep updating it as the code evolves.

What This App Does

CreloPay is a payment-link creation app built with Next.js App Router. Merchants create a payment link by filling a dynamic form, signing typed data with a wallet, and submitting the signed payload to server actions backed by Supabase. Payers open the generated link, complete payment on-chain, and the app stores a receipt record.

Tech Stack

  • Next.js (App Router)
  • React + TypeScript
  • Tailwind CSS + shadcn/ui components
  • TanStack React Query
  • wagmi (wallet connection and signing)
  • Supabase client/actions
  • GSAP (light UI animation)
  • Solidity (backend smart contract)

Quick Start

  1. Install dependencies:
npm install
  1. Run development server:
npm run dev
  1. Open:
http://localhost:3000

Useful Scripts

  • npm run dev - Start local dev server
  • npm run build - Production build
  • npm run start - Run production server
  • npm run lint - Run eslint checks

High-Level App Structure

app/
	layout.tsx                     # Global providers, navbar, toaster
	page.tsx                       # Renders CreatePaymentForm
  pay/[paymentId]/page.tsx       # Resolves payment id and loads payment record
	ReactQueryProvider/            # Query client provider setup

components/
	Navbar.tsx
	forms/
		CreatePaymentForm.tsx        # Main form and submit flow
    PayWithPaymentIdForm.tsx     # Payer checkout flow
		TypeBasedInputs/
			Donation.tsx               # Donation-only fields
			Ticket.tsx                 # Ticket-only fields
	ui/                            # Shared shadcn-style UI primitives

lib/
	types.ts                       # Shared form/value types
	HelperFunctions.ts             # Nonce generation and helpers
	constants.ts                   # Contract ABI/address
	contract/action.ts             # On-chain pay simulation + write flow
	ReactQueries/ContractQueries.tsx
	ReactQueries/SupabaseQueries.tsx
	supabase/scripts/
		action.ts                    # Supabase actions (create payment link)
		signature.ts                 # Metadata hash and bytes32 helpers

End-to-End App Flow

Merchant Flow Illustration

flowchart TD
  A[Merchant opens /] --> B[CreatePaymentForm]
  B --> C[validateForm]
  C --> D[buildMetadata]
  D --> E[buildMetadataHash]
  E --> F[generateNonce]
  F --> G[wagmi signTypedDataAsync]
  G --> H[useCreatePaymentLink]
  H --> I[createPaymentLink server action]
  I --> J[Verify hash and recover signer]
  J --> K[Insert payments_details row]
  K --> L[Return /pay/{paymentId} link]
Loading

Payer Flow Illustration

flowchart TD
  A[Payer opens /pay/[paymentId]] --> B[getPaymentDetailsById]
  B --> C[PayWithPaymentIdForm]
  C --> D[Validate payer inputs]
  D --> E[useCallContractPay]
  E --> F[pay contract action]
  F --> G[Check allowance]
  G --> H[Approve USDC if needed]
  H --> I[Simulate pay]
  I --> J[Send pay tx]
  J --> K[Read PaymentMade event]
  K --> L[useCreateReceipt]
  L --> M[createReceipt server action]
  M --> N[Store receipt in Supabase]
Loading

Merchant Flow (Create Link)

  1. Route app/page.tsx renders CreatePaymentForm.
  2. validateForm checks common and type-specific fields.
  3. buildMetadata converts form values into canonical metadata.
  4. buildMetadataHash creates deterministic bytes32 hash of metadata.
  5. generateNonce creates nonce used in signature payload.
  6. Wallet signs typed data (PaymentRequest) via wagmi signTypedDataAsync.
  7. useCreatePaymentLink calls server action createPaymentLink.
  8. Server recomputes metadata hash, recovers signer, validates signature.
  9. Server inserts payments_details row and returns /pay/{paymentId} link.

Payer Flow (Pay Link)

  1. Route app/pay/[paymentId]/page.tsx resolves param and calls getPaymentDetailsById.
  2. PayWithPaymentIdForm renders payer inputs based on stored payment type/metadata.
  3. Form validates payer data and computes final payable amount.
  4. useCallContractPay triggers pay in lib/contract/action.ts.
  5. pay checks/sets USDC allowance, simulates pay, then sends transaction.
  6. extractPaymentRef parses PaymentMade event from receipt.
  7. useCreateReceipt calls createReceipt to persist payer receipt details.

Exported Constants Map

config.ts

  • config
    • Central wagmi config (chains, connectors, RPC transports).
    • Used by wallet hooks and contract actions.

lib/constants.ts

  • CONTRACT_ABI
    • ABI for CreloPay contract (constructor, events, pay function, helpers).
    • Used for simulate/read/write and event log parsing.
  • CONTRACT_ADDRESS
    • Contract address loaded from NEXT_PUBLIC_CONTRACT_ADDRESS.

lib/HelperFunctions.ts

  • ERC20_ABI
    • Minimal ERC20 ABI subset (allowance, approve) for USDC approval flow.

Exported Functions Map

app/ReactQueryProvider/getQueryClients.tsx

  • getQueryClient
    • Returns request-scoped QueryClient on server and singleton on browser.

lib/HelperFunctions.ts

  • generateNonce(length = 32)
    • Generates random hex nonce for replay protection.
  • buildMetadata(formValues)
    • Builds normalized metadata object per payment type.
  • parseNumber(value)
    • Parses numeric string to number, returns NaN for invalid values.
  • parseCommaSeparatedNumbers(input)
    • Converts comma-separated input to positive number array.
  • parseCommaSeparatedStrings(input)
    • Converts comma-separated input to trimmed string array.
  • validateForm(formValues)
    • Validates merchant form fields before signing/submitting.
  • mapDbToSignature(dbData)
    • Maps app/db payload to exact EIP-712 PaymentRequest message shape.

lib/contract/action.ts

  • simulatePay({ request, signature, account })
    • Simulates contract pay call before sending transaction.
  • pay({ request, signature, account })
    • End-to-end payer transaction flow:
    • checks USDC allowance,
    • sends approval if needed,
    • simulates payment,
    • writes pay transaction,
    • extracts paymentRef from PaymentMade event.

lib/ReactQueries/ContractQueries.tsx

  • useCallContractPay()
    • React Query mutation wrapper around pay contract action.

lib/ReactQueries/SupabaseQueries.tsx

  • useCreatePaymentLink()
    • React Query mutation wrapper around server action createPaymentLink.
  • useCreateReceipt()
    • React Query mutation wrapper around server action createReceipt.

lib/supabase/config/client.ts

  • getSupabaseAdminClient()
    • Returns cached server-only Supabase service-role client.

lib/supabase/scripts/signature.ts

  • isBytes32Hex(value)
    • Type guard for 32-byte hex strings.
  • ensureBytes32Hex(value, label)
    • Validates and returns bytes32 hex string or throws.
  • buildMetadataHash(metadata)
    • Canonically serializes metadata and computes deterministic keccak256 hash.

lib/supabase/scripts/action.ts

  • createPaymentLink(paymentInfo)
    • Validates signature payload, verifies signer, inserts payment record,
    • returns payment link and payment id.
  • getPaymentDetailsById(paymentId)
    • Fetches a single payment record for payer route.
  • createReceipt(receiptInfo)
    • Persists receipt details after successful payment transaction.

lib/utils.ts

  • cn(...inputs)
    • Utility to merge Tailwind/class names (clsx + tailwind-merge).

Exported Types Map

lib/types.ts

  • PaymentType
    • Supported payment categories: DONATION, TICKET, PRODUCT, SERVICE, INVOICE.
  • PaymentFormValues
    • Merchant form state shape used by CreatePaymentForm.
  • DonationValues
    • Donation-only subset of merchant fields.
  • TicketValues
    • Ticket-only subset of merchant fields.
  • PaymentSignaturePayload
    • Canonical merchant signature payload contract.
  • CreatePaymentLinkInput
    • Input shape expected by createPaymentLink server action.
  • PaymentDetailsRecord
    • Persisted payment details record returned for payer flow.
  • PayerInputValues
    • Client-side payer form state in PayWithPaymentIdForm.
  • CreateReceiptInput
    • Input shape for receipt creation action.
  • PaymentRequestInput
    • Contract PaymentRequest struct shape for pay call.
  • PayInput
    • Input for contract pay helper (request, signature, payer account).
  • PayResult
    • Return shape from pay helper (txHash, paymentRef).

lib/supabase/scripts/signature.ts

  • Bytes32Hex
    • Type alias for bytes32-prefixed hex string.

Validation Rules (Current Behavior)

  • title is required.
  • email must be a valid email format.
  • unitPrice must be greater than zero for all types.
  • shippingFee must be greater than zero when shipping is enabled.
  • Donation requires goalAmount > 0 and at least one valid suggested amount.
  • Ticket requires eventDate, location, and totalSupply > 0.

Notes For Future Updates

  • Keep this README updated whenever exported symbols, payload shape, or route flow changes.
  • If a new payment type is added, update:
    • PaymentType in lib/types.ts,
    • buildMetadata and validateForm,
    • payer rendering logic in PayWithPaymentIdForm,
    • this README flow and symbol map.
  • If signature fields/domain change, update both frontend signing and backend recovery sections here.

About

CreloPay is a payment-link creation app built with Next.js App Router. Users configure payment details in a dynamic form, sign the payload with a wallet, and submit to Supabase-backed actions through a React Query mutation and then users van share there payment link generated to share to their payers to use when reciving funds from payers.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages