mirror of
https://github.com/averel10/crypto_clash.git
synced 2026-03-12 19:08:11 +01:00
added subpages for helloworld and clash, added game contract to config.json for usage in frontend
This commit is contained in:
245
crypto_clash_frontend/app/hello_world/page.tsx
Normal file
245
crypto_clash_frontend/app/hello_world/page.tsx
Normal file
@@ -0,0 +1,245 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import Web3 from "web3";
|
||||
|
||||
|
||||
|
||||
export default function Home() {
|
||||
const [config, setConfig] = useState<Config | null>(null);
|
||||
const [web3, setWeb3] = useState<Web3 | null>(null);
|
||||
const [contract, setContract] = useState<any>(null);
|
||||
const [message, setMessage] = useState<string>("");
|
||||
const [newMessage, setNewMessage] = useState<string>("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string>("");
|
||||
const [account, setAccount] = useState<string>("");
|
||||
|
||||
// Initialize Web3 and contract
|
||||
useEffect(() => {
|
||||
const loadConfig = async () => {
|
||||
try {
|
||||
const response = await fetch("/crypto_clash/config.json");
|
||||
const data = await response.json();
|
||||
setConfig(data);
|
||||
|
||||
// Initialize Web3
|
||||
const web3Instance = new Web3(data.API_URL);
|
||||
setWeb3(web3Instance);
|
||||
|
||||
// Create contract instance
|
||||
const contractInstance = new web3Instance.eth.Contract(
|
||||
data.ABI,
|
||||
data.CONTRACT_ADDRESS
|
||||
);
|
||||
setContract(contractInstance);
|
||||
|
||||
// Try to get connected account (if MetaMask or similar is available)
|
||||
if (typeof window !== "undefined" && (window as any).ethereum) {
|
||||
try {
|
||||
const accounts = await (window as any).ethereum.request({
|
||||
method: "eth_requestAccounts",
|
||||
});
|
||||
setAccount(accounts[0]);
|
||||
|
||||
// Get the network ID from the RPC endpoint
|
||||
const networkId = await web3Instance.eth.net.getId();
|
||||
const currentChainId = await (window as any).ethereum.request({
|
||||
method: "eth_chainId",
|
||||
});
|
||||
|
||||
// If on different network, notify user (they may need to switch networks manually)
|
||||
console.log(
|
||||
`RPC Network ID: ${networkId}, MetaMask Chain ID: ${currentChainId}`
|
||||
);
|
||||
} catch (err) {
|
||||
console.log("MetaMask not available or user denied access");
|
||||
}
|
||||
}
|
||||
|
||||
// Load initial message
|
||||
await readMessage(contractInstance);
|
||||
} catch (err) {
|
||||
setError(`Failed to load config: ${err}`);
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
loadConfig();
|
||||
}, []);
|
||||
|
||||
// Read message from contract
|
||||
const readMessage = async (contractInstance: any) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError("");
|
||||
const result = await contractInstance.methods.message().call();
|
||||
setMessage(result);
|
||||
} catch (err) {
|
||||
setError(`Failed to read message: ${err}`);
|
||||
console.error(err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Update message on contract
|
||||
const updateMessage = async () => {
|
||||
if (!newMessage.trim()) {
|
||||
setError("Please enter a message");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
setError("");
|
||||
|
||||
if (!web3 || !contract) {
|
||||
throw new Error("Web3 or contract not initialized");
|
||||
}
|
||||
|
||||
// Check if MetaMask is available
|
||||
if (!account && typeof window !== "undefined" && !(window as any).ethereum) {
|
||||
throw new Error(
|
||||
"MetaMask not available. Please install MetaMask to update the message."
|
||||
);
|
||||
}
|
||||
|
||||
// Create transaction
|
||||
const tx = contract.methods.update(newMessage);
|
||||
const gas = await tx.estimateGas({ from: account });
|
||||
|
||||
console.log(await web3.eth.net.getId());
|
||||
|
||||
// Send transaction via MetaMask
|
||||
const result = await (window as any).ethereum.request({
|
||||
method: "eth_sendTransaction",
|
||||
params: [
|
||||
{
|
||||
from: account,
|
||||
to: config?.CONTRACT_ADDRESS,
|
||||
data: tx.encodeABI(),
|
||||
gas: web3.utils.toHex(gas),
|
||||
chainId: web3.utils.toHex(await web3.eth.net.getId()),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
|
||||
setError(`Transaction sent: ${result}`);
|
||||
setNewMessage("");
|
||||
|
||||
// Wait a bit and refresh message from the RPC endpoint
|
||||
setTimeout(() => {
|
||||
if (contract) {
|
||||
readMessage(contract);
|
||||
}
|
||||
}, 2000);
|
||||
} catch (err) {
|
||||
setError(`Failed to update message: ${err}`);
|
||||
console.error(err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-slate-900 dark:to-slate-800 font-sans">
|
||||
<main className="w-full max-w-2xl mx-auto py-12 px-6">
|
||||
<div className="bg-white dark:bg-slate-800 rounded-lg shadow-lg p-8">
|
||||
<h1 className="text-4xl font-bold text-center mb-2 text-slate-900 dark:text-white">
|
||||
Smart Contract Interaction
|
||||
</h1>
|
||||
<p className="text-center text-slate-600 dark:text-slate-300 mb-8">
|
||||
Read and update messages on the blockchain
|
||||
</p>
|
||||
|
||||
{/* Status Section */}
|
||||
<div className="mb-8 p-4 bg-slate-100 dark:bg-slate-700 rounded-lg">
|
||||
<p className="text-sm text-slate-600 dark:text-slate-300">
|
||||
<span className="font-semibold">Connected Account:</span>{" "}
|
||||
{account ? `${account.slice(0, 6)}...${account.slice(-4)}` : "Not connected"}
|
||||
</p>
|
||||
<p className="text-sm text-slate-600 dark:text-slate-300 mt-2">
|
||||
<span className="font-semibold">Contract Address:</span>{" "}
|
||||
{config?.CONTRACT_ADDRESS}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Current Message Display */}
|
||||
<div className="mb-8 p-6 bg-indigo-50 dark:bg-slate-700 rounded-lg border-2 border-indigo-200 dark:border-slate-600">
|
||||
<h2 className="text-lg font-semibold text-slate-900 dark:text-white mb-2">
|
||||
Current Message:
|
||||
</h2>
|
||||
{loading && !message ? (
|
||||
<p className="text-slate-600 dark:text-slate-300 italic">Loading...</p>
|
||||
) : message ? (
|
||||
<p className="text-xl text-indigo-900 dark:text-indigo-200 break-words">
|
||||
{message}
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-slate-500 dark:text-slate-400 italic">
|
||||
No message yet
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Refresh Button */}
|
||||
<button
|
||||
onClick={() => readMessage(contract)}
|
||||
disabled={loading || !contract}
|
||||
className="w-full mb-6 py-3 px-4 bg-blue-500 hover:bg-blue-600 disabled:bg-slate-400 text-white font-semibold rounded-lg transition-colors"
|
||||
>
|
||||
{loading ? "Loading..." : "Refresh Message"}
|
||||
</button>
|
||||
|
||||
{/* Update Message Form */}
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-lg font-semibold text-slate-900 dark:text-white">
|
||||
Update Message:
|
||||
</h2>
|
||||
<input
|
||||
type="text"
|
||||
value={newMessage}
|
||||
onChange={(e) => setNewMessage(e.target.value)}
|
||||
placeholder="Enter new message..."
|
||||
className="w-full px-4 py-3 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-700 text-slate-900 dark:text-white placeholder-slate-400 dark:placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||||
/>
|
||||
<button
|
||||
onClick={updateMessage}
|
||||
disabled={loading || !account || !contract}
|
||||
className="w-full py-3 px-4 bg-green-500 hover:bg-green-600 disabled:bg-slate-400 text-white font-semibold rounded-lg transition-colors"
|
||||
>
|
||||
{loading ? "Updating..." : "Update Message"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Error/Status Messages */}
|
||||
{error && (
|
||||
<div
|
||||
className={`mt-6 p-4 rounded-lg ${
|
||||
error.includes("Transaction sent")
|
||||
? "bg-green-50 dark:bg-green-900 text-green-800 dark:text-green-200"
|
||||
: "bg-red-50 dark:bg-red-900 text-red-800 dark:text-red-200"
|
||||
}`}
|
||||
>
|
||||
<p className="text-sm break-words">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Info Section */}
|
||||
<div className="mt-8 p-4 bg-yellow-50 dark:bg-yellow-900 rounded-lg text-sm text-yellow-800 dark:text-yellow-200">
|
||||
<p className="font-semibold mb-2">ℹ️ Note:</p>
|
||||
<ul className="list-disc list-inside space-y-1">
|
||||
<li>To update messages, you need MetaMask or a compatible Web3 wallet</li>
|
||||
<li>Make sure your MetaMask is connected to the correct test network</li>
|
||||
<li>Reading messages is free and doesn't require a wallet</li>
|
||||
<li>Updates are written to the blockchain and may take time to confirm</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user