diff --git a/package-lock.json b/package-lock.json index 053f42b..efd9538 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19795,10 +19795,11 @@ }, "packages/nextjs/node_modules/@next/swc-win32-x64-msvc": { "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz", + "integrity": "sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -30289,6 +30290,126 @@ "optional": true } } + }, + "packages/nextjs/node_modules/@next/swc-darwin-arm64": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz", + "integrity": "sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "packages/nextjs/node_modules/@next/swc-darwin-x64": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz", + "integrity": "sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "packages/nextjs/node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz", + "integrity": "sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "packages/nextjs/node_modules/@next/swc-linux-arm64-musl": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz", + "integrity": "sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "packages/nextjs/node_modules/@next/swc-linux-x64-gnu": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz", + "integrity": "sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "packages/nextjs/node_modules/@next/swc-linux-x64-musl": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz", + "integrity": "sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "packages/nextjs/node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz", + "integrity": "sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "packages/nextjs/node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz", + "integrity": "sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } } }, "dependencies": { @@ -49578,6 +49699,60 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true + }, + "@next/swc-darwin-arm64": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz", + "integrity": "sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==", + "optional": true + }, + "@next/swc-darwin-x64": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz", + "integrity": "sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==", + "optional": true + }, + "@next/swc-linux-arm64-gnu": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz", + "integrity": "sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==", + "optional": true + }, + "@next/swc-linux-arm64-musl": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz", + "integrity": "sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==", + "optional": true + }, + "@next/swc-linux-x64-gnu": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz", + "integrity": "sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==", + "optional": true + }, + "@next/swc-linux-x64-musl": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz", + "integrity": "sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==", + "optional": true + }, + "@next/swc-win32-arm64-msvc": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz", + "integrity": "sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==", + "optional": true + }, + "@next/swc-win32-ia32-msvc": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz", + "integrity": "sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==", + "optional": true + }, + "@next/swc-win32-x64-msvc": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz", + "integrity": "sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==", + "optional": true } } } diff --git a/packages/nextjs/app/landing-page/page.tsx b/packages/nextjs/app/landing-page/page.tsx new file mode 100644 index 0000000..64c31aa --- /dev/null +++ b/packages/nextjs/app/landing-page/page.tsx @@ -0,0 +1,33 @@ +"use client"; + +import Image from "next/image"; +import type { NextPage } from "next"; +import { useAccount } from "wagmi"; +import { Address } from "~~/components/scaffold-eth"; +import { FaucetButton, RainbowKitCustomConnectButton } from "~~/components/scaffold-eth"; + +const Home: NextPage = () => { + const { address: connectedAddress } = useAccount(); + + return ( + <> +
+
+ Ninja Strike Background +
+
+
+

Connected Address:

+
+
+
+ + +
+
+
+ + ); +}; + +export default Home; diff --git a/packages/nextjs/app/layout.tsx b/packages/nextjs/app/layout.tsx index aa51df5..e675895 100644 --- a/packages/nextjs/app/layout.tsx +++ b/packages/nextjs/app/layout.tsx @@ -6,8 +6,8 @@ import "~~/styles/globals.css"; import { getMetadata } from "~~/utils/scaffold-eth/getMetadata"; export const metadata = getMetadata({ - title: "Scaffold-ETH 2 App", - description: "Built with 🏗 Scaffold-ETH 2", + title: "Ninja strike", + description: "Web3 Ninja Game", }); const ScaffoldEthApp = ({ children }: { children: React.ReactNode }) => { diff --git a/packages/nextjs/app/leaderboard/page.tsx b/packages/nextjs/app/leaderboard/page.tsx new file mode 100644 index 0000000..a83a8a6 --- /dev/null +++ b/packages/nextjs/app/leaderboard/page.tsx @@ -0,0 +1,166 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import Image from "next/image"; +import { useAccount } from "wagmi"; +import { Address } from "~~/components/scaffold-eth"; + +interface RawLeaderboardEntry { + winner: string; + amount: string; +} + +interface ProcessedLeaderboardEntry { + winner: string; + amount: string; +} + +const Leaderboard: React.FC = () => { + const { address: connectedAddress } = useAccount(); + const [leaderboardData, setLeaderboardData] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const processLeaderboard = (leaderboard: RawLeaderboardEntry[]): ProcessedLeaderboardEntry[] => { + const summedLeaderboard: { [key: string]: bigint } = {}; + + leaderboard.forEach(entry => { + const { winner, amount } = entry; + const amountBigInt = BigInt(amount); + + if (summedLeaderboard[winner]) { + summedLeaderboard[winner] += amountBigInt; + } else { + summedLeaderboard[winner] = amountBigInt; + } + }); + + const processedLeaderboard = Object.entries(summedLeaderboard).map(([winner, amount]) => ({ + winner, + amount: amount.toString(), + })); + + // Convert BigInt comparison to number comparison + return processedLeaderboard.sort((a, b) => Number(BigInt(b.amount) - BigInt(a.amount))); + }; + + useEffect(() => { + const fetchLeaderboardData = async () => { + try { + const response = await fetch("https://indexer.bigdevenergy.link/7fa3490/v1/graphql", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + query: ` + query { + leaderboard: Escrow_Released(limit: 20) { + winner + amount + } + } + `, + }), + }); + + const result = await response.json(); + if (result.errors) { + throw new Error(result.errors[0].message); + } + const processedData = processLeaderboard(result.data.leaderboard); + setLeaderboardData(processedData); + setLoading(false); + } catch (err) { + console.error("Error fetching leaderboard data:", err); + setError("Failed to load leaderboard data. Please try again later."); + setLoading(false); + } + }; + + fetchLeaderboardData(); + }, []); + + return ( +
+ Ninja Strike Background + +
+
+ Ninja Strike Logo + +
+

Connected Address:

+
+
+ +
+

+ Ninja Strike Leaderboard +

+ + {loading ? ( +

Loading leaderboard data...

+ ) : error ? ( +

{error}

+ ) : ( +
+ + + + + + + + + + {leaderboardData.map((entry, index) => ( + + + + + + ))} + +
RankPlayerAmount
+ + {index + 1} + + +
+
+ {`${entry.winner}'s +
+ + {entry.winner} + +
+
+ {entry.amount} +
+
+ )} +
+
+
+
+ ); +}; + +export default Leaderboard; diff --git a/packages/nextjs/app/nft-arena/NftArena.module.css b/packages/nextjs/app/nft-arena/NftArena.module.css new file mode 100644 index 0000000..66f18d9 --- /dev/null +++ b/packages/nextjs/app/nft-arena/NftArena.module.css @@ -0,0 +1,64 @@ +.container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + height: 100vh; + background: linear-gradient(135deg, #000080, #4b0082); + color: white; + font-family: "Arial", sans-serif; + padding-top: 50px; +} + +.title { + font-size: 36px; + margin-bottom: 10px; + letter-spacing: 2px; +} + +.subtitle { + font-size: 48px; + margin-bottom: 40px; + letter-spacing: 2px; +} + +.stats { + display: flex; + flex-direction: column; + align-items: flex-start; + width: 80%; + max-width: 600px; +} + +.statItem { + width: 100%; + margin-bottom: 30px; +} + +.label { + font-size: 24px; + margin-bottom: 5px; + font-weight: normal; +} + +.value { + font-size: 72px; + font-weight: bold; + margin: 0; +} + +.wallet { + position: absolute; + top: 20px; + right: 20px; + background: rgba(255, 255, 255, 0.1); + padding: 10px 20px; + border-radius: 20px; + font-size: 16px; +} + +.loading, +.error { + font-size: 18px; + margin-top: 20px; +} diff --git a/packages/nextjs/app/nft-arena/page.tsx b/packages/nextjs/app/nft-arena/page.tsx new file mode 100644 index 0000000..946660f --- /dev/null +++ b/packages/nextjs/app/nft-arena/page.tsx @@ -0,0 +1,144 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import Image from "next/image"; +import styles from "./NftArena.module.css"; +import { useAccount } from "wagmi"; + +interface DepositData { + amount: string; + escrowType: string; + escrowId: string; +} + +interface WinData { + amount: string; + escrowId: string; +} + +const NftArena: React.FC = () => { + const { address, isConnected } = useAccount(); // isConnected will help check if wallet is connected + const [totalDeposits, setTotalDeposits] = useState(0); + const [totalWins, setTotalWins] = useState(0); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const calculateTotal = (items: { amount: string }[]): number => { + return items.reduce((acc: number, item: { amount: string }) => acc + parseInt(item.amount), 0); + }; + + useEffect(() => { + const fetchData = async () => { + // Ensure the wallet is connected and the address is valid + if (!address || !isConnected) { + setError("Wallet not connected."); + setLoading(false); + return; + } + + console.log("Fetching data for address:", address); // Debug log to verify the address + + const query = ` + query UserStats($user: String!) { + totalDeposits: Escrow_Deposited(where: {user: {_eq: $user}}) { + id + amount + escrowType + escrowId + } + totalWins: Escrow_Released(where: {winner: {_eq: $user}}) { + id + amount + escrowId + } + transactionHistory: Escrow_Deposited(where: {user: {_eq: $user}}) { + id + amount + escrowType + escrowId + } + winningHistory: Escrow_Released(where: {winner: {_eq: $user}}) { + id + amount + escrowId + } + } + `; + + const variables = { + user: address, // Dynamically passing the connected user address + }; + + const raw = JSON.stringify({ + query, + variables, + }); + + const requestOptions = { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: raw, + }; + + try { + const response = await fetch("https://indexer.bigdevenergy.link/7fa3490/v1/graphql", requestOptions); + const result = await response.json(); + if (result.errors) { + throw new Error(result.errors[0].message); + } + + const fetchedDeposits: DepositData[] = result.data.totalDeposits; + const fetchedWins: WinData[] = result.data.totalWins; + + const calculatedDeposits = calculateTotal(fetchedDeposits); + const totalWinsCount = fetchedWins.length; + + setTotalDeposits(calculatedDeposits); + setTotalWins(totalWinsCount); + setLoading(false); + } catch (err) { + console.error("Error fetching data:", err); + setError("Failed to load data. Please try again later."); + setLoading(false); + } + }; + + if (address && isConnected) { + fetchData(); + } + }, [address, isConnected]); // Trigger fetchData when address or isConnected changes + + return ( +
+ Ninja Strike + +
NINJA STATS
+ + {loading ? ( +

Loading data...

+ ) : error ? ( +

{error}

+ ) : ( +
+
+

NINJA WINS

+

{totalWins.toString().padStart(2, "0")}

+
+
+

NINJA DEPOSITS

+

{(totalDeposits / 1e18).toFixed(1)} ETH

+
+
+ )} + +
+

Connected Address:

+

CONNECTED : {isConnected && address ? `${address.slice(0, 6)}...${address.slice(-4)}` : "Not Connected"}

+
+
+ ); +}; + +export default NftArena; diff --git a/packages/nextjs/app/ninja-game/page.tsx b/packages/nextjs/app/ninja-game/page.tsx new file mode 100644 index 0000000..64c31aa --- /dev/null +++ b/packages/nextjs/app/ninja-game/page.tsx @@ -0,0 +1,33 @@ +"use client"; + +import Image from "next/image"; +import type { NextPage } from "next"; +import { useAccount } from "wagmi"; +import { Address } from "~~/components/scaffold-eth"; +import { FaucetButton, RainbowKitCustomConnectButton } from "~~/components/scaffold-eth"; + +const Home: NextPage = () => { + const { address: connectedAddress } = useAccount(); + + return ( + <> +
+
+ Ninja Strike Background +
+
+
+

Connected Address:

+
+
+
+ + +
+
+
+ + ); +}; + +export default Home; diff --git a/packages/nextjs/app/page.tsx b/packages/nextjs/app/page.tsx index b91c22f..fb73501 100644 --- a/packages/nextjs/app/page.tsx +++ b/packages/nextjs/app/page.tsx @@ -1,70 +1,846 @@ "use client"; -import Link from "next/link"; +import { useEffect, useState } from "react"; +import Image from "next/image"; +import { ethers } from "ethers"; import type { NextPage } from "next"; -import { useAccount } from "wagmi"; -import { BugAntIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; -import { Address } from "~~/components/scaffold-eth"; +import { useAccount, useWalletClient } from "wagmi"; +import { FaucetButton, RainbowKitCustomConnectButton } from "~~/components/scaffold-eth"; + +const NFT_ABI =[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "lock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "MetadataLocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "MetadataUnlocked", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "string", + "name": "tokenURI", + "type": "string" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "pauseToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_onlyOwnerCanMint", + "type": "bool" + } + ], + "name": "setOnlyOwnerCanMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "TokenMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "TokenPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "TokenUnpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "unlock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "unpauseToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "string", + "name": "status", + "type": "string" + }, + { + "internalType": "string", + "name": "tokenURI", + "type": "string" + } + ], + "name": "updateNFT", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "nftData", + "outputs": [ + { + "internalType": "string", + "name": "status", + "type": "string" + }, + { + "internalType": "bool", + "name": "locked", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "onlyOwnerCanMint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "pausedTokens", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "tokensByAddress", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] + + +const NFT_CONTRACT_ADDRESS = "0x5233D4A008B7B94D27b98D634223E5088F84FDA3"; const Home: NextPage = () => { - const { address: connectedAddress } = useAccount(); + const { address: connectedAddress, isConnected } = useAccount(); + const { data: walletClient } = useWalletClient(); + const [showPopup, setShowPopup] = useState(false); + const [isClosing, setIsClosing] = useState(false); + const [hasNFT, setHasNFT] = useState(false); + const [nftContract, setNftContract] = useState(null); + console.log(hasNFT); + + useEffect(() => { + const setupContract = async () => { + if (walletClient) { + const provider = new ethers.BrowserProvider(walletClient as any); + const signer = await provider.getSigner(); + const contract = new ethers.Contract(NFT_CONTRACT_ADDRESS, NFT_ABI, signer); + setNftContract(contract); + } + }; + + setupContract(); + }, [walletClient]); + + useEffect(() => { + const checkNFTBalance = async () => { + if (isConnected && nftContract && connectedAddress) { + try { + const balance = await nftContract.balanceOf(connectedAddress); + console.log("this is balanmce", balance); + + setHasNFT(Number(balance) > 0); + setShowPopup(Number(balance) === 0); + } catch (error) { + console.error("Error checking NFT balance:", error); + setHasNFT(false); + setShowPopup(true); + } + } + }; + + checkNFTBalance(); + }, [isConnected, nftContract, connectedAddress]); + + const closePopup = () => { + setIsClosing(true); + setTimeout(() => { + setShowPopup(false); + setIsClosing(false); + }, 1500); + }; + + const mintNFT = async () => { + if (nftContract && connectedAddress) { + try { + // You might want to replace this with the actual URI for your NFT metadata + const tokenURI = + "https://gray-academic-grouse-23.mypinata.cloud/ipfs/QmNPnYgGcELxQP11S6ta2HCVMnni35diguMaDFdfyVR146"; + + // Call the mint function on the contract + const tx = await nftContract.mint(connectedAddress, tokenURI); + + // Wait for the transaction to be mined + await tx.wait(); + + setHasNFT(true); + setShowPopup(false); + console.log("NFT minted successfully!"); + } catch (error) { + console.error("Error minting NFT:", error); + } + } + }; return ( - <> -
-
-

- Welcome to - Scaffold-ETH 2 -

-
-

Connected Address:

-
-
-

- Get started by editing{" "} - - packages/nextjs/app/page.tsx - -

-

- Edit your smart contract{" "} - - YourContract.sol - {" "} - in{" "} - - packages/hardhat/contracts - -

+
+ {/* Main background */} +
+ Ninja Strike Background +
+ + {/* Connect Button - Positioned at top right */} +
+
+
+
-
-
-
- -

- Tinker with your smart contract using the{" "} - - Debug Contracts - {" "} - tab. -

-
-
- -

- Explore your local transactions with the{" "} - - Block Explorer - {" "} - tab. -

+ {/* Popup overlay */} + {showPopup && ( +
+
+ + Ninja Popup +
+
+ )} + + {/* Main content */} +
+
+ {isConnected && ( + <> + + + )} +
+
{isConnected && }
- +
); }; diff --git a/packages/nextjs/components/Footer.tsx b/packages/nextjs/components/Footer.tsx index 92b3c62..3427220 100644 --- a/packages/nextjs/components/Footer.tsx +++ b/packages/nextjs/components/Footer.tsx @@ -2,9 +2,6 @@ import React from "react"; import Link from "next/link"; import { hardhat } from "viem/chains"; import { CurrencyDollarIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; -import { HeartIcon } from "@heroicons/react/24/outline"; -import { SwitchTheme } from "~~/components/SwitchTheme"; -import { BuidlGuidlLogo } from "~~/components/assets/BuidlGuidlLogo"; import { Faucet } from "~~/components/scaffold-eth"; import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork"; import { useGlobalState } from "~~/services/store/store"; @@ -40,39 +37,12 @@ export const Footer = () => { )}
- + {/* */}
diff --git a/packages/nextjs/components/Header.tsx b/packages/nextjs/components/Header.tsx index 57d2752..fc86cc2 100644 --- a/packages/nextjs/components/Header.tsx +++ b/packages/nextjs/components/Header.tsx @@ -6,7 +6,6 @@ import Link from "next/link"; import { usePathname } from "next/navigation"; import { Bars3Icon, BugAntIcon } from "@heroicons/react/24/outline"; import { RectangleGroupIcon } from "@heroicons/react/24/outline"; -import { FaucetButton, RainbowKitCustomConnectButton } from "~~/components/scaffold-eth"; import { useOutsideClick } from "~~/hooks/scaffold-eth"; type HeaderMenuLink = { @@ -16,20 +15,39 @@ type HeaderMenuLink = { }; export const menuLinks: HeaderMenuLink[] = [ + // { + // label: "Home", + // href: "/", + // }, + // { + // label: "Debug Contracts", + // href: "/debug", + // icon: , + // }, + // { + // label: "OnchainKit examples", + // href: "/onchainkit-examples", + // icon: , + // }, { label: "Home", href: "/", }, { - label: "Debug Contracts", - href: "/debug", + label: "Leaderboard", + href: "/leaderboard", icon: , }, { - label: "OnchainKit examples", - href: "/onchainkit-examples", + label: "Ninja Game", + href: "/ninja-game", icon: , }, + { + label: "NFT Arena", + href: "/nft-arena", + icon: , + }, ]; export const HeaderMenuLinks = () => { @@ -58,9 +76,6 @@ export const HeaderMenuLinks = () => { ); }; -/** - * Site header - */ export const Header = () => { const [isDrawerOpen, setIsDrawerOpen] = useState(false); const burgerMenuRef = useRef(null); @@ -70,8 +85,18 @@ export const Header = () => { ); return ( -
-
+
+
+ +
+ SE2 logo +
+ +
+
+
    + +
- -
- SE2 logo -
-
- Scaffold-ETH - Ethereum dev stack -
- -
    - -
-
-
- -
); diff --git a/packages/nextjs/components/ScaffoldEthAppWithProviders.tsx b/packages/nextjs/components/ScaffoldEthAppWithProviders.tsx index 274e146..232a31e 100644 --- a/packages/nextjs/components/ScaffoldEthAppWithProviders.tsx +++ b/packages/nextjs/components/ScaffoldEthAppWithProviders.tsx @@ -19,9 +19,9 @@ const ScaffoldEthApp = ({ children }: { children: React.ReactNode }) => { return ( <> -
+
-
{children}
+
{children}
diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts index b933eb7..7ea7321 100644 --- a/packages/nextjs/contracts/deployedContracts.ts +++ b/packages/nextjs/contracts/deployedContracts.ts @@ -1244,18 +1244,29 @@ const deployedContracts = { }, ], inheritedFunctions: { - approve: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", - balanceOf: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", - getApproved: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", - isApprovedForAll: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + approve: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + balanceOf: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + getApproved: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + isApprovedForAll: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", name: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", - ownerOf: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", - safeTransferFrom: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", - setApprovalForAll: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", - supportsInterface: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", - symbol: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", - tokenURI: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", - transferFrom: "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + ownerOf: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + safeTransferFrom: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + setApprovalForAll: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + supportsInterface: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + symbol: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + tokenURI: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + transferFrom: + "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", owner: "@openzeppelin/contracts/access/Ownable.sol", renounceOwnership: "@openzeppelin/contracts/access/Ownable.sol", transferOwnership: "@openzeppelin/contracts/access/Ownable.sol", @@ -1556,7 +1567,11 @@ const deployedContracts = { }, }, YourContract: { +<<<<<<< HEAD + address: "0x5FbDB2315678afecb367f032d93F642f64180aa3", +======= address: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", +>>>>>>> b0a505d22357de9aaa07206d5c745bbe225723c6 abi: [ { inputs: [ diff --git a/packages/nextjs/public/Leaderboardbg.png b/packages/nextjs/public/Leaderboardbg.png new file mode 100644 index 0000000..daee49f Binary files /dev/null and b/packages/nextjs/public/Leaderboardbg.png differ diff --git a/packages/nextjs/public/Ninjabg.png b/packages/nextjs/public/Ninjabg.png new file mode 100644 index 0000000..0715e43 Binary files /dev/null and b/packages/nextjs/public/Ninjabg.png differ diff --git a/packages/nextjs/public/Ninjapopup.png b/packages/nextjs/public/Ninjapopup.png new file mode 100644 index 0000000..9bdf44b Binary files /dev/null and b/packages/nextjs/public/Ninjapopup.png differ diff --git a/packages/nextjs/public/avatar.jpg b/packages/nextjs/public/avatar.jpg new file mode 100644 index 0000000..a5825dc Binary files /dev/null and b/packages/nextjs/public/avatar.jpg differ diff --git a/packages/nextjs/public/nslogo.png b/packages/nextjs/public/nslogo.png new file mode 100644 index 0000000..d6a5095 Binary files /dev/null and b/packages/nextjs/public/nslogo.png differ diff --git a/packages/nextjs/scaffold.config.ts b/packages/nextjs/scaffold.config.ts index 4e74046..b2fa17f 100644 --- a/packages/nextjs/scaffold.config.ts +++ b/packages/nextjs/scaffold.config.ts @@ -10,7 +10,7 @@ export type ScaffoldConfig = { const scaffoldConfig = { // The networks on which your DApp is live - targetNetworks: [chains.hardhat, chains.base], + targetNetworks: [chains.sepolia, chains.morphHolesky], // The interval at which your front-end polls the RPC servers for new data // it has no effect if you only target the local network (default is 4000) diff --git a/packages/nextjs/styles/globals.css b/packages/nextjs/styles/globals.css index 3fb55ae..8e724d9 100644 --- a/packages/nextjs/styles/globals.css +++ b/packages/nextjs/styles/globals.css @@ -30,3 +30,44 @@ p { .btn.btn-ghost { @apply shadow-none; } + +/* leaderboard */ + +@keyframes ninja-vanish { + 0% { + opacity: 1; + transform: scale(1) rotate(0deg); + filter: blur(0px) brightness(1); + } + 20% { + opacity: 1; + transform: scale(1.05) rotate(-2deg); + filter: blur(2px) brightness(1.2); + } + 40% { + opacity: 0.8; + transform: scale(0.95) rotate(2deg); + filter: blur(0px) brightness(1.5); + } + 60% { + opacity: 0.6; + transform: scale(1.02) rotate(-1deg) translateY(-10px); + filter: blur(3px) brightness(2); + } + 80% { + opacity: 0.4; + transform: scale(0.98) rotate(1deg) translateY(5px); + filter: blur(5px) brightness(3); + } + 100% { + opacity: 0; + transform: scale(0.9) rotate(720deg) translateY(-50px); + filter: blur(10px) brightness(5); + } +} + +.animate-ninja-vanish { + animation: ninja-vanish 1.5s cubic-bezier(0.65, 0, 0.35, 1) forwards; +} + +/* nft arena */