Create an API Key

The first step for integrating 3rd party authentication into your project with Crossmint is to obtain a client-side API key. You can find more info for creating a client-side API key here.

Navigate to the "Integrate" section on the left navigation bar, and ensure you're on the "API Keys" tab.

Within the Client-side keys section, click the "Create new key" button in the top right.

On the authorized origins section, enter http://localhost:3000 and click "Add origin".

Next, check the scopes labeled wallets.create, wallets.read, users.create.

Check the "JWT Auth" box

Finally, create your key and save it for subsequent steps.

Use Privy for API Key Authentication

After the key is generated, you need to set it to require Privy auth tokens for authorization.

To begin, go to the Privy dashboard at https://dashboard.privy.io/.

Once logged in, select an existing project or create a new one.

When you’re ready to move to production/mainnet with Privy, you will need to complete the “Upgrade to production” steps in the Privy dashboard (Settings > Basic > Application state).

Then select the “Settings” link from left-hand navigation to find your Privy App ID.

Copy the Privy App ID and return to the Crossmint developer console. Within the JWT authentication section, select “3P Auth providers” option, and then select Privy. Add your App ID and click the “Save JWT auth settings” button.

You now have a properly configured client-side API key to use. Continue on to learn how to add Crossmint Smart Wallets to your application that uses Privy for authentication.

Integration Guide

Install the Crossmint React UI SDK:

pnpm i @crossmint/client-sdk-react-ui

Add your Crossmint client-side API key to your environment file:

.env.local
NEXT_PUBLIC_PRIVY_APP_ID=_YOUR_PRIVY_APP_ID_
NEXT_PUBLIC_CROSSMINT_API_KEY=_YOUR_CROSSMINT_API_KEY_

The layout.tsx code snippet below is adapted from the quickstart repository provided by Privy. You can view that repo here: https://github.com/privy-io/create-next-app.

The layout.tsx sample code is adapted from the app-router branch of the Privy quickstart repository.

Add a new file with the contents of the CrossmintWrapper.tsx tab to your app and update the layout.tsx file as demonstrated.


Use Privy Embedded Wallet as the Signer

Applications that already use embedded wallets from Privy can easily add a Crossmint Smart Wallet that uses the embedded wallet as the signer.

Add a new directory to your /app folder named smart-wallet and create a new page.tsx file within it. Then copy the contents of the code sample below to create a smart wallet for the logged in user.

/smart-wallet/page.tsx
"use client";

import { useEffect, useState } from "react";
import { useWallet as useCrossmintSmartWallet } from "@crossmint/client-sdk-react-ui";
import type { ExternalSigner, EVMSmartWallet } from "@crossmint/client-sdk-react-ui";
import { usePrivy, useWallets as usePrivyWallets } from "@privy-io/react-auth";
import { CollectionABI } from "./abi";

export default function MyComponent() {
    const { getOrCreateWallet, wallet, status } = useCrossmintSmartWallet();
    const { login, logout, ready, authenticated } = usePrivy();
    const { wallets: privyWallets } = usePrivyWallets();
    const [isLoadingMint, setIsLoadingMint] = useState(false);

    useEffect(() => {
        const createWalletIfNeeded = async () => {
            const privyEmbedded = privyWallets.filter((wallet) => wallet.walletClientType === "privy");
            const privyReady = ready && authenticated && privyEmbedded.length > 0;
            const shouldCreateCrossmintWallet = status === "not-loaded";
            if (privyReady && shouldCreateCrossmintWallet && privyEmbedded[0] != null) {
                const signer = (await privyEmbedded[0].getEthereumProvider()) as ExternalSigner;
                getOrCreateWallet({ type: "evm-smart-wallet", signer });
            }
        };

        createWalletIfNeeded();
    }, [ready, authenticated, privyWallets, getOrCreateWallet]);

    if (status === "in-progress") {
        return <div>loading</div>;
    }

    return (
        <>
            <button onClick={login} className="bg-blue-500 py-3 px-6 text-white rounded-lg">
                Log In
            </button>
            <button onClick={logout} className="bg-blue-500 py-3 px-6 text-white rounded-lg">
                Log Out
            </button>
            <div>crossmint smart wallet: {wallet?.address}</div>
            <div>privy signer wallet: {wallets[0]?.address}</div>
            <div>status: {status}</div>
        </>
    );
}

The example above is specifying a Privy embedded wallet as the signer. This is happening in the useEffect hook where the wallets are filtered by walletClientType === “privy”.

If you want to use a different connected wallet as the signer you’d pass it to the getOrCreateWallet function instead. The wallets object returned from the useWallets call will return an array of connected wallets in order of how recently they were connected.

Refer to this docs page for Privy useWallets hook for more info on selecting a specific wallet.