import React, { createContext, ReactNode, useCallback, useContext, useEffect, useRef, useState, } from "react"; import { useAccount, useReadContract, useWriteContract } from "wagmi"; import contractAbi from "../../../out/RaidGeld.sol/RaidGeld.json"; import { Hash, parseEther } from "viem"; import contracts from "../../contract_address"; import WaitingForTxModal from "../components/WaitingForTxModal"; import BossOutcomeModal from "../components/BossOutcomeModal"; import styles from "../styles/Background.module.css"; import { coinSound } from "../utils/soundsEffect"; const { contractAddress, daoTokenAddress } = contracts; const abi = contractAbi.abi; export type UnitType = 0 | 1 | 2 | 3; export type BossLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6; export interface Player { created_at: bigint; last_raided_at: bigint; total_minted: bigint; total_rewards: bigint; n_runs: number; prestige_level: number; is_registered: boolean; has_active_session: boolean; } export interface Army { anointed: { level: number }; apprentice: { level: number }; champion: { level: number }; moloch_denier: { level: number }; profit_per_second: bigint; } export interface Boss { level: BossLevel; variants: [ BossLevel, BossLevel, BossLevel, BossLevel, BossLevel, BossLevel, BossLevel ]; } export interface LastBossResult { level: BossLevel; variant: BossLevel; battled_at: bigint; reward: bigint; prestigeGained: boolean; } export interface PlayerContextType { isRegistered: boolean; player: null | Player; army: null | Army; boss: null | Boss; lastBossResult: null | LastBossResult; balance: bigint; register: (arg: "ETH" | "RGCVII") => void; raid: () => void; battleWithBoss: () => void; addUnit: (unit: UnitType, amount?: number) => void; } const PlayerContext = createContext({ isRegistered: false, player: null, army: null, boss: null, lastBossResult: null, balance: BigInt(0), register: () => {}, raid: () => {}, battleWithBoss: () => {}, addUnit: () => {}, }); const PlayerProvider = ({ children }: { children: ReactNode }) => { const { address, isConnected } = useAccount(); const { writeContract, error } = useWriteContract(); const [[txHash, callbackFn], setHashAndCallback] = useState< [Hash | null, () => void] >([null, () => {}]); const [bossBattledModalOpen, setBossBattlesModalOpen] = useState(false); const hasFetchedLastBossFirstTime = useRef(false); useEffect(() => { console.warn(error); }, [error]); const resetHashAndCallback = useCallback(() => { setHashAndCallback([null, () => {}]); }, []); const { data: isRegistered } = useReadContract({ address: contractAddress, abi, functionName: "isRegistered", args: [address], query: { enabled: isConnected, refetchInterval: 10000, }, }); const { data: balance } = useReadContract({ address: contractAddress, abi, functionName: "balanceOf", args: [address], query: { refetchInterval: 10000, enabled: isConnected, }, }); const { data: player } = useReadContract({ address: contractAddress, abi, functionName: "getPlayer", args: [address], query: { enabled: isConnected, refetchInterval: 10000, }, }); const { data: army } = useReadContract({ address: contractAddress, abi, functionName: "getArmy", args: [address], query: { enabled: isConnected, refetchInterval: 10000, }, }); const { data: boss } = useReadContract({ address: contractAddress, abi, functionName: "getBoss", args: [address], query: { enabled: isConnected, refetchInterval: 10000, }, }); const { data: lastBossResult } = useReadContract({ address: contractAddress, abi, functionName: "getLastBossResult", args: [address], query: { enabled: isConnected, refetchInterval: 10000, }, }); const register = useCallback( (arg: "RGCVII" | "ETH") => { if (arg === "ETH") { writeContract( { abi, address: contractAddress, functionName: "register_eth", value: parseEther("0.00045"), }, { onSuccess: (hash) => { setHashAndCallback([hash, resetHashAndCallback]); }, onError: () => resetHashAndCallback(), } ); } else if (arg === "RGCVII") { writeContract( { abi, address: daoTokenAddress, functionName: "approve", args: [contractAddress, parseEther("400")], }, { onSuccess: (hash) => { setHashAndCallback([ hash, () => writeContract( { abi, address: contractAddress, functionName: "register_dao", }, { onSuccess: (hash) => { setHashAndCallback([hash, resetHashAndCallback]); }, onError: () => resetHashAndCallback(), } ), ]); }, onError: () => resetHashAndCallback(), } ); } }, [writeContract, resetHashAndCallback] ); const raid = useCallback(() => { writeContract( { abi, address: contractAddress, functionName: "raid", }, { onSuccess: (hash) => { setHashAndCallback([hash, resetHashAndCallback]); }, onError: () => resetHashAndCallback(), } ); }, [writeContract, resetHashAndCallback]); const addUnit = useCallback( (unit: UnitType) => { writeContract( { abi, address: contractAddress, functionName: "addUnit", args: [unit, 1], }, { onSuccess: () => { coinSound(); }, onError: () => resetHashAndCallback(), } ); }, [writeContract, resetHashAndCallback] ); const battleWithBoss = useCallback(() => { writeContract( { abi, address: contractAddress, functionName: "battle_with_boss", }, { onSuccess: (hash) => { setHashAndCallback([hash, () => resetHashAndCallback()]); }, onError: () => resetHashAndCallback(), } ); }, [writeContract, resetHashAndCallback]); useEffect(() => { if (lastBossResult != null) { if (hasFetchedLastBossFirstTime.current) { setBossBattlesModalOpen(true); } else { hasFetchedLastBossFirstTime.current = true; } } }, [lastBossResult]); return ( {children}
{txHash && } {bossBattledModalOpen && ( )}
); }; export const usePlayer = () => { return useContext(PlayerContext); }; export default PlayerProvider;