Skip to content

Conversation

@SIDDHANTCOOKIE
Copy link

@SIDDHANTCOOKIE SIDDHANTCOOKIE commented Jan 26, 2026

Problem

Users will get cryptic "missing revert data" error when trying to create an invoice to themselves. The contract correctly blocks self-invoicing, but the frontend doesn't validate this before submission, causing gas estimation to fail.

Solution

Added frontend validation in CreateInvoice.jsx to check:

  1. Client address is valid
  2. Client address is different from sender address

Now users get a clear error message: "Cannot create invoice to yourself. Please use a different client address."

Fixes #82

Testing

  • Verified validation triggers when client address matches user address
  • Verified invoice creation works with different addresses
  • Error message is clear and actionable
    @Zahnentferner @kumawatkaran523 is my approach correct ? awaiting review thanks

Summary by CodeRabbit

  • New Features
    • Enhanced client wallet address validation in invoice creation with real-time, inline feedback as users type or when fields are prefilled via URL.
    • Validation covers empty/short inputs, address format/EVM compatibility, and prevents submitting invoices to your own address.
    • Submission is blocked until address validation passes; inline alert shown in the Client Information section.

✏️ Tip: You can customize this high-level summary in your review settings.

@kumawatkaran523
Copy link
Contributor

@SIDDHANTCOOKIE Although it’s good to prevent self-invoice scenarios, and great that you identified and fixed the issue, can we also work on improving the UI of the alert message?

@SIDDHANTCOOKIE
Copy link
Author

@kumawatkaran523 Thanks for the review. I will improve the UI of the alert message and update the PR shortly.

@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

📝 Walkthrough

Walkthrough

Adds inline client wallet address validation to the CreateInvoice form, integrates validation into prefill and submission flows (blocking submit on error), renders an inline clientAddressError alert, and introduces a duplicated validateClientAddress implementation in the same file.

Changes

Cohort / File(s) Summary
Client address validation
frontend/src/page/CreateInvoice.jsx
Adds clientAddressError state, validateClientAddress(value) usage in URL-prefill, onChange/onBlur handlers, and validation-before-submit logic (abort if error). Renders inline error UI in Client Information.
Duplication
frontend/src/page/CreateInvoice.jsx
validateClientAddress is implemented twice (identical logic) within the file; requires consolidation to remove redundancy.

Sequence Diagram(s)

sequenceDiagram
    participant U as User (UI)
    participant C as CreateInvoice component
    participant E as Ethers/isAddress check
    participant S as Invoice API (createInvoiceRequest)

    U->>C: Enter or prefill client address
    C->>C: validateClientAddress(value)
    C->>E: isAddress(value) / format checks
    alt invalid or self-invoice
        C-->>U: set `clientAddressError` (inline alert) and block submit
    else valid
        C-->>U: clear `clientAddressError`
        U->>C: Submit form
        C->>C: validateClientAddress(currentValue)
        alt still valid
            C->>S: createInvoiceRequest(payload)
            S-->>C: success / failure
        else invalid
            C-->>U: show `clientAddressError` and abort
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through form and field so wide,

I checked each address on the side,
I flagged the twins and raised a bell,
Two copies hid where one should dwell,
I’ll tidy hops and make it right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: preventing self-invoicing through frontend validation, which directly addresses the core issue.
Linked Issues check ✅ Passed The PR successfully implements frontend validation to prevent self-invoicing (checking client address against sender address) and validates EVM address format, meeting the core requirements from issue #82.
Out of Scope Changes check ✅ Passed All changes in CreateInvoice.jsx are directly related to validating client addresses and preventing self-invoicing; no unrelated modifications were introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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

🤖 Fix all issues with AI agents
In `@frontend/src/page/CreateInvoice.jsx`:
- Around line 725-735: The URL param useEffect sets clientAddress but doesn't
run validation; update the same effect that reads the clientAddress URL param
(where setClientAddress(...) is called) to also call
validateClientAddress(clientAddressValue) after setting state so the error state
reflects URL-prefilled values; ensure you reference the clientAddress state, the
validateClientAddress function, and the useEffect that parses URL params to
perform this additional call.
🧹 Nitpick comments (1)
frontend/src/page/CreateInvoice.jsx (1)

336-347: Duplicate validation logic and inconsistent null safety.

Two issues:

  1. DRY violation: This block duplicates the logic already in validateClientAddress. Consider refactoring validateClientAddress to return a boolean or error string, then reuse it here.

  2. Potential runtime error: Line 343 uses account.address.toLowerCase() without optional chaining, but line 322 in validateClientAddress uses account.address?.toLowerCase(). If account.address is undefined, this will throw.

♻️ Suggested refactor
-const validateClientAddress = (value) => {
+const validateClientAddress = (value, setError = true) => {
   // Empty input, no error
   if (!value) {
-    setClientAddressError("");
-    return;
+    if (setError) setClientAddressError("");
+    return "Please enter a valid wallet address";
   }

   // Do not validate until it looks like a full EVM address
   if (!value.startsWith("0x") || value.length < 42) {
-    setClientAddressError("");
-    return;
+    if (setError) setClientAddressError("");
+    return "Please enter a valid wallet address";
   }

   // Invalid EVM address
   if (!ethers.isAddress(value)) {
-    setClientAddressError("Please enter a valid wallet address");
-    return;
+    if (setError) setClientAddressError("Please enter a valid wallet address");
+    return "Please enter a valid wallet address";
   }

   // Self-invoicing check
   if (value.toLowerCase() === account.address?.toLowerCase()) {
-    setClientAddressError("You cannot create an invoice for your own wallet");
-    return;
+    const msg = "You cannot create an invoice for your own wallet";
+    if (setError) setClientAddressError(msg);
+    return msg;
   }

   // Valid other wallet
-  setClientAddressError("");
+  if (setError) setClientAddressError("");
+  return null;
 };

Then in createInvoiceRequest:

-// Validate client address
-    if (!data.clientAddress || !ethers.isAddress(data.clientAddress)) {
-  setClientAddressError("Please enter a valid wallet address");
-  return;
- }
-
-    // Check for self-invoicing
-    if (data.clientAddress.toLowerCase() === account.address.toLowerCase()) {
-  setClientAddressError("You cannot create an invoice for your own wallet");
-  return;
-}
-   setClientAddressError("");
+    const validationError = validateClientAddress(data.clientAddress);
+    if (validationError) {
+      return;
+    }

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

🤖 Fix all issues with AI agents
In `@frontend/src/page/CreateInvoice.jsx`:
- Around line 318-376: Remove the duplicated verifyToken function (the one
defined around lines 318-376) and keep the original useCallback-wrapped
verifyToken; delete the duplicate's rpcUrls and logic, remove the debug
console.log, and ensure the retained (useCallback) verifyToken sets chainId on
setVerifiedToken (add chainId: chainIdToUse) and uses the shared
CHAIN_ID_TO_PUBLIC_RPC constant instead of redefining RPC URLs so provider
selection remains RPC-first for link-sharing.
🧹 Nitpick comments (1)
frontend/src/page/CreateInvoice.jsx (1)

378-405: Consider wrapping in useCallback for consistency.

The validation logic is correct. Since this function is passed as a callback to onChange and references account.address, consider wrapping it in useCallback with [account.address] dependencies for better performance and to avoid unnecessary re-renders.

♻️ Optional improvement
-const validateClientAddress = (value) => {
+const validateClientAddress = useCallback((value) => {
   // Empty input, no error
   if (!value) {
     setClientAddressError("");
     return;
   }
   // ... rest of function
   setClientAddressError("");
-};
+}, [account.address]);

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

🤖 Fix all issues with AI agents
In `@frontend/src/page/CreateInvoice.jsx`:
- Around line 159-161: The useEffect calls validateClientAddress before its
const definition, creating a fragile TDZ risk; move the validateClientAddress
function above the useEffect that uses it (or convert it to a useCallback and
place its definition earlier) and then add that validateClientAddress callback
to the useEffect dependency array so the hook references a stable, defined
function (ensure validateClientAddress retains access to account.address via its
dependency list if converted to useCallback).
🧹 Nitpick comments (3)
frontend/src/page/CreateInvoice.jsx (3)

379-406: Wrap validateClientAddress in useCallback for memoization and closure safety.

This function depends on account.address but isn't memoized. If account changes (e.g., user switches wallets), the closure captures the old value until the component re-renders. Additionally, without useCallback, the function is recreated on every render.

♻️ Proposed fix
-const validateClientAddress = (value) => {
+const validateClientAddress = useCallback((value) => {
   if (!value) {
     setClientAddressError("");
     return;
   }
   if (!value.startsWith("0x") || value.length < 42) {
     setClientAddressError("");
     return;
   }
   if (!ethers.isAddress(value)) {
     setClientAddressError("Please enter a valid wallet address");
     return;
   }
   if (value.toLowerCase() === account.address?.toLowerCase()) {
     setClientAddressError("You cannot create an invoice for your own wallet");
     return;
   }
   setClientAddressError("");
-};
+}, [account.address]);

413-424: Validation at submission is correct, but consider returning a boolean from validateClientAddress.

Having validation both on input change and at submission time is good defense-in-depth. However, the logic is duplicated. Consider refactoring validateClientAddress to return a boolean, which would allow reuse:

const isValid = validateClientAddress(data.clientAddress);
if (!isValid) return;

This is optional since the current implementation works correctly.


807-810: Consider extracting the inline handler for readability.

The inline handler works but is cramped. A named handler would be clearer:

const handleClientAddressChange = (e) => {
  const value = e.target.value;
  setClientAddress(value);
  validateClientAddress(value);
};

Then: onChange={handleClientAddressChange}

@SIDDHANTCOOKIE
Copy link
Author

SIDDHANTCOOKIE commented Jan 28, 2026

@kumawatkaran523 as you told I've made the changes to the alerts, now the alerts are shown inline alert: when user puts the same address to prevent self-invoicing and when a user puts invalid address to remind of the invalid address.

Visual of the alerts

Screenshot 2026-01-29 012114 Screenshot 2026-01-29 024205

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.

Invoice creation failed

2 participants