diff --git a/.changeset/rude-moose-bathe.md b/.changeset/rude-moose-bathe.md new file mode 100644 index 000000000000..8e189ed015df --- /dev/null +++ b/.changeset/rude-moose-bathe.md @@ -0,0 +1,6 @@ +--- +"ledger-live-desktop": patch +"@ledgerhq/coin-evm": patch +--- + +Parent Account Error on gas fees LLD diff --git a/apps/ledger-live-desktop/src/renderer/components/SelectFeeStrategy.tsx b/apps/ledger-live-desktop/src/renderer/components/SelectFeeStrategy.tsx index 22f62432bb5e..2a0e8cee9407 100644 --- a/apps/ledger-live-desktop/src/renderer/components/SelectFeeStrategy.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/SelectFeeStrategy.tsx @@ -12,6 +12,7 @@ import CounterValue from "~/renderer/components/CounterValue"; import { getFeesCurrency, getFeesUnit, getMainAccount } from "@ledgerhq/live-common/account/index"; import { Account, FeeStrategy } from "@ledgerhq/types-live"; import { Transaction } from "@ledgerhq/live-common/generated/types"; +import { TransactionStatus } from "@ledgerhq/live-common/generated/types"; export type OnClickType = { amount: BigNumber; @@ -28,16 +29,21 @@ type Props = { [x: string]: unknown; }; suffixPerByte?: boolean; + status: TransactionStatus; }; -const FeesWrapper = styled(Box)<{ selected?: boolean; disabled?: boolean }>` +const FeesWrapper = styled(Box)<{ selected?: boolean; disabled?: boolean; error: boolean }>` flex-direction: row; align-items: center; justify-content: space-between; border: ${p => `1px solid ${ - p.selected ? p.theme.colors.palette.primary.main : p.theme.colors.palette.divider + p.selected + ? p.error + ? p.theme.colors.palette.warning.c70 + : p.theme.colors.palette.primary.main + : p.theme.colors.palette.divider }`}; ${p => (p.selected ? "box-shadow: 0px 0px 0px 4px rgba(138, 128, 219, 0.3);" : "")} padding: 20px 16px; @@ -50,10 +56,12 @@ const FeesWrapper = styled(Box)<{ selected?: boolean; disabled?: boolean }>` cursor: ${p => (p.disabled ? "unset" : "pointer")}; } `; -const FeesHeader = styled(Box)<{ selected?: boolean; disabled?: boolean }>` +const FeesHeader = styled(Box)<{ selected?: boolean; disabled?: boolean; error: boolean }>` color: ${p => p.selected - ? p.theme.colors.palette.primary.main + ? p.error + ? p.theme.colors.palette.warning.c70 + : p.theme.colors.palette.primary.main : p.disabled ? p.theme.colors.palette.text.shade20 : p.theme.colors.palette.text.shade50}; @@ -70,12 +78,17 @@ const SelectFeeStrategy = ({ strategies, mapStrategies, suffixPerByte, + status, }: Props) => { const mainAccount = getMainAccount(account, parentAccount); const feesCurrency = getFeesCurrency(mainAccount); const feesUnit = getFeesUnit(feesCurrency); const { t } = useTranslation(); strategies = mapStrategies ? strategies.map(mapStrategies) : strategies; + + const { errors } = status; + const { gasPrice: messageGas } = errors; + return ( {strategies.map(s => { @@ -87,6 +100,7 @@ const SelectFeeStrategy = ({ key={s.label} selected={selected} disabled={disabled} + error={!!messageGas} onClick={() => { !disabled && onClick({ @@ -95,7 +109,13 @@ const SelectFeeStrategy = ({ }); }} > - + {label === "medium" ? ( ) : label === "slow" ? ( diff --git a/apps/ledger-live-desktop/src/renderer/families/bitcoin/SendAmountFields.tsx b/apps/ledger-live-desktop/src/renderer/families/bitcoin/SendAmountFields.tsx index 49f061f15218..46ba140c259c 100644 --- a/apps/ledger-live-desktop/src/renderer/families/bitcoin/SendAmountFields.tsx +++ b/apps/ledger-live-desktop/src/renderer/families/bitcoin/SendAmountFields.tsx @@ -16,6 +16,13 @@ import CoinControlModal from "./CoinControlModal"; import { FeesField } from "./FeesField"; import { BitcoinFamily } from "./types"; import useBitcoinPickingStrategy from "./useBitcoinPickingStrategy"; +import Alert from "~/renderer/components/Alert"; +import TranslatedError from "~/renderer/components/TranslatedError"; +import { useDispatch } from "react-redux"; +import { useHistory } from "react-router"; +import { closeAllModal } from "~/renderer/actions/modals"; +import { setTrackingSource } from "~/renderer/analytics/TrackPage"; +import { Flex } from "@ledgerhq/react-ui"; type Props = NonNullable["component"]; @@ -46,6 +53,24 @@ const Fields: Props = ({ const { item } = useBitcoinPickingStrategy(transaction.utxoStrategy.strategy); const canNext = account.bitcoinResources?.utxos?.length; + const dispatch = useDispatch(); + const history = useHistory(); + + const onBuyClick = useCallback(() => { + dispatch(closeAllModal()); + setTrackingSource("send flow"); + history.push({ + pathname: "/exchange", + state: { + currency: account.currency.id, + account: account.id, + mode: "buy", // buy or sell + }, + }); + }, [account.currency.id, account.id, dispatch, history]); + + const { errors } = status; + const { gasPrice: messageGas } = errors; /* TODO: How do we set default RBF to be true ? (@gre) * Meanwhile, using this trick (please don't kill me) */ @@ -147,15 +172,25 @@ const Fields: Props = ({ ) : ( - + <> + + {messageGas && ( + + + + + + )} + )} ); diff --git a/apps/ledger-live-desktop/src/renderer/families/evm/SendAmountFields/SelectFeeStrategy.tsx b/apps/ledger-live-desktop/src/renderer/families/evm/SendAmountFields/SelectFeeStrategy.tsx index 097351394d43..616aefa332d2 100644 --- a/apps/ledger-live-desktop/src/renderer/families/evm/SendAmountFields/SelectFeeStrategy.tsx +++ b/apps/ledger-live-desktop/src/renderer/families/evm/SendAmountFields/SelectFeeStrategy.tsx @@ -19,6 +19,7 @@ import Clock from "~/renderer/icons/Clock"; import TachometerHigh from "~/renderer/icons/TachometerHigh"; import TachometerLow from "~/renderer/icons/TachometerLow"; import TachometerMedium from "~/renderer/icons/TachometerMedium"; +import { TransactionStatus } from "@ledgerhq/live-common/generated/types"; type Props = { onClick: (_: { feesStrategy: Strategy }) => void; @@ -26,9 +27,10 @@ type Props = { account: Account; gasOptions: GasOptions; transactionToUpdate?: EvmTransaction; + status: TransactionStatus; }; -const FeesWrapper = styled(Tabbable)` +const FeesWrapper = styled(Tabbable)<{ error?: boolean }>` flex-direction: column; align-items: center; justify-content: space-between; @@ -36,7 +38,11 @@ const FeesWrapper = styled(Tabbable)` border: ${p => `1px solid ${ - p?.selected ? p.theme.colors.palette.primary.main : p.theme.colors.palette.divider + p?.selected + ? p?.error + ? p.theme.colors.palette.warning.c70 + : p.theme.colors.palette.primary.main + : p.theme.colors.palette.divider }`}; padding: 20px 16px; font-family: "Inter"; @@ -49,10 +55,12 @@ const FeesWrapper = styled(Tabbable)` } `; -const FeesHeader = styled(Box)<{ selected?: boolean; disabled?: boolean }>` +const FeesHeader = styled(Box)<{ selected?: boolean; disabled?: boolean; error?: boolean }>` color: ${p => p.selected - ? p.theme.colors.palette.primary.main + ? p?.error + ? p.theme.colors.palette.warning.c70 + : p.theme.colors.palette.primary.main : p.disabled ? p.theme.colors.palette.text.shade20 : p.theme.colors.palette.text.shade50}; @@ -63,12 +71,16 @@ const FeesValue = styled(Box)` text-align: center; `; -const ApproximateTransactionTime = styled(Box)<{ selected?: boolean }>` +const ApproximateTransactionTime = styled(Box)<{ selected?: boolean; error?: boolean }>` flex-direction: row; align-items: center; border-radius: 3px; background-color: ${p => - p.selected ? p.theme.colors.palette.primary.main : p.theme.colors.palette.text.shade20}; + p.selected + ? p?.error + ? p.theme.colors.palette.warning.c70 + : p.theme.colors.palette.primary.main + : p.theme.colors.palette.text.shade20}; padding: 5px 6px; `; @@ -80,9 +92,12 @@ const SelectFeeStrategy = ({ onClick, gasOptions, transactionToUpdate, + status, }: Props) => { const accountUnit = getAccountUnit(account); const feesCurrency = getAccountCurrency(account); + const { errors } = status; + const { gasPrice: messageGas } = errors; const feeStrategies = useMemo( () => @@ -103,6 +118,7 @@ const SelectFeeStrategy = ({ key={strategy} selected={selected} disabled={disabled} + error={!!messageGas} onClick={() => { !disabled && onClick({ @@ -111,7 +127,13 @@ const SelectFeeStrategy = ({ }} > <> - + {strategy === "medium" ? ( ) : strategy === "slow" ? ( @@ -152,9 +174,17 @@ const SelectFeeStrategy = ({ /> {feesCurrency.id === "ethereum" && ( - - - + + + {strategy === "medium" ? ( <> ≈ 30 @@ -175,7 +205,7 @@ const SelectFeeStrategy = ({ ); }), - [accountUnit, feesCurrency, gasOptions, onClick, transaction, transactionToUpdate], + [accountUnit, feesCurrency, gasOptions, messageGas, onClick, transaction, transactionToUpdate], ); return ( diff --git a/apps/ledger-live-desktop/src/renderer/families/evm/SendAmountFields/index.tsx b/apps/ledger-live-desktop/src/renderer/families/evm/SendAmountFields/index.tsx index eae1cf9779fb..ab124fe2979b 100644 --- a/apps/ledger-live-desktop/src/renderer/families/evm/SendAmountFields/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/families/evm/SendAmountFields/index.tsx @@ -12,11 +12,37 @@ import GasPriceField from "./GasPriceField"; import MaxFeeField from "./MaxFeeField"; import PriorityFeeField from "./PriorityFeeField"; import SelectFeeStrategy from "./SelectFeeStrategy"; +import TranslatedError from "~/renderer/components/TranslatedError"; +import Alert from "~/renderer/components/Alert"; +import { Flex } from "@ledgerhq/react-ui"; +import { closeAllModal } from "~/renderer/actions/modals"; +import { setTrackingSource } from "~/renderer/analytics/TrackPage"; +import { useDispatch } from "react-redux"; +import { useHistory } from "react-router"; const Root: NonNullable["component"] = props => { const { account, updateTransaction, transaction } = props; const bridge: AccountBridge = getAccountBridge(account); + const { errors } = props.status; + const { gasPrice: messageGas } = errors; + + const dispatch = useDispatch(); + const history = useHistory(); + + const onBuyClick = useCallback(() => { + dispatch(closeAllModal()); + setTrackingSource("send flow"); + history.push({ + pathname: "/exchange", + state: { + currency: account.currency.id, + account: account.id, + mode: "buy", // buy or sell + }, + }); + }, [account.currency.id, account.id, dispatch, history]); + const [gasOptions, error, loading] = useGasOptions({ currency: account.currency, transaction, @@ -86,6 +112,13 @@ const Root: NonNullable["component"] = props => { )} + {messageGas && ( + + + + + + )} ); }; diff --git a/apps/ledger-live-desktop/src/renderer/modals/Send/fields/AmountField.tsx b/apps/ledger-live-desktop/src/renderer/modals/Send/fields/AmountField.tsx index 9a85e960636d..0b586a9bbd8e 100644 --- a/apps/ledger-live-desktop/src/renderer/modals/Send/fields/AmountField.tsx +++ b/apps/ledger-live-desktop/src/renderer/modals/Send/fields/AmountField.tsx @@ -70,7 +70,7 @@ const AmountField = ({ const { useAllAmount } = transaction; const { amount, errors, warnings } = status; - const { amount: amountError, dustLimit: messageDust, gasPrice: messageGas } = errors; + const { amount: amountError, dustLimit: messageDust } = errors; const { amount: amountWarning } = warnings; let amountErrMessage: Error | undefined = amountError; @@ -123,7 +123,7 @@ const AmountField = ({ { const isTerminated = mainAccount.currency.terminated; const hasErrors = Object.keys(errors).length; const canNext = !bridgePending && !hasErrors && !isTerminated; - const { - gasPrice: gasPriceError, - maxPriorityFee: maxPriorityFeeError, - maxFee: maxFeeError, - } = errors; + const { maxPriorityFee: maxPriorityFeeError, maxFee: maxFeeError } = errors; return ( <> {!isNFTSend ? ( ) : null} - {gasPriceError || maxPriorityFeeError || maxFeeError ? ( + {maxPriorityFeeError || maxFeeError ? ( ) : null}