Skip to content
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

fix: (ibc)send big numbers #81

Merged
merged 4 commits into from
Nov 27, 2024
Merged

fix: (ibc)send big numbers #81

merged 4 commits into from
Nov 27, 2024

Conversation

fmorency
Copy link
Contributor

@fmorency fmorency commented Nov 26, 2024

2024-11-26_13-52

Fixes #80

Summary by CodeRabbit

  • New Features

    • Enhanced SendForm and IbcSendForm components for improved amount validation and fee management.
    • Introduced a new utility function for precise number parsing and conversion.
  • Bug Fixes

    • Improved error handling for balance checks and fee warnings, ensuring better user experience.
  • Refactor

    • Streamlined utility functions, focusing on number parsing and reducing complexity.

@fmorency fmorency requested a review from chalabi2 November 26, 2024 18:53
@fmorency fmorency self-assigned this Nov 26, 2024
Copy link
Contributor

coderabbitai bot commented Nov 26, 2024

Walkthrough

The changes in this pull request primarily focus on the SendForm and IbcSendForm components, along with modifications to the utility functions in utils/maths.ts. A new utility function, parseNumberToBigInt, has been introduced to enhance the calculation of amounts in base units. The validation schema for both forms has been improved, particularly for the amount field, ensuring that balance checks are more robust. Additionally, several unused utility functions have been removed to streamline the codebase, while error handling has been enhanced to provide better feedback during calculations.

Changes

File Change Summary
components/bank/forms/sendForm.tsx - Updated handleSend to use parseNumberToBigInt for amount calculation.
- Enhanced validation schema for amount field and fee warning logic.
components/bank/forms/ibcSendForm.tsx - Updated handleSend to use parseNumberToBigInt for amount calculation.
- Adjusted filtering logic for balances.
utils/maths.ts - Removed functions: toNumber, formatNumber, truncateToTwoDecimals, sum, abbreviateNumber.
- Added parseNumberToBigInt for precise number conversion.
- Improved error handling in shiftDigits.

Assessment against linked issues

Objective Addressed Explanation
Improve handling of large token amounts (#80)

Possibly related PRs

  • fix: mint/burn form data display #78: The MintForm component changes involve the removal of the admin prop and simplification of the displayed information, which may relate to the overall handling of numeric values and user input, similar to the changes made in the SendForm component regarding the amountInBaseUnits calculation.

🐰 In fields of green where numbers play,
A new way to send tokens came today.
With parsing so neat and balances checked,
No more console errors to reflect!
Hop, skip, and jump, let the tokens flow,
A smoother transaction, oh what a show! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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
Contributor

@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

🧹 Outside diff range and nitpick comments (3)
components/bank/forms/sendForm.tsx (1)

Line range hint 99-114: Consider enhancing error handling for better user feedback

While the fix addresses the core issue, the error handling could be more user-friendly. Currently, errors are only logged to console (line 113).

Consider adding user-friendly error messages for common failure cases:

 } catch (error) {
   console.error('Error during sending:', error);
+  // Extract error message
+  const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
+  // Set error state for UI display
+  setError(errorMessage);
 } finally {
   setIsSending(false);
 }
utils/maths.ts (2)

41-42: Consider potential precision loss with .toNumber()

Using .toNumber() can introduce precision loss for very large numbers, which might be critical depending on the application's requirements. To maintain precision, consider returning a BigNumber or converting to a string representation instead.

You might modify the function as follows:

-export const toNumber = (val: string, decimals: number = 6) => {
-  return new BigNumber(val).decimalPlaces(decimals).toNumber();
+export const toNumberString = (val: string, decimals: number = 6) => {
+  return new BigNumber(val).decimalPlaces(decimals).toString();
 };

34-38: Add unit tests for parseNumberToBigInt

Given the importance of accurately parsing numbers to BigInt, it's crucial to include unit tests that cover a range of inputs, including large numbers, decimals, and invalid strings, to ensure the function behaves as expected.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 263a5e1 and 76cf30a.

📒 Files selected for processing (2)
  • components/bank/forms/sendForm.tsx (2 hunks)
  • utils/maths.ts (1 hunks)
🔇 Additional comments (2)
components/bank/forms/sendForm.tsx (2)

6-6: LGTM: Import changes align with large number handling requirements

The addition of parseNumberToBigInt import is appropriate for handling large token amounts.


99-99: Approve core fix with verification needed

The switch to parseNumberToBigInt is a solid fix for handling large token amounts, eliminating precision loss and floating-point errors that were likely causing the silent failures.

Let's verify the fix handles extreme cases properly:

✅ Verification successful

Implementation verified with proper safeguards in place

The parseNumberToBigInt implementation in utils/maths.ts is well-designed and safely handles token amounts:

  • Uses BigNumber for initial parsing to prevent floating-point errors
  • Properly scales the amount by the token's decimal places
  • Safely converts to BigInt for blockchain compatibility

The code shows consistent usage across the codebase:

  • Used in send forms for token transfers
  • Applied in mint/burn operations
  • Handles token decimals via exponent parameter

The implementation includes proper validation through:

  • Form validation before the conversion (from the Formik context)
  • Adjustments for maximum amounts in send forms
  • Safe conversion through BigNumber before BigInt
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for any maximum amount limitations or validations in the codebase
# that might affect large token transfers

# Look for amount validations or limits
rg -i "amount.*max|max.*amount" --type ts --type tsx

# Look for parseNumberToBigInt implementation and tests
ast-grep --pattern 'function parseNumberToBigInt($_) {
  $$$
}'

# Look for related test cases
rg -i "test.*large.*amount|test.*big.*number" --type test

Length of output: 237


Script:

#!/bin/bash
# Let's try with correct file extensions and more targeted searches

# Look for amount validations or limits
rg -i "amount.*max|max.*amount" -t ts -t tsx -t js -t jsx

# Look for parseNumberToBigInt implementation
rg "parseNumberToBigInt" -A 5 -t ts -t tsx -t js -t jsx

# Look for test files containing amount or number tests
rg -i "test.*amount|test.*number" -t ts -t tsx -t js -t jsx --glob "*test*" --glob "*spec*"

# Look for BigInt related validations
rg -i "bigint.*valid|valid.*amount" -t ts -t tsx -t js -t jsx

Length of output: 385


Script:

#!/bin/bash
# Let's try without explicit file type flags and use simpler patterns

# Look for parseNumberToBigInt implementation
rg "parseNumberToBigInt" -A 5

# Look for amount validations
rg "validateAmount|maxAmount|MAX_AMOUNT"

# Look for test cases in files with test/spec naming
fd -g "*test*" -g "*spec*" -x rg "amount" "{}"

# Look for BigInt usage context
rg "BigInt" -A 2 -B 2

Length of output: 16564

utils/maths.ts Outdated
Comment on lines 34 to 38
export const parseNumberToBigInt = (v: string, maxDigits: number = 6) => {
const amount = BigNumber(v);
const precision = BigNumber(`1e${maxDigits}`);
const b = amount.times(precision).toFixed();
return BigInt(b);
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 26, 2024

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refine precision calculation in parseNumberToBigInt

Using BigNumber(\1e${maxDigits}`)may lead to inaccuracies with large values ofmaxDigits. It's recommended to use new BigNumber(10).pow(maxDigits)` for precise and reliable calculations.

Apply the following diff to improve precision calculation:

 export const parseNumberToBigInt = (v: string, maxDigits: number = 6) => {
-  const amount = BigNumber(v);
-  const precision = BigNumber(`1e${maxDigits}`);
+  const amount = new BigNumber(v);
+  const precision = new BigNumber(10).pow(maxDigits);
   const b = amount.times(precision).toFixed();
   return BigInt(b);
 };
📝 Committable suggestion

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

Suggested change
export const parseNumberToBigInt = (v: string, maxDigits: number = 6) => {
const amount = BigNumber(v);
const precision = BigNumber(`1e${maxDigits}`);
const b = amount.times(precision).toFixed();
return BigInt(b);
export const parseNumberToBigInt = (v: string, maxDigits: number = 6) => {
const amount = new BigNumber(v);
const precision = new BigNumber(10).pow(maxDigits);
const b = amount.times(precision).toFixed();
return BigInt(b);

⚠️ Potential issue

Add input validation to handle invalid inputs in parseNumberToBigInt

The function currently lacks validation for the input v. If v is not a valid number, new BigNumber(v) may result in NaN, leading to unexpected behavior when converting to BigInt. Adding input validation ensures robustness and prevents potential errors.

Consider enhancing the function with input validation:

 export const parseNumberToBigInt = (v: string, maxDigits: number = 6) => {
+  const amount = new BigNumber(v);
+  if (!amount.isFinite()) {
+    console.error(`Invalid input passed to parseNumberToBigInt: ${v}`);
+    return BigInt(0);
+  }
-  const amount = BigNumber(v);
   const precision = new BigNumber(10).pow(maxDigits);
   const b = amount.times(precision).toFixed();
   return BigInt(b);
 };

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed in 6f7b535

Copy link
Contributor

Choose a reason for hiding this comment

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

@fmorency Thank you for implementing the suggested changes! The improvements to parseNumberToBigInt enhance its precision and robustness.


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

@fmorency fmorency changed the title fix: send big numbers fix: (ibc)send big numbers Nov 26, 2024
Copy link
Contributor

@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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 76cf30a and f8bc045.

📒 Files selected for processing (1)
  • components/bank/forms/ibcSendForm.tsx (2 hunks)
🔇 Additional comments (2)
components/bank/forms/ibcSendForm.tsx (2)

5-5: LGTM: Import of new BigInt utility

The addition of parseNumberToBigInt import aligns with the PR objective of fixing large token amount handling.


Line range hint 82-98: Verify error message visibility for large amounts

While the validation schema includes balance checks, we should ensure that users receive clear error messages when attempting to send large amounts, as the original issue #80 mentioned a lack of UI feedback.

Let's check the error handling implementation:

✅ Verification successful

Based on the results, I can now generate the final response:

Error messages are properly implemented for large amounts

The validation schema's error messages are correctly displayed in the UI:

  • The form shows validation errors in red text (text-red-500) when errors.amount exists
  • Error messages are displayed conditionally based on form state (touched.amount && errors.amount)
  • There's also a fee warning system that shows yellow warnings when applicable
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify error message handling in the form components

# Check for error message rendering logic
rg -A 2 "errors\.amount"

# Look for error display components
rg -A 2 "text-red-500"

# Check for any console.error usage that might hide errors from UI
rg "console\.error"

Length of output: 12125

const amountInBaseUnits = Math.floor(
parseFloat(values.amount) * Math.pow(10, exponent)
).toString();
const amountInBaseUnits = parseNumberToBigInt(values.amount, exponent).toString();
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 26, 2024

Choose a reason for hiding this comment

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

💡 Codebase verification

Potential precision issues found in factory and groups components

Several components still use floating-point calculations for token amounts which could lead to precision issues:

  • components/factory/forms/BurnForm.tsx: Uses parseFloat(amount) * Math.pow(10, exponent) for amount calculations
  • components/factory/forms/MintForm.tsx: Similar floating-point math for amount conversion
  • components/factory/modals/multiMfxMintModal.tsx and multiMfxBurnModal.tsx: Both use floating-point calculations
  • components/groups/forms/proposals/ProposalMessages.tsx: Uses Number() and floating-point division

These components should be updated to use parseNumberToBigInt from utils/maths.ts which properly handles large numbers using BigNumber.js library, similar to the fix implemented in ibcSendForm.tsx.

🔗 Analysis chain

LGTM: Improved precision for large token amounts

The switch to parseNumberToBigInt eliminates floating-point precision issues that were preventing large token transfers. This directly addresses the issue described in #80.

Let's verify the behavior with large numbers:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if parseNumberToBigInt is used consistently across the codebase
# and verify there are no remaining floating-point calculations for token amounts

# Search for any remaining floating-point calculations of token amounts
rg -l "Math\.floor.*amount|parseFloat.*amount|Number\(.*amount\)"

# Check for consistent usage of parseNumberToBigInt
rg "parseNumberToBigInt"

Length of output: 941


Script:

#!/bin/bash
# Let's examine the actual implementations to understand if there are any risky float calculations

# Check the implementation in files that still use float operations
rg -A 5 "Math\.floor.*amount|parseFloat.*amount|Number\(.*amount\)" components/groups/forms/proposals/ProposalMessages.tsx components/factory/modals/multiMfxMintModal.tsx components/factory/modals/multiMfxBurnModal.tsx components/factory/forms/MintForm.tsx components/factory/forms/BurnForm.tsx

# Also check the parseNumberToBigInt implementation
cat utils/maths.ts

Length of output: 6739

Copy link
Contributor Author

Choose a reason for hiding this comment

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

#83 and #82 take care of BurnForm, MintForm and multiMfx*. ProposalMessage will get nuked in a future PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

@fmorency, understood. Thanks for the update. Would you like me to open a new GitHub issue to track the removal of ProposalMessages.tsx?

Copy link
Contributor

@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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between f8bc045 and 6f7b535.

📒 Files selected for processing (1)
  • utils/maths.ts (1 hunks)
🔇 Additional comments (1)
utils/maths.ts (1)

34-42: LGTM! Implementation looks robust for handling large numbers.

The function properly handles precision and includes appropriate error handling. This implementation should effectively address the issue of sending large token amounts.

Let's verify the function handles extreme cases correctly:

✅ Verification successful

Implementation verified and used correctly in token transfer scenarios

The verification shows that:

  • The function is used correctly in token transfer forms (sendForm.tsx and ibcSendForm.tsx) with proper exponent handling
  • The implementation properly converts user input amounts to base units for blockchain transactions
  • Error handling is in place for invalid inputs
  • The function works alongside other numerical utilities (shiftDigits, toNumber) to provide a robust number handling system

The search results confirm that the implementation is solid and properly used in the critical token transfer paths, making it suitable for handling large token amounts as intended in the PR objectives.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for usage patterns to ensure the function is used correctly with large numbers

# Look for test cases or usage patterns
rg -A 3 "parseNumberToBigInt.*" --type typescript

# Look for potential error handling of the function's results
rg "BigInt.*" --type typescript

Length of output: 155


Script:

#!/bin/bash
# Search for usage patterns and test cases of parseNumberToBigInt
rg -A 3 "parseNumberToBigInt"

# Look for test files related to maths utilities
fd "maths.*test" --type f

# Look for BigInt usage patterns
rg "BigInt"

# Check the content of the maths utility file
cat utils/maths.ts

Length of output: 8680

Comment on lines +45 to +46
export const toNumber = (val: string, decimals: number = 6) => {
return new BigNumber(val).decimalPlaces(decimals).toNumber();
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Warning: Potential precision loss when handling large numbers

The toNumber function converts values to JavaScript's Number type, which has limitations for large values (maximum safe integer is 2^53 - 1). This could lead to precision loss or incorrect results when handling large token amounts.

Consider this safer implementation:

-export const toNumber = (val: string, decimals: number = 6) => {
-  return new BigNumber(val).decimalPlaces(decimals).toNumber();
+export const toNumber = (val: string, decimals: number = 6) => {
+  const num = new BigNumber(val);
+  if (!num.isFinite()) {
+    console.error(`Invalid input passed to toNumber: ${val}`);
+    return 0;
+  }
+  if (num.gt(Number.MAX_SAFE_INTEGER)) {
+    console.warn(`Number ${val} exceeds safe integer limits, precision may be lost`);
+  }
+  return num.decimalPlaces(decimals).toNumber();
+};
📝 Committable suggestion

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

Suggested change
export const toNumber = (val: string, decimals: number = 6) => {
return new BigNumber(val).decimalPlaces(decimals).toNumber();
export const toNumber = (val: string, decimals: number = 6) => {
const num = new BigNumber(val);
if (!num.isFinite()) {
console.error(`Invalid input passed to toNumber: ${val}`);
return 0;
}
if (num.gt(Number.MAX_SAFE_INTEGER)) {
console.warn(`Number ${val} exceeds safe integer limits, precision may be lost`);
}
return num.decimalPlaces(decimals).toNumber();
};

Copy link

codecov bot commented Nov 26, 2024

Codecov Report

Attention: Patch coverage is 28.57143% with 10 lines in your changes missing coverage. Please review.

Project coverage is 59.59%. Comparing base (5d19dc3) to head (b7bbb21).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
utils/maths.ts 20.00% 8 Missing ⚠️
components/bank/forms/ibcSendForm.tsx 50.00% 1 Missing ⚠️
components/bank/forms/sendForm.tsx 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #81      +/-   ##
==========================================
+ Coverage   59.42%   59.59%   +0.17%     
==========================================
  Files         146      146              
  Lines       14187    14140      -47     
==========================================
- Hits         8430     8427       -3     
+ Misses       5757     5713      -44     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@chalabi2 chalabi2 left a comment

Choose a reason for hiding this comment

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

lgtm! We should consider how we display massive numbers moving forward, as they could break the look of the UI

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.

Can't send huge amounts
2 participants