Automating the end user address validation
Pass and validate the end user's wallet address, so they can skip the steps where they have to select and validate their sending/receiving address.
All parameters must be URL encoded. Example:
/37KcpG6mEp+1oAan8/HLEvcfZFXUi6kTOxTHNjD3ZloxS8DL70v7lCmXiEyDOATm4hvewMzBO2d1n25QdJ8WBw=
must be passed as:
%2F37KcpG6mEp%2B1oAan8%2FHLEvcfZFXUi6kTOxTHNjD3ZloxS8DL70v7lCmXiEyDOATm4hvewMzBO2d1n25QdJ8WBw%3D
addr
public address
Allows you to automatically provide the user's receiving or sending public address (the address has to be unique for each user, common addresses are not permitted and will be rejected)
code
4-digits code
Random 4 digits code between 1000 and 9999 that you need to generate for each address supplied with the addr parameter (don't use the same code for all addresses or the validation will be rejected)
hash
#
base64 encoded signature of the following message: MtPelerin-<code>. The private key used to sign the message has to be the one matching the public address given in addr. To test it, see Test vector below.
chain
arbitrum_mainnet avalanche_mainnet base_mainnet bsc_mainnet celo_mainnet mainnet matic_mainnet optimism_mainnet rsk_mainnet xdai_mainnet zksync_mainnet
Opional, only required to validate the address of a smart contract wallet (EIP1271)
Test vector
You can verify that your signature for the 'hash' parameter is correct by testing it with the following info:
private key: 4142e80a872531fd1055f52ccab713d4c7f1eee28c33415558e74faeb516de2b
address: 0x270402aeB8f4dAc8203915fC26F0768feA61b532
code: 1234
hash: /37KcpG6mEp+1oAan8/HLEvcfZFXUi6kTOxTHNjD3ZloxS8DL70v7lCmXiEyDOATm4hvewMzBO2d1n25QdJ8WBw=
or with the following info:
seed: bamboo feed assist glove soda merry medal vanish almost solid bean loop
derivation path: m/44'/60'/0'/0/0
private key: 78ba65f1cc9427fab632340ae4d705b1485fba9f73ab5a24816907d36d5729e9
address: 0xEa22e16EA50A43092853329F3cEEa0825Cb9B03e
code: 1234
hash: yrXNJSmMc4wvVyKEzN4cEmLTvEaridjqTULZAfMwYAMM5PgBz4fCoIWNLr5NwKhxOYiPpI2vhMlKCihWadUw5xs=
Vanilla JS code with Metamask as signer
const toBase64 = (u8) =>
btoa(String.fromCharCode.apply(null, u8));
const fromBase64 = (str) =>
atob(str).split('').map(function (c) { return c.charCodeAt(0); });
const fromHexString = (hexString) =>
Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
const toHexString = (bytes) =>
bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');
/* Example for private key 78ba65f1cc9427fab632340ae4d705b1485fba9f73ab5a24816907d36d5729e9 */
const code = '1234';
const message = 'MtPelerin-' + code;
const address = '0xEa22e16EA50A43092853329F3cEEa0825Cb9B03e'; // ethereum address
window.ethereum.request({
method: 'personal_sign',
params: [message, address],
}).then((hash) => {
// hash should be 0xcab5cd25298c738c2f572284ccde1c1262d3bc46ab89d8ea4d42d901f33060030ce4f801cf87c2a0858d2ebe4dc0a87139888fa48daf84c94a0a285669d530e71b
const base64Hash = toBase64(fromHexString(hash.replace('0x', '')));
// base64Hash should be yrXNJSmMc4wvVyKEzN4cEmLTvEaridjqTULZAfMwYAMM5PgBz4fCoIWNLr5NwKhxOYiPpI2vhMlKCihWadUw5xs=
return base64Hash;
}).catch(console.log);
NodeJS code with ethers.Wallet as signer
const ethers = require('ethers');
/* Example for private key 78ba65f1cc9427fab632340ae4d705b1485fba9f73ab5a24816907d36d5729e9 */
const code = '1234';
const message = 'MtPelerin-' + code;
const address = '0xEa22e16EA50A43092853329F3cEEa0825Cb9B03e'; // ethereum address
const wallet = new ethers.Wallet('0x78ba65f1cc9427fab632340ae4d705b1485fba9f73ab5a24816907d36d5729e9');
wallet.signMessage(message).then((hash) => {
// hash should be 0xcab5cd25298c738c2f572284ccde1c1262d3bc46ab89d8ea4d42d901f33060030ce4f801cf87c2a0858d2ebe4dc0a87139888fa48daf84c94a0a285669d530e71b
const base64Hash = Buffer.from(hash.replace('0x', ''), 'hex').toString('base64');
// base64Hash should be yrXNJSmMc4wvVyKEzN4cEmLTvEaridjqTULZAfMwYAMM5PgBz4fCoIWNLr5NwKhxOYiPpI2vhMlKCihWadUw5xs=
return base64Hash;
}).catch(console.log);
Last updated