added faucet
This commit is contained in:
parent
f410f09d67
commit
b540e1372e
@ -5,12 +5,12 @@ import clrTokenJson from './CLRToken/CLRToken.json';
|
||||
|
||||
const clearNetABI = (clearNetJson as any).abi ?? clearNetJson;
|
||||
const clrTokenABI = (clrTokenJson as any).abi ?? clrTokenJson;
|
||||
const clearNetAddress = "0x265da498da1de3f22bb57c717d14806e4884cdda";
|
||||
const clearNetAddress = "0x0305e95225f65db13e98c775dbb95b98178ae73b";
|
||||
const clrTokenAddress = "0xf1664c17887767c8f58695846babb349ca61d2e9";
|
||||
// const clearNetAddress = "0x9a9f2ccfde556a7e9ff0848998aa4a0cfd8863ae";
|
||||
// const clrTokenAddress = "0x5fc8d32690cc91d4c39d9d3abcbd16989f875707";
|
||||
|
||||
const DEFAULT_MIN_STAKE = BigInt(10000) * BigInt(1e18); // 10000 CLR
|
||||
const DEFAULT_MIN_STAKE = BigInt(100) * BigInt(1e18); // 100 CLR
|
||||
|
||||
|
||||
export const getActiveNodes = async (provider: any): Promise<Node[]> => {
|
||||
|
||||
87
app/Components/Faucet.tsx
Normal file
87
app/Components/Faucet.tsx
Normal file
@ -0,0 +1,87 @@
|
||||
import React from "react";
|
||||
import { Button, Box, Typography, Alert } from "@mui/material";
|
||||
import useAuth from '~/hooks/useAuth';
|
||||
import { Web3 } from 'web3';
|
||||
|
||||
const FAUCET_ADDRESS = "0xA86b97D7CF0c00cd0e82bBDCe9F06d689cFb12b5";
|
||||
|
||||
const FAUCET_ABI = [
|
||||
{
|
||||
inputs: [],
|
||||
name: "claim",
|
||||
outputs: [],
|
||||
stateMutability: "nonpayable",
|
||||
type: "function",
|
||||
},
|
||||
];
|
||||
|
||||
export default function FaucetClaim() {
|
||||
const [status, setStatus] = React.useState<string | null>(null);
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
const { auth } = useAuth();
|
||||
const account = auth?.accounts?.[0];
|
||||
const isAuthed = Boolean(account);
|
||||
|
||||
const claimFaucet = async () => {
|
||||
if (!isAuthed) {
|
||||
setStatus("Please connect your wallet first.");
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
setStatus("Preparing transaction...");
|
||||
try {
|
||||
const provider = auth.providerWithInfo.provider;
|
||||
const web3 = new Web3(provider);
|
||||
const contract = new web3.eth.Contract(FAUCET_ABI, FAUCET_ADDRESS);
|
||||
|
||||
setStatus("Sending claim transaction...");
|
||||
const tx = await contract.methods.claim().send({ from: account });
|
||||
|
||||
setStatus("Transaction Hash: " + tx.transactionHash + '\n' + "Claim confirmed. Check your balance.");
|
||||
} catch (err: any) {
|
||||
setStatus("Claim failed: " + (err?.message ?? String(err)));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ fontFamily: "sans-serif", maxWidth: 640, margin: "24px auto", padding: "0 16px" }}>
|
||||
<Typography variant="h5" gutterBottom>
|
||||
CLR Faucet Claim
|
||||
</Typography>
|
||||
|
||||
<Typography sx={{ mt: 1 }}>
|
||||
Network: <strong>Sepolia</strong>
|
||||
</Typography>
|
||||
|
||||
<Typography sx={{ mt: 1 }}>
|
||||
Faucet: <code>{FAUCET_ADDRESS}</code>
|
||||
</Typography>
|
||||
|
||||
<Typography sx={{ mt: 1 }}>
|
||||
Token: <code>0xf1664c17887767c8f58695846babb349ca61d2e9</code>
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ display: "flex", gap: 1, mt: 3 }}>
|
||||
|
||||
<Button variant="outlined" onClick={claimFaucet} disabled={loading || !isAuthed}>
|
||||
{loading ? "Processing..." : "Claim CLR"}
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
{account && (
|
||||
<Typography sx={{ mt: 2, fontSize: 13, color: "text.secondary" }}>
|
||||
Connected: {account}
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
{status && (
|
||||
<Alert severity="info" sx={{ mt: 2 }}>
|
||||
{status}
|
||||
</Alert>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@ -30,7 +30,7 @@ export default function ButtonAppBar() {
|
||||
};
|
||||
|
||||
const register = async () => {
|
||||
const clr_deposit_amount = BigInt(10000) * BigInt(1e18); // 10000 CLR
|
||||
const clr_deposit_amount = BigInt(100) * BigInt(1e18); // 100 CLR
|
||||
await approveCLRTokenSpending(auth.providerWithInfo.provider, account!);
|
||||
await openPaymentChannel(auth.providerWithInfo.provider, account!, clr_deposit_amount);
|
||||
setRegistered(true);
|
||||
@ -67,6 +67,14 @@ export default function ButtonAppBar() {
|
||||
Home
|
||||
</Typography>
|
||||
|
||||
<Typography
|
||||
component={NavLink as any}
|
||||
to="/faucet"
|
||||
sx={{ color: 'inherit', textDecoration: 'none' }}
|
||||
>
|
||||
Faucet
|
||||
</Typography>
|
||||
|
||||
<Typography
|
||||
component={NavLink as any}
|
||||
to="/about"
|
||||
|
||||
95
app/Components/faucet-claim.html
Normal file
95
app/Components/faucet-claim.html
Normal file
@ -0,0 +1,95 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>CLR Faucet Claim</title>
|
||||
<style>
|
||||
body { font-family: sans-serif; max-width: 640px; margin: 24px auto; padding: 0 16px; }
|
||||
button { padding: 10px 16px; font-size: 16px; cursor: pointer; }
|
||||
.row { margin: 12px 0; }
|
||||
#status { margin-top: 12px; white-space: pre-line; }
|
||||
code { background: #f4f4f4; padding: 2px 4px; border-radius: 4px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>CLR Faucet Claim</h2>
|
||||
<div class="row">Network: <strong>Sepolia</strong></div>
|
||||
<div class="row">Faucet: <code id="faucetAddr">0xA86b97D7CF0c00cd0e82bBDCe9F06d689cFb12b5</code></div>
|
||||
<div class="row">Token: <code>0xf1664c17887767c8f58695846babb349ca61d2e9</code></div>
|
||||
|
||||
<div class="row">
|
||||
<button id="connect">Connect Wallet</button>
|
||||
<button id="claim" disabled>Claim 100 CLR</button>
|
||||
</div>
|
||||
<div id="status"></div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/ethers@6.13.1/dist/ethers.umd.min.js"></script>
|
||||
<script>
|
||||
// Check if ethers loaded
|
||||
if (typeof ethers === 'undefined') {
|
||||
document.getElementById("status").textContent = "Error: ethers.js failed to load. Check internet connection.";
|
||||
throw new Error("ethers.js not loaded");
|
||||
}
|
||||
|
||||
// ---------------------- CONFIG ----------------------
|
||||
const FAUCET_ADDRESS = "0xA86b97D7CF0c00cd0e82bBDCe9F06d689cFb12b5"; // set your deployed faucet address
|
||||
const FAUCET_ABI = ["function claim() external"];
|
||||
// ----------------------------------------------------
|
||||
|
||||
const statusEl = document.getElementById("status");
|
||||
const connectBtn = document.getElementById("connect");
|
||||
const claimBtn = document.getElementById("claim");
|
||||
document.getElementById("faucetAddr").textContent = FAUCET_ADDRESS;
|
||||
|
||||
function log(msg) {
|
||||
statusEl.textContent = msg;
|
||||
}
|
||||
|
||||
async function connect() {
|
||||
if (!window.ethereum) {
|
||||
log("Please install MetaMask.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
log("Connecting wallet...");
|
||||
await window.ethereum.request({ method: "eth_requestAccounts" });
|
||||
const provider = new ethers.BrowserProvider(window.ethereum);
|
||||
const network = await provider.getNetwork();
|
||||
if (network.chainId !== 11155111n) {
|
||||
log("Please switch MetaMask to Sepolia.");
|
||||
return;
|
||||
}
|
||||
log("Wallet connected on Sepolia.");
|
||||
claimBtn.disabled = false;
|
||||
return provider;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
log("Connect failed: " + (err?.message || err));
|
||||
}
|
||||
}
|
||||
|
||||
async function claim() {
|
||||
try {
|
||||
claimBtn.disabled = true;
|
||||
log("Sending claim transaction...");
|
||||
const provider = new ethers.BrowserProvider(window.ethereum);
|
||||
const signer = await provider.getSigner();
|
||||
const faucet = new ethers.Contract(FAUCET_ADDRESS, FAUCET_ABI, signer);
|
||||
const tx = await faucet.claim();
|
||||
log("Pending tx: " + tx.hash + "\nWaiting for confirmation...");
|
||||
await tx.wait();
|
||||
log("✅ Claim confirmed! Tx: " + tx.hash);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
log("Claim failed: " + (err?.shortMessage || err?.message || err));
|
||||
} finally {
|
||||
claimBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
connectBtn.onclick = connect;
|
||||
claimBtn.onclick = claim;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -3,5 +3,6 @@ import { type RouteConfig, index, route } from "@react-router/dev/routes";
|
||||
export default [
|
||||
index("routes/home.tsx"),
|
||||
route("wallets", "routes/wallets.tsx"),
|
||||
route("about", "routes/about.tsx")
|
||||
route("about", "routes/about.tsx"),
|
||||
route("faucet", "routes/faucet.tsx")
|
||||
] satisfies RouteConfig;
|
||||
|
||||
7
app/routes/faucet.tsx
Normal file
7
app/routes/faucet.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import FaucetClaim from "~/Components/Faucet";
|
||||
|
||||
export default function FaucetPage() {
|
||||
return(
|
||||
<FaucetClaim />
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user