aqua-cli 1.2.1

Aqua protocol command line tool that enable you to verify, sign and witness aqua chains.
// Define the HTML content as a constant
// copy the contents of static/sign.html to this string literal.
// since we are shipping a static binary html has to be hard coded.
// the static/sign.html is used for testing in dev
pub const SIGN_HTML: &str = r#"
<!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>Sign Aqua Chain With Metamask</h1>
        <button onclick="login()">Connect 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 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 getSignMessage() {
            const response = await fetch('/message');
            if (!response.ok) {
                throw new Error('Failed to get sign message');
            }
            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) {
            // const chainId = '0x89'; // Example: Polygon Mainnet chain ID
            if (typeof window.ethereum !== 'undefined') {
                try {
                    // Check if the network is already set
                    await window.ethereum.request({
                        method: 'wallet_switchEthereumChain',
                        params: [{ chainId }],
                    });
                    console.log("Network switched successfully");
                } catch (error) {
                    // If the network is not added, request MetaMask to add it
                    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...');

                // Request 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);

                // Get message to sign from server
                const { message } = await getSignMessage();
                showMessage(message);

                console.log("message ", message)



                // Create a  instance
                const provider = new ethers.BrowserProvider(window.ethereum);
                // const networkId = "sepolia";
                // const currentChainId = "0xaa36a7"


                let network = "sepolia";

                try {
                    const data = await getSignNetwork();
                    console.log("Response network "+data.network +" from network ",data)
                    // if (data.network != network) {
                        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)
                }



                const signer = await provider.getSigner();

                showStatus('Please sign the message in MetaMask...');

                // Hash the message (optional but recommended)
                const messageHash = ethers.hashMessage(message);

                // Sign the message using ethers.js
                const signature = await signer.signMessage(message);
                const signerAddress = await signer.getAddress()

                console.log("Signature: ", signature)

                if (!signature) {
                    alert("Signature not found ...");
                    return;
                }

                const publicKey = ethers.SigningKey.recoverPublicKey(
                    messageHash,
                    signature,
                )

                showStatus('Message signed, sending to server...');

                const walletAddress = ethers.getAddress(account)

                console.log("Signature:", signature);
                console.log("Public Key:", publicKey);
                console.log("account :", account);
                console.log("Wallet Address:", walletAddress);

                // Send to server
                const response = await fetch('/auth', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        signature: signature,
                        public_key: publicKey,
                        wallet_address: walletAddress
                    })
                });

                if (!response.ok) {
                    throw new Error(`Server responded with status: ${response.status}`);
                }

                const result = await response.json();
                showStatus('Signing successful!, closing the tab in 2 seconds');

                setTimeout(() => {
                    window.close()
                }, 200);

            } catch (err) {
                console.error(err);
                console.log("eRROR " + err.message);
                showStatus("Error =>" + err.message);
                
                // showStatus('Failed to authenticate: ' + err.message, true);
            }
        }

        (async () => {
            // Get message to sign from server
            const { message } = await getSignMessage();
            showMessage(message);

            await login();

        })()
    </script>
</body>

</html>

"#;