<!DOCTYPE html>
<html>
<head>
<title>Sign-In with Ethereum</title>
<script src="https://cdn.jsdelivr.net/npm/ethers@6.13.3/dist/ethers.umd.min.js"></script>
<style>
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
}
.status {
margin-top: 20px;
padding: 10px;
border-radius: 5px;
}
.error {
background-color: #ffebee;
color: #c62828;
}
.success {
background-color: #e8f5e9;
color: #2e7d32;
}
.message-box {
margin-top: 20px;
padding: 15px;
background-color: #f5f5f5;
border-radius: 5px;
white-space: pre-wrap;
font-family: monospace;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
background-color: #2196f3;
color: white;
border: none;
border-radius: 5px;
}
button:hover {
background-color: #1976d2;
}
</style>
</head>
<body>
<div class="container">
<h1>Witness Aqua Chain With Metamask</h1>
<button onclick="login()">Connecting with MetaMask ...</button>
<div id="status" class="status"></div>
<div id="message" class="message-box"></div>
</div>
<script>
const ETH_CHAINID_MAP = {
'mainnet': '0x1',
'sepolia': '0xaa36a7',
'holesky': '0x4268',
};
const ETH_CHAIN_ADDRESSES_MAP = {
'mainnet': '0x45f59310ADD88E6d23ca58A0Fa7A55BEE6d2a611',
'sepolia': '0x45f59310ADD88E6d23ca58A0Fa7A55BEE6d2a611',
'holesky': '0x45f59310ADD88E6d23ca58A0Fa7A55BEE6d2a611',
};
function getChainId(key) {
const map = new Map();
map.set('mainnet', '0x1');
map.set('sepolia', '0xaa36a7');
map.set('holesky', '0x4268');
return map.get(key)
}
function getChainAddress(key) {
const map = new Map();
map.set('mainnet', '0x45f59310ADD88E6d23ca58A0Fa7A55BEE6d2a611');
map.set('sepolia', '0x45f59310ADD88E6d23ca58A0Fa7A55BEE6d2a611');
map.set('holesky', '0x45f59310ADD88E6d23ca58A0Fa7A55BEE6d2a611');
return map.get(key)
}
function showStatus(message, isError = false) {
const statusDiv = document.getElementById('status');
statusDiv.className = `status ${isError ? 'error' : 'success'}`;
statusDiv.textContent = message;
}
function showMessage(message) {
const messageDiv = document.getElementById('message');
messageDiv.textContent = message;
}
async function getPreviousVerificationHash() {
const response = await fetch('/message');
if (!response.ok) {
throw new Error('Failed to get previous verification hash');
}
return response.json();
}
async function getSignNetwork() {
const response = await fetch('/network');
if (!response.ok) {
throw new Error('Failed to get sign message');
}
return response.json();
}
async function switchNetwork(chainId) {
console.log(" switchNetwork chain " + chainId)
if (typeof window.ethereum !== 'undefined') {
console.log("etherium found")
try {
await window.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId }],
});
console.log("Network switched successfully");
} catch (error) {
showStatus("Network switched error", err.message);
console.log("Network switched error", error);
}
} else {
console.error("MetaMask is not installed.");
}
}
async function login() {
if (typeof window.ethereum === 'undefined') {
showStatus('Please install MetaMask!', true);
return;
}
try {
showStatus('Requesting account access...');
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
const account = accounts[0];
if (!account) {
alert("Please connect your wallet to continue");
return;
}
showStatus('Account connected: ' + account);
const { message } = await getPreviousVerificationHash();
let witness_event_verification_hash = message;
showMessage(witness_event_verification_hash);
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = provider.getSigner();
showStatus('Please sign the message in MetaMask...');
let network = "sepolia";
try {
const data = await getSignNetwork();
console.log("Response network " + data.network + " from network ", data)
network = data.network;
let chainId = ETH_CHAINID_MAP[network];
console.log("Chain id " + chainId);
await switchNetwork(chainId);
} catch (e) {
console.log("Error fetching network ", e)
}
let address = '0x9cef4ea1'
let address_data = getChainId(network);
if (address_data != undefined) {
address = address_data;
}
let contract_address = "0x45f59310ADD88E6d23ca58A0Fa7A55BEE6d2a611";
let chain_address = getChainAddress("sepolia");
if (chain_address != undefined) {
contract_address = chain_address;
}
console.log("network " + network + " addrss " + address + " chain contract address " + contract_address);
const params = [
{
from: account,
to: contract_address,
data: address + witness_event_verification_hash,
},
]
let txhash = await window.ethereum
.request({
method: 'eth_sendTransaction',
params: params,
})
console.log("Transaction hash is: ", txhash)
try {
showStatus('Transaction hash is: ' + txhash + ' , sending to server...');
const walletAddress = ethers.getAddress(account)
console.log("tx_hash:", txhash);
console.log("wallet_address", walletAddress);
console.log("network", network);
const response = await fetch('/auth', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
tx_hash: txhash,
wallet_address: walletAddress,
network: network
})
});
if (!response.ok) {
console.log("receieved something othere than 200 from api...");
throw new Error(`Server responded with status: ${response.status}`);
}
const result = await response.json();
showStatus('Witness successful!, closing the tab in 2 seconds');
setTimeout(() => {
window.close()
}, 2000);
} catch (e) {
console.log("Api error");
console.log("Error ..", e);
}
} catch (err) {
console.error(err);
showStatus(' Witenness :: Failed to authenticate: ' + err.message, true);
}
}
(async () => {
const { message } = await getPreviousVerificationHash();
let witness_event_verification_hash = message;
showMessage(witness_event_verification_hash);
await login();
})()
</script>
</body>
</html>