Privy signer
Privy is an embedded wallet provider that simplifies user onboarding for dApps, enabling seamless authentication and key management.
By integrating Privy with Connect 4337, you can use Privy as a signer to create and manage smart wallets while using Connect 4337 gas sponsorship, batched transactions, and more.
Create the Privy provider
Follow Privy’s quickstart guide, to set up the Privy provider in your app.
import { PrivyProvider } from '@privy-io/react-auth';
import {WagmiProvider} from '@privy-io/wagmi';
import {QueryClient, QueryClientProvider} from '@tanstack/react-query';
import {createConfig} from '@privy-io/wagmi';
import { http } from "viem";
import { arbitrumSepolia } from "viem/chains";
const queryClient = new QueryClient();
const config = createConfig({
chains: [arbitrumSepolia],
transports: {
[arbitrumSepolia.id]: http(),
},
});
<PrivyProvider
appId={"<Privy-App-Id>"}
config={{
embeddedWallets: {
createOnLogin: "all-users",
},
}}
>
<QueryClientProvider client={queryClient}>
<WagmiProvider config={config}>
{children}
</WagmiProvider>
</QueryClientProvider>
</PrivyProvider>;
Integration
In your app, set Privy's embedded wallet as the active wallet for wagmi by using the useWallets react hook (after Privy login).
import { useWallets } from "@privy-io/react-auth";
const { wallets } = useWallets();
const embeddedWallet = wallets.find(
(wallet) => wallet.walletClientType === "privy"
);
Use it with Connect 4337:
import {
createComethPaymasterClient,
createSafeSmartAccount,
createSmartAccountClient,
providerToSmartAccountSigner
} from "@cometh/connect-sdk-4337";
import { type Hex, type PublicClient, createPublicClient, http } from "viem";
import { arbitrumSepolia } from "viem/chains";
const apiKey = process.env.COMETH_API_KEY;
const bundlerUrl = process.env.4337_BUNDLER_URL;
const paymasterUrl = process.env.NEXT_PUBLIC_4337_PAYMASTER_URL;
if (!embeddedWallet) throw new Error("User does not have an embedded wallet");
const privyProvider = await embeddedWallet!.getEthereumProvider()
const signer = await providerToSmartAccountSigner(privyProvider);
const publicClient = createPublicClient({
chain: arbitrumSepolia,
transport: http(),
cacheTime: 60_000,
batch: {
multicall: { wait: 50 },
},
}) as PublicClient;
const smartAccount = await createSafeSmartAccount({
apiKey,
signer,
chain: arbitrumSepolia,
publicClient,
smartAccountAddress //if smart account already exists
});
const walletAddress = smartAccount.address
const paymasterClient = await createComethPaymasterClient({
transport: http(paymasterUrl),
chain: arbitrumSepolia,
publicClient,
});
const smartAccountClient = createSmartAccountClient({
account: smartAccount,
chain: arbitrumSepolia,
bundlerTransport: http(bundlerUrl, {
retryCount: 5,
retryDelay: 1000,
timeout: 20_000,
}),
paymaster: paymasterClient,
userOperation: {
estimateFeesPerGas: async () => {
return await paymasterClient.getUserOperationGasPrice();
},
},
});
Last updated