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(frontend): incorrect "value" type in InputCurrency #3592

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

DenysKarmazynDFINITY
Copy link
Contributor

Motivation

While working on the conversion flow, I noticed one suspicious thing: the value prop that is controlled by InputCurrency is actually a string and not a number as it is expected to be according to the types in our codebase. It means that we incorrectly assume across the whole send flow that amount is number | undefined when it's in reality string | undefined. The same applies to the convert flow: sourceAmount was never a number.

After reading the GIX Input docs, I found this paragraph:

If the inputType is set to icp, the value bind by the component is a number. On the contrary, if bind to currency, the value is a string. This to avoid issue with scientific notation enforced by JavaScript. It is then up to you to parse the currency according your need, for example to bigint or BigNumber.

Having said that, we have quite an error-prompt situation: I noticed this issue while debugging one of the conversion services - sendAmount === 0 was always giving me false after typing 0, even though TS-wise the statement looks correct. Since in the code all send components also expect it to be a number, this may lead to the same issue.

Solution 1 (implemented in this PR): as suggested by GIX, I added an internal inputValue to the InputCurrency component which has string | undefined type, and on nnsInput I convert it to number before notifying parent. Also, provided some tests to test this behaviour.

Solution 2: update amount type everywhere where it's used. Would require a lot of changes.

@DenysKarmazynDFINITY DenysKarmazynDFINITY requested a review from a team as a code owner November 15, 2024 18:22
@DenysKarmazynDFINITY
Copy link
Contributor Author

@peterpeterparker @AntonioVentilii please take a look at the PR's description and code.

Copy link
Collaborator

@AntonioVentilii AntonioVentilii left a comment

Choose a reason for hiding this comment

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

It looks good, but thinking out loud: have you thought of using a context instead of binding the value? No preference, I am just asking if there is any worth in it or not

import { assertNonNullish } from '@dfinity/utils';
import { fireEvent, render } from '@testing-library/svelte';

describe('ConvertAmountExchange', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think here is InputCurrency, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Totally right, but since we will most likely proceed with the Solution 2, this PR won't be merged.

// Convert inputValue to number before updating parent's value
value = nonNullish(inputValue) ? Number(inputValue) : undefined;

// Bubble nnsInput as consumers might require the event as well
Copy link
Collaborator

Choose a reason for hiding this comment

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

not really sure we need this comment: I think it is a common pattern in the code of Oisy

@peterpeterparker
Copy link
Member

Wow! Good catch, it's been there forever!

Actually, I rather like solution 2. Because properties can flow up and down, I feel like it's more maintanable if we can avoid having to manipulate it therefore, I gave it a quick try and, at least from a linter perspective, it doesn’t seem too bad to implement, as I managed to put it together quickly in #3609.

WDYT?

@DenysKarmazynDFINITY
Copy link
Contributor Author

@peterpeterparker yeah, solution 2 also work for me perfectly fine, thanks for preparing the PR! I

@peterpeterparker
Copy link
Member

solution 2 also work for me perfectly fine

Cool, then let's proceed with solution 2.

peterpeterparker added a commit that referenced this pull request Nov 16, 2024
# Motivation

"Solution 2" of #3592 - i.e. @DenysKarmazynDFINITY spotted a bug that
was there since ages. We interpreted the value of the `Input currency`
as `number | undefined` while actually the type is a `string | number |
undefined`.

# TODO

Create a type `type OptionCurrencyValue = string | number | undefined`
or something.

# Changes

- Property `value` in `InputCurrency` must be of type `string | number |
undefined` - i.e. `string` was missing
- Populate changes in consumers
- Add `Number()` cast to few utils when property is defined
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.

3 participants