forked from mico/idle_moloch
Compare commits
2 Commits
session-wa
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| eb4ce2d2c7 | |||
|
|
3332eaf81e |
@ -1,24 +1,33 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import styles from '../styles/Leaderboard.module.css'
|
||||
import { TopEarnersResponse, TopRaidersResponse } from '../types/leaderboard'
|
||||
import { formatUnits } from 'viem'
|
||||
import { useEffect, useState } from "react";
|
||||
import styles from "../styles/Leaderboard.module.css";
|
||||
import {
|
||||
TopEarnersResponse,
|
||||
TopRaidersResponse,
|
||||
PlayerResponse,
|
||||
} from "../types/leaderboard";
|
||||
import { formatUnits } from "viem";
|
||||
|
||||
const SUBGRAPH_URL = 'https://api.studio.thegraph.com/query/75782/slay-the-moloch-base-sepolia/version/latest'
|
||||
const SUBGRAPH_URL =
|
||||
"https://api.studio.thegraph.com/query/75782/slay-the-moloch-base-mainnet/version/latest";
|
||||
|
||||
const Leaderboard = () => {
|
||||
const [topEarners, setTopEarners] = useState<TopEarnersResponse>()
|
||||
const [topRaiders, setTopRaiders] = useState<TopRaidersResponse>()
|
||||
const [activeTab, setActiveTab] = useState<'earners' | 'raiders'>('earners')
|
||||
const [topEarners, setTopEarners] = useState<TopEarnersResponse>();
|
||||
const [topRaiders, setTopRaiders] = useState<TopRaidersResponse>();
|
||||
const [activeTab, setActiveTab] = useState<
|
||||
"earners" | "raiders" | "bosses" | "prestige"
|
||||
>("earners");
|
||||
const [bossesDefeated, setBossesDefeated] = useState<PlayerResponse>();
|
||||
const [playerPrestige, setPlayerPrestige] = useState<PlayerResponse>();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchLeaderboards = async () => {
|
||||
try {
|
||||
// Fetch top earners
|
||||
const earnersResponse = await fetch(SUBGRAPH_URL, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
query: `{
|
||||
useEffect(() => {
|
||||
const fetchLeaderboards = async () => {
|
||||
try {
|
||||
// Fetch top earners
|
||||
const earnersResponse = await fetch(SUBGRAPH_URL, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
query: `{
|
||||
armies(first: 10, orderBy: profitPerSecond, orderDirection: desc) {
|
||||
player {
|
||||
id
|
||||
@ -32,83 +41,177 @@ const Leaderboard = () => {
|
||||
anointedLevel
|
||||
championLevel
|
||||
}
|
||||
}`
|
||||
})
|
||||
})
|
||||
const earnersData = await earnersResponse.json()
|
||||
setTopEarners({ armies: earnersData.data.armies })
|
||||
}`,
|
||||
}),
|
||||
});
|
||||
const earnersData = await earnersResponse.json();
|
||||
setTopEarners({ armies: earnersData.data.armies });
|
||||
|
||||
// Fetch top raiders
|
||||
const raidersResponse = await fetch(SUBGRAPH_URL, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
query: `{
|
||||
// Fetch top raiders
|
||||
const raidersResponse = await fetch(SUBGRAPH_URL, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
query: `{
|
||||
players(first: 10, orderBy: numberOfRaids, orderDirection: desc) {
|
||||
id
|
||||
numberOfRaids
|
||||
totalMinted
|
||||
currentBalance
|
||||
}
|
||||
}`
|
||||
})
|
||||
})
|
||||
const raidersData = await raidersResponse.json()
|
||||
setTopRaiders({ players: raidersData.data.players })
|
||||
} catch (error) {
|
||||
console.error('Error fetching leaderboard:', error)
|
||||
}
|
||||
}
|
||||
}`,
|
||||
}),
|
||||
});
|
||||
const raidersData = await raidersResponse.json();
|
||||
setTopRaiders({ players: raidersData.data.players });
|
||||
|
||||
fetchLeaderboards()
|
||||
const interval = setInterval(fetchLeaderboards, 30000) // Refresh every 30 seconds
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
// Fetch bosses defeated
|
||||
const bossesDefeatedResponse = await fetch(SUBGRAPH_URL, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
query: `{
|
||||
players(first: 10, orderBy: bossesDefeated, orderDirection: desc) {
|
||||
id
|
||||
bossesDefeated
|
||||
}
|
||||
}`,
|
||||
}),
|
||||
});
|
||||
const bossesDefeatedData = await bossesDefeatedResponse.json();
|
||||
setBossesDefeated({ players: bossesDefeatedData.data.players });
|
||||
|
||||
return (
|
||||
<div className={styles.leaderboard}>
|
||||
<h2 className={styles.title}>Leaderboard</h2>
|
||||
|
||||
<div className={styles.tabs}>
|
||||
<button
|
||||
className={`${styles.tab} ${activeTab === 'earners' ? styles.active : ''}`}
|
||||
onClick={() => setActiveTab('earners')}
|
||||
>
|
||||
Top Earners
|
||||
</button>
|
||||
<button
|
||||
className={`${styles.tab} ${activeTab === 'raiders' ? styles.active : ''}`}
|
||||
onClick={() => setActiveTab('raiders')}
|
||||
>
|
||||
Top Raiders
|
||||
</button>
|
||||
</div>
|
||||
// Fetch player prestige
|
||||
const playerPrestigeResponse = await fetch(SUBGRAPH_URL, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
query: `{
|
||||
players(first: 10, orderBy: prestigeLevel, orderDirection: desc) {
|
||||
id
|
||||
prestigeLevel
|
||||
}
|
||||
}`,
|
||||
}),
|
||||
});
|
||||
const playerPrestigeData = await playerPrestigeResponse.json();
|
||||
setPlayerPrestige({ players: playerPrestigeData.data.players });
|
||||
} catch (error) {
|
||||
console.error("Error fetching leaderboard:", error);
|
||||
}
|
||||
};
|
||||
|
||||
{activeTab === 'earners' && (
|
||||
<div className={styles.list}>
|
||||
{topEarners?.armies.map((army, index) => (
|
||||
<div key={army.player.id} className={styles.item}>
|
||||
<span className={styles.rank}>#{index + 1}</span>
|
||||
<span className={styles.address}>{army.player.id.slice(0, 6)}...{army.player.id.slice(-4)}</span>
|
||||
<span className={styles.stat}>{formatUnits(BigInt(army.profitPerSecond), 4)} GELD/s</span>
|
||||
fetchLeaderboards();
|
||||
const interval = setInterval(fetchLeaderboards, 30000); // Refresh every 30 seconds
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={styles.leaderboard}>
|
||||
<h2 className={styles.title}>Leaderboard</h2>
|
||||
|
||||
<div className={styles.tabs}>
|
||||
<button
|
||||
className={`${styles.tab} ${
|
||||
activeTab === "earners" ? styles.active : ""
|
||||
}`}
|
||||
onClick={() => setActiveTab("earners")}
|
||||
>
|
||||
Top Earners
|
||||
</button>
|
||||
<button
|
||||
className={`${styles.tab} ${
|
||||
activeTab === "raiders" ? styles.active : ""
|
||||
}`}
|
||||
onClick={() => setActiveTab("raiders")}
|
||||
>
|
||||
Top Raiders
|
||||
</button>
|
||||
<button
|
||||
className={`${styles.tab} ${
|
||||
activeTab === "bosses" ? styles.active : ""
|
||||
}`}
|
||||
onClick={() => setActiveTab("bosses")}
|
||||
>
|
||||
Top Boss Slayers
|
||||
</button>
|
||||
<button
|
||||
className={`${styles.tab} ${
|
||||
activeTab === "prestige" ? styles.active : ""
|
||||
}`}
|
||||
onClick={() => setActiveTab("prestige")}
|
||||
>
|
||||
Top Players by Prestige
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'raiders' && (
|
||||
<div className={styles.list}>
|
||||
{topRaiders?.players.map((player, index) => (
|
||||
<div key={player.id} className={styles.item}>
|
||||
<span className={styles.rank}>#{index + 1}</span>
|
||||
<span className={styles.address}>{player.id.slice(0, 6)}...{player.id.slice(-4)}</span>
|
||||
<span className={styles.stat}>{player.numberOfRaids} raids</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{activeTab === "earners" && (
|
||||
<div className={styles.list}>
|
||||
{topEarners?.armies.map((army, index) => (
|
||||
<div key={army.player.id} className={styles.item}>
|
||||
<span className={styles.rank}>#{index + 1}</span>
|
||||
<span className={styles.address}>
|
||||
{army.player.id.slice(0, 6)}...
|
||||
{army.player.id.slice(-4)}
|
||||
</span>
|
||||
<span className={styles.stat}>
|
||||
{formatUnits(BigInt(army.profitPerSecond), 4)}{" "}
|
||||
GELD/s
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
export default Leaderboard
|
||||
{activeTab === "raiders" && (
|
||||
<div className={styles.list}>
|
||||
{topRaiders?.players.map((player, index) => (
|
||||
<div key={player.id} className={styles.item}>
|
||||
<span className={styles.rank}>#{index + 1}</span>
|
||||
<span className={styles.address}>
|
||||
{player.id.slice(0, 6)}...{player.id.slice(-4)}
|
||||
</span>
|
||||
<span className={styles.stat}>
|
||||
{player.numberOfRaids} raids
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === "bosses" && (
|
||||
<div className={styles.list}>
|
||||
{bossesDefeated?.players.map((player, index) => (
|
||||
<div key={player.id} className={styles.item}>
|
||||
<span className={styles.rank}>#{index + 1}</span>
|
||||
<span className={styles.address}>
|
||||
{player.id.slice(0, 6)}...{player.id.slice(-4)}
|
||||
</span>
|
||||
<span className={styles.stat}>
|
||||
{player.bossesDefeated} Bosses Slain
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === "prestige" && (
|
||||
<div className={styles.list}>
|
||||
{playerPrestige?.players.map((player, index) => (
|
||||
<div key={player.id} className={styles.item}>
|
||||
<span className={styles.rank}>#{index + 1}</span>
|
||||
<span className={styles.address}>
|
||||
{player.id.slice(0, 6)}...{player.id.slice(-4)}
|
||||
</span>
|
||||
<span className={styles.stat}>
|
||||
{player.prestigeLevel} Prestige Level
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Leaderboard;
|
||||
|
||||
@ -1,25 +1,31 @@
|
||||
export interface Player {
|
||||
id: string
|
||||
totalMinted: string
|
||||
currentBalance: string
|
||||
numberOfRaids: string
|
||||
army?: Army
|
||||
}
|
||||
|
||||
export interface Army {
|
||||
player: Player
|
||||
profitPerSecond: string
|
||||
projectedDailyEarnings: string
|
||||
molochDenierLevel: string
|
||||
apprenticeLevel: string
|
||||
anointedLevel: string
|
||||
championLevel: string
|
||||
}
|
||||
|
||||
export interface TopEarnersResponse {
|
||||
armies: Army[]
|
||||
}
|
||||
|
||||
export interface TopRaidersResponse {
|
||||
players: Player[]
|
||||
}
|
||||
id: string;
|
||||
totalMinted: string;
|
||||
currentBalance: string;
|
||||
numberOfRaids: string;
|
||||
army?: Army;
|
||||
bossesDefeated?: string;
|
||||
prestigeLevel: string;
|
||||
}
|
||||
|
||||
export interface Army {
|
||||
player: Player;
|
||||
profitPerSecond: string;
|
||||
projectedDailyEarnings: string;
|
||||
molochDenierLevel: string;
|
||||
apprenticeLevel: string;
|
||||
anointedLevel: string;
|
||||
championLevel: string;
|
||||
}
|
||||
|
||||
export interface TopEarnersResponse {
|
||||
armies: Army[];
|
||||
}
|
||||
|
||||
export interface TopRaidersResponse {
|
||||
players: Player[];
|
||||
}
|
||||
|
||||
export interface PlayerResponse {
|
||||
players: Player[];
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user