> ## Documentation Index
> Fetch the complete documentation index at: https://stytch.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrate crypto wallets via the API

> Implement Ethereum crypto wallet authentication with the Consumer API.

Our [Crypto wallets](/api-reference/consumer/api/crypto-wallets/authenticate-start) product unlocks Web3 authentication in your app in four easy steps. For this guide we'll walk through integrating [MetaMask](https://metamask.io/), but you may integrate any Ethereum based wallet with Stytch, we'll talk about this more later in the guide.

If you get stuck while working through this guide, feel free to ask questions in our [forum](https://stytch.com/web/discourse), via [support@stytch.com](mailto:support@stytch.com), or in our [Slack community](https://join.slack.com/t/stytch/shared%5Finvite/zt-3aqo03e10-afWXyLzRIAlzGWJyF%5F~zHw).

<Steps>
  <Step title="Get Ethereum address">
    To start, we need the user's Ethereum address we want to authenticate with. We can use the following code snippet to fetch the user's MetaMask Ethereum address from the browser. You'll have to check if window\.ethereum is defined – if it isn't, the user doesn't have MetaMask installed.

    ```js theme={null}
    const [address] = await window.ethereum.request({ method: 'eth_requestAccounts' });
    ```
  </Step>

  <Step title="Start Ethereum authentication">
    Using the Ethereum address, make a request to `/v1/crypto_wallets/authenticate/start`. If you want to add this Ethereum address to an existing user, pass in that user's `user_id`. If the Ethereum address doesn't belong to a user yet, leaving out a `user_id` will create a new user automatically.

    You can optionally use the Sign in With Ethereum (SIWE) protocol by passing in the `siwe_params` parameter. SIWE is recommended for Ethereum crypto wallet flows because it will automatically warn the end user if the domain passed in the message does not match the domain of the site making the signing request to the crypto wallet.

    The only required parameters for SIWE are domain and uri. You can read more about each individual parameter in our [docs](/api-reference/consumer/api/crypto-wallets/authenticate-start), and you can also check out the [full SIWE spec](https://eips.ethereum.org/EIPS/eip-4361).

    ```js theme={null}
    const stytch = require("stytch")

    const client = new stytch.Client({
        project_id: "PROJECT_ID",
        secret: "SECRET",
        env: stytch.envs.test,
      }
    );

    const params = {
        crypto_wallet_address: "0x6df2dB4Fb3DA35d241901Bd53367770BF03123f1",
        crypto_wallet_type: "ethereum",
        user_id: "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6", // optional
        siwe_params: {
          domain: "example.com",
          uri: "https://example.com",
        }, // optional
    };
    client.cryptoWallets.authenticateStart(params)
        .then(resp => { console.log(resp) })
        .catch(err => { console.log(err) });
    ```
  </Step>

  <Step title="Sign the message">
    Using the challenge field from the `/v1/crypto_wallets/authenticate/start` response, request the user to sign the message. The user will see a MetaMask popup asking to sign a message with the content from the challenge. You'll also have to gracefully handle the situation where a user chooses to reject the message.

    ```js theme={null}
    // get challenge from authenticate/start call
    const signature = await window.ethereum.request({"method": "personal_sign", "params": [challenge, address]})
    ```

    <img src="https://mintcdn.com/stytch-34ca0595/ujkFjtNfcCtlcK2E/images/consumer/from-old-docs/metamask-popup.webp?fit=max&auto=format&n=ujkFjtNfcCtlcK2E&q=85&s=9ddc15e6c19a733b217df158f225f2e7" alt="MetaMask popup" width="300" height="482" data-path="images/consumer/from-old-docs/metamask-popup.webp" />
  </Step>

  <Step title="Finish Ethereum authentication">
    Using the signature from the signMessage call described in the last step, make a request to `/v1/crypto_wallets/authenticate`. Optionally, you may provide an existing `session_token` to reuse an existing session, and/or provide a `session_duration_minutes` value to set the lifetime of the session.

    Stytch will perform validation on the address, challenge, and signature and return a 400 if there are any issues. If the authentication is successful, we'll return a 200.

    ```js theme={null}
    const stytch = require("stytch")

    const client = new stytch.Client({
        project_id: "PROJECT_ID",
        secret: "SECRET",
        env: stytch.envs.test,
      }
    );

    const params = {
        crypto_wallet_address: "0x6df2dB4Fb3DA35d241901Bd53367770BF03123f1",
        crypto_wallet_type: "ethereum",
        signature: "0x0c4f82edc3c818b6beff4b89e0682994e5878074609903cecdfb843241728be32f75949e2fbae63dcccdef97c0e3789a26441f7e11456cc1f2ef79b3a436010f1b"
    };
    client.cryptoWallets.authenticate(params)
        .then(resp => { console.log(resp) })
        .catch(err => { console.log(err) });
    ```
  </Step>

  <Step title="You're done">
    You just finished all the critical components to authenticate your users with a MetaMask wallet! Have any feedback after having integrated Ethereum with your app? Get in touch with us and tell us what you think by [contacting us](https://stytch.com/contact).
  </Step>
</Steps>
