Particle Network的智能钱包即服务¶
概览¶
Particle Network是一个智能钱包即服务提供商,它允许开发者通过使用可定制的模块化外部拥有账户(Externally Owned Account,简称EOA)和账户抽象(Account Abstraction,简称AA)嵌入式钱包组件来提升用户体验。
Particle智能钱包即服务堆栈的其中一个重要组件是Particle Auth,该组件可通过用户熟悉的Web2账户(例如谷歌账户、邮箱地址和电话号码)简化用户入门流程。这是通过使用基于多方计算的阈值签名方案(MPC-TSS)技术进行密钥管理来实现的。
想要了解关于Particle堆栈的完整版介绍,请参考Particle的博客文章:介绍Particle智能钱包即服务模块化堆栈。
Particle通过标准EOA交互和原生ERC-4337 SimpleAccount实现支持Moonbeam、Moonriver和Moonbase Alpha测试网,从而促进全堆栈账户抽象。
具体来说,Particle Network的Moonbeam集成由以下组件组成:
- Particle Network Wallet-as-a-Service - 这是一个由Particle Network提供的钱包即服务旗舰产品,支持由MPC-TSS支持的应用程序嵌入式钱包,从而实现无缝且类似Web2入门和交互的体验。
- Particle Network Modular AA Stack - 除了以EOA为中心的基本交互之外(此交互默认情况下通过Particle的钱包即服务实现),Particle还具有原生模块化账户抽象堆栈,用于Moonbeam上ERC-4337账户抽象的实现。这意味着在构建支持账户抽象的应用程序时,您可以将智能账户、bundler和paymaster与Particle的钱包即服务结合使用,从而获得固有的灵活性
本教程中,我们将展示使用Particle Network的智能钱包即服务的分步教程。
创建应用程序¶
要在Moonbeam上使用Particle Network的智能钱包即服务,首先您需要通过在Particle Network数据面板创建账户并启动应用程序。
-
前往Particle Network数据面板,然后注册或登录
-
登陆后,点击Add New Project创建新项目
-
输入项目名称并点击Save保存
-
在项目的数据面板处,往下滑动找到Your Apps部分,选择iOS、Android或Web并提供要求的信息以创建新的App
-
最后,复制Project ID、Client Key和App ID
安装依赖项¶
要将Particle Network集成至Moonbeam,您需要安装一系列的依赖项,具体取决于您是否要完全使用Particle的钱包即服务生成的默认EOA,或使用附加的智能账户。
无论是使用EOA还是智能合约,都需要先安装@particle-network/auth
。
npm install @particle-network/auth
yarn add @particle-network/auth
如果您想要原生使用ERC-4337账户抽象,还需要安装@particle-network/aa
。
npm install @particle-network/aa
yarn add @particle-network/aa
创建抽象账户后,您需要将其传给提供商。您可以使用Particle或任何EVM钱包提供商。如果您使用的是Particle提供商,您需要安装@particle-network/provider
。
npm install @particle-network/provider
yarn add @particle-network/provider
配置Particle Network¶
创建好应用程序并安装完依赖项后,您可以开始配置项目了。
配置项目需要执行以下步骤:
- 从
@particle-network/auth
导入ParticleNetwork
- 您将在下一个步骤用到Moonbeam的链名称和ID,因此您需要先从
@particle-network/chains
导入Moonbeam
-
使用您的项目凭据以及Moonbeam的链名称和ID初始化
ParticleNetwork
,并且您可以在这里选择配置钱包显示和安全设置注意事项
您可以使用dotenv安全存储您的项目凭证。
"use client";
import React from "react";
import { ConnectKitProvider, createConfig } from "@particle-network/connectkit";
import { authWalletConnectors } from "@particle-network/connectkit/auth";
import { moonbeam } 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({})],
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: [moonbeam],
});
export const ParticleConnectkit = ({ children }: React.PropsWithChildren) => {
return <ConnectKitProvider config={config}>{children}</ConnectKitProvider>;
};
创建ERC-4337账户抽象¶
如果您想要使用ERC-4337账户抽象,您需要执行一些额外的步骤:
- 从
@particle-network/aa
和@particle-network/auth
导入SmartAccount
- 使用您在上述步骤创建的
particle
实例,初始化ParticleProvider
以处理钱包连接请求 - 使用提供商、项目凭证以及账户抽象实现和配置来初始化
SmartAccount
。对于Moonbeam来说,您需要使用simple
实现并传入Moonbeam链ID - 启用ERC-4337模式,指定
SIMPLE
实现
到现在为止,您已经注册并创建了一个应用程序,安装了所有所需依赖项,同时配置了ParticleNetwork
和SmartAccount
(若适用)。
包装EIP-1193提供商¶
如果您要与Ethers.js或Web3.js等以太坊库交互,您可以将账户抽象包装在自定义的提供商中。
为此,您需要执行以下步骤:
- 从
'@particle-network/aa'
导入AAWrapProvider
- 自行选择导入所需要的库
- 使用上述步骤中创建的账户抽象初始化
AAWrapProvider
- 使用所选择的库和
AAWrapProvider
包装EIP-1193提供商
使用示例¶
完成上述操作后,您可以根据上述类似步骤使用Particle Network,如下方示例应用程序所示:
具体来说,该应用程序通过社交登录在Moonbeam主网上创建一个智能账户,然后使用该应用程序发送一笔0.001 GLMR的测试交易。
"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.01").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 rounded-lg 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>
);
}
要查看包含上述代码的完整演示代码库,请访问particle-moonbeam-demo GitHub repository。
这就是关于Particle智能钱包即服务堆栈以及如何在Moonbeam上开始使用Particle的简要介绍。想要了解更多信息,请参考Particle Network文档网站。