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 (
+ <>
+
+ >
+ );
+};
+
+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 Leaderboard
+
+
+ {loading ? (
+
Loading leaderboard data...
+ ) : error ? (
+
{error}
+ ) : (
+
+
+
+
+ Rank |
+ Player |
+ Amount |
+
+
+
+ {leaderboardData.map((entry, index) => (
+
+
+
+ {index + 1}
+
+ |
+
+
+
+
+
+
+ {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 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 (
+ <>
+
+ >
+ );
+};
+
+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
-
-
-
- Get started by editing{" "}
-
- packages/nextjs/app/page.tsx
-
-
-
- Edit your smart contract{" "}
-
- YourContract.sol
-
{" "}
- in{" "}
-
- packages/hardhat/contracts
-
-
+
+ {/* Main 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 && (
+
+
+
+
+
+
+ )}
+
+ {/* 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 (
-
-
+
+
+
+
-
-
-
-
-
- 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 */