We ran into this issue few days ago and have not been able to resolve it. just implementing some minor updates on our website and unable to redeploy.
SDK Version (package.json):
“@web3auth/account-abstraction-provider”: “^9.7.0”,
“@web3auth/base”: “^9.7.0”,
“@web3auth/ethereum-provider”: “^9.7.0”,
“@web3auth/modal”: “^9.7.0”,
“viem”: “2.28.0”
Platform:
- Framework: Next.js
15.0.3
- Node.js Version:
22.x
(on Vercel) and20.18.0
(locally) - Operating System: Windows 10 (local development)
Browser Console Screenshots: The error occurs during the build process, so there are no browser console logs. Below is the build error message:
./node_modules/permissionless/accounts/biconomy/toBiconomySmartAccount.ts:217:5
Type error: Type '{ client: Client<Transport, Chain | undefined, { address: `0x${string}`; nonceManager?: NonceManager | undefined; sign?: ((parameters: { hash: `0x${string}`; }) => Promise<...>) | undefined; ... 6 more ...; type: "local"; } | JsonRpcAccount | undefined>; ... 17 more ...; type: "smart"; } | { ...; }' is not assignable to type 'ToBiconomySmartAccountReturnType'.
Type '{ client: Client<Transport, Chain | undefined, { address: `0x${string}`; nonceManager?: NonceManager | undefined; sign?: ((parameters: { hash: `0x${string}`; }) => Promise<...>) | undefined; ... 6 more ...; type: "local"; } | JsonRpcAccount | undefined>; ... 17 more ...; type: "smart"; }' is not assignable to type 'ToBiconomySmartAccountReturnType'.
Type '{ client: import("/vercel/path0/node_modules/viem/_types/clients/createClient").Client<import("/vercel/path0/node_modules/viem/_types/clients/transports/createTransport").Transport, import("/vercel/path0/node_modules/viem/_types/types/chain").Chain | undefined, { ...; } | ... 1 more ... | undefined>; ... 17 more ......' is not assignable to type '{ client: import("/vercel/path0/node_modules/viem/_types/clients/createClient").Client<import("/vercel/path0/node_modules/viem/_types/clients/transports/createTransport").Transport, import("/vercel/path0/node_modules/viem/_types/types/chain").Chain | undefined, { ...; } | ... 1 more ... | undefined>; ... 17 more ......'. Two different types with this name exist, but they are unrelated.
The types of 'entryPoint.abi' are incompatible between these types.
Type 'Abi' is not assignable to type 'readonly [{ readonly inputs: readonly [{ readonly name: "preOpGas"; readonly type: "uint256"; }, { readonly name: "paid"; readonly type: "uint256"; }, { readonly name: "validAfter"; readonly type: "uint48"; }, { ...; }, { ...; }, { ...; }]; readonly name: "ExecutionResult"; readonly type: "error"; }, ... 35 more ......'.
Target requires 37 element(s) but source may have fewer.
Web3Auth Initialization and Login Code Snippet: Here is the relevant code snippet for Web3Auth initialization and login:
"use client";
// Importing necessary packages and components
import { CHAIN_NAMESPACES, IAdapter, IProvider, WEB3AUTH_NETWORK } from "@web3auth/base";
import { Box, Paper, Typography, Button, TextField } from "@mui/material";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { Web3Auth, Web3AuthOptions } from "@web3auth/modal";
import { AccountAbstractionProvider, SafeSmartAccount } from "@web3auth/account-abstraction-provider";
import { ethers } from "ethers"; // Used for blockchain interaction
import { formatUnits, parseUnits } from "ethers"; // Utility functions for token formatting
import { useEffect, useState, useRef } from "react"; // React hooks for managing state and lifecycle
// Web3Auth client ID for initialization
const clientId = "BNUKnfjxWu4bIu2S9XLdLm102AL6Lq2aLlyDIsBX77Qo81ztaO7UkUyBdpOJuuqaUnY9ugqn3Q3aeBZElwSTdvk";
// API key for Pimlico (bundler and paymaster)
const pimlicoAPIKey = "pim_NQiLku6tPP9FW3Tn7B78JH";
// USDC contract address on Polygon Amoy Testnet (replace with the correct address for other networks)
const usdcContractAddress = "0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582";
// Configuration for the blockchain (Polygon Amoy Testnet)
const chainConfig = {
chainNamespace: CHAIN_NAMESPACES.EIP155, // Ethereum-compatible namespace
chainId: "0x13882", // Chain ID for Polygon Amoy Testnet
rpcTarget: "https://rpc.ankr.com/polygon_amoy", // RPC URL for interacting with the chain
displayName: "Polygon Amoy Testnet", // Friendly name for the chain
ticker: "MATIC", // Currency ticker
tickerName: "Matic", // Currency full name
};
// Ethereum provider for private key-based interaction
const privateKeyProvider = new EthereumPrivateKeyProvider({
config: { chainConfig },
});
// Account abstraction provider configuration
const accountAbstractionProvider = new AccountAbstractionProvider({
config: {
chainConfig,
smartAccountInit: new SafeSmartAccount(), // Safe smart account initialization
bundlerConfig: {
url: `https://api.pimlico.io/v2/80002/rpc?apikey=${pimlicoAPIKey}`, // Bundler API URL
},
paymasterConfig: {
url: `https://api.pimlico.io/v2/80002/rpc?apikey=${pimlicoAPIKey}`, // Paymaster API URL
},
},
});
function App() {
// State variables
const [provider, setProvider] = useState<IProvider | null>(null); // Blockchain provider
const [usdcBalance, setUsdcBalance] = useState<string>(""); // USDC balance
const [walletAddress, setWalletAddress] = useState<string>(""); // User's wallet address
const [loggedIn, setLoggedIn] = useState(false); // Login state
const web3auth = useRef<Web3Auth | null>(null); // Ref for Web3Auth instance
const [isInitialized, setIsInitialized] = useState(false); // Web3Auth initialization status
// Form inputs for recipient and amount
const [recipientAddress, setRecipientAddress] = useState("");
const [amount, setAmount] = useState<number>(0);
const isValidAddress = (address: string): boolean => ethers.isAddress(address);
const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = parseFloat(e.target.value);
if (isNaN(value) || value <= 0) {
console.error("Invalid input for amount:", e.target.value);
return;
}
setAmount(value);
};
// Function to fetch and set the user's wallet address
const fetchWalletAddress = async () => {
if (provider) {
const signer = new ethers.BrowserProvider(provider).getSigner();
const address = await (await signer).getAddress();
setWalletAddress(address);
}
};
// Function to fetch and set the user's USDC balance
const fetchUsdcBalance = async () => {
if (provider) {
const signer = new ethers.BrowserProvider(provider).getSigner();
const usdcContract = new ethers.Contract(
usdcContractAddress,
["function balanceOf(address owner) view returns (uint256)"],
await signer
);
const balance = await usdcContract.balanceOf(await (await signer).getAddress());
setUsdcBalance(formatUnits(balance, 6)); // Assuming USDC has 6 decimals
}
};
// Initialization of Web3Auth
useEffect(() => {
const init = async () => {
try {
const web3AuthOptions: Web3AuthOptions = {
clientId,
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,
privateKeyProvider,
accountAbstractionProvider,
};
// Initialize Web3Auth
web3auth.current = new Web3Auth(web3AuthOptions);
await web3auth.current.initModal();
// Set initial state
setIsInitialized(true);
setProvider(web3auth.current.provider);
if (web3auth.current.connected) {
setLoggedIn(true);
await fetchWalletAddress();
await fetchUsdcBalance();
}
} catch (error) {
console.error("Error initializing Web3Auth:", error);
}
};
init(); // Call the initialization function
}, []);
// Refetch balance when logged in state changes
useEffect(() => {
if (loggedIn) {
fetchWalletAddress();
fetchUsdcBalance();
}
}, [loggedIn]);
// Function to handle USDC transfer
const sendUSDC = async () => {
try {
// Ensure provider and accountAbstractionProvider are initialized
if (!provider || !accountAbstractionProvider) {
console.error("Provider or Account Abstraction Provider is not initialized.");
return;
}
if (!isValidAddress(recipientAddress)) {
console.error("Invalid recipient address:", recipientAddress);
return;
}
if (!amount || isNaN(amount)) {
console.error("Invalid amount entered:", amount);
return;
}
console.log("Preparing to send USDC using Account Abstraction...");
// Convert the amount to BigInt with USDC's decimals (6 decimals)
const transferAmount = parseUnits(amount.toString(), 6);
// Get the bundler client and smart account from the AA provider
const bundlerClient = accountAbstractionProvider.bundlerClient!;
const smartAccount = accountAbstractionProvider.smartAccount!;
// Create and submit the User Operation
const abi = new ethers.Interface([
"function transfer(address to, uint256 amount)"
]);
const userOpHash = await bundlerClient.sendUserOperation({
account: smartAccount,
calls: [
{
to: usdcContractAddress, // USDC contract address
abi: abi.fragments, // Use ABI fragments from the Interface instance
functionName: "transfer",
args: [recipientAddress, transferAmount],
},
],
});
console.log("User operation submitted. Hash:", userOpHash);
// Wait for User Operation receipt
const receipt = await bundlerClient.waitForUserOperationReceipt({
hash: userOpHash,
});
console.log("Transaction confirmed. Hash:", receipt.receipt.transactionHash);
// Update balance after successful transfer
await fetchUsdcBalance();
console.log("USDC transfer successful!");
} catch (error: any) {
console.error("Error during USDC transfer:", error.message || error);
}
};
// Function to log in the user
const login = async () => {
if (web3auth.current) {
const web3authProvider = await web3auth.current.connect();
setProvider(web3authProvider);
setLoggedIn(true);
await fetchWalletAddress();
await fetchUsdcBalance();
}
};
// Function to log out the user
const logout = async () => {
if (web3auth.current) {
await web3auth.current.logout();
setProvider(null);
setLoggedIn(false);
setWalletAddress("");
}
};
// Views for logged-in and unlogged-in states
const loggedInView = (
<Box sx={{ display: "flex", justifyContent: "center", mt: 3 }}>
<Paper
elevation={3}
sx={{
width: "100%",
maxWidth: 450,
borderRadius: 4,
p: 3,
textAlign: "center",
backgroundColor: "#f5f5f5",
}}
>
{/* Wallet overview */}
<Typography variant="h5" gutterBottom>
Wallet Overview
</Typography>
{/* Wallet address display */}
<Box sx={{ mt: 2, mb: 2 }}>
<Typography variant="subtitle2" color="textSecondary">
Wallet Address:
</Typography>
<Typography
variant="body2"
sx={{
wordBreak: "break-word",
overflowWrap: "anywhere",
fontWeight: "bold",
mt: 1,
backgroundColor: "#e0e0e0",
p: 1,
borderRadius: 1,
}}
>
{walletAddress}
</Typography>
<Button
onClick={() => {
navigator.clipboard.writeText(walletAddress);
alert("Wallet address copied!");
}}
variant="outlined"
color="primary"
sx={{ mt: 1 }}
>
Copy Address
</Button>
</Box>
{/* USDC balance display */}
<Box sx={{ mt: 3 }}>
<Typography variant="subtitle2" color="textSecondary">
USDC Balance:
</Typography>
<Typography variant="h6" color="primary" sx={{ fontWeight: "bold", mt: 1 }}>
{usdcBalance ? usdcBalance : "Loading..."}
</Typography>
</Box>
{/* Form for transferring USDC */}
<Box sx={{ mt: 3, mb: 2 }}>
<Typography variant="subtitle2" color="textSecondary">
USDC Transfer
</Typography>
<TextField
label="Recipient Address"
variant="outlined"
fullWidth
value={recipientAddress}
onChange={(e) => setRecipientAddress(e.target.value)}
sx={{ mt: 1, mb: 2 }}
helperText="Enter the recipient's wallet address"
/>
<TextField
label="Amount (USDC)"
type="number"
variant="outlined"
fullWidth
value={amount}
onChange={handleAmountChange}
sx={{ mb: 2 }}
helperText="Amount to send in USDC"
/>
{/* Transfer Button */}
<Button
onClick={sendUSDC}
disabled={
!amount ||
amount > parseFloat(usdcBalance) ||
!isValidAddress(recipientAddress)
}
variant="contained"
color="secondary"
fullWidth
sx={{ mt: 2 }}
>
Send USDC
</Button>
{!amount || amount > parseFloat(usdcBalance) ? (
<Typography
variant="body2"
color="error"
sx={{ mt: 1, textAlign: "center" }}
>
Insufficient Balance or Invalid Inputs
</Typography>
) : null}
</Box>
<Box sx={{ display: "flex", justifyContent: "center", mt: 3 }}>
<Button onClick={logout} variant="contained" color="error">
Logout
</Button>
</Box>
</Paper>
</Box>
);
const unloggedInView = (
<button onClick={login} className="card">Login</button>
);
return (
<div className="container">
<h1 className="title">
<a target="_blank" href="https://web3auth.io/docs/sdk/pnp/web/modal" rel="noreferrer">
PennyFundMe{" "}
</a>
& NextJS Quick Start
</h1>
{!isInitialized ? (
<p>Loading Web3Auth...</p> // Display loading message if still initializing
) : (
<div className="grid">{loggedIn ? loggedInView : unloggedInView}</div>
)}
</div>
);
}
export default App;
Code and Deployment:
- Code Repository: https://gitlab.com/fridayamehmatthew/web3auth-nextjs-project
- Deployed App: https://web3auth-nextjs-project.vercel.app
Additional Notes:
- The issue seems to be related to type mismatches between
permissionless
andviem
. Specifically, theentryPoint.abi
andclient
properties in thetoSmartAccount
function are causing type conflicts. - I have tried upgrading all related dependencies (
permissionless
,viem
,@web3auth/*
) to their latest versions, but the issue persists. - The error occurs during the build process on both local (Node.js
20.18.0
) and Vercel (Node.js22.x
) environments.
Could you please assist in resolving this issue? Let me know if you need any additional details.
Thank you!