Repository: trezor/trezor-suite
Pull request #17390: fix(suite): staking input validation
Author: login: martykan
Created: 2025-03-04T14:04:20Z | Merged: 2025-03-04T14:33:33Z

## Description

Fixed an issue where it was possible to stake SOL below the minimum threshold.
Fixed an issue where it was possible to unstake more than the current stake balance.

## Related Issue

Resolve https://github.com/trezor/trezor-suite/issues/17194 
Resolve https://github.com/trezor/trezor-suite/issues/17225

## Screenshots:
![image](https://github.com/user-attachments/assets/46af7a6d-ab2d-4da7-b926-ac4b36a435ac)
![image](https://github.com/user-attachments/assets/9df85c33-c3e6-46f3-b988-e9a82164d712)


Diff:
diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx
index 848c86f188d7..ce8acfbc9767 100644
--- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx
+++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx
@@ -17,6 +17,7 @@ import { validateStakingMax } from 'src/utils/suite/staking';
 import {
     validateCryptoLimits,
     validateDecimals,
+    validateFiatLimits,
     validateMin,
     validateReserveOrBalance,
 } from 'src/utils/suite/validation';
@@ -57,6 +58,13 @@ export const Inputs = () => {
         validate: {
             min: validateMin(translationString),
             decimals: validateDecimals(translationString, { decimals: 2 }),
+            limits: validateFiatLimits(translationString, {
+                amountLimits,
+                localCurrency,
+                formatter: CryptoAmountFormatter,
+                decimals: network.decimals,
+                rate: currentRate?.rate,
+            }),
         },
     };
 
diff --git a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Inputs.tsx b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Inputs.tsx
index 15b99b79226f..fe0660b97966 100644
--- a/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Inputs.tsx
+++ b/packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Inputs.tsx
@@ -2,11 +2,7 @@ import { useFormatters } from '@suite-common/formatters';
 import { formInputsMaxLength } from '@suite-common/validators';
 import { getNetworkDisplaySymbol } from '@suite-common/wallet-config';
 import { UnstakeFormState } from '@suite-common/wallet-core';
-import {
-    getInputState,
-    getNonComposeErrorMessage,
-    getStakingDataForNetwork,
-} from '@suite-common/wallet-utils';
+import { getInputState, getStakingDataForNetwork } from '@suite-common/wallet-utils';
 import { Column, FractionButtonProps, Text } from '@trezor/components';
 import { InputWithOptions } from '@trezor/product-components';
 import { spacings } from '@trezor/theme';
@@ -15,8 +11,13 @@ import { FiatValue, FormattedCryptoAmount, Translation } from 'src/components/su
 import { useSelector, useTranslation } from 'src/hooks/suite';
 import { useUnstakeEthFormContext } from 'src/hooks/wallet/useUnstakeEthForm';
 import { selectLanguage } from 'src/reducers/suite/suiteReducer';
-import { CRYPTO_INPUT, FIAT_INPUT, OUTPUT_AMOUNT } from 'src/types/wallet/stakeForms';
-import { validateCryptoLimits, validateDecimals, validateMin } from 'src/utils/suite/validation';
+import { FIAT_INPUT, OUTPUT_AMOUNT } from 'src/types/wallet/stakeForms';
+import {
+    validateCryptoLimits,
+    validateDecimals,
+    validateFiatLimits,
+    validateMin,
+} from 'src/utils/suite/validation';
 
 export const Inputs = () => {
     const { translationString } = useTranslation();
@@ -60,6 +61,13 @@ export const Inputs = () => {
         validate: {
             min: validateMin(translationString),
             decimals: validateDecimals(translationString, { decimals: 2 }),
+            limits: validateFiatLimits(translationString, {
+                amountLimits,
+                localCurrency,
+                formatter: CryptoAmountFormatter,
+                decimals: network.decimals,
+                rate: currentRate?.rate,
+            }),
         },
     };
 
@@ -88,7 +96,6 @@ export const Inputs = () => {
                     rules: cryptoInputRules,
                     maxLength: formInputsMaxLength.amount,
                     innerAddon: <Text variant="tertiary">{networkDisplaySymbol}</Text>,
-                    bottomText: getNonComposeErrorMessage(errors[CRYPTO_INPUT]),
                     inputState: getInputState(cryptoError || fiatError),
                     onChange: onCryptoAmountChange,
                 }}
@@ -104,7 +111,6 @@ export const Inputs = () => {
                               innerAddon: (
                                   <Text variant="tertiary">{localCurrency.toUpperCase()}</Text>
                               ),
-                              bottomText: getNonComposeErrorMessage(errors[FIAT_INPUT]),
                               inputState: getInputState(fiatError || cryptoError),
                               onChange: onFiatAmountChange,
                           }
diff --git a/packages/suite/src/hooks/wallet/useStakeEthForm.ts b/packages/suite/src/hooks/wallet/useStakeEthForm.ts
index dc7bc40ef52f..6559563efc74 100644
--- a/packages/suite/src/hooks/wallet/useStakeEthForm.ts
+++ b/packages/suite/src/hooks/wallet/useStakeEthForm.ts
@@ -30,7 +30,7 @@ import {
     getEthNetworkAddresses,
     getStakeFormsDefaultValues,
 } from 'src/utils/suite/ethereumStaking';
-import type { CryptoAmountLimitProps } from 'src/utils/suite/validation';
+import type { AmountLimitProps } from 'src/utils/suite/validation';
 
 import { useFees } from './form/useFees';
 import { useStakeCompose } from './form/useStakeCompose';
@@ -56,10 +56,12 @@ export const useStakeEthForm = ({ selectedAccount }: UseStakeFormsProps): StakeC
     const { MIN_AMOUNT_FOR_STAKING, MIN_FOR_WITHDRAWALS, MIN_BALANCE_FOR_STAKING } =
         getStakingLimitsByNetwork(account);
 
-    const amountLimits: CryptoAmountLimitProps = {
+    const amountLimits: AmountLimitProps = {
         currency: symbol,
         minCrypto: MIN_AMOUNT_FOR_STAKING.toString(),
         maxCrypto: account.formattedBalance,
+        minFiat: toFiatCurrency(MIN_AMOUNT_FOR_STAKING.toString(), currentRate?.rate) ?? undefined,
+        maxFiat: toFiatCurrency(account.formattedBalance, currentRate?.rate) ?? undefined,
     };
 
     const defaultValues = useMemo(() => {
diff --git a/packages/suite/src/hooks/wallet/useUnstakeEthForm.ts b/packages/suite/src/hooks/wallet/useUnstakeEthForm.ts
index a5332b95971d..85b9dda6d4de 100644
--- a/packages/suite/src/hooks/wallet/useUnstakeEthForm.ts
+++ b/packages/suite/src/hooks/wallet/useUnstakeEthForm.ts
@@ -70,6 +70,7 @@ export const useUnstakeEthForm = ({
     const amountLimits: AmountLimitProps = {
         currency: symbol,
         maxCrypto: autocompoundBalance,
+        maxFiat: toFiatCurrency(autocompoundBalance, currentRate?.rate) ?? undefined,
     };
 
     const defaultValues = useMemo(() => {
@@ -230,6 +231,7 @@ export const useUnstakeEthForm = ({
             setValue(CRYPTO_INPUT, cryptoValue || '', { shouldDirty: true, shouldValidate: true });
             setValue(OUTPUT_AMOUNT, cryptoValue || '', {
                 shouldDirty: true,
+                shouldValidate: true,
             });
             await composeRequest(FIAT_INPUT);
         },
diff --git a/packages/suite/src/utils/suite/validation.ts b/packages/suite/src/utils/suite/validation.ts
index 277c9b5de6df..ea6438dbaab5 100644
--- a/packages/suite/src/utils/suite/validation.ts
+++ b/packages/suite/src/utils/suite/validation.ts
@@ -1,9 +1,11 @@
 import { Formatter } from '@suite-common/formatters';
+import { FiatCurrencyCode } from '@suite-common/suite-config';
 import { isNetworkSymbol } from '@suite-common/wallet-config';
 import { Account } from '@suite-common/wallet-types';
 import {
     findToken,
     formatNetworkAmount,
+    fromFiatCurrency,
     isDecimalsValid,
     isInteger,
     networkAmountToSmallestUnit,
@@ -52,8 +54,8 @@ export type AmountLimitProps = {
 
 export type CryptoAmountLimitProps = Pick<AmountLimitProps, 'currency' | 'minCrypto' | 'maxCrypto'>;
 
-interface ValidateLimitsOptions {
-    amountLimits?: CryptoAmountLimitProps;
+interface ValidateCryptoLimitsOptions {
+    amountLimits?: AmountLimitProps;
     areSatsUsed?: boolean;
     formatter: Formatter<string, string>;
 }
@@ -61,7 +63,7 @@ interface ValidateLimitsOptions {
 export const validateCryptoLimits =
     (
         translationString: TranslationFunction,
-        { amountLimits, areSatsUsed, formatter }: ValidateLimitsOptions,
+        { amountLimits, areSatsUsed, formatter }: ValidateCryptoLimitsOptions,
     ) =>
     (value: string) => {
         if (value && amountLimits) {
@@ -110,6 +112,64 @@ export const validateCryptoLimits =
         }
     };
 
+interface ValidateFiatLimitsOptions {
+    amountLimits?: AmountLimitProps;
+    localCurrency: FiatCurrencyCode;
+    decimals: number;
+    rate?: number;
+    formatter: Formatter<string, string>;
+}
+
+export const validateFiatLimits =
+    (
+        translationString: TranslationFunction,
+        { amountLimits, localCurrency, formatter, decimals, rate }: ValidateFiatLimitsOptions,
+    ) =>
+    (value: string) => {
+        if (value && amountLimits) {
+            const currency = amountLimits.currency.toLowerCase();
+            const cryptoAmount = fromFiatCurrency(value, decimals, rate);
+            if (!cryptoAmount) return translationString('TR_FIAT_RATES_NOT_AVAILABLE');
+
+            if (amountLimits.minFiat && new BigNumber(value).lt(amountLimits.minFiat)) {
+                return translationString('TR_BUY_VALIDATION_ERROR_MINIMUM_FIAT', {
+                    minimum: amountLimits.minFiat,
+                    currency: localCurrency.toUpperCase(),
+                });
+            }
+
+            // if fiat validation passes we still need to check crypto amount because of floating-point precision errors
+            if (amountLimits.minCrypto && new BigNumber(cryptoAmount).lt(amountLimits.minCrypto)) {
+                return translationString('TR_BUY_VALIDATION_ERROR_MINIMUM_CRYPTO', {
+                    minimum: formatter.format(amountLimits.minCrypto, {
+                        isBalance: true,
+                        symbol: currency,
+                        shouldRedactNumbers: false,
+                        maxDisplayedDecimals: 18,
+                    }),
+                });
+            }
+
+            if (amountLimits.maxFiat && new BigNumber(value).gt(amountLimits.maxFiat)) {
+                return translationString('TR_BUY_VALIDATION_ERROR_MAXIMUM_FIAT', {
+                    maximum: amountLimits.maxFiat,
+                    currency: localCurrency.toUpperCase(),
+                });
+            }
+
+            if (amountLimits.maxCrypto && new BigNumber(cryptoAmount).gt(amountLimits.maxCrypto)) {
+                return translationString('TR_BUY_VALIDATION_ERROR_MAXIMUM_CRYPTO', {
+                    maximum: formatter.format(amountLimits.maxCrypto, {
+                        isBalance: true,
+                        symbol: currency,
+                        shouldRedactNumbers: false,
+                        maxDisplayedDecimals: 18,
+                    }),
+                });
+            }
+        }
+    };
+
 interface ValidateMinOptions {
     except?: boolean;
 }


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>packages/suite/src/utils/suite/validation.ts (1)</summary><blockquote>

`123-171`: **Consider consolidating fiat and crypto validation to reduce duplication.**  
The structure largely repeats what `validateCryptoLimits` does. Merging them or extracting shared logic could simplify maintenance and reduce potential errors. Also, double-check for any floating-point pitfalls when converting fiat to crypto in min/max comparisons.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

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

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between e1f21be5da5a434b003c5823262e052d2678c0ca and 4f502eae01fed20456fb2998c1bd18deb1ed9416.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx` (2 hunks)
* `packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Inputs.tsx` (3 hunks)
* `packages/suite/src/hooks/wallet/useStakeEthForm.ts` (2 hunks)
* `packages/suite/src/hooks/wallet/useUnstakeEthForm.ts` (2 hunks)
* `packages/suite/src/utils/suite/validation.ts` (3 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (9)</summary>

* GitHub Check: run-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
* GitHub Check: run-desktop-tests (@group=other, trezor-user-env-unix)
* GitHub Check: run-desktop-tests (@group=passphrase, trezor-user-env-unix)
* GitHub Check: run-desktop-tests (@group=settings, trezor-user-env-unix bitcoin-regtest)
* GitHub Check: run-desktop-tests (@group=device-management, trezor-user-env-unix)
* GitHub Check: Setup and Cache Dependencies
* GitHub Check: run-desktop-tests (@group=suite, trezor-user-env-unix)
* GitHub Check: build-web
* GitHub Check: Analyze with CodeQL (javascript)

</details>

<details>
<summary>🔇 Additional comments (11)</summary><blockquote>

<details>
<summary>packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx (1)</summary>

`20-23`: **Enhanced import with validateFiatLimits function**

Good addition of the `validateFiatLimits` function to the imports. This aligns with the PR objective to improve staking input validation.

</details>
<details>
<summary>packages/suite/src/hooks/wallet/useStakeEthForm.ts (2)</summary>

`33-33`: **Updated type import to support both crypto and fiat validations**

Good change from `CryptoAmountLimitProps` to `AmountLimitProps`. This type change supports the enhanced validation functionality that now handles both cryptocurrency and fiat values.

---

`59-65`: <details>
<summary>❓ Verification inconclusive</summary>

**Added fiat limits to amountLimits object**

This enhancement properly adds both `minFiat` and `maxFiat` properties to the `amountLimits` object, calculated from their cryptocurrency equivalents. This ensures consistent validation regardless of whether the user inputs cryptocurrency or fiat amounts.

The implementation correctly handles potential undefined values with the nullish coalescing operator.



Let's verify that these fiat limits are being correctly calculated:

---

🏁 Script executed:

```shell
#!/bin/bash
# Check how fiat conversion is implemented in the toFiatCurrency function
rg -A 10 "export const toFiatCurrency" packages/
```

Length of output: 50

---

**StakeETH Form: Verify Fiat Limits Calculation**

The updated code correctly extends the `amountLimits` object by adding `minFiat` and `maxFiat` calculated from their cryptocurrency counterparts, and the use of the nullish coalescing operator appropriately handles potential undefined values during the fiat conversion. However, our initial search for the `toFiatCurrency` function (using the export pattern) returned no output. Please ensure that the `toFiatCurrency` implementation (or its equivalent) exists and behaves as expected in the conversion process.

Key locations to review:
- **packages/suite/src/hooks/wallet/useStakeEthForm.ts (lines 59–65)**
- The implementation of `toFiatCurrency` (or similar) to confirm its role in calculating fiat values.


```

---

🏁 Script executed:

```shell

#!/bin/bash
# Searching for any usage or definition of `toFiatCurrency` across the repository.
rg -n "toFiatCurrency" packages/
```

Length of output: 3178

---



</details>

**Fiat Conversion Limits Verified**

The updates to the `amountLimits` object in `packages/suite/src/hooks/wallet/useStakeEthForm.ts` correctly add the `minFiat` and `maxFiat` fields by converting cryptocurrency values into fiat using the `toFiatCurrency` function. Our repository search confirms that `toFiatCurrency` is imported from `@suite-common/wallet-utils` and consistently used across various modules. The use of the nullish coalescing operator (`?? undefined`) ensures that potential undefined conversion results are handled properly.

For full confidence, please verify that the underlying implementation of `toFiatCurrency` in `@suite-common/wallet-utils` meets the expected conversion logic, especially for edge-case scenarios.

</details>
<details>
<summary>packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Inputs.tsx (2)</summary>

`5-5`: **Removed unused import and simplified dependency**

Good cleanup by removing the unused function from imports.

---

`14-20`: **Streamlined imports and added validateFiatLimits**

The import organization is improved, with explicitly listed validation functions including the newly added `validateFiatLimits`. This makes dependencies clearer and more maintainable.

</details>
<details>
<summary>packages/suite/src/hooks/wallet/useUnstakeEthForm.ts (1)</summary>

`234-234`: **Added validation trigger for fiat amount changes**

Good addition of `shouldValidate: true` to ensure form validation is triggered immediately when the fiat amount changes. This helps provide immediate feedback to users when they exceed unstaking limits.

</details>
<details>
<summary>packages/suite/src/utils/suite/validation.ts (5)</summary>

`2-2`: **No issues with new import.**  
Your new import of `FiatCurrencyCode` is straightforward and consistent.

---

`8-8`: **New import for `fromFiatCurrency` looks good.**  
No major issues with the usage. The code provides handling for missing rates later on, so this addition is appropriate.

---

`57-58`: **Renamed interface aligns well with broader usage.**  
Switching from `CryptoAmountLimitProps` to `AmountLimitProps` unifies the logic for both fiat and crypto, ensuring a single source of truth for limit validations.

---

`65-66`: **Parameters for `validateCryptoLimits` appear well-structured.**  
No immediate issues or parameter mismatches. This update is consistent with the new interface definition.

---

`115-121`: <details>
<summary>❓ Verification inconclusive</summary>

**Ensure callers handle the missing `rate` scenario.**  
Returning `'TR_FIAT_RATES_NOT_AVAILABLE'` when rates are unavailable is a good safeguard. Verify that all usages of `validateFiatLimits` properly manage this scenario.

---

🏁 Script executed:

```shell
#!/bin/bash
# Checks for all calls to `validateFiatLimits` and shows surrounding lines for context
rg -A 10 "validateFiatLimits("
```

Length of output: 121

---

I'll generate a revised shell script that escapes the parenthesis properly in the regex pattern. This will help us gather the necessary context for verifying that all calls to `validateFiatLimits` correctly handle the missing `rate` scenario.

---

🏁 Script executed:

```shell
#!/bin/bash
# Checks for all calls to `validateFiatLimits` with escaped parentheses and shows surrounding context
rg -A 10 "validateFiatLimits\(" .
```

Length of output: 3102

---



</details>

**Action Required: Verify Proper Handling for Missing `rate` in `validateFiatLimits` Callers**

We've located invocations of `validateFiatLimits` in the following files:
- `packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx`
- `packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Inputs.tsx`

In both cases, the call passes `rate: currentRate?.rate`, which means that when `currentRate` is undefined the `rate` parameter becomes undefined. Since `validateFiatLimits` is designed to return `'TR_FIAT_RATES_NOT_AVAILABLE'` in such cases, please verify that:
- The returned fallback string is being checked and handled appropriately downstream (e.g., in UI rendering or subsequent validations).
- There is clear logic in the caller that distinguishes between valid limits and the fallback error string when fiat rates are unavailable.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-04T14:07:56Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>packages/suite/src/utils/suite/validation.ts (1)</summary><blockquote>

`123-171`: **Consider reducing duplication between validation functions**

Both `validateCryptoLimits` and `validateFiatLimits` contain similar formatting code blocks. Consider extracting the common formatting options to a shared utility function to reduce duplication.

```typescript
// Example of a shared helper function
const getFormattingOptions = (currency: string) => ({
  isBalance: true,
  symbol: currency,
  shouldRedactNumbers: false,
  maxDisplayedDecimals: 18,
});
```

This would allow both validation functions to use the same formatting options without duplication.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

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

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 4f502eae01fed20456fb2998c1bd18deb1ed9416 and 14bc21f91704a058652cb99282ce0a89282b501a.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx` (2 hunks)
* `packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Inputs.tsx` (3 hunks)
* `packages/suite/src/hooks/wallet/useStakeEthForm.ts` (2 hunks)
* `packages/suite/src/hooks/wallet/useUnstakeEthForm.ts` (2 hunks)
* `packages/suite/src/utils/suite/validation.ts` (3 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (4)</summary>

* packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx
* packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Inputs.tsx
* packages/suite/src/hooks/wallet/useUnstakeEthForm.ts
* packages/suite/src/hooks/wallet/useStakeEthForm.ts

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: run-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
* GitHub Check: build-web
* GitHub Check: Setup and Cache Dependencies
* GitHub Check: Analyze with CodeQL (javascript)

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>packages/suite/src/utils/suite/validation.ts (8)</summary>

`2-2`: **✓ Appropriate imports added for fiat validation support**

The addition of `FiatCurrencyCode` and `fromFiatCurrency` imports properly supports the new fiat validation functionality being added to this file.



Also applies to: 8-8

---

`57-59`: **✓ Good renaming for improved clarity and type consistency**

Renaming `ValidateLimitsOptions` to `ValidateCryptoLimitsOptions` better describes the interface's purpose, and updating `amountLimits` to use the more comprehensive `AmountLimitProps` type ensures consistency with both crypto and fiat validation.

---

`66-66`: **✓ Parameter destructuring updated to match renamed interface**

The destructuring now correctly matches the renamed interface `ValidateCryptoLimitsOptions`.

---

`115-121`: **✓ Well-structured interface for fiat validation**

The new `ValidateFiatLimitsOptions` interface is well-defined with all the necessary properties for fiat validation including currency, conversion rate, and formatting options.

---

`123-133`: **✓ Robust fiat validation implementation with proper error handling**

The function correctly validates fiat amounts and includes appropriate error handling when rate conversion is not available.

---

`134-151`: **✓ Comprehensive minimum value validation**

The implementation correctly checks both fiat and crypto minimums, with appropriate error messages for each case.

---

`141-151`: **Good practice to check crypto amounts after fiat validation**

The comment explaining why crypto amounts need to be checked even after fiat validation passes (due to floating-point precision errors) is a valuable clarification and shows careful consideration of numeric precision issues.

---

`153-170`: **✓ Comprehensive maximum value validation**

The implementation correctly checks both fiat and crypto maximums, with appropriate error messages for each case.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-04T14:23:01Z
user: login: tomasklim
body: Formatter should floor amount up but that is another issue.

LGTM, works great, thanks
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-04T14:33:13Z

Review comments:
diff_hunk: @@ -57,6 +58,13 @@ export const Inputs = () => {
         validate: {
             min: validateMin(translationString),
             decimals: validateDecimals(translationString, { decimals: 2 }),
+            limits: validateFiatLimits(translationString, {
+                amountLimits,
+                localCurrency,
+                formatter: CryptoAmountFormatter,
+                decimals: network.decimals,
+                rate: currentRate?.rate,
+            }),
path: packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeEthForm/Inputs.tsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Added validation for fiat inputs to enforce staking limits**

This is a critical addition that addresses the PR objective of preventing users from staking below minimum thresholds. The implementation correctly passes all necessary parameters to the `validateFiatLimits` function, ensuring proper validation of fiat inputs against the defined limits.



Make sure to test this thoroughly with different currency rates to verify that users can't bypass minimum staking requirements by switching to fiat input.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-04T14:07:56Z
author_association: NONE
diff_hunk: @@ -60,6 +61,13 @@ export const Inputs = () => {
         validate: {
             min: validateMin(translationString),
             decimals: validateDecimals(translationString, { decimals: 2 }),
+            limits: validateFiatLimits(translationString, {
+                amountLimits,
+                localCurrency,
+                formatter: CryptoAmountFormatter,
+                decimals: network.decimals,
+                rate: currentRate?.rate,
+            }),
path: packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/UnstakeModal/UnstakeEthForm/Inputs.tsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Added fiat validation for unstaking limits**

This crucial addition addresses the PR objective of preventing users from unstaking amounts exceeding their current stake balance. The implementation correctly validates fiat inputs against the defined limits, maintaining consistency with the staking form.



This validation is a key fix for the issue that allowed users to unstake more than their current stake balance. Make sure to test edge cases where fiat/crypto conversions might lead to rounding issues.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-04T14:07:56Z
author_association: NONE
diff_hunk: @@ -70,6 +70,7 @@ export const useUnstakeEthForm = ({
     const amountLimits: AmountLimitProps = {
         currency: symbol,
         maxCrypto: autocompoundBalance,
+        maxFiat: toFiatCurrency(autocompoundBalance, currentRate?.rate) ?? undefined,
path: packages/suite/src/hooks/wallet/useUnstakeEthForm.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Added maxFiat limit to prevent excessive unstaking**

This addition is critical for fixing the unstaking limit issue. By calculating the fiat equivalent of the maximum unstakable amount, the form now properly restricts users from unstaking more than their available balance, regardless of input type.



This directly addresses the PR objective to prevent unstaking amounts exceeding the current stake balance.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-04T14:07:56Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-03-04T14:07:52Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This pull request updates the validation logic for fiat amounts alongside cryptocurrency validations across the staking and unstaking forms. A new validation function, `validateFiatLimits`, along with the interface `ValidateFiatLimitsOptions`, has been introduced to apply limits to fiat inputs. The changes adjust the existing validation rules by incorporating parameters such as fiat conversion, local currency formatting, and network decimals. In addition, the hooks managing staking and unstaking have been updated to include fiat limits (`minFiat` and `maxFiat`) in the `amountLimits` object using a fiat conversion function. Import statements and error handling mechanisms have been revised by removing an unused function and updating type imports. The type definitions have been refactored by renaming `ValidateLimitsOptions` to `ValidateCryptoLimitsOptions` and switching from `CryptoAmountLimitProps` to `AmountLimitProps` to accommodate both cryptocurrency and fiat value validations.

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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?

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai):

- 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 generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this 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](https://docs.coderabbit.ai/guides/configure-coderabbit) 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](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: tomasklim
created_at: 2025-03-04T14:19:35Z
body: /rebase
author_association: MEMBER
user: login: github-actions[bot]
created_at: 2025-03-04T14:19:53Z
body: Start rebasing: https://github.com/trezor/trezor-suite/actions/runs/13655744876
author_association: NONE