> For the complete documentation index, see [llms.txt](/llms.txt).

# Integrate Solana Pay with Embedded Wallets

`embedded wallets` `plug and play` `web` `solana` `solana pay` `react` `ed25519`MetaMask Developer Relations | November 15, 2025

Open in Claude

MetaMask Embedded Wallets enable users to log in with familiar web2 socials by using [Shamir's Secret Sharing](/embedded-wallets/infrastructure/sss-architecture/) Multi-Party Computation (MPC) to ensure the wallet key is distributed and non-custodial.

This tutorial demonstrates how to integrate Solana Pay with [MetaMask Embedded Wallets](/embedded-wallets/) to create a seamless payment experience for your users. By combining Embedded Wallets' familiar web2 social logins with Solana Pay's QR code functionality, you can enable users to make payments directly from their social login wallets.

MetaMask Embedded Wallets social login allows users to:

- Log in using familiar web2 social providers (such as Google and Apple).
- Generate Solana Pay QR codes for transactions.
- Make payments using their embedded wallet.

This tutorial follows the implementation demonstrated in the following live stream:

info

A [complete implementation example](https://github.com/Web3Auth/web3auth-examples/tree/main/other/solana-pay-example) is available on GitHub.

## Step 1: Set up the dashboard[​](#step-1-set-up-the-dashboard "Direct link to Step 1: Set up the dashboard")

Follow these steps to set up and configure your Embedded Wallets (Web3Auth) dashboard:

1. Sign up for a free account on the [Embedded Wallets dashboard](https://developer.metamask.io/login).
2. Create a new project.
3. Copy your Client ID from the dashboard. This ID is crucial for initializing the SDK.
4. Navigate to **Chains & Networks** and enable Solana, Solana Devnet, and Solana Testnet. Ensure all the [RPC URLs are configured](/embedded-wallets/dashboard/chains-and-networks/).

tip

See the [Embedded Wallets dashboard documentation](/embedded-wallets/dashboard/) for more information. You can explore other dashboard features, including custom verifiers, whitelabeling, and analytics.

## Step 2: Install dependencies[​](#step-2-install-dependencies "Direct link to Step 2: Install dependencies")

Install the following dependencies in your project:

- npm
- Yarn
- pnpm
- Bun

```
npm install @solana/pay bignumber.js @solana/web3.js

```

```
yarn add @solana/pay bignumber.js @solana/web3.js

```

```
pnpm add @solana/pay bignumber.js @solana/web3.js

```

```
bun add @solana/pay bignumber.js @solana/web3.js

```

note

- `@solana/pay`: The core Solana Pay protocol library.
- `bignumber.js`: Enables accurate handling of large numbers, especially when dealing with token amounts.
- `@solana/web3.js`: Enables interacting with the Solana blockchain, such as fetching balances or constructing transactions.

## Step 3: Integrate MetaMask Embedded Wallets in React[​](#step-3-integrate-metamask-embedded-wallets-in-react "Direct link to Step 3: Integrate MetaMask Embedded Wallets in React")

Use the `@web3auth/modal` SDK to integrate and manage Embedded Wallets in your React application.

### 3.1. Initialize the provider[​](#31-initialize-the-provider "Direct link to 3.1. Initialize the provider")

Wrap your application components with a `Web3AuthProvider` to configure the SDK with your Client ID:

src/main.tsx

```
import './index.css';

import ReactDOM from 'react-dom/client';
import { Web3AuthProvider } from '@web3auth/modal/react';
import web3AuthContextConfig from './web3authContext';
import App from './App';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <Web3AuthProvider config={web3AuthContextConfig}>
    <App />
  </Web3AuthProvider>
);

```

src/web3authContext.tsx

```
import { WEB3AUTH_NETWORK } from '@web3auth/modal'
import { type Web3AuthContextConfig } from '@web3auth/modal/react'

// Dashboard Registration
const clientId =
  'BFcLTVqWlTSpBBaELDPSz4_LFgG8Nf8hEltPlf3QeUG_88GDrQSw82fSjjYj5x4F3ys3ghMq8-InU7Azx7NbFSs' // get from https://developer.metamask.io

// Instantiate the SDK.
const web3AuthContextConfig: Web3AuthContextConfig = {
  web3AuthOptions: {
    clientId,
    web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
  },
}

export default web3AuthContextConfig

```

### 3.2. Access wallet information and fetch user balance[​](#32-access-wallet-information-and-fetch-user-balance "Direct link to 3.2. Access wallet information and fetch user balance")

Access wallet information and user details using the [Solana hooks](/embedded-wallets/sdk/react/solana-hooks/):

src/components/getBalance.tsx

```
import { useSolanaWallet } from '@web3auth/modal/react/solana';
import {
  LAMPORTS_PER_SOL,
  PublicKey,
} from '@solana/web3.js';
import { useEffect, useState } from 'react';

export function Balance() {
  const { accounts, connection } = useSolanaWallet();
  const [balance, setBalance] = useState<number | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const fetchBalance = async () => {
    if (connection && accounts && accounts.length > 0) {
      try {
        setIsLoading(true);
        setError(null);
        const publicKey = new PublicKey(accounts[0]);
        const balance = await connection.getBalance(publicKey);
        setBalance(balance);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Unknown error');
      } finally {
        setIsLoading(false);
      }
    }
  };

  useEffect(() => {
    fetchBalance();
  }, [connection, accounts]);

  return (
    <div>
      <h2>Balance</h2>
      <div>
        {balance !== null && `${balance / LAMPORTS_PER_SOL} SOL`}
      </div>
        {isLoading && <span className='loading'>Loading...</span>}
        {error && <span className='error'>Error: {error}</span>}
      <button onClick={fetchBalance} type='submit' className='card'>
          Fetch Balance
      </button>
    </div>
  )
}

```

## Step 4: Integrate Solana Pay[​](#step-4-integrate-solana-pay "Direct link to Step 4: Integrate Solana Pay")

Solana Pay enables the generation of transaction requests, typically as QR codes, for direct payments from Solana wallets. Follow these steps to create and display Solana Pay QR codes for payments.

### 4.1. Import components[​](#41-import-components "Direct link to 4.1. Import components")

Import the necessary components from the installed libraries:

```
import { createQR } from '@solana/pay'
import { Keypair, PublicKey } from '@solana/web3.js'
import BigNumber from 'bignumber.js'
import { useSolanaWallet } from '@web3auth/modal/react/solana'

```

### 4.2. Generate QR codes[​](#42-generate-qr-codes "Direct link to 4.2. Generate QR codes")

The core of the Solana Pay integration involves creating a payment request URL and then rendering it as a QR code. First, define the following:

- **Recipient and amount:** Define the `recipient` (a `PublicKey` of the merchant/receiver) and the `amount` (a `BigNumber` representing the payment value, for example, 0.001 SOL).
- **Reference:** Generate a unique `reference` for the payment. This acts as a unique identifier for the transaction.
- **Optional fields:** Include `label`, `message`, and `memo` for enhanced user experience.

The following is an example implementation of a Solana Pay QR code generator:

src/components/solanaPay.tsx

```
import { Keypair, PublicKey } from '@solana/web3.js';
import { createQR, encodeURL } from '@solana/pay';
import BigNumber from 'bignumber.js';
import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { useSolanaWallet } from '@web3auth/modal/react/solana';

export function SolanaPay() {
  const { accounts } = useSolanaWallet();
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [amountToSend, setAmountToSend] = useState(0);
  const [showModal, setShowModal] = useState(false);
  const [qrUrl, setQrUrl] = useState<string>('');
  const qrRef = useRef<HTMLDivElement>(null);

  const generateQrCode = () => {
    try {
      if (!accounts?.[0]) {
        setError('No wallet connected');
        return;
      }

      setIsLoading(true);
      setError(null);
      // set the parameter of the transfer
      const recipient = new PublicKey(accounts?.[0]!);
      const amount = new BigNumber(amountToSend);
      // reference should be a unique ID for the payment
      const reference = new Keypair().publicKey;
      // Label and message are optional. They will be shown in wallets when users scan it but won't show on chain
      const label = 'MetaMask Embedded Wallet x Solana Pay Demo';
      const message = 'Thanks for Trying Solana Pay!';
      // memo is optional and will be included in the onchain transaction
      const memo = 'Thanks for Trying Solana Pay!';
      // create the URL
      const url = encodeURL({
        recipient,
        amount,
        reference,
        label,
        message,
        memo,
      });

      setQrUrl(url.toString());
      setShowModal(true);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to generate QR code');
    } finally {
      setIsLoading(false);
    }
  };
  // Generate QR code when modal opens and URL is available
  useEffect(() => {
    if (showModal && qrUrl && qrRef.current) {
      qrRef.current.innerHTML = '';
      try {
        const qr = createQR(qrUrl, 300, 'white');
        qr.append(qrRef.current);
      } catch (err) {
        setError('Failed to create QR code');
      }
    }
  }, [showModal, qrUrl]);

  const closeModal = () => {
    setShowModal(false);
    setQrUrl('');
    setError(null);
  };

  return (
    <>
      <div>
        <h2>Solana Pay QR</h2>
        <div className='flex flex-col items-center gap-4'>
          <input
            type='number'
            placeholder='Enter SOL amount'
            onChange={(e) => setAmountToSend(Number(e.target.value))}
            className='px-4 py-2 border rounded-lg text-black'
            step='0.01'
            min='0'
          />
          <button
            onClick={generateQrCode}
            className='px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600'
            disabled={isLoading || amountToSend <= 0}
          >
            {isLoading ? 'Generating...' : 'Generate Payment QR'}
          </button>

          {/* Error Display */}
          {error && !showModal && (
            <div className='text-red-500 text-sm mt-2'>
              Error: {error}
            </div>
          )}
        </div>
      </div>
...

```

## Testing and best practices[​](#testing-and-best-practices "Direct link to Testing and best practices")

### Development environment[​](#development-environment "Direct link to Development environment")

- **Devnet for testing:** Always develop and test on devnet or testnet. You can use the [Solana Faucet](https://faucet.solana.com/) to get test SOL for your new account.
- **Environment variables:** Store your Client ID and other sensitive configuration in environment variables.

### User experience[​](#user-experience "Direct link to User experience")

- **User interface:** For better user experience, display the QR code within a modal or a dedicated confirmation page, providing clear messages to the user.
- **Loading states:** Implement proper loading states while generating QR codes and processing transactions.
- **Error handling:** Provide clear error messages when transactions fail or when the user's wallet doesn't have sufficient balance.

### Production readiness[​](#production-readiness "Direct link to Production readiness")

- **Tracking payments:** Implement a server-side solution to track the unique payment `reference` and poll for transaction confirmation using websockets. This allows you to update your application's state and perform reconciliation in your database.
- **Production RPCs:** For scalable production usage, use dedicated Solana RPC services from providers like [MetaMask](/services/reference/solana/), as public RPCs may have rate limits.
- **Security:** Validate all payment parameters server-side before processing transactions.

## Next steps[​](#next-steps "Direct link to Next steps")

- To learn more about Embedded Wallets, see the [Web SDK documentation](/embedded-wallets/sdk/react/) and the [Solana Pay integration example](https://github.com/Web3Auth/web3auth-examples/blob/main/other/solana-pay-example).

[Share](https://www.facebook.com/sharer/sharer.php?https://metamask.io/tutorials/integrate-solana-pay)[Tweet](http://twitter.com/share?text=Checkout Integrate Solana Pay with Embedded Wallets published by @MetaMask&url=https://metamask.io/tutorials/integrate-solana-pay)Copy

On this page
- [Step 1: Set up the dashboard](#step-1-set-up-the-dashboard)
- [Step 2: Install dependencies](#step-2-install-dependencies)
- [Step 3: Integrate MetaMask Embedded Wallets in React](#step-3-integrate-metamask-embedded-wallets-in-react)
  - [3.1. Initialize the provider](#31-initialize-the-provider)
  - [3.2. Access wallet information and fetch user balance](#32-access-wallet-information-and-fetch-user-balance)
- [Step 4: Integrate Solana Pay](#step-4-integrate-solana-pay)
  - [4.1. Import components](#41-import-components)
  - [4.2. Generate QR codes](#42-generate-qr-codes)
- [Testing and best practices](#testing-and-best-practices)
  - [Development environment](#development-environment)
  - [User experience](#user-experience)
  - [Production readiness](#production-readiness)
- [Next steps](#next-steps)
