Skip to content

Instantly share code, notes, and snippets.

@KenoLeon
Created March 13, 2022 01:41
Show Gist options
  • Save KenoLeon/f52131754f63cf9c71e18ddd523fddde to your computer and use it in GitHub Desktop.
Save KenoLeon/f52131754f63cf9c71e18ddd523fddde to your computer and use it in GitHub Desktop.
Standalone MetaMask Signer for Medium Article tutorial
<!doctype html>
<html lang="en">
<!-- Standalone MetaMask Signer for A Medium Article: Signing messages in Ethereum medium.com/@k3no-->
<!-- Not to be used in production, just for educational purposes. -->
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<style>
pre {
overflow-x: auto;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
}
</style>
<script>
var globalAccount;
var globalSignature;
window.onload = function () {
// web3 instance for signature recovery
const web3 = new Web3(window.ethereum);
if (typeof window.ethereum !== 'undefined') {
console.log('MetaMask is installed!');
document.getElementById("debugContent").innerHTML = "MetaMask is installed!";
document.getElementById("metaMaskState").innerHTML = JSON.stringify(window.ethereum._state);
} else {
console.log('MetaMask is not installed!');
document.getElementById("debugContent").innerHTML = "MetaMask is not installed!";
}
const ethereumButton = document.querySelector('.launchButton');
const signButton = document.querySelector('.signMessageButton');
const verifyButton = document.querySelector('.verifyMessageButton');
const showAccount = document.querySelector('.showAccount');
ethereumButton.addEventListener('click', () => {
//Get the main account from MetaMask needs manual reload.
getAccount();
});
signButton.addEventListener('click', () => {
signMessage();
});
verifyButton.addEventListener('click', () => {
verifyMessage();
});
async function signMessage() {
const message = 'Very Message Such Wow';
document.getElementById("messageString").innerHTML = JSON.stringify(message);
try {
const from = globalAccount;
console.log('from : ' + from);
const msg = `0x${bops.from(message, 'utf8').toString('hex')}`;
document.getElementById("messageHex").innerHTML = JSON.stringify(msg);
console.log('msg : ' + msg);
const sign = await ethereum.request({
method: 'personal_sign',
params: [msg, from, 'Random text'],
});
console.log('sign : ' + sign);
globalSignature = sign;
document.getElementById("signature").innerHTML = JSON.stringify(sign);
} catch (err) {
console.error(err);
}
}
async function verifyMessage() {
const message = 'Very Message Such Wow';
try {
const from = globalAccount;
const msg = `0x${bops.from(message, 'utf8').toString('hex')}`;
const recoveredAddr = web3.eth.accounts.recover(msg, globalSignature);
console.log('recoveredAddr : ' + recoveredAddr);
document.getElementById("recoveredAddress").innerHTML = "Recovered Address: " +
recoveredAddr
if (recoveredAddr.toLowerCase() === from.toLowerCase()) {
console.log(`Successfully ecRecovered signer as ${recoveredAddr}`);
document.getElementById('result').innerHTML = `Verified !`;
} else {
console.log(
`Failed to verify signer when comparing ${recoveredAddr} to ${from}`,
);
document.getElementById('result').innerHTML = `Not Verified :(`;
}
} catch (err) {
console.error(err);
}
}
async function getAccount() {
const accounts = await ethereum.request({
method: 'eth_requestAccounts'
});
const account = accounts[0];
globalAccount = accounts[0];
showAccount.innerHTML = "Account: " + account;
document.getElementById("metaMaskState").innerHTML = JSON.stringify(window.ethereum._state);
}
}
</script>
<title>MetaMask debugging and testing</title>
</head>
<body>
<div class="container">
<br>
<br>
<div class="row">
<div class="col-1">
</div>
<div class="col-10">
<div class="alert alert-dark">
<h5 class="alert-heading">MetaMask Debuggin and Testing .</h5>
</div>
<div class="alert alert-info" role="alert">
<h4 class="alert-heading">DEBUG</h4>
<div id="debugContent">
No Javascript detected!
</div>
<span class="badge rounded-pill bg-info text-dark showAccount"></span>
<h5>window.ethereum._state :</h5>
<div>
<pre id="metaMaskState"></pre>
</div>
<h5>Message String:</h5>
<div>
<pre id="messageString"></pre>
</div>
<h5>Message Hex:</h5>
<div>
<pre id="messageHex"></pre>
</div>
<h5>Signature :</h5>
<div>
<pre id="signature"></pre>
</div>
<h5>Verification :</h5>
<div>
<pre id="recoveredAddress"></pre>
<br>
</div>
<h5>RESULT :</h5>
<div id="result"></div>
</div>
<button type="button" class="btn btn-secondary btn-lg btn-block launchButton">Connect Launch Login
Metamask</button>
<br>
<br>
<button type="button" class="btn btn-secondary btn-lg btn-block signMessageButton">Sign Message</button>
<br>
<br>
<button type="button" class="btn btn-secondary btn-lg btn-block verifyMessageButton">Verify
Message</button>
</div>
<div class="col-1">
</div>
</div>
<br><br><br>
</div>
<!-- Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous">
</script>
<!-- Using Bops instead of Buffer (Node) for portability -->
<script src="https://cdn.jsdelivr.net/gh/chrisdickinson/bops@master/dist/bops.js" type="module"></script>
<!-- Also you will need some utils, web3.js instead of @Metamask/eth-sig-util -->
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment