├── test └── .gitkeep ├── src ├── vite-env.d.ts ├── types │ ├── global.d.ts │ └── index.ts ├── assets │ ├── Queen.png │ ├── Rook.png │ ├── Bishop.png │ └── pngegg.png ├── main.tsx ├── index.css ├── config │ ├── constants.ts │ └── ChessGame.json ├── components │ ├── Input.tsx │ ├── Dialog.tsx │ ├── ErrorMessage.tsx │ ├── Button.tsx │ ├── GameStatus.tsx │ ├── WalletConnect.tsx │ ├── Footer.tsx │ ├── Navbar.tsx │ └── Chessboard.tsx ├── store │ ├── useGameStore.ts │ └── useWalletStore.ts ├── App.tsx ├── services │ └── socketService.ts └── pages │ ├── Leaderboard.tsx │ ├── FreeMode.tsx │ ├── Home.tsx │ ├── OnlineMode.tsx │ └── BotMode.tsx ├── netlify.toml ├── MockDown images ├── clone.png ├── Botmode.png ├── Chess-home.png ├── local_run.png ├── game created.png ├── whitescreen.png ├── Contract report.png ├── local_install.png └── Chessgame report.png ├── postcss.config.js ├── server- ├── vercel.json ├── package.json ├── index.js └── package-lock.json ├── tsconfig.json ├── tailwind.config.js ├── vite.config.ts ├── Contract ├── tsconfig.json ├── data.txt ├── README.md ├── .gitignore └── ChessGame.sol ├── index.html ├── tsconfig.node.json ├── truffle-config.cjs ├── tsconfig.app.json ├── eslint.config.js ├── LICENSE ├── GetPoints.md ├── package.json ├── .gitignore ├── CONTRIBUTING.md └── README.md /test/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [[redirects]] 2 | from = "/*" 3 | to = "/index.html" 4 | status = 200 -------------------------------------------------------------------------------- /src/types/global.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | ethereum: any; 3 | Stockfish: any; 4 | } -------------------------------------------------------------------------------- /src/assets/Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/src/assets/Queen.png -------------------------------------------------------------------------------- /src/assets/Rook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/src/assets/Rook.png -------------------------------------------------------------------------------- /src/assets/Bishop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/src/assets/Bishop.png -------------------------------------------------------------------------------- /src/assets/pngegg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/src/assets/pngegg.png -------------------------------------------------------------------------------- /MockDown images/clone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/MockDown images/clone.png -------------------------------------------------------------------------------- /MockDown images/Botmode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/MockDown images/Botmode.png -------------------------------------------------------------------------------- /MockDown images/Chess-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/MockDown images/Chess-home.png -------------------------------------------------------------------------------- /MockDown images/local_run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/MockDown images/local_run.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /MockDown images/game created.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/MockDown images/game created.png -------------------------------------------------------------------------------- /MockDown images/whitescreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/MockDown images/whitescreen.png -------------------------------------------------------------------------------- /MockDown images/Contract report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/MockDown images/Contract report.png -------------------------------------------------------------------------------- /MockDown images/local_install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/MockDown images/local_install.png -------------------------------------------------------------------------------- /MockDown images/Chessgame report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Navneet1206/Ether-Chess-OTC/HEAD/MockDown images/Chessgame report.png -------------------------------------------------------------------------------- /server-/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version":2, 3 | "builds":[{"src":"./index.js","use":"@vercel/node"}], 4 | "routes": [{"src":"/(.*)","dest":"/"}] 5 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | 2 | import { createRoot } from 'react-dom/client'; 3 | import App from './App.tsx'; 4 | import './index.css'; 5 | 6 | createRoot(document.getElementById('root')!).render( 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss/base"; 2 | @import "tailwindcss/components"; 3 | @import "tailwindcss/utilities"; 4 | .highlight-check { 5 | background-color: rgba(255, 0, 0, 0.5); /* Red translucent background */ 6 | } -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | optimizeDeps: { 8 | exclude: ['lucide-react'], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /Contract/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/config/constants.ts: -------------------------------------------------------------------------------- 1 | export const CONTRACT_ADDRESS = '0x5E88992fC85ab96bb184269C8E5cBd77BF933147'; // Replace with actual deployed contract address 2 | 3 | export const MINIMUM_STAKE = '0.00001'; 4 | export const MAXIMUM_STAKE = '0.1'; 5 | 6 | export const BOT_DIFFICULTY_LEVELS = { 7 | EASY: 5, 8 | MEDIUM: 10, 9 | HARD: 15, 10 | } as const; -------------------------------------------------------------------------------- /src/components/Input.tsx: -------------------------------------------------------------------------------- 1 | export const Input = ({ label, ...props }) => ( 2 |
3 | {label && } 4 | 5 |
6 | ); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | web3-chess-platform 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Contract/data.txt: -------------------------------------------------------------------------------- 1 | import { HardhatUserConfig } from 'hardhat/config'; 2 | import '@nomicfoundation/hardhat-toolbox'; 3 | const config: HardhatUserConfig = { 4 | solidity: '0.8.20', 5 | networks: { 6 | sepolia: { 7 | url: `https://eth-ropsten.alchemyapi.io/v2/z4WpA8UKgqnwbTYmrZu15yCOiijBKaRv`, 8 | accounts: '2f99db8cdb04655028eee1dc98230925202f6b3e010e43fad2883b4bea90a1a3', 9 | }, 10 | }, 11 | }; 12 | 13 | export default config; -------------------------------------------------------------------------------- /Contract/README.md: -------------------------------------------------------------------------------- 1 | # Sample Hardhat Project 2 | 3 | This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a Hardhat Ignition module that deploys that contract. 4 | 5 | Try running some of the following tasks: 6 | 7 | ```shell 8 | npx hardhat help 9 | npx hardhat test 10 | REPORT_GAS=true npx hardhat test 11 | npx hardhat node 12 | npx hardhat ignition deploy ./ignition/modules/Lock.ts 13 | ``` 14 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | export interface Player { 2 | address: string; 3 | username: string; 4 | rating: number; 5 | earnings: number; 6 | } 7 | 8 | export interface GameState { 9 | gameId?: string | null; 10 | players?: { 11 | white: Player | null; 12 | black: Player | null; 13 | }; 14 | stake?: string | number; 15 | status?: 'waiting' | 'active' | 'completed'; 16 | winner?: string | null; 17 | moves?: string[]; 18 | position?: string; 19 | checkedKing?: 'white' | 'black' | null; //Check if the king is in checked 20 | } -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "lib": ["ES2023"], 5 | "module": "ESNext", 6 | "skipLibCheck": true, 7 | 8 | /* Bundler mode */ 9 | "moduleResolution": "bundler", 10 | "allowImportingTsExtensions": true, 11 | "isolatedModules": true, 12 | "moduleDetection": "force", 13 | "noEmit": true, 14 | 15 | /* Linting */ 16 | "strict": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "noFallthroughCasesInSwitch": true 20 | }, 21 | "include": ["vite.config.ts"] 22 | } 23 | -------------------------------------------------------------------------------- /truffle-config.cjs: -------------------------------------------------------------------------------- 1 | // truffle-config.cjs 2 | const { config: dotenvConfig } = require("dotenv"); 3 | const { HardhatUserConfig } = require("hardhat/config"); 4 | require("@nomiclabs/hardhat-ethers"); 5 | 6 | dotenvConfig(); // Loads .env variables 7 | 8 | const SEPOLIA_URL = process.env.SEPOLIA_URL || ""; 9 | const PRIVATE_KEY = process.env.PRIVATE_KEY || ""; 10 | 11 | const config = { 12 | solidity: "0.8.20", 13 | networks: { 14 | sepolia: { 15 | url: SEPOLIA_URL, 16 | accounts: PRIVATE_KEY !== "" ? [PRIVATE_KEY] : [], 17 | }, 18 | }, 19 | }; 20 | 21 | module.exports = config; 22 | -------------------------------------------------------------------------------- /src/components/Dialog.tsx: -------------------------------------------------------------------------------- 1 | export const Dialog = ({ open, onClose, title, description, children }) => { 2 | if (!open) return null; 3 | 4 | return ( 5 |
6 |
7 |
8 | {title &&

{title}

} 9 | {description &&

{description}

} 10 | {children} 11 |
12 |
13 | ); 14 | }; -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "isolatedModules": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"] 24 | } 25 | -------------------------------------------------------------------------------- /server-/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "start": "nodemon index.js" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "@jackstenglein/chess": "^2.2.8", 14 | "body-parser": "^1.20.3", 15 | "chess.js": "^1.0.0-beta.8", 16 | "chessground": "^9.1.1", 17 | "cors": "^2.8.5", 18 | "ethers": "^6.13.5", 19 | "express": "^4.21.2", 20 | "http": "^0.0.1-security", 21 | "socket.io": "^4.8.1", 22 | "ws": "^8.18.0" 23 | }, 24 | "devDependencies": { 25 | "nodemon": "^3.1.7" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/components/ErrorMessage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { AlertCircle } from 'lucide-react'; 3 | 4 | interface ErrorMessageProps { 5 | message: string; 6 | onClose?: () => void; 7 | } 8 | 9 | export const ErrorMessage: React.FC = ({ message, onClose }) => { 10 | return ( 11 |
12 |
13 | 14 |

{message}

15 | {onClose && ( 16 | 22 | )} 23 |
24 |
25 | ); 26 | }; -------------------------------------------------------------------------------- /src/components/Button.tsx: -------------------------------------------------------------------------------- 1 | import { Loader2 } from 'lucide-react'; 2 | 3 | export const Button = ({ children, onClick, disabled, variant = 'primary', className = '', loading = false }) => { 4 | const baseStyles = "px-4 py-2 rounded-lg font-medium transition-colors disabled:opacity-50 flex items-center justify-center gap-2"; 5 | const variants = { 6 | primary: "bg-indigo-600 hover:bg-indigo-500 text-white disabled:hover:bg-indigo-600", 7 | secondary: "bg-gray-700 hover:bg-gray-600 text-white", 8 | outline: "border border-white/10 bg-gray-800 hover:bg-gray-700 text-white" 9 | }; 10 | 11 | return ( 12 | 16 | ); 17 | }; -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js'; 2 | import globals from 'globals'; 3 | import reactHooks from 'eslint-plugin-react-hooks'; 4 | import reactRefresh from 'eslint-plugin-react-refresh'; 5 | import tseslint from 'typescript-eslint'; 6 | 7 | export default tseslint.config( 8 | { ignores: ['dist'] }, 9 | { 10 | extends: [js.configs.recommended, ...tseslint.configs.recommended], 11 | files: ['**/*.{ts,tsx}'], 12 | languageOptions: { 13 | ecmaVersion: 2020, 14 | globals: globals.browser, 15 | }, 16 | plugins: { 17 | 'react-hooks': reactHooks, 18 | 'react-refresh': reactRefresh, 19 | }, 20 | rules: { 21 | ...reactHooks.configs.recommended.rules, 22 | 'react-refresh/only-export-components': [ 23 | 'warn', 24 | { allowConstantExport: true }, 25 | ], 26 | }, 27 | } 28 | ); 29 | -------------------------------------------------------------------------------- /src/store/useGameStore.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand'; 2 | import { GameState } from '../types'; 3 | 4 | interface GameStore { 5 | gameState: GameState; 6 | setGameState: (state: GameState) => void; 7 | resetGame: () => void; 8 | checkedKing: 'white' | 'black' | null; 9 | setCheckedKing: (king: 'white' | 'black' | null) => void; 10 | } 11 | 12 | const initialGameState: GameState = { 13 | position: 'start', 14 | players: { 15 | white: null, 16 | black: null 17 | }, 18 | status: 'waiting', 19 | moves: [], 20 | stake: 0, 21 | gameId: null, 22 | checkedKing: null, 23 | }; 24 | 25 | export const useGameStore = create((set) => ({ 26 | checkedKing: null, 27 | setCheckedKing: (king) => set({ checkedKing: king }), 28 | gameState: initialGameState, 29 | setGameState: (state) => set({ gameState: { ...initialGameState, ...state } }), 30 | resetGame: () => set({ gameState: initialGameState }), 31 | })); 32 | -------------------------------------------------------------------------------- /Contract/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | 4 | # Hardhat files 5 | /cache 6 | /artifacts 7 | 8 | # TypeChain files 9 | /typechain 10 | /typechain-types 11 | 12 | # solidity-coverage files 13 | /coverage 14 | /coverage.json 15 | 16 | # Hardhat Ignition default folder for deployments against a local node 17 | ignition/deployments/chain-31337 18 | 19 | node_modules 20 | .env 21 | 22 | # Hardhat files 23 | /cache 24 | /artifacts 25 | 26 | # TypeChain files 27 | /typechain 28 | /typechain-types 29 | 30 | # solidity-coverage files 31 | /coverage 32 | /coverage.json 33 | 34 | # Hardhat Ignition default folder for deployments against a local node 35 | ignition/deployments/chain-31337 36 | 37 | node_modules 38 | .env 39 | 40 | # Hardhat files 41 | /cache 42 | /artifacts 43 | 44 | # TypeChain files 45 | /typechain 46 | /typechain-types 47 | 48 | # solidity-coverage files 49 | /coverage 50 | /coverage.json 51 | 52 | # Hardhat Ignition default folder for deployments against a local node 53 | ignition/deployments/chain-31337 54 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; 3 | import { Navbar } from './components/Navbar'; 4 | import { Home } from './pages/Home'; 5 | import { FreeMode } from './pages/FreeMode'; 6 | import { BotMode } from './pages/BotMode'; 7 | import { OnlineMode } from './pages/OnlineMode'; 8 | import { Leaderboard } from './pages/Leaderboard'; 9 | import { Footer } from './components/Footer'; 10 | 11 | function App() { 12 | return ( 13 | 14 |
15 | 16 | 17 | } /> 18 | } /> 19 | } /> 20 | } /> 21 | } /> 22 | 23 |
24 |
25 |
26 | ); 27 | } 28 | 29 | export default App; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Navneet Vishwakarma 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /GetPoints.md: -------------------------------------------------------------------------------- 1 | 2 | # Thank you for contributing to this project! To streamline the process and ensure smooth collaboration, please follow the guidelines below when submitting your pull requests. 3 | 4 | ## **How to Submit Pull Request Information** 5 | 6 | ### Step 1: Visit the Portfolio 7 | - Go to Portfolio :- https://navneet-resume.netlify.app/ 8 | 9 | ### Step 2: Fill Out the Contact Form 10 | provide the following details in the form: 11 | 12 | 1. **Name:** 13 | - Format: Your Full Name (GitHub Username) 14 | - Example: John Doe (johndoe123) 15 | 16 | 2. **Mail:** 17 | - Use your working email address. 18 | 19 | 3. **Project:** 20 | - Include the URL of your pull request. 21 | 22 | 4. **Message:** 23 | - Provide additional details about your contribution type(s). 24 | - If you have multiple pull requests, list them in the message using the format below: 25 | 26 | ### Example Format for the Message Section: 27 | ```plaintext 28 | Pull Request 1: [URL] 29 | Contribution Type: Bug Fix / Feature Addition / Documentation Update, etc. 30 | 31 | Pull Request 2: [URL] 32 | Contribution Type: Code Optimization / Testing, etc. 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web3-chess-platform", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@jackstenglein/chess": "^2.2.8", 14 | "@openzeppelin/contracts": "^5.0.1", 15 | "chess.js": "^1.0.0-beta.7", 16 | "chessground": "^9.1.1", 17 | "ethers": "^6.11.1", 18 | "express": "^4.18.3", 19 | "hardhat": "^2.22.17", 20 | "lucide-react": "^0.344.0", 21 | "react": "^18.3.1", 22 | "react-chessboard": "^4.4.0", 23 | "react-dom": "^18.3.1", 24 | "react-router-dom": "^6.22.2", 25 | "socket.io": "^4.7.4", 26 | "socket.io-client": "^4.7.4", 27 | "stockfish.js": "^10.0.2", 28 | "zustand": "^4.5.2" 29 | }, 30 | "devDependencies": { 31 | "@eslint/js": "^9.9.1", 32 | "@types/concat-stream": "^2.0.3", 33 | "@types/react": "^18.3.5", 34 | "@types/react-dom": "^18.3.0", 35 | "@vitejs/plugin-react": "^4.3.1", 36 | "autoprefixer": "^10.4.18", 37 | "eslint": "^9.9.1", 38 | "eslint-plugin-react-hooks": "^5.1.0-rc.0", 39 | "eslint-plugin-react-refresh": "^0.4.11", 40 | "globals": "^15.9.0", 41 | "postcss": "^8.4.35", 42 | "tailwindcss": "^3.4.1", 43 | "typescript": "^5.5.3", 44 | "typescript-eslint": "^8.3.0", 45 | "vite": "^5.4.2" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/components/GameStatus.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Clock } from 'lucide-react'; 3 | 4 | interface GameStatusProps { 5 | status: 'waiting' | 'active' | 'completed'; 6 | timeLeft?: number; 7 | currentPlayer?: 'white' | 'black'; 8 | } 9 | 10 | export const GameStatus: React.FC = ({ status, timeLeft, currentPlayer }) => { 11 | return ( 12 |
13 |
14 |
15 |
20 | {status} 21 |
22 | {timeLeft && ( 23 |
24 | 25 | {Math.floor(timeLeft / 60)}:{(timeLeft % 60).toString().padStart(2, '0')} 26 |
27 | )} 28 |
29 | {currentPlayer && status === 'active' && ( 30 |

31 | Current turn: {currentPlayer} 32 |

33 | )} 34 |
35 | ); 36 | }; 37 | -------------------------------------------------------------------------------- /src/store/useWalletStore.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand'; 2 | import { ethers } from 'ethers'; 3 | 4 | interface WalletState { 5 | address: string | null; 6 | balance: string | null; 7 | provider: ethers.BrowserProvider | null; 8 | signer: ethers.JsonRpcSigner | null; 9 | isConnecting: boolean; 10 | error: string | null; 11 | connectWallet: () => Promise; 12 | disconnectWallet: () => void; 13 | } 14 | 15 | export const useWalletStore = create((set) => ({ 16 | address: null, 17 | balance: null, 18 | provider: null, 19 | signer: null, 20 | isConnecting: false, 21 | error: null, 22 | 23 | connectWallet: async () => { 24 | try { 25 | set({ isConnecting: true, error: null }); 26 | 27 | if (!window.ethereum) { 28 | throw new Error('MetaMask is not installed'); 29 | } 30 | 31 | const provider = new ethers.BrowserProvider(window.ethereum); 32 | const signer = await provider.getSigner(); 33 | const address = await signer.getAddress(); 34 | const balance = ethers.formatEther(await provider.getBalance(address)); 35 | 36 | set({ provider, signer, address, balance, isConnecting: false }); 37 | } catch (error) { 38 | set({ error: (error as Error).message, isConnecting: false }); 39 | } 40 | }, 41 | 42 | disconnectWallet: () => { 43 | set({ 44 | address: null, 45 | balance: null, 46 | provider: null, 47 | signer: null, 48 | error: null, 49 | }); 50 | }, 51 | })); -------------------------------------------------------------------------------- /src/components/WalletConnect.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useWalletStore } from '../store/useWalletStore'; 3 | import { Wallet } from 'lucide-react'; 4 | 5 | export const WalletConnect: React.FC = () => { 6 | const { address, balance, connectWallet, disconnectWallet, isConnecting, error } = useWalletStore(); 7 | 8 | return ( 9 |
10 | {address ? ( 11 |
12 |
13 |

14 | {address.slice(0, 6)}...{address.slice(-4)} 15 |

16 |

{balance?.slice(0, 8)} ETH

17 |
18 | 24 |
25 | ) : ( 26 | 34 | )} 35 | {error &&

{error}

} 36 |
37 | ); 38 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | -------------------------------------------------------------------------------- /server-/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { ethers } = require('ethers'); 3 | const cors = require('cors'); 4 | const { Chess } = require('chess.js'); 5 | const { createServer } = require('http'); 6 | const { Server } = require('socket.io'); 7 | 8 | const app = express(); 9 | const server = createServer(app); 10 | const io = new Server(server, { 11 | cors: { 12 | origin: '*', // Allow all origins (update in production) 13 | }, 14 | }); 15 | 16 | app.use(cors()); 17 | app.use(express.json()); 18 | 19 | // Ethereum contract setup 20 | const provider = new ethers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'); // Replace with your Infura or Alchemy URL 21 | const contractAddress = '0xA12E9052EDbffCA633eBe3Fc9B3F477E516d4D43'; // Replace with your contract address 22 | const contractABI = [ 23 | // Paste your contract ABI here 24 | ]; 25 | 26 | const contract = new ethers.Contract(contractAddress, contractABI, provider); 27 | 28 | // In-memory game state storage 29 | const games = new Map(); // gameId -> { position: 'start', players: { white: address, black: address } } 30 | 31 | // Socket.io connection handler 32 | io.on('connection', (socket) => { 33 | console.log('A user connected:', socket.id); 34 | 35 | // Handle game creation 36 | socket.on('createGame', async ({ gameId, stake, address }) => { 37 | try { 38 | const game = new Chess(); 39 | games.set(gameId, { position: game.fen(), players: { white: address, black: null } }); 40 | socket.join(gameId); 41 | io.to(gameId).emit('gameState', { position: game.fen(), players: { white: address, black: null } }); 42 | } catch (error) { 43 | console.error('Error creating game:', error); 44 | socket.emit('error', 'Failed to create game'); 45 | } 46 | }); 47 | 48 | // Handle game joining 49 | socket.on('joinGame', async ({ gameId, address }) => { 50 | try { 51 | const gameState = games.get(gameId); 52 | if (!gameState) { 53 | throw new Error('Game does not exist'); 54 | } 55 | if (gameState.players.black) { 56 | throw new Error('Game is already full'); 57 | } 58 | 59 | gameState.players.black = address; 60 | games.set(gameId, gameState); 61 | socket.join(gameId); 62 | io.to(gameId).emit('gameState', gameState); 63 | } catch (error) { 64 | console.error('Error joining game:', error); 65 | socket.emit('error', error.message); 66 | } 67 | }); 68 | 69 | // Handle moves 70 | socket.on('makeMove', ({ gameId, move }) => { 71 | try { 72 | const gameState = games.get(gameId); 73 | if (!gameState) { 74 | throw new Error('Game does not exist'); 75 | } 76 | 77 | const game = new Chess(gameState.position); 78 | const result = game.move(move); 79 | if (!result) { 80 | throw new Error('Invalid move'); 81 | } 82 | 83 | gameState.position = game.fen(); 84 | games.set(gameId, gameState); 85 | io.to(gameId).emit('gameState', gameState); 86 | 87 | // Check for game over 88 | if (game.isGameOver()) { 89 | io.to(gameId).emit('gameOver', { winner: game.turn() === 'w' ? gameState.players.black : gameState.players.white }); 90 | } 91 | } catch (error) { 92 | console.error('Error making move:', error); 93 | socket.emit('error', error.message); 94 | } 95 | }); 96 | 97 | // Handle disconnection 98 | socket.on('disconnect', () => { 99 | console.log('A user disconnected:', socket.id); 100 | }); 101 | }); 102 | 103 | // Start the server 104 | const PORT = process.env.PORT || 5000; 105 | server.listen(PORT, () => { 106 | console.log(`Server running on port ${PORT}`); 107 | }); -------------------------------------------------------------------------------- /Contract/ChessGame.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | import "@openzeppelin/contracts/access/Ownable.sol"; 4 | import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 5 | 6 | contract ChessGame is Ownable, ReentrancyGuard { 7 | struct Game { 8 | address white; 9 | address black; 10 | uint256 stake; 11 | bool isActive; 12 | address winner; 13 | uint256 startTime; 14 | uint256 joinTimeout; // Timeout for joining the game 15 | } 16 | 17 | mapping(bytes32 => Game) public games; 18 | mapping(address => uint256) public playerEarnings; 19 | 20 | uint256 public ownerFeePercentage = 5; // 5% fee 21 | uint256 public joinTimeoutDuration = 1 hours; // Default timeout duration 22 | 23 | event GameCreated(bytes32 gameId, address indexed white, uint256 stake, uint256 startTime); 24 | event GameJoined(bytes32 gameId, address indexed black); 25 | event GameEnded(bytes32 gameId, address indexed winner, uint256 prize); 26 | event GameCanceled(bytes32 gameId, address indexed canceledBy); 27 | event StakeRefunded(bytes32 gameId, address indexed player, uint256 amount); 28 | 29 | constructor() {} 30 | 31 | /// @notice Creates a new chess game with a given gameId and stake. 32 | /// @param gameId The unique identifier for the game (as bytes32). 33 | function createGame(bytes32 gameId) external payable { 34 | require(msg.value > 0, "Stake must be greater than 0"); 35 | require(games[gameId].white == address(0), "Game already exists"); 36 | 37 | games[gameId] = Game({ 38 | white: msg.sender, 39 | black: address(0), 40 | stake: msg.value, 41 | isActive: true, 42 | winner: address(0), 43 | startTime: block.timestamp, 44 | joinTimeout: block.timestamp + joinTimeoutDuration 45 | }); 46 | 47 | emit GameCreated(gameId, msg.sender, msg.value, block.timestamp); 48 | } 49 | 50 | /// @notice Joins an existing game by providing the correct stake. 51 | /// @param gameId The unique identifier for the game to join. 52 | function joinGame(bytes32 gameId) external payable { 53 | Game storage game = games[gameId]; 54 | require(game.white != address(0), "Game does not exist"); 55 | require(game.black == address(0), "Game already full"); 56 | require(msg.value == game.stake, "Incorrect stake amount"); 57 | require(block.timestamp <= game.joinTimeout, "Join timeout expired"); 58 | 59 | game.black = msg.sender; 60 | emit GameJoined(gameId, msg.sender); 61 | } 62 | 63 | /// @notice Ends a game and declares the winner. Only the owner can call this. 64 | /// @param gameId The unique identifier for the game to end. 65 | /// @param winner The address of the winner. 66 | function endGame(bytes32 gameId, address winner) external onlyOwner { 67 | Game storage game = games[gameId]; 68 | require(game.isActive, "Game not active"); 69 | require(winner == game.white || winner == game.black, "Invalid winner"); 70 | 71 | game.isActive = false; 72 | game.winner = winner; 73 | 74 | uint256 totalPrize = game.stake * 2; 75 | uint256 ownerFee = (totalPrize * ownerFeePercentage) / 100; 76 | uint256 winnerPrize = totalPrize - ownerFee; 77 | 78 | playerEarnings[winner] += winnerPrize; 79 | 80 | emit GameEnded(gameId, winner, winnerPrize); 81 | } 82 | 83 | /// @notice Cancels a game and refunds stakes. Only the owner can call this. 84 | /// @param gameId The unique identifier for the game to cancel. 85 | function cancelGame(bytes32 gameId) external onlyOwner { 86 | Game storage game = games[gameId]; 87 | require(game.isActive, "Game not active"); 88 | 89 | game.isActive = false; 90 | 91 | // Refund stakes 92 | payable(game.white).transfer(game.stake); 93 | if (game.black != address(0)) { 94 | payable(game.black).transfer(game.stake); 95 | } 96 | 97 | emit GameCanceled(gameId, msg.sender); 98 | } 99 | 100 | /// @notice Withdraw earnings for the caller. 101 | function withdrawEarnings() external nonReentrant { 102 | uint256 amount = playerEarnings[msg.sender]; 103 | require(amount > 0, "No earnings to withdraw"); 104 | 105 | playerEarnings[msg.sender] = 0; 106 | payable(msg.sender).transfer(amount); 107 | } 108 | 109 | /// @notice Withdraw accumulated fees by the owner. 110 | function withdrawOwnerFees() external onlyOwner { 111 | uint256 balance = address(this).balance; 112 | require(balance > 0, "No fees to withdraw"); 113 | payable(owner()).transfer(balance); 114 | } 115 | } -------------------------------------------------------------------------------- /src/services/socketService.ts: -------------------------------------------------------------------------------- 1 | import { io, Socket } from 'socket.io-client'; 2 | import { GameState } from '../types'; 3 | import { useGameStore } from '../store/useGameStore'; 4 | 5 | class SocketService { 6 | private socket: Socket | null = null; 7 | private gameStateCallback: ((state: GameState) => void) | null = null; 8 | private reconnectAttempts = 0; 9 | private maxReconnectAttempts = 3; 10 | private currentGameId: string | null = null; 11 | 12 | connect(address: string, username: string) { 13 | this.disconnect(); 14 | 15 | if (!address || !username) { 16 | console.error('Invalid connection parameters'); 17 | return; 18 | } 19 | 20 | this.attemptConnection(address, username); 21 | } 22 | 23 | private attemptConnection(address: string, username: string) { 24 | this.reconnectAttempts = 0; 25 | this.createSocketConnection(address, username); 26 | } 27 | 28 | private createSocketConnection(address: string, username: string) { 29 | try { 30 | this.socket = io('http://localhost:8080', { 31 | query: { 32 | address: address.toLowerCase(), 33 | username: username.trim() 34 | }, 35 | transports: ['websocket', 'polling'], 36 | reconnection: true, 37 | reconnectionAttempts: this.maxReconnectAttempts, 38 | reconnectionDelay: 1000 39 | }); 40 | 41 | this.setupSocketListeners(address, username); 42 | } catch (error) { 43 | console.error('Socket connection initialization error:', error); 44 | this.handleConnectionError(address, username); 45 | } 46 | } 47 | 48 | private setupSocketListeners(address: string, username: string) { 49 | if (!this.socket) return; 50 | 51 | this.socket.on('connect', () => { 52 | console.log('Socket connected successfully'); 53 | this.reconnectAttempts = 0; 54 | 55 | // Request initial game state if a game is in progress 56 | if (this.currentGameId && this.socket) { 57 | this.socket.emit('requestInitialGameState', { gameId: this.currentGameId }); 58 | } 59 | }); 60 | 61 | this.socket.on('connect_error', (error) => { 62 | console.error('Connection error:', error); 63 | this.handleConnectionError(address, username); 64 | }); 65 | 66 | this.socket.on('disconnect', (reason) => { 67 | console.log('Socket disconnected:', reason); 68 | if (reason === 'io server disconnect') { 69 | this.createSocketConnection(address, username); 70 | } 71 | }); 72 | 73 | this.socket.on('gameCreated', ({ gameId }) => { 74 | console.log('Game created with ID:', gameId); 75 | this.currentGameId = gameId; 76 | }); 77 | 78 | this.socket.on('gameState', (state: GameState) => { 79 | console.log('Received game state:', state); 80 | if (this.gameStateCallback) { 81 | this.gameStateCallback(state); 82 | } 83 | }); 84 | 85 | this.socket.on('initialGameState', (state: GameState) => { 86 | console.log('Received initial game state:', state); 87 | if (this.gameStateCallback) { 88 | this.gameStateCallback(state); 89 | } 90 | }); 91 | 92 | // Check if the king is in check 93 | this.socket.on('kingInCheck', ({ kingColor }) => { 94 | console.log('King in check:', kingColor); 95 | useGameStore.getState().setCheckedKing(kingColor); 96 | }); 97 | 98 | this.socket.on('gameOver', ({ winner }) => { 99 | console.log('Game over, winner:', winner); 100 | useGameStore.getState().setGameState({ status: 'finished', winner }); 101 | }); 102 | } 103 | 104 | private handleConnectionError(address: string, username: string) { 105 | this.reconnectAttempts++; 106 | 107 | if (this.reconnectAttempts < this.maxReconnectAttempts) { 108 | console.log(`Reconnection attempt ${this.reconnectAttempts}`); 109 | 110 | setTimeout(() => { 111 | this.createSocketConnection(address, username); 112 | }, 1000 * this.reconnectAttempts); 113 | } else { 114 | console.error('Maximum reconnection attempts reached'); 115 | } 116 | } 117 | 118 | createGame(stake: string) { 119 | if (!this.socket) return; 120 | this.socket.emit('createGame', { stake }); 121 | } 122 | 123 | joinGame(gameId: string) { 124 | if (!this.socket) return; 125 | this.currentGameId = gameId; 126 | this.socket.emit('joinGame', { gameId }); 127 | } 128 | 129 | makeMove(gameId: string, move: { from: string; to: string }) { 130 | if (!this.socket) return; 131 | this.socket.emit('makeMove', { gameId, move }); 132 | } 133 | 134 | onGameState(callback: (state: GameState) => void) { 135 | this.gameStateCallback = callback; 136 | } 137 | 138 | disconnect() { 139 | if (this.socket) { 140 | this.socket.disconnect(); 141 | this.socket = null; 142 | this.currentGameId = null; 143 | } 144 | } 145 | } 146 | 147 | export const socketService = new SocketService(); -------------------------------------------------------------------------------- /src/components/Footer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | export const Footer: React.FC = () => { 5 | return ( 6 |
7 | {/* Subtle animated chess pattern */} 8 |
9 |
10 | {[...Array(16)].map((_, i) => ( 11 |
17 | ))} 18 |
19 |
20 | 21 |
22 |
23 |
24 |
25 | 26 |

Web3 Chess

27 |
28 |

29 | The future of chess meets blockchain technology. Play, compete, and earn in the most innovative chess platform. 30 |

31 |
32 | 33 |
34 |

Play

35 |
    36 |
  • 37 | console.log('Navigate to practice')} className="text-blue-200/70 hover:text-blue-400 text-sm transition-colors"> 38 | Practice Mode 39 | 40 |
  • 41 |
  • 42 | console.log('Navigate to tournaments')} className="text-blue-200/70 hover:text-blue-400 text-sm transition-colors"> 43 | Tournaments 44 | 45 |
  • 46 |
  • 47 | console.log('Navigate to AI')} className="text-blue-200/70 hover:text-blue-400 text-sm transition-colors"> 48 | AI Challenge 49 | 50 |
  • 51 |
52 |
53 | 54 |
55 |

Resources

56 |
    57 |
  • 58 | 61 |
  • 62 |
  • 63 | 66 |
  • 67 |
  • 68 | 71 |
  • 72 |
73 |
74 | 75 |
76 |

Legal

77 |
    78 |
  • 79 | 82 |
  • 83 |
  • 84 | 87 |
  • 88 |
  • 89 | 92 |
  • 93 |
94 |
95 |
96 | 97 |
98 |

99 | © {new Date().getFullYear()} Web3 Chess. All rights reserved. 100 |

101 |
102 | 105 | 108 | 111 |
112 |
113 |
114 |
115 | ); 116 | }; -------------------------------------------------------------------------------- /src/pages/Leaderboard.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Trophy, Crown, Award, Medal } from 'lucide-react'; 3 | 4 | interface LeaderboardEntry { 5 | address: string; 6 | username: string; 7 | earnings: number; 8 | gamesPlayed: number; 9 | winRate: number; 10 | } 11 | 12 | const mockLeaderboard: LeaderboardEntry[] = [ 13 | { 14 | address: '0x1234...5678', 15 | username: 'GrandMaster1', 16 | earnings: 3.5, 17 | gamesPlayed: 145, 18 | winRate: 0.82, 19 | }, 20 | { 21 | address: '0x8765...4321', 22 | username: 'CryptoKing', 23 | earnings: 2.8, 24 | gamesPlayed: 98, 25 | winRate: 0.75, 26 | }, 27 | { 28 | address: '0x9876...1234', 29 | username: 'ChessWhiz', 30 | earnings: 2.1, 31 | gamesPlayed: 112, 32 | winRate: 0.71, 33 | }, 34 | { 35 | address: '0x4567...8901', 36 | username: 'BlockchainKnight', 37 | earnings: 1.9, 38 | gamesPlayed: 87, 39 | winRate: 0.68, 40 | }, 41 | { 42 | address: '0x3456...7890', 43 | username: 'Web3Bishop', 44 | earnings: 1.5, 45 | gamesPlayed: 76, 46 | winRate: 0.65, 47 | }, 48 | ]; 49 | 50 | export const Leaderboard: React.FC = () => { 51 | const getRankIcon = (index: number) => { 52 | switch (index) { 53 | case 0: 54 | return ; 55 | case 1: 56 | return ; 57 | case 2: 58 | return ; 59 | default: 60 | return
{index + 1}
; 61 | } 62 | }; 63 | 64 | return ( 65 |
66 |
67 |
68 |
69 |
70 | 71 |
72 |

Masters of the Board

73 |

Top players by earnings and performance

74 |
75 |
76 |
77 | 78 |
79 | 80 | 81 | 82 | 85 | 88 | 91 | 94 | 97 | 98 | 99 | 100 | {mockLeaderboard.map((entry, index) => ( 101 | 105 | 110 | 114 | 119 | 124 | 129 | 130 | ))} 131 | 132 |
83 | Rank 84 | 86 | Player 87 | 89 | Earnings (ETH) 90 | 92 | Games 93 | 95 | Win Rate 96 |
106 |
107 | {getRankIcon(index)} 108 |
109 |
111 |
{entry.username}
112 |
{entry.address}
113 |
115 |
116 | {entry.earnings.toFixed(2)} ETH 117 |
118 |
120 |
121 | {entry.gamesPlayed} 122 |
123 |
125 |
126 | {(entry.winRate * 100).toFixed(1)}% 127 |
128 |
133 |
134 |
135 |
136 |
137 | ); 138 | }; 139 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribute to the Online Chess Game Project 2 | 3 | Thank you for your interest in contributing to the Online Chess Game project! Below is a detailed guide on the current issues and how you can help improve the project. 4 | 5 | --- 6 | 7 | ## Project Overview 8 | This is an online chess platform built using React, Ethereum, and Web3.js. Players can connect their wallets, make payments in ETH, and start chess games. While the core functionality is in place, there are some bugs and areas for improvement. 9 | 10 | --- 11 | 12 | ## Current Issues 13 | 14 | ### 1. **Drag-and-Drop Chess Piece Movement (High Priority)** 15 | - **Description**: Currently, players must hold and drag a chess piece to its desired position. This behavior is unintuitive and disrupts gameplay. 16 | - **Improvement**: Implement a smoother drag-and-drop functionality or enable single-click selection and movement for a better user experience. 17 | 18 | --- 19 | 20 | ### 2. **Pawn Promotion Bug** 21 | - **Description**: When a pawn reaches the last rank for promotion, the game gets stuck, and no promotion options are shown. 22 | - **Improvement**: 23 | 1. Fix the logic to detect when a pawn reaches the promotion rank. 24 | 2. Display a modal or dropdown to select the desired piece (Queen, Rook, Bishop, Knight). 25 | 3. Ensure the game resumes seamlessly after promotion. 26 | 27 | --- 28 | 29 | ### 3. **Chess Game Loading Issue** 30 | - **Description**: After connecting the wallet and making a payment, the chess game occasionally fails to load, resulting in a white screen. 31 | - **Improvement**: Debug the chessboard component's state and props to ensure they initialize correctly. Verify dependencies and WebSocket connections. 32 | 33 | **Error Preview**: 34 | ![Error Screenshot](./MockDown%20images/whitescreen.png) 35 | 36 | ```error 37 | socketService.ts:21 WebSocket connection to 'ws://localhost:3001/socket.io/?address=0xbf786287609d1e4bfa96794893fc899ae957f484&username=Player&EIO=4&transport=websocket' failed: WebSocket is closed before the connection is established. 38 | setTimeoutconnect@socketService.ts:21handleCreateGame@OnlineMode.tsx:75 39 | socketService.ts:39 Socket connected successfully 40 | socketService.ts:47 Game created with ID: 3gik7tpb 41 | ``` 42 | 43 | --- 44 | 45 | ### 4. **Alerts Instead of Popups** 46 | - **Location**: Multiple files, primarily `src/components/OnlineMode.jsx` 47 | - **Description**: The application currently uses `alert()` for notifications, which is disruptive and not user-friendly. 48 | - **Improvement**: Replace `alert()` with a modal-based popup component for better UX. 49 | 50 | --- 51 | 52 | ### 5. **Missing Loaders** 53 | - **Location**: `src/components/OnlineMode.jsx` 54 | - **Description**: There is no indication of ongoing processes such as connecting to the wallet, making a payment, or loading the game. 55 | - **Improvement**: Add loaders to show progress for the following actions: 56 | - Wallet connection 57 | - Payment processing 58 | - Chess game initialization 59 | 60 | --- 61 | 62 | ### 6. **Add Input Validation** 63 | - **Location**: `src/components/OnlineMode.jsx` 64 | - **Description**: The input fields (e.g., stake amount) do not have proper validation, leading to potential errors or misuse. 65 | - **Improvement**: Add validations to ensure: 66 | - Stake amounts are positive integers. 67 | - All required fields are filled before proceeding. 68 | 69 | --- 70 | 71 | ### 7. **Suggested Features** 72 | - **Enhance User Interface**: Improve the layout and aesthetics of the chess game and wallet integration screens. 73 | - **Add Sound Effects**: Provide sound feedback for actions like moves, payments, and connection success. 74 | - **Game History**: Display a log of moves made during the chess game. 75 | - **Dynamic Theme**: Allow users to switch between light and dark themes. 76 | 77 | --- 78 | 79 | ## How to Contribute 80 | 81 | ### Step 1: Fork and Clone the Repository 82 | ```bash 83 | # Clone the repository 84 | git clone https://github.com/your-repo/online-chess-game.git 85 | cd online-chess-game 86 | ``` 87 | 88 | ### Step 2: Set Up the Development Environment 89 | Follow the instructions in the `README.md` file to set up your local environment. 90 | 91 | ### Step 3: Address Specific Issues 92 | 93 | #### For **Drag-and-Drop Movement**: 94 | - Review the chessboard component handling piece movement. 95 | - Use libraries like `react-dnd` for implementing robust drag-and-drop functionality. 96 | 97 | #### For **Pawn Promotion**: 98 | - Add logic to detect pawn promotion conditions. 99 | - Use a modal to display promotion options and update the game state accordingly. 100 | 101 | #### For **Alerts Instead of Popups**: 102 | - Replace existing `alert()` calls with a custom modal component using libraries like `react-modal` or `Material-UI`. 103 | - Ensure the modal design aligns with the app’s UI and offers dismissible options. 104 | 105 | ### Step 4: Test Your Changes 106 | 1. Run the application locally: 107 | ```bash 108 | npm start 109 | ``` 110 | 2. Test various scenarios, such as moving pieces, pawn promotion, and responsive navigation. 111 | 3. Ensure no regressions are introduced. 112 | 113 | ### 4. Local Installation 114 | ![Local Installation Preview](./MockDown%20images/local_install.png) 115 | 116 | ### 5. Local Run 117 | ![Local Run Preview](./MockDown%20images/local_run.png) 118 | 119 | ### Step 5: Submit a Pull Request 120 | 1. Push your changes to your forked repository. 121 | 2. Open a pull request with a clear description of your changes and reference the issue numbers you are addressing. 122 | 123 | --- 124 | 125 | ## Contact 126 | If you have any questions or need guidance, feel free to open an issue or reach out to the project maintainer. 127 | 128 | Happy Coding! -------------------------------------------------------------------------------- /src/pages/FreeMode.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { Chessboard } from '../components/Chessboard'; 3 | import { GameStatus } from '../components/GameStatus'; 4 | import { Chess } from 'chess.js'; 5 | import { useGameStore } from '../store/useGameStore'; 6 | import { Trophy } from 'lucide-react'; 7 | 8 | // Toast component for error feedback (example implementation) 9 | const Toast = ({ message }: { message: string }) => ( 10 |
11 | {message} 12 |
13 | ); 14 | 15 | export const FreeMode: React.FC = () => { 16 | const [game] = useState(() => new Chess()); // Optimized initialization 17 | const [position, setPosition] = useState(game.fen()); 18 | const [error, setError] = useState(null); // State for error feedback 19 | const [gameOver, setGameOver] = useState(false); 20 | const [winner, setWinner] = useState<'white' | 'black' | 'draw' | null>(null); 21 | const [showWinnerPopup, setShowWinnerPopup] = useState(false); 22 | const [timeLeft, setTimeLeft] = useState(20); 23 | const setCheckedKing = useGameStore((state) => state.setCheckedKing); 24 | let checkedKing = useGameStore((state) => state.checkedKing); // Retrieve checkedKing from store 25 | 26 | const handleMove = (move: { from: string; to: string; promotion?: string }) => { 27 | try { 28 | const moveResult = game.move(move); 29 | if (!moveResult) throw new Error('Invalid move'); 30 | setPosition(game.fen()); 31 | setError(null); // Clear error on successful move 32 | 33 | // Determine if the king is in check 34 | checkedKing = game.inCheck() 35 | ? game.turn() === 'w' ? 'white' : 'black' 36 | : null; 37 | setCheckedKing(checkedKing); 38 | 39 | // Check for game over conditions 40 | if (game.isGameOver()) { 41 | determineGameOutcome(); 42 | } 43 | } catch (error) { 44 | console.error('Invalid move:', error); 45 | setError('Invalid move! Please try again.'); // User feedback 46 | } 47 | }; 48 | 49 | const determineGameOutcome = () => { 50 | let gameWinner: 'white' | 'black' | 'draw' | null = null; 51 | 52 | if (game.isCheckmate()) { 53 | // If it's checkmate, the winner is the opposite of the current player 54 | gameWinner = game.turn() === 'w' ? 'black' : 'white'; 55 | } else if (game.isDraw()) { 56 | // If it's a draw, set the winner to 'draw' 57 | gameWinner = 'draw'; 58 | } 59 | 60 | // Update the state with the game outcome 61 | setGameOver(true); 62 | setWinner(gameWinner); 63 | setShowWinnerPopup(true); 64 | setTimeLeft(20); 65 | }; 66 | 67 | useEffect(() => { 68 | let timer: NodeJS.Timeout; 69 | 70 | if (showWinnerPopup && timeLeft > 0) { 71 | timer = setInterval(() => { 72 | setTimeLeft(prev => prev - 1); 73 | }, 1000); 74 | } else if (timeLeft === 0) { 75 | setShowWinnerPopup(false); 76 | restartGame(); 77 | } 78 | 79 | return () => { 80 | if (timer) { 81 | clearInterval(timer); 82 | } 83 | }; 84 | }, [showWinnerPopup, timeLeft]); 85 | 86 | const restartGame = () => { 87 | const newGame = new Chess(); 88 | setGame(newGame); 89 | setPosition(newGame.fen()); 90 | setGameOver(false); 91 | setWinner(null); 92 | setCheckedKing(null); 93 | setError(null); 94 | }; 95 | 96 | const winnerAnnouncement = showWinnerPopup && ( 97 |
98 |
99 | 100 |

101 | {winner === 'draw' 102 | ? 'Game is a Draw!' 103 | : `${winner === 'white' ? 'White' : 'Black'} Wins!`} 104 |

105 |

Restarting in {timeLeft} seconds

106 | {/* */} 112 |
113 |
114 | ); 115 | 116 | return ( 117 |
118 | {/* Background Chessboard Pattern */} 119 | 157 | ); 158 | }; -------------------------------------------------------------------------------- /src/components/Navbar.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Sword } from 'lucide-react'; 3 | import { useNavigate } from 'react-router-dom'; 4 | import { WalletConnect } from './WalletConnect'; 5 | 6 | export const Navbar: React.FC = () => { 7 | const [isOpen, setIsOpen] = useState(false); 8 | const navigate = useNavigate(); 9 | const toggleNavbar = () => { 10 | setIsOpen(!isOpen); 11 | }; 12 | 13 | const handleNavigation = (path: string) => { 14 | navigate(path); // Navigate to the specified path 15 | }; 16 | 17 | return ( 18 | 142 | ); 143 | }; 144 | -------------------------------------------------------------------------------- /src/components/Chessboard.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useRef } from 'react'; 2 | import { Chessboard as ReactChessboard } from 'react-chessboard'; 3 | import { Chess } from 'chess.js'; 4 | 5 | interface ChessboardProps { 6 | position?: string; 7 | onMove?: (move: { from: string; to: string; promotion?: string }) => void; 8 | orientation?: 'white' | 'black'; 9 | disabled?: boolean; 10 | gameState: { checkedKing: 'white' | 'black' | null }; 11 | } 12 | 13 | export function Chessboard({ 14 | position = 'start', 15 | onMove, 16 | orientation = 'white', 17 | disabled = false, 18 | gameState, 19 | }: ChessboardProps) { 20 | const [chess] = useState(() => new Chess(position)); 21 | const [selectedSquare, setSelectedSquare] = useState(null); 22 | const [promotionMove, setPromotionMove] = useState<{ from: string; to: string } | null>(null); 23 | const [isPromotionInProgress, setIsPromotionInProgress] = useState(false); // New flag 24 | 25 | const currentPositionRef = useRef(position); 26 | if (position !== currentPositionRef.current) { 27 | chess.load(position); 28 | currentPositionRef.current = position; 29 | } 30 | 31 | const getLegalMovesForSquare = (square: string) => { 32 | const moves = chess.moves({ square, verbose: true }); 33 | return moves.map(move => move.to); 34 | }; 35 | 36 | const onSquareClick = (square: string) => { 37 | if (disabled || isPromotionInProgress) return; // Check flag 38 | 39 | const piece = chess.get(square); 40 | 41 | if (piece && piece.color === chess.turn()) { 42 | setSelectedSquare(square); 43 | return; 44 | } 45 | 46 | if (selectedSquare) { 47 | const move = { from: selectedSquare, to: square }; 48 | 49 | const promotionPiece = chess.get(selectedSquare); 50 | if (promotionPiece?.type === 'p' && (square[1] === '1' || square[1] === '8')) { 51 | setPromotionMove(move); 52 | setIsPromotionInProgress(true); // Set flag 53 | return; 54 | } 55 | 56 | try { 57 | const moveAttempt = chess.move({ ...move, promotion: 'q' }); 58 | 59 | if (moveAttempt !== null && onMove) { 60 | onMove(move); 61 | } 62 | } catch { 63 | // Invalid move 64 | } 65 | setSelectedSquare(null); 66 | } 67 | }; 68 | 69 | const onDrop = (sourceSquare: string, targetSquare: string) => { 70 | if (disabled || isPromotionInProgress) return false; // Check flag 71 | 72 | const move = { from: sourceSquare, to: targetSquare }; 73 | 74 | const promotionPiece = chess.get(sourceSquare); 75 | if (promotionPiece?.type === 'p' && (targetSquare[1] === '1' || targetSquare[1] === '8')) { 76 | setPromotionMove(move); 77 | setIsPromotionInProgress(true); // Set flag 78 | return false; 79 | } 80 | 81 | try { 82 | const moveAttempt = chess.move({ ...move, promotion: 'q' }); 83 | 84 | if (moveAttempt === null) return false; 85 | 86 | if (onMove) { 87 | onMove(move); 88 | } 89 | 90 | return true; 91 | } catch { 92 | return false; 93 | } 94 | }; 95 | 96 | const handlePromotion = (promotion: 'q' | 'r' | 'b' | 'n') => { 97 | if (!promotionMove) return; 98 | 99 | try { 100 | const moveAttempt = chess.move({ 101 | ...promotionMove, 102 | promotion, 103 | }); 104 | 105 | if (moveAttempt !== null && onMove) { 106 | onMove({ ...promotionMove, promotion }); 107 | } 108 | } catch { 109 | // Invalid move 110 | } 111 | 112 | setPromotionMove(null); 113 | setSelectedSquare(null); 114 | setIsPromotionInProgress(false); // Reset flag 115 | }; 116 | 117 | const getCustomSquareStyles = () => { 118 | const styles: Record = {}; 119 | 120 | if (selectedSquare) { 121 | styles[selectedSquare] = { backgroundColor: 'rgba(255, 255, 0, 0.4)' }; 122 | const legalMoves = getLegalMovesForSquare(selectedSquare); 123 | legalMoves.forEach(square => { 124 | styles[square] = { 125 | backgroundColor: 'rgba(0, 255, 0, 0.2)', 126 | borderRadius: '50%', 127 | }; 128 | }); 129 | } 130 | 131 | if (gameState.checkedKing) { 132 | const kingSquare = chess.board().flat().find( 133 | piece => 134 | piece && 135 | piece.type === 'k' && 136 | ((gameState.checkedKing === 'white' && piece.color === 'w') || 137 | (gameState.checkedKing === 'black' && piece.color === 'b')) 138 | )?.square; 139 | 140 | if (kingSquare) { 141 | styles[kingSquare] = { 142 | backgroundColor: 'rgba(255, 0, 0, 0.4)', 143 | border: '2px solid red', 144 | }; 145 | } 146 | } 147 | 148 | return styles; 149 | }; 150 | 151 | return ( 152 |
153 | 164 | {promotionMove && ( 165 |
166 |
167 |

Promote Pawn

168 |
169 | 175 | 181 | 187 | 193 |
194 |
195 |
196 | )} 197 |
198 | ); 199 | } 200 | -------------------------------------------------------------------------------- /src/pages/Home.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ChevronRight } from 'lucide-react'; 3 | import { useNavigate } from 'react-router-dom'; 4 | 5 | export const Home: React.FC = () => { 6 | const navigate = useNavigate(); // React Router's navigate function 7 | 8 | const handleNavigation = (path: string) => { 9 | navigate(path); // Navigate to the specified path 10 | }; 11 | 12 | return ( 13 |
14 | {/* Animated chess board pattern */} 15 |
16 |
17 | {[...Array(64)].map((_, i) => ( 18 |
24 | ))} 25 |
26 |
27 | 28 |
29 |
30 |
31 | 32 | 33 | 34 | 35 | 36 |
37 |

38 | Crypto Chess Arena 39 |

40 |

41 | Where Grandmasters Meet the Blockchain 42 |

43 |
44 | 45 |
46 | 60 | 61 | 75 | 76 | 90 |
91 | 92 |
93 |

94 | Your Path to Mastery 95 |

96 |
97 |
98 |
99 |
100 | ♟ 101 |
102 |

Connect Wallet

103 |
104 |

105 | Link your MetaMask to enter tournaments and earn rewards. 106 |

107 |
108 |
109 |
110 |
111 | ♞ 112 |
113 |

Select Format

114 |
115 |

116 | Choose from Blitz, Rapid, or Classical time controls. 117 |

118 |
119 |
120 |
121 |
122 | ♔ 123 |
124 |

Compete & Earn

125 |
126 |

127 | Win matches to climb the leaderboard and earn ETH rewards. 128 |

129 |
130 |
131 |
132 |
133 |
134 | ); 135 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

🎮 Welcome to Web3 Based Chess Game 🎮

2 |

A decentralized platform where blockchain meets chess!🕹️

3 | 4 |

5 | Typing SVG 6 |

7 | 8 | ![Ether-Chess-OTC](https://socialify.git.ci/Navneet1206/Ether-Chess-OTC/image?description=1&forks=1&issues=1&language=1&name=1&owner=1&pulls=1&stargazers=1&theme=Dark) 9 | --- 10 | 11 |

🔧 Tech Stack 🔧

12 |

13 | React 14 | Solidity 15 | Ethereum 16 | Node.js 17 | Tailwind CSS 18 |

19 | 20 |

21 | ♟️ Live Preview ♟️ 22 |

23 | 24 | --- 25 | 26 |

🚀 Features 🚀

27 | 28 | - **🏠 Home Screen**: Sleek interface for easy navigation between game modes. 29 | - **🤖 Bot Mode**: Challenge a computer bot with various difficulty levels. 30 | - **🌐 Online Mode**: Connect with players worldwide and stake ETH in games. 31 | - **🔔 Game Alerts**: Real-time notifications for in-game actions. 32 | - **🔐 Wallet Integration**: Connect and manage your Ethereum wallet effortlessly. 33 | - **✅ Secure Transactions**: Ensure transparency and security with smart contracts. 34 | - **👤 User Profiles**: Track your performance with personalized profiles. 35 | 36 | --- 37 | 38 |

👤 Contributors 👤

39 | 40 |

🌟 Core Functional Contributors 🌟

41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 55 | 62 | 69 | 70 |
♖The Rook♖ ♔The King♔ ♖The Rook♖
49 | 50 | Chetan6969
51 | Chetan6969 52 |

53 | 💻 Project Collaborator & Full-Stack Developer 54 |
56 | 57 | Navneet1206
58 | Navneet1206 59 |

60 | 🚀 Project Creator, Lead Blockchain & Full-Stack Developer 61 |
63 | 64 | Yashvi Sharma
65 | Yashvi Sharma 66 |

67 | 🎨 UI Design & Website Contributions 68 |
71 | 72 |

🛠️ Moderate Contributors 🛠️

73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 88 | 95 | 102 | 109 | 110 |
♗The Bishop♗ ♗The Bishop♗ ♗The Bishop♗ ♗The Bishop♗
82 | 83 | Yash Pandav
84 | Yash Pandav 85 |

86 | 🤖 Bot Mode Finishing Functionality 87 |
89 | 90 | Aman Singh
91 | Aman Singh 92 |

93 | 🧩 Free Mode Functionality Contributions 94 |
96 | 97 | GauravKaraKoti
98 | Gaurav KaraKoti 99 |

100 | Documentation and functional Contributions 101 |
103 | 104 | Roshansuthar
105 | Roshan Suthar 106 |

107 | functional Contributions 108 |
111 | 112 |

🛠️ Documentation Contributors 🛠️

113 | 114 | 115 | 116 | 117 | 118 | 125 | 126 |
♘The Knight♘
119 | 120 | GauravKaraKoti
121 | Gaurav KaraKoti 122 |

123 | Documentation Contributions 124 |
127 | 128 | --- 129 | 130 |

💡 How It Works 💡

131 | 132 | #### 🌐 Online Mode: 133 | 1. Connect your Ethereum wallet. 134 | 2. Set a stake amount (in ETH). 135 | 3. Create or join a game. 136 | 4. Play chess and win ETH! 137 | 138 | #### 🤖 Bot Mode: 139 | 1. Choose your difficulty level. 140 | 2. Play against the AI bot. 141 | 3. Improve your chess skills. 142 | 143 | --- 144 | 145 |

🎓 Installation & Setup 🎓

146 | 147 | 1. Clone the repository: 148 | ```bash 149 | git clone https://github.com/Navneet1206/Ether-Chess-OTC 150 | ``` 151 | 2. Install dependencies in main folder: 152 | ```bash 153 | npm install 154 | ``` 155 | 156 | 3. Start the Application : 157 | ```bash 158 | npm run dev 159 | ``` 160 | 161 | 4. Install dependencies in server folder : 162 | ```bash 163 | npm install 164 | ``` 165 | 5. Start the server : 166 | ```bash 167 | npm run dev 168 | ``` 169 | 170 | 6. Deploy Smart Contracts: 171 | ```bash 172 | truffle migrate --network sepolia 173 | ``` 174 | 7. Configure the environment variables in the `.env` file. 175 | 176 | --- 177 | 178 |

🔧 Testing 🔧

179 | 180 | 1. Run the application locally: 181 | ```bash 182 | npm run dev 183 | ``` 184 | 185 | 2. Test features: 186 | - Wallet connection 187 | - Game creation and notifications 188 | - Chess gameplay 189 | 190 | 3. Run linting and tests: 191 | ```bash 192 | npm run lint 193 | npm test 194 | ``` 195 | 196 | --- 197 | 198 |

🖼 Preview 🖼

199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 210 | 214 | 215 |
🖥️Home Screen🖥️🤖Bot Mode🤖
207 | Web3 Chess Home Screen 208 |

Play Chess, Earn Crypto: Explore various modes

209 |
211 | Web3 Chess Bot Mode 212 |

Challenge our AI bot and improve your skills

213 |
216 | 217 | 218 | 219 | 220 | 221 | 222 | 226 | 231 | 232 | 233 | 234 |
🎯Game Created Alert🎯🛠️Local Installation and Run🛠️
223 | Web3 Chess Game Created 224 |

Get alerted whenever the game is created

225 |
227 | Web3 Chess Local Installation 228 | Web3 Chess Local Run 229 |

This is how you can install and run the game

230 |
235 | 236 | --- 237 |

⚠️ Important Note: ⚠️

238 | 239 | **Off Anti-Tracking** 240 | For a seamless user experience, ensure that anti-tracking features are disabled in the browser settings, as this might cause issues with game state tracking and wallet interactions. You can disable these features in your browser preferences to avoid potential problems. 241 | 242 | --- 243 | 244 |

📂 Issues and Contributions 📂

245 |

Check the 📜 CONTRIBUTING.md 📜 file for detailed information on known issues and how you can contribute.

246 | 247 | --- 248 | 249 |

📧 Contact 📧

250 |

For queries or support, feel free to open an issue on GitHub or contact the project maintainer.

251 | 252 | --- 253 | 254 |

255 | Typing SVG 256 |

257 | -------------------------------------------------------------------------------- /src/pages/OnlineMode.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { useWalletStore } from '../store/useWalletStore'; 3 | import { socketService } from '../services/socketService'; 4 | import { Chessboard } from '../components/Chessboard'; 5 | import { ethers } from 'ethers'; 6 | import { useGameStore } from '../store/useGameStore'; 7 | import { AlertCircle, Check, Loader2, ArrowUp, ArrowDown } from 'lucide-react'; 8 | import { Chess } from 'chess.js'; 9 | import { Button } from '../components/Button'; // Import extracted components 10 | import { Input } from '../components/Input'; // Import extracted components 11 | import { Dialog } from '../components/Dialog'; // Import extracted components 12 | 13 | const MIN_STAKE = 0.0001; 14 | const MAX_STAKE = 0.1; 15 | const STAKE_INCREMENT = 0.0001; 16 | 17 | const chessGameABI = [ 18 | "function createGame(string calldata gameId) external payable", 19 | "function joinGame(string calldata gameId) external payable", 20 | "function games(string calldata) external view returns (address white, address black, uint256 stake, bool isActive, address winner, uint256 startTime)" 21 | ]; 22 | 23 | export const OnlineMode = () => { 24 | const { address, signer, provider } = useWalletStore(); 25 | const { gameState, setGameState } = useGameStore(); 26 | const [gameId, setGameId] = useState(null); 27 | const [stake, setStake] = useState(MIN_STAKE); 28 | const [error, setError] = useState(null); 29 | const [contractAddress] = useState('0xA12E9052EDbffCA633eBe3Fc9B3F477E516d4D43'); 30 | const [isJoinGameDialogOpen, setIsJoinGameDialogOpen] = useState(false); 31 | const [joinGameId, setJoinGameId] = useState(''); 32 | const [showSuccessToast, setShowSuccessToast] = useState(false); 33 | const [successMessage, setSuccessMessage] = useState(''); 34 | const [isCreatingGame, setIsCreatingGame] = useState(false); 35 | const [isJoiningGame, setIsJoiningGame] = useState(false); 36 | const [isVerifyingGame, setIsVerifyingGame] = useState(false); 37 | const [game] = useState(new Chess()); 38 | 39 | useEffect(() => { 40 | if (gameState?.gameId) { 41 | setGameId(gameState.gameId); 42 | } 43 | }, [gameState]); 44 | 45 | useEffect(() => { 46 | socketService.onGameState((state) => { 47 | setGameState(state); 48 | game.load(state.position); 49 | }); 50 | return () => { 51 | socketService.disconnect(); 52 | }; 53 | }, [setGameState, game]); 54 | 55 | const handleStakeChange = (increment) => { 56 | setStake(prevStake => { 57 | const newStake = parseFloat((prevStake + increment).toFixed(4)); 58 | return newStake >= MIN_STAKE && newStake <= MAX_STAKE ? newStake : prevStake; 59 | }); 60 | }; 61 | 62 | const handleStakeInput = (event) => { 63 | const value = event.target.value; 64 | if (value === '') { 65 | setStake(MIN_STAKE); 66 | return; 67 | } 68 | 69 | const numValue = parseFloat(value); 70 | if (!isNaN(numValue)) { 71 | const roundedValue = parseFloat(numValue.toFixed(4)); 72 | if (roundedValue >= MIN_STAKE && roundedValue <= MAX_STAKE) { 73 | setStake(roundedValue); 74 | } else if (roundedValue < MIN_STAKE) { 75 | setStake(MIN_STAKE); 76 | } else if (roundedValue > MAX_STAKE) { 77 | setStake(MAX_STAKE); 78 | } 79 | } 80 | }; 81 | 82 | const showToast = (message) => { 83 | setSuccessMessage(message); 84 | setShowSuccessToast(true); 85 | setTimeout(() => setShowSuccessToast(false), 5000); 86 | }; 87 | 88 | const verifyGameExists = async (gameId) => { 89 | if (!provider) return false; 90 | setIsVerifyingGame(true); 91 | try { 92 | const contract = new ethers.Contract(contractAddress, chessGameABI, provider); 93 | const gameDetails = await contract.games(gameId); 94 | return gameDetails.white !== ethers.ZeroAddress; 95 | } catch (error) { 96 | console.error('Error verifying game:', error); 97 | return false; 98 | } finally { 99 | setIsVerifyingGame(false); 100 | } 101 | }; 102 | 103 | const handleCreateGame = async () => { 104 | if (!address || !signer || !provider) { 105 | setError('Please connect your wallet first'); 106 | return; 107 | } 108 | 109 | if (stake < MIN_STAKE || stake > MAX_STAKE) { 110 | setError(`Stake must be between ${MIN_STAKE} and ${MAX_STAKE} ETH`); 111 | return; 112 | } 113 | 114 | setIsCreatingGame(true); 115 | setError(null); 116 | 117 | try { 118 | const stakeInWei = ethers.parseEther(stake.toString()); 119 | const contract = new ethers.Contract(contractAddress, chessGameABI, signer); 120 | const generatedGameId = Math.random().toString(36).substring(7); 121 | 122 | const tx = await contract.createGame(generatedGameId, { value: stakeInWei }); 123 | showToast('Transaction submitted. Waiting for confirmation...'); 124 | await tx.wait(); 125 | 126 | const gameExists = await verifyGameExists(generatedGameId); 127 | if (!gameExists) { 128 | throw new Error('Game creation failed on blockchain'); 129 | } 130 | 131 | await socketService.connect(address, 'Player'); 132 | await socketService.createGame(stake); 133 | 134 | setGameId(generatedGameId); 135 | showToast(`Game created successfully! Game ID: ${generatedGameId}`); 136 | } catch (error) { 137 | console.error('Error creating game:', error); 138 | setError(error.reason || error.message || 'Failed to create game'); 139 | } finally { 140 | setIsCreatingGame(false); 141 | } 142 | }; 143 | 144 | const handleJoinGame = async () => { 145 | if (!address || !signer || !provider) { 146 | setError('Please connect your wallet first'); 147 | return; 148 | } 149 | 150 | if (!joinGameId.trim()) { 151 | setError('Please enter a valid Game ID'); 152 | return; 153 | } 154 | 155 | setIsJoiningGame(true); 156 | setError(null); 157 | 158 | try { 159 | const contract = new ethers.Contract(contractAddress, chessGameABI, provider); 160 | const gameDetails = await contract.games(joinGameId); 161 | 162 | if (gameDetails.white === ethers.ZeroAddress) { 163 | throw new Error('Game does not exist'); 164 | } 165 | 166 | if (gameDetails.black !== ethers.ZeroAddress) { 167 | throw new Error('Game is already full'); 168 | } 169 | 170 | const contractWithSigner = new ethers.Contract(contractAddress, chessGameABI, signer); 171 | const tx = await contractWithSigner.joinGame(joinGameId, { value: gameDetails.stake }); 172 | showToast('Transaction submitted. Waiting for confirmation...'); 173 | await tx.wait(); 174 | 175 | await socketService.connect(address, 'Player'); 176 | await socketService.joinGame(joinGameId); 177 | 178 | setGameId(joinGameId); 179 | setIsJoinGameDialogOpen(false); 180 | showToast('Successfully joined the game!'); 181 | } catch (error) { 182 | console.error('Error joining game:', error); 183 | setError(error.reason || error.message || 'Failed to join game'); 184 | } finally { 185 | setIsJoiningGame(false); 186 | } 187 | }; 188 | 189 | const handleMove = (move) => { 190 | if (gameId) { 191 | socketService.makeMove(gameId, move); 192 | } 193 | }; 194 | 195 | return ( 196 |
197 |
198 |

Online Chess Game

199 | 200 | {error && ( 201 |
202 | 203 | {error} 204 |
205 | )} 206 | 207 | {showSuccessToast && ( 208 |
209 | 210 | {successMessage} 211 |
212 | )} 213 | 214 | {!gameId ? ( 215 |
216 |
217 | 218 |
219 | 222 |
223 | 224 | ETH 225 |
226 | 229 |
230 |

Min: {MIN_STAKE} ETH - Max: {MAX_STAKE} ETH

231 |
232 | 233 |
234 | 237 | 240 |
241 |
242 | ) : ( 243 |
244 |
245 |

246 | Game ID: {gameId} 247 |

248 |
249 |
250 | 251 |
252 |
253 | )} 254 | 255 | setIsJoinGameDialogOpen(false)} title="Join Game" description="Enter the Game ID to join an existing game"> 256 |
257 | setJoinGameId(e.target.value)} /> 258 |
259 | 260 | 263 |
264 |
265 |
266 |
267 |
268 | ); 269 | }; 270 | 271 | export default OnlineMode; -------------------------------------------------------------------------------- /src/pages/BotMode.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useCallback } from 'react'; 2 | import { Chessboard as ReactChessboard } from 'react-chessboard'; 3 | import { Chess } from 'chess.js'; 4 | import { Bot, Trophy } from 'lucide-react'; 5 | 6 | type Difficulty = 'EASY' | 'MEDIUM' | 'HARD'; 7 | 8 | interface PieceValues { 9 | p: number; 10 | n: number; 11 | b: number; 12 | r: number; 13 | q: number; 14 | k: number; 15 | } 16 | 17 | const PIECE_VALUES: PieceValues = { 18 | p: 1, 19 | n: 3, 20 | b: 3, 21 | r: 5, 22 | q: 9, 23 | k: 0 24 | }; 25 | 26 | export const BotMode: React.FC = () => { 27 | const [game, setGame] = useState(new Chess()); 28 | const [position, setPosition] = useState(game.fen()); 29 | const [difficulty, setDifficulty] = useState('MEDIUM'); 30 | const [gameOver, setGameOver] = useState(false); 31 | const [winner, setWinner] = useState<'white' | 'black' | 'draw' | null>(null); 32 | const [thinking, setThinking] = useState(false); 33 | const [selectedSquare, setSelectedSquare] = useState(null); 34 | const [promotionSquare, setPromotionSquare] = useState(null); 35 | const [checkedKing, setCheckedKing] = useState<'white' | 'black' | null>(null); 36 | const [showWinnerPopup, setShowWinnerPopup] = useState(false); 37 | const [timeLeft, setTimeLeft] = useState(20); 38 | 39 | // Evaluate board position for bot 40 | const evaluatePosition = (chess: Chess): number => { 41 | let score = 0; 42 | 43 | chess.board().forEach(row => { 44 | row.forEach(piece => { 45 | if (piece) { 46 | const value = PIECE_VALUES[piece.type as keyof PieceValues]; 47 | score += piece.color === 'w' ? value : -value; 48 | } 49 | }); 50 | }); 51 | 52 | const moves = chess.moves({ verbose: true }); 53 | score += (moves.length * 0.1) * (chess.turn() === 'w' ? 1 : -1); 54 | 55 | const centerSquares = ['d4', 'd5', 'e4', 'e5']; 56 | centerSquares.forEach(square => { 57 | const piece = chess.get(square); 58 | if (piece) { 59 | score += piece.color === 'w' ? 0.5 : -0.5; 60 | } 61 | }); 62 | 63 | return score; 64 | }; 65 | 66 | const minimax = ( 67 | chess: Chess, 68 | depth: number, 69 | alpha: number, 70 | beta: number, 71 | isMaximizing: boolean 72 | ): { score: number; move?: string } => { 73 | if (depth === 0 || chess.isGameOver()) { 74 | return { score: evaluatePosition(chess) }; 75 | } 76 | 77 | const moves = chess.moves({ verbose: true }); 78 | let bestMove: string | undefined; 79 | 80 | if (isMaximizing) { 81 | let maxScore = -Infinity; 82 | for (const move of moves) { 83 | chess.move(move); 84 | const evaluation = minimax(chess, depth - 1, alpha, beta, false).score; 85 | chess.undo(); 86 | 87 | if (evaluation > maxScore) { 88 | maxScore = evaluation; 89 | bestMove = move.san; 90 | } 91 | alpha = Math.max(alpha, maxScore); 92 | if (beta <= alpha) break; 93 | } 94 | return { score: maxScore, move: bestMove }; 95 | } else { 96 | let minScore = Infinity; 97 | for (const move of moves) { 98 | chess.move(move); 99 | const evaluation = minimax(chess, depth - 1, alpha, beta, true).score; 100 | chess.undo(); 101 | 102 | if (evaluation < minScore) { 103 | minScore = evaluation; 104 | bestMove = move.san; 105 | } 106 | beta = Math.min(beta, minScore); 107 | if (beta <= alpha) break; 108 | } 109 | return { score: minScore, move: bestMove }; 110 | } 111 | }; 112 | 113 | const makeBotMove = useCallback(() => { 114 | if (game.isGameOver()) { 115 | determineGameOutcome(); 116 | return; 117 | } 118 | 119 | setThinking(true); 120 | const gameCopy = new Chess(game.fen()); 121 | 122 | // Check for immediate winning moves (checkmate) 123 | const moves = gameCopy.moves({ verbose: true }); 124 | for (const move of moves) { 125 | gameCopy.move(move); 126 | if (gameCopy.isCheckmate()) { 127 | setGame(gameCopy); 128 | setPosition(gameCopy.fen()); 129 | updateCheckedKing(gameCopy); 130 | setThinking(false); 131 | determineGameOutcome(); 132 | return; 133 | } 134 | gameCopy.undo(); 135 | } 136 | 137 | let moveToMake; 138 | 139 | switch (difficulty) { 140 | case 'EASY': 141 | // Random move, but avoid losing moves 142 | const safeMoves = moves.filter(move => { 143 | gameCopy.move(move); 144 | const isSafe = !gameCopy.isCheckmate() && !gameCopy.isDraw(); 145 | gameCopy.undo(); 146 | return isSafe; 147 | }); 148 | moveToMake = safeMoves[Math.floor(Math.random() * safeMoves.length)]; 149 | break; 150 | 151 | case 'MEDIUM': 152 | const { move } = minimax(gameCopy, 2, -Infinity, Infinity, false); 153 | moveToMake = move ? gameCopy.moves({ verbose: true }).find(m => m.san === move) : null; 154 | break; 155 | 156 | case 'HARD': 157 | const result = minimax(gameCopy, 3, -Infinity, Infinity, false); 158 | moveToMake = result.move ? gameCopy.moves({ verbose: true }).find(m => m.san === result.move) : null; 159 | break; 160 | } 161 | 162 | if (moveToMake) { 163 | gameCopy.move(moveToMake); 164 | setGame(gameCopy); 165 | setPosition(gameCopy.fen()); 166 | updateCheckedKing(gameCopy); 167 | } 168 | 169 | setThinking(false); 170 | }, [game, difficulty]); 171 | 172 | const updateCheckedKing = (currentGame: Chess) => { 173 | if (currentGame.inCheck()) { 174 | setCheckedKing(currentGame.turn() === 'w' ? 'white' : 'black'); 175 | } else { 176 | setCheckedKing(null); 177 | } 178 | }; 179 | 180 | const determineGameOutcome = () => { 181 | let gameWinner: 'white' | 'black' | 'draw' | null = null; 182 | 183 | if (game.isCheckmate()) { 184 | gameWinner = game.turn() === 'w' ? 'black' : 'white'; 185 | } else if (game.isDraw()) { 186 | gameWinner = 'draw'; 187 | } 188 | 189 | setGameOver(true); 190 | setWinner(gameWinner); 191 | setShowWinnerPopup(true); 192 | setTimeLeft(20); 193 | }; 194 | 195 | useEffect(() => { 196 | let timer: NodeJS.Timeout; 197 | 198 | if (showWinnerPopup && timeLeft > 0) { 199 | timer = setInterval(() => { 200 | setTimeLeft(prev => prev - 1); 201 | }, 1000); 202 | } else if (timeLeft === 0) { 203 | setShowWinnerPopup(false); 204 | restartGame(); 205 | } 206 | 207 | return () => { 208 | if (timer) { 209 | clearInterval(timer); 210 | } 211 | }; 212 | }, [showWinnerPopup, timeLeft]); 213 | 214 | const restartGame = () => { 215 | const newGame = new Chess(); 216 | setGame(newGame); 217 | setPosition(newGame.fen()); 218 | setGameOver(false); 219 | setWinner(null); 220 | setCheckedKing(null); 221 | setSelectedSquare(null); 222 | setPromotionSquare(null); 223 | setThinking(false); 224 | }; 225 | 226 | const getLegalMovesForSquare = (square: string) => { 227 | return game.moves({ square, verbose: true }).map(move => move.to); 228 | }; 229 | 230 | const handleSquareClick = (square: string) => { 231 | if (thinking || gameOver || game.turn() === 'b') return; 232 | 233 | const piece = game.get(square); 234 | 235 | if (promotionSquare) { 236 | const promotionMove = { 237 | from: selectedSquare!, 238 | to: promotionSquare, 239 | promotion: square[0] as 'q' | 'r' | 'b' | 'n' 240 | }; 241 | 242 | try { 243 | game.move(promotionMove); 244 | setPosition(game.fen()); 245 | setSelectedSquare(null); 246 | setPromotionSquare(null); 247 | updateCheckedKing(game); 248 | setTimeout(makeBotMove, 500); 249 | } catch (error) { 250 | console.error('Invalid promotion move:', error); 251 | } 252 | return; 253 | } 254 | 255 | if (piece && piece.color === game.turn()) { 256 | setSelectedSquare(square); 257 | return; 258 | } 259 | 260 | if (selectedSquare) { 261 | const moveAttempt = { 262 | from: selectedSquare, 263 | to: square, 264 | }; 265 | 266 | const piece = game.get(selectedSquare); 267 | if ( 268 | piece && 269 | piece.type === 'p' && 270 | ((piece.color === 'w' && square[1] === '8') || 271 | (piece.color === 'b' && square[1] === '1')) 272 | ) { 273 | setPromotionSquare(square); 274 | return; 275 | } 276 | 277 | try { 278 | game.move(moveAttempt); 279 | setPosition(game.fen()); 280 | setSelectedSquare(null); 281 | updateCheckedKing(game); 282 | setTimeout(makeBotMove, 500); 283 | } catch (error) { 284 | console.error('Invalid move:', error); 285 | } 286 | } 287 | }; 288 | 289 | const customSquareStyles = () => { 290 | const styles: Record = {}; 291 | 292 | if (selectedSquare) { 293 | styles[selectedSquare] = { 294 | backgroundColor: 'rgba(255, 255, 0, 0.4)', 295 | }; 296 | 297 | const legalMoves = getLegalMovesForSquare(selectedSquare); 298 | legalMoves.forEach(square => { 299 | styles[square] = { 300 | backgroundColor: 'rgba(0, 255, 0, 0.2)', 301 | borderRadius: '50%', 302 | }; 303 | }); 304 | } 305 | 306 | if (checkedKing) { 307 | const kingSquare = game.board().flat().find( 308 | piece => piece && piece.type === 'k' && 309 | ((checkedKing === 'white' && piece.color === 'w') || 310 | (checkedKing === 'black' && piece.color === 'b')) 311 | )?.square; 312 | 313 | if (kingSquare) { 314 | styles[kingSquare] = { 315 | backgroundColor: 'rgba(255, 0, 0, 0.4)', 316 | border: '2px solid red', 317 | }; 318 | } 319 | } 320 | 321 | return styles; 322 | }; 323 | 324 | const promotionPieces = promotionSquare && ( 325 |
327 | {['q', 'r', 'b', 'n'].map((piece) => ( 328 | 335 | ))} 336 |
337 | ); 338 | 339 | const winnerAnnouncement = showWinnerPopup && ( 340 |
341 |
342 | 343 |

344 | {winner === 'draw' 345 | ? 'Game is a Draw!' 346 | : `${winner === 'white' ? 'White' : 'Black'} Wins!`} 347 |

348 |

Restarting in {timeLeft} seconds

349 | {/* */} 355 |
356 |
357 | ); 358 | 359 | return ( 360 |
361 |
362 |
363 |
364 |

365 | Bot Mode 366 |

367 | 368 |
369 | 375 | {promotionPieces} 376 | {winnerAnnouncement} 377 |
378 |
379 | 380 |
381 |
382 |

Game Status

383 |
384 |

Current Turn: {game.turn() === 'w' ? 'White' : 'Black'}

385 |

Status: {gameOver ? 'Game Over' : 'Active'}

386 |
387 |
388 | 389 |
390 |

Bot Settings

391 | 401 |
402 |
403 |
404 |
405 |
406 | ); 407 | }; -------------------------------------------------------------------------------- /src/config/ChessGame.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "ChessGame", 4 | "sourceName": "contracts/ChessGame.sol", 5 | "abi": [ 6 | { 7 | "inputs": [], 8 | "stateMutability": "nonpayable", 9 | "type": "constructor" 10 | }, 11 | { 12 | "anonymous": false, 13 | "inputs": [ 14 | { 15 | "indexed": false, 16 | "internalType": "string", 17 | "name": "gameId", 18 | "type": "string" 19 | }, 20 | { 21 | "indexed": false, 22 | "internalType": "address", 23 | "name": "white", 24 | "type": "address" 25 | }, 26 | { 27 | "indexed": false, 28 | "internalType": "uint256", 29 | "name": "stake", 30 | "type": "uint256" 31 | } 32 | ], 33 | "name": "GameCreated", 34 | "type": "event" 35 | }, 36 | { 37 | "anonymous": false, 38 | "inputs": [ 39 | { 40 | "indexed": false, 41 | "internalType": "string", 42 | "name": "gameId", 43 | "type": "string" 44 | }, 45 | { 46 | "indexed": false, 47 | "internalType": "address", 48 | "name": "winner", 49 | "type": "address" 50 | }, 51 | { 52 | "indexed": false, 53 | "internalType": "uint256", 54 | "name": "prize", 55 | "type": "uint256" 56 | } 57 | ], 58 | "name": "GameEnded", 59 | "type": "event" 60 | }, 61 | { 62 | "anonymous": false, 63 | "inputs": [ 64 | { 65 | "indexed": false, 66 | "internalType": "string", 67 | "name": "gameId", 68 | "type": "string" 69 | }, 70 | { 71 | "indexed": false, 72 | "internalType": "address", 73 | "name": "black", 74 | "type": "address" 75 | } 76 | ], 77 | "name": "GameJoined", 78 | "type": "event" 79 | }, 80 | { 81 | "anonymous": false, 82 | "inputs": [ 83 | { 84 | "indexed": true, 85 | "internalType": "address", 86 | "name": "previousOwner", 87 | "type": "address" 88 | }, 89 | { 90 | "indexed": true, 91 | "internalType": "address", 92 | "name": "newOwner", 93 | "type": "address" 94 | } 95 | ], 96 | "name": "OwnershipTransferred", 97 | "type": "event" 98 | }, 99 | { 100 | "inputs": [ 101 | { 102 | "internalType": "string", 103 | "name": "gameId", 104 | "type": "string" 105 | } 106 | ], 107 | "name": "createGame", 108 | "outputs": [], 109 | "stateMutability": "payable", 110 | "type": "function" 111 | }, 112 | { 113 | "inputs": [ 114 | { 115 | "internalType": "string", 116 | "name": "gameId", 117 | "type": "string" 118 | }, 119 | { 120 | "internalType": "address", 121 | "name": "winner", 122 | "type": "address" 123 | } 124 | ], 125 | "name": "endGame", 126 | "outputs": [], 127 | "stateMutability": "nonpayable", 128 | "type": "function" 129 | }, 130 | { 131 | "inputs": [ 132 | { 133 | "internalType": "string", 134 | "name": "", 135 | "type": "string" 136 | } 137 | ], 138 | "name": "games", 139 | "outputs": [ 140 | { 141 | "internalType": "address", 142 | "name": "white", 143 | "type": "address" 144 | }, 145 | { 146 | "internalType": "address", 147 | "name": "black", 148 | "type": "address" 149 | }, 150 | { 151 | "internalType": "uint256", 152 | "name": "stake", 153 | "type": "uint256" 154 | }, 155 | { 156 | "internalType": "bool", 157 | "name": "isActive", 158 | "type": "bool" 159 | }, 160 | { 161 | "internalType": "address", 162 | "name": "winner", 163 | "type": "address" 164 | }, 165 | { 166 | "internalType": "uint256", 167 | "name": "startTime", 168 | "type": "uint256" 169 | } 170 | ], 171 | "stateMutability": "view", 172 | "type": "function" 173 | }, 174 | { 175 | "inputs": [ 176 | { 177 | "internalType": "string", 178 | "name": "gameId", 179 | "type": "string" 180 | } 181 | ], 182 | "name": "joinGame", 183 | "outputs": [], 184 | "stateMutability": "payable", 185 | "type": "function" 186 | }, 187 | { 188 | "inputs": [], 189 | "name": "owner", 190 | "outputs": [ 191 | { 192 | "internalType": "address", 193 | "name": "", 194 | "type": "address" 195 | } 196 | ], 197 | "stateMutability": "view", 198 | "type": "function" 199 | }, 200 | { 201 | "inputs": [], 202 | "name": "ownerFeePercentage", 203 | "outputs": [ 204 | { 205 | "internalType": "uint256", 206 | "name": "", 207 | "type": "uint256" 208 | } 209 | ], 210 | "stateMutability": "view", 211 | "type": "function" 212 | }, 213 | { 214 | "inputs": [ 215 | { 216 | "internalType": "address", 217 | "name": "", 218 | "type": "address" 219 | } 220 | ], 221 | "name": "playerEarnings", 222 | "outputs": [ 223 | { 224 | "internalType": "uint256", 225 | "name": "", 226 | "type": "uint256" 227 | } 228 | ], 229 | "stateMutability": "view", 230 | "type": "function" 231 | }, 232 | { 233 | "inputs": [], 234 | "name": "renounceOwnership", 235 | "outputs": [], 236 | "stateMutability": "nonpayable", 237 | "type": "function" 238 | }, 239 | { 240 | "inputs": [ 241 | { 242 | "internalType": "address", 243 | "name": "newOwner", 244 | "type": "address" 245 | } 246 | ], 247 | "name": "transferOwnership", 248 | "outputs": [], 249 | "stateMutability": "nonpayable", 250 | "type": "function" 251 | }, 252 | { 253 | "inputs": [], 254 | "name": "withdrawEarnings", 255 | "outputs": [], 256 | "stateMutability": "nonpayable", 257 | "type": "function" 258 | }, 259 | { 260 | "inputs": [], 261 | "name": "withdrawOwnerFees", 262 | "outputs": [], 263 | "stateMutability": "nonpayable", 264 | "type": "function" 265 | } 266 | ], 267 | "bytecode": "0x6080604052600560045534801561001557600080fd5b5061003261002761003e60201b60201c565b61004660201b60201c565b6001808190555061010a565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b611bcd806101196000396000f3fe60806040526004361061009c5760003560e01c80636d20931a116100645780636d20931a14610158578063715018a61461019a5780637753af3e146101b15780638da5cb5b146101da578063b73c6ce914610205578063f2fde38b1461021c5761009c565b80630a9ef34c146100a15780631cb398c2146100b85780632ebc0504146100e35780633d536a2e146100ff57806369f927731461011b575b600080fd5b3480156100ad57600080fd5b506100b6610245565b005b3480156100c457600080fd5b506100cd61035a565b6040516100da9190611033565b60405180910390f35b6100fd60048036038101906100f891906110c7565b610360565b005b610119600480360381019061011491906110c7565b610636565b005b34801561012757600080fd5b50610142600480360381019061013d9190611172565b610849565b60405161014f9190611033565b60405180910390f35b34801561016457600080fd5b5061017f600480360381019061017a91906112e0565b610861565b60405161019196959493929190611353565b60405180910390f35b3480156101a657600080fd5b506101af610920565b005b3480156101bd57600080fd5b506101d860048036038101906101d391906113b4565b6109a8565b005b3480156101e657600080fd5b506101ef610cc4565b6040516101fc9190611414565b60405180910390f35b34801561021157600080fd5b5061021a610ced565b005b34801561022857600080fd5b50610243600480360381019061023e9190611172565b610e57565b005b61024d610f4e565b73ffffffffffffffffffffffffffffffffffffffff1661026b610cc4565b73ffffffffffffffffffffffffffffffffffffffff16146102c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b89061148c565b60405180910390fd5b600047905060008111610309576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610300906114f8565b60405180910390fd5b610311610cc4565b73ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610356573d6000803e3d6000fd5b5050565b60045481565b600034116103a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039a90611564565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600283836040516103cd9291906115b4565b908152602001604051809103902060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610455576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044c90611619565b60405180910390fd5b6040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001348152602001600115158152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200142815250600283836040516104db9291906115b4565b908152602001604051809103902060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040820151816002015560608201518160030160006101000a81548160ff02191690831515021790555060808201518160030160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a082015181600401559050507f132c99221e3a8bd54ab4759163b62794bddb60ad4f2dc5f1e3604a5fe03bae578282333460405161062a9493929190611666565b60405180910390a15050565b60006002838360405161064a9291906115b4565b90815260200160405180910390209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036106ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e4906116f2565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610780576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107779061175e565b60405180910390fd5b806002015434146107c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bd906117ca565b60405180910390fd5b338160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f69b91453edfa045ed34feb2b032d08b6c3333ec2404f18b285c7ce7ffe69ba5183833360405161083c939291906117ea565b60405180910390a1505050565b60036020528060005260406000206000915090505481565b6002818051602081018201805184825260208301602085012081835280955050505050506000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154908060030160009054906101000a900460ff16908060030160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060040154905086565b610928610f4e565b73ffffffffffffffffffffffffffffffffffffffff16610946610cc4565b73ffffffffffffffffffffffffffffffffffffffff161461099c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109939061148c565b60405180910390fd5b6109a66000610f56565b565b6109b0610f4e565b73ffffffffffffffffffffffffffffffffffffffff166109ce610cc4565b73ffffffffffffffffffffffffffffffffffffffff1614610a24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1b9061148c565b60405180910390fd5b600060028484604051610a389291906115b4565b908152602001604051809103902090508060030160009054906101000a900460ff16610a99576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9090611868565b60405180910390fd5b8060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480610b4657508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b610b85576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7c906118d4565b60405180910390fd5b60008160030160006101000a81548160ff021916908315150217905550818160030160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600060028260020154610bf89190611923565b90506000606460045483610c0c9190611923565b610c169190611994565b905060008183610c2691906119c5565b905080600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610c7791906119f9565b925050819055507ffe19dffae58b26bebdf0f9362f64c6e305eda567dd06dec08adc7457f65c00ea87878784604051610cb39493929190611666565b60405180910390a150505050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600260015403610d32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2990611a79565b60405180910390fd5b60026001819055506000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008111610dc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db890611ae5565b60405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610e4c573d6000803e3d6000fd5b505060018081905550565b610e5f610f4e565b73ffffffffffffffffffffffffffffffffffffffff16610e7d610cc4565b73ffffffffffffffffffffffffffffffffffffffff1614610ed3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eca9061148c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610f42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3990611b77565b60405180910390fd5b610f4b81610f56565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000819050919050565b61102d8161101a565b82525050565b60006020820190506110486000830184611024565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f84011261108757611086611062565b5b8235905067ffffffffffffffff8111156110a4576110a3611067565b5b6020830191508360018202830111156110c0576110bf61106c565b5b9250929050565b600080602083850312156110de576110dd611058565b5b600083013567ffffffffffffffff8111156110fc576110fb61105d565b5b61110885828601611071565b92509250509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061113f82611114565b9050919050565b61114f81611134565b811461115a57600080fd5b50565b60008135905061116c81611146565b92915050565b60006020828403121561118857611187611058565b5b60006111968482850161115d565b91505092915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6111ed826111a4565b810181811067ffffffffffffffff8211171561120c5761120b6111b5565b5b80604052505050565b600061121f61104e565b905061122b82826111e4565b919050565b600067ffffffffffffffff82111561124b5761124a6111b5565b5b611254826111a4565b9050602081019050919050565b82818337600083830152505050565b600061128361127e84611230565b611215565b90508281526020810184848401111561129f5761129e61119f565b5b6112aa848285611261565b509392505050565b600082601f8301126112c7576112c6611062565b5b81356112d7848260208601611270565b91505092915050565b6000602082840312156112f6576112f5611058565b5b600082013567ffffffffffffffff8111156113145761131361105d565b5b611320848285016112b2565b91505092915050565b61133281611134565b82525050565b60008115159050919050565b61134d81611338565b82525050565b600060c0820190506113686000830189611329565b6113756020830188611329565b6113826040830187611024565b61138f6060830186611344565b61139c6080830185611329565b6113a960a0830184611024565b979650505050505050565b6000806000604084860312156113cd576113cc611058565b5b600084013567ffffffffffffffff8111156113eb576113ea61105d565b5b6113f786828701611071565b9350935050602061140a8682870161115d565b9150509250925092565b60006020820190506114296000830184611329565b92915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061147660208361142f565b915061148182611440565b602082019050919050565b600060208201905081810360008301526114a581611469565b9050919050565b7f4e6f206665657320746f20776974686472617700000000000000000000000000600082015250565b60006114e260138361142f565b91506114ed826114ac565b602082019050919050565b60006020820190508181036000830152611511816114d5565b9050919050565b7f5374616b65206d7573742062652067726561746572207468616e203000000000600082015250565b600061154e601c8361142f565b915061155982611518565b602082019050919050565b6000602082019050818103600083015261157d81611541565b9050919050565b600081905092915050565b600061159b8385611584565b93506115a8838584611261565b82840190509392505050565b60006115c182848661158f565b91508190509392505050565b7f47616d6520616c72656164792065786973747300000000000000000000000000600082015250565b600061160360138361142f565b915061160e826115cd565b602082019050919050565b60006020820190508181036000830152611632816115f6565b9050919050565b6000611645838561142f565b9350611652838584611261565b61165b836111a4565b840190509392505050565b60006060820190508181036000830152611681818688611639565b90506116906020830185611329565b61169d6040830184611024565b95945050505050565b7f47616d6520646f6573206e6f7420657869737400000000000000000000000000600082015250565b60006116dc60138361142f565b91506116e7826116a6565b602082019050919050565b6000602082019050818103600083015261170b816116cf565b9050919050565b7f47616d6520616c72656164792066756c6c000000000000000000000000000000600082015250565b600061174860118361142f565b915061175382611712565b602082019050919050565b600060208201905081810360008301526117778161173b565b9050919050565b7f496e636f7272656374207374616b6520616d6f756e7400000000000000000000600082015250565b60006117b460168361142f565b91506117bf8261177e565b602082019050919050565b600060208201905081810360008301526117e3816117a7565b9050919050565b60006040820190508181036000830152611805818587611639565b90506118146020830184611329565b949350505050565b7f47616d65206e6f74206163746976650000000000000000000000000000000000600082015250565b6000611852600f8361142f565b915061185d8261181c565b602082019050919050565b6000602082019050818103600083015261188181611845565b9050919050565b7f496e76616c69642077696e6e6572000000000000000000000000000000000000600082015250565b60006118be600e8361142f565b91506118c982611888565b602082019050919050565b600060208201905081810360008301526118ed816118b1565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061192e8261101a565b91506119398361101a565b92508282026119478161101a565b9150828204841483151761195e5761195d6118f4565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061199f8261101a565b91506119aa8361101a565b9250826119ba576119b9611965565b5b828204905092915050565b60006119d08261101a565b91506119db8361101a565b92508282039050818111156119f3576119f26118f4565b5b92915050565b6000611a048261101a565b9150611a0f8361101a565b9250828201905080821115611a2757611a266118f4565b5b92915050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000611a63601f8361142f565b9150611a6e82611a2d565b602082019050919050565b60006020820190508181036000830152611a9281611a56565b9050919050565b7f4e6f206561726e696e677320746f207769746864726177000000000000000000600082015250565b6000611acf60178361142f565b9150611ada82611a99565b602082019050919050565b60006020820190508181036000830152611afe81611ac2565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000611b6160268361142f565b9150611b6c82611b05565b604082019050919050565b60006020820190508181036000830152611b9081611b54565b905091905056fea2646970667358221220da42bab4deed86f9aaf14bc08f2ee2a16e3019b4ad3f3b9c6b2ef44700c024c064736f6c63430008140033", 268 | "deployedBytecode": "0x60806040526004361061009c5760003560e01c80636d20931a116100645780636d20931a14610158578063715018a61461019a5780637753af3e146101b15780638da5cb5b146101da578063b73c6ce914610205578063f2fde38b1461021c5761009c565b80630a9ef34c146100a15780631cb398c2146100b85780632ebc0504146100e35780633d536a2e146100ff57806369f927731461011b575b600080fd5b3480156100ad57600080fd5b506100b6610245565b005b3480156100c457600080fd5b506100cd61035a565b6040516100da9190611033565b60405180910390f35b6100fd60048036038101906100f891906110c7565b610360565b005b610119600480360381019061011491906110c7565b610636565b005b34801561012757600080fd5b50610142600480360381019061013d9190611172565b610849565b60405161014f9190611033565b60405180910390f35b34801561016457600080fd5b5061017f600480360381019061017a91906112e0565b610861565b60405161019196959493929190611353565b60405180910390f35b3480156101a657600080fd5b506101af610920565b005b3480156101bd57600080fd5b506101d860048036038101906101d391906113b4565b6109a8565b005b3480156101e657600080fd5b506101ef610cc4565b6040516101fc9190611414565b60405180910390f35b34801561021157600080fd5b5061021a610ced565b005b34801561022857600080fd5b50610243600480360381019061023e9190611172565b610e57565b005b61024d610f4e565b73ffffffffffffffffffffffffffffffffffffffff1661026b610cc4565b73ffffffffffffffffffffffffffffffffffffffff16146102c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b89061148c565b60405180910390fd5b600047905060008111610309576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610300906114f8565b60405180910390fd5b610311610cc4565b73ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610356573d6000803e3d6000fd5b5050565b60045481565b600034116103a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039a90611564565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600283836040516103cd9291906115b4565b908152602001604051809103902060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610455576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044c90611619565b60405180910390fd5b6040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001348152602001600115158152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200142815250600283836040516104db9291906115b4565b908152602001604051809103902060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040820151816002015560608201518160030160006101000a81548160ff02191690831515021790555060808201518160030160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a082015181600401559050507f132c99221e3a8bd54ab4759163b62794bddb60ad4f2dc5f1e3604a5fe03bae578282333460405161062a9493929190611666565b60405180910390a15050565b60006002838360405161064a9291906115b4565b90815260200160405180910390209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036106ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e4906116f2565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610780576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107779061175e565b60405180910390fd5b806002015434146107c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bd906117ca565b60405180910390fd5b338160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f69b91453edfa045ed34feb2b032d08b6c3333ec2404f18b285c7ce7ffe69ba5183833360405161083c939291906117ea565b60405180910390a1505050565b60036020528060005260406000206000915090505481565b6002818051602081018201805184825260208301602085012081835280955050505050506000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154908060030160009054906101000a900460ff16908060030160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060040154905086565b610928610f4e565b73ffffffffffffffffffffffffffffffffffffffff16610946610cc4565b73ffffffffffffffffffffffffffffffffffffffff161461099c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109939061148c565b60405180910390fd5b6109a66000610f56565b565b6109b0610f4e565b73ffffffffffffffffffffffffffffffffffffffff166109ce610cc4565b73ffffffffffffffffffffffffffffffffffffffff1614610a24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1b9061148c565b60405180910390fd5b600060028484604051610a389291906115b4565b908152602001604051809103902090508060030160009054906101000a900460ff16610a99576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9090611868565b60405180910390fd5b8060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480610b4657508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b610b85576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7c906118d4565b60405180910390fd5b60008160030160006101000a81548160ff021916908315150217905550818160030160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600060028260020154610bf89190611923565b90506000606460045483610c0c9190611923565b610c169190611994565b905060008183610c2691906119c5565b905080600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610c7791906119f9565b925050819055507ffe19dffae58b26bebdf0f9362f64c6e305eda567dd06dec08adc7457f65c00ea87878784604051610cb39493929190611666565b60405180910390a150505050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600260015403610d32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2990611a79565b60405180910390fd5b60026001819055506000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008111610dc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610db890611ae5565b60405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610e4c573d6000803e3d6000fd5b505060018081905550565b610e5f610f4e565b73ffffffffffffffffffffffffffffffffffffffff16610e7d610cc4565b73ffffffffffffffffffffffffffffffffffffffff1614610ed3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eca9061148c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610f42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3990611b77565b60405180910390fd5b610f4b81610f56565b50565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000819050919050565b61102d8161101a565b82525050565b60006020820190506110486000830184611024565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f84011261108757611086611062565b5b8235905067ffffffffffffffff8111156110a4576110a3611067565b5b6020830191508360018202830111156110c0576110bf61106c565b5b9250929050565b600080602083850312156110de576110dd611058565b5b600083013567ffffffffffffffff8111156110fc576110fb61105d565b5b61110885828601611071565b92509250509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061113f82611114565b9050919050565b61114f81611134565b811461115a57600080fd5b50565b60008135905061116c81611146565b92915050565b60006020828403121561118857611187611058565b5b60006111968482850161115d565b91505092915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6111ed826111a4565b810181811067ffffffffffffffff8211171561120c5761120b6111b5565b5b80604052505050565b600061121f61104e565b905061122b82826111e4565b919050565b600067ffffffffffffffff82111561124b5761124a6111b5565b5b611254826111a4565b9050602081019050919050565b82818337600083830152505050565b600061128361127e84611230565b611215565b90508281526020810184848401111561129f5761129e61119f565b5b6112aa848285611261565b509392505050565b600082601f8301126112c7576112c6611062565b5b81356112d7848260208601611270565b91505092915050565b6000602082840312156112f6576112f5611058565b5b600082013567ffffffffffffffff8111156113145761131361105d565b5b611320848285016112b2565b91505092915050565b61133281611134565b82525050565b60008115159050919050565b61134d81611338565b82525050565b600060c0820190506113686000830189611329565b6113756020830188611329565b6113826040830187611024565b61138f6060830186611344565b61139c6080830185611329565b6113a960a0830184611024565b979650505050505050565b6000806000604084860312156113cd576113cc611058565b5b600084013567ffffffffffffffff8111156113eb576113ea61105d565b5b6113f786828701611071565b9350935050602061140a8682870161115d565b9150509250925092565b60006020820190506114296000830184611329565b92915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061147660208361142f565b915061148182611440565b602082019050919050565b600060208201905081810360008301526114a581611469565b9050919050565b7f4e6f206665657320746f20776974686472617700000000000000000000000000600082015250565b60006114e260138361142f565b91506114ed826114ac565b602082019050919050565b60006020820190508181036000830152611511816114d5565b9050919050565b7f5374616b65206d7573742062652067726561746572207468616e203000000000600082015250565b600061154e601c8361142f565b915061155982611518565b602082019050919050565b6000602082019050818103600083015261157d81611541565b9050919050565b600081905092915050565b600061159b8385611584565b93506115a8838584611261565b82840190509392505050565b60006115c182848661158f565b91508190509392505050565b7f47616d6520616c72656164792065786973747300000000000000000000000000600082015250565b600061160360138361142f565b915061160e826115cd565b602082019050919050565b60006020820190508181036000830152611632816115f6565b9050919050565b6000611645838561142f565b9350611652838584611261565b61165b836111a4565b840190509392505050565b60006060820190508181036000830152611681818688611639565b90506116906020830185611329565b61169d6040830184611024565b95945050505050565b7f47616d6520646f6573206e6f7420657869737400000000000000000000000000600082015250565b60006116dc60138361142f565b91506116e7826116a6565b602082019050919050565b6000602082019050818103600083015261170b816116cf565b9050919050565b7f47616d6520616c72656164792066756c6c000000000000000000000000000000600082015250565b600061174860118361142f565b915061175382611712565b602082019050919050565b600060208201905081810360008301526117778161173b565b9050919050565b7f496e636f7272656374207374616b6520616d6f756e7400000000000000000000600082015250565b60006117b460168361142f565b91506117bf8261177e565b602082019050919050565b600060208201905081810360008301526117e3816117a7565b9050919050565b60006040820190508181036000830152611805818587611639565b90506118146020830184611329565b949350505050565b7f47616d65206e6f74206163746976650000000000000000000000000000000000600082015250565b6000611852600f8361142f565b915061185d8261181c565b602082019050919050565b6000602082019050818103600083015261188181611845565b9050919050565b7f496e76616c69642077696e6e6572000000000000000000000000000000000000600082015250565b60006118be600e8361142f565b91506118c982611888565b602082019050919050565b600060208201905081810360008301526118ed816118b1565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061192e8261101a565b91506119398361101a565b92508282026119478161101a565b9150828204841483151761195e5761195d6118f4565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061199f8261101a565b91506119aa8361101a565b9250826119ba576119b9611965565b5b828204905092915050565b60006119d08261101a565b91506119db8361101a565b92508282039050818111156119f3576119f26118f4565b5b92915050565b6000611a048261101a565b9150611a0f8361101a565b9250828201905080821115611a2757611a266118f4565b5b92915050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000611a63601f8361142f565b9150611a6e82611a2d565b602082019050919050565b60006020820190508181036000830152611a9281611a56565b9050919050565b7f4e6f206561726e696e677320746f207769746864726177000000000000000000600082015250565b6000611acf60178361142f565b9150611ada82611a99565b602082019050919050565b60006020820190508181036000830152611afe81611ac2565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000611b6160268361142f565b9150611b6c82611b05565b604082019050919050565b60006020820190508181036000830152611b9081611b54565b905091905056fea2646970667358221220da42bab4deed86f9aaf14bc08f2ee2a16e3019b4ad3f3b9c6b2ef44700c024c064736f6c63430008140033", 269 | "linkReferences": {}, 270 | "deployedLinkReferences": {} 271 | } 272 | -------------------------------------------------------------------------------- /server-/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "server", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@jackstenglein/chess": "^2.2.8", 13 | "body-parser": "^1.20.3", 14 | "chess.js": "^1.0.0-beta.8", 15 | "chessground": "^9.1.1", 16 | "cors": "^2.8.5", 17 | "ethers": "^6.13.5", 18 | "express": "^4.21.2", 19 | "http": "^0.0.1-security", 20 | "socket.io": "^4.8.1", 21 | "ws": "^8.18.0" 22 | }, 23 | "devDependencies": { 24 | "nodemon": "^3.1.7" 25 | } 26 | }, 27 | "node_modules/@adraffy/ens-normalize": { 28 | "version": "1.10.1", 29 | "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", 30 | "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", 31 | "license": "MIT" 32 | }, 33 | "node_modules/@jackstenglein/chess": { 34 | "version": "2.2.8", 35 | "resolved": "https://registry.npmjs.org/@jackstenglein/chess/-/chess-2.2.8.tgz", 36 | "integrity": "sha512-NpDBNXuOlkrbb3cSIM/XLDhEigqFKBQUkJWDhhmi5GeDSqio1qTmZ924D5KhIHd550p732p7B/nfsJwxtkrw+A==", 37 | "license": "MIT", 38 | "dependencies": { 39 | "@jackstenglein/pgn-parser": "^2.0.7", 40 | "chess.js": "^1.0.0-beta.7" 41 | } 42 | }, 43 | "node_modules/@jackstenglein/pgn-parser": { 44 | "version": "2.0.8", 45 | "resolved": "https://registry.npmjs.org/@jackstenglein/pgn-parser/-/pgn-parser-2.0.8.tgz", 46 | "integrity": "sha512-4qmK+GdiY3bAGHKtzxMXQhLJUOdZ9l16hY5h7S/T35G3xPVcsmeb1x0cFlrJ7adeJHm09aLnaKkCd1SC+7bAUw==", 47 | "license": "Apache-2.0", 48 | "bin": { 49 | "pgn-parser": "bin/pgn-to-json.js" 50 | } 51 | }, 52 | "node_modules/@noble/curves": { 53 | "version": "1.2.0", 54 | "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", 55 | "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", 56 | "license": "MIT", 57 | "dependencies": { 58 | "@noble/hashes": "1.3.2" 59 | }, 60 | "funding": { 61 | "url": "https://paulmillr.com/funding/" 62 | } 63 | }, 64 | "node_modules/@noble/hashes": { 65 | "version": "1.3.2", 66 | "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", 67 | "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", 68 | "license": "MIT", 69 | "engines": { 70 | "node": ">= 16" 71 | }, 72 | "funding": { 73 | "url": "https://paulmillr.com/funding/" 74 | } 75 | }, 76 | "node_modules/@socket.io/component-emitter": { 77 | "version": "3.1.2", 78 | "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", 79 | "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", 80 | "license": "MIT" 81 | }, 82 | "node_modules/@types/cookie": { 83 | "version": "0.4.1", 84 | "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", 85 | "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", 86 | "license": "MIT" 87 | }, 88 | "node_modules/@types/cors": { 89 | "version": "2.8.17", 90 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", 91 | "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", 92 | "license": "MIT", 93 | "dependencies": { 94 | "@types/node": "*" 95 | } 96 | }, 97 | "node_modules/@types/node": { 98 | "version": "22.10.1", 99 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", 100 | "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", 101 | "license": "MIT", 102 | "dependencies": { 103 | "undici-types": "~6.20.0" 104 | } 105 | }, 106 | "node_modules/accepts": { 107 | "version": "1.3.8", 108 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 109 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 110 | "license": "MIT", 111 | "dependencies": { 112 | "mime-types": "~2.1.34", 113 | "negotiator": "0.6.3" 114 | }, 115 | "engines": { 116 | "node": ">= 0.6" 117 | } 118 | }, 119 | "node_modules/aes-js": { 120 | "version": "4.0.0-beta.5", 121 | "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", 122 | "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", 123 | "license": "MIT" 124 | }, 125 | "node_modules/anymatch": { 126 | "version": "3.1.3", 127 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 128 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 129 | "dev": true, 130 | "license": "ISC", 131 | "dependencies": { 132 | "normalize-path": "^3.0.0", 133 | "picomatch": "^2.0.4" 134 | }, 135 | "engines": { 136 | "node": ">= 8" 137 | } 138 | }, 139 | "node_modules/array-flatten": { 140 | "version": "1.1.1", 141 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 142 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", 143 | "license": "MIT" 144 | }, 145 | "node_modules/balanced-match": { 146 | "version": "1.0.2", 147 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 148 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 149 | "dev": true, 150 | "license": "MIT" 151 | }, 152 | "node_modules/base64id": { 153 | "version": "2.0.0", 154 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", 155 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", 156 | "license": "MIT", 157 | "engines": { 158 | "node": "^4.5.0 || >= 5.9" 159 | } 160 | }, 161 | "node_modules/binary-extensions": { 162 | "version": "2.3.0", 163 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 164 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 165 | "dev": true, 166 | "license": "MIT", 167 | "engines": { 168 | "node": ">=8" 169 | }, 170 | "funding": { 171 | "url": "https://github.com/sponsors/sindresorhus" 172 | } 173 | }, 174 | "node_modules/body-parser": { 175 | "version": "1.20.3", 176 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 177 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 178 | "license": "MIT", 179 | "dependencies": { 180 | "bytes": "3.1.2", 181 | "content-type": "~1.0.5", 182 | "debug": "2.6.9", 183 | "depd": "2.0.0", 184 | "destroy": "1.2.0", 185 | "http-errors": "2.0.0", 186 | "iconv-lite": "0.4.24", 187 | "on-finished": "2.4.1", 188 | "qs": "6.13.0", 189 | "raw-body": "2.5.2", 190 | "type-is": "~1.6.18", 191 | "unpipe": "1.0.0" 192 | }, 193 | "engines": { 194 | "node": ">= 0.8", 195 | "npm": "1.2.8000 || >= 1.4.16" 196 | } 197 | }, 198 | "node_modules/brace-expansion": { 199 | "version": "1.1.11", 200 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 201 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 202 | "dev": true, 203 | "license": "MIT", 204 | "dependencies": { 205 | "balanced-match": "^1.0.0", 206 | "concat-map": "0.0.1" 207 | } 208 | }, 209 | "node_modules/braces": { 210 | "version": "3.0.3", 211 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 212 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 213 | "dev": true, 214 | "license": "MIT", 215 | "dependencies": { 216 | "fill-range": "^7.1.1" 217 | }, 218 | "engines": { 219 | "node": ">=8" 220 | } 221 | }, 222 | "node_modules/bytes": { 223 | "version": "3.1.2", 224 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 225 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 226 | "license": "MIT", 227 | "engines": { 228 | "node": ">= 0.8" 229 | } 230 | }, 231 | "node_modules/call-bind": { 232 | "version": "1.0.7", 233 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 234 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 235 | "license": "MIT", 236 | "dependencies": { 237 | "es-define-property": "^1.0.0", 238 | "es-errors": "^1.3.0", 239 | "function-bind": "^1.1.2", 240 | "get-intrinsic": "^1.2.4", 241 | "set-function-length": "^1.2.1" 242 | }, 243 | "engines": { 244 | "node": ">= 0.4" 245 | }, 246 | "funding": { 247 | "url": "https://github.com/sponsors/ljharb" 248 | } 249 | }, 250 | "node_modules/chess.js": { 251 | "version": "1.0.0-beta.8", 252 | "resolved": "https://registry.npmjs.org/chess.js/-/chess.js-1.0.0-beta.8.tgz", 253 | "integrity": "sha512-UngzUMXmexcQaQA/UEJuJj5vatEy34awYMD5YMOp/FW3HM7lqspp7ymYs5JAmquDq0WROtURRfSffoa/vrCCyw==", 254 | "license": "BSD-2-Clause" 255 | }, 256 | "node_modules/chessground": { 257 | "version": "9.1.1", 258 | "resolved": "https://registry.npmjs.org/chessground/-/chessground-9.1.1.tgz", 259 | "integrity": "sha512-X4xrBICrixaLATCn+jGEzk58UXcas+9QqJnwVq9nT7AaX2M1CJLMA0vC7noG0s6Tr2zoAHZ1FOviE5b05MgduQ==", 260 | "license": "GPL-3.0-or-later", 261 | "funding": { 262 | "url": "https://lichess.org/patron" 263 | } 264 | }, 265 | "node_modules/chokidar": { 266 | "version": "3.6.0", 267 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 268 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 269 | "dev": true, 270 | "license": "MIT", 271 | "dependencies": { 272 | "anymatch": "~3.1.2", 273 | "braces": "~3.0.2", 274 | "glob-parent": "~5.1.2", 275 | "is-binary-path": "~2.1.0", 276 | "is-glob": "~4.0.1", 277 | "normalize-path": "~3.0.0", 278 | "readdirp": "~3.6.0" 279 | }, 280 | "engines": { 281 | "node": ">= 8.10.0" 282 | }, 283 | "funding": { 284 | "url": "https://paulmillr.com/funding/" 285 | }, 286 | "optionalDependencies": { 287 | "fsevents": "~2.3.2" 288 | } 289 | }, 290 | "node_modules/concat-map": { 291 | "version": "0.0.1", 292 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 293 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 294 | "dev": true, 295 | "license": "MIT" 296 | }, 297 | "node_modules/content-disposition": { 298 | "version": "0.5.4", 299 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 300 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 301 | "license": "MIT", 302 | "dependencies": { 303 | "safe-buffer": "5.2.1" 304 | }, 305 | "engines": { 306 | "node": ">= 0.6" 307 | } 308 | }, 309 | "node_modules/content-type": { 310 | "version": "1.0.5", 311 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 312 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 313 | "license": "MIT", 314 | "engines": { 315 | "node": ">= 0.6" 316 | } 317 | }, 318 | "node_modules/cookie": { 319 | "version": "0.7.1", 320 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 321 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", 322 | "license": "MIT", 323 | "engines": { 324 | "node": ">= 0.6" 325 | } 326 | }, 327 | "node_modules/cookie-signature": { 328 | "version": "1.0.6", 329 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 330 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", 331 | "license": "MIT" 332 | }, 333 | "node_modules/cors": { 334 | "version": "2.8.5", 335 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 336 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 337 | "license": "MIT", 338 | "dependencies": { 339 | "object-assign": "^4", 340 | "vary": "^1" 341 | }, 342 | "engines": { 343 | "node": ">= 0.10" 344 | } 345 | }, 346 | "node_modules/debug": { 347 | "version": "2.6.9", 348 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 349 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 350 | "license": "MIT", 351 | "dependencies": { 352 | "ms": "2.0.0" 353 | } 354 | }, 355 | "node_modules/define-data-property": { 356 | "version": "1.1.4", 357 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 358 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 359 | "license": "MIT", 360 | "dependencies": { 361 | "es-define-property": "^1.0.0", 362 | "es-errors": "^1.3.0", 363 | "gopd": "^1.0.1" 364 | }, 365 | "engines": { 366 | "node": ">= 0.4" 367 | }, 368 | "funding": { 369 | "url": "https://github.com/sponsors/ljharb" 370 | } 371 | }, 372 | "node_modules/depd": { 373 | "version": "2.0.0", 374 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 375 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 376 | "license": "MIT", 377 | "engines": { 378 | "node": ">= 0.8" 379 | } 380 | }, 381 | "node_modules/destroy": { 382 | "version": "1.2.0", 383 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 384 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 385 | "license": "MIT", 386 | "engines": { 387 | "node": ">= 0.8", 388 | "npm": "1.2.8000 || >= 1.4.16" 389 | } 390 | }, 391 | "node_modules/ee-first": { 392 | "version": "1.1.1", 393 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 394 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", 395 | "license": "MIT" 396 | }, 397 | "node_modules/encodeurl": { 398 | "version": "2.0.0", 399 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 400 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 401 | "license": "MIT", 402 | "engines": { 403 | "node": ">= 0.8" 404 | } 405 | }, 406 | "node_modules/engine.io": { 407 | "version": "6.6.2", 408 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", 409 | "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", 410 | "license": "MIT", 411 | "dependencies": { 412 | "@types/cookie": "^0.4.1", 413 | "@types/cors": "^2.8.12", 414 | "@types/node": ">=10.0.0", 415 | "accepts": "~1.3.4", 416 | "base64id": "2.0.0", 417 | "cookie": "~0.7.2", 418 | "cors": "~2.8.5", 419 | "debug": "~4.3.1", 420 | "engine.io-parser": "~5.2.1", 421 | "ws": "~8.17.1" 422 | }, 423 | "engines": { 424 | "node": ">=10.2.0" 425 | } 426 | }, 427 | "node_modules/engine.io-parser": { 428 | "version": "5.2.3", 429 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", 430 | "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", 431 | "license": "MIT", 432 | "engines": { 433 | "node": ">=10.0.0" 434 | } 435 | }, 436 | "node_modules/engine.io/node_modules/cookie": { 437 | "version": "0.7.2", 438 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 439 | "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 440 | "license": "MIT", 441 | "engines": { 442 | "node": ">= 0.6" 443 | } 444 | }, 445 | "node_modules/engine.io/node_modules/debug": { 446 | "version": "4.3.7", 447 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 448 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 449 | "license": "MIT", 450 | "dependencies": { 451 | "ms": "^2.1.3" 452 | }, 453 | "engines": { 454 | "node": ">=6.0" 455 | }, 456 | "peerDependenciesMeta": { 457 | "supports-color": { 458 | "optional": true 459 | } 460 | } 461 | }, 462 | "node_modules/engine.io/node_modules/ms": { 463 | "version": "2.1.3", 464 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 465 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 466 | "license": "MIT" 467 | }, 468 | "node_modules/engine.io/node_modules/ws": { 469 | "version": "8.17.1", 470 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", 471 | "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", 472 | "license": "MIT", 473 | "engines": { 474 | "node": ">=10.0.0" 475 | }, 476 | "peerDependencies": { 477 | "bufferutil": "^4.0.1", 478 | "utf-8-validate": ">=5.0.2" 479 | }, 480 | "peerDependenciesMeta": { 481 | "bufferutil": { 482 | "optional": true 483 | }, 484 | "utf-8-validate": { 485 | "optional": true 486 | } 487 | } 488 | }, 489 | "node_modules/es-define-property": { 490 | "version": "1.0.0", 491 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 492 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 493 | "license": "MIT", 494 | "dependencies": { 495 | "get-intrinsic": "^1.2.4" 496 | }, 497 | "engines": { 498 | "node": ">= 0.4" 499 | } 500 | }, 501 | "node_modules/es-errors": { 502 | "version": "1.3.0", 503 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 504 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 505 | "license": "MIT", 506 | "engines": { 507 | "node": ">= 0.4" 508 | } 509 | }, 510 | "node_modules/escape-html": { 511 | "version": "1.0.3", 512 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 513 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 514 | "license": "MIT" 515 | }, 516 | "node_modules/etag": { 517 | "version": "1.8.1", 518 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 519 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 520 | "license": "MIT", 521 | "engines": { 522 | "node": ">= 0.6" 523 | } 524 | }, 525 | "node_modules/ethers": { 526 | "version": "6.13.5", 527 | "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz", 528 | "integrity": "sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==", 529 | "funding": [ 530 | { 531 | "type": "individual", 532 | "url": "https://github.com/sponsors/ethers-io/" 533 | }, 534 | { 535 | "type": "individual", 536 | "url": "https://www.buymeacoffee.com/ricmoo" 537 | } 538 | ], 539 | "license": "MIT", 540 | "dependencies": { 541 | "@adraffy/ens-normalize": "1.10.1", 542 | "@noble/curves": "1.2.0", 543 | "@noble/hashes": "1.3.2", 544 | "@types/node": "22.7.5", 545 | "aes-js": "4.0.0-beta.5", 546 | "tslib": "2.7.0", 547 | "ws": "8.17.1" 548 | }, 549 | "engines": { 550 | "node": ">=14.0.0" 551 | } 552 | }, 553 | "node_modules/ethers/node_modules/@types/node": { 554 | "version": "22.7.5", 555 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", 556 | "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", 557 | "license": "MIT", 558 | "dependencies": { 559 | "undici-types": "~6.19.2" 560 | } 561 | }, 562 | "node_modules/ethers/node_modules/undici-types": { 563 | "version": "6.19.8", 564 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", 565 | "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", 566 | "license": "MIT" 567 | }, 568 | "node_modules/ethers/node_modules/ws": { 569 | "version": "8.17.1", 570 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", 571 | "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", 572 | "license": "MIT", 573 | "engines": { 574 | "node": ">=10.0.0" 575 | }, 576 | "peerDependencies": { 577 | "bufferutil": "^4.0.1", 578 | "utf-8-validate": ">=5.0.2" 579 | }, 580 | "peerDependenciesMeta": { 581 | "bufferutil": { 582 | "optional": true 583 | }, 584 | "utf-8-validate": { 585 | "optional": true 586 | } 587 | } 588 | }, 589 | "node_modules/express": { 590 | "version": "4.21.2", 591 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", 592 | "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", 593 | "license": "MIT", 594 | "dependencies": { 595 | "accepts": "~1.3.8", 596 | "array-flatten": "1.1.1", 597 | "body-parser": "1.20.3", 598 | "content-disposition": "0.5.4", 599 | "content-type": "~1.0.4", 600 | "cookie": "0.7.1", 601 | "cookie-signature": "1.0.6", 602 | "debug": "2.6.9", 603 | "depd": "2.0.0", 604 | "encodeurl": "~2.0.0", 605 | "escape-html": "~1.0.3", 606 | "etag": "~1.8.1", 607 | "finalhandler": "1.3.1", 608 | "fresh": "0.5.2", 609 | "http-errors": "2.0.0", 610 | "merge-descriptors": "1.0.3", 611 | "methods": "~1.1.2", 612 | "on-finished": "2.4.1", 613 | "parseurl": "~1.3.3", 614 | "path-to-regexp": "0.1.12", 615 | "proxy-addr": "~2.0.7", 616 | "qs": "6.13.0", 617 | "range-parser": "~1.2.1", 618 | "safe-buffer": "5.2.1", 619 | "send": "0.19.0", 620 | "serve-static": "1.16.2", 621 | "setprototypeof": "1.2.0", 622 | "statuses": "2.0.1", 623 | "type-is": "~1.6.18", 624 | "utils-merge": "1.0.1", 625 | "vary": "~1.1.2" 626 | }, 627 | "engines": { 628 | "node": ">= 0.10.0" 629 | }, 630 | "funding": { 631 | "type": "opencollective", 632 | "url": "https://opencollective.com/express" 633 | } 634 | }, 635 | "node_modules/fill-range": { 636 | "version": "7.1.1", 637 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 638 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 639 | "dev": true, 640 | "license": "MIT", 641 | "dependencies": { 642 | "to-regex-range": "^5.0.1" 643 | }, 644 | "engines": { 645 | "node": ">=8" 646 | } 647 | }, 648 | "node_modules/finalhandler": { 649 | "version": "1.3.1", 650 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 651 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 652 | "license": "MIT", 653 | "dependencies": { 654 | "debug": "2.6.9", 655 | "encodeurl": "~2.0.0", 656 | "escape-html": "~1.0.3", 657 | "on-finished": "2.4.1", 658 | "parseurl": "~1.3.3", 659 | "statuses": "2.0.1", 660 | "unpipe": "~1.0.0" 661 | }, 662 | "engines": { 663 | "node": ">= 0.8" 664 | } 665 | }, 666 | "node_modules/forwarded": { 667 | "version": "0.2.0", 668 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 669 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 670 | "license": "MIT", 671 | "engines": { 672 | "node": ">= 0.6" 673 | } 674 | }, 675 | "node_modules/fresh": { 676 | "version": "0.5.2", 677 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 678 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 679 | "license": "MIT", 680 | "engines": { 681 | "node": ">= 0.6" 682 | } 683 | }, 684 | "node_modules/fsevents": { 685 | "version": "2.3.3", 686 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 687 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 688 | "dev": true, 689 | "hasInstallScript": true, 690 | "license": "MIT", 691 | "optional": true, 692 | "os": [ 693 | "darwin" 694 | ], 695 | "engines": { 696 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 697 | } 698 | }, 699 | "node_modules/function-bind": { 700 | "version": "1.1.2", 701 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 702 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 703 | "license": "MIT", 704 | "funding": { 705 | "url": "https://github.com/sponsors/ljharb" 706 | } 707 | }, 708 | "node_modules/get-intrinsic": { 709 | "version": "1.2.4", 710 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 711 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 712 | "license": "MIT", 713 | "dependencies": { 714 | "es-errors": "^1.3.0", 715 | "function-bind": "^1.1.2", 716 | "has-proto": "^1.0.1", 717 | "has-symbols": "^1.0.3", 718 | "hasown": "^2.0.0" 719 | }, 720 | "engines": { 721 | "node": ">= 0.4" 722 | }, 723 | "funding": { 724 | "url": "https://github.com/sponsors/ljharb" 725 | } 726 | }, 727 | "node_modules/glob-parent": { 728 | "version": "5.1.2", 729 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 730 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 731 | "dev": true, 732 | "license": "ISC", 733 | "dependencies": { 734 | "is-glob": "^4.0.1" 735 | }, 736 | "engines": { 737 | "node": ">= 6" 738 | } 739 | }, 740 | "node_modules/gopd": { 741 | "version": "1.1.0", 742 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.1.0.tgz", 743 | "integrity": "sha512-FQoVQnqcdk4hVM4JN1eromaun4iuS34oStkdlLENLdpULsuQcTyXj8w7ayhuUfPwEYZ1ZOooOTT6fdA9Vmx/RA==", 744 | "license": "MIT", 745 | "dependencies": { 746 | "get-intrinsic": "^1.2.4" 747 | }, 748 | "engines": { 749 | "node": ">= 0.4" 750 | }, 751 | "funding": { 752 | "url": "https://github.com/sponsors/ljharb" 753 | } 754 | }, 755 | "node_modules/has-flag": { 756 | "version": "3.0.0", 757 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 758 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 759 | "dev": true, 760 | "license": "MIT", 761 | "engines": { 762 | "node": ">=4" 763 | } 764 | }, 765 | "node_modules/has-property-descriptors": { 766 | "version": "1.0.2", 767 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 768 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 769 | "license": "MIT", 770 | "dependencies": { 771 | "es-define-property": "^1.0.0" 772 | }, 773 | "funding": { 774 | "url": "https://github.com/sponsors/ljharb" 775 | } 776 | }, 777 | "node_modules/has-proto": { 778 | "version": "1.0.3", 779 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 780 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", 781 | "license": "MIT", 782 | "engines": { 783 | "node": ">= 0.4" 784 | }, 785 | "funding": { 786 | "url": "https://github.com/sponsors/ljharb" 787 | } 788 | }, 789 | "node_modules/has-symbols": { 790 | "version": "1.0.3", 791 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 792 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 793 | "license": "MIT", 794 | "engines": { 795 | "node": ">= 0.4" 796 | }, 797 | "funding": { 798 | "url": "https://github.com/sponsors/ljharb" 799 | } 800 | }, 801 | "node_modules/hasown": { 802 | "version": "2.0.2", 803 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 804 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 805 | "license": "MIT", 806 | "dependencies": { 807 | "function-bind": "^1.1.2" 808 | }, 809 | "engines": { 810 | "node": ">= 0.4" 811 | } 812 | }, 813 | "node_modules/http": { 814 | "version": "0.0.1-security", 815 | "resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz", 816 | "integrity": "sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g==" 817 | }, 818 | "node_modules/http-errors": { 819 | "version": "2.0.0", 820 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 821 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 822 | "license": "MIT", 823 | "dependencies": { 824 | "depd": "2.0.0", 825 | "inherits": "2.0.4", 826 | "setprototypeof": "1.2.0", 827 | "statuses": "2.0.1", 828 | "toidentifier": "1.0.1" 829 | }, 830 | "engines": { 831 | "node": ">= 0.8" 832 | } 833 | }, 834 | "node_modules/iconv-lite": { 835 | "version": "0.4.24", 836 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 837 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 838 | "license": "MIT", 839 | "dependencies": { 840 | "safer-buffer": ">= 2.1.2 < 3" 841 | }, 842 | "engines": { 843 | "node": ">=0.10.0" 844 | } 845 | }, 846 | "node_modules/ignore-by-default": { 847 | "version": "1.0.1", 848 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 849 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", 850 | "dev": true, 851 | "license": "ISC" 852 | }, 853 | "node_modules/inherits": { 854 | "version": "2.0.4", 855 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 856 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 857 | "license": "ISC" 858 | }, 859 | "node_modules/ipaddr.js": { 860 | "version": "1.9.1", 861 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 862 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 863 | "license": "MIT", 864 | "engines": { 865 | "node": ">= 0.10" 866 | } 867 | }, 868 | "node_modules/is-binary-path": { 869 | "version": "2.1.0", 870 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 871 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 872 | "dev": true, 873 | "license": "MIT", 874 | "dependencies": { 875 | "binary-extensions": "^2.0.0" 876 | }, 877 | "engines": { 878 | "node": ">=8" 879 | } 880 | }, 881 | "node_modules/is-extglob": { 882 | "version": "2.1.1", 883 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 884 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 885 | "dev": true, 886 | "license": "MIT", 887 | "engines": { 888 | "node": ">=0.10.0" 889 | } 890 | }, 891 | "node_modules/is-glob": { 892 | "version": "4.0.3", 893 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 894 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 895 | "dev": true, 896 | "license": "MIT", 897 | "dependencies": { 898 | "is-extglob": "^2.1.1" 899 | }, 900 | "engines": { 901 | "node": ">=0.10.0" 902 | } 903 | }, 904 | "node_modules/is-number": { 905 | "version": "7.0.0", 906 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 907 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 908 | "dev": true, 909 | "license": "MIT", 910 | "engines": { 911 | "node": ">=0.12.0" 912 | } 913 | }, 914 | "node_modules/media-typer": { 915 | "version": "0.3.0", 916 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 917 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 918 | "license": "MIT", 919 | "engines": { 920 | "node": ">= 0.6" 921 | } 922 | }, 923 | "node_modules/merge-descriptors": { 924 | "version": "1.0.3", 925 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 926 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 927 | "license": "MIT", 928 | "funding": { 929 | "url": "https://github.com/sponsors/sindresorhus" 930 | } 931 | }, 932 | "node_modules/methods": { 933 | "version": "1.1.2", 934 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 935 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 936 | "license": "MIT", 937 | "engines": { 938 | "node": ">= 0.6" 939 | } 940 | }, 941 | "node_modules/mime": { 942 | "version": "1.6.0", 943 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 944 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 945 | "license": "MIT", 946 | "bin": { 947 | "mime": "cli.js" 948 | }, 949 | "engines": { 950 | "node": ">=4" 951 | } 952 | }, 953 | "node_modules/mime-db": { 954 | "version": "1.52.0", 955 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 956 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 957 | "license": "MIT", 958 | "engines": { 959 | "node": ">= 0.6" 960 | } 961 | }, 962 | "node_modules/mime-types": { 963 | "version": "2.1.35", 964 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 965 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 966 | "license": "MIT", 967 | "dependencies": { 968 | "mime-db": "1.52.0" 969 | }, 970 | "engines": { 971 | "node": ">= 0.6" 972 | } 973 | }, 974 | "node_modules/minimatch": { 975 | "version": "3.1.2", 976 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 977 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 978 | "dev": true, 979 | "license": "ISC", 980 | "dependencies": { 981 | "brace-expansion": "^1.1.7" 982 | }, 983 | "engines": { 984 | "node": "*" 985 | } 986 | }, 987 | "node_modules/ms": { 988 | "version": "2.0.0", 989 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 990 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", 991 | "license": "MIT" 992 | }, 993 | "node_modules/negotiator": { 994 | "version": "0.6.3", 995 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 996 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 997 | "license": "MIT", 998 | "engines": { 999 | "node": ">= 0.6" 1000 | } 1001 | }, 1002 | "node_modules/nodemon": { 1003 | "version": "3.1.7", 1004 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", 1005 | "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", 1006 | "dev": true, 1007 | "license": "MIT", 1008 | "dependencies": { 1009 | "chokidar": "^3.5.2", 1010 | "debug": "^4", 1011 | "ignore-by-default": "^1.0.1", 1012 | "minimatch": "^3.1.2", 1013 | "pstree.remy": "^1.1.8", 1014 | "semver": "^7.5.3", 1015 | "simple-update-notifier": "^2.0.0", 1016 | "supports-color": "^5.5.0", 1017 | "touch": "^3.1.0", 1018 | "undefsafe": "^2.0.5" 1019 | }, 1020 | "bin": { 1021 | "nodemon": "bin/nodemon.js" 1022 | }, 1023 | "engines": { 1024 | "node": ">=10" 1025 | }, 1026 | "funding": { 1027 | "type": "opencollective", 1028 | "url": "https://opencollective.com/nodemon" 1029 | } 1030 | }, 1031 | "node_modules/nodemon/node_modules/debug": { 1032 | "version": "4.3.7", 1033 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 1034 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 1035 | "dev": true, 1036 | "license": "MIT", 1037 | "dependencies": { 1038 | "ms": "^2.1.3" 1039 | }, 1040 | "engines": { 1041 | "node": ">=6.0" 1042 | }, 1043 | "peerDependenciesMeta": { 1044 | "supports-color": { 1045 | "optional": true 1046 | } 1047 | } 1048 | }, 1049 | "node_modules/nodemon/node_modules/ms": { 1050 | "version": "2.1.3", 1051 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1052 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1053 | "dev": true, 1054 | "license": "MIT" 1055 | }, 1056 | "node_modules/normalize-path": { 1057 | "version": "3.0.0", 1058 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1059 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1060 | "dev": true, 1061 | "license": "MIT", 1062 | "engines": { 1063 | "node": ">=0.10.0" 1064 | } 1065 | }, 1066 | "node_modules/object-assign": { 1067 | "version": "4.1.1", 1068 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1069 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 1070 | "license": "MIT", 1071 | "engines": { 1072 | "node": ">=0.10.0" 1073 | } 1074 | }, 1075 | "node_modules/object-inspect": { 1076 | "version": "1.13.3", 1077 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", 1078 | "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", 1079 | "license": "MIT", 1080 | "engines": { 1081 | "node": ">= 0.4" 1082 | }, 1083 | "funding": { 1084 | "url": "https://github.com/sponsors/ljharb" 1085 | } 1086 | }, 1087 | "node_modules/on-finished": { 1088 | "version": "2.4.1", 1089 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1090 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1091 | "license": "MIT", 1092 | "dependencies": { 1093 | "ee-first": "1.1.1" 1094 | }, 1095 | "engines": { 1096 | "node": ">= 0.8" 1097 | } 1098 | }, 1099 | "node_modules/parseurl": { 1100 | "version": "1.3.3", 1101 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1102 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 1103 | "license": "MIT", 1104 | "engines": { 1105 | "node": ">= 0.8" 1106 | } 1107 | }, 1108 | "node_modules/path-to-regexp": { 1109 | "version": "0.1.12", 1110 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", 1111 | "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", 1112 | "license": "MIT" 1113 | }, 1114 | "node_modules/picomatch": { 1115 | "version": "2.3.1", 1116 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1117 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1118 | "dev": true, 1119 | "license": "MIT", 1120 | "engines": { 1121 | "node": ">=8.6" 1122 | }, 1123 | "funding": { 1124 | "url": "https://github.com/sponsors/jonschlinkert" 1125 | } 1126 | }, 1127 | "node_modules/proxy-addr": { 1128 | "version": "2.0.7", 1129 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1130 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1131 | "license": "MIT", 1132 | "dependencies": { 1133 | "forwarded": "0.2.0", 1134 | "ipaddr.js": "1.9.1" 1135 | }, 1136 | "engines": { 1137 | "node": ">= 0.10" 1138 | } 1139 | }, 1140 | "node_modules/pstree.remy": { 1141 | "version": "1.1.8", 1142 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 1143 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 1144 | "dev": true, 1145 | "license": "MIT" 1146 | }, 1147 | "node_modules/qs": { 1148 | "version": "6.13.0", 1149 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 1150 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 1151 | "license": "BSD-3-Clause", 1152 | "dependencies": { 1153 | "side-channel": "^1.0.6" 1154 | }, 1155 | "engines": { 1156 | "node": ">=0.6" 1157 | }, 1158 | "funding": { 1159 | "url": "https://github.com/sponsors/ljharb" 1160 | } 1161 | }, 1162 | "node_modules/range-parser": { 1163 | "version": "1.2.1", 1164 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1165 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 1166 | "license": "MIT", 1167 | "engines": { 1168 | "node": ">= 0.6" 1169 | } 1170 | }, 1171 | "node_modules/raw-body": { 1172 | "version": "2.5.2", 1173 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 1174 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 1175 | "license": "MIT", 1176 | "dependencies": { 1177 | "bytes": "3.1.2", 1178 | "http-errors": "2.0.0", 1179 | "iconv-lite": "0.4.24", 1180 | "unpipe": "1.0.0" 1181 | }, 1182 | "engines": { 1183 | "node": ">= 0.8" 1184 | } 1185 | }, 1186 | "node_modules/readdirp": { 1187 | "version": "3.6.0", 1188 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1189 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1190 | "dev": true, 1191 | "license": "MIT", 1192 | "dependencies": { 1193 | "picomatch": "^2.2.1" 1194 | }, 1195 | "engines": { 1196 | "node": ">=8.10.0" 1197 | } 1198 | }, 1199 | "node_modules/safe-buffer": { 1200 | "version": "5.2.1", 1201 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1202 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1203 | "funding": [ 1204 | { 1205 | "type": "github", 1206 | "url": "https://github.com/sponsors/feross" 1207 | }, 1208 | { 1209 | "type": "patreon", 1210 | "url": "https://www.patreon.com/feross" 1211 | }, 1212 | { 1213 | "type": "consulting", 1214 | "url": "https://feross.org/support" 1215 | } 1216 | ], 1217 | "license": "MIT" 1218 | }, 1219 | "node_modules/safer-buffer": { 1220 | "version": "2.1.2", 1221 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1222 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1223 | "license": "MIT" 1224 | }, 1225 | "node_modules/semver": { 1226 | "version": "7.6.3", 1227 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", 1228 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", 1229 | "dev": true, 1230 | "license": "ISC", 1231 | "bin": { 1232 | "semver": "bin/semver.js" 1233 | }, 1234 | "engines": { 1235 | "node": ">=10" 1236 | } 1237 | }, 1238 | "node_modules/send": { 1239 | "version": "0.19.0", 1240 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 1241 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 1242 | "license": "MIT", 1243 | "dependencies": { 1244 | "debug": "2.6.9", 1245 | "depd": "2.0.0", 1246 | "destroy": "1.2.0", 1247 | "encodeurl": "~1.0.2", 1248 | "escape-html": "~1.0.3", 1249 | "etag": "~1.8.1", 1250 | "fresh": "0.5.2", 1251 | "http-errors": "2.0.0", 1252 | "mime": "1.6.0", 1253 | "ms": "2.1.3", 1254 | "on-finished": "2.4.1", 1255 | "range-parser": "~1.2.1", 1256 | "statuses": "2.0.1" 1257 | }, 1258 | "engines": { 1259 | "node": ">= 0.8.0" 1260 | } 1261 | }, 1262 | "node_modules/send/node_modules/encodeurl": { 1263 | "version": "1.0.2", 1264 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 1265 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 1266 | "license": "MIT", 1267 | "engines": { 1268 | "node": ">= 0.8" 1269 | } 1270 | }, 1271 | "node_modules/send/node_modules/ms": { 1272 | "version": "2.1.3", 1273 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1274 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1275 | "license": "MIT" 1276 | }, 1277 | "node_modules/serve-static": { 1278 | "version": "1.16.2", 1279 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 1280 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 1281 | "license": "MIT", 1282 | "dependencies": { 1283 | "encodeurl": "~2.0.0", 1284 | "escape-html": "~1.0.3", 1285 | "parseurl": "~1.3.3", 1286 | "send": "0.19.0" 1287 | }, 1288 | "engines": { 1289 | "node": ">= 0.8.0" 1290 | } 1291 | }, 1292 | "node_modules/set-function-length": { 1293 | "version": "1.2.2", 1294 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 1295 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 1296 | "license": "MIT", 1297 | "dependencies": { 1298 | "define-data-property": "^1.1.4", 1299 | "es-errors": "^1.3.0", 1300 | "function-bind": "^1.1.2", 1301 | "get-intrinsic": "^1.2.4", 1302 | "gopd": "^1.0.1", 1303 | "has-property-descriptors": "^1.0.2" 1304 | }, 1305 | "engines": { 1306 | "node": ">= 0.4" 1307 | } 1308 | }, 1309 | "node_modules/setprototypeof": { 1310 | "version": "1.2.0", 1311 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1312 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", 1313 | "license": "ISC" 1314 | }, 1315 | "node_modules/side-channel": { 1316 | "version": "1.0.6", 1317 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 1318 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 1319 | "license": "MIT", 1320 | "dependencies": { 1321 | "call-bind": "^1.0.7", 1322 | "es-errors": "^1.3.0", 1323 | "get-intrinsic": "^1.2.4", 1324 | "object-inspect": "^1.13.1" 1325 | }, 1326 | "engines": { 1327 | "node": ">= 0.4" 1328 | }, 1329 | "funding": { 1330 | "url": "https://github.com/sponsors/ljharb" 1331 | } 1332 | }, 1333 | "node_modules/simple-update-notifier": { 1334 | "version": "2.0.0", 1335 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", 1336 | "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", 1337 | "dev": true, 1338 | "license": "MIT", 1339 | "dependencies": { 1340 | "semver": "^7.5.3" 1341 | }, 1342 | "engines": { 1343 | "node": ">=10" 1344 | } 1345 | }, 1346 | "node_modules/socket.io": { 1347 | "version": "4.8.1", 1348 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", 1349 | "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", 1350 | "license": "MIT", 1351 | "dependencies": { 1352 | "accepts": "~1.3.4", 1353 | "base64id": "~2.0.0", 1354 | "cors": "~2.8.5", 1355 | "debug": "~4.3.2", 1356 | "engine.io": "~6.6.0", 1357 | "socket.io-adapter": "~2.5.2", 1358 | "socket.io-parser": "~4.2.4" 1359 | }, 1360 | "engines": { 1361 | "node": ">=10.2.0" 1362 | } 1363 | }, 1364 | "node_modules/socket.io-adapter": { 1365 | "version": "2.5.5", 1366 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", 1367 | "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", 1368 | "license": "MIT", 1369 | "dependencies": { 1370 | "debug": "~4.3.4", 1371 | "ws": "~8.17.1" 1372 | } 1373 | }, 1374 | "node_modules/socket.io-adapter/node_modules/debug": { 1375 | "version": "4.3.7", 1376 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 1377 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 1378 | "license": "MIT", 1379 | "dependencies": { 1380 | "ms": "^2.1.3" 1381 | }, 1382 | "engines": { 1383 | "node": ">=6.0" 1384 | }, 1385 | "peerDependenciesMeta": { 1386 | "supports-color": { 1387 | "optional": true 1388 | } 1389 | } 1390 | }, 1391 | "node_modules/socket.io-adapter/node_modules/ms": { 1392 | "version": "2.1.3", 1393 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1394 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1395 | "license": "MIT" 1396 | }, 1397 | "node_modules/socket.io-adapter/node_modules/ws": { 1398 | "version": "8.17.1", 1399 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", 1400 | "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", 1401 | "license": "MIT", 1402 | "engines": { 1403 | "node": ">=10.0.0" 1404 | }, 1405 | "peerDependencies": { 1406 | "bufferutil": "^4.0.1", 1407 | "utf-8-validate": ">=5.0.2" 1408 | }, 1409 | "peerDependenciesMeta": { 1410 | "bufferutil": { 1411 | "optional": true 1412 | }, 1413 | "utf-8-validate": { 1414 | "optional": true 1415 | } 1416 | } 1417 | }, 1418 | "node_modules/socket.io-parser": { 1419 | "version": "4.2.4", 1420 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", 1421 | "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", 1422 | "license": "MIT", 1423 | "dependencies": { 1424 | "@socket.io/component-emitter": "~3.1.0", 1425 | "debug": "~4.3.1" 1426 | }, 1427 | "engines": { 1428 | "node": ">=10.0.0" 1429 | } 1430 | }, 1431 | "node_modules/socket.io-parser/node_modules/debug": { 1432 | "version": "4.3.7", 1433 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 1434 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 1435 | "license": "MIT", 1436 | "dependencies": { 1437 | "ms": "^2.1.3" 1438 | }, 1439 | "engines": { 1440 | "node": ">=6.0" 1441 | }, 1442 | "peerDependenciesMeta": { 1443 | "supports-color": { 1444 | "optional": true 1445 | } 1446 | } 1447 | }, 1448 | "node_modules/socket.io-parser/node_modules/ms": { 1449 | "version": "2.1.3", 1450 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1451 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1452 | "license": "MIT" 1453 | }, 1454 | "node_modules/socket.io/node_modules/debug": { 1455 | "version": "4.3.7", 1456 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 1457 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 1458 | "license": "MIT", 1459 | "dependencies": { 1460 | "ms": "^2.1.3" 1461 | }, 1462 | "engines": { 1463 | "node": ">=6.0" 1464 | }, 1465 | "peerDependenciesMeta": { 1466 | "supports-color": { 1467 | "optional": true 1468 | } 1469 | } 1470 | }, 1471 | "node_modules/socket.io/node_modules/ms": { 1472 | "version": "2.1.3", 1473 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1474 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1475 | "license": "MIT" 1476 | }, 1477 | "node_modules/statuses": { 1478 | "version": "2.0.1", 1479 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1480 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1481 | "license": "MIT", 1482 | "engines": { 1483 | "node": ">= 0.8" 1484 | } 1485 | }, 1486 | "node_modules/supports-color": { 1487 | "version": "5.5.0", 1488 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1489 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1490 | "dev": true, 1491 | "license": "MIT", 1492 | "dependencies": { 1493 | "has-flag": "^3.0.0" 1494 | }, 1495 | "engines": { 1496 | "node": ">=4" 1497 | } 1498 | }, 1499 | "node_modules/to-regex-range": { 1500 | "version": "5.0.1", 1501 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1502 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1503 | "dev": true, 1504 | "license": "MIT", 1505 | "dependencies": { 1506 | "is-number": "^7.0.0" 1507 | }, 1508 | "engines": { 1509 | "node": ">=8.0" 1510 | } 1511 | }, 1512 | "node_modules/toidentifier": { 1513 | "version": "1.0.1", 1514 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1515 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1516 | "license": "MIT", 1517 | "engines": { 1518 | "node": ">=0.6" 1519 | } 1520 | }, 1521 | "node_modules/touch": { 1522 | "version": "3.1.1", 1523 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", 1524 | "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", 1525 | "dev": true, 1526 | "license": "ISC", 1527 | "bin": { 1528 | "nodetouch": "bin/nodetouch.js" 1529 | } 1530 | }, 1531 | "node_modules/tslib": { 1532 | "version": "2.7.0", 1533 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", 1534 | "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", 1535 | "license": "0BSD" 1536 | }, 1537 | "node_modules/type-is": { 1538 | "version": "1.6.18", 1539 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1540 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1541 | "license": "MIT", 1542 | "dependencies": { 1543 | "media-typer": "0.3.0", 1544 | "mime-types": "~2.1.24" 1545 | }, 1546 | "engines": { 1547 | "node": ">= 0.6" 1548 | } 1549 | }, 1550 | "node_modules/undefsafe": { 1551 | "version": "2.0.5", 1552 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 1553 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", 1554 | "dev": true, 1555 | "license": "MIT" 1556 | }, 1557 | "node_modules/undici-types": { 1558 | "version": "6.20.0", 1559 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", 1560 | "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", 1561 | "license": "MIT" 1562 | }, 1563 | "node_modules/unpipe": { 1564 | "version": "1.0.0", 1565 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1566 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1567 | "license": "MIT", 1568 | "engines": { 1569 | "node": ">= 0.8" 1570 | } 1571 | }, 1572 | "node_modules/utils-merge": { 1573 | "version": "1.0.1", 1574 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1575 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 1576 | "license": "MIT", 1577 | "engines": { 1578 | "node": ">= 0.4.0" 1579 | } 1580 | }, 1581 | "node_modules/vary": { 1582 | "version": "1.1.2", 1583 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1584 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1585 | "license": "MIT", 1586 | "engines": { 1587 | "node": ">= 0.8" 1588 | } 1589 | }, 1590 | "node_modules/ws": { 1591 | "version": "8.18.0", 1592 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", 1593 | "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", 1594 | "license": "MIT", 1595 | "engines": { 1596 | "node": ">=10.0.0" 1597 | }, 1598 | "peerDependencies": { 1599 | "bufferutil": "^4.0.1", 1600 | "utf-8-validate": ">=5.0.2" 1601 | }, 1602 | "peerDependenciesMeta": { 1603 | "bufferutil": { 1604 | "optional": true 1605 | }, 1606 | "utf-8-validate": { 1607 | "optional": true 1608 | } 1609 | } 1610 | } 1611 | } 1612 | } 1613 | --------------------------------------------------------------------------------