Sign messages to prove ownership without spending gas.
Sign a message with a user's private key
Signs arbitrary data with the user's private key. This proves ownership of an address without spending any ETH. The signature can be verified by anyone.
async function signMessage(message) {
try {
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
const signature = await window.ethereum.request({
method: 'personal_sign',
params: [message, accounts[0]]
});
console.log('Signature:', signature);
return signature;
} catch (error) {
console.error('Sign failed:', error);
}
}User signs a message to prove they own the address, enabling gasless login
Sign arbitrary data to prove you created it without blockchain transaction
Enable meta-transactions where someone else pays gas on your behalf
Sign terms and conditions to create legally binding agreements
async function loginWithWallet() {
// 1. Request wallet connection
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
const userAddress = accounts[0];
// 2. Create a message to sign
const message = `Login to our app
Address: ${userAddress}
Time: ${new Date().toISOString()}`;
// 3. User signs the message
const signature = await window.ethereum.request({
method: 'personal_sign',
params: [message, userAddress]
});
// 4. Send to backend for verification
const response = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ address: userAddress, signature, message })
});
const { token } = await response.json();
localStorage.setItem('authToken', token);
console.log('Logged in as:', userAddress);
}Backend verification: The server can recover the address from the signature and verify it matches the claimed address.
Never ask users to sign messages that could be used as transactions or approvals. Always include clear context in the message about what they're signing. Malicious sites could trick users into signing away their funds.