Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions frontend/src/components/Navbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ function Navbar() {
<motion.div
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
className="flex items-center space-x-2 cursor-pointer"
className="flex items-center space-x-1 xl:space-x-2 cursor-pointer"
onClick={() => {
navigate("/");
closeMobileMenu();
Expand All @@ -156,7 +156,7 @@ function Navbar() {
</motion.div>

{/* Desktop Navigation */}
<div className="hidden lg:flex items-center space-x-0 xl:space-x-2">
<div className="hidden lg:flex items-center relative left-4 space-x-0 xl:space-x-2">
{/* {navItems.map((item) => (
<motion.button
key={item.name}
Expand All @@ -183,7 +183,7 @@ function Navbar() {
{item?.path === "/dashboard" ? (
<Link
to="/dashboard/create"
className={`flex items-center px-2 xl:px-4 py-2 rounded-lg transition-colors ${isActive(item.path)
className={`flex items-center px-1 xl:px-4 py-2 rounded-lg transition-colors ${isActive(item.path)
? "text-green-400 font-medium"
: "text-white hover:text-green-400"
}`}
Expand All @@ -194,7 +194,7 @@ function Navbar() {
) : (
<Link
to={item.path}
className={`flex items-center px-4 py-2 rounded-lg transition-colors ${isActive(item.path)
className={`flex items-center px-1 xl:px-4 py-2 rounded-lg transition-colors ${isActive(item.path)
? "text-green-400 font-medium"
: "text-white hover:text-green-400"
}`}
Expand Down
80 changes: 57 additions & 23 deletions frontend/src/page/CreateInvoice.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ function CreateInvoice() {
};

processUrlToken();
}, [searchParams, tokens, loadingTokens, account.address]);
}, [searchParams, walletClient, tokens, loadingTokens, account.address]);

useEffect(() => {
const total = itemData.reduce((sum, item) => {
Expand Down Expand Up @@ -236,31 +236,65 @@ function CreateInvoice() {
]);
};

const verifyToken = async (address) => {
setTokenVerificationState("verifying");

try {
if (typeof window !== "undefined" && window.ethereum) {
const provider = new BrowserProvider(window.ethereum);
const contract = new ethers.Contract(address, ERC20_ABI, provider);

const [symbol, name, decimals] = await Promise.all([
contract.symbol().catch(() => "UNKNOWN"),
contract.name().catch(() => "Unknown Token"),
contract.decimals().catch(() => 18),
]);

setVerifiedToken({ address, symbol, name, decimals });
setTokenVerificationState("success");
} else {
console.error("No Ethereum provider found");

const verifyToken = async (address, targetChainId = null) => {
setTokenVerificationState("verifying");

// Determine which chain to verify on
const chainIdToUse = targetChainId || searchParams.get("chain") || account?.chainId;

try {
let provider;


// for UNKNOWN symbol and name unknown update this rpc with some better one
const rpcUrls = {
1: "https://eth.llamarpc.com", // Ethereum (very fast)
61: "https://etc.rivet.link", // Ethereum Classic
137: "https://polygon.llamarpc.com", // Polygon
56: "https://bsc.llamarpc.com", // BNB Smart Chain
8453: "https://base.llamarpc.com", // Base
11155111: "https://rpc.ankr.com/eth_sepolia", // Sepolia
};
if (typeof window !== "undefined" && isConnected) {
// Fallback to wallet provider if no chainId specified
provider = new BrowserProvider(walletClient);
// If chainId is available, always use public RPC (works without wallet)
} else if (chainIdToUse) {
const rpcUrl = rpcUrls[chainIdToUse];

if (!rpcUrl) {
console.error(`Unsupported chain ${chainIdToUse}. Supported chains: Ethereum (1), Ethereum Classic (61), Polygon (137), BNB Smart Chain (56), Base (8453), Sepolia (11155111)`);
setTokenVerificationState("error");
return;
}
} catch (error) {
console.error("Verification failed:", error);
setTokenVerificationState("error");
// Use JsonRpcProvider with timeout for faster response
provider = new ethers.JsonRpcProvider(rpcUrl, Number(chainIdToUse));
}
Comment on lines +259 to 274
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Handle the case when neither wallet nor chainId is available.

If isConnected is false and chainIdToUse is undefined (e.g., no wallet connected, no chain URL param, and account?.chainId is undefined), provider remains undefined. The subsequent contract call will fail with a generic error.

Consider adding an explicit check and user-friendly error message:

Proposed fix
     if (typeof window !== "undefined" && isConnected) {
-      // Fallback to wallet provider if no chainId specified
+      // Use wallet provider when connected
       provider = new BrowserProvider(walletClient);
-    // If chainId is available, always use public RPC (works without wallet)
     } else if (chainIdToUse) {
+      // Use public RPC when chainId is available (works without wallet)
       const rpcUrl = rpcUrls[chainIdToUse];
       
       if (!rpcUrl) {
         console.error(`Unsupported chain ${chainIdToUse}. Supported chains: Ethereum (1), Ethereum Classic (61), Polygon (137), BNB Smart Chain (56), Base (8453), Sepolia (11155111)`);
         setTokenVerificationState("error");
         return;
       }
       
       // Use JsonRpcProvider with timeout for faster response
       provider = new ethers.JsonRpcProvider(rpcUrl, Number(chainIdToUse));
+    } else {
+      console.error("Cannot verify token: No wallet connected and no chain specified");
+      setTokenVerificationState("error");
+      return;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (typeof window !== "undefined" && isConnected) {
// Fallback to wallet provider if no chainId specified
provider = new BrowserProvider(walletClient);
// If chainId is available, always use public RPC (works without wallet)
} else if (chainIdToUse) {
const rpcUrl = rpcUrls[chainIdToUse];
if (!rpcUrl) {
console.error(`Unsupported chain ${chainIdToUse}. Supported chains: Ethereum (1), Ethereum Classic (61), Polygon (137), BNB Smart Chain (56), Base (8453), Sepolia (11155111)`);
setTokenVerificationState("error");
return;
}
} catch (error) {
console.error("Verification failed:", error);
setTokenVerificationState("error");
// Use JsonRpcProvider with timeout for faster response
provider = new ethers.JsonRpcProvider(rpcUrl, Number(chainIdToUse));
}
if (typeof window !== "undefined" && isConnected) {
// Use wallet provider when connected
provider = new BrowserProvider(walletClient);
} else if (chainIdToUse) {
// Use public RPC when chainId is available (works without wallet)
const rpcUrl = rpcUrls[chainIdToUse];
if (!rpcUrl) {
console.error(`Unsupported chain ${chainIdToUse}. Supported chains: Ethereum (1), Ethereum Classic (61), Polygon (137), BNB Smart Chain (56), Base (8453), Sepolia (11155111)`);
setTokenVerificationState("error");
return;
}
// Use JsonRpcProvider with timeout for faster response
provider = new ethers.JsonRpcProvider(rpcUrl, Number(chainIdToUse));
} else {
console.error("Cannot verify token: No wallet connected and no chain specified");
setTokenVerificationState("error");
return;
}
🤖 Prompt for AI Agents
In `@frontend/src/page/CreateInvoice.jsx` around lines 259 - 274, The code can
leave `provider` undefined when neither `isConnected` nor `chainIdToUse` are
available; update the logic in CreateInvoice.jsx (the block that chooses between
`BrowserProvider(walletClient)` and `new ethers.JsonRpcProvider(rpcUrl,
Number(chainIdToUse))`) to explicitly handle the fallback case: check after
those branches if `provider` is still undefined and call
`setTokenVerificationState("error")` and return (or surface a user-friendly
error message) so downstream contract calls don't run with an undefined
`provider`; reference `provider`, `isConnected`, `chainIdToUse`, `walletClient`,
and `setTokenVerificationState` when implementing the check.

};

const contract = new ethers.Contract(address, ERC20_ABI, provider);

const [symbol, name, decimals] = await Promise.all([
contract.symbol().catch(() => "UNKNOWN"),
contract.name().catch(() => "Unknown Token"),
contract.decimals().catch(() => 18),
]);

console.log([symbol, name, decimals]);
setVerifiedToken({
address,
symbol,
name,
decimals: Number(decimals),
chainId: chainIdToUse
});
setTokenVerificationState("success");
} catch (error) {
console.error("Verification failed:", error);
setTokenVerificationState("error");
}
};

const createInvoiceRequest = async (data) => {
if (!isConnected || !walletClient) {
Expand Down