Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ SUPABASE_SERVICE_ROLE_KEY=
CIRCLE_API_KEY=
CIRCLE_ENTITY_SECRET=
CIRCLE_BLOCKCHAIN=ARC-TESTNET
CIRCLE_USDC_TOKEN_ID=
CIRCLE_USDC_TOKEN_ID=15dc2b5d-0994-58b0-bf8c-3a0501148ee8
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are prefilling the blockchain, then we should prefill the token ID as well. It's not that easy to find the token ID at the moment.


# Misc
ADMIN_EMAIL=admin@admin.com
116 changes: 75 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,85 +1,119 @@
# Arc Commerce

This project demonstrates how to integrate USDC as a payment method for purchasing credits on Arc.
Integrate USDC as a payment method for purchasing credits on Arc. This sample application uses Next.js, Supabase, and Circle Developer Controlled Wallets to demonstrate a credit purchase flow with USDC payments on Arc testnet.

## Table of Contents
<img width="830" height="646" alt="User dashboard for credit purchase" src="public/screenshot.png" />

- [Clone and Run Locally](#clone-and-run-locally)
- [Environment Variables](#environment-variables)
## Prerequisites

## Clone and Run Locally
- Node.js 20.x or newer
- npm (automatically installed when Node.js is installed)
- Docker (for running Supabase locally)
- [ngrok](https://ngrok.com/) (for local webhook testing)
- Circle Developer Controlled Wallets [API key](https://console.circle.com/signin) and [Entity Secret](https://developers.circle.com/wallets/dev-controlled/register-entity-secret)

1. **Clone and install dependencies:**
## Getting Started

1. Clone the repository and install dependencies:

```bash
git clone git@github.com:circlefin/arc-commerce.git
cd top-up
cd arc-commerce
npm install
```

2. **Set up environment variables:**
2. Create a `.env.local` file in the project root:

```bash
cp .env.example .env.local
```

Then edit `.env.local` and fill in all required values (see [Environment Variables](#environment-variables) section below).
Required variables:

```bash
# Supabase
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY=your_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key

# Circle
CIRCLE_API_KEY=your_circle_api_key
CIRCLE_ENTITY_SECRET=your_entity_secret
CIRCLE_BLOCKCHAIN=ARC-TESTNET
CIRCLE_USDC_TOKEN_ID=15dc2b5d-0994-58b0-bf8c-3a0501148ee8

# Misc
ADMIN_EMAIL=admin@admin.com
```

3. **Start Supabase locally** (requires Docker):
3. Start Supabase locally:

```bash
npx supabase start
npx supabase migration up
```

4. **Start the development server:**
4. Start the development server:

```bash
npm run dev
```

The app will be available at [http://localhost:3000](http://localhost:3000/). The admin wallet will be automatically created on first startup.
The app will be available at `http://localhost:3000`. The admin wallet is automatically created on first startup.

5. **Set up Circle Webhooks:**
5. Set up Circle Webhooks (for local development):

In a separate terminal, start ngrok to expose your local server:
In a separate terminal, expose your local server:

```bash
ngrok http 3000
```

Copy the HTTPS URL from ngrok (e.g., `https://your-ngrok-url.ngrok.io`) and add it to your Circle Console webhooks section:
Add the webhook endpoint in Circle Console:
- Navigate to Circle Console → Webhooks
- Add a new webhook endpoint: `https://your-ngrok-url.ngrok.io/api/circle/webhook`
- Keep ngrok running while developing to receive webhook events
- Add endpoint: `https://your-ngrok-url.ngrok.io/api/circle/webhook`
- Keep ngrok running to receive webhook events

## How It Works

- Built with [Next.js](https://nextjs.org/) and [Supabase](https://supabase.com/)
- Uses [Circle Developer Controlled Wallets](https://developers.circle.com/wallets/dev-controlled) for USDC transactions
- Wallet operations handled server-side with `@circle-fin/developer-controlled-wallets`
- Webhook signature verification ensures secure transaction notifications
- Admin wallet automatically initialized on first run

## Environment Variables

Copy `.env.example` to `.env.local` and fill in the required values:
| Variable | Scope | Purpose |
| ------------------------------------- | ----------- | ------------------------------------------------------------------------ |
| `NEXT_PUBLIC_SUPABASE_URL` | Public | Supabase project URL |
| `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY` | Public | Supabase anonymous/public key |
| `SUPABASE_SERVICE_ROLE_KEY` | Server-side | Service role for privileged database operations |
| `CIRCLE_API_KEY` | Server-side | Circle API key for webhook signature verification |
| `CIRCLE_ENTITY_SECRET` | Server-side | Circle entity secret for wallet operations |
| `CIRCLE_BLOCKCHAIN` | Server-side | Blockchain network identifier (e.g., "ARC-TESTNET") |
| `CIRCLE_USDC_TOKEN_ID` | Server-side | USDC token ID for the specified blockchain |
| `ADMIN_EMAIL` | Server-side | Email address that determines which user gets admin dashboard access |

```bash
# Supabase
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
## Usage Notes

# Circle
CIRCLE_API_KEY=
CIRCLE_ENTITY_SECRET=
CIRCLE_BLOCKCHAIN=ARC-TESTNET
CIRCLE_USDC_TOKEN_ID=
- Designed for Arc testnet only
- Requires valid Circle API credentials and Supabase configuration
- Admin wallet must have sufficient USDC and gas fees
- ngrok (or similar) required for local webhook testing

# Misc
ADMIN_EMAIL=admin@admin.com
```
## Scripts

| Variable | Scope | Purpose |
| ------------------------------------- | ----------- | ------------------------------------------------------------------------ |
| `NEXT_PUBLIC_SUPABASE_URL` | Public | Supabase project URL. |
| `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY` | Public | Supabase anonymous/public key. |
| `SUPABASE_SERVICE_ROLE_KEY` | Server-side | Service role for privileged writes (e.g., transaction inserts). |
| `CIRCLE_API_KEY` | Server-side | Used to fetch Circle webhook public keys for signature verification. |
| `CIRCLE_ENTITY_SECRET` | Server-side | Circle entity secret for wallet operations. |
| `CIRCLE_BLOCKCHAIN` | Server-side | Blockchain network identifier (e.g., "ARC-TESTNET"). |
| `CIRCLE_USDC_TOKEN_ID` | Server-side | USDC token ID for the specified blockchain. |
| `ADMIN_EMAIL` | Server-side | Admin user email address. |
- `npm run dev`: Start Next.js development server with auto-reload
- `npx supabase start`: Start local Supabase instance
- `npx supabase migration up`: Apply database migrations

## Security & Usage Model

This sample application:
- Assumes testnet usage only
- Handles secrets via environment variables
- Verifies webhook signatures for security
- Is not intended for production use without modification

See `SECURITY.md` for vulnerability reporting guidelines. Please report issues privately via Circle's bug bounty program.
2 changes: 1 addition & 1 deletion app/dashboard/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function ProtectedLayout({
<div className="w-full max-w-5xl flex justify-between items-center p-3 px-5 text-sm">
<div className="flex gap-5 items-center font-semibold">
<ThemeSwitcher />
<Link href={"/"}>top-up</Link>
<Link href={"/"}>arc-commerce</Link>
</div>
<div className="flex items-center gap-3">
{/* The wallet buttons have been removed from here */}
Expand Down
4 changes: 2 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const defaultUrl = process.env.VERCEL_URL

export const metadata: Metadata = {
metadataBase: new URL(defaultUrl),
title: "Next.js and Supabase Starter Kit",
description: "The fastest way to build apps with Next.js and Supabase",
title: "Arc Commerce",
description: "Platform credit purchases using USDC and Circle Wallets",
};

export default function RootLayout({
Expand Down
2 changes: 1 addition & 1 deletion app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default function Home() {
<div className="w-full max-w-5xl flex justify-between items-center p-3 px-5 text-sm">
<div className="flex gap-5 items-center font-semibold">
<ThemeSwitcher />
<Link href={"/"}>top-up</Link>
<Link href={"/"}>arc-commerce</Link>
</div>
{!hasEnvVars ? <EnvVarWarning /> : <AuthButton />}
</div>
Expand Down
16 changes: 3 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,8 @@
"lint": "next lint"
},
"dependencies": {
"@circle-fin/bridge-kit": "^1.1.2",
"@circle-fin/developer-controlled-wallets": "^8.4.1",
"@circle-fin/modular-wallets-core": "^1.0.11",
"@hookform/resolvers": "^5.2.2",
"@metamask/delegation-toolkit": "^0.13.0",
"@circle-fin/developer-controlled-wallets": "^10.0.1",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-checkbox": "^1.3.1",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.7",
Expand All @@ -27,31 +22,26 @@
"@supabase/supabase-js": "latest",
"@tanstack/react-query": "^5.90.2",
"@tanstack/react-table": "^8.21.3",
"axios": "^1.12.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"date-fns": "^4.1.0",
"lucide-react": "^0.511.0",
"next": "latest",
"next-themes": "^0.4.6",
"react": "^19.0.0",
"react-day-picker": "^9.11.0",
"react-dom": "^19.0.0",
"react-hook-form": "^7.63.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.0",
"viem": "^2.38.0",
"wagmi": "^2.17.5",
"zod": "^4.1.11"
"viem": "^2.44.4",
"wagmi": "^2.19.5"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@tailwindcss/postcss": "^4.1.13",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"baseline-browser-mapping": "^2.9.3",
"eslint": "^9",
"eslint-config-next": "15.3.1",
"postcss": "^8",
Expand Down
Binary file added public/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading