diff --git a/.changeset/nice-plants-complain.md b/.changeset/nice-plants-complain.md new file mode 100644 index 000000000000..b412b51fd442 --- /dev/null +++ b/.changeset/nice-plants-complain.md @@ -0,0 +1,6 @@ +--- +"live-mobile": minor +"@ledgerhq/native-ui": minor +--- + +Add the receive flow `NeedMemoTagModal` diff --git a/apps/ledger-live-mobile/src/locales/en/common.json b/apps/ledger-live-mobile/src/locales/en/common.json index 4ca7eb36ea53..720def956cf2 100644 --- a/apps/ledger-live-mobile/src/locales/en/common.json +++ b/apps/ledger-live-mobile/src/locales/en/common.json @@ -3134,6 +3134,13 @@ "shareAddress": "Share address", "addressCopied": "Address copied in clipboard", "taprootWarning": "Make sure the sender supports taproot", + "memoTag": { + "link": "Need a Tag/Memo?", + "title": "Need a Tag/Memo?", + "description": "You might need a Tag/Memo for receiving this asset from an exchange. You can use any combination of numbers like 1234.", + "cta": "I understand", + "learnMore": "Learn more about Tags" + }, "selectCrypto": { "title": "Choose a crypto you want to receive" }, diff --git a/apps/ledger-live-mobile/src/screens/ReceiveFunds/03-Confirmation.tsx b/apps/ledger-live-mobile/src/screens/ReceiveFunds/03-Confirmation.tsx index 8fc419880fcd..9f9db551c80f 100644 --- a/apps/ledger-live-mobile/src/screens/ReceiveFunds/03-Confirmation.tsx +++ b/apps/ledger-live-mobile/src/screens/ReceiveFunds/03-Confirmation.tsx @@ -13,6 +13,7 @@ import { getAccountCurrency, } from "@ledgerhq/live-common/account/index"; import { getCurrencyColor } from "@ledgerhq/live-common/currencies/color"; +import FeatureToggle from "@ledgerhq/live-common/featureFlags/FeatureToggle"; import { useToasts } from "@ledgerhq/live-common/notifications/ToastProvider/index"; import { useTheme } from "styled-components/native"; import { Flex, Text, IconsLegacy, Button, Box, BannerCard, Icons } from "@ledgerhq/native-ui"; @@ -37,6 +38,7 @@ import { useSafeAreaInsets } from "react-native-safe-area-context"; import { hasClosedWithdrawBannerSelector } from "~/reducers/settings"; import { setCloseWithdrawBanner } from "~/actions/settings"; import { useCompleteActionCallback } from "~/logic/postOnboarding/useCompleteAction"; +import { MEMO_TAG_COINS } from "~/utils/constants"; import { urls } from "~/utils/urls"; import { useMaybeAccountName } from "~/reducers/wallet"; import Animated, { @@ -46,6 +48,7 @@ import Animated, { runOnJS, } from "react-native-reanimated"; import { isUTXOCompliant } from "@ledgerhq/live-common/currencies/helpers"; +import { NeedMemoTagModal } from "./NeedMemoTagModal"; type ScreenProps = BaseComposite< StackNavigatorProps @@ -390,6 +393,9 @@ function ReceiveConfirmationInner({ navigation, route, account, parentAccount }: )} + + {"id" in currency && MEMO_TAG_COINS.includes(currency.id) && } + {isUTXOCompliantCurrency && ( diff --git a/apps/ledger-live-mobile/src/screens/ReceiveFunds/NeedMemoTagModal/NeedMemoTagModal.tsx b/apps/ledger-live-mobile/src/screens/ReceiveFunds/NeedMemoTagModal/NeedMemoTagModal.tsx new file mode 100644 index 000000000000..fbec78e1c4e8 --- /dev/null +++ b/apps/ledger-live-mobile/src/screens/ReceiveFunds/NeedMemoTagModal/NeedMemoTagModal.tsx @@ -0,0 +1,53 @@ +import { useTheme } from "styled-components/native"; +import React, { useState } from "react"; +import { Linking } from "react-native"; +import { Button, Flex, Icons, Text } from "@ledgerhq/native-ui"; +import { useTranslation } from "react-i18next"; +import Circle from "~/components/Circle"; +import QueuedDrawer from "~/components/QueuedDrawer"; +import { urls } from "~/utils/urls"; + +export function NeedMemoTagModal() { + const { colors } = useTheme(); + const { t } = useTranslation(); + const [isOpen, setIsOpen] = useState(false); + const openModal = () => setIsOpen(true); + const closeModal = () => setIsOpen(false); + + return ( + <> + + + + + + + + + + + {t("transfer.receive.memoTag.title")} + + + + {t("transfer.receive.memoTag.description")} + + + + + + + + ); +} diff --git a/apps/ledger-live-mobile/src/screens/ReceiveFunds/NeedMemoTagModal/index.ts b/apps/ledger-live-mobile/src/screens/ReceiveFunds/NeedMemoTagModal/index.ts new file mode 100644 index 000000000000..31e74da5e7ca --- /dev/null +++ b/apps/ledger-live-mobile/src/screens/ReceiveFunds/NeedMemoTagModal/index.ts @@ -0,0 +1 @@ +export * from "./NeedMemoTagModal"; diff --git a/apps/ledger-live-mobile/src/utils/constants.ts b/apps/ledger-live-mobile/src/utils/constants.ts index 21855c86e586..64fcc818dd9f 100644 --- a/apps/ledger-live-mobile/src/utils/constants.ts +++ b/apps/ledger-live-mobile/src/utils/constants.ts @@ -1,4 +1,5 @@ import Config from "react-native-config"; +import { CryptoCurrencyId } from "@ledgerhq/types-cryptoassets"; export const SYNC_DELAY = 2500; export const BLE_SCANNING_NOTHING_TIMEOUT = (Config.MOCK ? 60 : 30) * 1000; @@ -7,3 +8,17 @@ export const VIBRATION_PATTERN_ERROR = [0, 150]; export const LEDGER_APPLE_WARNING_EXPLAINER_LINK = "https://support.ledger.com/hc/articles/12309873917853?docs=true"; export const PTX_SERVICES_TOAST_ID = "PTX_SERVICES_TOAST_ID"; + +export const MEMO_TAG_COINS: string[] = [ + "ripple", + "stellar", + "cosmos", + "hedera", + "injective", + "crypto_org", + "crypto_org_croeseid", + "stacks", + "ton", + "eos", + "bsc", +] satisfies CryptoCurrencyId[]; diff --git a/apps/ledger-live-mobile/src/utils/urls.tsx b/apps/ledger-live-mobile/src/utils/urls.tsx index ca33dd4a61e7..37e4dde77a03 100644 --- a/apps/ledger-live-mobile/src/utils/urls.tsx +++ b/apps/ledger-live-mobile/src/utils/urls.tsx @@ -55,6 +55,7 @@ export const urls = { tr: "https://support.ledger.com/tr/article/4423020306705-zd", zh: "https://support.ledger.com/zh-CN/article/4423020306705-zd", }, + memoTag: "https://support.ledger.com/article/4409603715217-zd", pairingIssues: "https://support.ledger.com/article/360025864773-zd", ratingsContact: "https://support.ledger.com/article/4423020306705-zd", buyNanoX: diff --git a/libs/ui/packages/native/src/components/cta/Button/getButtonStyle.ts b/libs/ui/packages/native/src/components/cta/Button/getButtonStyle.ts index cd7f06e43d05..56e1b4ffdee3 100644 --- a/libs/ui/packages/native/src/components/cta/Button/getButtonStyle.ts +++ b/libs/ui/packages/native/src/components/cta/Button/getButtonStyle.ts @@ -17,6 +17,12 @@ export function getButtonColors(colors: Theme["colors"]): { pressedColor: "transparent", pressedOutlineColor: "transparent", }, + accent: { + primaryColor: colors.primary.c80, + secondaryColor: "rgba(0,0,255,0)", + pressedColor: "transparent", + pressedOutlineColor: "transparent", + }, disabled: { primaryColor: colors.neutral.c50, secondaryColor: colors.neutral.c30, diff --git a/libs/ui/packages/native/src/components/cta/Button/index.tsx b/libs/ui/packages/native/src/components/cta/Button/index.tsx index 413dcbda7234..8dc25543548b 100644 --- a/libs/ui/packages/native/src/components/cta/Button/index.tsx +++ b/libs/ui/packages/native/src/components/cta/Button/index.tsx @@ -20,7 +20,7 @@ export type ButtonProps = TouchableOpacityProps & BaseStyledProps & { onPressWhenDisabled?: TouchableOpacityProps["onPress"]; iconName?: string; - type?: "main" | "shade" | "error" | "color" | "default"; + type?: "main" | "shade" | "error" | "color" | "accent" | "default"; size?: "small" | "medium" | "large"; iconPosition?: "right" | "left"; outline?: boolean; diff --git a/libs/ui/packages/native/storybook/stories/Cta/Button/Button.stories.tsx b/libs/ui/packages/native/storybook/stories/Cta/Button/Button.stories.tsx index defb0888d4f8..31909f72b3c5 100644 --- a/libs/ui/packages/native/storybook/stories/Cta/Button/Button.stories.tsx +++ b/libs/ui/packages/native/storybook/stories/Cta/Button/Button.stories.tsx @@ -12,7 +12,7 @@ export default { component: Button, argTypes: { type: { - options: ["main", "error", "shade", "color", undefined], + options: ["main", "error", "shade", "color", "default", "accent", undefined], control: { type: "select" }, }, size: {