> ## Documentation Index
> Fetch the complete documentation index at: https://crossmint-wallets-docs-2-5.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Crypto Payments

> Add cross-chain crypto payments to the embedded checkout

In this guide, you will add crypto payments to the embedded checkout, enabling users to pay for digital assets with cryptocurrency. These payments work cross-chain: for example, users can pay for digital assets on any supported chain with ETH on mainnet or many popular L2s (Base, OP, Arbitrum One, and Arbitrum Nova) or even SOL.

### Experience the Flow

You can try out the flow in the app below. You must have some ETH available on the supported test networks to complete the purchase.

<Frame type="simple">
  <iframe src="https://embedded-crosschain.vercel.app/" width="730px" height="813px" />
</Frame>

You can also preview the live demo [in a new tab](https://embedded-crosschain.vercel.app/).

### Enabling Cross-Chain Payments

If you already have the embedded digital asset checkout configured in your application, adding cross-chain functionality simply requires adding a new `signer` property to the `CrossmintPayElement`. The guides and documentation here leverages the rainbowkit SDK, but you can find examples for other signers at the end.

### The Signer Object

You will pass a `signer` object to the `CrossmintPayElement` to enable cross-chain payments. Here is an outline of what that object will look like:

```tsx signer outline theme={null}
<CrossmintPayElement
  ... // other properties hidden
  paymentMethod="ETH"
  signer={{
    address, // public address of connected wallet
    signAndSendTransaction: async (transaction) => {
      // custom code that will present transaction to the user's wallet
    },
    chain, // the currently selected chain
    supportedChains, // array of chains you want to enable crosschain payments on
    handleChainSwitch: async (chain) => {
      // custom logic to trigger a network change in the connected wallet
    }
  }}
/>
```

### Signer Properties

<ResponseField name="address" type="string" required>
  This is the public address of the connected wallet.
</ResponseField>

<ResponseField name="signAndSendTransaction" type="function" required>
  This is a custom function that will present the transaction to the user for signing.

  Here is an example using the wagmi library:

  ```typescript theme={null}
  signAndSendTransaction: async (transaction) => {
    return await sendTransactionAsync(transaction);
  },
  ```

  <Note>This function **must** return the txId. Older versions of wagmi's `sendTransactionAsync` function return an object with `hash` as a property. In this case you must return `result.hash`.</Note>
</ResponseField>

<ResponseField name="chain" type="string">
  This is the string chain name of the currently selected chain. This is important and must be set to match the chain
  of the connected wallet. This value is used to re-calculate the payment transaction for the newly selected network.
  <p>The option set here **must** match one of the values passed to the `supportedChains` property below.</p>
</ResponseField>

<ResponseField name="supportedChains" type="array">
  This is an array of string chain names listing the networks you want to be
  available for selection to the user.

  <p>Available chains include:</p>
  <p>**mainnet:** `ethereum`, `base`, `optimism`, `arbitrum`</p>
  <p>**testnet:** `ethereum-sepolia`, `base-sepolia`, `optimism-sepolia`, `arbitrum-sepolia`</p>

  <Note>The network selection dropdown will only contain chains where the connected wallet has a greater than 0 ETH balance.</Note>
</ResponseField>

<ResponseField name="handleChainSwitch" type="function">
  This is a function you must implement when you're also using the
  `supportedChains` property and passing more than a single chain. Add logic
  here that will trigger the connected wallet to switch networks to match the
  selection the user makes in the Network dropdown.

  ```typescript theme={null}
  handleChainSwitch: async (chain) => {
    switchChain({
      chainId: chainIdMap[chain as keyof typeof chainIdMap],
    });
  },
  // where chainIdMap is an object mapping chainName to chainId
  ```
</ResponseField>

### Examples for Other Signers

<Tabs>
  <Tab title="Rainbowkit (wagmi/viem)">
    The code examples above are using rainbowkit v2.x. If you're using an older version of rainbowkit and its dependencies (wagmi and viem) you will need to tweak your `signAndSendTransaction` function to ensure it returns the txId hash as a string.

    <Card title="embedded-crosschain rainbowkit" icon="github" href="https://github.com/Crossmint/embedded-crosschain">
      Refer to the full repo for complete code examples
    </Card>
  </Tab>

  <Tab title="Dynamic.xyz">
    <Card title="embedded-crosschain Dynamic.xyz" icon="github" href="https://github.com/Crossmint/embedded-crosschain-dynamic">
      Refer to the full repo for complete code examples
    </Card>
  </Tab>

  <Tab title="Ethers.js V5">
    <Card title="embedded-crosschain ethers V5" icon="github" href="https://github.com/Crossmint/embedded-crosschain-ethers-v5">
      Refer to the full repo for complete code examples
    </Card>

    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](/payments/embedded/quickstart#set-up-the-project).

    ### 2. Add `ethers` to the project

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

    ```bash theme={null}
    pnpm i ethers@5.7.2
    ```

    ### 3. Edit the `/app/page.tsx` file

    Replace the file contents with the code snippet below.

    ```tsx /app/page.tsx theme={null}
    "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.

    <Accordion title="More info about this custom hook">
      A custom hook in React allows you to extract component logic into reusable functions.

      The `useEthersSigner.ts` file is a custom hook that's used to interact with the Ethereum blockchain. Here's a breakdown of what it does:

      1. It declares a state variable named `accounts` and a reference named `signerRef`. The `accounts` variable holds the Ethereum accounts the user has access to. The `signerRef` will hold a `JsonRpcSigner` object, which is used to sign transactions.

      2. The useEffect hook is leverated to run some code when the component mounts. This code checks if the `window.ethereum` object is defined (which would mean that an Ethereum provider like MetaMask is installed), requests access to the user's Ethereum accounts and sets up the `JsonRpcSigner`.

      3. If the user grants access, their accounts are stored in the accounts state variable and the `JsonRpcSigner` is stored in `signerRef`.

      4. The hook returns an object containing the current value of `signerRef` and `accounts`. This object is then used by the `Crossmint.tsx` component that is setup in the next step.
    </Accordion>

    ```tsx /app/hooks/useEthersSigner.ts theme={null}
    "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.

    ```tsx app/components/Crossmint.tsx theme={null}
    "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;
    ```

    <Note>The `emailInputOptions` attribute should be removed when setting up embedded checkout to use cross-chain payments.</Note>

    ### 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>
      Check out the repo: [https://github.com/Crossmint/embedded-crosschain-ethers-v5](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.
    </Check>
  </Tab>

  <Tab title="Using an API Signer">
    ## Using an API Signer

    Implementing `signAndSendTransaction` using a fetch method suggests that you are
    interacting with some backend service that will handle the transaction signing
    and broadcasting. Here's a conceptual example of how the implementation might look:

    ```jsx theme={null}
    <CrossmintPaymentElement
      // other props removed for brevity
      signer={{
        address: userAddress,
        signAndSendTransaction: async (transaction) => {
          // Sending the transaction details to a backend server for processing
          const response = await fetch('/api/sign-and-send-transaction', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({ transaction }),
          });

          const { transactionHash } = await response.json();
          return transactionHash; // the backend should return the transaction hash
        }
      }}
      ...
    />
    ```

    In the above example, you're making a POST request to the hypothetical `/api/sign-and-send-transaction` endpoint on your server.
    You need to stringify the transaction object since you are sending it as JSON in the request body.
    Your server would handle the signing and sending of the transaction to the blockchain, then respond with the transaction hash.
  </Tab>
</Tabs>
