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

# Social logins with Particle Connect

> Comprehensive guide on Social logins with Particle Connect on Sei. Learn key concepts, commands, and best practices.

[Particle Network](https://particle.network) uses its Wallet Abstraction stack
to simplify onboarding into both EOAs and ERC-4337 smart accounts. Particle
gives you an aggregated modal with social logins and wallet adapters, such as
MetaMask. The modal is fully compatible with Sei and supports 2-click
onboarding.

The Particle Connect user flow starts with social login. Users log in with
custom authentication or with predefined options from the platform, such as
email, Google, or X. This process uses MPC-TSS to generate an EOA. The EOA can
then be the signer for a smart account. You can use a smart account
implementation such as `SimpleAccount` or Biconomy (V1 or V2), depending on the
requirements of your dApp.

This guide gives a high-level overview of how to build a demo dApp on Sei. The
demo uses the
[Particle Connect SDK](https://developers.particle.network/social-logins/connect/desktop/web),
Particle's onboarding solution. It implements the modal described above for
social logins and wallet connection. It also uses account abstraction to send a
gasless transaction.

In this guide, you build a demo dApp that:

1. Uses a `SimpleAccount` instance of a smart account to onboard users through
   social login.
2. Executes a gasless (sponsored) transaction. This shows how the SDK
   simplifies user interactions on Sei.

## Getting started

### Dependencies

To integrate Particle Connect into your Sei dApp, you need only a few
dependencies. Particle Connect has built-in support for account abstraction
(AA). However, this example uses the Particle AA SDK with an EIP-1193 provider,
such as ethers.js.

```bash theme={null}
yarn add @particle-network/connectkit viem@^2 @particle-network/aa ethers
```

### Setting up the Particle dashboard

Before you start the configuration, go to the
[Particle dashboard](https://dashboard.particle.network) to get the three keys
that your project requires.

When you use any SDK from Particle Network, you routinely need a `projectId`, a
`clientKey`, and an `appId`. These keys authenticate your project. They also
connect your instance of Particle Auth to the Particle dashboard. In the
dashboard, you can customize the modals embedded in your dApp, track users, and
fund gasless transactions, among other tasks.

In the Particle dashboard, follow these steps:

1. Create a new project through **Add New Project**.
2. Under **Your Apps**, click **Web**. If you intend to use a different
   platform, see the
   [platform-specific guides in the Particle documentation](https://developers.particle.network/social-logins/connect/introduction).
3. Choose a name and a domain for your dApp. If you have not deployed yet, or
   you have not decided where to deploy, you can use any placeholder domain.
4. Copy the **Project ID**, **Client Key**, and **App ID**.

Because these values authenticate your project, store them in a `.env` file
with this format:

```shell theme={null}
NEXT_PUBLIC_PROJECT_ID='PROJECT_ID'
NEXT_PUBLIC_CLIENT_KEY='CLIENT_KEY'
NEXT_PUBLIC_APP_ID='APP_ID'
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID='WALLETCONNECT_PROJECT_ID'
```

## Configuring Particle Connect

First, configure and initialize Particle Connect. Create a new `ConnectKit.tsx`
file in your `src` directory.

This file defines the `ParticleConnectKit` component, which wraps the
configured `ConnectKitProvider` instance. This component manages the Particle
Connect configuration and makes it available across your dApp.

```typescript theme={null}
"use client";

import React from "react";
import { ConnectKitProvider, createConfig } from "@particle-network/connectkit";
import { authWalletConnectors } from "@particle-network/connectkit/auth";
import { evmWalletConnectors } from "@particle-network/connectkit/evm";
import { sei, seiTestnet } from "@particle-network/connectkit/chains";
import { wallet, EntryPosition } from "@particle-network/connectkit/wallet";
import { aa } from "@particle-network/connectkit/aa";

const config = createConfig({
  projectId: process.env.NEXT_PUBLIC_PROJECT_ID!,
  clientKey: process.env.NEXT_PUBLIC_CLIENT_KEY!,
  appId: process.env.NEXT_PUBLIC_APP_ID!,

  walletConnectors: [
    authWalletConnectors({}), // Social logins

    // Default Web3 logins
    evmWalletConnectors({
      walletConnectProjectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID, // optional, retrieved from https://cloud.walletconnect.com
    }),
  ],

  plugins: [
    wallet({
      entryPosition: EntryPosition.BR, // Positions the modal button at the bottom right on login
      visible: true, // Determines if the wallet modal is displayed
    }),
    aa({
      name: "SIMPLE",
      version: "2.0.0",
    }),
  ],
  chains: [sei, seiTestnet],
});

export const ParticleConnectkit = ({ children }: React.PropsWithChildren) => {
  return <ConnectKitProvider config={config}>{children}</ConnectKitProvider>;
};
```

This code configures Particle Connect for wallet authentication and blockchain
interactions on Sei Mainnet and Sei Testnet. It includes social logins and
traditional Web3 options through WalletConnect. It also enables account
abstraction (AA) with a `SimpleAccount` instance, version 2.0.0. The configured
`ConnectKitProvider` component then wraps the content of your dApp and makes
this configuration available to it.

## Integrate Particle Connect in your app

After you configure Particle Connect, wrap your dApp with the
`ParticleConnectKit` component. This makes the Particle Connect SDK available
throughout the dApp. Update the `layout.tsx` file in the `src` directory with
this code:

```tsx theme={null}
import { ParticleConnectkit } from '@/components/Connectkit';
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';

const inter = Inter({ subsets: ['latin'] });

export const metadata: Metadata = {
  title: 'Particle Connectkit App',
  description: 'Generated by create next app'
};

export default function RootLayout({
  children
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <ParticleConnectkit>{children}</ParticleConnectkit>
      </body>
    </html>
  );
}
```

## Building the application

With your project set up, the dependencies installed, and Particle Connect
configured, you can start to build in the `page.tsx` file.

In `page.tsx`, you define the core features: the login flow, transaction
handling, and the UI.

### Connecting the wallet

After you configure `layout.tsx`, add a primary **Connect Wallet** button so
that users can log in. Import `ConnectButton` from
`@particle-network/connectkit`. Then add it to the interface. When a user clicks
the `ConnectButton` component to log in, it opens a unified login modal. You can
see an example of this modal in the
[Particle demo](https://demo.particle.network).

```tsx theme={null}
'use client';
import { ConnectButton, useAccount } from '@particle-network/connectkit';

const HomePage = () => {
  const { address, isConnected, chainId } = useAccount();

  return (
    <div className="flex justify-center items-center h-screen">
      <div className="text-center">
        <ConnectButton />
        {isConnected && (
          <>
            <h2>Address: {address}</h2>
            <h2>Chain ID: {chainId}</h2>
          </>
        )}
      </div>
    </div>
  );
};

export default HomePage;
```

### Sending transactions with an EIP-1193 provider

Particle Connect has built-in AA features. If you also use the Particle AA SDK,
you can work with EIP-1193 providers, such as `ethers`. This approach is
especially helpful if you already know these providers or you are integrating
Particle Connect into an existing dApp.

To do this, wrap the smart account from Particle Connect in an instance of
`ethers` to create a `customProvider`. You can then use `ethers` as usual. The
smart account signs the transactions in the background.

```tsx theme={null}
import { useSmartAccount } from '@particle-network/connectkit';
import { AAWrapProvider, SendTransactionMode } from '@particle-network/aa';

const smartAccount = useSmartAccount();

// Init custom provider with gasless transaction mode
const customProvider = smartAccount ? new ethers.BrowserProvider(new AAWrapProvider(smartAccount, SendTransactionMode.Gasless) as Eip1193Provider, 'any') : null;

/**
 * Sends a transaction using the ethers.js library.
 * This transaction is gasless since the customProvider is initialized as gasless
 */
const executeTxEthers = async () => {
  if (!customProvider) return;

  const signer = await customProvider.getSigner();
  const tx = {
    to: recipientAddress,
    value: parseEther('0.01').toString()
  };

  const txResponse = await signer.sendTransaction(tx);
  const txReceipt = await txResponse.wait();
  console.log(txReceipt?.hash);
};
```

This transaction is gasless because it meets two conditions:

1. **Gasless mode configuration**: The code sets `SendTransactionMode.Gasless`
   in `AAWrapProvider`. This setting specifies that the transaction should be
   gasless and sponsored.
2. **Funding requirements**: On Sei Testnet, all transactions are sponsored
   automatically, so you do not need to deposit funds to pay transaction fees.
   On Sei Mainnet, however, the paymaster needs sufficient funds to sponsor
   these transactions. You can configure the paymaster in the
   [Particle dashboard](https://dashboard.particle.network).

This example shows how to use an existing EIP-1193 provider. You can also build
a `userOp` directly with Particle Connect. For an example, see the
[starter repository](https://github.com/Particle-Network/connectkit-aa-demo/blob/2017262daf297624362d51f3d50cccd3b4606ef9/app/page.tsx#L117).

## Full app example

With the setup complete, you can use Particle Connect as this example dApp
shows.

In this example, the dApp uses a social login or a Web3 login to create a smart
account on Sei. Then it sends a gasless transaction of 0.001 SEI through the
`ethers` provider.

```tsx theme={null}
'use client';
import React, { useEffect, useState } from 'react';

// Particle imports
import { ConnectButton, useAccount, usePublicClient, useSmartAccount } from '@particle-network/connectkit';

// Eip1193 and AA Provider
import { AAWrapProvider, SendTransactionMode } from '@particle-network/aa'; // Only needed with Eip1193 provider
import { ethers, type Eip1193Provider } from 'ethers';
import { formatEther, parseEther } from 'viem';

export default function Home() {
  const { isConnected, chain } = useAccount();
  const publicClient = usePublicClient();
  const smartAccount = useSmartAccount();

  const [userAddress, setUserAddress] = useState<string>('');
  const [balance, setBalance] = useState<string | null>(null);
  const [recipientAddress, setRecipientAddress] = useState<string>('');
  const [transactionHash, setTransactionHash] = useState<string | null>(null);

  // Init custom provider with gasless transaction mode
  const customProvider = smartAccount ? new ethers.BrowserProvider(new AAWrapProvider(smartAccount, SendTransactionMode.Gasless) as Eip1193Provider, 'any') : null;

  /**
   * Fetches the balance of a given address.
   * @param {string} address - The address to fetch the balance for.
   */
  const fetchBalance = async (address: string) => {
    try {
      const balanceResponse = await publicClient?.getBalance({
        address: address as `0x${string}`
      });
      if (balanceResponse) {
        const balanceInEther = formatEther(balanceResponse).toString();
        setBalance(balanceInEther);
      } else {
        setBalance('0.0');
      }
    } catch (error) {
      console.error('Error fetching balance:', error);
      setBalance('0.0');
    }
  };

  /**
   * Loads the user's account data, including address and balance.
   */
  useEffect(() => {
    const loadAccountData = async () => {
      if (isConnected && smartAccount) {
        try {
          const address = await smartAccount.getAddress();
          setUserAddress(address);
          await fetchBalance(address);
        } catch (error) {
          console.error('Error loading account data:', error);
        }
      }
    };
    loadAccountData();
  }, [isConnected, smartAccount]);

  /**
   * Sends a transaction using the ethers.js library.
   * This transaction is gasless since the customProvider is initialized as gasless
   */
  const executeTxEthers = async () => {
    if (!customProvider) return;

    const signer = await customProvider.getSigner();
    try {
      const tx = {
        to: recipientAddress,
        value: parseEther('0.001').toString()
      };

      const txResponse = await signer.sendTransaction(tx);
      const txReceipt = await txResponse.wait();

      setTransactionHash(txReceipt?.hash || null);
    } catch (error) {
      console.error('Failed to send transaction using ethers.js:', error);
    }
  };

  return (
    <div className="container min-h-screen flex flex-col justify-center items-center mx-auto gap-4 px-4 md:px-8">
      <div className="w-full flex justify-center mt-4">
        <ConnectButton label="Click to login" />
      </div>
      {isConnected && (
        <>
          <div className="border border-purple-500 p-6  w-full">
            <h2 className="text-lg font-semibold mb-2 text-white">
              Address: <code>{userAddress || 'Loading...'}</code>
            </h2>
            <h2 className="text-lg font-semibold mb-2 text-white">
              Balance: {balance || 'Loading...'} {chain?.nativeCurrency.symbol}
            </h2>
            <input type="text" placeholder="Recipient Address" value={recipientAddress} onChange={(e) => setRecipientAddress(e.target.value)} className="mt-4 p-3 w-full rounded border border-gray-700 bg-gray-900 text-white focus:outline-none" />
            <button className="bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded mt-4" onClick={executeTxEthers} disabled={!recipientAddress}>
              Send 0.001 {chain?.nativeCurrency.name}
            </button>
            {transactionHash && <p className="text-green-500 mt-4">Transaction Hash: {transactionHash}</p>}
          </div>
        </>
      )}
    </div>
  );
}
```

### Available Particle Connect hooks

This example shows a basic use of Particle Connect. For the complete list of
available hooks, see the
[Particle Connect documentation](https://developers.particle.network/social-logins/connect/desktop/web#key-react-hooks-for-particle-connect).

## Conclusion

A Sei dApp that uses both social logins and smart accounts needs only a few
lines of code. If you already use ethers, Web3.js, or another standard library
that supports EIP-1193 providers, the code is even shorter.

To see the complete demo dApp that uses the code snippets in this guide, go to
the [GitHub repository](https://github.com/Particle-Network/sei-aa-connect).

To learn more about Particle Network, see these resources:

* [Website](https://particle.network)
* [Blog](https://blog.particle.network)
* [Documentation](https://developers.particle.network)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.