In this guide, you will add crypto payments to the embedded checkout, enabling users able to pay for NFTs with cryptocurrency. These payments work cross-chain: for example, users can pay for Optimism NFTs with mainnet ETH or Solana.

The first step to integrate is getting a signer reference for your user’s wallet. Check out the options below:

  • Ethers.js V5

  • Using an API Signer

Using a Local Signer

You can clone this nextjs repo to get up running immediately: https://github.com/Crossmint/embedded-crosschain-ethers-v5

See below for a step by step walkthrough.

1. Create a new Next.js application

Check out the steps to setup a nextjs application here.

2. Add ethers to the project

This example is using nextjs with app router. Specify ethers version 5 when installing it.

pnpm i ethers@5.7.2

3. Edit the /app/page.tsx file

Replace the file contents with the code snippet below.

/app/page.tsx
"use client";

import React from "react";
import Crossmint from "./components/Crossmint";
import useEthersSigner from "./hooks/useEthersSigner";

const Page: React.FC = () => {
  const { signer, accounts } = useEthersSigner();

  return (
    <div className="container mx-auto max-w-md bg-white p-4">
      <div className="flex flex-col">
        {signer && <Crossmint signer={signer} accounts={accounts} />}
      </div>
    </div>
  );
};

export default Page;

4. Add a custom hook to initialize ethers

Create a new folder named hooks in the /app directory and add a file named useEthersSigner.ts. Then add the code in the block below.

/app/hooks/useEthersSigner.ts
"use client";

import { useState, useEffect, useRef } from "react";
import { ethers } from "ethers";

declare global {
  interface Window {
    ethereum: any;
  }
}

const useEthersSigner = () => {
  const [accounts, setAccounts] = useState([]);
  const signerRef = useRef<ethers.providers.JsonRpcSigner>();

  useEffect(() => {
    const initializeEthers = async () => {
      if (typeof window.ethereum !== "undefined") {
        try {
          const accounts = await window.ethereum.request({
            method: "eth_requestAccounts",
          });
          setAccounts(accounts);

          const provider = new ethers.providers.Web3Provider(window.ethereum);

          const signer = provider.getSigner();
          signerRef.current = signer;
        } catch (error) {
          console.error("User denied account access", error);
        }
      } else {
        console.log("MetaMask is not installed!");
      }
    };

    initializeEthers();
  }, []);

  return { signer: signerRef.current, accounts };
};

export default useEthersSigner;

5. Setup the CrossmintPayElement in a new file named Crossmint.tsx

The key details here are adding paymentMethod="ETH" and the signer property.

app/components/Crossmint.tsx
"use client";

import React from "react";
import { CrossmintPaymentElement } from "@crossmint/client-sdk-react-ui";
import { ethers } from "ethers";

type CrossmintProps = {
  signer: ethers.providers.JsonRpcSigner;
  accounts: string[];
};

const Crossmint: React.FC<CrossmintProps> = ({ signer, accounts }) => {
  const projectId = process.env.NEXT_PUBLIC_PROJECT_ID as string;
  const collectionId = process.env.NEXT_PUBLIC_COLLECTION_ID as string;
  const environment = process.env.NEXT_PUBLIC_ENVIRONMENT as string;

  return (
    <CrossmintPaymentElement
      projectId={projectId}
      collectionId={collectionId}
      environment={environment}
      paymentMethod="ETH"
      signer={{
        address: accounts[0],
        signAndSendTransaction: async (transaction) => {
          const response = await signer.sendTransaction({
            ...transaction,
            type: transaction.type!,
          });

          return response.hash;
        },
      }}
      mintConfig={{
        type: "erc-721",
        totalPrice: "0.001",
        _quantity: "1",
      }}
      onEvent={(event) => {
        console.log(event);
        if (event.type === "payment:process.succeeded") {
          console.log(
            "This is a basic example and does not logic to update UI upon payment completion. Check the main branch of this repository for a full example. https://github.com/Crossmint/embedded-crosschain-ethers-v5"
          );
        }
      }}
    />
  );
};

export default Crossmint;
The emailInputOptions attribute should be removed when setting up embedded checkout to use cross-chain payments.

That’s it! 🎉

Users can now start paying with other cryptocurrencies. You will receive the proceeds in the native currency of the contract, regardless of how the user paid.

Check out the repo: https://github.com/Crossmint/embedded-crosschain-ethers-v5

The example above is based on the simple branch in this linked repo. The main branch includes a more complete example with logic to detect minting events and update the UI.