From 07a242d9c54a4b70d9fec7ef390b8e8ab7de4df7 Mon Sep 17 00:00:00 2001 From: Hedi EDELBLOUTE Date: Wed, 2 Oct 2024 16:03:28 +0200 Subject: [PATCH] Support/fix ada fees (#7965) * cardano high fees checks * add custom CardanoFeeTooHigh error * display feeTooHigh error * validate protocol params * handle fee error in delegation * fee warning in delegation * show tx status warnings and errors * update * tx error update * sync proto params in tx prepare * add coinconfig + update translations * fix cc * update texts * add changeset --------- Co-authored-by: pavanvora Co-authored-by: Prashanth Co-authored-by: Pavan Vora Co-authored-by: mehulcs --- .changeset/thick-foxes-repair.md | 8 ++ .../steps/StepDelegation.tsx | 2 +- .../DelegationFlowModal/steps/StepSummary.tsx | 24 ++++- .../MemoField.tsx} | 8 +- .../{ => SendAmountFields}/MemoValueField.tsx | 1 + .../cardano/SendAmountFields/index.tsx | 27 ++++++ .../UndelegateFlowModal/steps/StepSummary.tsx | 52 ++++++---- .../static/i18n/en/app.json | 12 +++ .../cardano/DelegationFlow/02-Summary.tsx | 52 +++++++++- .../cardano/UndelegationFlow/01-Summary.tsx | 97 +++++++++++++++---- .../src/locales/en/common.json | 12 +++ .../coin-cardano/src/bridge/index.ts | 8 +- .../coin-cardano/src/buildTransaction.ts | 16 ++- libs/coin-modules/coin-cardano/src/config.ts | 12 +++ libs/coin-modules/coin-cardano/src/errors.ts | 8 ++ .../coin-cardano/src/estimateMaxSpendable.ts | 4 +- .../coin-cardano/src/getTransactionStatus.ts | 22 ++++- libs/coin-modules/coin-cardano/src/logic.ts | 24 +++++ .../coin-cardano/src/logic.unit.test.ts | 19 +++- .../coin-cardano/src/prepareTransaction.ts | 9 ++ .../coin-cardano/src/signOperation.ts | 5 + .../coin-cardano/src/transaction.ts | 2 + libs/coin-modules/coin-cardano/src/types.ts | 2 + .../src/families/cardano/config.ts | 9 +- .../src/families/cardano/setup.ts | 8 ++ 25 files changed, 383 insertions(+), 60 deletions(-) create mode 100644 .changeset/thick-foxes-repair.md rename apps/ledger-live-desktop/src/renderer/families/cardano/{SendAmountFields.tsx => SendAmountFields/MemoField.tsx} (91%) rename apps/ledger-live-desktop/src/renderer/families/cardano/{ => SendAmountFields}/MemoValueField.tsx (99%) create mode 100644 apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields/index.tsx create mode 100644 libs/coin-modules/coin-cardano/src/config.ts diff --git a/.changeset/thick-foxes-repair.md b/.changeset/thick-foxes-repair.md new file mode 100644 index 000000000000..7b06f99fa1d9 --- /dev/null +++ b/.changeset/thick-foxes-repair.md @@ -0,0 +1,8 @@ +--- +"@ledgerhq/coin-cardano": patch +"ledger-live-desktop": patch +"live-mobile": patch +"@ledgerhq/live-common": patch +--- + +Cardano fees warning + fix high fees issue diff --git a/apps/ledger-live-desktop/src/renderer/families/cardano/DelegationFlowModal/steps/StepDelegation.tsx b/apps/ledger-live-desktop/src/renderer/families/cardano/DelegationFlowModal/steps/StepDelegation.tsx index 9729c15951e8..7fa3dd1cf29f 100644 --- a/apps/ledger-live-desktop/src/renderer/families/cardano/DelegationFlowModal/steps/StepDelegation.tsx +++ b/apps/ledger-live-desktop/src/renderer/families/cardano/DelegationFlowModal/steps/StepDelegation.tsx @@ -77,7 +77,7 @@ export function StepDelegationFooter({ }: StepProps) { invariant(account, "account required"); const { errors } = status; - const canNext = !bridgePending && !errors.amount && transaction; + const canNext = !bridgePending && Object.keys(errors).length === 0 && transaction; return ( diff --git a/apps/ledger-live-desktop/src/renderer/families/cardano/DelegationFlowModal/steps/StepSummary.tsx b/apps/ledger-live-desktop/src/renderer/families/cardano/DelegationFlowModal/steps/StepSummary.tsx index 5bbfa729d979..edb9f62b4e06 100644 --- a/apps/ledger-live-desktop/src/renderer/families/cardano/DelegationFlowModal/steps/StepSummary.tsx +++ b/apps/ledger-live-desktop/src/renderer/families/cardano/DelegationFlowModal/steps/StepSummary.tsx @@ -12,6 +12,8 @@ import { StepProps } from "../types"; import CardanoLedgerPoolIcon from "../LedgerPoolIcon"; import BigNumber from "bignumber.js"; import { useMaybeAccountUnit } from "~/renderer/hooks/useAccountUnit"; +import IconExclamationCircle from "~/renderer/icons/ExclamationCircle"; +import TranslatedError from "~/renderer/components/TranslatedError"; const FromToWrapper = styled.div``; const Separator = styled.div` @@ -27,8 +29,8 @@ function StepSummary(props: StepProps) { const feesUnit = useMaybeAccountUnit(account); if (!account || !transaction) return null; - const { estimatedFees } = status; - + const { estimatedFees, warnings } = status; + const { feeTooHigh } = warnings; const feesCurrency = getAccountCurrency(account); const showDeposit = !account.cardanoResources?.delegation?.status; const stakeKeyDeposit = account.cardanoResources?.protocolParams.stakeKeyDeposit; @@ -105,7 +107,7 @@ function StepSummary(props: StepProps) { + {feeTooHigh ? ( + + + + + + + ) : null} ); diff --git a/apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields.tsx b/apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields/MemoField.tsx similarity index 91% rename from apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields.tsx rename to apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields/MemoField.tsx index ca36eb021a8c..0c379939cfae 100644 --- a/apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields.tsx +++ b/apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields/MemoField.tsx @@ -8,7 +8,8 @@ import { Transaction, TransactionStatus, } from "@ledgerhq/live-common/families/cardano/types"; -const Root = (props: { + +const MemoField = (props: { account: CardanoAccount; transaction: Transaction; status: TransactionStatus; @@ -32,7 +33,4 @@ const Root = (props: { ); }; -export default { - component: Root, - fields: ["memo"], -}; +export default MemoField; diff --git a/apps/ledger-live-desktop/src/renderer/families/cardano/MemoValueField.tsx b/apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields/MemoValueField.tsx similarity index 99% rename from apps/ledger-live-desktop/src/renderer/families/cardano/MemoValueField.tsx rename to apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields/MemoValueField.tsx index 64880c147205..69072f358fa6 100644 --- a/apps/ledger-live-desktop/src/renderer/families/cardano/MemoValueField.tsx +++ b/apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields/MemoValueField.tsx @@ -9,6 +9,7 @@ import { TransactionStatus, } from "@ledgerhq/live-common/families/cardano/types"; import { track } from "~/renderer/analytics/segment"; + const MemoValueField = ({ onChange, account, diff --git a/apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields/index.tsx b/apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields/index.tsx new file mode 100644 index 000000000000..859bea084385 --- /dev/null +++ b/apps/ledger-live-desktop/src/renderer/families/cardano/SendAmountFields/index.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import { + CardanoAccount, + Transaction, + TransactionStatus, +} from "@ledgerhq/live-common/families/cardano/types"; + +import MemoField from "./MemoField"; + +const Root = (props: { + account: CardanoAccount; + transaction: Transaction; + status: TransactionStatus; + onChange: (t: Transaction) => void; + trackProperties?: Record; +}) => { + return ( + <> + + + ); +}; + +export default { + component: Root, + fields: ["memo"], +}; diff --git a/apps/ledger-live-desktop/src/renderer/families/cardano/UndelegateFlowModal/steps/StepSummary.tsx b/apps/ledger-live-desktop/src/renderer/families/cardano/UndelegateFlowModal/steps/StepSummary.tsx index 3f491b4686cf..c0974c7a6b3b 100644 --- a/apps/ledger-live-desktop/src/renderer/families/cardano/UndelegateFlowModal/steps/StepSummary.tsx +++ b/apps/ledger-live-desktop/src/renderer/families/cardano/UndelegateFlowModal/steps/StepSummary.tsx @@ -13,6 +13,7 @@ import { StepProps } from "../types"; import BigNumber from "bignumber.js"; import Alert from "~/renderer/components/Alert"; import { useMaybeAccountUnit } from "~/renderer/hooks/useAccountUnit"; +import IconExclamationCircle from "~/renderer/icons/ExclamationCircle"; const FromToWrapper = styled.div``; const Separator = styled.div` @@ -24,7 +25,8 @@ const Separator = styled.div` function StepSummary(props: StepProps) { const { account, transaction, status, error } = props; - const { estimatedFees, errors } = status; + const { estimatedFees, errors, warnings } = status; + const { feeTooHigh } = warnings; const displayError = errors.amount?.message ? errors.amount : ""; const accountUnit = useMaybeAccountUnit(account); @@ -72,7 +74,7 @@ function StepSummary(props: StepProps) { + {feeTooHigh ? ( + + + + + + + ) : null} {displayError ? ( @@ -114,22 +130,20 @@ export function StepSummaryFooter({ onClose, }: StepProps) { const { errors } = status; - const canNext = !errors.amount && !bridgePending && !errors.validators && transaction; + const canNext = Object.keys(errors).length === 0 && !bridgePending && transaction; return ( - <> - - - - - + + + + ); } diff --git a/apps/ledger-live-desktop/static/i18n/en/app.json b/apps/ledger-live-desktop/static/i18n/en/app.json index f3239d24d7f8..76c1ee9a3bb3 100644 --- a/apps/ledger-live-desktop/static/i18n/en/app.json +++ b/apps/ledger-live-desktop/static/i18n/en/app.json @@ -6084,6 +6084,18 @@ "CardanoStakeKeyDepositError": { "title": "Ensure that you have {{depositAmount}} ADA available for the deposit" }, + "CardanoFeeHigh": { + "title": "Abnormally high network fees.", + "description": "Network fees unusually high please double check your transaction." + }, + "CardanoFeeTooHigh": { + "title": "Abnormally high network fees.", + "description": "ADA transactions are temporarily unavailable. Please resync your account and try again or contact Support if you need assistance." + }, + "CardanoInvalidProtoParams": { + "title": "Cardano invalid protocol parameters", + "description": "ADA transactions are temporarily unavailable. Please resync your account and try again or contact Support if you need assistance." + }, "StacksMemoTooLong": { "title": "Memo length is too long" }, diff --git a/apps/ledger-live-mobile/src/families/cardano/DelegationFlow/02-Summary.tsx b/apps/ledger-live-mobile/src/families/cardano/DelegationFlow/02-Summary.tsx index 6211f832a940..358abca3cfba 100644 --- a/apps/ledger-live-mobile/src/families/cardano/DelegationFlow/02-Summary.tsx +++ b/apps/ledger-live-mobile/src/families/cardano/DelegationFlow/02-Summary.tsx @@ -40,6 +40,9 @@ import { StackNavigatorProps } from "~/components/RootNavigator/types/helpers"; import { CardanoDelegationFlowParamList } from "./types"; import TranslatedError from "~/components/TranslatedError"; import { useAccountUnit } from "~/hooks/useAccountUnit"; +import GenericErrorBottomModal from "~/components/GenericErrorBottomModal"; +import RetryButton from "~/components/RetryButton"; +import CancelButton from "~/components/CancelButton"; type Props = StackNavigatorProps< CardanoDelegationFlowParamList, @@ -100,6 +103,21 @@ export default function DelegationSummary({ navigation, route }: Props) { return { account, transaction: tx }; }); + const [bridgeErr, setBridgeErr] = useState(bridgeError); + useEffect(() => setBridgeErr(bridgeError), [bridgeError]); + + const onBridgeErrorCancel = useCallback(() => { + setBridgeErr(null); + const parent = navigation.getParent(); + if (parent) parent.goBack(); + }, [navigation]); + const onBridgeErrorRetry = useCallback(() => { + setBridgeErr(null); + if (!transaction) return; + const bridge = getAccountBridge(account, parentAccount); + setTransaction(bridge.updateTransaction(transaction, {})); + }, [setTransaction, account, parentAccount, transaction]); + invariant(transaction, "transaction must be defined"); invariant(transaction.family === "cardano", "transaction cardano"); @@ -141,6 +159,9 @@ export default function DelegationSummary({ navigation, route }: Props) { const displayError = useMemo(() => { return status.errors.amount ? status.errors.amount : ""; }, [status]); + const displayWarning = useMemo(() => { + return status.warnings.feeTooHigh ? status.warnings.feeTooHigh : ""; + }, [status]); return ( @@ -181,6 +202,15 @@ export default function DelegationSummary({ navigation, route }: Props) { ) : ( <> )} + {displayWarning ? ( + + + + + + ) : ( + <> + )}