From be7a72e5335c8191ba355db0889a24702a7b30d8 Mon Sep 17 00:00:00 2001 From: Soos3D <99700157+soos3d@users.noreply.github.com> Date: Mon, 9 Sep 2024 14:51:27 -0300 Subject: [PATCH 1/2] App Particle Network tutorial --- docs/fuse-box/tutorials/partner/README.mdx | 1 + .../tutorials/partner/particle-connect.mdx | 591 ++++++++++++++++++ 2 files changed, 592 insertions(+) create mode 100644 docs/fuse-box/tutorials/partner/particle-connect.mdx diff --git a/docs/fuse-box/tutorials/partner/README.mdx b/docs/fuse-box/tutorials/partner/README.mdx index 39e3960a..9ccc1969 100644 --- a/docs/fuse-box/tutorials/partner/README.mdx +++ b/docs/fuse-box/tutorials/partner/README.mdx @@ -7,3 +7,4 @@ sidebar_position: 3 | :------------------------------------------------------------ | :---- | | [FuseBox Login using MetaMask](metamask-login) | Web | | [FuseBox Social Login using Web3Auth](web3auth-login) | Web | +| [Social Logins and Account Abstraction with Particle Connect](particle-connect) | Web | diff --git a/docs/fuse-box/tutorials/partner/particle-connect.mdx b/docs/fuse-box/tutorials/partner/particle-connect.mdx new file mode 100644 index 00000000..87be51fa --- /dev/null +++ b/docs/fuse-box/tutorials/partner/particle-connect.mdx @@ -0,0 +1,591 @@ +--- +title: Social Logins and Account Abstraction with Particle Connect +sidebar_position: 8 +--- + +Particle Connect combines Social and Web3 logins with built-in Account Abstraction support, all within a single SDK. This approach allows you to simplify user onboarding while directly incorporating AA features into your **Fuse dApp**. + +Integrating **Particle Connect** into your **Fuse** web application can be done in **under five minutes**. + +This guide provides a concise overview of how to install, configure, and enable social logins in a Next.js application using `create @particle-network/connectkit` as your starting point. + +:::note +For a detailed explanation of each feature and more advanced configurations, refer to the [Particle Connect SDK reference](/api-reference/connect/desktop/web). +::: + +--- + +### Boilerplate: Initializing Particle Connect + +The easiest way to get started with **Particle Connect** is through its built-in starter/boilerplate; this includes the core file setup and code structure needed to configure Particle Connect. + +To initialize this boilerplate, copy and execute one of the following commands. + +```sh Terminal +npm init @particle-network/connectkit@latest +# or +pnpm create @particle-network/connectkit@latest +# or +yarn create @particle-network/connectkit +``` + +After running one of the aforementioned commands, the CLI will guide you through a setup process; it will prompt you to enter a project name, choose your preferred framework (Next.js or React), and select additional options. + +```shell Terminal +🤩 Welcome to Particle Network! + +✔ What is the name of your project? … connectkit-aa-usage + +✔ What is the template of your project? › create-next-app +✔ Which chains does your app support?​ › EVM +✔ Which ERC-4337 Contract does your app support?​ › SIMPLE-2.0.0 +✔ Does it support an embedded wallet?​ … yes +``` + +:::note +This guide will proceed with a **Next.js** project setup, although **React (create-react-app)** is also supported. + +Additionally, the **Fuse** Network for Account Abstraction is only supported by the `SIMPLE` instance of Smart Account. +::: + +### Configuring Particle Connect + +With a starter project initialized, you're ready to configure Particle Connect through its core component, `ConnectKitProvider`. + +Before diving deeper, you'll need some keys from the [Particle dashboard](https://dashboard.particle.network). + +**Particle Connect** requires three key values from the dashboard to be initiated: `projectId`, `clientKey`, and `appId`. + +### Access the Particle Dashboard + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +:::note +To get started, sign up or log in to the [Particle dashboard](https://dashboard.particle.network). +::: + +### Create a New Project or Use an Existing One + + + + +You can create a new project by clicking the **Add New Project** button on the dashboard. + + + + +Already have a project? Simply choose your existing project from the list on the dashboard. + + + + +### Create a New Web Application + +Create a new **Web** application from the **Your Apps** section in the Particle dashboard. + +### Retrieve the Project ID, Client Key, and Application ID + +Follow these steps to retrieve your credentials: + +1. Navigate to the **Project Information** section in your dashboard. + - Here, you'll find both your `projectId` and `clientKey`. +2. Go to the **Your Apps** section. + - Locate the web application you just created (or an existing one), and find the `appId` listed under the app's details. + +:::note +For a quick overview of the Particle dashboard, watch [this video](https://www.youtube.com/watch?v=d7DYCMNDmjo&ab_channel=ParticleNetwork) or check out the [Dashboard Quickstart Guide](/guides/dashboard). +::: + +After obtaining your `projectId`, `clientKey`, and `appId`, you'll need to use these to configure the `ConnectKitProvider` component from `@particle-network/connectkit`. + +The boilerplate already includes the basic variable setup—just add your API keys to the `.env.sample` file and rename it to `.env`. + +:::tip +At this point, you're ready to either run and test the application or begin development through `app/page.tsx`. + +We’ll also go over some of the granular controls available through `ConnectKitProvider`. +::: + +### Configuring ConnectKitProvider + +When working with `ConnectKitProvider`, it's recommended to use a dedicated `Connectkit.tsx` file in the `src` directory where you can configure and export the component. Then, you'll use this export to wrap your main App component (the location of your Particle Connect implementation through `ConnectButton`). + +Here’s how you can configure `ConnectKitProvider`: + +**Required Configurations:** +- `projectId`, `clientKey`, and `appId` — Get these from the [Particle dashboard](https://dashboard.particle.network). +- `chains` — Specify the supported chains for your dApp (this is an array of Viem-originating chain objects imported from `@particle-network/connectkit/chains`). +- `walletConnectors` — Define the wallets you want to support. + +**Optional Configurations:** +- `theme` and `language` for basic customization of the connection modal UI. +- Additional appearance customizations. + +:::note +In the boilerplate application, you'll find a pre-configured `Connectkit.tsx` file located in the `src` directory. +::: + +Below is an example of a **configured** instance of `ConnectKitProvider`. For more details around each available property, head over to the [Particle Connect Web SDK reference](/api-reference/connect/desktop/web). + +In this example, we import the `fuse` and `fuseSparknet` networks from `"@particle-network/connectkit/chains"`, and then add them to the `chains` array inside the `plugins` object. + +```tsx + +"use client"; + +// Particle imports +import { ConnectKitProvider, createConfig } from '@particle-network/connectkit'; +import { authWalletConnectors } from '@particle-network/connectkit/auth'; +import { evmWalletConnectors } from '@particle-network/connectkit/evm'; +import { solanaWalletConnectors } from '@particle-network/connectkit/solana'; +import { EntryPosition, wallet } from '@particle-network/connectkit/wallet'; + +import { fuse, fuseSparknet } from "@particle-network/connectkit/chains"; // Chains are imported here +import { aa } from "@particle-network/connectkit/aa"; // Account Abstraction packages +import React from 'react'; + +const config = createConfig({ + projectId: process.env.NEXT_PUBLIC_PROJECT_ID!, + clientKey: process.env.NEXT_PUBLIC_CLIENT_KEY!, + appId: process.env.NEXT_PUBLIC_APP_ID!, + + appearance: { + recommendedWallets: [ + { walletId: 'metaMask', label: 'Recommended' }, + { walletId: 'coinbaseWallet', label: 'popular' }, + ], + language: 'en-US', + mode: "auto", // dark or auto. + }, + + walletConnectors: [ + evmWalletConnectors({ + // Replace this with your app metadata. + metadata: { + name: 'Connectkit Demo', + icon: typeof window !== 'undefined' ? `${window.location.origin}/favicon.ico` : '', + description: 'Particle Connectkit Next.js Scaffold.', + url: typeof window !== 'undefined' ? window.location.origin : '', + }, + walletConnectProjectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID as string, + }), + + authWalletConnectors({ + authTypes: ['email', 'google', 'twitter', 'github'], // Optional, restricts the types of social logins supported + }), + ], + + plugins: [ + wallet({ + visible: true, + entryPosition: EntryPosition.BR, // Use BR (bottom right), BL (bottom left), TR (top right), TL (top left) to move the wallet entry position + }), + + // aa config start + aa({ + name: "SIMPLE", + version: "2.0.0", + }), + // aa config end + ], + + // List the chains you want to include + chains: [fuse, fuseSparknet], +}); + +// Wrap your application with this exported component, or ConnectKitProvider directly. +export const ParticleConnectkit = ({ children }: React.PropsWithChildren) => { + return {children}; +}; +``` + +:::tip +For more detailed information, visit the full [**Particle Connect** SDK documentation](/api-reference/connect/desktop/web). +::: + +### Wrapping Your Application with ConnectKitProvider + +Wrap your primary application component (wherever you place and use `ConnectButton` alongside the various hooks from Particle Connect) with the `ParticleConnectKit` component (exported from `ConnectKitProvider`). + +:::note +In the boilerplate application, you'll find a pre-configured `layout.tsx` file located in the `app` directory. +::: + +Here’s an example of what this looks like for a `layout.tsx` file: + +```tsx layout.tsx +import { ParticleConnectkit } from '@/connectkit'; // Export of a configured ConnectKitProvider instance +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 ( + + + {children} + + + ); +} +``` + +### Facilitating Logins and Chain Interactions + +With **Particle Connect** now configured, you can proceed to enable social logins within your application through the aforementioned `ConnectButton` component. + +Additionally, for driving application-level interaction (after initial onboarding), `@particle-network/connectkit` provides a variety of hooks. You can explore all available hooks in the [Particle Connect SDK documentation](/api-reference/connect/desktop/web#key-react-hooks-for-particle-connect). + +:::note +The boilerplate application includes a basic example featuring only a **Connect** button (`ConnectButton`). +::: + +After logging in (connecting), users can access the embedded wallet modal provided by **Particle Connect** via the button in the bottom right corner, unless customized through the `wallet` configuration within `ConnectKitProvider`. + +To explore additional features like fetching and displaying user information, balances, on-ramp services, and sending transactions using either the native Particle Provider (Viem-based WalletClient) or ethers.js through an EIP-1193 provider, paste the following code into `app/page.tsx`. + +```tsx page.tsx +"use client"; + +import React, { useEffect, useState } from "react"; + +// Particle imports +import { + ConnectButton, + useAccount, + useDisconnect, + usePublicClient, + useParticleAuth, + useWallets, +} from "@particle-network/connectkit"; + +// Connectkit uses Viem, so Viem's features can be utilized +import { formatEther, parseEther } from "viem"; + +// Optional: Import ethers provider for EIP-1193 compatibility +import { ethers, type Eip1193Provider } from "ethers"; + +export default function Home() { + // Initialize account-related states from Particle's useAccount hook + const { address, isConnected, isConnecting, isDisconnected, chainId } = + useAccount(); + const { disconnect, disconnectAsync } = useDisconnect(); + const { getUserInfo } = useParticleAuth(); + + // Optional: Initialize public client for RPC calls using Viem + const publicClient = usePublicClient(); + + // Retrieve the primary wallet from the Particle Wallets + const [primaryWallet] = useWallets(); + + // Define state variables + const [account, setAccount] = useState(null); // Store account information + const [balance, setBalance] = useState(""); // Store user's balance + const [userAddress, setUserAddress] = useState(""); // Store user's address + const [userInfo, setUserInfo] = useState(null); // Store user's information + const [isLoadingUserInfo, setIsLoadingUserInfo] = useState(false); // Loading state for fetching user info + const [userInfoError, setUserInfoError] = useState(null); // Error state for fetching user info + const [recipientAddress, setRecipientAddress] = useState(""); // Store recipient's address for transactions + const [transactionHash, setTransactionHash] = useState(null); // Store transaction hash after sending + const [isSending, setIsSending] = useState(false); // State for showing sending status + + // Connection status message + + based on the account's connection state + const connectionStatus = isConnecting + ? "Connecting..." + : isConnected + ? "Connected" + : isDisconnected + ? "Disconnected" + : "Unknown"; + + // Load account details and fetch balance when address or chainId changes + useEffect(() => { + async function loadAccount() { + if (address) { + setAccount(account); + setUserAddress(address); + await fetchBalance(); + } + } + loadAccount(); + }, [chainId, address]); + + // Fetch and set user information when connected + useEffect(() => { + const fetchUserInfo = async () => { + setIsLoadingUserInfo(true); + setUserInfoError(null); + + try { + const userInfo = await getUserInfo(); + console.log(userInfo); + setUserInfo(userInfo); + } catch (error) { + setUserInfoError( + "Error fetching user info: The current wallet is not a particle wallet." + ); + console.error("Error fetching user info:", error); + } finally { + setIsLoadingUserInfo(false); + } + }; + + if (isConnected) { + fetchUserInfo(); + } + }, [isConnected, getUserInfo]); + + // Fetch user's balance and format it for display + const fetchBalance = async () => { + try { + if (!address) return; + const balanceResponse = await publicClient?.getBalance({ address }); + const balanceInEther = formatEther(balanceResponse!); + console.log(balanceResponse); + setBalance(parseFloat(balanceInEther).toFixed(4)); // Display balance with 4 decimal places + } catch (error) { + console.error("Error fetching balance:", error); + } + }; + + // Handle user disconnect action + const handleDisconnect = async () => { + try { + await disconnectAsync(); + } catch (error) { + console.error("Error disconnecting:", error); + } + }; + + // Option 1: Send transaction using ethers.js with a custom EIP-1193 provider + const executeTxEthers = async () => { + const tx = { + to: recipientAddress, + value: parseEther("0.01"), // Set value to 0.01 Ether + data: "0x", // No data, as there is no contract interaction + }; + + setIsSending(true); + + try { + const EOAprovider = await primaryWallet.connector.getProvider(); + const customProvider = new ethers.BrowserProvider( + EOAprovider as Eip1193Provider, + "any" + ); + + const signer = await customProvider.getSigner(); + const txResponse = await signer.sendTransaction(tx); + const txReceipt = await txResponse.wait(); + + if (txReceipt) { + setTransactionHash(txReceipt.hash); + } else { + console.error("Transaction receipt is null"); + } + } catch (error) { + console.error("Error executing EVM transaction:", error); + } finally { + setIsSending(false); + } + }; + + // Option 2: Send transaction using the native Particle provider + const executeTxNative = async () => { + try { + const tx = { + to: recipientAddress, + value: parseEther("0.01"), // Set value to 0.01 Ether + data: "0x", // No data, as there is no contract interaction + chainId: primaryWallet.chainId, // Current chainId + account: primaryWallet.accounts[0], // Primary account + }; + + setIsSending(true); + + const walletClient = primaryWallet.getWalletClient(); + const transactionResponse = await walletClient.sendTransaction(tx); + + setTransactionHash(transactionResponse); + console.log("Transaction sent:", transactionResponse); + } catch (error) { + console.error("Failed to send transaction:", error); + } finally { + setIsSending(false); + } + }; + + // Parameters for the on-ramp URL + const fiatCoin = "USD"; + const cryptoCoin = "ETH"; + const network = "Ethereum"; + const theme = "dark"; + const language = "en"; + + // Function to handle the on-ramp button click + const handleOnRamp = () => { + const onRampUrl = `https://ramp.particle.network/?fiatCoin=${fiatCoin}&cryptoCoin=${cryptoCoin}&network=${network}&theme=${theme}&language=${language}`; + window.open(onRampUrl, "_blank"); + }; + + // Function to copy text to clipboard + const copyToClipboard = (text: string) => { + navigator.clipboard.writeText(text).then(() => { + alert("Copied to clipboard!"); + }); + }; + + // Function to truncate Ethereum address + const truncateAddress = (address: string) => { + return address.slice(0, 6) + "..." + address.slice(-4); + }; + + return ( +
+ {/* Header */} +
+ Particle Network Logo +

Particle Connect 2.0

+

+ Particle Connect Quickstart— Fetch user data and send trasnactions +

+
+ +
+ {/* Display connection status */} +
+

+ Status: {connectionStatus} +

+
+ + {isConnected ? ( + <> +
+
+
+ {isLoadingUserInfo ? ( +
Loading user info...
+ ) : userInfoError ? ( +
{userInfoError}
+ ) : ( + userInfo && ( // Conditionally render user info +
+

+ Name: {userInfo.name || "N/A"} +

+ {userInfo.avatar && ( + User Avatar + )} +
+ ) + )} +

+ Address: {truncateAddress(userAddress)} + +

+

+ Chain ID: {chainId} +

+

+ Balance: {balance !== "" ? balance : "Loading..."} + +

+ +
+ +
+
+ +
+

+ Send a transaction +

+

Send 0.01

+ setRecipientAddress(e.target.value)} + className="mt-4 p-2 + + w-full rounded border border-gray-700 bg-gray-900 text-white focus:outline-none focus:ring-2 focus:ring-purple-400" + /> + + + {/* Display transaction notification with the hash */} + {transactionHash && ( +
+ Transaction Hash: {transactionHash} +
+ )} +
+
+
+ + ) : ( + + )} +
+
+ ); +} +``` + +:::tip + A Next.js demo repository containing the above code can be found on [GitHub](https://github.com/Particle-Network/particle-connectkit2.0-quickstart). +::: From 46bda83489fcfbec519c98e65fd0fc12f90cf370 Mon Sep 17 00:00:00 2001 From: Soos3D <99700157+soos3d@users.noreply.github.com> Date: Mon, 9 Sep 2024 15:15:21 -0300 Subject: [PATCH 2/2] Update particle-connect.mdx --- .../tutorials/partner/particle-connect.mdx | 336 +----------------- 1 file changed, 3 insertions(+), 333 deletions(-) diff --git a/docs/fuse-box/tutorials/partner/particle-connect.mdx b/docs/fuse-box/tutorials/partner/particle-connect.mdx index 87be51fa..61b4f290 100644 --- a/docs/fuse-box/tutorials/partner/particle-connect.mdx +++ b/docs/fuse-box/tutorials/partner/particle-connect.mdx @@ -45,7 +45,7 @@ After running one of the aforementioned commands, the CLI will guide you through :::note This guide will proceed with a **Next.js** project setup, although **React (create-react-app)** is also supported. -Additionally, the **Fuse** Network for Account Abstraction is only supported by the `SIMPLE` instance of Smart Account. +Additionally, Account Abstraction on Fuse is only supported through the `SIMPLE` instance of Smart Account. ::: ### Configuring Particle Connect @@ -254,338 +254,8 @@ The boilerplate application includes a basic example featuring only a **Connect* After logging in (connecting), users can access the embedded wallet modal provided by **Particle Connect** via the button in the bottom right corner, unless customized through the `wallet` configuration within `ConnectKitProvider`. -To explore additional features like fetching and displaying user information, balances, on-ramp services, and sending transactions using either the native Particle Provider (Viem-based WalletClient) or ethers.js through an EIP-1193 provider, paste the following code into `app/page.tsx`. - -```tsx page.tsx -"use client"; - -import React, { useEffect, useState } from "react"; - -// Particle imports -import { - ConnectButton, - useAccount, - useDisconnect, - usePublicClient, - useParticleAuth, - useWallets, -} from "@particle-network/connectkit"; - -// Connectkit uses Viem, so Viem's features can be utilized -import { formatEther, parseEther } from "viem"; - -// Optional: Import ethers provider for EIP-1193 compatibility -import { ethers, type Eip1193Provider } from "ethers"; - -export default function Home() { - // Initialize account-related states from Particle's useAccount hook - const { address, isConnected, isConnecting, isDisconnected, chainId } = - useAccount(); - const { disconnect, disconnectAsync } = useDisconnect(); - const { getUserInfo } = useParticleAuth(); - - // Optional: Initialize public client for RPC calls using Viem - const publicClient = usePublicClient(); - - // Retrieve the primary wallet from the Particle Wallets - const [primaryWallet] = useWallets(); - - // Define state variables - const [account, setAccount] = useState(null); // Store account information - const [balance, setBalance] = useState(""); // Store user's balance - const [userAddress, setUserAddress] = useState(""); // Store user's address - const [userInfo, setUserInfo] = useState(null); // Store user's information - const [isLoadingUserInfo, setIsLoadingUserInfo] = useState(false); // Loading state for fetching user info - const [userInfoError, setUserInfoError] = useState(null); // Error state for fetching user info - const [recipientAddress, setRecipientAddress] = useState(""); // Store recipient's address for transactions - const [transactionHash, setTransactionHash] = useState(null); // Store transaction hash after sending - const [isSending, setIsSending] = useState(false); // State for showing sending status - - // Connection status message - - based on the account's connection state - const connectionStatus = isConnecting - ? "Connecting..." - : isConnected - ? "Connected" - : isDisconnected - ? "Disconnected" - : "Unknown"; - - // Load account details and fetch balance when address or chainId changes - useEffect(() => { - async function loadAccount() { - if (address) { - setAccount(account); - setUserAddress(address); - await fetchBalance(); - } - } - loadAccount(); - }, [chainId, address]); - - // Fetch and set user information when connected - useEffect(() => { - const fetchUserInfo = async () => { - setIsLoadingUserInfo(true); - setUserInfoError(null); - - try { - const userInfo = await getUserInfo(); - console.log(userInfo); - setUserInfo(userInfo); - } catch (error) { - setUserInfoError( - "Error fetching user info: The current wallet is not a particle wallet." - ); - console.error("Error fetching user info:", error); - } finally { - setIsLoadingUserInfo(false); - } - }; - - if (isConnected) { - fetchUserInfo(); - } - }, [isConnected, getUserInfo]); - - // Fetch user's balance and format it for display - const fetchBalance = async () => { - try { - if (!address) return; - const balanceResponse = await publicClient?.getBalance({ address }); - const balanceInEther = formatEther(balanceResponse!); - console.log(balanceResponse); - setBalance(parseFloat(balanceInEther).toFixed(4)); // Display balance with 4 decimal places - } catch (error) { - console.error("Error fetching balance:", error); - } - }; - - // Handle user disconnect action - const handleDisconnect = async () => { - try { - await disconnectAsync(); - } catch (error) { - console.error("Error disconnecting:", error); - } - }; - - // Option 1: Send transaction using ethers.js with a custom EIP-1193 provider - const executeTxEthers = async () => { - const tx = { - to: recipientAddress, - value: parseEther("0.01"), // Set value to 0.01 Ether - data: "0x", // No data, as there is no contract interaction - }; - - setIsSending(true); - - try { - const EOAprovider = await primaryWallet.connector.getProvider(); - const customProvider = new ethers.BrowserProvider( - EOAprovider as Eip1193Provider, - "any" - ); - - const signer = await customProvider.getSigner(); - const txResponse = await signer.sendTransaction(tx); - const txReceipt = await txResponse.wait(); - - if (txReceipt) { - setTransactionHash(txReceipt.hash); - } else { - console.error("Transaction receipt is null"); - } - } catch (error) { - console.error("Error executing EVM transaction:", error); - } finally { - setIsSending(false); - } - }; - - // Option 2: Send transaction using the native Particle provider - const executeTxNative = async () => { - try { - const tx = { - to: recipientAddress, - value: parseEther("0.01"), // Set value to 0.01 Ether - data: "0x", // No data, as there is no contract interaction - chainId: primaryWallet.chainId, // Current chainId - account: primaryWallet.accounts[0], // Primary account - }; - - setIsSending(true); - - const walletClient = primaryWallet.getWalletClient(); - const transactionResponse = await walletClient.sendTransaction(tx); - - setTransactionHash(transactionResponse); - console.log("Transaction sent:", transactionResponse); - } catch (error) { - console.error("Failed to send transaction:", error); - } finally { - setIsSending(false); - } - }; - - // Parameters for the on-ramp URL - const fiatCoin = "USD"; - const cryptoCoin = "ETH"; - const network = "Ethereum"; - const theme = "dark"; - const language = "en"; - - // Function to handle the on-ramp button click - const handleOnRamp = () => { - const onRampUrl = `https://ramp.particle.network/?fiatCoin=${fiatCoin}&cryptoCoin=${cryptoCoin}&network=${network}&theme=${theme}&language=${language}`; - window.open(onRampUrl, "_blank"); - }; - - // Function to copy text to clipboard - const copyToClipboard = (text: string) => { - navigator.clipboard.writeText(text).then(() => { - alert("Copied to clipboard!"); - }); - }; - - // Function to truncate Ethereum address - const truncateAddress = (address: string) => { - return address.slice(0, 6) + "..." + address.slice(-4); - }; - - return ( -
- {/* Header */} -
- Particle Network Logo -

Particle Connect 2.0

-

- Particle Connect Quickstart— Fetch user data and send trasnactions -

-
- -
- {/* Display connection status */} -
-

- Status: {connectionStatus} -

-
- - {isConnected ? ( - <> -
-
-
- {isLoadingUserInfo ? ( -
Loading user info...
- ) : userInfoError ? ( -
{userInfoError}
- ) : ( - userInfo && ( // Conditionally render user info -
-

- Name: {userInfo.name || "N/A"} -

- {userInfo.avatar && ( - User Avatar - )} -
- ) - )} -

- Address: {truncateAddress(userAddress)} - -

-

- Chain ID: {chainId} -

-

- Balance: {balance !== "" ? balance : "Loading..."} - -

- -
- -
-
- -
-

- Send a transaction -

-

Send 0.01

- setRecipientAddress(e.target.value)} - className="mt-4 p-2 - - w-full rounded border border-gray-700 bg-gray-900 text-white focus:outline-none focus:ring-2 focus:ring-purple-400" - /> - - - {/* Display transaction notification with the hash */} - {transactionHash && ( -
- Transaction Hash: {transactionHash} -
- )} -
-
-
- - ) : ( - - )} -
-
- ); -} -``` +Find an example of additional features like fetching and displaying user information, balances, on-ramp services, and sending transactions using either the native Particle Provider (Viem-based WalletClient) or ethers.js through an EIP-1193 provider from the [page.tsx](https://github.com/Particle-Network/particle-connectkit2.0-quickstart/blob/main/particle-connect/src/app/page.tsx) file in the demo repository. :::tip - A Next.js demo repository containing the above code can be found on [GitHub](https://github.com/Particle-Network/particle-connectkit2.0-quickstart). + A Next.js demo repository can be found on [GitHub](https://github.com/Particle-Network/particle-connectkit2.0-quickstart). :::