💬 Tech Support & Safety Hub

How to Build a Multiplayer Tic-Tac-Toe Game with Solana Wallet Integration

A

Anthony Olajide

Jan 2, 2026 at 2:56 PM

10 replies 217 views
Introduction

In this comprehensive tutorial, we'll create a web-based Tic-Tac-Toe game with real-time multiplayer functionality and Solana wallet integration. This project will allow players to connect their Solana wallets, find opponents, and play games with the option to record results on the blockchain.

Features
[list][*]    Real-time multiplayer Tic-Tac-Toe[*]    Solana wallet authentication[*]    Game lobby system[*]    On-chain game history (optional)[*]    Winner payouts (optional)[/list]Tech Stack
[list][*]    Frontend: React + TailwindCSS[*]    Blockchain: Solana Web3.js + Devnet[*]    Wallet: Phantom + Solana Wallet Adapter[*]    Realtime Communication: Firebase Realtime Database[*]    Backend: Firebase Functions (optional Express alternative)[/list]Setup Instructions
Prerequisites
[list][*]    Node.js (v16 or later)[*]    Yarn or npm[*]    Phantom Wallet (or other Solana wallet)[*]    Firebase account (free tier sufficient)[*]    Basic understanding of JavaScript and React[/list]

10 Replies

Sign in to join the conversation

A

Anthony Olajide

1 month ago
Step 8: On-Chain Integration (Optional)


Create src/utils/solana.ts for blockchain interactions:

import { Connection, PublicKey, Transaction, SystemProgram } from '@solana/web3.js'

const connection = new Connection('https://api.devnet.solana.com')

export const recordGameResult = async (
winner: PublicKey,
loser: PublicKey,
amount: number
) => {
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: loser,
toPubkey: winner,
lamports: amount
})
)

// In a real app, you'd sign and send this transaction properly
return transaction
}

export const getGameHistory = async (player: PublicKey) => {
// Implement fetching game history from your on-chain program
return []
}
A

Anthony Olajide

1 month ago
Deployment

1. Build the React App
bash

yarn build


2. Deploy to Firebase Hosting
bash

yarn add -D firebase-tools
firebase login
firebase init
# Select Hosting and follow prompts
firebase deploy
j

jenny@africoders.com

1 month ago
Hey there! Building a multiplayer Tic-Tac-Toe game with Solana Wallet Integration sounds like an exciting project! To get started, you'll want to dive into Solana's documentation to understand how you can integrate the wallet functionality into your game. Solana's developer resources are pretty robust and should guide you through the process step by step.

For the game itself, consider using a framework like React or Vue.js to handle the frontend and Solana's web3.js library for interacting with the blockchain. You'll need to manage game state, handle player moves, and ensure that the game logic is sound.

Don't forget about security - make sure to implement proper validation and error handling to prevent any vulnerabilities. And testing, testing, testing! It's crucial to ensure that your game runs smoothly in a multiplayer environment.

Good luck with your project! Feel free to ask if you run into any roadblocks - this community is here to help!
A

Anthony Olajide

1 month ago
Step 1: Initialize the Project

npx create-react-app solana-tic-tac-toe --template typescript
cd solana-tic-tac-toe
yarn add @solana/web3.js @solana/wallet-adapter-react @solana/wallet-adapter-react-ui @solana/wallet-adapter-wallets @solana/wallet-adapter-base firebase @chakra-ui/react @emotion/react @emotion/styled framer-motion
yarn add -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
A

Anthony Olajide

1 month ago
Step 2: Configure TailwindCSS

Update  tailwind.config.js:
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}


Add to src/index.css:

@tailwind base;
@tailwind components;
@tailwind utilities;
A

Anthony Olajide

1 month ago
Step 3. Firebase Setup


Create a new Firebase project and enable:

Realtime Database
Authentication (anonymous or email/password)

Add your Firebase config to src/firebase.ts:

import { initializeApp } from 'firebase/app'
import { getDatabase } from 'firebase/database'

const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
databaseURL: "YOUR_DATABASE_URL",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_STORAGE_BUCKET",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
};

const app = initializeApp(firebaseConfig)
const database = getDatabase(app)

export { database }
A

Anthony Olajide

1 month ago
Step 4. Wallet Integration


Create src/components/WalletContextProvider.tsx:


import React, { useMemo } from 'react'
import { WalletAdapterNetwork } from '@solana/wallet-adapter-base'
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui'
import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react'
import { PhantomWalletAdapter } from '@solana/wallet-adapter-wallets'
import { clusterApiUrl } from '@solana/web3.js'

require('@solana/wallet-adapter-react-ui/styles.css')

export const WalletContextProvider = ({ children }: { children: React.ReactNode }) => {
const network = WalletAdapterNetwork.Devnet
const endpoint = useMemo(() => clusterApiUrl(network), [network])
const wallets = useMemo(() => [new PhantomWalletAdapter()], [])

return (


{children}


)
}
A

Anthony Olajide

1 month ago
Step 5. Game Components


Create src/components/GameBoard.tsx:


import React from 'react'

type BoardProps = {
board: string[]
onCellClick: (index: number) => void
disabled: boolean
}

export const GameBoard = ({ board, onCellClick, disabled }: BoardProps) => {
return (

{board.map((cell, index) => (
onCellClick(index)}
disabled={disabled || !!cell}
className="flex items-center justify-center text-4xl font-bold bg-gray-200 hover:bg-gray-300 rounded-lg h-20 w-20"
>
{cell}

))}

)
}
A

Anthony Olajide

1 month ago
Step 6: Multiplayer Logic


Create src/hooks/useGame.ts for game state management:

import { useState, useEffect } from 'react'
import { ref, onValue, set, push, update } from 'firebase/database'
import { database } from '../firebase'
import { useWallet } from '@solana/wallet-adapter-react'

type GameState = {
board: string[]
currentPlayer: 'X' | 'O'
winner: string | null
playerX: string | null
playerO: string | null
}

export const useGame = (gameId?: string) => {
const { publicKey } = useWallet()
const [gameState, setGameState] = useState({
board: Array(9).fill(''),
currentPlayer: 'X',
winner: null,
playerX: null,
playerO: null
})
const [isLoading, setIsLoading] = useState(true)
const [isPlayer, setIsPlayer] = useState(false)
const [playerSymbol, setPlayerSymbol] = useState(null)

// Game logic implementation here
// Including Firebase realtime updates, move validation, etc.

return {
gameState,
isLoading,
isPlayer,
playerSymbol,
makeMove: (cellIndex: number) => {
// Implement move logic
},
createGame: async () => {
// Implement game creation
},
joinGame: async (gameId: string) => {
// Implement game joining
}
}
}
A

Anthony Olajide

1 month ago
Step 7: Main App Component


Update src/App.tsx:

import React from 'react'
import { WalletContextProvider } from './components/WalletContextProvider'
import { WalletMultiButton } from '@solana/wallet-adapter-react-ui'
import { useGame } from './hooks/useGame'
import { GameBoard } from './components/GameBoard'

function App() {
const {
gameState,
isLoading,
isPlayer,
playerSymbol,
makeMove,
createGame,
joinGame
} = useGame()

if (isLoading) return Loading...

return (


Solana Tic-Tac-Toe




{!gameState.playerX || !gameState.playerO ? (


Create New Game



joinGame('game-id-from-input')}
className="py-2 px-4 bg-green-500 text-white rounded-r hover:bg-green-600"
>
Join




) : (


{gameState.winner ? (

{gameState.winner === 'draw'
? "It's a draw!"
: `${gameState.winner} wins!`}


) : (

Current turn: {gameState.currentPlayer}
{isPlayer && ` (You're ${playerSymbol})`}

)}




)}


)
}

export default function WrappedApp() {
return (



)
}