Minimal full‑stack demo for creating Privy wallets and deploying Argent Ready accounts on Starknet (Sepolia) with Privy authentication. Includes an optional SNIP‑29 paymaster path and a simple Counter example (read + write).
The project is split into two independent apps:
- api/ – Express backend (port 3000). Handles Privy server calls and Starknet account deployment via starknet.js.
- client/ – Next.js frontend (port 3001). Handles login via Privy and simple wallet actions.
starknet-privy-demo/
├─ api/ # Express backend (starknet.js)
│ ├─ server.ts # App entry
│ ├─ src/ # Routes, libs, middleware
│ └─ .env.example # API env template
└─ client/ # Next.js frontend (Privy auth)
├─ src/ # Pages and components
└─ .env.example # Client env template
- Node.js 18+
- A Privy App (App ID/Secret)
- A Ready account class hash for your target network
API (backend)
cd api
npm install
cp .env.example .env # or .env.local
# Edit .env (see examples below)
npm run devClient (frontend)
cd client
npm install
cp .env.example .env.local
# Edit .env.local (see examples below)
npm run devAccess
Frontend: http://localhost:3001
Backend: http://localhost:3000
API minimal .env
PORT=3000
CLIENT_URL=http://localhost:3001
# Starknet
# Example: Voyager/Alchemy RPC (use any Starknet RPC provider)
RPC_URL=Voyager/Alchemy
READY_CLASSHASH=0x...
# Privy server credentials
PRIVY_APP_ID=your_app_id
PRIVY_APP_SECRET=your_app_secret
# Counter (used by demo endpoints)
COUNTER_CONTRACT_ADDRESS=0x...
COUNTER_ENTRYPOINT_GET=get_counter
COUNTER_ENTRYPOINT_INCREASE=increase_counter
# Paymaster (optional)
# PAYMASTER_URL=https://sepolia.paymaster.avnu.fi
# PAYMASTER_MODE=sponsored # or 'default'
# PAYMASTER_API_KEY=... # required for sponsored
# GAS_TOKEN_ADDRESS=0x... # required for defaultClient minimal .env.local
NEXT_PUBLIC_PRIVY_APP_ID=your_privy_app_id
NEXT_PUBLIC_API_URL=http://localhost:3000 # no trailing slash
# Counter (UI uses this if API did not set COUNTER_CONTRACT_ADDRESS)
NEXT_PUBLIC_CONTRACT_ADDRESS=0x...
# Optional explorer bases (defaults to Voyager Sepolia)
# NEXT_PUBLIC_EXPLORER_TX_BASE=https://sepolia.voyager.online/tx
# NEXT_PUBLIC_EXPLORER_ADDR_BASE=https://sepolia.voyager.online/contract
# Optional: Privy login methods (comma-separated; defaults to email only)
# e.g., email,google or email,google,twitter,discord
# NEXT_PUBLIC_PRIVY_LOGIN_METHODS=emailEnvironment loading for API
- The server loads env in this order (first match wins):
- api/.env.local, api/.env, repo-root/.env.local, repo-root/.env
- In production, prefer real environment variables over files.
- Privy wallet: Create a Starknet wallet in Privy for the user. We use Privy’s Wallet API with user authorization (raw_sign) to sign Starknet messages.
- Ready account: An Argent Ready account is deployed on Starknet. Its address is derived from the class hash and the user’s public key.
- Paymaster (optional): If configured, deploy/txs can be sponsored (dApp pays) or use a gas token in “default” mode.
- Counter: A simple contract used for demo. The UI polls
get_counter(user)every second and sendsincrease_counterwhen you click Increase. - Safety: The Increase button is disabled until the wallet is deployed.
- Login with Privy on the frontend.
- Create Wallet → backend creates a Privy Starknet wallet and returns ids/keys.
- Deploy Wallet → backend deploys Ready account (with paymaster if configured).
- Counter → the UI polls
get_counter(user)every second and shows a big number. - Increase → sends a transaction to
increase_counter; a toast shows tx link.
- POST
/privy/create-wallet - POST
/privy/public-key - GET
/privy/user-wallets?userId=… - POST
/privy/deploy-wallet - POST
/privy/execute - POST
/privy/increase-counter - GET
/privy/counter?contract=…&user=…
- Return user ID and wallet details from the API when not present in client localStorage (bootstrap state on first load).
- Implement session keys to improve security and UX for repeated actions.
- Integrate KYC and fiat onramping using MoonPay.
- Add optional social logins (Google, Twitter, Discord) with an env-controlled toggle.
MIT — see LICENSE