-
Notifications
You must be signed in to change notification settings - Fork 17
Updated readme.md with Deployment guide #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis update introduces two new Git submodules for external contract dependencies, adds example environment configuration files for both backend and frontend, and modifies the documentation to include Ethereum Classic deployment instructions. It removes a Solidity mock contract, refactors the Chainvoice smart contract and its ABI, updates environment file handling and import statements, and adjusts frontend environment management. The frontend components are enhanced to encrypt and decrypt invoice data using Lit Protocol, integrating access control and secure data handling. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User (Frontend)
participant Lit as Lit Protocol
participant Contract as Chainvoice Contract
participant Blockchain as Ethereum Network
User->>Lit: Connect and authenticate (SIWE)
User->>Lit: Encrypt invoice data with access control
Lit-->>User: Return encrypted data and encrypted hash
User->>Contract: Call createInvoice(encryptedData, encryptedHash)
Contract->>Blockchain: Store encrypted invoice on-chain
User->>Contract: Request received/sent invoices (encrypted)
Contract-->>User: Returns encrypted invoice data
User->>Lit: Decrypt invoice data with access control
Lit-->>User: Returns decrypted invoice details
User->>UI: Display decrypted invoice details
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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
🧹 Nitpick comments (7)
contracts/.env.example (1)
1-3: Remind users to secure their private key
The placeholderPRIVATE_KEY=your_private_key_hereis fine, but consider adding a comment or README note that.envmust never be committed and private keys should be stored securely.frontend/src/App.jsx (1)
16-16: Remove unused CSS import
The removal ofimport './App.css';is appropriate given the Tailwind setup. Consider deleting the now-unusedApp.cssfile to keep the codebase clean.frontend/.env.example (1)
1-1: Clarify the purpose of the "env-copy" comment.The comment
# env-copyat the top is unclear. Consider replacing it with a more descriptive comment explaining the file's purpose.-# env-copy +# Frontend Environment Variables Template +# Copy this file to .env and update the values for your deploymentREADME.md (3)
59-59: Add missing comma before abbreviation.Grammar improvement needed before "i.e.".
-- Create a .env in your project root i.e. `contracts/` +- Create a .env in your project root, i.e. `contracts/`🧰 Tools
🪛 LanguageTool
[typographical] ~59-~59: Consider putting a comma before the abbreviation “i.e.”.
Context: ...ts - Create a .env in your project root i.e.contracts/- Copy all the varible...(IE_COMMA)
79-79: Add missing article and improve grammar.Two grammar improvements needed for better readability.
-5. Finally add Contract Address to Frontend `.env` +5. Finally add the Contract Address to the Frontend `.env`🧰 Tools
🪛 LanguageTool
[uncategorized] ~79-~79: Possible missing comma found.
Context: ...y $PRIVATE_KEY \ --broadcast \ ``` 5. Finally add Contract Address to Frontend.env...(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~79-~79: You might be missing the article “the” here.
Context: ...EY \ --broadcast \ ``` 5. Finally add Contract Address to Frontend.env- Creat...(AI_EN_LECTOR_MISSING_DETERMINER_THE)
90-90: Add comma for compound sentence clarity.Grammar improvement for better sentence flow.
-- Restart your frontend development server so the new environment variables are loaded. +- Restart your frontend development server, so the new environment variables are loaded.🧰 Tools
🪛 LanguageTool
[uncategorized] ~90-~90: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...Restart your frontend development server so the new environment variables are loade...(COMMA_COMPOUND_SENTENCE_2)
frontend/src/contractsABI/ChainvoiceABI.js (1)
770-770: Potential typo in parameter namenewTreauserAdd.The parameter name
newTreauserAddappears to be a typo. It should likely benewTreasuryAddornewTreasuryAddressfor clarity and consistency.Consider updating the ABI if this represents an actual contract interface issue, or verify that this parameter name is intentional.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
.gitmodules(1 hunks)README.md(1 hunks)contracts/.env.example(1 hunks)contracts/lib/forge-std(1 hunks)contracts/src/MockV3Aggregator.sol(0 hunks)frontend/.env(0 hunks)frontend/.env.example(1 hunks)frontend/.gitignore(2 hunks)frontend/src/App.jsx(1 hunks)frontend/src/contractsABI/ChainvoiceABI.js(6 hunks)
💤 Files with no reviewable changes (2)
- frontend/.env
- contracts/src/MockV3Aggregator.sol
🧰 Additional context used
🪛 LanguageTool
README.md
[typographical] ~59-~59: Consider putting a comma before the abbreviation “i.e.”.
Context: ...ts - Create a .env in your project root i.e. contracts/ - Copy all the varible...
(IE_COMMA)
[uncategorized] ~79-~79: Possible missing comma found.
Context: ...y $PRIVATE_KEY \ --broadcast \ ``` 5. Finally add Contract Address to Frontend .env...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~79-~79: You might be missing the article “the” here.
Context: ...EY \ --broadcast \ ``` 5. Finally add Contract Address to Frontend .env - Creat...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
[uncategorized] ~90-~90: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...Restart your frontend development server so the new environment variables are loade...
(COMMA_COMPOUND_SENTENCE_2)
🪛 markdownlint-cli2 (0.17.2)
README.md
73-73: Fenced code blocks should have a language specified
null
(MD040, fenced-code-language)
🔇 Additional comments (12)
frontend/.gitignore (2)
14-14: Ignore base.envfile
Adding.envensures local environment variables won’t be accidentally committed, which is critical for protecting sensitive data.
26-26: Add Vim swap file patterns
The wildcard*.sw?correctly ignores Vim swap files (e.g.,.swp,.swo).contracts/.env.example (2)
4-8: Sepolia network placeholders look correct
The RPC URL, chain ID11155111, and explorer URL follow a consistent naming convention and align with Sepolia testnet settings.
9-12: Ethereum Classic network placeholders look correct
Chain ID61and the RPC URL placeholder match ETC mainnet configuration.contracts/lib/forge-std (1)
1-1: Verify submodule configuration in.gitmodules.This gitlink commit pins the
contracts/lib/forge-stdsubmodule to a specific commit. Please confirm that the root.gitmodulesfile has been updated with the correctpathandurlfor this submodule, and that CI workflows includegit submodule update --init --recursiveto ensure reproducible builds..gitmodules (1)
1-6: LGTM! Well-configured submodules for Foundry and Chainlink integration.The Git submodules are properly configured to integrate official dependencies:
forge-stdprovides Foundry's standard testing librarychainlink-brownie-contractsoffers official Chainlink contract interfacesThis setup supports the transition from mock contracts to real Chainlink dependencies as mentioned in the AI summary.
frontend/.env.example (1)
3-14: Well-structured environment template with clear examples.The environment variables are properly configured with:
- Appropriate
VITE_prefix for client-side exposure- Clear descriptive comments with network examples
- Logical grouping of related configuration
This template provides excellent guidance for users setting up their frontend environment.
frontend/src/contractsABI/ChainvoiceABI.js (5)
4-4: Breaking change: Constructor no longer accepts parameters.The constructor now has an empty inputs array, which is a significant change from the previous interface. Ensure that any deployment scripts and frontend initialization code are updated accordingly.
757-760: Parameter renamed insetFeeAmountfunction.The parameter has been renamed from the previous name to
_feeand the type changed touint256. Verify that frontend code calling this function uses the correct parameter structure.
174-180:Details
✅ Verification successful
Breaking change:
getReceivedInvoicesnow requires an address parameter.The function signature has changed from
getMyReceivedInvoices()togetReceivedInvoices(address _address). This breaking change affects how the frontend retrieves received invoices.
🏁 Script executed:
#!/bin/bash # Description: Verify frontend code has been updated for the new function signature # Search for references to old function names rg -i "getMyReceivedInvoices|getReceivedInvoices" frontend/ # Check for proper address parameter usage rg -A 3 -B 3 "getReceivedInvoices" frontend/Length of output: 1337
Confirmed: Frontend Updated for
getReceivedInvoices(address)All calls to the old
getMyReceivedInvoices()have been removed, andReceivedInvoice.jsxnow correctly invokes:const res = await contract.getReceivedInvoices(address);No further changes are needed—this breaking change has been fully addressed.
161-161:Details
✅ Verification successful
Function renamed from
feeAmountInUSDtofee.This is a breaking change that requires updating all frontend code that previously called
feeAmountInUSD().
🏁 Script executed:
#!/bin/bash # Description: Check if frontend code has been updated to use the new function name # Search for any remaining references to the old function name rg -i "feeAmountInUSD" frontend/Length of output: 32
Function rename to
feevalidated
- Searched the entire frontend (
rg -i "feeAmountInUSD" frontend/) and found no remaining references.- ABI entry at
frontend/src/contractsABI/ChainvoiceABI.js:161correctly uses"name": "fee".All calls have been updated—approving these changes.
341-348:Details
✅ Verification successful
Breaking change:
getSentInvoicesnow requires an address parameter.Similar to
getReceivedInvoices, this function has been renamed fromgetMySentInvoices()and now requires an address parameter. Ensure frontend code passes the appropriate address when calling this function.
🏁 Script executed:
#!/bin/bash # Description: Verify frontend usage of getSentInvoices function # Search for references to old and new function names rg -i "getMySentInvoices|getSentInvoices" frontend/ # Check for proper address parameter usage rg -A 3 -B 3 "getSentInvoices" frontend/Length of output: 1304
getSentInvoices usage confirmed
The front-end code inSentInvoice.jsxalready callscontract.getSentInvoices(address), so the address parameter is being passed as required. No further changes are needed.• frontend/src/page/SentInvoice.jsx:
const res = await contract.getSentInvoices(address);
| ``` | ||
| forge create src/Contract.sol:Contract \ | ||
| --rpc-url $SEPOLIA_RPC_URL \ | ||
| --private-key $PRIVATE_KEY \ | ||
| --broadcast \ | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix code block and variable naming issues.
Two issues need addressing:
- Missing language specification for the code block
- Using
SEPOLIA_RPC_URLvariable in an Ethereum Classic deployment guide
-```
+```bash
forge create src/Contract.sol:Contract \
- --rpc-url $SEPOLIA_RPC_URL \
+ --rpc-url $ETC_RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast \
-```
+```🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
73-73: Fenced code blocks should have a language specified
null
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
In README.md around lines 73 to 78, fix the code block by specifying the
language as bash for proper formatting and replace the variable SEPOLIA_RPC_URL
with ETC_RPC_URL to correctly reflect the Ethereum Classic deployment
environment. Also, ensure the closing code block uses triple backticks without a
language specifier.
There was a problem hiding this 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
🧹 Nitpick comments (1)
contracts/src/Chainvoice.sol (1)
122-130: Setters lack events – hinder off-chain indexing & audits.
setFeeAmountandsetTreasuryAddressmutate critical economic parameters yet emit no events.
EmitFeeUpdated(oldFee, newFee)andTreasuryUpdated(oldAddr, newAddr)so indexers / UIs can react to governance changes and historical state can be audited.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
contracts/src/Chainvoice.sol(1 hunks)
🔇 Additional comments (1)
contracts/src/Chainvoice.sol (1)
131-140: Anyone can triggerwithdrawFees– verify this is intended.
withdrawFeesis publicly callable; the caller cannot redirect funds, but they can force a withdrawal at arbitrary times (e.g., front-run an owner who prefers batching to save gas).
If you want only governance control over timing, addonlyOwner; otherwise leave as-is but document the open callable nature.
There was a problem hiding this 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
🧹 Nitpick comments (2)
frontend/src/page/ReceivedInvoice.jsx (1)
528-545: Add a stable React key in theitems.maploop
<tbody>rendered without akeyprop triggers React warnings and was flagged by static analysis.-{drawerState.selectedInvoice?.items?.map((item, index) => ( - <tbody> +{drawerState.selectedInvoice?.items?.map((item, index) => ( + <tbody key={index}>frontend/src/components/CreateInvoice.jsx (1)
187-216: Unnecessary session sigs during encryption
encryptStringdoes not require decryption abilities; you can drop thegetSessionSigscall to save one SIWE round-trip.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
frontend/package.json(1 hunks)frontend/src/components/CreateInvoice.jsx(6 hunks)frontend/src/contractsABI/ChainvoiceABI.js(14 hunks)frontend/src/page/ReceivedInvoice.jsx(8 hunks)frontend/src/page/SentInvoice.jsx(6 hunks)frontend/vite.config.js(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- frontend/package.json
- frontend/vite.config.js
🧰 Additional context used
🪛 Biome (1.9.4)
frontend/src/page/ReceivedInvoice.jsx
[error] 529-529: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
🔇 Additional comments (3)
frontend/src/page/ReceivedInvoice.jsx (1)
59-66: MissingaddressinuseEffectdependency arrayIf the connected wallet address changes, invoices stay stale. Add
address(and maybefee) to the dependency list.-}, [walletClient]); +}, [walletClient, address]);frontend/src/page/SentInvoice.jsx (1)
57-60: Refresh when wallet address changesAdd
addressto theuseEffectdependency array so sent-invoice data stays in sync with the active account.frontend/src/contractsABI/ChainvoiceABI.js (1)
328-339: Minor naming mismatchFrontend calls
contract.fee()but ABI exposessetFeeAmount. Ensure constant getter is still namedfee(it is). No action needed.
| Fee for invoice pay : {parseFloat( | ||
| ethers.formatUnits(fee) | ||
| )}{" "} | ||
| ETH | ||
| </p> | ||
| <p className="text-right font-semibold"> | ||
| {" "} | ||
| Amount: {drawerState.selectedInvoice.amountDue}{" "} | ||
| {/* {ethers.formatUnits(drawerState.selectedInvoice.amountDue)}{" "} */} | ||
| ETH | ||
| </p> | ||
| <p className="text-right font-semibold"> | ||
| Total Amount:{" "} | ||
| {parseFloat(drawerState.selectedInvoice.amountDue) + | ||
| parseFloat(ethers.formatUnits(fee))}{" "} | ||
| ETH | ||
| </p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid parseFloat for ETH arithmetic
Floating-point math on token amounts can introduce rounding errors. Keep values in Wei (BigInt) and format only for display.
const totalWei = BigInt(invoice.amountDueWei) + fee; // all BigInt
const totalEth = ethers.formatUnits(totalWei);🤖 Prompt for AI Agents
In frontend/src/page/ReceivedInvoice.jsx around lines 550 to 566, the code uses
parseFloat on ETH amounts for arithmetic, which can cause rounding errors. To
fix this, keep all token amounts in Wei as BigInt for calculations, add them
directly as BigInt values, and only convert to ETH string format using
ethers.formatUnits when displaying the result.
| const ciphertext = atob(encryptedStringBase64); | ||
|
|
||
| const accessControlConditions = [ | ||
| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decryption likely fails – drop the atob call
decryptToString expects the same base-64 string produced by encryptString. Converting with atob() mutates the data and causes “could not decrypt” errors.
-const ciphertext = atob(encryptedStringBase64);
+const ciphertext = encryptedStringBase64; // already base-64📝 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.
| const ciphertext = atob(encryptedStringBase64); | |
| const accessControlConditions = [ | |
| { | |
| // Before decrypting, use the original Base64 string | |
| - const ciphertext = atob(encryptedStringBase64); | |
| + const ciphertext = encryptedStringBase64; // already base-64 | |
| const accessControlConditions = [ | |
| { | |
| // … |
🤖 Prompt for AI Agents
In frontend/src/page/ReceivedInvoice.jsx around lines 105 to 108, the code
incorrectly uses atob() to decode the base64 encrypted string before passing it
to decryptToString, which expects the original base64 string. Remove the atob()
call and pass the encrypted base64 string directly to decryptToString to fix the
decryption errors.
| {parseFloat(drawerState.selectedInvoice.amountDue) + | ||
| parseFloat(ethers.formatUnits(fee))}{" "} | ||
| ETH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Do ETH maths in Wei, not parseFloat
Convert both amountDue and fee to Wei, add, then format for display to prevent rounding drift.
🤖 Prompt for AI Agents
In frontend/src/page/SentInvoice.jsx around lines 511 to 513, the addition of
amountDue and fee is done using parseFloat on ETH values, which can cause
rounding errors. Convert both amountDue and fee to Wei units first, perform the
addition in Wei as integers, then convert the result back to ETH for display
using ethers utility functions. This ensures precise arithmetic without floating
point drift.
| const ciphertext = atob(encryptedStringBase64); | ||
| const accessControlConditions = [ | ||
| { | ||
| contractAddress: "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the original base-64 ciphertext
Remove atob() to prevent decryption failures (same rationale as in ReceivedInvoice).
-const ciphertext = atob(encryptedStringBase64);
+const ciphertext = encryptedStringBase64;📝 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.
| const ciphertext = atob(encryptedStringBase64); | |
| const accessControlConditions = [ | |
| { | |
| contractAddress: "", | |
| const ciphertext = encryptedStringBase64; | |
| const accessControlConditions = [ | |
| { | |
| contractAddress: "", |
🤖 Prompt for AI Agents
In frontend/src/page/SentInvoice.jsx around lines 103 to 106, the code uses
atob() to decode the base64 encrypted string before decryption, which causes
decryption failures. Remove the atob() call and use the original base64
ciphertext string directly to fix the issue, consistent with the approach in
ReceivedInvoice.
| contractAddress: "", | ||
| standardContractType: "", | ||
| chain: "ethereum", | ||
| method: "", | ||
| parameters: [":userAddress"], | ||
| returnValueTest: { | ||
| comparator: "=", | ||
| value: data.clientAddress.toLowerCase(), | ||
| }, | ||
| }, | ||
| ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate recipient address before encrypting
A malformed data.clientAddress will pass straight to the contract and later revert. Add a checksum test:
if (!ethers.isAddress(data.clientAddress)) {
alert("Invalid client address");
return;
}🤖 Prompt for AI Agents
In frontend/src/components/CreateInvoice.jsx around lines 166 to 176, the code
uses data.clientAddress without validating it, which can cause contract call
failures if the address is malformed. Add a validation step before using
data.clientAddress by checking if it is a valid Ethereum address using
ethers.isAddress. If the address is invalid, show an alert with "Invalid client
address" and return early to prevent further processing.
| const invoiceString = JSON.stringify(invoicePayload); | ||
|
|
||
| // 2. Setup Lit | ||
| const litNodeClient = new LitNodeClient({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we setting up the lit client on every function call, instead of once, just when the component renders?
There was a problem hiding this 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 (2)
114-114: Decryption likely fails – drop theatobcall
decryptToStringexpects the same base-64 string produced byencryptString. Converting withatob()mutates the data and causes "could not decrypt" errors.-const ciphertext = atob(encryptedStringBase64); +const ciphertext = encryptedStringBase64; // already base-64
557-573: AvoidparseFloatfor ETH arithmeticFloating-point math on token amounts can introduce rounding errors. Keep values in Wei (BigInt) and format only for display.
const totalWei = BigInt(invoice.amountDueWei) + fee; // all BigInt const totalEth = ethers.formatUnits(totalWei);frontend/src/components/CreateInvoice.jsx (2)
51-62: Floating-point totals will bite you
totalAmountDueis built withparseFloat, which can mis-round (e.g., 0.3 + 0.6). Preferethers.parseUnitsper line item or at least useBigInt.
183-193: Validate recipient address before encryptingA malformed
data.clientAddresswill pass straight to the contract and later revert. Add a checksum test:if (!ethers.isAddress(data.clientAddress)) { alert("Invalid client address"); return; }
🧹 Nitpick comments (1)
frontend/src/components/CreateInvoice.jsx (1)
515-521: Consider precision for amount calculation displayWhile the calculation logic is correct, consider using
Number.parseFloat().toFixed(2)or similar for consistent decimal display in the amount field.value={ - (parseFloat(itemData[index].qty) || 0) * - (parseFloat(itemData[index].unitPrice) || 0) - - (parseFloat(itemData[index].discount) || 0) + - (parseFloat(itemData[index].tax) || 0) + ((parseFloat(itemData[index].qty) || 0) * + (parseFloat(itemData[index].unitPrice) || 0) - + (parseFloat(itemData[index].discount) || 0) + + (parseFloat(itemData[index].tax) || 0)).toFixed(2) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
frontend/src/components/CreateInvoice.jsx(6 hunks)frontend/src/page/ReceivedInvoice.jsx(8 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
🪛 Biome (1.9.4)
frontend/src/page/ReceivedInvoice.jsx
[error] 536-536: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
🔇 Additional comments (5)
frontend/src/page/ReceivedInvoice.jsx (2)
59-74: LGTM: Proper Lit client initializationThe Lit client is correctly initialized once on component mount and stored in a ref, avoiding unnecessary re-initializations on every function call.
76-200: Well-structured decryption flow with proper error handlingThe invoice fetching logic correctly waits for both wallet client and Lit readiness, implements proper access control conditions, and includes comprehensive error handling.
frontend/src/components/CreateInvoice.jsx (3)
64-77: Excellent: Lit client initialized once on mountThis addresses the previous feedback about setting up the Lit client on every function call. The client is now properly initialized once and reused.
79-118: Well-implemented dynamic item managementThe item handling logic correctly calculates amounts dynamically and maintains proper state updates. The real-time calculation provides good UX.
134-257: Robust encryption implementation with comprehensive flowThe invoice encryption process is well-structured:
- Proper payload construction
- Correct access control conditions (sender OR receiver)
- Session signature generation
- Error handling for encryption/transaction failures
The integration with the updated contract ABI is seamless.
There was a problem hiding this 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 (1)
README.md (1)
73-78: Add language identifier to fenced code blockMarkdown-lint (MD040) still flags this block. Prefix the opening fence with
bashfor syntax highlighting.-``` +```bash forge create contracts/src/Chainvoice.sol:Chainvoice \ --rpc-url $ETC_RPC_URL \ --private-key $PRIVATE_KEY \ --broadcast -``` +```
🧹 Nitpick comments (1)
README.md (1)
59-63: Fix typo and punctuation for claritySmall language issues hinder readability.
- - Create a .env in your project root i.e. `contracts/` - - Copy all the varible from `contracts/.env.example` to newly created `.env` + - Create a `.env` in your project root, i.e., `contracts/` + - Copy all the variables from `contracts/.env.example` to the newly created `.env`
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
README.md(1 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md
[typographical] ~59-~59: Consider putting a comma before the abbreviation “i.e.”.
Context: ...ts - Create a .env in your project root i.e. contracts/ - Copy all the varible...
(IE_COMMA)
[uncategorized] ~79-~79: Possible missing comma found.
Context: ...key $PRIVATE_KEY \ --broadcast ``` 5. Finally add Contract Address to Frontend .env...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~90-~90: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...Restart your frontend development server so the new environment variables are loade...
(COMMA_COMPOUND_SENTENCE_2)
🪛 markdownlint-cli2 (0.17.2)
README.md
73-73: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
There was a problem hiding this 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 (4)
frontend/src/page/ReceivedInvoice.jsx (3)
118-121: Decryption likely fails – drop theatobcall
decryptToStringexpects the same base-64 string produced byencryptString. Converting withatob()mutates the data and causes "could not decrypt" errors.-const ciphertext = atob(encryptedStringBase64); +const ciphertext = encryptedStringBase64; // already base-64
539-556: Add missing key property for React list itemsThe map iteration is missing a key property, which can cause React rendering issues when the order of items changes.
-{drawerState.selectedInvoice?.items?.map((item, index) => ( - <tbody> +{drawerState.selectedInvoice?.items?.map((item, index) => ( + <tbody key={index}>
561-577: AvoidparseFloatfor ETH arithmeticFloating-point math on token amounts can introduce rounding errors. Keep values in Wei (BigInt) and format only for display.
const totalWei = BigInt(invoice.amountDueWei) + fee; // all BigInt const totalEth = ethers.formatUnits(totalWei);frontend/src/components/CreateInvoice.jsx (1)
186-196: Validate recipient address before encryptingA malformed
data.clientAddresswill pass straight to the contract and later revert. Add a checksum test:if (!ethers.isAddress(data.clientAddress)) { alert("Invalid client address"); return; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
contracts/src/Chainvoice.sol(1 hunks)frontend/src/components/CreateInvoice.jsx(6 hunks)frontend/src/contractsABI/ChainvoiceABI.js(1 hunks)frontend/src/page/ReceivedInvoice.jsx(8 hunks)frontend/src/page/SentInvoice.jsx(6 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- frontend/src/page/SentInvoice.jsx
- contracts/src/Chainvoice.sol
🧰 Additional context used
🪛 Biome (1.9.4)
frontend/src/page/ReceivedInvoice.jsx
[error] 540-540: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
🔇 Additional comments (5)
frontend/src/page/ReceivedInvoice.jsx (2)
56-78: LGTM! Lit client initialization properly moved to mount.The Lit client is now correctly initialized once on component mount rather than on every function call, addressing the previous feedback about inefficient initialization.
219-225: LGTM! Payment calculation uses proper BigInt arithmetic.The payment function now correctly converts amounts to Wei and performs BigInt addition, preventing precision errors in financial calculations.
frontend/src/components/CreateInvoice.jsx (2)
52-66: LGTM! Total calculation uses precise BigInt arithmetic.The total amount calculation now uses
parseUnitsand BigInt operations, preventing floating-point precision errors in financial calculations.
68-81: LGTM! Lit client initialization properly moved to mount.The Lit client is now correctly initialized once on component mount, addressing the previous feedback about inefficient initialization patterns.
frontend/src/contractsABI/ChainvoiceABI.js (1)
1-454: LGTM! ABI correctly reflects the updated contract interface.The ABI has been properly updated to support the new encrypted invoice approach, with simplified function signatures and appropriate event indexing. The changes are consistent with the contract's shift from storing detailed invoice data to encrypted payloads.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (2)
frontend/src/page/ReceivedInvoice.jsx (2)
118-121: Still usingatob()- this will cause decryption failuresThis is the same issue flagged in previous reviews. The
decryptToStringfunction expects the original base64 string, butatob()decodes it into binary data, causing decryption to fail.-const ciphertext = atob(encryptedStringBase64); +const ciphertext = encryptedStringBase64;
561-577: Still usingparseFloatfor ETH arithmetic - precision issues remainThis is the same issue flagged in previous reviews. Using
parseFloaton ETH amounts can introduce rounding errors in financial calculations.-Fee for invoice pay : {parseFloat( - ethers.formatUnits(fee) -)}{" "} +Fee for invoice pay : {ethers.formatUnits(fee)}{" "} ETH-Total Amount:{" "} -{parseFloat(drawerState.selectedInvoice.amountDue) + - parseFloat(ethers.formatUnits(fee))}{" "} -ETH +Total Amount:{" "} +{( + BigInt(ethers.parseUnits(drawerState.selectedInvoice.amountDue.toString(), 18)) + + BigInt(fee) +).toString() / 1e18}{" "} +ETH
🧹 Nitpick comments (1)
frontend/src/page/ReceivedInvoice.jsx (1)
194-200: Improve error handling granularityThe current error handling catches all errors broadly. Consider handling specific error types differently (network errors, decryption failures, contract errors).
} catch (error) { - console.error("Decryption error:", error); - alert("Failed to fetch or decrypt received invoices."); + console.error("Error fetching invoices:", error); + if (error.message?.includes('decrypt')) { + alert("Failed to decrypt invoice data. You may not have permission to view these invoices."); + } else if (error.message?.includes('network')) { + alert("Network error. Please check your connection and try again."); + } else { + alert("Failed to fetch received invoices. Please try again."); + } } finally { setLoading(false); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
frontend/src/page/ReceivedInvoice.jsx(8 hunks)
🔇 Additional comments (2)
frontend/src/page/ReceivedInvoice.jsx (2)
216-225: Payment function correctly uses Wei calculationsGood improvement! The payment function now properly converts amounts to Wei before arithmetic operations, avoiding floating-point precision issues.
539-556: React key property correctly addedGood fix! The
tbodyelements now have unique keys, resolving the React rendering issue flagged in previous reviews.
| const value = invoice.user[column.id] || ""; | ||
| if (column.id === "to") { | ||
| return ( | ||
| <TableCell key={column.id} align={column.align} sx={{ color: 'white', borderColor: '#25272b' }}> | ||
| {invoice.to.substring(0, 10)}...{invoice.to.substring(invoice.to.length - 10)} | ||
| <TableCell | ||
| key={column.id} | ||
| align={column.align} | ||
| sx={{ color: "white", borderColor: "#25272b" }} | ||
| > | ||
| {invoice.user.address | ||
| ? `${invoice.user.address.substring( | ||
| 0, | ||
| 10 | ||
| )}...${invoice.user.address.substring( | ||
| invoice.user.address.length - 10 | ||
| )}` | ||
| : "N/A"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Potential null reference on user data
The code assumes invoice.user exists but doesn't handle cases where the decrypted data might be malformed or incomplete.
-const value = invoice.user[column.id] || "";
+const value = invoice.user?.[column.id] || "";
if (column.id === "to") {
return (
<TableCell
key={column.id}
align={column.align}
sx={{ color: "white", borderColor: "#25272b" }}
>
- {invoice.user.address
- ? `${invoice.user.address.substring(
+ {invoice.user?.address
+ ? `${invoice.user.address.substring(
0,
10
)}...${invoice.user.address.substring(
invoice.user.address.length - 10
)}`
: "N/A"}
</TableCell>
);
}📝 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.
| const value = invoice.user[column.id] || ""; | |
| if (column.id === "to") { | |
| return ( | |
| <TableCell key={column.id} align={column.align} sx={{ color: 'white', borderColor: '#25272b' }}> | |
| {invoice.to.substring(0, 10)}...{invoice.to.substring(invoice.to.length - 10)} | |
| <TableCell | |
| key={column.id} | |
| align={column.align} | |
| sx={{ color: "white", borderColor: "#25272b" }} | |
| > | |
| {invoice.user.address | |
| ? `${invoice.user.address.substring( | |
| 0, | |
| 10 | |
| )}...${invoice.user.address.substring( | |
| invoice.user.address.length - 10 | |
| )}` | |
| : "N/A"} | |
| const value = invoice.user?.[column.id] || ""; | |
| if (column.id === "to") { | |
| return ( | |
| <TableCell | |
| key={column.id} | |
| align={column.align} | |
| sx={{ color: "white", borderColor: "#25272b" }} | |
| > | |
| {invoice.user?.address | |
| ? `${invoice.user.address.substring( | |
| 0, | |
| 10 | |
| )}...${invoice.user.address.substring( | |
| invoice.user.address.length - 10 | |
| )}` | |
| : "N/A"} |
🤖 Prompt for AI Agents
In frontend/src/page/ReceivedInvoice.jsx around lines 327 to 342, the code
assumes invoice.user is always defined, which can cause null reference errors if
the user data is missing or malformed. Add a check to ensure invoice.user exists
before accessing its properties, and provide a fallback UI or default value when
invoice.user is undefined or null to prevent runtime errors.
There was a problem hiding this 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 (1)
README.md (1)
73-78: Add language spec to fenced code blockThe Forge command block still violates MD040 (
fenced-code-language) and renders without syntax highlighting.
Usebashimmediately after the opening back-ticks.-``` +```bash forge create contracts/src/Chainvoice.sol:Chainvoice \ --rpc-url $ETC_RPC_URL \ --private-key $PRIVATE_KEY \ --broadcast -``` +```
🧹 Nitpick comments (2)
README.md (2)
59-63: Fix typos and improve bullet wordingMinor language issues reduce professionalism and may confuse readers.
- - Create a .env in your project root i.e. `contracts/` - - Copy all the varible from `contracts/.env.example` to newly created `.env` + - Create a `.env` file in your project root, i.e., `contracts/` + - Copy all the variables from `contracts/.env.example` to the newly created `.env`
88-90: Tweak sentence for readabilityConsider adding “that” for smoother flow.
- - Restart your frontend development server so the new environment variables are loaded. + - Restart your frontend development server so that the new environment variables are loaded.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
README.md(1 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md
[typographical] ~59-~59: Consider putting a comma before the abbreviation “i.e.”.
Context: ...ts - Create a .env in your project root i.e. contracts/ - Copy all the varible...
(IE_COMMA)
[uncategorized] ~60-~60: You might be missing the article “the” here.
Context: ...arible from contracts/.env.example to newly created .env `cp .env.ex...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
[uncategorized] ~79-~79: Possible missing comma found.
Context: ...key $PRIVATE_KEY \ --broadcast ``` 5. Finally add Contract Address to Frontend .env...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~79-~79: You might be missing the article “the” here.
Context: ..._KEY \ --broadcast ``` 5. Finally add Contract Address to Frontend .env - Creat...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
[uncategorized] ~90-~90: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...Restart your frontend development server so the new environment variables are loade...
(COMMA_COMPOUND_SENTENCE_2)
🪛 markdownlint-cli2 (0.17.2)
README.md
73-73: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
There was a problem hiding this 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 (2)
frontend/src/components/CreateInvoice.jsx (2)
190-200: Client address validation still missingThe
data.clientAddressis used in access control conditions without validation, which was flagged in a previous review. A malformed address will cause the encryption to fail or behave unexpectedly.Add address validation before using it:
+if (!ethers.isAddress(data.clientAddress)) { + alert("Invalid client address"); + return; +} + const accessControlConditions = [ { contractAddress: "",
524-529: Individual item display calculation still uses floating-point arithmeticThe display value calculation for individual items uses
parseFloat, which creates inconsistency with the precise BigInt arithmetic used elsewhere. This was flagged in a previous review.Use the computed
amountfrom the item data instead:-value={ - (parseFloat(itemData[index].qty) || 0) * - (parseFloat(itemData[index].unitPrice) || 0) - - (parseFloat(itemData[index].discount) || 0) + - (parseFloat(itemData[index].tax) || 0) -} +value={itemData[index].amount}
🧹 Nitpick comments (1)
frontend/src/components/CreateInvoice.jsx (1)
203-255: Verify encryption error handlingThe encryption process should handle specific error cases to provide better user feedback. Consider distinguishing between Lit Protocol connection errors, encryption failures, and contract transaction failures.
} catch (err) { + if (err.message.includes('Lit')) { + console.error("Lit Protocol error:", err); + alert("Failed to encrypt invoice data. Please try again."); + } else if (err.message.includes('transaction')) { + console.error("Transaction error:", err); + alert("Failed to submit invoice to blockchain. Please try again."); + } else { - console.error("Encryption or transaction failed:", err); - alert("Failed to create invoice."); + console.error("Unexpected error:", err); + alert("An unexpected error occurred. Please try again."); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
frontend/src/components/CreateInvoice.jsx(6 hunks)frontend/src/page/ReceivedInvoice.jsx(8 hunks)frontend/src/page/SentInvoice.jsx(6 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- frontend/src/page/ReceivedInvoice.jsx
- frontend/src/page/SentInvoice.jsx
🔇 Additional comments (4)
frontend/src/components/CreateInvoice.jsx (4)
68-81: Good improvement: Lit client initialization moved to useEffectThe Lit client is now properly initialized once in useEffect instead of on every function call, addressing the previous feedback about efficiency.
96-105: Excellent: Precise BigInt arithmetic for individual item calculationsThe individual item amount calculations now use
parseUnitsand BigInt arithmetic, which resolves the floating-point precision issues flagged in previous reviews.
51-66: Precise total calculation implementation looks solidThe total amount calculation properly uses BigInt arithmetic throughout, preventing floating-point precision errors. The logic correctly handles the multiplication and division scaling.
360-365: User address field correctly set to read-onlyThe user address input is properly set to read-only and pre-filled with the connected wallet address, preventing accidental modifications.
Summary by CodeRabbit
New Features
Chores
Refactor
Bug Fixes
Documentation