Skip to content

Commit 1193fe7

Browse files
committed
update scripts
1 parent f294081 commit 1193fe7

File tree

14 files changed

+795
-139
lines changed

14 files changed

+795
-139
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22
"1": {
33
"name": "mainnet",
44
"contracts": {
5-
"MyContract": ""
5+
"Lottery": ""
66
}
77
},
88
"11155111": {
99
"name": "sepolia",
1010
"contracts": {
11-
"MyContract": ""
11+
"Lottery": "0x783444D9F6bB3b9e34393A401aC8E824E016Ed43"
1212
}
1313
},
1414
"31337": {
1515
"name": "localhost",
1616
"contracts": {
17-
"MyContract": ""
17+
"Lottery": ""
1818
}
1919
}
2020
}

contracts/script/Deploy.s.sol

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,46 @@
1-
// SPDX-License-Identifier: MIT
2-
pragma solidity ^0.8.19;
3-
4-
import "../../lib/forge-std/src/Script.sol";
5-
import "../src/MyContract.sol";
61

2+
pragma solidity ^0.8.19;
3+
import "forge-std/Script.sol";
4+
import "forge-std/StdJson.sol";
5+
import "../src/Lottery.sol";
76
contract DeployScript is Script {
8-
function run() external returns (MyContract) {
9-
uint256 deployerPrivateKey;
7+
using stdJson for string;
8+
9+
function run() external {
10+
// Load the private key from the .env file
11+
uint256 deployerPrivateKey = vm.envUint("LOCAL_PRIVATE_KEY");
1012

11-
// Determine which private key to use based on chain ID
12-
if (block.chainid == 1) {
13-
// Mainnet
14-
deployerPrivateKey = vm.envUint("PRIVATE_KEY");
15-
} else if (block.chainid == 11155111) {
16-
// Sepolia
17-
deployerPrivateKey = vm.envUint("SEPOLIA_PRIVATE_KEY");
18-
} else {
19-
// Local (Anvil/Hardhat)
20-
deployerPrivateKey = vm.envUint("LOCAL_PRIVATE_KEY");
21-
}
13+
string memory deploymentsPath = "contracts/deployments.json";
2214

15+
// --- DEPLOYMENT ---
2316
vm.startBroadcast(deployerPrivateKey);
17+
18+
// 1. Deploy the Lottery contract
19+
Lottery lottery = new Lottery();
2420

25-
MyContract myContract = new MyContract();
21+
// 2. Initialize the lottery with a seed value (like in the old script)
22+
uint8 seed = 9;
23+
lottery.initialiseLottery(seed);
24+
25+
vm.stopBroadcast();
26+
27+
// --- UPDATE DEPLOYMENTS FILE ---
2628

27-
console.log("MyContract deployed to:", address(myContract));
28-
console.log("Network:", block.chainid);
29+
// 3. Get the current chain ID
30+
string memory chainId = vm.toString(block.chainid);
2931

30-
vm.stopBroadcast();
32+
// 4. Define the key path for the JSON update
33+
// Example: "31337.contracts.Lottery"
34+
string memory key = string.concat(chainId, ".contracts.Lottery");
3135

32-
return myContract;
36+
// 5. Use the serializeAddress cheatcode to update the JSON file.
37+
// This reads the file, sets the value at the specified key, and writes it back.
38+
vm.serializeAddress(deploymentsPath, key, address(lottery));
39+
40+
// 6. Log the results to the console
41+
console.log("");
42+
console.log("Lottery contract deployed to:", address(lottery));
43+
console.log("Initialised with seed:", seed);
44+
console.log("Updated contracts/deployments.json with new address.");
3345
}
34-
}
46+
}

contracts/src/MyContract.sol

Lines changed: 0 additions & 13 deletions
This file was deleted.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"contracts:test:fork": "forge test --fork-url $MAINNET_RPC_URL",
2121

2222

23-
"deploy:local": "forge script contracts/script/Deploy.s.sol --broadcast",
23+
"deploy:local": "forge script contracts/script/Deploy.s.sol --rpc-url local --broadcast",
2424
"deploy:sepolia": "forge script contracts/script/Deploy.s.sol --rpc-url sepolia --broadcast --verify",
2525
"deploy:mainnet": "forge script contracts/script/Deploy.s.sol --rpc-url mainnet --broadcast --verify",
2626

src/App.tsx

Lines changed: 96 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,103 @@
1-
import { useAccount, useConnect, useDisconnect } from 'wagmi'
1+
// FILE: src/App.tsx
2+
// PURPOSE: Main application component, lays out the UI and manages state.
3+
4+
import { useAccount, useConfig } from 'wagmi';
5+
import { readContracts } from 'wagmi/actions';
6+
import { useState, useEffect, useCallback } from 'react';
7+
import { lotteryContractConfig } from './wagmi';
8+
import { Team, useGetTeamCount, useLotteryEvents } from './hooks/useLottery';
9+
10+
import { Header } from './components/Header';
11+
import { Connect } from './components/Connect';
12+
import { RegisterTeam } from './components/RegisterTeam';
13+
import { MakeGuess } from './components/MakeGuess';
14+
import { TeamsTable } from './components/TeamsTable';
215

316
function App() {
4-
const account = useAccount()
5-
const { connectors, connect, status, error } = useConnect()
6-
const { disconnect } = useDisconnect()
17+
const { isConnected, chain } = useAccount();
18+
const wagmiConfig = useConfig();
19+
const [teams, setTeams] = useState<Team[]>([]);
20+
const [isLoadingTeams, setIsLoadingTeams] = useState(false);
21+
const [refetchTrigger, setRefetchTrigger] = useState(0);
22+
23+
const { data: teamCount, refetch: refetchTeamCount } = useGetTeamCount();
24+
25+
const fetchAllTeams = useCallback(async () => {
26+
// --- FIX: Only fetch if connected and teamCount is a valid number ---
27+
if (!isConnected || typeof teamCount !== 'bigint' || !chain) {
28+
setTeams([]); // Clear teams if not connected or no data
29+
return;
30+
}
31+
32+
const count = Number(teamCount);
33+
if (count === 0) {
34+
setTeams([]);
35+
setIsLoadingTeams(false);
36+
return;
37+
}
38+
39+
setIsLoadingTeams(true);
40+
try {
41+
const contractAddress = lotteryContractConfig.address(chain.id);
42+
if (!contractAddress) {
43+
throw new Error("Contract address not found for this chain.");
44+
}
45+
46+
const contracts = Array.from({ length: count }, (_, i) => ({
47+
...lotteryContractConfig,
48+
address: contractAddress,
49+
functionName: 'getTeamDetails',
50+
args: [BigInt(i)],
51+
}));
52+
53+
const results = await readContracts(wagmiConfig, { contracts });
54+
55+
const validResults: Team[] = results
56+
.filter(r => r.status === 'success' && r.result)
57+
.map(r => {
58+
const [name, address, score] = r.result as [string, `0x${string}`, bigint];
59+
return { name, address, score: Number(score) };
60+
});
61+
62+
setTeams(validResults);
63+
} catch (e) {
64+
console.error("Failed to fetch teams:", e);
65+
setTeams([]);
66+
} finally {
67+
setIsLoadingTeams(false);
68+
}
69+
}, [teamCount, chain, isConnected, wagmiConfig]);
70+
71+
72+
// Refetch teams when the dependencies of fetchAllTeams change
73+
useEffect(() => {
74+
fetchAllTeams();
75+
}, [fetchAllTeams]);
76+
77+
// Use the event hook to trigger a refetch
78+
useLotteryEvents(fetchAllTeams);
779

880
return (
9-
<>
10-
<div>
11-
<h2>Account</h2>
12-
13-
<div>
14-
status: {account.status}
15-
<br />
16-
addresses: {JSON.stringify(account.addresses)}
17-
<br />
18-
chainId: {account.chainId}
81+
<div className="app-container">
82+
<Header refetchTrigger={refetchTrigger} />
83+
<main className="main-content">
84+
<div className="content-grid">
85+
<div className="forms-column">
86+
<Connect />
87+
{isConnected && (
88+
<>
89+
<RegisterTeam />
90+
<MakeGuess />
91+
</>
92+
)}
93+
</div>
94+
<div className="table-column">
95+
<TeamsTable teams={teams} isLoading={isLoadingTeams} />
96+
</div>
1997
</div>
20-
21-
{account.status === 'connected' && (
22-
<button type="button" onClick={() => disconnect()}>
23-
Disconnect
24-
</button>
25-
)}
26-
</div>
27-
28-
<div>
29-
<h2>Connect</h2>
30-
{connectors.map((connector) => (
31-
<button
32-
key={connector.uid}
33-
onClick={() => connect({ connector })}
34-
type="button"
35-
>
36-
{connector.name}
37-
</button>
38-
))}
39-
<div>{status}</div>
40-
<div>{error?.message}</div>
41-
</div>
42-
</>
43-
)
98+
</main>
99+
</div>
100+
);
44101
}
45102

46-
export default App
103+
export default App;

src/components/Connect.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// FILE: src/components/Connect.tsx
2+
// PURPOSE: Handles wallet connection, displays account info, and the disconnect button.
3+
4+
import { useAccount, useConnect, useDisconnect } from 'wagmi'
5+
6+
export function Connect() {
7+
const account = useAccount()
8+
const { connectors, connect, status, error } = useConnect()
9+
const { disconnect } = useDisconnect()
10+
11+
return (
12+
<div className="wallet-info-card">
13+
<h2>Wallet Information</h2>
14+
<div>
15+
Status: <strong>{account.status}</strong>
16+
</div>
17+
{account.status === 'connected' && (
18+
<>
19+
<div>Addresses: {account.addresses?.join(', ')}</div>
20+
<div>Chain ID: {account.chainId}</div>
21+
<button type="button" onClick={() => disconnect()} className="button-disconnect">
22+
Disconnect
23+
</button>
24+
</>
25+
)}
26+
27+
{account.status === 'disconnected' && (
28+
<div className="connector-buttons">
29+
<h3>Connect Wallet</h3>
30+
{connectors.map((connector) => (
31+
<button
32+
key={connector.uid}
33+
onClick={() => connect({ connector })}
34+
type="button"
35+
className="button"
36+
>
37+
{connector.name}
38+
</button>
39+
))}
40+
</div>
41+
)}
42+
43+
{error && <div>{error.message}</div>}
44+
</div>
45+
)
46+
}

src/components/Header.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// FILE: src/components/Header.tsx
2+
// PURPOSE: Displays the main header and lottery contract balance.
3+
4+
import { useGetLotteryBalance } from '../hooks/useLottery'
5+
import { formatEther } from 'viem'
6+
import { useAccount } from 'wagmi'
7+
8+
export function Header({ refetchTrigger }: { refetchTrigger: number }) {
9+
const { chain } = useAccount();
10+
const balance = useGetLotteryBalance(refetchTrigger);
11+
12+
return (
13+
<nav className="navbar">
14+
<h1>Lottery Game</h1>
15+
{chain && balance && (
16+
<div className="navbar-balance">
17+
Lottery Balance: {Number(formatEther(balance.value)).toFixed(4)} {balance.symbol}
18+
</div>
19+
)}
20+
</nav>
21+
)
22+
}

0 commit comments

Comments
 (0)