Setup and Configuration
- Alchemy Account Kit
- Biconomy
- Gelato
- Pimlico
- Rhinestone
- Safe
- Thirdweb
- ZeroDev
Installation
Copy
Ask AI
npm install --save-exact @aa-sdk/core@latest @account-kit/infra@latest @account-kit/smart-contracts@latest viem
Configuration
useAlchemySmartAccount.ts
Copy
Ask AI
import { type WalletClient, http, createWalletClient } from "viem";
import { sepolia } from "viem/chains";
import { useViemAccount } from "@getpara/react-sdk";
import { WalletClientSigner } from "@aa-sdk/core";
import { createModularAccountAlchemyClient } from "@account-kit/smart-contracts";
import { alchemy } from "@account-kit/infra";
import { useState, useEffect } from "react";
// Configuration constants - Replace with your values
const CHAIN = sepolia; // Target chain
const ALCHEMY_RPC_URL = "https://eth-sepolia.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY"; // Replace with your Alchemy RPC URL
const GAS_POLICY_ID = "YOUR_ALCHEMY_GAS_POLICY_ID"; // Replace with your Alchemy gas policy ID
const salt = "YOUR_SALT"; // Used for account creation.
export const useAlchemySmartAccount = () => {
const { viemAccount, isLoading: accountLoading } = useViemAccount();
const [client, setClient] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const initializeClient = async () => {
if (!viemAccount || accountLoading) return;
try {
// Create a Viem WalletClient with the Para account
const walletClient: WalletClient = createWalletClient({
account: viemAccount,
chain: CHAIN,
transport: http(ALCHEMY_RPC_URL)
});
// Create WalletClientSigner from the Viem WalletClient
const walletClientSigner = new WalletClientSigner(walletClient, "wallet");
// Create modular account Alchemy client with the WalletClientSigner
const alchemyClient = await createModularAccountAlchemyClient({
transport: alchemy({ rpcUrl: ALCHEMY_RPC_URL }),
chain: CHAIN,
signer: walletClientSigner,
policyId: GAS_POLICY_ID,
salt,
});
setClient(alchemyClient);
} catch (error) {
console.error("Failed to initialize Alchemy client:", error);
} finally {
setIsLoading(false);
}
};
initializeClient();
}, [viemAccount, accountLoading]);
return { client, isLoading: isLoading || accountLoading };
};
Installation
Copy
Ask AI
npm install --save-exact @biconomy/account@latest viem@latest
Configuration
useBiconomySmartAccount.ts
Copy
Ask AI
import { type WalletClient, http, createWalletClient } from "viem";
import { sepolia } from "viem/chains";
import { useViemAccount } from "@getpara/react-sdk";
import { createSmartAccountClient } from '@biconomy/account';
import { useState, useEffect } from "react";
// Configuration constants - Replace with your values
const CHAIN = sepolia; // Target chain
const RPC_URL = "https://ethereum-sepolia-rpc.publicnode.com"; // Your RPC endpoint
const BUNDLER_API_KEY = 'YOUR_BICONOMY_BUNDLER_API_KEY'; // From dashboard.biconomy.io
const PAYMASTER_API_KEY = 'YOUR_BICONOMY_PAYMASTER_API_KEY'; // From dashboard.biconomy.io (optional for paymaster)
const BUNDLER_URL = `https://bundler.biconomy.io/api/v2/${CHAIN.id}/${BUNDLER_API_KEY}`; // Biconomy bundler URL
const PAYMASTER_URL = `https://paymaster.biconomy.io/api/v2/${CHAIN.id}/${PAYMASTER_API_KEY}`; // Biconomy paymaster URL (optional)
export const useBiconomySmartAccount = () => {
const { viemAccount, isLoading: accountLoading } = useViemAccount();
const [smartAccountClient, setSmartAccountClient] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const initializeClient = async () => {
if (!viemAccount || accountLoading) return;
try {
// Create a Viem WalletClient with the Para account
const walletClient: WalletClient = createWalletClient({
account: viemAccount,
chain: CHAIN,
transport: http(RPC_URL)
});
// Create Biconomy smart account client with the WalletClient
const client = await createSmartAccountClient({
signer: walletClient,
chainId: CHAIN.id,
bundlerUrl: BUNDLER_URL,
paymasterUrl: PAYMASTER_URL, // Optional; include for gasless tx support
});
setSmartAccountClient(client);
} catch (error) {
console.error("Failed to initialize Biconomy client:", error);
} finally {
setIsLoading(false);
}
};
initializeClient();
}, [viemAccount, accountLoading]);
return { smartAccountClient, isLoading: isLoading || accountLoading };
};
Installation
Copy
Ask AI
npm install --save-exact @gelatonetwork/smartwallet viem
Configuration
useGelatoSmartAccount.ts
Copy
Ask AI
import { createPublicClient, http, createWalletClient } from "viem";
import { sepolia } from "viem/chains";
import { useViemAccount } from "@getpara/react-sdk";
import { createGelatoSmartWalletClient, accounts } from "@gelatonetwork/smartwallet";
import { useState, useEffect } from "react";
// Configuration constants - Replace with your values
const CHAIN = sepolia; // Target chain
const RPC_URL = "https://ethereum-sepolia-rpc.publicnode.com"; // Your RPC endpoint
const GELATO_API_KEY = "YOUR_GELATO_API_KEY"; // Gelato API key
const WALLET_INDEX = 0n; // Account index for deterministic addresses
export const useGelatoSmartAccount = () => {
const { viemAccount, isLoading: accountLoading } = useViemAccount();
const [smartWalletClient, setSmartWalletClient] = useState(null);
const [walletClient, setWalletClient] = useState(null);
const [kernelAccount, setKernelAccount] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const initializeClient = async () => {
if (!viemAccount || accountLoading) return;
try {
// Create a public client for the chain
const publicClient = createPublicClient({
chain: CHAIN,
transport: http(RPC_URL)
});
// Create Gelato Kernel account with Para as the owner
const kernel = await accounts.kernel({
owner: viemAccount,
client: publicClient,
index: WALLET_INDEX,
eip7702: false, // Disable EIP-7702 mode
});
// Create wallet client with the kernel account
const wallet = createWalletClient({
account: kernel,
chain: CHAIN,
transport: http(RPC_URL),
});
// Create Gelato smart wallet client for gasless transactions
const smartWallet = await createGelatoSmartWalletClient(wallet, {
apiKey: GELATO_API_KEY,
});
setKernelAccount(kernel);
setWalletClient(wallet);
setSmartWalletClient(smartWallet);
} catch (error) {
console.error("Failed to initialize Gelato client:", error);
} finally {
setIsLoading(false);
}
};
initializeClient();
}, [viemAccount, accountLoading]);
return { smartWalletClient, walletClient, kernelAccount, isLoading: isLoading || accountLoading };
};
Installation
Copy
Ask AI
npm install --save-exact permissionless viem
Configuration
usePimlicoSmartAccount.ts
Copy
Ask AI
import { http, createPublicClient } from "viem";
import { sepolia } from "viem/chains";
import { useViemAccount } from "@getpara/react-sdk";
import { createSmartAccountClient, toSimpleSmartAccount } from "permissionless";
import { createPimlicoClient } from "permissionless/clients/pimlico";
import { entryPoint07Address } from "viem/account-abstraction";
import { useState, useEffect } from "react";
// Configuration constants - Replace with your values
const CHAIN = sepolia; // Target chain
const RPC_URL = "https://ethereum-sepolia-rpc.publicnode.com"; // Your RPC endpoint
const PIMLICO_API_KEY = 'YOUR_PIMLICO_API_KEY'; // From dashboard.pimlico.io
const PIMLICO_URL = `https://api.pimlico.io/v2/${CHAIN.id}/rpc?apikey=${PIMLICO_API_KEY}`;
export const usePimlicoSmartAccount = () => {
const { viemAccount, isLoading: accountLoading } = useViemAccount();
const [smartAccountClient, setSmartAccountClient] = useState(null);
const [pimlicoClient, setPimlicoClient] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const initializeClient = async () => {
if (!viemAccount || accountLoading) return;
try {
// Create Viem PublicClient (needed for smart account)
const publicClient = createPublicClient({
chain: CHAIN,
transport: http(RPC_URL)
});
// Create a SimpleAccount using the Para account as owner
const simpleSmartAccount = await toSimpleSmartAccount({
owner: viemAccount, // Para account acts as the EOA owner
client: publicClient,
entryPoint: {
address: entryPoint07Address,
version: "0.7"
}
// Optional: you can specify index for deterministic address
// index: 0n
});
// Create Pimlico client for bundler operations
const pimlico = createPimlicoClient({
transport: http(PIMLICO_URL),
entryPoint: {
address: entryPoint07Address,
version: "0.7"
}
});
// Create the Smart Account Client
const client = createSmartAccountClient({
account: simpleSmartAccount,
chain: CHAIN,
bundlerTransport: http(PIMLICO_URL),
paymaster: pimlico, // Optional: for gasless transactions
userOperation: {
estimateFeesPerGas: async () => {
return (await pimlico.getUserOperationGasPrice()).fast
}
}
});
setPimlicoClient(pimlico);
setSmartAccountClient(client);
} catch (error) {
console.error("Failed to initialize Pimlico client:", error);
} finally {
setIsLoading(false);
}
};
initializeClient();
}, [viemAccount, accountLoading]);
return { smartAccountClient, pimlicoClient, isLoading: isLoading || accountLoading };
};
Installation
Copy
Ask AI
npm install --save-exact @rhinestone/sdk viem @tanstack/react-query
Configuration
useRhinestoneSmartAccount.ts
Copy
Ask AI
import { useState, useEffect, useCallback } from "react";
import { useWallet, useViemAccount } from "@getpara/react-sdk";
import { RhinestoneSDK, wrapParaAccount } from "@rhinestone/sdk";
import type { Account } from "viem";
// You can get a Rhinestone API key from the Rhinestone dashboard. You don't need a key to use the SDK on testnets.
// We recommend not storing the sponsoredAPI key in the client-side code.
// See https://docs.rhinestone.dev/sdk/security for more information.
const RHINESTONE_API_KEY = process.env.NEXT_PUBLIC_RHINESTONE_API_KEY;
export const useRhinestoneSmartAccount = () => {
const { data: wallet } = useWallet();
const { viemAccount, isLoading: accountLoading } = useViemAccount();
const [rhinestoneAccount, setRhinestoneAccount] = useState(null);
const [accountAddress, setAccountAddress] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const initializeAccount = async () => {
if (!viemAccount || !wallet?.id || accountLoading) return;
try {
// Initialize Rhinestone SDK
const rhinestone = new RhinestoneSDK({
apiKey: RHINESTONE_API_KEY,
endpointUrl: RHINESTONE_ENDPOINT,
});
// Wrap Para account for signature compatibility
const wrappedAccount = wrapParaAccount(viemAccount, wallet.id);
// Create Rhinestone cross-chain smart account
const account = await rhinestone.createAccount({
owners: {
type: "ecdsa",
accounts: [wrappedAccount as Account],
},
});
setRhinestoneAccount(account);
setAccountAddress(account.getAddress());
} catch (error) {
console.error("Failed to initialize Rhinestone account:", error);
} finally {
setIsLoading(false);
}
};
initializeAccount();
}, [viemAccount, wallet?.id, accountLoading]);
const sendCrossChainTransaction = useCallback(
async (sourceChains: any[], targetChain: any, calls: any[], tokenRequests: any[]) => {
if (!rhinestoneAccount) throw new Error("Account not initialized");
const transaction = await rhinestoneAccount.sendTransaction({
sourceChains,
targetChain,
calls,
tokenRequests,
sponsored: true, // Enable gas sponsorship
});
return await rhinestoneAccount.waitForExecution(transaction);
},
[rhinestoneAccount]
);
return {
rhinestoneAccount,
accountAddress,
sendCrossChainTransaction,
isLoading: isLoading || accountLoading
};
};
Installation
Copy
Ask AI
npm install --save-exact permissionless viem
Configuration
useSafeSmartAccount.ts
Copy
Ask AI
import { createWalletClient, http, createPublicClient } from "viem";
import { sepolia } from "viem/chains";
import { useViemAccount } from "@getpara/react-sdk";
import { createSmartAccountClient } from "permissionless";
import { toSafeSmartAccount } from "permissionless/accounts";
import { createPimlicoClient } from "permissionless/clients/pimlico";
import { entryPoint07Address } from "viem/account-abstraction";
import { useState, useEffect } from "react";
// Configuration constants - Replace with your values
const CHAIN = sepolia; // Target chain
const RPC_URL = "https://ethereum-sepolia-rpc.publicnode.com"; // Your RPC endpoint
const PIMLICO_API_KEY = 'YOUR_PIMLICO_API_KEY'; // From dashboard.pimlico.io
const PIMLICO_URL = `https://api.pimlico.io/v2/${CHAIN.id}/rpc?apikey=${PIMLICO_API_KEY}`;
export const useSafeSmartAccount = () => {
const { viemAccount, isLoading: accountLoading } = useViemAccount();
const [smartAccountClient, setSmartAccountClient] = useState(null);
const [safeAccount, setSafeAccount] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const initializeClient = async () => {
if (!viemAccount || accountLoading) return;
try {
// Create Viem WalletClient (used as the EOA owner)
const walletClient = createWalletClient({
account: viemAccount,
chain: CHAIN,
transport: http(RPC_URL)
});
// Create Viem PublicClient (needed for smart account)
const publicClient = createPublicClient({
chain: CHAIN,
transport: http(RPC_URL)
});
// Create a Safe account using the WalletClient as owner
const safe = await toSafeSmartAccount({
client: publicClient,
owners: [walletClient],
entryPoint: {
address: entryPoint07Address,
version: "0.7"
},
safeVersion: "1.4.1"
// Optional: index for deterministic address
// index: 0n
});
// Create Pimlico client for bundler operations
const pimlicoClient = createPimlicoClient({
transport: http(PIMLICO_URL),
entryPoint: {
address: entryPoint07Address,
version: "0.7"
}
});
// Create the Smart Account Client
const client = createSmartAccountClient({
account: safe,
chain: CHAIN,
bundlerTransport: http(PIMLICO_URL),
paymaster: pimlicoClient, // Optional: for gasless transactions
userOperation: {
estimateFeesPerGas: async () => {
return (await pimlicoClient.getUserOperationGasPrice()).fast
}
}
});
setSafeAccount(safe);
setSmartAccountClient(client);
} catch (error) {
console.error("Failed to initialize Safe client:", error);
} finally {
setIsLoading(false);
}
};
initializeClient();
}, [viemAccount, accountLoading]);
return { smartAccountClient, safeAccount, isLoading: isLoading || accountLoading };
};
Installation
Copy
Ask AI
npm install --save-exact thirdweb viem
Configuration
useThirdwebSmartAccount.ts
Copy
Ask AI
import { createWalletClient, http } from "viem";
import { sepolia } from "viem/chains";
import { useViemAccount } from "@getpara/react-sdk";
import { smartWallet } from "thirdweb/wallets";
import { viemAdapter } from "thirdweb/adapters/viem";
import { DEFAULT_ACCOUNT_FACTORY_V0_7 } from "thirdweb/wallets/smart";
import { createThirdwebClient } from "thirdweb";
import { useState, useEffect, useRef } from "react";
// Configuration constants - Replace with your values
const CHAIN = sepolia; // Target chain
const RPC_URL = "https://ethereum-sepolia-rpc.publicnode.com"; // Your RPC endpoint
const THIRDWEB_CLIENT_ID = "YOUR_THIRDWEB_CLIENT_ID"; // thirdweb client ID
const THIRDWEB_SECRET_KEY = "YOUR_THIRDWEB_SECRET_KEY"; // thirdweb secret
const WALLET_INDEX = 0n; // Account index for deterministic addresses
// Create singleton thirdweb client outside hook
const thirdwebClient = createThirdwebClient({
clientId: THIRDWEB_CLIENT_ID,
secretKey: THIRDWEB_SECRET_KEY,
});
export const useThirdwebSmartAccount = () => {
const { viemAccount, isLoading: accountLoading } = useViemAccount();
const [smartAccount, setSmartAccount] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const clientRef = useRef(thirdwebClient);
useEffect(() => {
const initializeClient = async () => {
if (!viemAccount || accountLoading) return;
try {
// Create Viem wallet client with Para account
const viemWalletClient = createWalletClient({
account: viemAccount,
chain: CHAIN,
transport: http(RPC_URL),
});
// Convert Viem wallet to thirdweb wallet
const personalAccount = viemAdapter.walletClient.fromViem({
walletClient: viemWalletClient,
});
// Generate deterministic salt for the smart wallet
const salt = `0x${WALLET_INDEX.toString(16).padStart(64, "0")}`;
// Configure smart wallet with gas sponsorship
const smartWalletConfig = smartWallet({
chain: CHAIN,
sponsorGas: true, // Enable gasless transactions
factoryAddress: DEFAULT_ACCOUNT_FACTORY_V0_7,
overrides: {
accountSalt: salt, // Deterministic address generation
},
});
// Connect the smart wallet with Para as the signer
const account = await smartWalletConfig.connect({
client: clientRef.current,
personalAccount,
});
setSmartAccount(account);
} catch (error) {
console.error("Failed to initialize Thirdweb client:", error);
} finally {
setIsLoading(false);
}
};
initializeClient();
}, [viemAccount, accountLoading]);
return { smartAccount, thirdwebClient: clientRef.current, isLoading: isLoading || accountLoading };
};
Installation
Copy
Ask AI
npm install --save-exact @zerodevapp/sdk viem
Configuration
useZeroDevSmartAccount.ts
Copy
Ask AI
import { createPublicClient, http, createWalletClient } from "viem";
import { sepolia } from "viem/chains";
import { useViemAccount } from "@getpara/react-sdk";
import { createKernelAccount, createKernelAccountClient } from "@zerodevapp/sdk";
import { useState, useEffect } from "react";
// Configuration constants - Replace with your values
const CHAIN = sepolia; // Target chain
const RPC_URL = "https://ethereum-sepolia-rpc.publicnode.com"; // Your RPC endpoint
const ZERODEV_PROJECT_ID = "YOUR_ZERODEV_PROJECT_ID"; // ZeroDev project ID
export const useZeroDevSmartAccount = () => {
const { viemAccount, isLoading: accountLoading } = useViemAccount();
const [kernelClient, setKernelClient] = useState(null);
const [kernelAccount, setKernelAccount] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const initializeClient = async () => {
if (!viemAccount || accountLoading) return;
try {
// Create a public client for the chain
const publicClient = createPublicClient({
chain: CHAIN,
transport: http(RPC_URL)
});
// Create wallet client with Para account
const walletClient = createWalletClient({
account: viemAccount,
chain: CHAIN,
transport: http(RPC_URL)
});
// Create Kernel account with Para as the signer
const kernel = await createKernelAccount(publicClient, {
plugins: {
sudo: walletClient
}
});
// Create Kernel account client with ZeroDev bundler
const client = createKernelAccountClient({
account: kernel,
chain: CHAIN,
transport: http(`https://rpc.zerodev.app/api/v2/bundler/${ZERODEV_PROJECT_ID}`),
});
setKernelAccount(kernel);
setKernelClient(client);
} catch (error) {
console.error("Failed to initialize ZeroDev client:", error);
} finally {
setIsLoading(false);
}
};
initializeClient();
}, [viemAccount, accountLoading]);
return { kernelClient, kernelAccount, isLoading: isLoading || accountLoading };
};
Smart Wallets contracts are deployed automatically on the first transaction by the provider. Meaning you don’t need to deploy them manually. However, you can deploy them manually if you want by signing and sending an empty transaction.