RISE Logo-Light

Setup

Initialize the project, install dependencies, and configure your development environment

Project Setup

We'll build this as a monorepo combining a Foundry smart contract project with a Next.js frontend.

Create Project Structure

mkdir rise-slots && cd rise-slots

Initialize Foundry Project

mkdir foundry-app && cd foundry-app
forge init

This creates the Foundry structure:

  • src/ for contracts
  • test/ for tests
  • script/ for deployment scripts
  • foundry.toml for configuration

Install OpenZeppelin Contracts

We'll use OpenZeppelin's ERC20 implementation for the RCT token:

forge install OpenZeppelin/openzeppelin-contracts

Add to foundry.toml:

[profile.default]
src = "src"
out = "out"
libs = ["lib"]
remappings = ["@openzeppelin/=lib/openzeppelin-contracts/"]

Initialize Next.js Project

Return to the root directory and create the Next.js app:

cd ..
bun create next-app@latest . --typescript --tailwind --app

Select the following options:

  • Use recommended Next.js defaults: No, customize settings
  • TypeScript: Yes
  • Linter: None
  • React Compiler: Yes
  • Tailwind CSS: Yes
  • src/ directory: Yes
  • App Router: Yes
  • Customize import alias: No

If you've completed another tutorial, you can select No, reuse previous settings to skip configuration.

Install Core Dependencies

Install the required packages for blockchain interaction:

bun add viem wagmi rise-wallet @tanstack/react-query shreds ox

Package breakdown:

  • viem: Ethereum library for contract interaction
  • wagmi: React hooks for Ethereum
  • rise-wallet: RISE Wallet connector with passkey support
  • @tanstack/react-query: Async state management (required by wagmi)
  • shreds: RISE's real-time event streaming library
  • ox: Cryptography library for session key P256 operations

Install UI Dependencies

bun add framer-motion class-variance-authority clsx tailwind-merge

These provide:

  • framer-motion: Animations for spinning reels
  • Tailwind utility functions for styling

Project Structure

Your project should now look like this:

rise-slots/
├── foundry-app/
│   ├── src/
│   ├── test/
│   ├── script/
│   ├── lib/
│   │   └── openzeppelin-contracts/
│   └── foundry.toml
├── src/
│   └── app/
│       ├── page.tsx
│       ├── layout.tsx
│       └── providers.tsx (we'll create this)
├── package.json
└── next.config.ts

Configuration 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 (passkey-based)
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")
  }
})

declare module 'wagmi' {
  interface Register {
    config: typeof config
  }
}

RISE Wallet uses passkeys for authentication - no seed phrases or private keys to manage! Users create an account with biometrics or a security key.

Provider Setup

Create src/app/providers.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 "./providers"
import "./globals.css"

export const metadata: Metadata = {
  title: "RISE Slots",
  description: "Instant VRF-powered slot machine with gasless gameplay",
}

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 contracts):

// Contract addresses (update after deployment)
export const SLOT_MACHINE_ADDRESS = "0x..." as const
export const RCT_TOKEN_ADDRESS = "0x..." as const

// Contract ABIs (we'll import these after compilation)
export const SLOT_MACHINE_ABI = [] as const
export const RCT_ABI = [] as const

Next Steps

Your development environment is ready! Next, we'll write the smart contracts: an ERC20 token (RCT) and a VRF-powered slot machine.

Make sure you have some testnet ETH for deploying contracts. Get free testnet ETH from RISE Faucet.