Repository: trezor/trezor-suite
Pull request #18944: Add tooltip explaining provider-adjusted sell amount in offer list
Author: login: izmy
Created: 2025-05-14T13:01:45Z | Merged: 2025-05-20T19:17:35Z

## Description

Sell offers now include a tooltip when the provider's offered crypto amount differs from the user input.

## Related Issue

Resolve https://github.com/trezor/trezor-suite/issues/16669

## Screenshots:

<img width="1228" alt="image" src="https://github.com/user-attachments/assets/a25eb8d7-0837-48e5-938e-5255e4d77a91" />

<img width="1234" alt="image" src="https://github.com/user-attachments/assets/481aee8b-09d7-4f52-b736-d84988d71b3e" />

🔍🖥️ **Suite web test results:** [View in Currents](https://app.currents.dev/projects/Og0NOQ/runs?branch=fix/sell-provider-amount-tooltip&lookback=7)

🔍🖥️ **Suite desktop test results:** [View in Currents](https://app.currents.dev/projects/4ytF0E/runs?branch=fix/sell-provider-amount-tooltip&lookback=7)


Diff:
diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts
index 629898e1dd3b..12ecc82bf705 100644
--- a/packages/suite/src/support/messages.ts
+++ b/packages/suite/src/support/messages.ts
@@ -799,6 +799,10 @@ export default defineMessages({
         defaultMessage: 'Pending',
         id: 'TR_SELL_STATUS_PENDING',
     },
+    TR_SELL_PROVIDER_ADJUSTED_AMOUNT: {
+        defaultMessage: 'Provider adjusted your amount to {roundedAmountWithSymbol}',
+        id: 'TR_SELL_PROVIDER_ADJUSTED_AMOUNT',
+    },
     TR_REQUIRED_FIELD: {
         defaultMessage: 'Required',
         id: 'TR_REQUIRED_FIELD',
diff --git a/packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx b/packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
index ba41119fa8f8..29e26a776a44 100644
--- a/packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
+++ b/packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
@@ -10,7 +10,7 @@ import {
     parseCryptoId,
     useTradingInfo,
 } from '@suite-common/trading';
-import { Button, Column, Paragraph, Row, TextButton } from '@trezor/components';
+import { Button, Column, Paragraph, Row, TextButton, Tooltip } from '@trezor/components';
 import { spacings } from '@trezor/theme';
 
 import { Translation } from 'src/components/suite';
@@ -23,12 +23,14 @@ import {
     getSelectQuoteTyped,
     getSelectedCrypto,
     isTradingExchangeContext,
+    isTradingSellContext,
 } from 'src/utils/wallet/trading/tradingTypingUtils';
 import {
     tradingGetAmountLabels,
     tradingGetRoundedFiatAmount,
     tradingGetSectionActionLabel,
 } from 'src/utils/wallet/trading/tradingUtils';
+import { TradingCryptoAmount } from 'src/views/wallet/trading/common/TradingCryptoAmount';
 import { TradingFormOfferCryptoAmount } from 'src/views/wallet/trading/common/TradingForm/TradingFormOfferCryptoAmount';
 import { TradingFormOfferFiatAmount } from 'src/views/wallet/trading/common/TradingForm/TradingFormOfferFiatAmount';
 import { TradingFormOfferItem } from 'src/views/wallet/trading/common/TradingForm/TradingFormOfferItem';
@@ -80,6 +82,9 @@ export const TradingFormOffer = () => {
 
     const { tradingDeviceDisconnected } = useTradingDeviceDisconnected();
 
+    const showProviderAdjustedAmountTooltip =
+        isTradingSellContext(context) && bestScoredQuoteAmounts && !state.isFormLoading;
+
     const onSelectQuote = () => {
         if (!quote) {
             return;
@@ -126,7 +131,31 @@ export const TradingFormOffer = () => {
             </Column>
             <Column gap={spacings.xxs} margin={{ vertical: spacings.md }}>
                 <Row justifyContent="space-between">
-                    <Translation id="TR_TRADING_YOUR_BEST_OFFER" />
+                    {showProviderAdjustedAmountTooltip ? (
+                        <Tooltip
+                            hasIcon
+                            placement="right"
+                            content={
+                                <Translation
+                                    id="TR_SELL_PROVIDER_ADJUSTED_AMOUNT"
+                                    values={{
+                                        roundedAmountWithSymbol: (
+                                            <TradingCryptoAmount
+                                                amount={bestScoredQuoteAmounts.receiveAmount}
+                                                cryptoId={
+                                                    bestScoredQuoteAmounts.receiveCurrency as CryptoId
+                                                }
+                                            />
+                                        ),
+                                    }}
+                                />
+                            }
+                        >
+                            <Translation id="TR_TRADING_YOUR_BEST_OFFER" />
+                        </Tooltip>
+                    ) : (
+                        <Translation id="TR_TRADING_YOUR_BEST_OFFER" />
+                    )}
                     <TextButton
                         onClick={onCompareAllOffersClick}
                         size="small"
diff --git a/packages/suite/src/views/wallet/trading/common/TradingOffers/TradingOffersItem.tsx b/packages/suite/src/views/wallet/trading/common/TradingOffers/TradingOffersItem.tsx
index 88365fb2689f..b1cdcd1bba3c 100644
--- a/packages/suite/src/views/wallet/trading/common/TradingOffers/TradingOffersItem.tsx
+++ b/packages/suite/src/views/wallet/trading/common/TradingOffers/TradingOffersItem.tsx
@@ -150,6 +150,7 @@ export const TradingOffersItem = ({ quote }: TradingOffersItemProps) => {
                     <AmountOfferColumn>
                         <Row alignItems="flex-end" data-testid="@trading/offer/amount">
                             <TradingUtilsPrice {...cryptoAmountProps} />
+
                             {isTradingExchangeContext(context) && (
                                 <TradingUtilsKyc
                                     exchange={exchange}
diff --git a/packages/suite/src/views/wallet/trading/common/TradingUtils/TradingUtilsPrice.tsx b/packages/suite/src/views/wallet/trading/common/TradingUtils/TradingUtilsPrice.tsx
index 6821bb8c6aa0..a1c6a43da804 100644
--- a/packages/suite/src/views/wallet/trading/common/TradingUtils/TradingUtilsPrice.tsx
+++ b/packages/suite/src/views/wallet/trading/common/TradingUtils/TradingUtilsPrice.tsx
@@ -1,5 +1,7 @@
+import { CryptoId } from 'invity-api';
 import styled from 'styled-components';
 
+import { Tooltip } from '@trezor/components';
 import { FONT_SIZE, SCREEN_QUERY } from '@trezor/components/src/config/variables';
 import { spacingsPx, typography } from '@trezor/theme';
 
@@ -46,14 +48,43 @@ export const TradingUtilsPrice = ({
     return (
         <PriceWrap>
             <PriceTitle>
-                <Translation
-                    id={
-                        tradingGetAmountLabels({
-                            type,
-                            amountInCrypto: !!amountInCrypto,
-                        }).labelComparatorOffer
-                    }
-                />
+                {type === 'sell' ? (
+                    <Tooltip
+                        hasIcon
+                        placement="right"
+                        content={
+                            <Translation
+                                id="TR_SELL_PROVIDER_ADJUSTED_AMOUNT"
+                                values={{
+                                    roundedAmountWithSymbol: (
+                                        <TradingCryptoAmount
+                                            amount={receiveAmount}
+                                            cryptoId={receiveCurrency as CryptoId}
+                                        />
+                                    ),
+                                }}
+                            />
+                        }
+                    >
+                        <Translation
+                            id={
+                                tradingGetAmountLabels({
+                                    type,
+                                    amountInCrypto: !!amountInCrypto,
+                                }).labelComparatorOffer
+                            }
+                        />
+                    </Tooltip>
+                ) : (
+                    <Translation
+                        id={
+                            tradingGetAmountLabels({
+                                type,
+                                amountInCrypto: !!amountInCrypto,
+                            }).labelComparatorOffer
+                        }
+                    />
+                )}
             </PriceTitle>
             <PriceValueWrap data-testid="@trading/offers/quote/amount">
                 <PriceValue>


Reviews:
user: login: TomasBoda
body: Please rebase, e2e tests should be working now
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T08:34:02Z
user: login: TomasBoda
body: I'm wondering if it wouldn't be cleaner if the tooltip icon was next to the label:

<img width="1175" alt="Screenshot 2025-05-16 at 10 45 39" src="https://github.com/user-attachments/assets/b543f42f-d444-45bd-b0be-f8683913f832" />

<img width="1175" alt="Screenshot 2025-05-16 at 10 48 35" src="https://github.com/user-attachments/assets/0cfcebaf-abe1-4bb3-b165-d2aa64abd6f7" />

What do you think?
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T08:49:11Z
user: login: TomasBoda
body: LGTM 🎉
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T14:41:23Z
user: login: adderpositive
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T17:36:23Z
user: login: tomasklim
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-18T08:21:43Z
user: login: tomasklim
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-18T08:22:36Z
user: login: izmy
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T10:15:10Z
user: login: izmy
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T10:15:20Z
user: login: izmy
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T10:15:26Z

Review comments:
diff_hunk: @@ -35,6 +35,8 @@ import { TradingFormOfferItem } from 'src/views/wallet/trading/common/TradingFor
 import { TradingFormOfferOTC } from 'src/views/wallet/trading/common/TradingForm/TradingFormOfferOTC';
 import { TradingFormOffersSwitcher } from 'src/views/wallet/trading/common/TradingForm/TradingFormOffersSwitcher';
 
+import { TradingCryptoAmount } from '../TradingCryptoAmount';
path: packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
user: login: adderpositive
body: Absolute path
created_at: 2025-05-17T17:29:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -80,6 +82,9 @@ export const TradingFormOffer = () => {
 
     const { tradingDeviceDisconnected } = useTradingDeviceDisconnected();
 
+    const showProviderAdjustedAmountTooltip =
+        context.type === 'sell' && bestScoredQuoteAmounts && !state.isFormLoading;
path: packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
user: login: adderpositive
body: Nit

```suggestion
        isTradingSellContext(context) && bestScoredQuoteAmounts && !state.isFormLoading;
```
created_at: 2025-05-17T17:30:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -126,7 +131,32 @@ export const TradingFormOffer = () => {
             </Column>
             <Column gap={spacings.xxs} margin={{ vertical: spacings.md }}>
                 <Row justifyContent="space-between">
-                    <Translation id="TR_TRADING_YOUR_BEST_OFFER" />
+                    {showProviderAdjustedAmountTooltip ? (
+                        <Tooltip
+                            hasIcon
+                            placement="right"
+                            content={
+                                <Translation
+                                    id="TR_SELL_PROVIDER_ADJUSTED_AMOUNT"
+                                    values={{
+                                        roundedAmount: (
+                                            <TradingCryptoAmount
+                                                amount={bestScoredQuoteAmounts.receiveAmount}
+                                                cryptoId={
+                                                    bestScoredQuoteAmounts.receiveCurrency as CryptoId
+                                                }
+                                                type="sell"
+                                            />
+                                        ),
+                                    }}
path: packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
user: login: adderpositive
body: Is this ok to use react component as a value? 
created_at: 2025-05-17T17:35:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -126,7 +131,32 @@ export const TradingFormOffer = () => {
             </Column>
             <Column gap={spacings.xxs} margin={{ vertical: spacings.md }}>
                 <Row justifyContent="space-between">
-                    <Translation id="TR_TRADING_YOUR_BEST_OFFER" />
+                    {showProviderAdjustedAmountTooltip ? (
+                        <Tooltip
+                            hasIcon
+                            placement="right"
+                            content={
+                                <Translation
+                                    id="TR_SELL_PROVIDER_ADJUSTED_AMOUNT"
+                                    values={{
+                                        roundedAmount: (
path: packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
user: login: tomasklim
body: ```suggestion
                                        roundedAmountWithSymbol: (
```
created_at: 2025-05-18T08:21:43Z
author_association: MEMBER
diff_hunk: @@ -126,7 +131,32 @@ export const TradingFormOffer = () => {
             </Column>
             <Column gap={spacings.xxs} margin={{ vertical: spacings.md }}>
                 <Row justifyContent="space-between">
-                    <Translation id="TR_TRADING_YOUR_BEST_OFFER" />
+                    {showProviderAdjustedAmountTooltip ? (
+                        <Tooltip
+                            hasIcon
+                            placement="right"
+                            content={
+                                <Translation
+                                    id="TR_SELL_PROVIDER_ADJUSTED_AMOUNT"
+                                    values={{
+                                        roundedAmount: (
+                                            <TradingCryptoAmount
+                                                amount={bestScoredQuoteAmounts.receiveAmount}
+                                                cryptoId={
+                                                    bestScoredQuoteAmounts.receiveCurrency as CryptoId
+                                                }
+                                                type="sell"
+                                            />
+                                        ),
+                                    }}
path: packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
user: login: tomasklim
body: We use it on other places
created_at: 2025-05-18T08:22:36Z
author_association: MEMBER
diff_hunk: @@ -126,7 +131,32 @@ export const TradingFormOffer = () => {
             </Column>
             <Column gap={spacings.xxs} margin={{ vertical: spacings.md }}>
                 <Row justifyContent="space-between">
-                    <Translation id="TR_TRADING_YOUR_BEST_OFFER" />
+                    {showProviderAdjustedAmountTooltip ? (
+                        <Tooltip
+                            hasIcon
+                            placement="right"
+                            content={
+                                <Translation
+                                    id="TR_SELL_PROVIDER_ADJUSTED_AMOUNT"
+                                    values={{
+                                        roundedAmount: (
path: packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
user: login: izmy
body: done
created_at: 2025-05-19T10:15:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -80,6 +82,9 @@ export const TradingFormOffer = () => {
 
     const { tradingDeviceDisconnected } = useTradingDeviceDisconnected();
 
+    const showProviderAdjustedAmountTooltip =
+        context.type === 'sell' && bestScoredQuoteAmounts && !state.isFormLoading;
path: packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
user: login: izmy
body: done
created_at: 2025-05-19T10:15:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -35,6 +35,8 @@ import { TradingFormOfferItem } from 'src/views/wallet/trading/common/TradingFor
 import { TradingFormOfferOTC } from 'src/views/wallet/trading/common/TradingForm/TradingFormOfferOTC';
 import { TradingFormOffersSwitcher } from 'src/views/wallet/trading/common/TradingForm/TradingFormOffersSwitcher';
 
+import { TradingCryptoAmount } from '../TradingCryptoAmount';
path: packages/suite/src/views/wallet/trading/common/TradingForm/TradingFormOffer.tsx
user: login: izmy
body: done
created_at: 2025-05-19T10:15:26Z
author_association: CONTRIBUTOR

PR comments:
user: login: izmy
created_at: 2025-05-16T11:05:18Z
body: > I'm wondering if it wouldn't be cleaner if the tooltip icon was next to the label:

Great idea, thanks. I changed it.
author_association: CONTRIBUTOR
user: login: trezor-bot[bot]
created_at: 2025-05-16T14:28:33Z
body: ✅ Previously successful run of **[Test] PR Suite Web e2e tests** workflow has been found.
⏭️ Skipping tests for this run.
💡 If you are unsure about your latest changes, please rerun the workflow manually. (Use the Re-run all jobs option)
author_association: CONTRIBUTOR
user: login: tomasklim
created_at: 2025-05-19T16:09:34Z
body: @izmy please resolve CI
author_association: MEMBER
user: login: trezor-bot[bot]
created_at: 2025-05-20T16:10:25Z
body: ✅ Previously successful run of **[Test] PR Suite Web e2e tests** workflow has been found.
⏭️ Skipping tests for this run.
💡 If you are unsure about your latest changes, please rerun the workflow manually. (Use the Re-run all jobs option)
author_association: CONTRIBUTOR
user: login: adderpositive
created_at: 2025-05-20T19:18:33Z
body: 👌
author_association: CONTRIBUTOR