Skip to main content

Signing & Verifying Messages

Signing Messages

Sequence wallets are able to sign arbitrary messages.

To request a user's signature of a simple message:

const signer = wallet.getSigner()
const message = 'Hello World!'

const signature = await signer.signMessage(message)
console.log(signature)

To request a user's signature of a typed-data (EIP712) message:

const typedData: sequence.utils.TypedData = {
domain: {
name: 'Ether Mail',
version: '1',
chainId: await wallet.getChainId(),
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC'
},
types: {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' }
]
},
message: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'
}
}

const signer = wallet.getSigner()

const signature = await signer.signTypedData(typedData.domain, typedData.types, typedData.message)
console.log(signature)

Verifying Message Signatures

Once you have a signature, you'll often want to verify the validity of the data either from your app or from your server. The Sequence SDKs make this easy to do from either your frontend or backend.

Given a message and signature, you can check if a particular wallet signed that message:

// Here we fetch the different parameters, but in practice you may have these values
// encoded and passed separately.
const wallet = sequence.getWallet()
const provider = wallet.getProvider()
const walletAddress = await wallet.getAddress()
const chainId = await wallet.getChainId()

// The sequence utils `isValidMessageSignature` method can validate signatures
// from any kind of wallet (ie. EOA or Smart Wallet) which includes Metamask, Coinbase,
// and Sequence.
const isValid = await sequence.utils.isValidMessageSignature(
walletAddress,
message,
signature,
provider,
chainId // optional, as it will use the chain id from the provider
)

console.log(isValid)
Sequence is a Smart Contract based account

As a Smart Contract-based account, Sequence signatures must be validated with the standard EIP1271 method, see https://eips.ethereum.org/EIPS/eip-1271.

The sequence.utils.isValidMessageSignature utility function is an easy way to validate any kind of message signature from any wallet.


Verifying Message Signatures (via Sequence API)

The Sequence API also offers the convenience to verify any wallet message signature by making a simple remote API call.

The Sequence API (https://api.sequence.app) supports the following RPC methods:

  • /rpc/API/IsValidMessageSignature -- verifying a simple text message signature
  • /rpc/API/IsValidTypedDataSignature -- verifying a EIP712 typed data object
  • /rpc/API/IsValidSignature -- verifying an arbitrary message digest
  • /rpc/API/IsValidETHAuthProof -- verifying an ETHAuth proof

The most common methods are IsValidMessageSignature and IsValidETHAuthProof.

Verifying message signature from any kind of wallet (ie. Metamask or Sequence)

Sequence API IsValidMessageSignature Method:

  • Request: POST https://api.sequence.app/rpc/API/IsValidMessageSignature
  • Content-Type: application/json
  • Body (in JSON):
    • chainId (string) -- the chain id of the signature, ie. "1" or "mainnet", or "137" or "polygon", etc
    • walletAddress (string) -- the wallet address
    • message (string) -- the message in utf8 text encoding
    • signature (string) -- the signature in hex encoding

IsValidMessageSignature example usage:

curl -X POST -H "Content-Type: application/json" https://api.sequence.app/rpc/API/IsValidMessageSignature -d '{ "chainId": "polygon", "walletAddress": "0x2fa0b551fdFa31a4471c1C52206fdb448ad997d1", "message": "Hi, please sign this message", "signature": "0x000501032a44625bec3b842df681db00a92a74dda5e42bcf0203596af90cecdbf9a768886e771178fd5561dd27ab005d0001000183d971056b1eca1bcc7289b9a6926677c5b07db4197925346367f61f2d09c732760719a91722acee0b24826f412cb69bd2125e48f231705a5be33d1f5523f9291c020101c50adeadb7fe15bee45dcb820610cdedcd314eb0030002f19915df00d669708608502d3011a09948b32674d6e443202a2ba884a4dcd26c2624ff33a8ee9836cc3ca2fbb8d3aa43382047b73d21646cb66cc2916076c1331c02" }'

Verifying ETHAuth proof upon connecting a Sequence Wallet

Sequence API IsValidETHAuthProof Method:

  • Request: POST https://api.sequence.app/rpc/API/IsValidETHAuthProof
  • Content-Type: application/json
  • Body (in JSON):
    • chainId (string) -- the chain id of the signature, ie. "1" or "mainnet", or "137" or "polygon", etc
    • walletAddress (string) -- the wallet address
    • ethAuthProofString (string) -- the ETHAuth encoded signature

IsValidETHAuthProof example usage:

curl -X POST -H "Content-Type: application/json" https://api.sequence.app/rpc/API/IsValidETHAuthProof -d '{"chainId":"polygon", "walletAddress":"0x2fa0b551fdFa31a4471c1C52206fdb448ad997d1","ethAuthProofString": "eth.0x2fa0b551fdfa31a4471c1c52206fdb448ad997d1.eyJhcHAiOiJEZW1vIERhcHAiLCJpYXQiOjAsImV4cCI6MTY2MDIzMTAyOCwidiI6IjEiLCJvZ24iOiJodHRwOi8vbG9jYWxob3N0OjQwMDAifQ.0x000501032a44625bec3b842df681db00a92a74dda5e42bcf0203596af90cecdbf9a768886e771178fd5561dd27ab005d00010001f7dad5ade840bb961cbab889d731bbc080bb4c36fc090435e82fe78e3c152b671505ad544adb562cc25a5933cd06c9108e239a52a82ba797c3d3522645c69cd81b020101c50adeadb7fe15bee45dcb820610cdedcd314eb003000274164fb33c93b4384582c54c30d9a1e2ef219063d03084005edc1da853af2f1f2e67275dbb6ef945d04600b6dd83cfd997cc9ae4173ea61b0c5cc0808fb196681b02"}' 


How does it work?

Notes on Signature Validation with EIP1271

Smart Wallets like Sequence rely on the EIP1271 standard for signature validation.

The EIP1271 is a single function on a contract defined as:

function isValidSignature(
bytes32 _hash,
bytes memory _signature
) public view returns (bytes4 magicValue)

The first _hash argument accepts the hash of the message digest, and the second argument _signature is the signed payload returned by the wallet upon signing.

For Javascript/Typescript signature verification, you can use 0xsequence utility functions like so:

import { 0xsequence } from '0xsequence'

const isValid = await sequence.utils.isValidSignature(
walletAddress,
digest,
signature,
provider,
chainId
)

console.log(isValid) // returns true/false

Additionally you can also use sequence.utils.isValidMessageSignature or sequence.utils.isValidTypedDataSignature which are just syntactic sugar for sequence.utils.isValidSignature.

As well, for convenience the signature validation fucntions above support verifying EOA or Smart Wallet signatures. This allows you to use a single code path in your Dapp to verify any kind of signature and support multiple wallets at the same time, like Metamask, Coinbase, Sequence, WalletConnect, Argent, Rainbow, etc. -- all Ethereum compatible wallets, EOA or Smart Wallets, will just work.