Integrate Particle Network into a dApp
Introduction
Particle Network provides Wallet Abstraction services to simplify user onboarding.
The Particle Connect SDK supports EVM-compatible chains, including Kaia and its testnet. It allows for 2-click onboarding with social and Web3 login options, all within a single modal.
With Particle Network, developers on Kaia can embed social logins for the Kaia Mainnet and testnet, allowing users to generate and use a wallet within your application using only their Google, email, X, etc.
This page offers an overview and tutorial for implementing Particle Connect within a Kaia-based application, to help you start the integration process.
Prerequisites
- A Next.js project set up with TypeScript and Tailwind CSS
- You can create this by running:
npx create-next-app@latest
- You can create this by running:
- A Project ID, Client Key, and App ID from the Particle Dashboard.
Installation
To leverage Particle Network, specifically Particle Connect, within your dApp, you'll need to first install the required libraries. The Particle Connect SDK streamlines wallet creation, user login, and blockchain interactions with one interface. It supports both social and Web3 logins for easy access.
To install the SDK, along with Viem (backend for Connect) and ethers (demonstrating EIP-1193 providers), run:
yarn add @particle-network/connectkit viem@^2 ethers
Initializing Particle Connect
To begin with, we’ll set up Particle Connect, Particle's flagship authentication SDK. Create a new file called ConnectKit.tsx
in the root directory of your project. This file will house the ParticleConnectKit
component, a wrapper for the configured ConnectKitProvider
instance that serves as the primary interface for the configuration of Particle Connect (we'll go over what this looks like programmatically in a moment).
Next, head over to the Particle dashboard to create a new web application project and obtain the following essential API keys:
projectId
– a unique identifier for your project.clientKey
– a key specific to your client.appId
– the ID for your application.
Store these API keys in a .env
file as follows:
NEXT_PUBLIC_PROJECT_ID='PROJECT_ID'NEXT_PUBLIC_CLIENT_KEY='CLIENT_KEY'NEXT_PUBLIC_APP_ID='APP_ID'
Now, add the following code to your ConnectKit.tsx
file:
"use client";import React from "react";import { ConnectKitProvider, createConfig } from "@particle-network/connectkit";import { authWalletConnectors } from "@particle-network/connectkit/auth";import { defineChain } from "@particle-network/connectkit/chains";import { wallet, EntryPosition } from "@particle-network/connectkit/wallet";const kaiaMainnet = defineChain({ id: 8217, name: "Kaia", nativeCurrency: { decimals: 18, name: "KAIA", symbol: "KAIA", }, rpcUrls: { default: { http: ["https://public-en.node.kaia.io"], }, }, blockExplorers: { default: { name: "Explorer", url: "https://kaiascope.com/" }, }, testnet: false,});const kaiaTestnet = defineChain({ id: 1001, name: "Kaia Testnet", nativeCurrency: { decimals: 18, name: "KAIA", symbol: "KAIA", }, rpcUrls: { default: { http: ["https://public-en-kairos.node.kaia.io"], }, }, blockExplorers: { default: { name: "Explorer", url: "https://kairos.kaiascope.com/" }, }, testnet: true,});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({})], plugins: [ wallet({ entryPosition: EntryPosition.BR, // Positions the modal button at the bottom right on login visible: true, // Determines if the wallet modal is displayed }), ], chains: [kaiaMainnet, kaiaTestnet],});export const ParticleConnectkit = ({ children }: React.PropsWithChildren) => { return <ConnectKitProvider config={config}>{children}</ConnectKitProvider>;};
Virtually every property of this component can be configured, from the different login types you support to the visual appearance of the modal; to explore these various options, head over to Particle's documentation.
Integrate Particle Connect into Your App
Now that the configuration is complete, wrap your application with the ParticleConnectKit
component to enable global access to the Particle Connect SDK. To achieve this, modify your layout.tsx
file in the src
directory as follows:
import { ParticleConnectkit } from '@/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,}: { children: React.ReactNode;}) { return ( <html lang="en"> <body className={inter.className}> <ParticleConnectkit>{children}</ParticleConnectkit> </body> </html> );}
Connecting Wallet
With your layout.tsx
file setup, you can move on to connecting your users through a central Connect Wallet button. You can import ConnectButton
from @particle-network/connectkit
to do this. The ConnectButton
turns into an embedded widget once the user logs in.
import { ConnectButton, useAccount } from '@particle-network/connectkit';export const App = () => { const { address, isConnected, chainId } = useAccount(); // Standard ConnectButton utilization return ( <div> <ConnectButton /> {isConnected && ( <> <h2>Address: {address}</h2> <h2>Chain ID: {chainId}</h2> </> )} </div> );};
Getting Account and Balance
With a wallet (or social login) now successfully connected through the ConnectButton
component, you can retrieve the user's associated Kaia address. Additionally, you can retrieve its current balance (in KAIA) through the publicClient
, which leverages the Viem provider already set up by Particle Connect.
"use client";import { useState, useEffect } from "react";import { ConnectButton, useAccount, usePublicClient,} from "@particle-network/connectkit";import { formatEther } from "viem";export default function Home() { // Account-related states const { isConnected, address, chain } = useAccount(); const publicClient = usePublicClient(); // State variable for balance const [balance, setBalance] = useState<string>(""); // Fetch and display user balance when connected useEffect(() => { const fetchBalance = async () => { if (address) { try { const balanceResponse = await publicClient.getBalance({ address }); const balanceInEther = formatEther(balanceResponse); setBalance(balanceInEther); } catch (error) { console.error("Error fetching balance:", error); } } }; if (isConnected) { fetchBalance(); } }, [isConnected, address, publicClient]); return ( <div className="min-h-screen flex flex-col items-center justify-center p-8 bg-black text-white"> <ConnectButton label="Connect Wallet" /> {isConnected && ( <div className="w-full max-w-md mt-6"> <h2 className="text-xl font-bold text-white mb-4">Account Details</h2> <p className="text-lg text-white"> Address: {address || "Loading..."} </p> <p className="text-lg text-white"> Balance: {balance || "Loading..."} {chain?.nativeCurrency.symbol} </p> </div> )} </div> );}
Disconnecting Wallet
Once a user has logged in, you can programmatically force a logout through disconnect
derived from useDisconnect
. This will disconnect the current active session from your dApp, returning the user to their initial state.
import { useDisconnect } from "@particle-network/connectkit";const { disconnect } = useDisconnect();// Inside your component's JSX<button className="mt-4 w-full bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-4 rounded" onClick={disconnect}> Disconnect</button>
Getting User Info
When a user connects via social accounts, you can use the useParticleAuth()
hook to access userinfo
, which includes details about their connection method, account creation date, name, emails, and other relevant information from Particle Auth.
import { useAccount, useParticleAuth, useWallets } from '@particle-network/connectkit';import { useState, useEffect } from 'react';export const App = () => { const { getUserInfo } = useParticleAuth(); const { isConnected } = useAccount(); // Retrieve the primary wallet from the Particle Wallets const [primaryWallet] = useWallets(); // Store userInfo in a useState to use it in your app const [userInfo, setUserInfo] = useState<any>(null); useEffect(() => { const fetchUserInfo = async () => { // Use walletConnectorType as a condition to avoid account not initialized errors if (primaryWallet?.connector?.walletConnectorType === 'particleAuth') { const userInfo = await getUserInfo(); setUserInfo(userInfo); } }; fetchUserInfo(); }, [isConnected, getUserInfo]); return <h2 className="text-style">Name: {userInfo.name || 'N/A'}</h2>;};
Sending Native Transaction
Particle Connect allows you to leverage an already existing EIP-1193 provider, in this example we create a provider instance with ethers
to send a transfer transaction.
import { useWallets } from "@particle-network/connectkit";import { ethers, type Eip1193Provider } from "ethers";const [primaryWallet] = useWallets();const executeTransaction = async () => { // Get the provider from the primary wallet's connector const EOAprovider = await primaryWallet.connector.getProvider(); // Initialize a custom provider using ethers.js with the obtained EIP-1193 provider const customProvider = new ethers.BrowserProvider(EOAprovider as Eip1193Provider, "any"); // Get the signer (an abstraction of the account that can sign transactions) const signer = await customProvider.getSigner(); // Send a transaction with specified recipient address, amount (0.01 ETH), and empty data await signer.sendTransaction({ to: recipientAddress, value: parseEther("0.01"), data: "0x", });};
Next Steps
You can find a complete list of hooks available on the Particle Connect docs.
For additional guides regarding Particle Network (Particle Connect, Particle Auth, and other SDKs), please refer to the Particle Network docs and the Particle Network GitHub account. Additionally, you may want to visit the Particle Network blog for additional information on Particle Network's services, upcoming releases, and tech stack.