Skip to content

Conversation

@kumawatkaran523
Copy link
Contributor

@kumawatkaran523 kumawatkaran523 commented Jul 13, 2025

Summary by CodeRabbit

  • New Features

    • ERC‑20 + native payments per invoice, invoice cancellation, and payment-capability checks.
    • Token selector (presets + custom verification) and token carousel.
    • Create-invoice flow with encrypted invoice storage, on‑chain submission, global toast notifications, invoice detail drawers, and PNG download.
    • Treasury admin: update fee/treasury address and withdraw flow; added citreaTestnet.
  • Refactor/UX

    • Redesigned Landing, Dashboard, Sent/Received views, Navbar, and app layout; routing renamed to “dashboard”.
  • Chores

    • Added UI/animation/toast/icon dependencies, ERC‑20 ABI, and token presets data.

@coderabbitai
Copy link

coderabbitai bot commented Jul 13, 2025

Walkthrough

Adds per-invoice ERC‑20 token support, invoice cancellation, and payment-status queries to the Chainvoice contract; updates ABIs; and integrates token-aware creation, ERC‑20/native payments, cancellation, Lit encryption/decryption, token UI components, and multiple frontend UI/UX changes.

Changes

Cohort / File(s) Summary
Smart Contract
contracts/src/Chainvoice.sol
Adds IERC20 interface; extends InvoiceDetails with tokenAddress and isCancelled; emits new InvoiceCancelled event; createInvoice accepts and validates tokenAddress; cancelInvoice allows creators to cancel unpaid invoices; payInvoice supports native ETH and ERC‑20 flows; adds getPaymentStatus.
Contract ABIs
frontend/src/contractsABI/ChainvoiceABI.js, frontend/src/contractsABI/ERC20_ABI.js
Updates Chainvoice ABI (new params, outputs, events, cancel/getPaymentStatus) and adds standard ERC20_ABI for frontend token interactions.
Frontend deps & app entry
frontend/package.json, frontend/src/App.jsx
Adds UI libs (@radix-ui/react-select, framer-motion, react-hot-toast, react-icons, react-toastify); registers citreaTestnet; adds global Toaster; renames route homedashboard.
Layout & Navigation
frontend/src/page/Applayout.jsx, frontend/src/components/Navbar.jsx, frontend/src/components/Footer.jsx
Layout and styling tweaks; Navbar items updated (Dashboard routing, connect button behavior, scroll handling); Footer copyright paragraph commented out.
Token UI primitives
frontend/src/components/ui/select.jsx
New Radix-based Select primitives and styled Select components exported for use across UI.
Token components
frontend/src/components/TokenCrousel.jsx, frontend/src/components/TokenSelector.jsx, frontend/src/components/TokenIntegrationRequest.jsx
Adds token carousel, token selector (presets + custom verification), and token integration request prompt.
Pages — Create / Sent / Received
frontend/src/page/CreateInvoice.jsx, frontend/src/page/SentInvoice.jsx, frontend/src/page/ReceivedInvoice.jsx
New CreateInvoice page with token selection/verification, Lit encryption, and createInvoice(..., tokenAddress, ciphertext, hash); Sent/Received pages refactored to decrypt via Lit, enforce Sepolia, enrich token metadata, support ERC‑20 payments (allowance/approve), support cancelInvoice, redesigned drawers/details, and PNG download/print.
Pages — Landing / Home / Treasure
frontend/src/page/Landing.jsx, frontend/src/page/Home.jsx, frontend/src/page/Treasure.jsx
Landing redesigned with animations and token carousel; Home sidebar restyled; Treasure adds fee & treasury address update handlers and animated UI.
Utilities / Tokens
frontend/src/utils/erc20_token.js
Adds TOKEN_PRESETS (token metadata) used by selectors and pages.
ABI usage across frontend
frontend/src/**
Multiple frontend modules updated to use new Chainvoice ABI signatures and ERC20_ABI (imports and call sites updated where required).

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant FE as Frontend (CreateInvoice)
  participant Lit as Lit Protocol
  participant SC as Chainvoice.sol

  U->>FE: Enter invoice data + select token
  FE->>Lit: SIWE auth & encrypt invoice JSON
  Lit-->>FE: Ciphertext + hash
  FE->>SC: createInvoice(to, amount, tokenAddress, ciphertext, hash)
  SC-->>FE: Tx receipt (InvoiceCreated)
  FE-->>U: Navigate to dashboard
Loading
sequenceDiagram
  participant P as Payer
  participant FE as Frontend (ReceivedInvoice)
  participant T as ERC20 Token
  participant SC as Chainvoice.sol

  P->>FE: Initiate payment
  alt ERC20 payment
    FE->>T: allowance(payer, Chainvoice)
    alt insufficient allowance
      FE->>T: approve(Chainvoice, amount)
    end
    FE->>SC: payInvoice(invoiceId) with msg.value = fee (ETH)
  else Native ETH
    FE->>SC: payInvoice(invoiceId) with msg.value = amountDue + fee
  end
  SC-->>FE: Tx receipt (InvoicePaid)
  FE-->>P: Update UI/status
Loading
sequenceDiagram
  participant S as Sender
  participant FE as Frontend (SentInvoice)
  participant SC as Chainvoice.sol

  S->>FE: Cancel invoice
  FE->>SC: cancelInvoice(invoiceId)
  SC-->>FE: Tx receipt (InvoiceCancelled)
  FE-->>S: Refresh list/status
Loading
sequenceDiagram
  participant FE as Frontend
  participant SC as Chainvoice.sol
  participant T as ERC20 Token

  FE->>SC: getPaymentStatus(invoiceId, payer)
  alt Native
    SC-->>FE: canPay, payerBalance, MAX_UINT allowance
  else ERC20
    SC->>T: staticcall balanceOf/allowance
    SC-->>FE: canPay, payerBalance, allowanceAmount
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

I nibble bytes and hop through chains,
Encrypt your invoices, guard your plains.
ETH or ERC‑20, I kindly embrace,
Cancel or pay — I track every trace.
A carrot of code, invoices in place 🥕🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 14

♻️ Duplicate comments (1)
frontend/src/page/SentInvoice.jsx (1)

221-234: Extract duplicated token enrichment logic.

This is the same token enrichment logic as in ReceivedInvoice.jsx. As suggested earlier, extract this to a shared utility function to avoid duplication.

🧹 Nitpick comments (18)
frontend/src/utils/erc20_token.js (2)

1-7: Consider uncommenting or removing the Chainvoice token entry.

The commented-out Chainvoice token at the top suggests this might be needed for the platform. Either include it in the active token list or remove the dead code.


8-709: Consider optimizations for large static data.

This large token array will increase bundle size. Consider:

  1. Loading token data asynchronously or from an API
  2. Implementing lazy loading for logos
  3. Adding network/chain identification since addresses are mainnet-specific
  4. Validating token addresses are properly checksummed
frontend/src/components/TokenIntegrationRequest.jsx (2)

1-1: Remove unused prop or implement its usage.

The address prop is declared but never used within the component. Either remove it or implement its intended functionality.

-function TokenIntegrationRequest({ address }) {
+function TokenIntegrationRequest() {

6-6: Consider making the URL configurable.

The hardcoded URL should be made configurable through props or environment variables for better maintainability.

-        href="https://stability.nexus/"
+        href={requestUrl || "https://stability.nexus/"}
frontend/src/components/TokenSelector.jsx (3)

286-288: Implement token verification functionality.

The verification button has placeholder logic that needs to be implemented for proper token validation.

Do you want me to generate the token verification implementation that validates ERC-20 contract addresses and fetches token metadata?

                      onClick={() => {
-                        /* Add verification logic here */
+                        verifyCustomToken(customTokenAddress);
                      }}

206-206: Remove commented code.

Commented code should be removed to maintain code cleanliness.

                      <img
-                        // src={`/tokenImages/${selectedToken.symbol.toLowerCase()}.png`}
                        src={selectedToken.logo}

14-19: Consider moving popular tokens to configuration.

The hardcoded POPULAR_TOKENS array should be moved to a configuration file for better maintainability.

Consider moving this to frontend/src/utils/erc20_token.js alongside TOKEN_PRESETS.

frontend/src/components/TokenCrousel.jsx (2)

6-6: Fix filename typo.

The filename has a typo: TokenCrousel.jsx should be TokenCarousel.jsx to match the component name.


48-77: Consider memoizing the duplicated tokens array.

The tokens duplication happens on every render. Consider using useMemo for better performance.

+import { useEffect, useRef, useMemo } from "react";

const TokenCarousel = () => {
  const carouselRef = useRef();
-  const duplicatedTokens = [...TOKEN_PRESETS, ...TOKEN_PRESETS];
+  const duplicatedTokens = useMemo(() => [...TOKEN_PRESETS, ...TOKEN_PRESETS], []);
frontend/src/page/Home.jsx (1)

19-38: Consider extracting menu configuration to separate file.

The menuItems array could be moved to a separate configuration file for better maintainability and potential reuse.

+// config/menuItems.js
+export const MENU_ITEMS = [
+  {
+    text: "Sent Requests",
+    icon: <MailOutlineIcon />,
+    route: "sent",
+    color: "#4ade80",
+  },
+  // ... other items
+];
frontend/src/App.jsx (1)

54-68: Consider adding error boundaries for better error handling

The routing structure looks good, but consider wrapping routes in error boundaries to handle component errors gracefully.

Would you like me to generate an ErrorBoundary component that can wrap your routes to provide better error handling and user feedback when components fail to render?

frontend/src/components/Navbar.jsx (2)

78-97: Remove commented out code

There are large blocks of commented code that should be removed to keep the codebase clean.

Remove the commented navItems array and the commented navigation sections in both desktop and mobile views. If this code might be needed later, it should be preserved in version control history rather than as comments.

Also applies to: 161-176, 270-287


43-46: Consider making navigation on disconnect optional

Automatically navigating users to the home page when they disconnect their wallet might be disruptive, especially if they're viewing public content.

     if (!address) {
-      navigate("/");
+      // Only navigate away from protected routes
+      if (location.pathname.startsWith("/dashboard") || location.pathname === "/treasure") {
+        navigate("/");
+      }
       setHasConnected(false);
     }
frontend/src/page/Landing.jsx (1)

305-322: Footer links need implementation

All footer links are currently placeholders with href="#". These should either be implemented with actual navigation/URLs or removed if not needed.

Would you like me to help implement proper routing for these footer links or create a footer configuration object that maps to actual routes and external URLs?

Also applies to: 329-346, 353-376

frontend/src/page/ReceivedInvoice.jsx (2)

105-111: Use strict equality and consider extracting chain ID.

Use strict equality operator and consider extracting the chain ID to a constant for better maintainability.

+ const SEPOLIA_CHAIN_ID = 11155111;
+ 
- if (network.chainId != 11155111) {
+ if (network.chainId !== SEPOLIA_CHAIN_ID) {

224-237: Consider extracting token enrichment to a utility function.

This token enrichment logic is duplicated in SentInvoice.jsx. Consider extracting it to a shared utility function for better maintainability.

Create a utility function in a shared utils file:

// utils/tokenUtils.js
export const enrichTokenWithPresets = (paymentToken) => {
  if (!paymentToken?.address) return paymentToken;
  
  const tokenInfo = TOKEN_PRESETS.find(
    (t) => t.address.toLowerCase() === paymentToken.address.toLowerCase()
  );
  
  if (tokenInfo) {
    return {
      ...paymentToken,
      logo: tokenInfo.logo,
      decimals: tokenInfo.decimals,
    };
  }
  
  return paymentToken;
};

Then use it here:

- if (parsed.paymentToken?.address) {
-   const tokenInfo = TOKEN_PRESETS.find(
-     (t) =>
-       t.address.toLowerCase() ===
-       parsed.paymentToken.address.toLowerCase()
-   );
-   if (tokenInfo) {
-     parsed.paymentToken = {
-       ...parsed.paymentToken,
-       logo: tokenInfo.logo,
-       decimals: tokenInfo.decimals,
-     };
-   }
- }
+ parsed.paymentToken = enrichTokenWithPresets(parsed.paymentToken);
contracts/src/Chainvoice.sol (1)

74-80: Good ERC20 validation, but consider additional checks.

The token validation correctly checks if the address is a contract and has a balanceOf function. Consider also validating the decimals to ensure it's within a reasonable range (typically 0-18).

Add decimals validation:

if (tokenAddress != address(0)) { 
    require(tokenAddress.code.length > 0, "Not a contract address");
    (bool success,) = tokenAddress.staticcall(
        abi.encodeWithSignature("balanceOf(address)", address(this))
    );
    require(success, "Not an ERC20 token");
    
    // Validate decimals
    (bool decSuccess, bytes memory decData) = tokenAddress.staticcall(
        abi.encodeWithSignature("decimals()")
    );
    if (decSuccess && decData.length > 0) {
        uint8 decimals = abi.decode(decData, (uint8));
        require(decimals <= 18, "Token decimals too high");
    }
}
frontend/src/page/SentInvoice.jsx (1)

104-110: Use strict equality for network check.

Same as in ReceivedInvoice.jsx, use strict equality operator for consistency.

- if (network.chainId != 11155111) {
+ if (network.chainId !== 11155111) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a927e94 and 99defe6.

⛔ Files ignored due to path filters (8)
  • frontend/public/dashboard.png is excluded by !**/*.png
  • frontend/public/lit-protocol-diagram.png is excluded by !**/*.png
  • frontend/public/lit-protocol-logo.png is excluded by !**/*.png
  • frontend/public/logo.png is excluded by !**/*.png
  • frontend/public/token-select.png is excluded by !**/*.png
  • frontend/public/tokenImages/cin.png is excluded by !**/*.png
  • frontend/public/tokenImages/eth.png is excluded by !**/*.png
  • frontend/public/tokenImages/generic.png is excluded by !**/*.png
📒 Files selected for processing (20)
  • contracts/src/Chainvoice.sol (6 hunks)
  • frontend/package.json (2 hunks)
  • frontend/src/App.jsx (1 hunks)
  • frontend/src/components/CreateInvoice.jsx (0 hunks)
  • frontend/src/components/Footer.jsx (1 hunks)
  • frontend/src/components/Navbar.jsx (1 hunks)
  • frontend/src/components/TokenCrousel.jsx (1 hunks)
  • frontend/src/components/TokenIntegrationRequest.jsx (1 hunks)
  • frontend/src/components/TokenSelector.jsx (1 hunks)
  • frontend/src/components/ui/select.jsx (1 hunks)
  • frontend/src/contractsABI/ChainvoiceABI.js (8 hunks)
  • frontend/src/contractsABI/ERC20_ABI.js (1 hunks)
  • frontend/src/page/Applayout.jsx (1 hunks)
  • frontend/src/page/CreateInvoice.jsx (1 hunks)
  • frontend/src/page/Home.jsx (1 hunks)
  • frontend/src/page/Landing.jsx (1 hunks)
  • frontend/src/page/ReceivedInvoice.jsx (4 hunks)
  • frontend/src/page/SentInvoice.jsx (4 hunks)
  • frontend/src/page/Treasure.jsx (2 hunks)
  • frontend/src/utils/erc20_token.js (1 hunks)
💤 Files with no reviewable changes (1)
  • frontend/src/components/CreateInvoice.jsx
🧰 Additional context used
🧬 Code Graph Analysis (5)
frontend/src/page/Home.jsx (2)
frontend/src/components/Navbar.jsx (2)
  • navigate (17-17)
  • location (18-18)
frontend/src/page/CreateInvoice.jsx (1)
  • navigate (58-58)
frontend/src/components/ui/select.jsx (1)
frontend/src/lib/utils.js (1)
  • cn (4-6)
frontend/src/components/Navbar.jsx (4)
frontend/src/page/SentInvoice.jsx (1)
  • useAccount (53-53)
frontend/src/page/ReceivedInvoice.jsx (1)
  • useAccount (53-53)
frontend/src/page/About.jsx (1)
  • useAccount (7-7)
frontend/src/page/Home.jsx (2)
  • navigate (16-16)
  • location (17-17)
frontend/src/page/Landing.jsx (1)
frontend/src/components/TokenCrousel.jsx (1)
  • TokenCarousel (6-82)
frontend/src/page/SentInvoice.jsx (4)
frontend/src/page/ReceivedInvoice.jsx (20)
  • columns (40-47)
  • page (50-50)
  • rowsPerPage (51-51)
  • walletClient (52-52)
  • useAccount (53-53)
  • loading (54-54)
  • fee (56-56)
  • error (57-57)
  • litReady (58-58)
  • litClientRef (59-59)
  • paymentLoading (60-60)
  • networkLoading (61-61)
  • handleChangePage (63-65)
  • handleChangeRowsPerPage (67-70)
  • drawerState (347-350)
  • switchNetwork (379-393)
  • formatAddress (395-399)
  • formatDate (401-404)
  • toggleDrawer (352-364)
  • handlePrint (366-377)
frontend/src/page/CreateInvoice.jsx (4)
  • walletClient (52-52)
  • useAccount (53-53)
  • loading (57-57)
  • litClientRef (59-59)
frontend/src/components/Navbar.jsx (1)
  • useAccount (16-16)
frontend/src/page/Working.jsx (2)
  • toggleDrawer (11-21)
  • handlePrint (23-48)
🔇 Additional comments (16)
frontend/package.json (1)

23-23: LGTM! Dependencies align with new UI features.

The new dependencies support the enhanced UI components for multi-token payment support:

  • @radix-ui/react-select for accessible token selection dropdowns
  • framer-motion for smooth animations in navigation and components
  • react-hot-toast for user notification system
  • react-icons for consistent iconography

All versions are recent and appropriate for production use.

Also applies to: 34-34, 42-43

frontend/src/components/Footer.jsx (1)

13-15: Verify that removing the copyright notice is intentional.

The copyright notice has been commented out. Confirm this aligns with legal/branding requirements for the platform.

frontend/src/contractsABI/ERC20_ABI.js (1)

1-10: LGTM! Standard and complete ERC20 ABI.

The ABI includes all essential ERC20 functions needed for token interactions:

  • Transfer operations (transfer, transferFrom, approve)
  • Balance queries (balanceOf, allowance)
  • Metadata access (name, symbol, decimals)

The human-readable format is appropriate for ethers.js integration.

frontend/src/page/Applayout.jsx (1)

8-16: LGTM! Improved semantic structure and styling.

The refactoring enhances the layout with:

  • Semantic <main> element for better accessibility
  • Simplified structure by removing unnecessary fragment
  • Appropriate flex layout with flex-1 for content area
  • Proper spacing with pt-20 (likely for fixed navbar clearance)

The removal of h-full allows content to determine the natural height.

frontend/src/components/TokenCrousel.jsx (1)

10-42: Excellent animation implementation with proper cleanup.

The infinite scroll animation is well-implemented with proper event listeners cleanup, pause on hover functionality, and smooth transitions.

frontend/src/components/ui/select.jsx (3)

13-27: Excellent use of React.forwardRef and component composition.

The SelectTrigger implementation properly forwards refs and uses consistent styling patterns with the cn utility function.


50-72: Well-structured SelectContent with accessibility features.

The component properly implements Radix UI Portal pattern with scroll buttons and responsive positioning. The animation classes provide smooth user experience.


108-119: Complete and consistent component exports.

All necessary Select components are properly exported, providing a comprehensive API for the component library.

frontend/src/page/Home.jsx (2)

48-125: Excellent responsive design implementation.

The responsive layout with proper Material UI breakpoints, smooth transitions, and accessible navigation patterns creates a great user experience.


84-100: Great dynamic styling based on route state.

The conditional styling based on location.pathname provides clear visual feedback for navigation state with smooth transitions and color coding.

frontend/src/contractsABI/ChainvoiceABI.js (1)

34-38: ABI updates for ERC20 token support look correct

The ABI has been properly updated to support multi-token payments:

  • Added tokenAddress parameter to createInvoice function
  • Updated InvoiceDetails struct with tokenAddress field
  • Extended events to include token information
  • Added getPaymentStatus function for payment verification

These changes correctly reflect the smart contract modifications for ERC20 token support.

Also applies to: 102-106, 197-201, 258-262, 314-318, 480-484, 517-521

frontend/src/page/ReceivedInvoice.jsx (1)

258-345: Well-structured multi-token payment implementation.

The payment function correctly handles both native ETH and ERC20 token payments with proper allowance checks, approval flow, and error handling. The separation of fee handling (always in ETH) from the payment amount is implemented correctly.

frontend/src/page/CreateInvoice.jsx (2)

94-108: Excellent handling of precision in calculations.

The total amount calculation correctly uses BigInt arithmetic with ethers.js utilities to avoid floating-point precision issues. The division by parseUnits("1", 18) properly cancels the double scaling when multiplying quantities.


169-187: Well-implemented token verification.

The token verification correctly validates ERC20 contracts by calling standard methods with proper error handling and fallback values. Good use of Promise.all for efficiency.

contracts/src/Chainvoice.sol (2)

102-139: Well-structured payment logic with proper separation of concerns.

The payment function correctly handles both native and ERC20 token payments. The design choice to always collect fees in native tokens simplifies the implementation and ensures consistent fee collection. The allowance check and event emission are properly implemented.


141-163: Useful view function for payment status checks.

The getPaymentStatus function provides valuable information for the frontend to determine payment capability. Good handling of the allowance concept for native tokens.

Consider adding a check for invoice payment status to avoid unnecessary checks for already paid invoices:

require(!invoice.isPaid, "Invoice already paid");

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🔭 Outside diff range comments (1)
contracts/src/Chainvoice.sol (1)

124-173: Harden pay flow: set state before external calls and consider nonReentrant

Although reentrancy into payInvoice is currently constrained by msg.sender == invoice.to, best practice is to follow Checks-Effects-Interactions and/or use a reentrancy guard.

  • Move invoice.isPaid = true; before the external call to invoice.from (state change will revert if transfer fails).
  • Consider adding OpenZeppelin ReentrancyGuard and marking payInvoice/withdrawFees as nonReentrant.
  • For ERC-20 transfers, prefer SafeERC20.safeTransferFrom.

Apply this diff to move the effect before interactions:

         if (invoice.tokenAddress == address(0)) {
           // Native token (ETH) payment
           require(
             msg.value == invoice.amountDue + fee,
             "Incorrect payment amount"
           );
-          accumulatedFees += fee;
-
-          uint256 amountToSender = msg.value - fee;
-          (bool sent, ) = payable(invoice.from).call{value: amountToSender}(
-              ""
-          );
-          require(sent, "Transfer failed");
+          // Effects before interactions
+          invoice.isPaid = true;
+          accumulatedFees += fee;
+
+          uint256 amountToSender = msg.value - fee; // equals amountDue
+          (bool sent, ) = payable(invoice.from).call{value: amountToSender}("");
+          require(sent, "Transfer failed");
         } else {
           // ERC20 token payment
           require(msg.value == fee, "Must pay fee in native token");
           require(
             IERC20(invoice.tokenAddress).allowance(
               msg.sender,
               address(this)
             ) >= invoice.amountDue,
             "Insufficient allowance"
           );
 
-          accumulatedFees += fee;
-          bool transferSuccess = IERC20(invoice.tokenAddress).transferFrom(
+          // Effects before interactions
+          invoice.isPaid = true;
+          accumulatedFees += fee;
+          bool transferSuccess = IERC20(invoice.tokenAddress).transferFrom(
             msg.sender,
             invoice.from,
             invoice.amountDue
           );
           require(transferSuccess, "Token transfer failed");
         }
 
-        invoice.isPaid = true;
         emit InvoicePaid(
           invoiceId,
           invoice.from,
           invoice.to,
           invoice.amountDue,
           invoice.tokenAddress
         );
🧹 Nitpick comments (6)
contracts/src/Chainvoice.sol (3)

82-89: ERC-20 validation can be made more robust

The staticcall to balanceOf(address) is a lightweight sanity check, but it can pass for contracts that merely implement that selector. Consider a stricter check:

  • Use a try/catch on IERC20(tokenAddress).balanceOf(address(this)) to guarantee the call decodes properly.
  • Optionally, also try reading allowance to ensure both views decode correctly.

Example:

try IERC20(tokenAddress).balanceOf(address(this)) returns (uint256) {} catch {
  revert("Not an ERC20 token");
}

175-207: getPaymentStatus behavior is sensible; minor note on native allowances

Returning type(uint256).max for native allowance is a pragmatic sentinel. Document this in the ABI/README so the frontend doesn’t attempt arithmetic with it unnecessarily.


239-246: Emit an event when fee/treasury is updated

Consider emitting FeeUpdated(uint256 oldFee, uint256 newFee) and TreasuryUpdated(address oldTreasury, address newTreasury) to ease off-chain indexing and audits.

frontend/src/page/SentInvoice.jsx (3)

312-326: Add wallet_addEthereumChain fallback for unconfigured Sepolia

If Sepolia isn’t added, wallet_switchEthereumChain returns code 4902. Add a fallback to prompt chain addition.

Suggested change:

   try {
     setNetworkLoading(true);
-    await window.ethereum.request({
-      method: "wallet_switchEthereumChain",
-      params: [{ chainId: "0xaa36a7" }], // Sepolia chain ID
-    });
+    try {
+      await window.ethereum.request({
+        method: "wallet_switchEthereumChain",
+        params: [{ chainId: "0xaa36a7" }],
+      });
+    } catch (err) {
+      if (err?.code === 4902) {
+        await window.ethereum.request({
+          method: "wallet_addEthereumChain",
+          params: [
+            {
+              chainId: "0xaa36a7",
+              chainName: "Sepolia",
+              nativeCurrency: { name: "Sepolia Ether", symbol: "ETH", decimals: 18 },
+              rpcUrls: ["https://rpc.sepolia.org"],
+              blockExplorerUrls: ["https://sepolia.etherscan.io"],
+            },
+          ],
+        });
+      } else {
+        throw err;
+      }
+    }
     setError(null);

539-547: Inconsistent date sources (timestamp vs issueDate)

Tooltip uses invoice.timestamp while the visible date uses issueDate. Unless both are guaranteed present and consistent, pick one canonical source (likely issueDate) or gracefully fallback.

Example:

-  title={new Date(invoice.timestamp * 1000).toLocaleString()}
+  title={new Date(Number(drawerState.selectedInvoice?.issueDate ?? Date.now())).toLocaleString()}

120-134: Contract address must be present; consider early guard

If import.meta.env.VITE_CONTRACT_ADDRESS is missing, calls will fail at runtime. Add a guard and user-facing error.

Example:

-        const contract = new Contract(
-          import.meta.env.VITE_CONTRACT_ADDRESS,
+        const contractAddr = import.meta.env.VITE_CONTRACT_ADDRESS;
+        if (!contractAddr) {
+          setError("Contract address is not configured.");
+          setLoading(false);
+          return;
+        }
+        const contract = new Contract(
+          contractAddr,
           ChainvoiceABI,
           signer
         );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 99defe6 and e46a4f3.

📒 Files selected for processing (3)
  • contracts/src/Chainvoice.sol (6 hunks)
  • frontend/src/contractsABI/ChainvoiceABI.js (10 hunks)
  • frontend/src/page/SentInvoice.jsx (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
frontend/src/page/SentInvoice.jsx (2)
frontend/src/page/ReceivedInvoice.jsx (8)
  • columns (40-47)
  • page (50-50)
  • fee (56-56)
  • error (57-57)
  • litReady (58-58)
  • litClientRef (59-59)
  • networkLoading (61-61)
  • switchNetwork (379-393)
frontend/src/contractsABI/ChainvoiceABI.js (2)
  • ChainvoiceABI (1-589)
  • ChainvoiceABI (1-589)
🔇 Additional comments (10)
contracts/src/Chainvoice.sol (2)

111-122: Cancellation flow looks correct

Proper authorization and state checks are in place; event emission is included. No issues.


248-257: Confirm intention: anyone can trigger fee withdrawal to treasury

withdrawFees is intentionally callable by anyone but sends funds to treasuryAddress. This is a common pattern, but please confirm this is intended. If not, gate with onlyOwner.

frontend/src/contractsABI/ChainvoiceABI.js (7)

20-32: ABI addition for cancelInvoice matches contract signature

cancelInvoice(uint256) nonpayable aligns with the Solidity implementation. Good.


47-52: createInvoice input signature matches on-chain (tokenAddress added)

The parameter order and types are consistent with the contract. Good.


115-129: Struct shape update (tokenAddress, isCancelled) is consistent

InvoiceDetails tuple now includes tokenAddress and isCancelled in the correct positions. Ensure frontend index accessors are updated accordingly.


145-178: getPaymentStatus ABI matches contract (canPay, payerBalance, allowanceAmount)

This will enable richer UX for payment readiness checks. Looks good.


490-520: InvoiceCancelled event definition matches on-chain

Fields and indexed parameters align with the Solidity event. Good.


543-549: InvoiceCreated event extended with tokenAddress

Matches contract changes. Good.


580-586: InvoicePaid event extended with tokenAddress

Matches contract changes. Good.

frontend/src/page/SentInvoice.jsx (1)

510-536: Status chip logic now works once isCancelled is propagated

After fixing parsing to set isCancelled, this UI section becomes correct. No further changes needed here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🔭 Outside diff range comments (1)
frontend/package.json (1)

23-47: Action required: remove duplicate toast lib and wire the chosen provider

Short: package.json contains both react-hot-toast and react-toastify. App.jsx already mounts react-hot-toast's , but ReceivedInvoice.jsx imports react-toastify's toast without any ToastContainer in the repo — and SentInvoice.jsx calls toast.* but doesn't import toast. This will lead to missing/inconsistent toasts. Standardize on one lib and fix imports/providers.

Files to inspect/fix:

  • frontend/package.json — contains both "react-hot-toast" and "react-toastify".
  • frontend/src/App.jsx — imports { Toaster } from "react-hot-toast" and mounts at app root.
  • frontend/src/page/ReceivedInvoice.jsx — imports { toast } from "react-toastify" and the react-toastify CSS (lines ~26-27) and calls toast.error(...) (lines ~341-348). No is present anywhere.
  • frontend/src/page/SentInvoice.jsx — calls toast.success / toast.error (lines ~316/319) but the file does not import toast.

Recommended fixes (pick one):

Option A — keep react-hot-toast (recommended since App already mounts it)

  • Replace in ReceivedInvoice.jsx:
    • Remove:
      import { toast } from "react-toastify";
      import "react-toastify/dist/ReactToastify.css";
    • Add:
      import { toast } from "react-hot-toast";
  • Ensure SentInvoice.jsx imports toast if missing:
    • Add at top: import { toast } from "react-hot-toast";
  • Remove "react-toastify" from frontend/package.json and run your package manager to update lockfile.

Option B — keep react-toastify

  • In App.jsx replace the react-hot-toast with react-toastify's (and import it), or add a root-level .
  • Update SentInvoice.jsx to import { toast } from "react-toastify" (if you keep usage there).
  • Remove "react-hot-toast" from frontend/package.json and update lockfile.

Minimal code snippets (Option A):

  • ReceivedInvoice.jsx: replace
    import { toast } from "react-toastify";
    import "react-toastify/dist/ReactToastify.css";
    with
    import { toast } from "react-hot-toast";
  • SentInvoice.jsx: add at top if missing
    import { toast } from "react-hot-toast";

Please implement one of the options and run the app to confirm toasts appear consistently across pages.

♻️ Duplicate comments (6)
frontend/src/page/SentInvoice.jsx (5)

873-883: Total computation mixes floats/units — use integer math and format for display

Adding parseFloat(amountDue) with parseFloat(ethers.formatUnits(fee)) loses precision and mixes units. Prefer base units + proper formatting.

Example (ETH-only display path):

-                  {drawerState.selectedInvoice.paymentToken?.symbol === "ETH"
-                    ? `${(
-                        parseFloat(drawerState.selectedInvoice.amountDue) +
-                        parseFloat(ethers.formatUnits(fee))
-                      ).toFixed(6)} ETH`
+                  {drawerState.selectedInvoice.paymentToken?.symbol === "ETH"
+                    ? (() => {
+                        const dueWei = ethers.parseUnits(
+                          String(drawerState.selectedInvoice.amountDue),
+                          18
+                        );
+                        const totalWei = dueWei + fee;
+                        return `${ethers.formatUnits(totalWei, 18)} ETH`;
+                      })()

For ERC-20, keep showing “amount + fee ETH” but ensure amountDue is formatted using token decimals when known.


111-119: Fix BigInt vs Number comparison for chainId (ethers v6)

getNetwork().chainId is a BigInt in ethers v6; comparing to a Number throws a TypeError.

Apply:

-        if (network.chainId != 11155111) {
+        if (network.chainId !== 11155111n) {

Alternatively:

-        if (network.chainId != 11155111) {
+        if (Number(network.chainId) !== 11155111) {

164-164: Don’t atob() the ciphertext — pass base64 string to Lit

decryptToString expects the base64-encoded ciphertext string. Decoding with atob corrupts the data.

Apply:

-            const ciphertext = atob(encryptedStringBase64);
+            const ciphertext = encryptedStringBase64; // already base64

316-323: Undefined ‘toast’ — import and ensure provider

toast.success/error is used but not imported, causing runtime errors.

Add at the top of this file (or a shared layout):

import { toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

Ensure is rendered once at the app root. If you intend to use react-hot-toast instead, replace calls with from 'react-hot-toast' and mount at the root.


340-344: Guard against undefined/short addresses in formatter

formatAddress assumes a non-empty string and will throw on undefined. Also simplify with slice.

Apply:

-  const formatAddress = (address) => {
-    return `${address.substring(0, 10)}...${address.substring(
-      address.length - 10
-    )}`;
-  };
+  const formatAddress = (addr) => {
+    if (!addr) return "";
+    const s = String(addr);
+    if (s.length <= 20) return s;
+    return `${s.slice(0, 10)}...${s.slice(-10)}`;
+  };
frontend/src/page/ReceivedInvoice.jsx (1)

133-137: Setter name is corrected — LGTM

Using setReceivedInvoice matches the state variable receivedInvoices.

🧹 Nitpick comments (5)
frontend/src/page/SentInvoice.jsx (3)

563-583: Disable cancel button while processing to prevent duplicate submissions

You already track per-invoice loading; wire it to the button’s disabled state.

Apply:

-                                  <IconButton
+                                  <IconButton
+                                    disabled={!!paymentLoading[invoice.id]}
                                     size="small"
                                     onClick={() => {
                                       setInvoiceToCancel(invoice);
                                       setCancelConfirmOpen(true);
                                     }}

333-335: Prefer toast over alert for consistent UX

Stay consistent with your toast system instead of alert().

Apply:

-      alert("Failed to switch network. Please switch to Sepolia manually.");
+      toast.error("Failed to switch network. Please switch to Sepolia manually.");

Note: Requires toast import as suggested above.


936-949: Nit: fix dialog button copy

Minor grammar/spacing improvement.

Apply:

-          <Button onClick={() => setCancelConfirmOpen(false)}>
-            {" "}
-            No,Keep Invoice Active
+          <Button onClick={() => setCancelConfirmOpen(false)}>
+            No, Keep Invoice Active
           </Button>
frontend/src/page/ReceivedInvoice.jsx (2)

386-400: Prefer toast over alert for network switch errors

Align with your toast system for consistent UX and theming.

Apply:

-      alert("Failed to switch network. Please switch to Sepolia manually.");
+      toast.error("Failed to switch network. Please switch to Sepolia manually.");

965-973: Total computation mixes floats/units — use integer math and format

Adding parseFloat(amountDue) to parseFloat(formatUnits(fee)) can be lossy. Use BigInt units and format only for display.

Example:

-                  {drawerState.selectedInvoice.paymentToken?.symbol === "ETH"
-                    ? `${(
-                        parseFloat(drawerState.selectedInvoice.amountDue) +
-                        parseFloat(ethers.formatUnits(fee))
-                      ).toFixed(6)} ETH`
+                  {drawerState.selectedInvoice.paymentToken?.symbol === "ETH"
+                    ? (() => {
+                        const dueWei = ethers.parseUnits(
+                          String(drawerState.selectedInvoice.amountDue),
+                          18
+                        );
+                        const totalWei = dueWei + fee;
+                        return `${ethers.formatUnits(totalWei, 18)} ETH`;
+                      })()
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e46a4f3 and 9a5ae47.

📒 Files selected for processing (3)
  • frontend/package.json (2 hunks)
  • frontend/src/page/ReceivedInvoice.jsx (4 hunks)
  • frontend/src/page/SentInvoice.jsx (6 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
frontend/src/page/SentInvoice.jsx (2)
frontend/src/page/ReceivedInvoice.jsx (7)
  • columns (45-52)
  • page (55-55)
  • fee (61-61)
  • error (62-62)
  • switchNetwork (386-400)
  • formatAddress (402-406)
  • formatDate (408-411)
frontend/src/contractsABI/ChainvoiceABI.js (2)
  • ChainvoiceABI (1-589)
  • ChainvoiceABI (1-589)
frontend/src/page/ReceivedInvoice.jsx (8)
frontend/src/page/SentInvoice.jsx (12)
  • columns (49-56)
  • page (59-59)
  • walletClient (61-61)
  • useAccount (62-62)
  • loading (63-63)
  • fee (65-65)
  • error (66-66)
  • drawerState (266-269)
  • switchNetwork (324-338)
  • formatAddress (340-344)
  • formatDate (346-349)
  • handlePrint (285-296)
frontend/src/page/Treasure.jsx (3)
  • walletClient (22-22)
  • loading (23-28)
  • fee (21-21)
frontend/src/page/CreateInvoice.jsx (4)
  • walletClient (52-52)
  • useAccount (53-53)
  • loading (57-57)
  • issueDate (56-56)
frontend/src/components/Navbar.jsx (1)
  • useAccount (16-16)
frontend/src/page/About.jsx (2)
  • useAccount (7-7)
  • loading (9-9)
frontend/src/contractsABI/ChainvoiceABI.js (2)
  • ChainvoiceABI (1-589)
  • ChainvoiceABI (1-589)
frontend/src/utils/erc20_token.js (2)
  • TOKEN_PRESETS (8-709)
  • TOKEN_PRESETS (8-709)
frontend/src/contractsABI/ERC20_ABI.js (2)
  • ERC20_ABI (1-10)
  • ERC20_ABI (1-10)
🔇 Additional comments (4)
frontend/src/page/SentInvoice.jsx (1)

149-156: Correct InvoiceDetails indexing — LGTM

Indices reflect the updated struct: id(0), from(1), to(2), isPaid(5), isCancelled(6), encryptedData(7), dataHash(8).

frontend/src/page/ReceivedInvoice.jsx (3)

614-624: Use issueDate for tooltip; avoid undefined ‘timestamp’ NaN

invoice.timestamp isn’t guaranteed; use the already-present issueDate.

Apply:

-                            <Tooltip
-                              title={new Date(
-                                invoice.timestamp * 1000
-                              ).toLocaleString()}
-                            >
+                            <Tooltip
+                              title={new Date(invoice.issueDate).toLocaleString()}
+                            >

If timestamp is required, ensure it’s set in the decrypted payload first.


25-44: Nice: ERC-20 ABI and token presets integration

Bringing in ERC20_ABI and TOKEN_PRESETS unlocks the approval/payment and richer token display flows. The enrichment with logo/decimals is handled cleanly.


26-28: Confirm a single is mounted — manual verification required

I ran rg -n '<ToastContainer' -A 2 against the repo and found no matches. Since frontend/src/page/ReceivedInvoice.jsx imports toast, please confirm a single root-level is mounted (e.g., App.jsx or index.jsx) to avoid duplicate containers/memory leaks.

Files/steps to check:

  • File importing toast: frontend/src/page/ReceivedInvoice.jsx (lines 26–28).
  • Run locally to locate provider/usages:
    • rg -n "ToastContainer" -S
    • rg -n "react-toastify" -S
    • rg -n "toast(" -S

Reply with the location of the mounted or ask me to run a broader search in the repo.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (14)
frontend/src/page/SentInvoice.jsx (5)

113-119: Fix BigInt vs Number comparison for chainId (ethers v6)

getNetwork().chainId is BigInt in ethers v6; comparing to a Number can throw. Use a BigInt literal or cast to Number.

-        if (network.chainId != 11155111) {
+        if (network.chainId !== 11155111n) {

Alternatively:

-        if (network.chainId != 11155111) {
+        if (Number(network.chainId) !== 11155111) {

164-166: Don’t atob() the ciphertext — pass base64 string to Lit

Base64-decoding corrupts input for Lit decryption. Pass the base64 string directly.

-            const ciphertext = atob(encryptedStringBase64);
+            const ciphertext = encryptedStringBase64; // already base64

No other changes needed; decryptToString currently passes ciphertext variable correctly.

Also applies to: 217-226


25-41: Import toast used in cancel flow

toast.success/error is used but not imported; this will crash at runtime.

 import {
   createSiweMessageWithRecaps,
   generateAuthSig,
   LitAccessControlConditionResource,
 } from "@lit-protocol/auth-helpers";
+import { toast } from "react-toastify";
+import "react-toastify/dist/ReactToastify.css";

552-559: Fix tooltip date source — invoice.timestamp is undefined

Title uses invoice.timestamp leading to “Invalid Date”. Use the available issueDate.

-                            <Tooltip
-                              title={new Date(
-                                invoice.timestamp * 1000
-                              ).toLocaleString()}
-                            >
+                            <Tooltip
+                              title={new Date(invoice.issueDate).toLocaleString()}
+                            >

340-344: Guard against undefined/short addresses in formatter

Current implementation throws when address is undefined or too short.

-  const formatAddress = (address) => {
-    return `${address.substring(0, 10)}...${address.substring(
-      address.length - 10
-    )}`;
-  };
+  const formatAddress = (addr) => {
+    if (!addr) return "";
+    const s = String(addr);
+    if (s.length <= 20) return s;
+    return `${s.slice(0, 10)}...${s.slice(-10)}`;
+  };
frontend/src/page/ReceivedInvoice.jsx (5)

110-116: Fix BigInt vs Number comparison for chainId (ethers v6)

getNetwork().chainId is BigInt in ethers v6; comparing to a Number can throw. Use a BigInt literal or cast.

-        if (network.chainId != 11155111) {
+        if (network.chainId !== 11155111n) {

Or:

-        if (network.chainId != 11155111) {
+        if (Number(network.chainId) !== 11155111) {

167-167: Don’t atob() the ciphertext — pass base64 string to Lit

Base64-decoding the ciphertext breaks Lit decryption.

-            const ciphertext = atob(encryptedStringBase64);
+            const ciphertext = encryptedStringBase64; // already base64

Also applies to: 218-226


611-618: Status fallback shows Cancelled incorrectly — should be Pending/Unpaid

The else branch duplicates Cancelled; unpaid invoices should show Pending.

-                            ) : (
-                              <Chip
-                                icon={<CancelIcon />}
-                                label="Cancelled"
-                                color="error"
-                                size="small"
-                                variant="outlined"
-                              />
-                            )}
+                            ) : (
+                              <Chip
+                                icon={<UnpaidIcon />}
+                                label="Pending"
+                                color="warning"
+                                size="small"
+                                variant="outlined"
+                              />
+                            )}

652-660: Pass ZeroAddress for native ETH to avoid undefined tokenAddress

For ETH invoices, paymentToken.address may be undefined, causing isAddress() to fail.

-                                    payInvoice(
-                                      invoice.id,
-                                      invoice.amountDue,
-                                      invoice.paymentToken.address
-                                    )
+                                    payInvoice(
+                                      invoice.id,
+                                      invoice.amountDue,
+                                      invoice.paymentToken?.address ?? ethers.ZeroAddress
+                                    )

410-414: Guard against undefined/short addresses in formatter

Avoid substring on possibly undefined values; handle short strings.

-  const formatAddress = (address) => {
-    return `${address.substring(0, 10)}...${address.substring(
-      address.length - 10
-    )}`;
-  };
+  const formatAddress = (addr) => {
+    if (!addr) return "";
+    const s = String(addr);
+    if (s.length <= 20) return s;
+    return `${s.slice(0, 10)}...${s.slice(-10)}`;
+  };
frontend/src/page/Treasure.jsx (4)

41-44: Hoist and validate contract address; replace direct env usage

Avoid repeating import.meta.env.VITE_CONTRACT_ADDRESS and add a single validated constant. Prevents runtime errors when the env var is missing and improves consistency.

Apply this diff to replace direct usages:

-      const contract = new Contract(
-        import.meta.env.VITE_CONTRACT_ADDRESS,
-        ChainvoiceABI,
-        signer
-      );
+      const contract = new Contract(CONTRACT_ADDRESS, ChainvoiceABI, signer);

Add this at the top of the file (after imports):

// Add near imports
const CONTRACT_ADDRESS = import.meta.env.VITE_CONTRACT_ADDRESS;
if (!CONTRACT_ADDRESS) {
  console.error("VITE_CONTRACT_ADDRESS is not defined in environment variables");
}

Also applies to: 73-77, 97-101, 125-129


63-89: Replace alert() with toasts and improve UX for address updates

Replace blocking alert()s with non-blocking toasts; the app already uses react-hot-toast elsewhere.

Add import:

-import { useState, useEffect } from "react";
+import { useState, useEffect } from "react";
+import toast from "react-hot-toast";

Update the handler:

   const handleSetTreasuryAddress = async () => {
     if (!ethers.isAddress(newTreasuryAddress)) {
-      alert("Please enter a valid Ethereum address");
+      toast.error("Please enter a valid Ethereum address");
       return;
     }
     try {
       if (!walletClient) return;
@@
       await tx.wait();
       setTreasuryAddress(newTreasuryAddress);
       setNewTreasuryAddress("");
-      alert("Treasury address updated successfully!");
+      toast.success("Treasury address updated successfully");
     } catch (error) {
       console.error("Error setting treasury address:", error);
-      alert(error.message || "Failed to update treasury address");
+      toast.error(error?.shortMessage || error?.message || "Failed to update treasury address");
     } finally {
       setLoading((prev) => ({ ...prev, setAddress: false }));
     }
   };

91-113: Add a confirmation step and replace alerts in withdrawal flow

Withdrawing funds should require user confirmation. Also replace alert() with toasts.

   const handleWithdrawCollection = async () => {
+    const confirmWithdraw = window.confirm(
+      `Are you sure you want to withdraw ${treasureAmount} ETH to the treasury address?`
+    );
+    if (!confirmWithdraw) return;
     try {
       if (!walletClient) return;
@@
       const newAmt = await contract.accumulatedFees();
       setTreasureAmount(ethers.formatUnits(newAmt));
-      alert("Funds withdrawn successfully!");
+      toast.success("Funds withdrawn successfully");
     } catch (error) {
       console.error("Error withdrawing collection:", error);
-      alert(error.message || "Failed to withdraw funds");
+      toast.error(error?.shortMessage || error?.message || "Failed to withdraw funds");
     } finally {
       setLoading((prev) => ({ ...prev, withdraw: false }));
     }
   };

115-144: Strengthen fee validation and switch alerts to toasts

Enhance input validation to prevent negative/absurd fees and replace alert() with toasts. Keeps UX consistent and avoids accidental high-fee settings.

   const handleUpdateFee = async () => {
-    if (!newFee || isNaN(newFee)) {
-      alert("Please enter a valid fee amount");
-      return;
-    }
+    const feeValue = parseFloat(newFee);
+    if (!newFee || !Number.isFinite(feeValue) || feeValue < 0) {
+      toast.error("Please enter a valid positive fee amount");
+      return;
+    }
+    // Optional safety guard; adjust threshold to your business rules
+    if (feeValue > 1) {
+      toast.error("Fee amount seems too high. Please confirm the value.");
+      return;
+    }
     try {
       if (!walletClient) return;
       setLoading((prev) => ({ ...prev, feeUpdate: true }));
@@
-      const tx = await contract.setFeeAmount(
-        ethers.parseUnits(newFee, "ether")
-      );
+      const tx = await contract.setFeeAmount(ethers.parseUnits(newFee, "ether"));
       await tx.wait();
       const updatedFee = await contract.fee();
       setFee(ethers.formatUnits(updatedFee));
       setNewFee("");
-      alert("Fee updated successfully!");
+      toast.success("Fee updated successfully");
     } catch (error) {
       console.error("Error updating fee:", error);
-      alert(error.message || "Failed to update fee");
+      toast.error(error?.shortMessage || error?.message || "Failed to update fee");
     } finally {
       setLoading((prev) => ({ ...prev, feeUpdate: false }));
     }
   };
🧹 Nitpick comments (11)
frontend/src/page/SentInvoice.jsx (2)

872-881: Avoid floating-point math for totals; compute with base units

Mixing parseFloat with formatUnits is lossy. Prefer BigInt arithmetic and format only for display. For ETH, parse amountDue with 18 decimals; for ERC-20, keep fee (ETH) separate.

Example approach:

  • For ETH: const totalWei = ethers.parseUnits(amountDue, 18) + fee; display ethers.formatUnits(totalWei, 18).
  • For ERC-20: display ${amountDue} TOKEN + ${ethers.formatUnits(fee)} ETH.

If you want, I can provide a small helper to format totals safely using BigInt.


258-258: Nit: remove stale state log in finally

console.log(sentInvoices) logs the previous state due to closure. Consider moving logs to where state is updated or remove.

frontend/src/page/ReceivedInvoice.jsx (3)

623-631: Fix tooltip date source — invoice.timestamp is undefined

Using invoice.timestamp yields “Invalid Date”. Use issueDate instead.

-                            <Tooltip
-                              title={new Date(
-                                invoice.timestamp * 1000
-                              ).toLocaleString()}
-                            >
+                            <Tooltip
+                              title={new Date(invoice.issueDate).toLocaleString()}
+                            >

318-321: Prefer toast over alert for UX consistency

Use non-blocking toasts (already imported) for approval and success messages.

-          alert(
-            `Approval for ${tokenSymbol} completed! Now processing payment...`
-          );
+          toast.success(`Approved ${tokenSymbol}. Processing payment...`);
-        await tx.wait();
-        alert(`Payment successful in ${tokenSymbol}!`);
+        await tx.wait();
+        toast.success(`Payment successful in ${tokenSymbol}!`);
-        await tx.wait();
-        alert("Payment successful in ETH!");
+        await tx.wait();
+        toast.success("Payment successful in ETH!");

Also applies to: 328-339


970-979: Avoid floating-point math for totals; compute with base units

Same concern as SentInvoice: parseFloat with formatUnits is lossy. Prefer BigInt arithmetic for ETH totals and show “+ fee ETH” for ERC-20.

I can provide a small helper to compute and format totals safely if helpful.

frontend/src/page/Treasure.jsx (6)

284-289: Allow decimal fee input with step/min attributes

Type=number defaults to integer step=1 on some browsers. Permit decimals and disallow negatives.

-              <Input
-                type="number"
+              <Input
+                type="number"
+                step="any"
+                min="0"
                 placeholder={`Current: ${fee} ETH`}
                 value={newFee}
                 onChange={(e) => setNewFee(e.target.value)}
                 className="bg-gray-800 border-gray-700 text-white font-mono"
               />

316-318: Avoid implicit string-to-number coercion in disabled check

treasureAmount is a string from formatUnits. Be explicit to improve readability and prevent edge-case bugs.

-              disabled={loading.withdraw || treasureAmount <= 0}
+              disabled={loading.withdraw || Number(treasureAmount) <= 0}

Optional: Track the raw wei value in state to avoid floating point comparisons altogether.

// Example
const [treasuryAmountWei, setTreasuryAmountWei] = useState(0n);
// on fetch: setTreasuryAmountWei(amt);
// disabled={loading.withdraw || treasuryAmountWei === 0n}

39-44: DRY up contract instantiation with a helper

The provider/signer/contract boilerplate is repeated four times. Extracting it reduces errors and centralizes address/ABI changes.

Add once inside the component:

import { useCallback } from "react";

const getContract = useCallback(async () => {
  if (!walletClient) throw new Error("Wallet not connected");
  const provider = new BrowserProvider(walletClient);
  const signer = await provider.getSigner();
  return new Contract(CONTRACT_ADDRESS, ChainvoiceABI, signer);
}, [walletClient]);

Then replace occurrences:

-const provider = new BrowserProvider(walletClient);
-const signer = await provider.getSigner();
-const contract = new Contract(CONTRACT_ADDRESS, ChainvoiceABI, signer);
+const contract = await getContract();

Also applies to: 71-77, 95-101, 123-129


188-201: Reconcile Treasury UI with multi-token (ERC20) fees

The UI labels balances/fees as “ETH” and reads a single accumulatedFees and fee(). With ERC20 support, fees may accrue per-token and require separate withdraws.

  • Confirm the contract interface for token fees (e.g., accumulatedFees(address token), withdrawTokenFees(address token)).
  • Consider extending the UI with a token selector and per-token balances/withdrawals.
  • If ETH-only fees remain, clarify in copy and code comments.

Would you like a mock of a token-aware Treasury panel?


19-21: Align naming: “Treasure” → “Treasury”

Current naming mixes “Treasure” (component/file) with “Treasury” (UI text). Rename for clarity and consistency.

  • File: Treasure.jsx → Treasury.jsx
  • Component: Treasure → Treasury
  • State: treasureAmount → treasuryAmount

Also applies to: 31-31


183-184: Format displayed ETH values to a readable precision

Raw formatUnits strings can be long. Trim to a few decimals for UI polish.

Example helper:

const formatEth = (val) =>
  Number(val).toLocaleString(undefined, { maximumFractionDigits: 6 });

/* Usage */
{`${formatEth(treasureAmount)} ETH`}
{`${formatEth(fee)} ETH`}
`Withdraw ${formatEth(treasureAmount)} ETH`

Also applies to: 197-198, 324-325

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9a5ae47 and 7717396.

📒 Files selected for processing (4)
  • frontend/src/components/Navbar.jsx (5 hunks)
  • frontend/src/page/ReceivedInvoice.jsx (5 hunks)
  • frontend/src/page/SentInvoice.jsx (6 hunks)
  • frontend/src/page/Treasure.jsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/Navbar.jsx
🧰 Additional context used
🧬 Code Graph Analysis (3)
frontend/src/page/SentInvoice.jsx (6)
frontend/src/page/ReceivedInvoice.jsx (7)
  • columns (45-52)
  • page (55-55)
  • walletClient (57-57)
  • useAccount (58-58)
  • loading (59-59)
  • fee (61-61)
  • litClientRef (64-64)
frontend/src/page/Treasure.jsx (3)
  • walletClient (22-22)
  • loading (23-28)
  • fee (21-21)
frontend/src/page/CreateInvoice.jsx (4)
  • walletClient (52-52)
  • useAccount (53-53)
  • loading (57-57)
  • litClientRef (59-59)
frontend/src/components/Navbar.jsx (1)
  • useAccount (16-16)
frontend/src/page/About.jsx (2)
  • useAccount (7-7)
  • loading (9-9)
frontend/src/contractsABI/ChainvoiceABI.js (2)
  • ChainvoiceABI (1-589)
  • ChainvoiceABI (1-589)
frontend/src/page/Treasure.jsx (4)
frontend/src/page/CreateInvoice.jsx (2)
  • walletClient (52-52)
  • loading (57-57)
frontend/src/contractsABI/ChainvoiceABI.js (2)
  • ChainvoiceABI (1-589)
  • ChainvoiceABI (1-589)
frontend/src/components/ui/input.jsx (1)
  • Input (5-16)
frontend/src/components/ui/button.jsx (1)
  • Button (37-45)
frontend/src/page/ReceivedInvoice.jsx (6)
frontend/src/page/SentInvoice.jsx (6)
  • columns (49-56)
  • page (59-59)
  • useAccount (62-62)
  • loading (63-63)
  • fee (65-65)
  • handlePrint (285-296)
frontend/src/components/Navbar.jsx (1)
  • useAccount (16-16)
frontend/src/page/About.jsx (2)
  • useAccount (7-7)
  • loading (9-9)
frontend/src/utils/erc20_token.js (2)
  • TOKEN_PRESETS (8-709)
  • TOKEN_PRESETS (8-709)
frontend/src/contractsABI/ERC20_ABI.js (2)
  • ERC20_ABI (1-10)
  • ERC20_ABI (1-10)
frontend/src/page/Working.jsx (1)
  • handlePrint (23-48)
🔇 Additional comments (1)
frontend/src/page/Treasure.jsx (1)

38-39: Verify BrowserProvider compatibility with wagmi's walletClient (v2)

new BrowserProvider(walletClient) assumes walletClient is an EIP-1193 provider. Depending on wagmi version, you may need walletClient.transport?.provider or a fallback to window.ethereum.

If you encounter runtime/type errors, this pattern is safer:

const eip1193 = walletClient?.transport?.provider ?? window.ethereum;
const provider = new BrowserProvider(eip1193);
const signer = await provider.getSigner();

Please verify on the targeted wagmi/ethers versions and across popular wallets (MetaMask, RainbowKit connectors).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (3)
frontend/src/page/ReceivedInvoice.jsx (3)

110-116: Fix BigInt vs Number chainId comparison (ethers v6).

getNetwork().chainId is BigInt in ethers v6. Comparing to a Number risks subtle bugs and makes intent unclear. Use a BigInt literal or coerce to Number.

Apply one of the following diffs:

-        if (network.chainId != 11155111) {
+        if (network.chainId !== 11155111n) {

or

-        if (network.chainId != 11155111) {
+        if (Number(network.chainId) !== 11155111) {

167-167: Don’t atob() the ciphertext — pass base64 string to Lit.

atob(encryptedStringBase64) corrupts the payload expected by Lit; Lit expects the ciphertext as base64.

Apply:

-            const ciphertext = atob(encryptedStringBase64);
+            const ciphertext = encryptedStringBase64; // already base64

410-414: Guard against undefined/short addresses in formatter.

Current implementation will throw for falsy or short inputs.

Apply:

-  const formatAddress = (address) => {
-    return `${address.substring(0, 10)}...${address.substring(
-      address.length - 10
-    )}`;
-  };
+  const formatAddress = (addr) => {
+    if (!addr) return "";
+    const s = String(addr);
+    if (s.length <= 20) return s;
+    return `${s.slice(0, 10)}...${s.slice(-10)}`;
+  };
🧹 Nitpick comments (8)
frontend/src/page/ReceivedInvoice.jsx (8)

241-246: Harden token metadata merge; handle decimal vs decimals and missing fields.

Some presets use decimal (singular). Preserve existing fields and provide sensible fallbacks.

Apply:

-              if (tokenInfo) {
-                parsed.paymentToken = {
-                  ...parsed.paymentToken,
-                  logo: tokenInfo.logo,
-                  decimals: tokenInfo.decimals,
-                };
-              }
+              if (tokenInfo) {
+                parsed.paymentToken = {
+                  ...parsed.paymentToken,
+                  logo: tokenInfo.logo ?? parsed.paymentToken.logo,
+                  decimals:
+                    tokenInfo.decimals ??
+                    tokenInfo.decimal ??
+                    parsed.paymentToken.decimals ??
+                    18,
+                  symbol: tokenInfo.symbol ?? parsed.paymentToken.symbol,
+                  name: tokenInfo.name ?? parsed.paymentToken.name,
+                };
+              }

318-321: Replace blocking alert with non-blocking toast for approval flow.

Alerts block UI and are inconsistent with toast-based error handling.

Apply:

-          await approveTx.wait();
-          alert(
-            `Approval for ${tokenSymbol} completed! Now processing payment...`
-          );
+          await approveTx.wait();
+          toast.info(`Approval for ${tokenSymbol} completed! Now processing payment...`);

327-339: Use toast for payment success messages (both ERC20 and ETH paths).

Keep feedback consistent and non-blocking.

Apply:

-        await tx.wait();
-        alert(`Payment successful in ${tokenSymbol}!`);
+        await tx.wait();
+        toast.success(`Payment successful in ${tokenSymbol}!`);

and

-        await tx.wait();
-        alert("Payment successful in ETH!");
+        await tx.wait();
+        toast.success("Payment successful in ETH!");

404-405: Use toast for network switch failure; avoid blocking alert.

Aligns with the rest of your UX.

Apply:

-      console.error("Network switch failed:", error);
-      alert("Failed to switch network. Please switch to Sepolia manually.");
+      console.error("Network switch failed:", error);
+      toast.error("Failed to switch network. Please switch to Sepolia manually.");

130-131: Remove noisy console log or guard behind a debug flag.

Avoid logging raw on-chain/encrypted data in production.

Apply:

-        console.log("Raw invoices data:", res);
+        // console.debug("Raw invoices data:", res);

880-888: Use the shared formatter for token address display.

The current slicing uses hard-coded indices and may produce uneven truncation. Reuse formatAddress for consistency and safety.

Apply:

-                    {drawerState.selectedInvoice.paymentToken?.address
-                      ? `${drawerState.selectedInvoice.paymentToken.address.substring(
-                          0,
-                          10
-                        )}......${drawerState.selectedInvoice.paymentToken.address.substring(
-                          33
-                        )}`
-                      : "Native Currency"}
+                    {drawerState.selectedInvoice.paymentToken?.address
+                      ? formatAddress(drawerState.selectedInvoice.paymentToken.address)
+                      : "Native Currency"}

570-589: Amount column: provide a fallback symbol for native ETH.

If paymentToken?.symbol is undefined for native payments, the amount renders without a symbol.

Apply:

-                                {invoice.amountDue}{" "}
-                                {invoice.paymentToken?.symbol}
+                                {invoice.amountDue}{" "}
+                                {invoice.paymentToken?.symbol ?? "ETH"}

395-401: Guard against missing window.ethereum.

Prevent runtime errors on non-EIP-1193 environments.

Apply:

-      await window.ethereum.request({
+      if (!window?.ethereum?.request) {
+        toast.error("No Ethereum provider found. Please install MetaMask.");
+        return;
+      }
+      await window.ethereum.request({
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7717396 and c43085e.

📒 Files selected for processing (2)
  • frontend/src/page/ReceivedInvoice.jsx (5 hunks)
  • frontend/src/page/SentInvoice.jsx (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/page/SentInvoice.jsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
frontend/src/page/ReceivedInvoice.jsx (4)
frontend/src/components/Navbar.jsx (1)
  • useAccount (16-16)
frontend/src/contractsABI/ChainvoiceABI.js (2)
  • ChainvoiceABI (1-589)
  • ChainvoiceABI (1-589)
frontend/src/utils/erc20_token.js (2)
  • TOKEN_PRESETS (8-709)
  • TOKEN_PRESETS (8-709)
frontend/src/contractsABI/ERC20_ABI.js (2)
  • ERC20_ABI (1-10)
  • ERC20_ABI (1-10)
🔇 Additional comments (1)
frontend/src/page/ReceivedInvoice.jsx (1)

654-659: LGTM: Default ZeroAddress for native ETH payment.

Good catch defaulting to ethers.ZeroAddress when token address is absent. This avoids isAddress failures and cleanly distinguishes native from ERC-20.

@kumawatkaran523 kumawatkaran523 changed the title Multi-Token (ERC20) Payment Support Implementation Multi-Token (ERC20) Payment Support and Invoice Cancellation Aug 14, 2025
@kumawatkaran523
Copy link
Contributor Author

Added Invoice cancellation Feature

image image image image

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (4)
frontend/src/page/ReceivedInvoice.jsx (4)

110-116: Fix BigInt vs Number comparison for chainId (ethers v6).

getNetwork().chainId is a BigInt in ethers v6; comparing to a Number will throw. Use a BigInt literal or coerce safely.

Apply:

-        if (network.chainId != 11155111) {
+        if (network?.chainId !== 11155111n) {

Alternatively (if you prefer coercion):

-        if (network.chainId != 11155111) {
+        if (Number(network?.chainId) !== 11155111) {

167-167: Don’t atob() the ciphertext — pass base64 string to Lit.

Base64-decoding the ciphertext breaks Lit decryption. Lit expects the base64 string as-is.

Apply:

-            const ciphertext = atob(encryptedStringBase64);
+            const ciphertext = encryptedStringBase64; // already base64-encoded

Also applies to: 218-227


394-408: After network switch, refresh state or listen to chain changes.

Switching chains clears the error, but the UI may remain stale. Trigger a refresh or subscribe to chain changes.

Minimal fix (inline):

   const switchNetwork = async () => {
     try {
       setNetworkLoading(true);
+      if (!window?.ethereum) {
+        toast.error("No Ethereum provider found");
+        return;
+      }
       await window.ethereum.request({
         method: "wallet_switchEthereumChain",
         params: [{ chainId: "0xaa36a7" }], // Sepolia chain ID
       });
       setError(null);
+      // Ensure UI reflects the new network immediately
+      window.location.reload();

Preferred (add a chainChanged listener and refetch instead of reloading). Because fetchReceivedInvoices is scoped inside an effect, wrap it with useCallback first, then add:

// Add near other hooks (outside effects)
const fetchReceivedInvoices = useCallback(async () => {
  // move existing body from inside the effect here
}, [walletClient, address, litReady]);

useEffect(() => {
  if (!walletClient || !address || !litReady) return;
  fetchReceivedInvoices();
}, [walletClient, litReady, address, fetchReceivedInvoices]);

useEffect(() => {
  if (!window?.ethereum) return;
  const handler = () => fetchReceivedInvoices();
  window.ethereum.on("chainChanged", handler);
  return () => {
    window.ethereum.removeListener("chainChanged", handler);
  };
}, [fetchReceivedInvoices]);

410-414: Guard against undefined/short addresses in formatter.

Apply:

-  const formatAddress = (address) => {
-    return `${address.substring(0, 10)}...${address.substring(
-      address.length - 10
-    )}`;
-  };
+  const formatAddress = (addr) => {
+    if (!addr) return "";
+    const s = String(addr);
+    if (s.length <= 20) return s;
+    return `${s.slice(0, 10)}...${s.slice(-10)}`;
+  };
🧹 Nitpick comments (5)
frontend/src/page/ReceivedInvoice.jsx (5)

318-321: Replace blocking alerts with non-blocking toasts for consistent UX.

Leverage react-toastify (already imported) instead of alert() to avoid blocking modals and maintain a consistent notification style.

Apply:

-          await approveTx.wait();
-          alert(
-            `Approval for ${tokenSymbol} completed! Now processing payment...`
-          );
+          await approveTx.wait();
+          toast.info(`Approval for ${tokenSymbol} completed. Processing payment...`);
-        await tx.wait();
-        alert(`Payment successful in ${tokenSymbol}!`);
+        await tx.wait();
+        toast.success(`Payment successful in ${tokenSymbol}!`);
-        await tx.wait();
-        alert("Payment successful in ETH!");
+        await tx.wait();
+        toast.success("Payment successful in ETH!");

Also applies to: 328-339


416-419: Make date formatting robust for epoch seconds/strings.

issueDate may be epoch seconds (10-digit) or a numeric/string. Current code can produce “Invalid Date”.

Apply:

-  const formatDate = (issueDate) => {
-    const date = new Date(issueDate);
-    return date.toLocaleString();
-  };
+  const formatDate = (value) => {
+    if (!value) return "";
+    let date;
+    const n = typeof value === "string" ? Number(value) : value;
+    if (Number.isFinite(n)) {
+      // Heuristic: treat 10-digit epoch seconds as seconds
+      date = new Date(n < 1e12 ? n * 1000 : n);
+    } else {
+      date = new Date(value);
+    }
+    return isNaN(date.getTime()) ? "" : date.toLocaleString();
+  };

874-882: Use formatAddress here instead of hard-coded substrings.

The current slicing assumes fixed length and uses a magic index (33). Reuse the formatter for consistency and safety.

Apply:

-                    {drawerState.selectedInvoice.paymentToken?.address
-                      ? `${drawerState.selectedInvoice.paymentToken.address.substring(
-                          0,
-                          10
-                        )}......${drawerState.selectedInvoice.paymentToken.address.substring(
-                          33
-                        )}`
-                      : "Native Currency"}
+                    {drawerState.selectedInvoice.paymentToken?.address
+                      ? formatAddress(
+                          drawerState.selectedInvoice.paymentToken.address
+                        )
+                      : "Native Currency"}

259-262: Surface fetch/decrypt failures to the user (not just console).

Errors during fetch/decrypt are swallowed from the UX perspective. Provide feedback so users know to retry or switch networks.

Apply:

-      } catch (error) {
-        console.error("Fetch error:", error);
+      } catch (error) {
+        console.error("Fetch error:", error);
+        toast.error("Failed to load invoices. Please try again.");

18-18: Avoid deep import path for Lit decryptToString.

Importing from an internal path can break across versions/bundlers. Prefer the package entrypoint.

Apply:

-import { decryptToString } from "@lit-protocol/encryption/src/lib/encryption.js";
+import { decryptToString } from "@lit-protocol/encryption";
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c43085e and 363b696.

📒 Files selected for processing (1)
  • frontend/src/page/ReceivedInvoice.jsx (5 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
frontend/src/page/ReceivedInvoice.jsx (3)
frontend/src/contractsABI/ChainvoiceABI.js (2)
  • ChainvoiceABI (1-589)
  • ChainvoiceABI (1-589)
frontend/src/utils/erc20_token.js (2)
  • TOKEN_PRESETS (8-709)
  • TOKEN_PRESETS (8-709)
frontend/src/contractsABI/ERC20_ABI.js (2)
  • ERC20_ABI (1-10)
  • ERC20_ABI (1-10)

@adityabhattad2021 adityabhattad2021 merged commit 3c43534 into StabilityNexus:main Aug 17, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants