1
0
forked from mico/idle_moloch
idle_moloch/app/src/providers/PlayerProvider.tsx

268 lines
6.8 KiB
TypeScript

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"
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<PlayerContextType>({
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: 15,
}
});
const { data: balance, } = useReadContract({
address: contractAddress,
abi,
functionName: 'balanceOf',
args: [address],
query: {
refetchInterval: 15,
enabled: isConnected
}
});
const { data: player } = useReadContract({
address: contractAddress,
abi,
functionName: 'getPlayer',
args: [address],
query: {
enabled: isConnected,
refetchInterval: 15
}
});
const { data: army } = useReadContract({
address: contractAddress,
abi,
functionName: 'getArmy',
args: [address],
query: {
enabled: isConnected,
refetchInterval: 15
}
});
const { data: boss } = useReadContract({
address: contractAddress,
abi,
functionName: 'getBoss',
args: [address],
query: {
enabled: isConnected,
refetchInterval: 15
}
});
const { data: lastBossResult } = useReadContract({
address: contractAddress,
abi,
functionName: 'getLastBossResult',
args: [address],
query: {
enabled: isConnected,
refetchInterval: 15
}
});
console.log(balance, player, army, boss)
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]
})
}, [writeContract])
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 (
<PlayerContext.Provider value={{
isRegistered: isRegistered as boolean,
player: player as Player,
army: army as Army,
boss: boss as Boss,
balance: balance as bigint,
lastBossResult: lastBossResult as LastBossResult,
register,
raid,
addUnit,
battleWithBoss
}}>
{children}
<div className={`${(txHash || bossBattledModalOpen) ? styles.leaderboardOverlay : ""}`}>
{txHash && <WaitingForTxModal hash={txHash} callbackFn={callbackFn} />}
{bossBattledModalOpen && <BossOutcomeModal setIsOpen={setBossBattlesModalOpen} />}
</div>
</PlayerContext.Provider>
);
}
export const usePlayer = () => {
return useContext(PlayerContext);
}
export default PlayerProvider