How to test
Check that your address validation automation works
Test seed
Every vector on this page is derived from a single seed phrase, so you can check your implementation on all three chain families with one wallet.
seed: bamboo feed assist glove soda merry medal vanish almost solid bean loop
code: 1234
message: MtPelerin-1234Ethereum
m/44'/60'/0'/0/0
0xEa22e16EA50A43092853329F3cEEa0825Cb9B03e
Bitcoin, native SegWit
m/84'/0'/0'/0/0
bc1qjq907v02ra3pde52zza345c7cj52guwuucz527
Bitcoin, Taproot
m/86'/0'/0'/0/0
bc1p2uj2zul3vl87grth4ju9fqmam5gxsncr4w9sdzvdv44sr90v657s4ey7a0
Bitcoin, nested SegWit
m/49'/0'/0'/0/0
39MJF9h9YUcHtmgB9yfpqhPcuVFA848unL
Bitcoin, legacy
m/44'/0'/0'/0/0
17RudQJ5mepFTCoqErbuwRkey6hPWULcnb
Tezos
m/44'/1729'/0'/0'
tz1dnCbNYHDoxmHss9kEQVjWQj6GvYX4gYp5
The seed phrase and private keys on this page are for test purposes only, do not use them with real funds.
EVM
What goes in hash
The raw bytes returned by personal_sign, encoded in base64. The widget accepts any EVM network, and smart contract wallets are supported through the chain parameter, see below.
Test vector
A second vector, from a standalone private key with no seed phrase:
Browser, Metamask
NodeJS, ethers
Smart contract wallets
To validate the address of a smart contract wallet (EIP-1271), add the chain parameter so the on-chain isValidSignature call targets the right network. Counterfactual wallets that are not deployed yet are also accepted, through EIP-6492.
Accepted values: arbitrum_mainnet, avalanche_mainnet, base_mainnet, bsc_mainnet (BNB Chain), celo_mainnet, mainnet (Ethereum), matic_mainnet (Polygon), optimism_mainnet, rsk_mainnet (Rootstock), sonic_mainnet, tempo_mainnet, xdai_mainnet (Gnosis Chain), zksync_mainnet.
Ready to use URL
Bitcoin
What goes in hash
The base64 signature of the message, sent as is. Two schemes are accepted:
BIP-322 simple, for native SegWit (
bc1q...), nested SegWit (3...) and single-key-spend Taproot (bc1p...). This is what modern wallets return.BIP-137, the legacy
signmessagescheme, for legacy addresses (1...).
Unlike the EVM flow, there is no hex to base64 conversion to do: Bitcoin wallets already return base64.
Test vector, native SegWit
Test vector, Taproot
Note Taproot is the one exception on this page: BIP-340 signatures embed auxiliary random data, so signing the same message twice with the same key gives two different signatures. Yours will not match the value above, and both are valid. Every other vector on this page is deterministic and must match byte for byte.
Test vector, nested SegWit
Test vector, legacy
Browser, wallet extensions
Wallets that implement message signing return the base64 signature directly, so the value goes straight into hash once URL encoded. Ask for the BIP-322 scheme when the wallet lets you choose:
NodeJS, bip322-js
For a legacy address, bitcoinjs-message produces the accepted BIP-137 form:
Ready to use URLs
Native SegWit:
Taproot:
Nested SegWit:
Legacy:
Info Base64 signatures contain
+,/and=, which all have a meaning in a query string. If your signature is refused, check that they were encoded as%2B,%2Fand%3D.
Tezos
What the wallet signs
Tezos does not sign the message directly. It signs the Michelson PACK form of the message prefixed with Tezos Signed Message: , that is the two bytes 05 01, the byte length on 4 bytes big-endian, then the UTF-8 bytes.
For the code 1234, the bytes handed to the wallet are:
The armored block
The hash parameter is not a bare signature: it is the standard Tezos armored block, exactly 6 lines joined by \n. A missing line, an extra line, a trailing newline or \r\n line endings are all rejected.
Line 2:
Tezos Signed Message:followed byMtPelerin-{code}, byte for byte.Line 4: the signer's public key.
Line 5: the signature.
The public key on line 4 must correspond to the address passed in addr. A block signed by a different key is rejected, even when the signature itself is valid.
Test vector
Browser, Beacon SDK
NodeJS, Taquito
Ready to use URL
Supported Tezos addresses
tz1(Ed25519),tz2(secp256k1) andtz3(P-256) are supported.KT1originated accounts (smart contracts) andtz4(BLS) cannot be validated by signature.The address is case sensitive. Pass it exactly as the wallet returns it, never lowercased.
Lightning
Lightning accounts cannot be validated through this URL mechanism, because the proof is produced by the node key while the account holds a Lightning address. They are validated inside the widget, or by paying a 1 sat invoice.
Last updated