Setup
Initialize the project, install dependencies, and configure your development environment
Project Setup
We'll build this as a monorepo with two main parts: a Foundry smart contract project and a Next.js frontend/backend.
Create Project Structure
mkdir vrf-rps && cd vrf-rpsInitialize Foundry Project
forge init foundry-project
cd foundry-projectThis creates a Foundry project with the standard layout:
src/for contractstest/for testsscript/for deployment scriptsfoundry.tomlfor configuration
Initialize Next.js Project
Return to the root directory and create the Next.js app:
cd ..
bunx create-next-app@latest . --typescript --tailwind --app --no-src-dirSelect the following options:
- Use recommended Next.js defaults: No, customize settings
- TypeScript: Yes
- Linter: None
- React Compiler: Yes
- Tailwind CSS: Yes
src/directory: No- App Router: Yes
- Customize import alias: No
If you've completed another tutorial, you can select No, reuse previous settings to skip configuration.
Install Dependencies
Install the required packages for blockchain interaction and wallet integration:
bun add viem wagmi rise-wallet @tanstack/react-queryPackage breakdown:
viem: Ethereum library for contract interactionwagmi: React hooks for Ethereumrise-wallet: RISE Wallet connector for gasless transactions@tanstack/react-query: Async state management (required by wagmi)
Install shadcn/ui
Initialize shadcn/ui in your project:
npx shadcn@latest inityarn dlx shadcn@latest initpnpm dlx shadcn@latest initbun x shadcn@latest initWhen prompted, select these options:
- Style: New York
- Base color: Neutral
- CSS variables: Yes
Then add the required components:
npx shadcn@latest add button dropdown-menuyarn dlx shadcn@latest add button dropdown-menupnpm dlx shadcn@latest add button dropdown-menubun x shadcn@latest add button dropdown-menuThis installs the Button and Dropdown Menu components with all necessary dependencies.
Environment Configuration
Create a .env.local file in the root directory:
touch .env.localAdd your sponsor wallet private key (this account pays for VRF requests):
DEV_PRIVATE_KEY=0x...your_private_key_hereSecurity: Never commit .env.local to git. Make sure it's in your .gitignore. This should be a burner wallet with only testnet funds.
Update .gitignore
Ensure your .gitignore includes:
# Environment
.env.local
# Foundry
foundry-project/out
foundry-project/cache
foundry-project/broadcastProject Structure
Your project should now look like this:
vrf-rps/
├── foundry-project/
│ ├── src/
│ ├── test/
│ ├── script/
│ └── foundry.toml
├── src/
│ └── app/
│ ├── page.tsx
│ ├── layout.tsx
│ └── api/
│ └── route.ts (we'll create this)
├── .env.local
├── package.json
└── next.config.tsConfiguration Files
Wagmi Configuration
Create src/config/wagmi.ts:
import { http, createConfig } from 'wagmi'
import { Chains, RiseWallet } from "rise-wallet"
import { riseWallet } from "rise-wallet/wagmi"
// RISE Wallet connector with default config
export const rwConnector = riseWallet(RiseWallet.defaultConfig)
// Wagmi configuration for RISE Testnet
export const config = createConfig({
chains: [Chains.riseTestnet],
connectors: [rwConnector],
transports: {
[Chains.riseTestnet.id]: http("https://testnet.riselabs.xyz")
}
})Provider Setup
Create src/context/index.tsx:
"use client"
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { WagmiProvider } from 'wagmi'
import { config } from '@/config/wagmi'
import { ReactNode, useState } from 'react'
export function Providers({ children }: { children: ReactNode }) {
const [queryClient] = useState(() => new QueryClient())
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</WagmiProvider>
)
}Update Root Layout
Modify src/app/layout.tsx:
import type { Metadata } from "next"
import { Providers } from "@/context"
import "./globals.css"
export const metadata: Metadata = {
title: "VRF Rock Paper Scissors",
description: "Onchain RPS with RISE VRF",
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<Providers>
{children}
</Providers>
</body>
</html>
)
}Constants Setup
Create src/constants/index.ts (we'll populate this after deploying the contract):
// Contract address (update after deployment)
export const RPS_ADDRESS = "0x..." as const
// Contract ABI (update after compilation)
export const ABI = [] as constNext Steps
Your development environment is ready! Next, we'll write and deploy the smart contract with VRF integration.
Make sure you have some testnet ETH in your sponsor wallet address. Get free testnet ETH from RISE Faucet.