# Automating the end user address validation

{% hint style="warning" %}
**All parameters must be URL encoded. Example:**

/37KcpG6mEp+1oAan8/HLEvcfZFXUi6kTOxTHNjD3ZloxS8DL70v7lCmXiEyDOATm4hvewMzBO2d1n25QdJ8WBw=&#x20;

**must be passed as:**

%2F37KcpG6mEp%2B1oAan8%2FHLEvcfZFXUi6kTOxTHNjD3ZloxS8DL70v7lCmXiEyDOATm4hvewMzBO2d1n25QdJ8WBw%3D
{% endhint %}

| Parameter | Value                                                                                                                                                                                                                       | Description                                                                                                                                                                                                        |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 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     | <p>arbitrum\_mainnet<br>avalanche\_mainnet<br>base\_mainnet<br>bsc\_mainnet<br>celo\_mainnet<br>mainnet<br>matic\_mainnet<br>optimism\_mainnet<br>rsk\_mainnet</p><p>sonic\_mainnet<br>xdai\_mainnet<br>zksync\_mainnet</p> | Optional, 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=

{% hint style="danger" %}
The private key and seed phrase above are for test purposes only, **do not** use them with real funds.
{% endhint %}

#### 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);
```

{% hint style="info" %}
If your signature implementation fails, make sure you have properly URL encoded the parameters.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.mtpelerin.com/integration-guides/parameters-and-customization/automating-the-end-user-address-validation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
