Web3.py – Python Web3 Account Sign_Message with Nonce

messagepythonweb3js

I want to sign message for login dapp,

The message is like "Welcome !" and have Nonce.
How can I using sign_message function with nonce?

In the Metamask show like below.

enter image description here

Best Answer

Under the hood, it's just one message that you need to sign.

Some background on how it works. Let's use Nansen as an example as it's the closest to the one on your screenshot.

When you click "Sign in with Wallet" (e.g. MetaMask), the app server generates a message with a time to live & a nonce. Here's what the message looks like in the MetaMask UI:

MetaMask sign-in

And here's what's actually sent to you from the server:

app.nansen.ai wants you to sign in with your Ethereum account:\n0x9729187D9E8Bbefa8295F39f5634cA454dd9d294\n\nBy signing this transaction you are allowing Nansen to see the following: your wallet address.\n\nURI: https://app.nansen.ai\nVersion: 1\nChain ID: 1\nNonce: BELEGLDkqN5\nIssued At: 2024-01-15T09:19:11.000Z

So, you need to sign the entirety of this message as one with your private key:

from eth_account.messages import encode_defunct
from web3 import Web3

private_key = '1e5a89614d79cab1e39a45f5b116498a38d373ba117a05b35df397f42d7a0c94'

# The message you received from Nansen
message = "app.nansen.ai wants you to sign in with your Ethereum account:\n0x9729187D9E8Bbefa8295F39f5634cA454dd9d294\n\nBy signing this transaction you are allowing Nansen to see the following: your wallet address.\n\nURI: https://app.nansen.ai\nVersion: 1\nChain ID: 1\nNonce: BELEGLDkqN5\nIssued At: 2024-01-15T09:19:11.000Z"

# Encode the message
encoded_message = encode_defunct(text=str(message))

# Sign the message with your private key
signed_message = Web3().eth.account.sign_message(encoded_message, private_key=private_key)

print("Signature:", signed_message.signature.hex())

Once you get the signature, you need to post it back to the app server within the time to live period so that you get signed in.